Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] power: reset: qnap-poweroff: Fix License String
From: Uwe Kleine-König @ 2013-01-21  8:11 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20130120204728.GA16339@lizard.gateway.2wire.net>

Hello Anton,

On Sun, Jan 20, 2013 at 12:47:29PM -0800, Anton Vorontsov wrote:
> On Sun, Jan 20, 2013 at 09:13:36PM +0100, Uwe Kleine-K?nig wrote:
> > On Tue, Jan 08, 2013 at 07:15:26PM +0100, Andrew Lunn wrote:
> > > GPLv2+ is not a valid license string. Replace it with one that is.
> > > 
> > > Signed-off-by: Andrew Lunn <andrew@lunn.ch>
> > > ---
> > >  drivers/power/reset/qnap-poweroff.c |    2 +-
> > >  1 file changed, 1 insertion(+), 1 deletion(-)
> > > 
> > > diff --git a/drivers/power/reset/qnap-poweroff.c b/drivers/power/reset/qnap-poweroff.c
> > > index ca0b476..8af772b 100644
> > > --- a/drivers/power/reset/qnap-poweroff.c
> > > +++ b/drivers/power/reset/qnap-poweroff.c
> > > @@ -121,4 +121,4 @@ module_platform_driver(qnap_power_off_driver);
> > >  
> > >  MODULE_AUTHOR("Andrew Lunn <andrew@lunn.ch>");
> > >  MODULE_DESCRIPTION("QNAP Power off driver");
> > > -MODULE_LICENSE("GPLv2+");
> > > +MODULE_LICENSE("GPL v2");
> > This change is wrong.
> > 
> > According to include/linux/module.h "GPL v2" means exactly that: version
> > 2. As the file specifies v2 or later in the header you have to use "GPL"
> > which means v2 or later.
> 
> Does it even make sense to have the two separate things ("GPL v2" and
> "GPL")?
Yeah. If you had another OS project that uses GPL-4 you can just copy
over a GPL-2+ driver to it, not an GPL-2 driver. So assuming the kernel
will stay at GPL-2 forever it doesn't make any difference for the
kernel. But other projects might benefit. (And if in the future someone
might want to change the kernel to GPL-4, she only needs to contact the
GPL-2 authors and can legally change GPL-2+ to GPL-4+.)

> Suppose there is a global change that modifies a bunch of drivers, some of
> them are GPLv2+. Now, the author of the global change is submitting it
> under "GPL v2 only" license, which, by definition, turns any GPLv2+ code
> into "GPL v2 only", right?
See http://yarchive.net/comp/linux/dual_license_bsd_gpl.html for Linus'
POV. It's an old mail, but I think it still applies.

> So, changing from GPLv2+ to "GPL v2 only" is OK, but not the other way
> around.
OK as in (probably) legal. OK as in fair is questionable.

> IANAL, tho.
ditto.

Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-K?nig            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

^ permalink raw reply

* [PATCH 08/10] ARM: OMAP5: hwmod data: Create initial OMAP5 SOC hwmod data
From: Santosh Shilimkar @ 2013-01-21  8:11 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20130118171500.GC15361@atomide.com>

On Friday 18 January 2013 10:45 PM, Tony Lindgren wrote:
> Hi,
>
> * Santosh Shilimkar <santosh.shilimkar@ti.com> [130118 07:30]:
>> From: Benoit Cousson <b-cousson@ti.com>
>>
>> Adding the hwmod data for OMAP54xx platforms.
>> --- /dev/null
>> +++ b/arch/arm/mach-omap2/omap_hwmod_54xx_data.c
>> +/* bb2d */
>> +static struct omap_hwmod_irq_info omap54xx_bb2d_irqs[] = {
>> +	{ .irq = 125 + OMAP54XX_IRQ_GIC_START },
>> +	{ .irq = -1 }
>> +};
> ...
>
>> +/* c2c */
>> +static struct omap_hwmod_irq_info omap54xx_c2c_irqs[] = {
>> +	{ .irq = 88 + OMAP54XX_IRQ_GIC_START },
>> +	{ .irq = -1 }
>> +};
> ...
>
>
>> +static struct omap_hwmod_dma_info omap54xx_c2c_sdma_reqs[] = {
>> +	{ .dma_req = 68 + OMAP54XX_DMA_REQ_START },
>> +	{ .dma_req = -1 }
>> +};
>
>
>
>> +static struct omap_hwmod_addr_space omap54xx_elm_addrs[] = {
>> +	{
>> +		.pa_start	= 0x48078000,
>> +		.pa_end		= 0x48078fff,
>> +		.flags		= ADDR_TYPE_RT
>> +	},
>> +	{ }
>> +};
> ...
>
>> +static struct omap_hwmod_addr_space omap54xx_emif1_addrs[] = {
>> +	{
>> +		.pa_start	= 0x4c000000,
>> +		.pa_end		= 0x4c0003ff,
>> +		.flags		= ADDR_TYPE_RT
>> +	},
>> +	{ }
>> +};
>
> As discussed earlier on this list, let's not duplicate the standard
> resources here as they already are supposed to come from device tree.
>
> Whatever issues prevent us from dropping the duplicate data here need
> to be fixed. I believe Benoit already had some scripts/patches for
> that and was just waiting for the DMA binding to get merged?
>
Will have a loot at it. DMA binding pull request narrowly missed
3.8 but should get into 3.9.

Regards
santosh

^ permalink raw reply

* [PATCH 07/10] ARM: OMAP5: clock data: Add OMAP54XX full clock tree and headers
From: Santosh Shilimkar @ 2013-01-21  8:14 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20130118171912.GD15361@atomide.com>

On Friday 18 January 2013 10:49 PM, Tony Lindgren wrote:
> * Santosh Shilimkar <santosh.shilimkar@ti.com> [130118 07:30]:
>> From: Rajendra Nayak <rnayak@ti.com>
>>
>> Add the clock tree related data for OMAP54xx platforms.
>>
>> Cc: Paul Walmsley <paul@pwsan.com>
>>
>> Signed-off-by: Rajendra Nayak <rnayak@ti.com>
>> Signed-off-by: Benoit Cousson <b-cousson@ti.com>
>> [santosh.shilimkar at ti.com: Generated es2.0 data]
>> Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
>> ---
>> As mentioned in the summary, this patch will be updated once the
>> movement of clock data to drivers/clock is clear.
>
> Yes let's first fix up the issues prevent us from moving all the
> cclock*_data.c files to live under drivers/clock/omap.
>
> It seems that fixing this issue boils down to rearranging some
> clock related headers in arch/arm/mach-omap2, and then populating
> some of the clock data dynamically. Or am I missing something?
>
Am not sure of all the dependencies.  Since clock data is using the low
level prm/cm APIs, all those needs to be exported some how to move
the data. Paul can comment better on it.

Regards,
Santosh

^ permalink raw reply

* [PATCH v5 7/9] ARM: davinci: Remoteproc platform device creation data/code
From: Sekhar Nori @ 2013-01-21  8:34 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1357863807-380-8-git-send-email-rtivy@ti.com>


On 1/11/2013 5:53 AM, Robert Tivy wrote:
> Added a new remoteproc platform device for DA8XX.  Contains CMA-based
> reservation of physical memory block.  A new kernel command-line
> parameter has been added to allow boot-time specification of the
> physical memory block.
> 
> Signed-off-by: Robert Tivy <rtivy@ti.com>
> ---
>  Documentation/kernel-parameters.txt        |    7 +++
>  arch/arm/mach-davinci/devices-da8xx.c      |   93 +++++++++++++++++++++++++++-
>  arch/arm/mach-davinci/include/mach/da8xx.h |    4 ++
>  3 files changed, 103 insertions(+), 1 deletion(-)
> 
> diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
> index 363e348..e95afb1 100644
> --- a/Documentation/kernel-parameters.txt
> +++ b/Documentation/kernel-parameters.txt
> @@ -44,6 +44,7 @@ parameter is applicable:
>  	AVR32	AVR32 architecture is enabled.
>  	AX25	Appropriate AX.25 support is enabled.
>  	BLACKFIN Blackfin architecture is enabled.
> +	CMA	Contiguous Memory Area support is enabled.
>  	DRM	Direct Rendering Management support is enabled.
>  	DYNAMIC_DEBUG Build in debug messages and enable them at runtime
>  	EDD	BIOS Enhanced Disk Drive Services (EDD) is enabled
> @@ -2634,6 +2635,12 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
>  			Useful for devices that are detected asynchronously
>  			(e.g. USB and MMC devices).
>  
> +	rproc_mem=nn[KMG][@address]
> +			[KNL,ARM,CMA] Remoteproc physical memory block.
> +			Memory area to be used by remote processor image,
> +			managed by CMA.  Suitable defaults exist if not
> +			specified.

There are no defaults now, right?

> +
>  	rw		[KNL] Mount root device read-write on boot
>  
>  	S		[KNL] Run init in single mode
> diff --git a/arch/arm/mach-davinci/devices-da8xx.c b/arch/arm/mach-davinci/devices-da8xx.c
> index fb2f51b..e8016ca 100644
> --- a/arch/arm/mach-davinci/devices-da8xx.c
> +++ b/arch/arm/mach-davinci/devices-da8xx.c
> @@ -12,10 +12,11 @@
>   */
>  #include <linux/init.h>
>  #include <linux/platform_device.h>
> -#include <linux/dma-mapping.h>
> +#include <linux/dma-contiguous.h>
>  #include <linux/serial_8250.h>
>  #include <linux/ahci_platform.h>
>  #include <linux/clk.h>
> +#include <linux/platform_data/da8xx-remoteproc.h>
>  
>  #include <mach/cputype.h>
>  #include <mach/common.h>
> @@ -706,6 +707,96 @@ int __init da850_register_mmcsd1(struct davinci_mmc_config *config)
>  }
>  #endif
>  
> +static struct resource da8xx_rproc_resources[] = {
> +	{ /* DSP boot address */
> +		.start		= DA8XX_SYSCFG0_BASE + DA8XX_HOST1CFG_REG,
> +		.end		= DA8XX_SYSCFG0_BASE + DA8XX_HOST1CFG_REG + 3,
> +		.flags		= IORESOURCE_MEM,
> +	},
> +	{ /* dsp irq */
> +		.start		= IRQ_DA8XX_CHIPINT0,
> +		.end		= IRQ_DA8XX_CHIPINT0,
> +		.flags		= IORESOURCE_IRQ,
> +	},
> +};
> +
> +static struct da8xx_rproc_pdata rproc_pdata = {
> +	.name		= "dsp",
> +};

Since the driver is only for da850 so the name of the remote processor
is fixed and can probably be hardcoded in the driver itself.

> +
> +static struct platform_device da8xx_dsp = {
> +	.name	= "davinci-rproc",
> +	.id	= 0,
> +	.dev	= {
> +		.platform_data		= &rproc_pdata,
> +		.coherent_dma_mask	= DMA_BIT_MASK(32),
> +	},
> +	.num_resources	= ARRAY_SIZE(da8xx_rproc_resources),
> +	.resource	= da8xx_rproc_resources,
> +};
> +
> +#if IS_ENABLED(CONFIG_DAVINCI_REMOTEPROC)
> +
> +static phys_addr_t rproc_base __initdata;
> +static unsigned long rproc_size __initdata;
> +
> +static int __init early_rproc_mem(char *p)
> +{
> +	char *endp;
> +
> +	if (p == NULL)
> +		return 0;
> +
> +	rproc_size = memparse(p, &endp);
> +	if (*endp == '@')
> +		rproc_base = memparse(endp + 1, NULL);
> +
> +	return 0;
> +}
> +early_param("rproc_mem", early_rproc_mem);
> +
> +void __init da8xx_rproc_reserve_cma(void)
> +{
> +	int ret;
> +
> +	if (!rproc_base || !rproc_size) {
> +		pr_err("%s: 'rproc_mem=nn at address' badly specified\n"
> +		       "    'nn' and 'address' must both be non-zero\n",
> +		       __func__);
> +
> +		return;
> +	}
> +
> +	pr_info("%s: reserving 0x%lx @ 0x%lx...\n",
> +		__func__, rproc_size, (unsigned long)rproc_base);
> +
> +	ret = dma_declare_contiguous(&da8xx_dsp.dev, rproc_size, rproc_base, 0);
> +	if (ret)
> +		pr_err("%s: dma_declare_contiguous failed %d\n", __func__, ret);
> +}
> +
> +#else
> +
> +void __init da8xx_rproc_reserve_cma(void)
> +{
> +}
> +
> +#endif
> +
> +int __init da8xx_register_rproc(void)
> +{
> +	int ret;
> +
> +	ret = platform_device_register(&da8xx_dsp);
> +	if (ret) {
> +		pr_err("%s: platform_device_register: %d\n", __func__, ret);
> +
> +		return ret;
> +	}
> +
> +	return 0;
> +};
> +
>  static struct resource da8xx_rtc_resources[] = {
>  	{
>  		.start		= DA8XX_RTC_BASE,
> diff --git a/arch/arm/mach-davinci/include/mach/da8xx.h b/arch/arm/mach-davinci/include/mach/da8xx.h
> index 700d311..e9295bd 100644
> --- a/arch/arm/mach-davinci/include/mach/da8xx.h
> +++ b/arch/arm/mach-davinci/include/mach/da8xx.h
> @@ -54,6 +54,7 @@ extern unsigned int da850_max_speed;
>  #define DA8XX_SYSCFG0_BASE	(IO_PHYS + 0x14000)
>  #define DA8XX_SYSCFG0_VIRT(x)	(da8xx_syscfg0_base + (x))
>  #define DA8XX_JTAG_ID_REG	0x18
> +#define DA8XX_HOST1CFG_REG	0x44
>  #define DA8XX_CFGCHIP0_REG	0x17c
>  #define DA8XX_CFGCHIP2_REG	0x184
>  #define DA8XX_CFGCHIP3_REG	0x188
> @@ -105,6 +106,9 @@ int __init da850_register_vpif_display
>  int __init da850_register_vpif_capture
>  			(struct vpif_capture_config *capture_config);
>  void da8xx_restart(char mode, const char *cmd);
> +void __init da8xx_rproc_reserve_cma(void);

No need of __init qualifier in function prototypes.

The patch looks good to me otherwise, but I will not apply it right away
and instead wait for the driver to get accepted first.

Thanks,
Sekhar

^ permalink raw reply

* [PATCH v5 8/9] ARM: davinci: da850 board: Added .reserve function and rproc platform registration
From: Sekhar Nori @ 2013-01-21  8:36 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1357863807-380-9-git-send-email-rtivy@ti.com>

On 1/11/2013 5:53 AM, Robert Tivy wrote:
> Added .reserve function for reserving CMA memory block to MACHINE_START.
> 
> Added call to remoteproc platform device registration function during init.
> 
> Signed-off-by: Robert Tivy <rtivy@ti.com>

Looks good to me. I will apply after the driver is accepted.

Thanks,
Sekhar

^ permalink raw reply

* [GIT PULL] ste_dma40 updates for 3.9
From: Fabio Baltieri @ 2013-01-21  8:36 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20130120140733.GH23398@intel.com>

On Sun, Jan 20, 2013 at 06:07:33AM -0800, Vinod Koul wrote:
> On Tue, Jan 15, 2013 at 11:14:50AM -0800, Olof Johansson wrote:
> > On Tue, Jan 15, 2013 at 09:53:05AM +0100, Linus Walleij wrote:
> > > On Tue, Jan 15, 2013 at 7:48 AM, Olof Johansson <olof@lixom.net> wrote:
> > > 
> > > > This series of patches only modify the ste_dma40 driver, there are no
> > > > corresponding changes under arch/arm that need to be coordinated or
> > > > considered w.r.t. merge conflicts. I.e. they all seem nicely isolated
> > > > to only the driver.
> > > >
> > > > So is there a specific reason for why these shouldn't just go in
> > > > through the dmaengine tree?
> > > 
> > > One reason would be if there are DMA bindings to device tree coming
> > > this merge window, as I'm told, and it implicates a lot of platform code
> > > changes on top of this as we adopt to it.
> > > 
> > > But maybe this will be wholly confined to the DMAengine tree?
> > 
> > Changing platform code in the driver trees is asking for conflicts at
> > merge time and a grumpy Linus, I'd prefer to merge arch/arm/* through
> > arm-soc in that case.
> > 
> > Either way, this branch can be merged into dmaengine as a branch pull,
> > and if needed we can bring it in as a dependency on arm-soc. We would
> > need the same for the dmaengine DT bindings branch as a base. Of course,
> > that requires that Vinod doesn't rebase his branch and keeps the merge
> > intact. Vinod, is that compatible with your workflow?
> Yes it is.
> 
> Is this series dependent on dmaengine dt-bindings. If so then it wont apply to
> arm tree. Btw I dont mind it getting merged to any of the trees as long as we
> keep dependecies and avoid major conflicts :)

So, would you accept my original pull-request in the dmaengine tree?

Thanks,
Fabio

-- 
Fabio Baltieri

^ permalink raw reply

* [PATCH] net: fec: Add support for multiple phys on mdiobus
From: Sascha Hauer @ 2013-01-21  8:37 UTC (permalink / raw)
  To: linux-arm-kernel

There may be multiple phys on an mdio bus. This series adds support
for this to the fec driver. I recently had a board which has a switch
connected to the fec's mdio bus, so I had to pick the correct phy.

This series should be in line with other network drivers supporting
this (Marvell Armada for example)

Sascha

----------------------------------------------------------------
Sascha Hauer (2):
      net: fec: refactor dt probing
      net: fec: Add support for phys from devicetree

 Documentation/devicetree/bindings/net/fsl-fec.txt |   20 ++++++
 drivers/net/ethernet/freescale/fec.c              |   77 ++++++++++++---------
 drivers/net/ethernet/freescale/fec.h              |    1 +
 3 files changed, 67 insertions(+), 31 deletions(-)

^ permalink raw reply

* [PATCH 1/2] net: fec: refactor dt probing
From: Sascha Hauer @ 2013-01-21  8:37 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1358757475-21035-1-git-send-email-s.hauer@pengutronix.de>

For devicetree parsing only the fec_get_phy_mode_dt() is
available. Rename it to fec_probe_dt() to be able to add more devicetree
parsing to it.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/net/ethernet/freescale/fec.c |   16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/net/ethernet/freescale/fec.c b/drivers/net/ethernet/freescale/fec.c
index 0704bca..2f86557 100644
--- a/drivers/net/ethernet/freescale/fec.c
+++ b/drivers/net/ethernet/freescale/fec.c
@@ -1484,12 +1484,14 @@ static int fec_enet_init(struct net_device *ndev)
 }
 
 #ifdef CONFIG_OF
-static int fec_get_phy_mode_dt(struct platform_device *pdev)
+static int fec_probe_dt(struct fec_enet_private *fep)
 {
-	struct device_node *np = pdev->dev.of_node;
+	struct device_node *np = fep->pdev->dev.of_node;
 
-	if (np)
-		return of_get_phy_mode(np);
+	if (!np)
+		return -ENODEV;
+
+	fep->phy_interface = of_get_phy_mode(np);
 
 	return -ENODEV;
 }
@@ -1519,7 +1521,7 @@ static void fec_reset_phy(struct platform_device *pdev)
 	gpio_set_value(phy_reset, 1);
 }
 #else /* CONFIG_OF */
-static inline int fec_get_phy_mode_dt(struct platform_device *pdev)
+static inline int fec_probe_dt(struct fec_enet_private *fep)
 {
 	return -ENODEV;
 }
@@ -1581,15 +1583,13 @@ fec_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, ndev);
 
-	ret = fec_get_phy_mode_dt(pdev);
+	ret = fec_probe_dt(fep);
 	if (ret < 0) {
 		pdata = pdev->dev.platform_data;
 		if (pdata)
 			fep->phy_interface = pdata->phy;
 		else
 			fep->phy_interface = PHY_INTERFACE_MODE_MII;
-	} else {
-		fep->phy_interface = ret;
 	}
 
 	for (i = 0; i < FEC_IRQ_NUM; i++) {
-- 
1.7.10.4

^ permalink raw reply related

* [PATCH 2/2] net: fec: Add support for phys from devicetree
From: Sascha Hauer @ 2013-01-21  8:37 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1358757475-21035-1-git-send-email-s.hauer@pengutronix.de>

This adds support for specifying the phy for the fec driver through the
devicetree. Possible usecases are:

- The fec internal MDIO bus has multiple phys connected and a particular
  one has to be chosen which is physically connected to the (RG)MII interface.
- The phy is connected to an external MDIO bus.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 Documentation/devicetree/bindings/net/fsl-fec.txt |   20 +++++++
 drivers/net/ethernet/freescale/fec.c              |   61 +++++++++++++--------
 drivers/net/ethernet/freescale/fec.h              |    1 +
 3 files changed, 59 insertions(+), 23 deletions(-)

diff --git a/Documentation/devicetree/bindings/net/fsl-fec.txt b/Documentation/devicetree/bindings/net/fsl-fec.txt
index d536392..ec7060b 100644
--- a/Documentation/devicetree/bindings/net/fsl-fec.txt
+++ b/Documentation/devicetree/bindings/net/fsl-fec.txt
@@ -15,6 +15,9 @@ Optional properties:
   only if property "phy-reset-gpios" is available.  Missing the property
   will have the duration be 1 millisecond.  Numbers greater than 1000 are
   invalid and 1 millisecond will be used instead.
+- phy : a phandle for the PHY device used for the fec. Used to specify an
+  external phy or to specify a particular address if the mdio bus has multiple
+  phys on it.
 
 Example:
 
@@ -26,3 +29,20 @@ ethernet at 83fec000 {
 	phy-reset-gpios = <&gpio2 14 0>; /* GPIO2_14 */
 	local-mac-address = [00 04 9F 01 1B B9];
 };
+
+Example with specific phy address:
+
+ethernet at 83fec000 {
+	compatible = "fsl,imx51-fec", "fsl,imx27-fec";
+	reg = <0x83fec000 0x4000>;
+	interrupts = <87>;
+	phy-mode = "mii";
+	phy-reset-gpios = <&gpio2 14 0>; /* GPIO2_14 */
+	local-mac-address = [00 04 9F 01 1B B9];
+	phy = &phy3;
+
+	phy3: ethernet-phy at 3 {
+		reg = <3>;
+		device_type = "ethernet-phy";
+	};
+};
diff --git a/drivers/net/ethernet/freescale/fec.c b/drivers/net/ethernet/freescale/fec.c
index 2f86557..54a8506 100644
--- a/drivers/net/ethernet/freescale/fec.c
+++ b/drivers/net/ethernet/freescale/fec.c
@@ -48,6 +48,7 @@
 #include <linux/of_device.h>
 #include <linux/of_gpio.h>
 #include <linux/of_net.h>
+#include <linux/of_mdio.h>
 #include <linux/pinctrl/consumer.h>
 #include <linux/regulator/consumer.h>
 
@@ -950,31 +951,38 @@ static int fec_enet_mii_probe(struct net_device *ndev)
 
 	fep->phy_dev = NULL;
 
-	/* check for attached phy */
-	for (phy_id = 0; (phy_id < PHY_MAX_ADDR); phy_id++) {
-		if ((fep->mii_bus->phy_mask & (1 << phy_id)))
-			continue;
-		if (fep->mii_bus->phy_map[phy_id] == NULL)
-			continue;
-		if (fep->mii_bus->phy_map[phy_id]->phy_id == 0)
-			continue;
-		if (dev_id--)
-			continue;
-		strncpy(mdio_bus_id, fep->mii_bus->id, MII_BUS_ID_SIZE);
-		break;
-	}
+	if (fep->phy_node) {
+		phy_dev = of_phy_connect(ndev, fep->phy_node, &fec_enet_adjust_link, 0,
+			      fep->phy_interface);
+	} else {
+		/* check for attached phy */
+		for (phy_id = 0; (phy_id < PHY_MAX_ADDR); phy_id++) {
+			if ((fep->mii_bus->phy_mask & (1 << phy_id)))
+				continue;
+			if (fep->mii_bus->phy_map[phy_id] == NULL)
+				continue;
+			if (fep->mii_bus->phy_map[phy_id]->phy_id == 0)
+				continue;
+			if (dev_id--)
+				continue;
+			strncpy(mdio_bus_id, fep->mii_bus->id, MII_BUS_ID_SIZE);
+			break;
+		}
+
+		if (phy_id >= PHY_MAX_ADDR) {
+			printk(KERN_INFO
+				"%s: no PHY, assuming direct connection to switch\n",
+				ndev->name);
+			strncpy(mdio_bus_id, "fixed-0", MII_BUS_ID_SIZE);
+			phy_id = 0;
+		}
+
+		snprintf(phy_name, sizeof(phy_name), PHY_ID_FMT, mdio_bus_id, phy_id);
 
-	if (phy_id >= PHY_MAX_ADDR) {
-		printk(KERN_INFO
-			"%s: no PHY, assuming direct connection to switch\n",
-			ndev->name);
-		strncpy(mdio_bus_id, "fixed-0", MII_BUS_ID_SIZE);
-		phy_id = 0;
+		phy_dev = phy_connect(ndev, phy_name, &fec_enet_adjust_link, 0,
+				      fep->phy_interface);
 	}
 
-	snprintf(phy_name, sizeof(phy_name), PHY_ID_FMT, mdio_bus_id, phy_id);
-	phy_dev = phy_connect(ndev, phy_name, &fec_enet_adjust_link, 0,
-			      fep->phy_interface);
 	if (IS_ERR(phy_dev)) {
 		printk(KERN_ERR "%s: could not attach to PHY\n", ndev->name);
 		return PTR_ERR(phy_dev);
@@ -1076,7 +1084,12 @@ static int fec_enet_mii_init(struct platform_device *pdev)
 	for (i = 0; i < PHY_MAX_ADDR; i++)
 		fep->mii_bus->irq[i] = PHY_POLL;
 
-	if (mdiobus_register(fep->mii_bus))
+	if (fep->phy_node)
+		err = of_mdiobus_register(fep->mii_bus, pdev->dev.of_node);
+	else
+		err = mdiobus_register(fep->mii_bus);
+
+	if (err)
 		goto err_out_free_mdio_irq;
 
 	mii_cnt++;
@@ -1493,6 +1506,8 @@ static int fec_probe_dt(struct fec_enet_private *fep)
 
 	fep->phy_interface = of_get_phy_mode(np);
 
+	fep->phy_node = of_parse_phandle(np, "phy", 0);
+
 	return -ENODEV;
 }
 
diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h
index c5a3bc1..0120ea6 100644
--- a/drivers/net/ethernet/freescale/fec.h
+++ b/drivers/net/ethernet/freescale/fec.h
@@ -236,6 +236,7 @@ struct fec_enet_private {
 	/* Phylib and MDIO interface */
 	struct	mii_bus *mii_bus;
 	struct	phy_device *phy_dev;
+	struct	device_node *phy_node;
 	int	mii_timeout;
 	uint	phy_speed;
 	phy_interface_t	phy_interface;
-- 
1.7.10.4

^ permalink raw reply related

* [PATCH] net: fec: Add support for multiple phys on mdiobus
From: Wolfgang Grandegger @ 2013-01-21  8:56 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1358757475-21035-1-git-send-email-s.hauer@pengutronix.de>

On 01/21/2013 09:37 AM, Sascha Hauer wrote:
> There may be multiple phys on an mdio bus. This series adds support
> for this to the fec driver. I recently had a board which has a switch
> connected to the fec's mdio bus, so I had to pick the correct phy.

Pick one PHY from a switch port? Well, does a PHY-less (or fixed-link)
configuration for a switch not make more sense? Various ARM Ethernet
contoller drivers do not support it. I recently needed a hack for an
AT91 board.

Wolfgang.

^ permalink raw reply

* [PATCH 0/9] ARM: OMAP2+: AM33XX: Misc fixes/updates
From: Peter Korsgaard @ 2013-01-21  9:03 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <B5906170F1614E41A8A28DE3B8D121433ECF09E0@DBDE01.ent.ti.com>

>>>>> "V" == Bedia, Vaibhav <vaibhav.bedia@ti.com> writes:

Hi,

 >> Vaibhav Bedia (9):
 >> ARM: OMAP2+: AM33XX: CM: Get rid of unncessary header inclusions
 >> ARM: OMAP2+: AM33XX: CM/PRM: Use __ASSEMBLER__ macros in header files
 >> ARM: OMAP2+: AM33XX: hwmod: Register OCMC RAM hwmod
 >> ARM: OMAP2+: AM33XX: hwmod: Update TPTC0 hwmod with the right flags
 >> ARM: OMAP2+: AM33XX: hwmod: Fixup cpgmac0 hwmod entry
 >> ARM: OMAP2+: AM33XX: hwmod: Update the WKUP-M3 hwmod with reset
 >> status bit
 >> ARM: OMAP2+: AM33XX: Update the hardreset API
 >> ARM: DTS: AM33XX: Add nodes for OCMC RAM and WKUP-M3
 >> ARM: OMAP2+: AM33XX: control: Add some control module registers and
 >> APIs
 >> 

 V> Any comments on these before I resend addressing the comments from Sergei?

Wouldn't the ocmram/wkup dt nodes need a reg property to define their
size as I indirectly mentioned here:

http://thread.gmane.org/gmane.linux.ports.arm.omap/91405/focus=92061

-- 
Bye, Peter Korsgaard

^ permalink raw reply

* [PATCH] ARM: sched: correct update_sched_clock()
From: Joonsoo Kim @ 2013-01-21  9:10 UTC (permalink / raw)
  To: linux-arm-kernel

If we want load epoch_cyc and epoch_ns atomically,
we should update epoch_cyc_copy first of all.
This notify reader that updating is in progress.

If we update epoch_cyc first like as current implementation,
there is subtle error case.
Look at the below example.

<Initial Condition>
cyc = 9
ns = 900
cyc_copy = 9

== CASE 1 ==
<CPU A = reader>           <CPU B = updater>
                           write cyc = 10
read cyc = 10
read ns = 900
                           write ns = 1000
                           write cyc_copy = 10
read cyc_copy = 10

output = (10, 900)

== CASE 2 ==
<CPU A = reader>           <CPU B = updater>
read cyc = 9
                           write cyc = 10
                           write ns = 1000
read ns = 1000
read cyc_copy = 9
                           write cyc_copy = 10
output = (9, 1000)

If atomic read is ensured, output should be (9, 900) or (10, 1000).
But, output in example case are not.

So, change updating sequence in order to correct this problem.

Signed-off-by: Joonsoo Kim <iamjoonsoo.kim@lge.com>

diff --git a/arch/arm/kernel/sched_clock.c b/arch/arm/kernel/sched_clock.c
index fc6692e..bd6f56b 100644
--- a/arch/arm/kernel/sched_clock.c
+++ b/arch/arm/kernel/sched_clock.c
@@ -93,11 +93,11 @@ static void notrace update_sched_clock(void)
 	 * detectable in cyc_to_fixed_sched_clock().
 	 */
 	raw_local_irq_save(flags);
-	cd.epoch_cyc = cyc;
+	cd.epoch_cyc_copy = cyc;
 	smp_wmb();
 	cd.epoch_ns = ns;
 	smp_wmb();
-	cd.epoch_cyc_copy = cyc;
+	cd.epoch_cyc = cyc;
 	raw_local_irq_restore(flags);
 }
 
-- 
1.7.9.5

^ permalink raw reply related

* [PATCH v2 3/9] ARM: PRIMA2: initialize l2x0 according to mach from DT
From: Mark Rutland @ 2013-01-21  9:22 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAGsJ_4wXRsaX99NQNYPAqAc-9TpzXNpDB0X6y9D18ka4szPMAw@mail.gmail.com>

On Sat, Jan 19, 2013 at 04:21:47AM +0000, Barry Song wrote:
> Hi Mark,
> 
> 2013/1/16 Mark Rutland <mark.rutland@arm.com>:
> > On Wed, Jan 16, 2013 at 05:53:29AM +0000, Barry Song wrote:
> >> From: Barry Song <Baohua.Song@csr.com>
> >>
> >> prima2 and marco have diffetent l2 cache configuration, so
> >> we initialize l2x0 cache based on dtb given to kernel.
> >>
> >> Signed-off-by: Barry Song <Baohua.Song@csr.com>
> >> Cc: Mark Rutland <mark.rutland@arm.com>
> >> ---
> >>  arch/arm/mach-prima2/l2x0.c |   29 ++++++++++++++++++++++++-----
> >>  1 files changed, 24 insertions(+), 5 deletions(-)
> >>
> >> diff --git a/arch/arm/mach-prima2/l2x0.c b/arch/arm/mach-prima2/l2x0.c
> >> index c998377..e41ecd2 100644
> >> --- a/arch/arm/mach-prima2/l2x0.c
> >> +++ b/arch/arm/mach-prima2/l2x0.c
> >> @@ -11,19 +11,38 @@
> >>  #include <linux/of.h>
> >>  #include <asm/hardware/cache-l2x0.h>
> >>
> >> -static struct of_device_id prima2_l2x0_ids[]  = {
> >> -     { .compatible = "sirf,prima2-pl310-cache" },
> >> +struct l2x0_aux
> >> +{
> >> +     u32 val;
> >> +     u32 mask;
> >> +};
> >> +
> >> +static struct l2x0_aux prima2_l2x0_aux __initconst = {
> >> +     0x40000,
> >> +     0,
> >> +};
> >
> > That 0x40000 is a bit opaque. Now would be a good time to make it a bit more
> > legible. Am I right in saying that's (2 << L2X0_AUX_CTRL_WAY_SIZE_SHIFT) ?
> >
> > It'd also be nice if you used designated initializers:
> >
> > static struct l2x0_aux prima2_l2x0_aux __initconst = {
> >         .val    = (2 << L2X0_AUX_CTRL_WAY_SIZE_SHIFT),
> >         .mask   = 0,
> > };
> 
> good. and make prima2 have consistent style with marco.
> 
> >
> >> +
> >> +static struct l2x0_aux marco_l2x0_aux __initconst = {
> >> +     (2 << L2X0_AUX_CTRL_WAY_SIZE_SHIFT) |
> >> +             (1 << L2X0_AUX_CTRL_ASSOCIATIVITY_SHIFT),
> >> +     L2X0_AUX_CTRL_MASK,
> >> +};
> >
> > And here too:
> >
> > static struct l2x0_aux marco_l2x0_aux __initconst = {
> >         .val    = (2 << L2X0_AUX_CTRL_WAY_SIZE_SHIFT) |
> >                         (1 << L2X0_AUX_CTRL_ASSOCIATIVITY_SHIFT),
> >         .mask   = L2X0_AUX_CTRL_MASK,
> > };
> >
> >> +
> >> +static struct of_device_id sirf_l2x0_ids[] __initconst = {
> >> +     { .compatible = "sirf,prima2-pl310-cache", .data = &prima2_l2x0_aux, },
> >> +     { .compatible = "sirf,marco-pl310-cache", .data = &marco_l2x0_aux, },
> >>       {},
> >>  };
> >
> > I took a look at of_match_node, and it seems that the first match found in an
> > of_match_table will be returned first, rather than finding the match earliest
> > in a device node's compatible list. This is somewhat counter-intuitive.
> >
> > Therefore, the marco variant should be listed first, or it will get initialised
> > with the prima2 configuration values.
> 
> sorry. i don't get it.  do you mean .data(prima2_l2x0_aux) will be
> returned for marco?
> 
> here l2 node in matco.dts  without "sirf,prima2-pl310-cache"  will
> only have "sirf,marco-pl310-cache" and l2 node in prima2.dts without
> "sirf,marco-pl310-cache" will only have "sirf,prima2-pl310-cache"

Ah, I missed that they were mutually exclusive. As long as the node only has
one of these entries in its compatible list it'll be fine as-is.

> >
> >>
> >>  static int __init sirfsoc_l2x0_init(void)
> >>  {
> >>       struct device_node *np;
> >> +     const struct l2x0_aux *aux;
> >>
> >> -     np = of_find_matching_node(NULL, prima2_l2x0_ids);
> >> +     np = of_find_matching_node(NULL, sirf_l2x0_ids);
> >>       if (np) {
> >> -             pr_info("Initializing prima2 L2 cache\n");
> >> -             return l2x0_of_init(0x40000, 0);
> >> +             aux = of_match_node(sirf_l2x0_ids, np)->data;
> >> +             return l2x0_of_init(aux->val, aux->mask);
> >>       }
> >>
> >>       return 0;
> >> --
> >> 1.7.5.4
> >>
> >>
> >
> > With those changes:
> >
> > Reviewed-by: Mark Rutland <mark.rutland@arm.com>
> >
> > Thanks,
> > Mark.
> 
> -barry
> 

Thanks,
Mark.

^ permalink raw reply

* [PATCH v8 19/22] ARM: OMAP3: clock data: get rid of unused USB host clock aliases and dummies
From: Roger Quadros @ 2013-01-21  9:35 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <alpine.DEB.2.00.1301182027040.19470@utopia.booyaka.com>

On 01/18/2013 10:27 PM, Paul Walmsley wrote:
> Hi Roger,
> 
> On Fri, 18 Jan 2013, Roger Quadros wrote:
> 
>> We don't need multiple aliases for the OMAP USB host clocks and neither
>> the dummy clocks so remove them.
>>
>> CC: Paul Walmsley <paul@pwsan.com>
>> CC: Rajendra Nayak <rnayak@ti.com>
>> CC: Benoit Cousson <b-cousson@ti.com>
>> CC: Mike Turquette <mturquette@linaro.com>
>>
>> Signed-off-by: Roger Quadros <rogerq@ti.com>
>> Reviewed-by: Felipe Balbi <balbi@ti.com>
>> Acked-by: Paul Walmsley <paul@pwsan.com>
> 
> Per Tony's earlier request, you can drop this patch and patch 20 from your 
> series now.  I've got them queued for 3.10 or late 3.9 merge window.
> 

Should have mentioned it earlier, but just this patch without the rest
of the cleanup patches will break USB Host on OMAP3, as the old driver
bails out if optional clock nodes are missing.

Including patch 20 doesn't seem to cause a problem with OMAP4 though.

regards,
-roger

^ permalink raw reply

* [PATCH v2 8/9] ARM: PRIMA2: add new SiRFmarco SMP SoC infrastructures
From: Mark Rutland @ 2013-01-21  9:48 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAGsJ_4ysfqBvdrBEbKHzSp5TZEk1MArpUGuZ0ukLFsO490pfjg@mail.gmail.com>

On Sat, Jan 19, 2013 at 04:08:55AM +0000, Barry Song wrote:
> Hi Mark,
> Thanks very much for reviewing.
> 
> 2013/1/16 Mark Rutland <mark.rutland@arm.com>:
> > Hello,
> >
> > On Wed, Jan 16, 2013 at 05:56:23AM +0000, Barry Song wrote:
> >> From: Barry Song <Baohua.Song@csr.com>
> >>
> >> this patch adds tick timer, smp entries and generic DT machine
> >> for SiRFmarco dual-core SMP chips.
> >>
> >> with the added marco, we change the defconfig, using the same
> >> defconfig, we get a zImage which can work on both prima2 and
> >> marco.
> >>
> >> Signed-off-by: Barry Song <Baohua.Song@csr.com>
> >> ---
> >>  arch/arm/boot/dts/Makefile         |    1 +
> >>  arch/arm/configs/prima2_defconfig  |    3 +
> >>  arch/arm/mach-prima2/Kconfig       |   10 +
> >>  arch/arm/mach-prima2/Makefile      |    3 +
> >>  arch/arm/mach-prima2/common.c      |   40 ++++-
> >>  arch/arm/mach-prima2/common.h      |   11 +
> >>  arch/arm/mach-prima2/headsmp.S     |   79 ++++++++
> >>  arch/arm/mach-prima2/hotplug.c     |   41 ++++
> >>  arch/arm/mach-prima2/platsmp.c     |  170 +++++++++++++++++
> >>  arch/arm/mach-prima2/timer-marco.c |  355 ++++++++++++++++++++++++++++++++++++
> >>  10 files changed, 712 insertions(+), 1 deletions(-)
> >>  create mode 100644 arch/arm/mach-prima2/headsmp.S
> >>  create mode 100644 arch/arm/mach-prima2/hotplug.c
> >>  create mode 100644 arch/arm/mach-prima2/platsmp.c
> >>  create mode 100644 arch/arm/mach-prima2/timer-marco.c
> >>
> >> diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
> >> index e44da40..6af9901 100644
> >> --- a/arch/arm/boot/dts/Makefile
> >> +++ b/arch/arm/boot/dts/Makefile
> >> @@ -73,6 +73,7 @@ dtb-$(CONFIG_ARCH_KIRKWOOD) += kirkwood-dns320.dtb \
> >>         kirkwood-ts219-6281.dtb \
> >>         kirkwood-ts219-6282.dtb \
> >>         kirkwood-openblocks_a6.dtb
> >> +dtb-$(CONFIG_ARCH_MARCO) += marco-evb.dtb
> >>  dtb-$(CONFIG_ARCH_MSM) += msm8660-surf.dtb \
> >>         msm8960-cdp.dtb
> >>  dtb-$(CONFIG_ARCH_MVEBU) += armada-370-db.dtb \
> >> diff --git a/arch/arm/configs/prima2_defconfig b/arch/arm/configs/prima2_defconfig
> >> index 6a936c7..002a1ce 100644
> >> --- a/arch/arm/configs/prima2_defconfig
> >> +++ b/arch/arm/configs/prima2_defconfig
> >> @@ -11,6 +11,9 @@ CONFIG_PARTITION_ADVANCED=y
> >>  CONFIG_BSD_DISKLABEL=y
> >>  CONFIG_SOLARIS_X86_PARTITION=y
> >>  CONFIG_ARCH_SIRF=y
> >> +# CONFIG_SWP_EMULATE is not set
> >> +CONFIG_SMP=y
> >> +CONFIG_SCHED_MC=y
> >>  CONFIG_PREEMPT=y
> >>  CONFIG_AEABI=y
> >>  CONFIG_KEXEC=y
> >> diff --git a/arch/arm/mach-prima2/Kconfig b/arch/arm/mach-prima2/Kconfig
> >> index 558ccfb..4f7379f 100644
> >> --- a/arch/arm/mach-prima2/Kconfig
> >> +++ b/arch/arm/mach-prima2/Kconfig
> >> @@ -11,6 +11,16 @@ config ARCH_PRIMA2
> >>         help
> >>            Support for CSR SiRFSoC ARM Cortex A9 Platform
> >>
> >> +config ARCH_MARCO
> >> +       bool "CSR SiRFSoC MARCO ARM Cortex A9 Platform"
> >> +       default y
> >> +       select ARM_GIC
> >> +       select CPU_V7
> >> +       select HAVE_SMP
> >> +       select SMP_ON_UP
> >> +       help
> >> +          Support for CSR SiRFSoC ARM Cortex A9 Platform
> >> +
> >>  endmenu
> >>
> >>  config SIRF_IRQ
> >> diff --git a/arch/arm/mach-prima2/Makefile b/arch/arm/mach-prima2/Makefile
> >> index 0007a6e..bfe360c 100644
> >> --- a/arch/arm/mach-prima2/Makefile
> >> +++ b/arch/arm/mach-prima2/Makefile
> >> @@ -5,4 +5,7 @@ obj-$(CONFIG_DEBUG_LL) += lluart.o
> >>  obj-$(CONFIG_CACHE_L2X0) += l2x0.o
> >>  obj-$(CONFIG_SUSPEND) += pm.o sleep.o
> >>  obj-$(CONFIG_SIRF_IRQ) += irq.o
> >> +obj-$(CONFIG_SMP) += platsmp.o headsmp.o
> >> +obj-$(CONFIG_HOTPLUG_CPU)  += hotplug.o
> >>  obj-$(CONFIG_ARCH_PRIMA2) += timer-prima2.o
> >> +obj-$(CONFIG_ARCH_MARCO) += timer-marco.o
> >> diff --git a/arch/arm/mach-prima2/common.c b/arch/arm/mach-prima2/common.c
> >> index 99f9c7e..00a6564 100644
> >> --- a/arch/arm/mach-prima2/common.c
> >> +++ b/arch/arm/mach-prima2/common.c
> >> @@ -8,9 +8,11 @@
> >>
> >>  #include <linux/init.h>
> >>  #include <linux/kernel.h>
> >> +#include <linux/of_irq.h>
> >>  #include <asm/sizes.h>
> >>  #include <asm/mach-types.h>
> >>  #include <asm/mach/arch.h>
> >> +#include <asm/hardware/gic.h>
> >>  #include <linux/of.h>
> >>  #include <linux/of_platform.h>
> >>  #include "common.h"
> >> @@ -30,6 +32,12 @@ void __init sirfsoc_init_late(void)
> >>         sirfsoc_pm_init();
> >>  }
> >>
> >> +static __init void sirfsoc_map_io(void)
> >> +{
> >> +       sirfsoc_map_lluart();
> >> +       sirfsoc_map_scu();
> >> +}
> >> +
> >>  #ifdef CONFIG_ARCH_PRIMA2
> >>  static const char *prima2_dt_match[] __initdata = {
> >>         "sirf,prima2",
> >> @@ -38,7 +46,7 @@ static const char *prima2_dt_match[] __initdata = {
> >>
> >>  DT_MACHINE_START(PRIMA2_DT, "Generic PRIMA2 (Flattened Device Tree)")
> >>         /* Maintainer: Barry Song <baohua.song@csr.com> */
> >> -       .map_io         = sirfsoc_map_lluart,
> >> +       .map_io         = sirfsoc_map_io,
> >>         .init_irq       = sirfsoc_of_irq_init,
> >>         .init_time      = sirfsoc_prima2_timer_init,
> >>  #ifdef CONFIG_MULTI_IRQ_HANDLER
> >> @@ -51,3 +59,33 @@ DT_MACHINE_START(PRIMA2_DT, "Generic PRIMA2 (Flattened Device Tree)")
> >>         .restart        = sirfsoc_restart,
> >>  MACHINE_END
> >>  #endif
> >> +
> >> +#ifdef CONFIG_ARCH_MARCO
> >> +static const struct of_device_id marco_irq_match[] __initconst = {
> >> +       { .compatible = "arm,cortex-a9-gic", .data = gic_of_init, },
> >> +       { /* sentinel */ }
> >> +};
> >> +
> >> +static void __init marco_init_irq(void)
> >> +{
> >> +       of_irq_init(marco_irq_match);
> >> +}
> >> +
> >> +static const char *marco_dt_match[] __initdata = {
> >> +       "sirf,marco",
> >> +       NULL
> >> +};
> >> +
> >> +DT_MACHINE_START(MARCO_DT, "Generic MARCO (Flattened Device Tree)")
> >> +       /* Maintainer: Barry Song <baohua.song@csr.com> */
> >> +       .smp            = smp_ops(sirfsoc_smp_ops),
> >> +       .map_io         = sirfsoc_map_io,
> >> +       .init_irq       = marco_init_irq,
> >> +       .init_time      = sirfsoc_marco_timer_init,
> >> +       .handle_irq     = gic_handle_irq,
> >> +       .init_machine   = sirfsoc_mach_init,
> >> +       .init_late      = sirfsoc_init_late,
> >> +       .dt_compat      = marco_dt_match,
> >> +       .restart        = sirfsoc_restart,
> >> +MACHINE_END
> >> +#endif
> >> diff --git a/arch/arm/mach-prima2/common.h b/arch/arm/mach-prima2/common.h
> >> index a4f91a6..b7c26b6 100644
> >> --- a/arch/arm/mach-prima2/common.h
> >> +++ b/arch/arm/mach-prima2/common.h
> >> @@ -14,6 +14,11 @@
> >>  #include <asm/exception.h>
> >>
> >>  extern void sirfsoc_prima2_timer_init(void);
> >> +extern void sirfsoc_marco_timer_init(void);
> >> +
> >> +extern struct smp_operations   sirfsoc_smp_ops;
> >> +extern void sirfsoc_secondary_startup(void);
> >> +extern void sirfsoc_cpu_die(unsigned int cpu);
> >>
> >>  extern void __init sirfsoc_of_irq_init(void);
> >>  extern void __init sirfsoc_of_clk_init(void);
> >> @@ -26,6 +31,12 @@ static inline void sirfsoc_map_lluart(void)  {}
> >>  extern void __init sirfsoc_map_lluart(void);
> >>  #endif
> >>
> >> +#ifndef CONFIG_SMP
> >> +static inline void sirfsoc_map_scu(void) {}
> >> +#else
> >> +extern void sirfsoc_map_scu(void);
> >> +#endif
> >> +
> >>  #ifdef CONFIG_SUSPEND
> >>  extern int sirfsoc_pm_init(void);
> >>  #else
> >> diff --git a/arch/arm/mach-prima2/headsmp.S b/arch/arm/mach-prima2/headsmp.S
> >> new file mode 100644
> >> index 0000000..6ec19d5
> >> --- /dev/null
> >> +++ b/arch/arm/mach-prima2/headsmp.S
> >> @@ -0,0 +1,79 @@
> >> +/*
> >> + * Entry of the second core for CSR Marco dual-core SMP SoCs
> >> + *
> >> + * Copyright (c) 2012 Cambridge Silicon Radio Limited, a CSR plc group company.
> >> + *
> >> + * Licensed under GPLv2 or later.
> >> + */
> >> +
> >> +#include <linux/linkage.h>
> >> +#include <linux/init.h>
> >> +
> >> +       __INIT
> >> +/*
> >> + * Cold boot and hardware reset show different behaviour,
> >> + * system will be always panic if we warm-reset the board
> >> + * Here we invalidate L1 of CPU1 to make sure there isn't
> >> + * uninitialized data written into memory later
> >> + */
> >> +ENTRY(v7_invalidate_l1)
> >> +       mov     r0, #0
> >> +       mcr     p15, 0, r0, c7, c5, 0   @ invalidate I cache
> >> +       mcr     p15, 2, r0, c0, c0, 0
> >> +       mrc     p15, 1, r0, c0, c0, 0
> >> +
> >> +       ldr     r1, =0x7fff
> >> +       and     r2, r1, r0, lsr #13
> >> +
> >> +       ldr     r1, =0x3ff
> >> +
> >> +       and     r3, r1, r0, lsr #3      @ NumWays - 1
> >> +       add     r2, r2, #1              @ NumSets
> >> +
> >> +       and     r0, r0, #0x7
> >> +       add     r0, r0, #4      @ SetShift
> >> +
> >> +       clz     r1, r3          @ WayShift
> >> +       add     r4, r3, #1      @ NumWays
> >> +1:     sub     r2, r2, #1      @ NumSets--
> >> +       mov     r3, r4          @ Temp = NumWays
> >> +2:     subs    r3, r3, #1      @ Temp--
> >> +       mov     r5, r3, lsl r1
> >> +       mov     r6, r2, lsl r0
> >> +       orr     r5, r5, r6      @ Reg = (Temp<<WayShift)|(NumSets<<SetShift)
> >> +       mcr     p15, 0, r5, c7, c6, 2
> >> +       bgt     2b
> >> +       cmp     r2, #0
> >> +       bgt     1b
> >> +       dsb
> >> +       isb
> >> +       mov     pc, lr
> >> +ENDPROC(v7_invalidate_l1)
> >> +
> >> +/*
> >> + * SIRFSOC specific entry point for secondary CPUs.  This provides
> >> + * a "holding pen" into which all secondary cores are held until we're
> >> + * ready for them to initialise.
> >> + */
> >> +ENTRY(sirfsoc_secondary_startup)
> >> +       bl v7_invalidate_l1
> >> +        mrc     p15, 0, r0, c0, c0, 5
> >> +        and     r0, r0, #15
> >> +        adr     r4, 1f
> >> +        ldmia   r4, {r5, r6}
> >> +        sub     r4, r4, r5
> >> +        add     r6, r6, r4
> >> +pen:    ldr     r7, [r6]
> >> +        cmp     r7, r0
> >> +        bne     pen
> >> +
> >> +        /*
> >> +         * we've been released from the holding pen: secondary_stack
> >> +         * should now contain the SVC stack for this core
> >> +         */
> >> +        b       secondary_startup
> >> +ENDPROC(sirfsoc_secondary_startup)
> >> +
> >> +        .align
> >> +1:      .long   .
> >> +        .long   pen_release
> >> diff --git a/arch/arm/mach-prima2/hotplug.c b/arch/arm/mach-prima2/hotplug.c
> >> new file mode 100644
> >> index 0000000..97c1ee5
> >> --- /dev/null
> >> +++ b/arch/arm/mach-prima2/hotplug.c
> >> @@ -0,0 +1,41 @@
> >> +/*
> >> + * CPU hotplug support for CSR Marco dual-core SMP SoCs
> >> + *
> >> + * Copyright (c) 2012 Cambridge Silicon Radio Limited, a CSR plc group company.
> >> + *
> >> + * Licensed under GPLv2 or later.
> >> + */
> >> +
> >> +#include <linux/kernel.h>
> >> +#include <linux/errno.h>
> >> +#include <linux/smp.h>
> >> +
> >> +#include <asm/cacheflush.h>
> >> +#include <asm/smp_plat.h>
> >> +
> >> +static inline void platform_do_lowpower(unsigned int cpu)
> >> +{
> >> +       flush_cache_all();
> >> +
> >> +       /* we put the platform to just WFI */
> >> +       for (;;) {
> >> +               __asm__ __volatile__("dsb\n\t" "wfi\n\t"
> >> +                       : : : "memory");
> >> +               if (pen_release == cpu_logical_map(cpu)) {
> >> +                       /*
> >> +                        * OK, proper wakeup, we're done
> >> +                        */
> >> +                       break;
> >> +               }
> >> +       }
> >> +}
> >> +
> >> +/*
> >> + * platform-specific code to shutdown a CPU
> >> + *
> >> + * Called with IRQs disabled
> >> + */
> >> +void sirfsoc_cpu_die(unsigned int cpu)
> >> +{
> >> +       platform_do_lowpower(cpu);
> >> +}
> >> diff --git a/arch/arm/mach-prima2/platsmp.c b/arch/arm/mach-prima2/platsmp.c
> >> new file mode 100644
> >> index 0000000..b939e9b4
> >> --- /dev/null
> >> +++ b/arch/arm/mach-prima2/platsmp.c
> >> @@ -0,0 +1,170 @@
> >> +/*
> >> + * plat smp support for CSR Marco dual-core SMP SoCs
> >> + *
> >> + * Copyright (c) 2012 Cambridge Silicon Radio Limited, a CSR plc group company.
> >> + *
> >> + * Licensed under GPLv2 or later.
> >> + */
> >> +
> >> +#include <linux/init.h>
> >> +#include <linux/smp.h>
> >> +#include <linux/delay.h>
> >> +#include <linux/of.h>
> >> +#include <linux/of_address.h>
> >> +#include <asm/page.h>
> >> +#include <asm/mach/map.h>
> >> +#include <asm/smp_plat.h>
> >> +#include <asm/smp_scu.h>
> >> +#include <asm/cacheflush.h>
> >> +#include <asm/cputype.h>
> >> +#include <asm/hardware/gic.h>
> >> +#include <mach/map.h>
> >> +
> >> +#include "common.h"
> >> +
> >> +static void __iomem *scu_base;
> >> +static void __iomem *rsc_base;
> >> +
> >> +static DEFINE_SPINLOCK(boot_lock);
> >> +
> >> +static struct map_desc scu_io_desc __initdata = {
> >> +       .length         = SZ_4K,
> >> +       .type           = MT_DEVICE,
> >> +};
> >> +
> >> +void __init sirfsoc_map_scu(void)
> >> +{
> >> +       unsigned long base;
> >> +
> >> +       /* Get SCU base */
> >> +       asm("mrc p15, 4, %0, c15, c0, 0" : "=r" (base));
> >> +
> >> +       scu_io_desc.virtual = SIRFSOC_VA(base);
> >> +       scu_io_desc.pfn = __phys_to_pfn(base);
> >> +       iotable_init(&scu_io_desc, 1);
> >> +
> >> +       scu_base = (void __iomem *)SIRFSOC_VA(base);
> >> +}
> >> +
> >> +static void __cpuinit sirfsoc_secondary_init(unsigned int cpu)
> >> +{
> >> +       /*
> >> +        * if any interrupts are already enabled for the primary
> >> +        * core (e.g. timer irq), then they will not have been enabled
> >> +        * for us: do so
> >> +        */
> >> +       gic_secondary_init(0);
> >> +
> >> +       /*
> >> +        * let the primary processor know we're out of the
> >> +        * pen, then head off into the C entry point
> >> +        */
> >> +       pen_release = -1;
> >> +       smp_wmb();
> >> +
> >> +       /*
> >> +        * Synchronise with the boot thread.
> >> +        */
> >> +       spin_lock(&boot_lock);
> >> +       spin_unlock(&boot_lock);
> >> +}
> >> +
> >> +static struct of_device_id rsc_ids[]  = {
> >> +       { .compatible = "sirf,marco-rsc" },
> >> +       {},
> >> +};
> >> +
> >> +static int __cpuinit sirfsoc_boot_secondary(unsigned int cpu, struct task_struct *idle)
> >> +{
> >> +       unsigned long timeout;
> >> +       struct device_node *np;
> >> +
> >> +       np = of_find_matching_node(NULL, rsc_ids);
> >> +       if (!np)
> >> +               return -ENODEV;
> >> +
> >> +       rsc_base = of_iomap(np, 0);
> >> +       if (!rsc_base)
> >> +               return -ENOMEM;
> >> +
> >> +       /*
> >> +        * write the address of secondary startup into the sram register
> >> +        * at offset 0x2C, then write the magic number 0x3CAF5D62 to the
> >> +        * RSC register at offset 0x28, which is what boot rom code is
> >> +        * waiting for. This would wake up the secondary core from WFE
> >> +        */
> >> +#define SIRFSOC_CPU1_JUMPADDR_OFFSET 0x2C
> >> +       __raw_writel(virt_to_phys(sirfsoc_secondary_startup),
> >> +               rsc_base + SIRFSOC_CPU1_JUMPADDR_OFFSET);
> >> +
> >> +#define SIRFSOC_CPU1_WAKEMAGIC_OFFSET 0x28
> >> +       __raw_writel(0x3CAF5D62,
> >> +               rsc_base + SIRFSOC_CPU1_WAKEMAGIC_OFFSET);
> >> +
> >> +       /* make sure write buffer is drained */
> >> +       mb();
> >> +
> >> +       spin_lock(&boot_lock);
> >> +
> >> +       /*
> >> +        * The secondary processor is waiting to be released from
> >> +        * the holding pen - release it, then wait for it to flag
> >> +        * that it has been released by resetting pen_release.
> >> +        *
> >> +        * Note that "pen_release" is the hardware CPU ID, whereas
> >> +        * "cpu" is Linux's internal ID.
> >> +        */
> >> +       pen_release = cpu_logical_map(cpu);
> >> +       __cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release));
> >> +       outer_clean_range(__pa(&pen_release), __pa(&pen_release + 1));
> >> +
> >> +       /*
> >> +        * Send the secondary CPU SEV, thereby causing the boot monitor to read
> >> +        * the JUMPADDR and WAKEMAGIC, and branch to the address found there.
> >> +        */
> >> +       dsb_sev();
> >> +
> >> +       timeout = jiffies + (1 * HZ);
> >> +       while (time_before(jiffies, timeout)) {
> >> +               smp_rmb();
> >> +               if (pen_release == -1)
> >> +                       break;
> >> +
> >> +               udelay(10);
> >> +       }
> >> +
> >> +       /*
> >> +        * now the secondary core is starting up let it run its
> >> +        * calibrations, then wait for it to finish
> >> +        */
> >> +       spin_unlock(&boot_lock);
> >> +
> >> +       return pen_release != -1 ? -ENOSYS : 0;
> >> +}
> >> +
> >> +static void __init sirfsoc_smp_init_cpus(void)
> >> +{
> >> +       int i, ncores;
> >> +
> >> +       ncores = scu_get_core_count(scu_base);
> >> +
> >> +       for (i = 0; i < ncores; i++)
> >> +               set_cpu_possible(i, true);
> >> +
> >> +       set_smp_cross_call(gic_raise_softirq);
> >> +}
> >
> > You don't need to use scu_get_core_count to figure out which cpus to set
> > possible. It duplicates work already done by arm_dt_init_cpu_maps, and doesn't
> > initialise the logical map (as arm_dt_init_cpu_maps does).
> >
> > You're already relying on the arm_dt_init_cpu_maps to set up the logical map
> > for the holding pen release, so you may as well rely on it to set_cpu_possible
> > for each of the cpus described in the dt.
> >
> > Tegra is already on its way to doing this:
> >
> > http://lists.infradead.org/pipermail/linux-arm-kernel/2012-December/138319.html
> > http://lists.infradead.org/pipermail/linux-arm-kernel/2013-January/140219.html
> > http://lists.infradead.org/pipermail/linux-arm-kernel/2013-January/141596.html
> >
> what if there are 4 nodes in dts but there are actually only one core
> in soc? for example, using qemu to run vexpress without --smp=4?
> SiRFmarco will have 2 versions, one is UP, the other one is dual core.
> if using dt, i might need to take cpus node out of marco.dtsi

If the dt doesn't match the hardware, then the dt is wrong. It's probably worth
having a separate dtsi for the UP and SMP versions (with all the core stuff in
another shared dsti).

> 
> >> +
> >> +static void __init sirfsoc_smp_prepare_cpus(unsigned int max_cpus)
> >> +{
> >> +       scu_enable(scu_base);
> >> +}
> >> +
> >> +struct smp_operations sirfsoc_smp_ops __initdata = {
> >> +        .smp_init_cpus          = sirfsoc_smp_init_cpus,
> >> +        .smp_prepare_cpus       = sirfsoc_smp_prepare_cpus,
> >> +        .smp_secondary_init     = sirfsoc_secondary_init,
> >> +        .smp_boot_secondary     = sirfsoc_boot_secondary,
> >> +#ifdef CONFIG_HOTPLUG_CPU
> >> +       .cpu_die                = sirfsoc_cpu_die,
> >> +#endif
> >> +};
> >
> > The timer below is a big chunk of code, it'd be nicer if it had a patch to
> > itself.
> ok.
> 
> >
> >> diff --git a/arch/arm/mach-prima2/timer-marco.c b/arch/arm/mach-prima2/timer-marco.c
> >> new file mode 100644
> >> index 0000000..07b3a6b
> >> --- /dev/null
> >> +++ b/arch/arm/mach-prima2/timer-marco.c
> >> @@ -0,0 +1,355 @@
> >> +/*
> >> + * System timer for CSR SiRFprimaII
> >> + *
> >> + * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
> >> + *
> >> + * Licensed under GPLv2 or later.
> >> + */
> >> +
> >> +#include <linux/kernel.h>
> >> +#include <linux/interrupt.h>
> >> +#include <linux/clockchips.h>
> >> +#include <linux/clocksource.h>
> >> +#include <linux/bitops.h>
> >> +#include <linux/irq.h>
> >> +#include <linux/clk.h>
> >> +#include <linux/slab.h>
> >> +#include <linux/of.h>
> >> +#include <linux/of_irq.h>
> >> +#include <linux/of_address.h>
> >> +#include <asm/sched_clock.h>
> >> +#include <asm/localtimer.h>
> >> +#include <asm/mach/time.h>
> >> +
> >> +#include "common.h"
> >> +
> >> +#define SIRFSOC_TIMER_32COUNTER_0_CTRL                 0x0000
> >> +#define SIRFSOC_TIMER_32COUNTER_1_CTRL                 0x0004
> >> +#define SIRFSOC_TIMER_MATCH_0                          0x0018
> >> +#define SIRFSOC_TIMER_MATCH_1                          0x001c
> >> +#define SIRFSOC_TIMER_COUNTER_0                                0x0048
> >> +#define SIRFSOC_TIMER_COUNTER_1                                0x004c
> >> +#define SIRFSOC_TIMER_INTR_STATUS                      0x0060
> >> +#define SIRFSOC_TIMER_WATCHDOG_EN                      0x0064
> >> +#define SIRFSOC_TIMER_64COUNTER_CTRL                   0x0068
> >> +#define SIRFSOC_TIMER_64COUNTER_LO                     0x006c
> >> +#define SIRFSOC_TIMER_64COUNTER_HI                     0x0070
> >> +#define SIRFSOC_TIMER_64COUNTER_LOAD_LO                        0x0074
> >> +#define SIRFSOC_TIMER_64COUNTER_LOAD_HI                        0x0078
> >> +#define SIRFSOC_TIMER_64COUNTER_RLATCHED_LO            0x007c
> >> +#define SIRFSOC_TIMER_64COUNTER_RLATCHED_HI            0x0080
> >> +
> >> +#define SIRFSOC_TIMER_REG_CNT 6
> >> +
> >> +static const u32 sirfsoc_timer_reg_list[SIRFSOC_TIMER_REG_CNT] = {
> >> +       SIRFSOC_TIMER_WATCHDOG_EN,
> >> +       SIRFSOC_TIMER_32COUNTER_0_CTRL,
> >> +       SIRFSOC_TIMER_32COUNTER_1_CTRL,
> >> +       SIRFSOC_TIMER_64COUNTER_CTRL,
> >> +       SIRFSOC_TIMER_64COUNTER_RLATCHED_LO,
> >> +       SIRFSOC_TIMER_64COUNTER_RLATCHED_HI,
> >> +};
> >> +
> >> +static u32 sirfsoc_timer_reg_val[SIRFSOC_TIMER_REG_CNT];
> >> +
> >> +static void __iomem *sirfsoc_timer_base;
> >> +static void __init sirfsoc_of_timer_map(void);
> >> +
> >> +/* disable count and interrupt */
> >> +static inline void sirfsoc_timer_count_disable(int idx)
> >> +{
> >> +       writel_relaxed(readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_32COUNTER_0_CTRL + 4 * idx) & ~0x7,
> >> +               sirfsoc_timer_base + SIRFSOC_TIMER_32COUNTER_0_CTRL + 4 * idx);
> >> +}
> >> +
> >> +/* enable count and interrupt */
> >> +static inline void sirfsoc_timer_count_enable(int idx)
> >> +{
> >> +       writel_relaxed(readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_32COUNTER_0_CTRL + 4 * idx) | 0x7,
> >> +               sirfsoc_timer_base + SIRFSOC_TIMER_32COUNTER_0_CTRL + 4 * idx);
> >> +}
> >> +
> >> +/* timer0 interrupt handler */
> >> +static irqreturn_t sirfsoc_timer_interrupt(int irq, void *dev_id)
> >> +{
> >> +       struct clock_event_device *ce = dev_id;
> >> +
> >> +       /* clear timer0 interrupt */
> >> +       writel_relaxed(BIT(0), sirfsoc_timer_base + SIRFSOC_TIMER_INTR_STATUS);
> >> +
> >> +       if (ce->mode == CLOCK_EVT_MODE_ONESHOT)
> >> +               sirfsoc_timer_count_disable(0);
> >> +
> >> +       ce->event_handler(ce);
> >> +
> >> +       return IRQ_HANDLED;
> >> +}
> >> +
> >> +/* read 64-bit timer counter */
> >> +static cycle_t sirfsoc_timer_read(struct clocksource *cs)
> >> +{
> >> +       u64 cycles;
> >> +
> >> +       writel_relaxed((readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_CTRL) |
> >> +                       BIT(0)) & ~BIT(1), sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_CTRL);
> >> +
> >> +       cycles = readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_RLATCHED_HI);
> >> +       cycles = (cycles << 32) | readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_RLATCHED_LO);
> >> +
> >> +       return cycles;
> >> +}
> >> +
> >> +static int sirfsoc_timer_set_next_event(unsigned long delta,
> >> +       struct clock_event_device *ce)
> >> +{
> >> +
> >> +       writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_COUNTER_0);
> >> +       writel_relaxed(delta, sirfsoc_timer_base + SIRFSOC_TIMER_MATCH_0);
> >> +
> >> +       /* enable the tick */
> >> +       sirfsoc_timer_count_enable(0);
> >> +
> >> +       return 0;
> >> +}
> >> +
> >> +static void sirfsoc_timer_set_mode(enum clock_event_mode mode,
> >> +       struct clock_event_device *ce)
> >> +{
> >> +       switch (mode) {
> >> +       case CLOCK_EVT_MODE_ONESHOT:
> >> +               /* enable in set_next_event */
> >> +               break;
> >> +       default:
> >> +               break;
> >> +       }
> >> +
> >> +       sirfsoc_timer_count_disable(0);
> >> +}
> >> +
> >> +static void sirfsoc_clocksource_suspend(struct clocksource *cs)
> >> +{
> >> +       int i;
> >> +
> >> +       for (i = 0; i < SIRFSOC_TIMER_REG_CNT; i++)
> >> +               sirfsoc_timer_reg_val[i] = readl_relaxed(sirfsoc_timer_base + sirfsoc_timer_reg_list[i]);
> >> +}
> >> +
> >> +static void sirfsoc_clocksource_resume(struct clocksource *cs)
> >> +{
> >> +       int i;
> >> +
> >> +       for (i = 0; i < SIRFSOC_TIMER_REG_CNT - 2; i++)
> >> +               writel_relaxed(sirfsoc_timer_reg_val[i], sirfsoc_timer_base + sirfsoc_timer_reg_list[i]);
> >> +
> >> +       writel_relaxed(sirfsoc_timer_reg_val[SIRFSOC_TIMER_REG_CNT - 2],
> >> +               sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_LOAD_LO);
> >> +       writel_relaxed(sirfsoc_timer_reg_val[SIRFSOC_TIMER_REG_CNT - 1],
> >> +               sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_LOAD_HI);
> >> +
> >> +       writel_relaxed(readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_CTRL) |
> >> +               BIT(1) | BIT(0), sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_CTRL);
> >> +}
> >> +
> >> +static struct clock_event_device sirfsoc_clockevent = {
> >> +       .name = "sirfsoc_clockevent",
> >> +       .rating = 200,
> >> +       .features = CLOCK_EVT_FEAT_ONESHOT,
> >> +       .set_mode = sirfsoc_timer_set_mode,
> >> +       .set_next_event = sirfsoc_timer_set_next_event,
> >> +};
> >> +
> >> +static struct clocksource sirfsoc_clocksource = {
> >> +       .name = "sirfsoc_clocksource",
> >> +       .rating = 200,
> >> +       .mask = CLOCKSOURCE_MASK(64),
> >> +       .flags = CLOCK_SOURCE_IS_CONTINUOUS,
> >> +       .read = sirfsoc_timer_read,
> >> +       .suspend = sirfsoc_clocksource_suspend,
> >> +       .resume = sirfsoc_clocksource_resume,
> >> +};
> >> +
> >> +static struct irqaction sirfsoc_timer_irq = {
> >> +       .name = "sirfsoc_timer0",
> >> +       .flags = IRQF_TIMER | IRQF_NOBALANCING,
> >> +       .handler = sirfsoc_timer_interrupt,
> >> +       .dev_id = &sirfsoc_clockevent,
> >> +};
> >> +
> >> +#ifdef CONFIG_LOCAL_TIMERS
> >> +
> >> +/* timer1 interrupt handler */
> >> +static irqreturn_t sirfsoc_timer1_interrupt(int irq, void *dev_id)
> >> +{
> >> +       struct clock_event_device *ce = dev_id;
> >> +
> >> +       /* clear timer1 interrupt */
> >> +       writel_relaxed(BIT(1), sirfsoc_timer_base + SIRFSOC_TIMER_INTR_STATUS);
> >> +
> >> +       if (ce->mode == CLOCK_EVT_MODE_ONESHOT)
> >> +               sirfsoc_timer_count_disable(1);
> >> +
> >> +       ce->event_handler(ce);
> >> +
> >> +       return IRQ_HANDLED;
> >> +}
> >> +
> >> +static struct irqaction sirfsoc_timer1_irq = {
> >> +       .name = "sirfsoc_timer1",
> >> +       .flags = IRQF_TIMER | IRQF_NOBALANCING,
> >> +       .handler = sirfsoc_timer1_interrupt,
> >> +};
> >> +
> >> +static int sirfsoc_timer1_set_next_event(unsigned long delta,
> >> +       struct clock_event_device *ce)
> >> +{
> >> +       writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_COUNTER_1);
> >> +       writel_relaxed(delta, sirfsoc_timer_base + SIRFSOC_TIMER_MATCH_1);
> >> +
> >> +       /* enable the tick */
> >> +       sirfsoc_timer_count_enable(1);
> >> +
> >> +       return 0;
> >> +}
> >> +
> >> +static void sirfsoc_timer1_set_mode(enum clock_event_mode mode,
> >> +       struct clock_event_device *ce)
> >> +{
> >> +       switch (mode) {
> >> +       case CLOCK_EVT_MODE_ONESHOT:
> >> +               /* enable in set_next_event */
> >> +               break;
> >> +       default:
> >> +               break;
> >> +       }
> >> +
> >> +       sirfsoc_timer_count_disable(1);
> >> +}
> >> +
> >> +static int __cpuinit sirfsoc_local_timer_setup(struct clock_event_device *ce)
> >> +{
> >> +       /* Use existing clock_event for cpu 0 */
> >> +       if (!smp_processor_id())
> >> +               return 0;
> >
> > This seems a little scary. Does the timer only exist for 1 core, or is it not
> > actually a local timer?
> 
> there are multiple timers, everyone can be avaliable to all cores.
> here we actually use timer0 as cpu0's tick, timer1 as cpu1's tick.
> each one uses a seperate timers.

Ok.

>From a glance over the code, it looks like the timer0 and timer1 are pretty
much identical. Is there no way to have the logic unified, figuring out whether
to use SIRFSOC_TIMER_*_{0,1} automatically?

> 
> >
> >> +
> >> +       ce->irq = sirfsoc_timer1_irq.irq;
> >> +       ce->name = "local_timer";
> >> +       ce->features = sirfsoc_clockevent.features;
> >> +       ce->rating = sirfsoc_clockevent.rating;
> >> +       ce->cpumask = cpumask_of(1);
> >
> > The local_timer api sets the cpumask, and you've already rejected setups from
> > cpu0, so this isn't technically necessary.
> 
> right.
> >
> >> +       ce->set_mode = sirfsoc_timer1_set_mode;
> >> +       ce->set_next_event = sirfsoc_timer1_set_next_event;
> >> +       ce->shift = sirfsoc_clockevent.shift;
> >> +       ce->mult = sirfsoc_clockevent.mult;
> >> +       ce->max_delta_ns = sirfsoc_clockevent.max_delta_ns;
> >> +       ce->min_delta_ns = sirfsoc_clockevent.min_delta_ns;
> >> +
> >> +       sirfsoc_timer1_irq.dev_id = ce;
> >> +       BUG_ON(setup_irq(ce->irq, &sirfsoc_timer1_irq));
> >> +       irq_set_affinity(sirfsoc_timer1_irq.irq, cpumask_of(1));
> >> +
> >> +       clockevents_register_device(ce);
> >> +       return 0;
> >> +}
> >> +
> >> +static void sirfsoc_local_timer_stop(struct clock_event_device *ce)
> >> +{
> >> +       sirfsoc_timer_count_disable(1);
> >> +
> >> +       remove_irq(sirfsoc_timer1_irq.irq, &sirfsoc_timer1_irq);
> >> +}
> >
> > Presumably you need to balance what you've done in sirfsoc_local_timer_setup,
> > and return early for cpu0.

If you don't unify the code for the two timers, I really think you should have
an early return here for cpu0.

> >
> >> +
> >> +static struct local_timer_ops sirfsoc_local_timer_ops __cpuinitdata = {
> >> +       .setup  = sirfsoc_local_timer_setup,
> >> +       .stop   = sirfsoc_local_timer_stop,
> >> +};
> >> +#endif /* CONFIG_LOCAL_TIMERS */
> >> +
> >> +static void __init sirfsoc_clockevent_init(void)
> >> +{
> >> +       clockevents_calc_mult_shift(&sirfsoc_clockevent, CLOCK_TICK_RATE, 60);
> >> +
> >> +       sirfsoc_clockevent.max_delta_ns =
> >> +               clockevent_delta2ns(-2, &sirfsoc_clockevent);
> >
> > I assume this is a typo. For one thing, clockevent_delta2ns takes an unsigned
> > long.
> 
> grep and get:
> http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux.git&a=search&h=HEAD&st=grep&s=clockevent_delta2ns
> almost all platforms don't really take it seriously if we think -2 is
> very big unsigned long and number like 0xfffffffe is almost not
> unsigned long without UL.

That's a bit opaque, but as you say, everyone's doing it (or something
equivalent).

> 
> >
> >> +       sirfsoc_clockevent.min_delta_ns =
> >> +               clockevent_delta2ns(2, &sirfsoc_clockevent);
> >> +
> >> +       sirfsoc_clockevent.cpumask = cpumask_of(0);
> >> +       clockevents_register_device(&sirfsoc_clockevent);
> >> +#ifdef CONFIG_LOCAL_TIMERS
> >> +       local_timer_register(&sirfsoc_local_timer_ops);
> >> +#endif
> >> +}
> >> +
> >> +/* initialize the kernel jiffy timer source */
> >> +void __init sirfsoc_marco_timer_init(void)
> >> +{
> >> +       unsigned long rate;
> >> +       u32 timer_div;
> >> +       struct clk *clk;
> >> +
> >> +       /* initialize clocking early, we want to set the OS timer */
> >> +       sirfsoc_of_clk_init();
> >> +
> >> +       /* timer's input clock is io clock */
> >> +       clk = clk_get_sys("io", NULL);
> >> +
> >> +       BUG_ON(IS_ERR(clk));
> >> +       rate = clk_get_rate(clk);
> >> +
> >> +       BUG_ON(rate < CLOCK_TICK_RATE);
> >> +       BUG_ON(rate % CLOCK_TICK_RATE);
> >> +
> >> +       sirfsoc_of_timer_map();
> >> +
> >> +       /* Initialize the timer dividers */
> >> +       timer_div = rate / CLOCK_TICK_RATE / 2 - 1;
> >> +       writel_relaxed(timer_div << 16, sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_CTRL);
> >> +       writel_relaxed(timer_div << 16, sirfsoc_timer_base + SIRFSOC_TIMER_32COUNTER_0_CTRL);
> >> +       writel_relaxed(timer_div << 16, sirfsoc_timer_base + SIRFSOC_TIMER_32COUNTER_1_CTRL);
> >> +
> >> +       /* Initialize timer counters to 0 */
> >> +       writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_LOAD_LO);
> >> +       writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_LOAD_HI);
> >> +       writel_relaxed(readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_CTRL) |
> >> +               BIT(1) | BIT(0), sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_CTRL);
> >> +       writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_COUNTER_0);
> >> +       writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_COUNTER_1);
> >> +
> >> +       /* Clear all interrupts */
> >> +       writel_relaxed(0xFFFF, sirfsoc_timer_base + SIRFSOC_TIMER_INTR_STATUS);
> >> +
> >> +       BUG_ON(clocksource_register_hz(&sirfsoc_clocksource, CLOCK_TICK_RATE));
> >> +
> >> +       BUG_ON(setup_irq(sirfsoc_timer_irq.irq, &sirfsoc_timer_irq));
> >> +
> >> +       sirfsoc_clockevent_init();
> >> +}
> >> +
> >> +static struct of_device_id timer_ids[] = {
> >> +       { .compatible = "sirf,marco-tick" },
> >> +       {},
> >> +};
> >> +
> >> +static void __init sirfsoc_of_timer_map(void)
> >> +{
> >> +       struct device_node *np;
> >> +
> >> +       np = of_find_matching_node(NULL, timer_ids);
> >> +       if (!np)
> >> +               return;
> >> +       sirfsoc_timer_base = of_iomap(np, 0);
> >> +       if (!sirfsoc_timer_base)
> >> +               panic("unable to map timer cpu registers\n");
> >> +
> >> +       sirfsoc_timer_irq.irq = irq_of_parse_and_map(np, 0);
> >> +       if (!sirfsoc_timer_irq.irq)
> >> +               panic("No irq passed for timer0 via DT\n");
> >> +
> >> +#ifdef CONFIG_LOCAL_TIMERS
> >> +       sirfsoc_timer1_irq.irq = irq_of_parse_and_map(np, 1);
> >> +       if (!sirfsoc_timer1_irq.irq)
> >> +               panic("No irq passed for timer1 via DT\n");
> >> +#endif
> >> +
> >> +       of_node_put(np);
> >> +}
> >> --
> >> 1.7.5.4
> 
> > Thanks,
> > Mark.
> 
> -barry
> 

Thanks,
Mark.

^ permalink raw reply

* [PATCH] ARM: tegra114: cpuidle: add ARM_CPUIDLE_WFI_STATE support
From: Joseph Lo @ 2013-01-21  9:49 UTC (permalink / raw)
  To: linux-arm-kernel

Adding the generic ARM_CPUIDLE_WFI_STATE support for Tegra114.

Signed-off-by: Joseph Lo <josephl@nvidia.com>
---
 arch/arm/mach-tegra/Makefile           |  3 ++
 arch/arm/mach-tegra/cpuidle-tegra114.c | 61 ++++++++++++++++++++++++++++++++++
 arch/arm/mach-tegra/cpuidle.c          |  3 ++
 arch/arm/mach-tegra/cpuidle.h          |  6 ++++
 4 files changed, 73 insertions(+)
 create mode 100644 arch/arm/mach-tegra/cpuidle-tegra114.c

diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile
index 219c2ed..1335aac 100644
--- a/arch/arm/mach-tegra/Makefile
+++ b/arch/arm/mach-tegra/Makefile
@@ -34,6 +34,9 @@ obj-$(CONFIG_TEGRA_PCI)			+= pcie.o
 obj-$(CONFIG_ARCH_TEGRA_2x_SOC)		+= board-dt-tegra20.o
 obj-$(CONFIG_ARCH_TEGRA_3x_SOC)		+= board-dt-tegra30.o
 obj-$(CONFIG_ARCH_TEGRA_114_SOC)	+= board-dt-tegra114.o
+ifeq ($(CONFIG_CPU_IDLE),y)
+obj-$(CONFIG_ARCH_TEGRA_114_SOC)	+= cpuidle-tegra114.o
+endif
 
 obj-$(CONFIG_ARCH_TEGRA_2x_SOC)		+= board-harmony-pcie.o
 
diff --git a/arch/arm/mach-tegra/cpuidle-tegra114.c b/arch/arm/mach-tegra/cpuidle-tegra114.c
new file mode 100644
index 0000000..0f4e8c4
--- /dev/null
+++ b/arch/arm/mach-tegra/cpuidle-tegra114.c
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2013, NVIDIA Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/cpuidle.h>
+
+#include <asm/cpuidle.h>
+
+static struct cpuidle_driver tegra_idle_driver = {
+	.name = "tegra_idle",
+	.owner = THIS_MODULE,
+	.en_core_tk_irqen = 1,
+	.state_count = 1,
+	.states = {
+		[0] = ARM_CPUIDLE_WFI_STATE_PWR(600),
+	},
+};
+
+static DEFINE_PER_CPU(struct cpuidle_device, tegra_idle_device);
+
+int __init tegra114_cpuidle_init(void)
+{
+	int ret;
+	unsigned int cpu;
+	struct cpuidle_device *dev;
+	struct cpuidle_driver *drv = &tegra_idle_driver;
+
+	ret = cpuidle_register_driver(&tegra_idle_driver);
+	if (ret) {
+		pr_err("CPUidle driver registration failed\n");
+		return ret;
+	}
+
+	for_each_possible_cpu(cpu) {
+		dev = &per_cpu(tegra_idle_device, cpu);
+		dev->cpu = cpu;
+
+		dev->state_count = drv->state_count;
+		ret = cpuidle_register_device(dev);
+		if (ret) {
+			pr_err("CPU%u: CPUidle device registration failed\n",
+				cpu);
+			return ret;
+		}
+	}
+	return 0;
+}
diff --git a/arch/arm/mach-tegra/cpuidle.c b/arch/arm/mach-tegra/cpuidle.c
index d065139..4b744c4 100644
--- a/arch/arm/mach-tegra/cpuidle.c
+++ b/arch/arm/mach-tegra/cpuidle.c
@@ -38,6 +38,9 @@ static int __init tegra_cpuidle_init(void)
 	case TEGRA30:
 		ret = tegra30_cpuidle_init();
 		break;
+	case TEGRA114:
+		ret = tegra114_cpuidle_init();
+		break;
 	default:
 		ret = -ENODEV;
 		break;
diff --git a/arch/arm/mach-tegra/cpuidle.h b/arch/arm/mach-tegra/cpuidle.h
index 496204d..d733f75 100644
--- a/arch/arm/mach-tegra/cpuidle.h
+++ b/arch/arm/mach-tegra/cpuidle.h
@@ -29,4 +29,10 @@ int tegra30_cpuidle_init(void);
 static inline int tegra30_cpuidle_init(void) { return -ENODEV; }
 #endif
 
+#ifdef CONFIG_ARCH_TEGRA_114_SOC
+int tegra114_cpuidle_init(void);
+#else
+static inline int tegra114_cpuidle_init(void) { return -ENODEV; }
+#endif
+
 #endif
-- 
1.8.0.3

^ permalink raw reply related

* [PATCH 3/7] ARM i.MX6q: Add GPU, VPU, IPU, and OpenVG resets to System Reset Controller (SRC)
From: Philipp Zabel @ 2013-01-21  9:52 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAKGA1bmjKQcX3RzSjbnuYqoJqbzXYGa_Whv7QQkNyAhBDzZWdw@mail.gmail.com>

Hi Matt,

thank you for your comments.

Am Freitag, den 18.01.2013, 13:57 -0600 schrieb Matt Sealey:
> On Wed, Jan 16, 2013 at 10:13 AM, Philipp Zabel <p.zabel@pengutronix.de> wrote:
> > The SRC has auto-deasserting reset bits that control reset lines to
> > the GPU, VPU, IPU, and OpenVG IP modules. This patch adds a reset
> > controller that can be controlled by those devices using the
> > reset controller API.
> >
> > Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
> 
> Hi Philipp,
> 
> I'm so glad someone actually sat down and coded this :)
> 
> +
> +static int imx_src_reset(unsigned long sw_reset_idx)
> +{
> 
> Having a name like imx_src_reset seems needlessly generic and
> confusing. Surely we are performing a reset on an SoC unit and not
> having the SRC itself reset, even if it is clearer when we look at the
> argument?

imx_src_reset_module, then? Also, I'll add the struct
reset_controller_dev pointer as an argument next time:

static int imx_src_reset_module(struct reset_controller_dev *rcdev,
                unsigned long sw_reset_idx)

> +       timeout = jiffies + msecs_to_jiffies(1000);
> +       while (readl(src_base + SRC_SCR) & bit) {
> +               if (time_after(jiffies, timeout))
> +                       return -ETIME;
> +               cpu_relax();
> 
> ... I do wonder though, all versions of the very-similar i.MX SRC
> (i.MX51, i.MX53, i.MX6) implementing these bits actually have an
> interrupt (with the same status-bit positions as the reset-enable
> register) which fires when the unit actually resets.
> 
> Rather than poll with a timeout shouldn't we be waiting for the
> interrupt and doing some completion event? It seems a little overly
> involved to me to poll and cpu_relax() when we can just let the kernel
> do whatever it likes while the hardware does the job.
> 
> It is technically impossible for the unit to "never reset" without
> there being something hideously wrong elsewhere (i.e. if you ask the
> VPU to reset, and it never fires the interrupt, you have far, far more
> problems than just a locked VPU), but we actually should have no idea
> without some empirical data (under every scenario at least) how long
> it would actually take so having a timeout seems rather odd. Having a
> timeout of a full second also *seems* to be far too long under the
> same circumstances but I don't think anyone can predict what the real
> values might be.
> 
> I looked at writing this exact same kind of code a long while back
> including support for i.MX51 and i.MX53 as a cleanup for the older
> version of Sascha's IPU driver, and simply never got it nice enough to
> submit upstream (it is currently stuffed away in a huge backup disk
> and I have no idea where the kernel tree is), but the way I handled it
> was something like registering a real interrupt handler in the src
> initialization function and then simply setting the bit and letting
> the completion event do the work. I also did have a timeout for 5000ms
> which basically would still capture any reset oddities - if we passed
> 5 seconds, and the unit did not reset, to start executing WARN_ON or
> something to give the kernel developer (or user) a real indication
> that something is *actually* hideously wrong with their board
> implementation or the stability of their SoC, power rails, heatsink
> etc.. or million other possibilities (any warning is at least better
> than none).
> 
> I could never get the warning code to ever execute except in a
> contrived test scenario (I set a reserved bit and faked that it never
> fired an interrupt) but in my opinion, ANY warning on this kind of
> failure to reset is better than just returning -ETIME to the reset
> consumer and hoping the consumer reports a reasonable error to the
> kernel log - if the SRC fails to reset a unit then this is not an
> error condition so low in seriousness that telling the consumer
> something timed out is adequate (based on the intended and functional
> implementation of the SRC controller itself). As I said, what I
> decided on was that I would return -ETIMEDOUT (the wrong code, but
> bear with me, I was hacking) but before return, pr_err the problem
> unit, and then WARN_ON inside the SRC driver itself, so that
> everything would carry on (no system lockups or panics), but the
> driver was not responsible for reporting the problem and the
> seriousness was implicated in something a little more noticable than a
> single line in a log.
> 
> I understand that waiting on an interrupt or completion event is not
> available infrastructure in the current reset-controller code... but
> maybe it should be a little more advanced than polling implementation
> :D

Yes, maybe the module reset part of the SRC should be implemented as a
proper device driver in drivers/reset. Then we could use the interrupt
functionality and WARN_ON(timeout), as you suggest.

> I am not not-acking the code, and I would be overjoyed for it to go in
> as-is (maybe with a function rename as above), but I would appreciate
> the consideration that a reset-controller with some way of reporting a
> successful reset other than polling is something that might come in
> handy for other people (and i.MX SRC would be a highly desirable use
> case) and at the very least in the case of the i.MX SRC, "this unit
> did not reset after [possibly more than] a whole second of waiting" is
> not encompassed within if (ret) pr_err("unit did not reset") in the
> driver.. nor would this be an immediate and serious indication to the
> driver or end-user.

regards
Philipp

^ permalink raw reply

* [PATCH] slab : allow SLAB_RED_ZONE and SLAB_STORE_USER to work on arm
From: Matthieu CASTET @ 2013-01-21  9:56 UTC (permalink / raw)
  To: linux-arm-kernel

The current slab code only allow to put redzone( and user store) info if "buffer
alignment(ralign) <= __alignof__(unsigned long long)". This was done because we
want to keep the buffer aligned for user even after adding redzone@the
beginning of the buffer (the user store is stored after user buffer) [1]

But instead of disabling this feature when "ralign > __alignof__(unsigned long
long)", we can force the alignment by allocating ralign before user buffer.

This is done by setting ralign in obj_offset when "ralign > __alignof__(unsigned
long long)" and keeping the old behavior when  "ralign <= __alignof__(unsigned
long long)" (we set sizeof(unsigned long long)).

The 5c5e3b33b7cb959a401f823707bee006caadd76e commit wasn't handling "ralign <=
__alignof__(unsigned long long)", that's why it broked some configuration.

This was tested on omap3 (ralign is 64 and __alignof__(unsigned long long) is 8)

[1]
/*
 * memory layout of objects:
 * 0        : objp
 * 0 .. cachep->obj_offset - BYTES_PER_WORD - 1: padding. This ensures that
 *      the end of an object is aligned with the end of the real
 *      allocation. Catches writes behind the end of the allocation.
 * cachep->obj_offset - BYTES_PER_WORD .. cachep->obj_offset - 1:
 *      redzone word.
 * cachep->obj_offset: The real object.
 * cachep->buffer_size - 2* BYTES_PER_WORD: redzone word [BYTES_PER_WORD long]
 * cachep->buffer_size - 1* BYTES_PER_WORD: last caller address
 *                  [BYTES_PER_WORD long]
 */

Signed-off-by: Matthieu Castet <matthieu.castet@parrot.com>
CC: Russell King <rmk@arm.linux.org.uk>
CC: Pekka Enberg <penberg@cs.helsinki.fi>
---
 mm/slab.c |    8 +++-----
 1 file changed, 3 insertions(+), 5 deletions(-)

diff --git a/mm/slab.c b/mm/slab.c
index e7667a3..d2380d9 100644
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -2392,9 +2392,6 @@ __kmem_cache_create (struct kmem_cache *cachep, unsigned long flags)
 	if (ralign < cachep->align) {
 		ralign = cachep->align;
 	}
-	/* disable debug if necessary */
-	if (ralign > __alignof__(unsigned long long))
-		flags &= ~(SLAB_RED_ZONE | SLAB_STORE_USER);
 	/*
 	 * 4) Store it.
 	 */
@@ -2414,8 +2411,9 @@ __kmem_cache_create (struct kmem_cache *cachep, unsigned long flags)
 	 */
 	if (flags & SLAB_RED_ZONE) {
 		/* add space for red zone words */
-		cachep->obj_offset += sizeof(unsigned long long);
-		size += 2 * sizeof(unsigned long long);
+		int offset = max(ralign, sizeof(unsigned long long));
+		cachep->obj_offset += offset;
+		size += offset + sizeof(unsigned long long);
 	}
 	if (flags & SLAB_STORE_USER) {
 		/* user store requires one word storage behind the end of
-- 
1.7.10.4

^ permalink raw reply related

* [PATCH v4 0/7] ARM: Exynos: Enable device tree support for MCT controller
From: Thomas Abraham @ 2013-01-21 10:02 UTC (permalink / raw)
  To: linux-arm-kernel

Changes since v3:
- Based on Stephen Warren's CONFIG_CLKSRC_OF patches (merged from arm-soc
  'timer/cleanup' branch).
- Moved the mct driver from mach-exynos to drivers/clocksource

Changes since v2:
- Rebased to linux 3.8-rc1

Changes since v1:
- Includes changes suggested by Sylwester Nawrocki <sylvester.nawrocki@gmail.com>

This patch series adds device tree support for Exynos4/5 MCT controller and
moves the MCT driver from mach-exynos to drivers/clocksource. These patches
are based on Stephen Warren's CONFIG_CLKSRC_OF patches which were merged from
the 'timer/cleanup' branch of the arm-soc tree. It also depends on the
following two patches.

- http://lists.infradead.org/pipermail/linux-arm-kernel/2013-January/143084.html
- http://lists.infradead.org/pipermail/linux-arm-kernel/2013-January/143119.html

This patch series has been tested on Exynos4210 based Origen board, Exynos4412
based Origen board and Exynos5250 based SMDK board.

Thomas Abraham (7):
  ARM: Exynos: add a register base address variable in mct controller driver
  ARM: Exynos: prepare an array of MCT interrupt numbers and use it
  ARM: Exynos: add device tree support for MCT controller driver
  ARM: Exynos: allow dt based discovery of mct controller using clocksource_of_init
  ARM: dts: add mct device tree node for all supported Exynos SoC's
  ARM: Exynos: remove static io-remapping of mct registers for Exynos5
  ARM: Exynos: move mct driver to drivers/clocksource

 .../bindings/timer/samsung,exynos4210-mct.txt      |   68 +++++++
 arch/arm/Kconfig                                   |    2 +-
 arch/arm/boot/dts/exynos4210.dtsi                  |    7 +
 arch/arm/boot/dts/exynos4212.dtsi                  |    9 +
 arch/arm/boot/dts/exynos4412.dtsi                  |    7 +
 arch/arm/boot/dts/exynos5250.dtsi                  |   20 ++
 arch/arm/mach-exynos/Kconfig                       |    8 +-
 arch/arm/mach-exynos/Makefile                      |    2 -
 arch/arm/mach-exynos/common.c                      |    5 -
 arch/arm/mach-exynos/common.h                      |    2 +-
 arch/arm/mach-exynos/include/mach/irqs.h           |    6 -
 arch/arm/mach-exynos/include/mach/map.h            |    1 -
 arch/arm/mach-exynos/include/mach/regs-mct.h       |   53 ------
 arch/arm/mach-exynos/mach-armlex4210.c             |    2 +-
 arch/arm/mach-exynos/mach-exynos4-dt.c             |    3 +-
 arch/arm/mach-exynos/mach-exynos5-dt.c             |    3 +-
 arch/arm/mach-exynos/mach-nuri.c                   |    2 +-
 arch/arm/mach-exynos/mach-origen.c                 |    2 +-
 arch/arm/mach-exynos/mach-smdk4x12.c               |    4 +-
 arch/arm/mach-exynos/mach-smdkv310.c               |    4 +-
 drivers/clocksource/Kconfig                        |    5 +
 drivers/clocksource/Makefile                       |    1 +
 .../mct.c => drivers/clocksource/exynos_mct.c      |  197 +++++++++++++-------
 23 files changed, 264 insertions(+), 149 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/timer/samsung,exynos4210-mct.txt
 delete mode 100644 arch/arm/mach-exynos/include/mach/regs-mct.h
 rename arch/arm/mach-exynos/mct.c => drivers/clocksource/exynos_mct.c (67%)

^ permalink raw reply

* [PATCH v4 1/7] ARM: Exynos: add a register base address variable in mct controller driver
From: Thomas Abraham @ 2013-01-21 10:02 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1358762542-19008-1-git-send-email-thomas.abraham@linaro.org>

All the MCT register read/writes use a fixed remapped address S5P_VA_SYSTIMER.
With device tree support for MCT controller, it is possible to remove the
static remap of the MCT controller address space and do the remap during the
initialization of the MCT controller with the physical address obtained from
the device tree.

So in preparation of adding device tree support for MCT controller, add a new
register base address variable that will hold the remapped MCT controller base
address and convert all MCT register read/writes to use this new variable as
the base address instead of the fixed S5P_VA_SYSTIMER.

While at it, the MCT register offset and bit mask definitions are moved into
the MCT controller driver file since there are no other consumers of these
definitions.

Cc: Changhwan Youn <chaos.youn@samsung.com>
Signed-off-by: Thomas Abraham <thomas.abraham@linaro.org>
---
 arch/arm/mach-exynos/include/mach/regs-mct.h |   53 --------------
 arch/arm/mach-exynos/mct.c                   |   97 ++++++++++++++++---------
 2 files changed, 62 insertions(+), 88 deletions(-)
 delete mode 100644 arch/arm/mach-exynos/include/mach/regs-mct.h

diff --git a/arch/arm/mach-exynos/include/mach/regs-mct.h b/arch/arm/mach-exynos/include/mach/regs-mct.h
deleted file mode 100644
index 80dd02a..0000000
--- a/arch/arm/mach-exynos/include/mach/regs-mct.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/* arch/arm/mach-exynos4/include/mach/regs-mct.h
- *
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * EXYNOS4 MCT configutation
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARCH_REGS_MCT_H
-#define __ASM_ARCH_REGS_MCT_H __FILE__
-
-#include <mach/map.h>
-
-#define EXYNOS4_MCTREG(x)		(S5P_VA_SYSTIMER + (x))
-
-#define EXYNOS4_MCT_G_CNT_L		EXYNOS4_MCTREG(0x100)
-#define EXYNOS4_MCT_G_CNT_U		EXYNOS4_MCTREG(0x104)
-#define EXYNOS4_MCT_G_CNT_WSTAT		EXYNOS4_MCTREG(0x110)
-
-#define EXYNOS4_MCT_G_COMP0_L		EXYNOS4_MCTREG(0x200)
-#define EXYNOS4_MCT_G_COMP0_U		EXYNOS4_MCTREG(0x204)
-#define EXYNOS4_MCT_G_COMP0_ADD_INCR	EXYNOS4_MCTREG(0x208)
-
-#define EXYNOS4_MCT_G_TCON		EXYNOS4_MCTREG(0x240)
-
-#define EXYNOS4_MCT_G_INT_CSTAT		EXYNOS4_MCTREG(0x244)
-#define EXYNOS4_MCT_G_INT_ENB		EXYNOS4_MCTREG(0x248)
-#define EXYNOS4_MCT_G_WSTAT		EXYNOS4_MCTREG(0x24C)
-
-#define _EXYNOS4_MCT_L_BASE		EXYNOS4_MCTREG(0x300)
-#define EXYNOS4_MCT_L_BASE(x)		(_EXYNOS4_MCT_L_BASE + (0x100 * x))
-#define EXYNOS4_MCT_L_MASK		(0xffffff00)
-
-#define MCT_L_TCNTB_OFFSET		(0x00)
-#define MCT_L_ICNTB_OFFSET		(0x08)
-#define MCT_L_TCON_OFFSET		(0x20)
-#define MCT_L_INT_CSTAT_OFFSET		(0x30)
-#define MCT_L_INT_ENB_OFFSET		(0x34)
-#define MCT_L_WSTAT_OFFSET		(0x40)
-
-#define MCT_G_TCON_START		(1 << 8)
-#define MCT_G_TCON_COMP0_AUTO_INC	(1 << 1)
-#define MCT_G_TCON_COMP0_ENABLE		(1 << 0)
-
-#define MCT_L_TCON_INTERVAL_MODE	(1 << 2)
-#define MCT_L_TCON_INT_START		(1 << 1)
-#define MCT_L_TCON_TIMER_START		(1 << 0)
-
-#endif /* __ASM_ARCH_REGS_MCT_H */
diff --git a/arch/arm/mach-exynos/mct.c b/arch/arm/mach-exynos/mct.c
index 4a89b54..6ceb1dd 100644
--- a/arch/arm/mach-exynos/mct.c
+++ b/arch/arm/mach-exynos/mct.c
@@ -29,9 +29,36 @@
 
 #include <mach/map.h>
 #include <mach/irqs.h>
-#include <mach/regs-mct.h>
 #include <asm/mach/time.h>
 
+#define EXYNOS4_MCTREG(x)		(x)
+#define EXYNOS4_MCT_G_CNT_L		EXYNOS4_MCTREG(0x100)
+#define EXYNOS4_MCT_G_CNT_U		EXYNOS4_MCTREG(0x104)
+#define EXYNOS4_MCT_G_CNT_WSTAT		EXYNOS4_MCTREG(0x110)
+#define EXYNOS4_MCT_G_COMP0_L		EXYNOS4_MCTREG(0x200)
+#define EXYNOS4_MCT_G_COMP0_U		EXYNOS4_MCTREG(0x204)
+#define EXYNOS4_MCT_G_COMP0_ADD_INCR	EXYNOS4_MCTREG(0x208)
+#define EXYNOS4_MCT_G_TCON		EXYNOS4_MCTREG(0x240)
+#define EXYNOS4_MCT_G_INT_CSTAT		EXYNOS4_MCTREG(0x244)
+#define EXYNOS4_MCT_G_INT_ENB		EXYNOS4_MCTREG(0x248)
+#define EXYNOS4_MCT_G_WSTAT		EXYNOS4_MCTREG(0x24C)
+#define _EXYNOS4_MCT_L_BASE		EXYNOS4_MCTREG(0x300)
+#define EXYNOS4_MCT_L_BASE(x)		(_EXYNOS4_MCT_L_BASE + (0x100 * x))
+#define EXYNOS4_MCT_L_MASK		(0xffffff00)
+
+#define MCT_L_TCNTB_OFFSET		(0x00)
+#define MCT_L_ICNTB_OFFSET		(0x08)
+#define MCT_L_TCON_OFFSET		(0x20)
+#define MCT_L_INT_CSTAT_OFFSET		(0x30)
+#define MCT_L_INT_ENB_OFFSET		(0x34)
+#define MCT_L_WSTAT_OFFSET		(0x40)
+#define MCT_G_TCON_START		(1 << 8)
+#define MCT_G_TCON_COMP0_AUTO_INC	(1 << 1)
+#define MCT_G_TCON_COMP0_ENABLE		(1 << 0)
+#define MCT_L_TCON_INTERVAL_MODE	(1 << 2)
+#define MCT_L_TCON_INT_START		(1 << 1)
+#define MCT_L_TCON_TIMER_START		(1 << 0)
+
 #define TICK_BASE_CNT	1
 
 enum {
@@ -39,64 +66,62 @@ enum {
 	MCT_INT_PPI
 };
 
+static void __iomem *reg_base;
 static unsigned long clk_rate;
 static unsigned int mct_int_type;
 
 struct mct_clock_event_device {
 	struct clock_event_device *evt;
-	void __iomem *base;
+	unsigned long base;
 	char name[10];
 };
 
-static void exynos4_mct_write(unsigned int value, void *addr)
+static void exynos4_mct_write(unsigned int value, unsigned long offset)
 {
-	void __iomem *stat_addr;
+	unsigned long stat_addr;
 	u32 mask;
 	u32 i;
 
-	__raw_writel(value, addr);
+	__raw_writel(value, reg_base + offset);
 
-	if (likely(addr >= EXYNOS4_MCT_L_BASE(0))) {
-		u32 base = (u32) addr & EXYNOS4_MCT_L_MASK;
-		switch ((u32) addr & ~EXYNOS4_MCT_L_MASK) {
-		case (u32) MCT_L_TCON_OFFSET:
-			stat_addr = (void __iomem *) base + MCT_L_WSTAT_OFFSET;
+	if (likely(offset >= EXYNOS4_MCT_L_BASE(0))) {
+		stat_addr = (offset & ~EXYNOS4_MCT_L_MASK) + MCT_L_WSTAT_OFFSET;
+		switch (offset & EXYNOS4_MCT_L_MASK) {
+		case MCT_L_TCON_OFFSET:
 			mask = 1 << 3;		/* L_TCON write status */
 			break;
-		case (u32) MCT_L_ICNTB_OFFSET:
-			stat_addr = (void __iomem *) base + MCT_L_WSTAT_OFFSET;
+		case MCT_L_ICNTB_OFFSET:
 			mask = 1 << 1;		/* L_ICNTB write status */
 			break;
-		case (u32) MCT_L_TCNTB_OFFSET:
-			stat_addr = (void __iomem *) base + MCT_L_WSTAT_OFFSET;
+		case MCT_L_TCNTB_OFFSET:
 			mask = 1 << 0;		/* L_TCNTB write status */
 			break;
 		default:
 			return;
 		}
 	} else {
-		switch ((u32) addr) {
-		case (u32) EXYNOS4_MCT_G_TCON:
+		switch (offset) {
+		case EXYNOS4_MCT_G_TCON:
 			stat_addr = EXYNOS4_MCT_G_WSTAT;
 			mask = 1 << 16;		/* G_TCON write status */
 			break;
-		case (u32) EXYNOS4_MCT_G_COMP0_L:
+		case EXYNOS4_MCT_G_COMP0_L:
 			stat_addr = EXYNOS4_MCT_G_WSTAT;
 			mask = 1 << 0;		/* G_COMP0_L write status */
 			break;
-		case (u32) EXYNOS4_MCT_G_COMP0_U:
+		case EXYNOS4_MCT_G_COMP0_U:
 			stat_addr = EXYNOS4_MCT_G_WSTAT;
 			mask = 1 << 1;		/* G_COMP0_U write status */
 			break;
-		case (u32) EXYNOS4_MCT_G_COMP0_ADD_INCR:
+		case EXYNOS4_MCT_G_COMP0_ADD_INCR:
 			stat_addr = EXYNOS4_MCT_G_WSTAT;
 			mask = 1 << 2;		/* G_COMP0_ADD_INCR w status */
 			break;
-		case (u32) EXYNOS4_MCT_G_CNT_L:
+		case EXYNOS4_MCT_G_CNT_L:
 			stat_addr = EXYNOS4_MCT_G_CNT_WSTAT;
 			mask = 1 << 0;		/* G_CNT_L write status */
 			break;
-		case (u32) EXYNOS4_MCT_G_CNT_U:
+		case EXYNOS4_MCT_G_CNT_U:
 			stat_addr = EXYNOS4_MCT_G_CNT_WSTAT;
 			mask = 1 << 1;		/* G_CNT_U write status */
 			break;
@@ -107,12 +132,12 @@ static void exynos4_mct_write(unsigned int value, void *addr)
 
 	/* Wait maximum 1 ms until written values are applied */
 	for (i = 0; i < loops_per_jiffy / 1000 * HZ; i++)
-		if (__raw_readl(stat_addr) & mask) {
-			__raw_writel(mask, stat_addr);
+		if (__raw_readl(reg_base + stat_addr) & mask) {
+			__raw_writel(mask, reg_base + stat_addr);
 			return;
 		}
 
-	panic("MCT hangs after writing %d (addr:0x%08x)\n", value, (u32)addr);
+	panic("MCT hangs after writing %d (offset:0x%lx)\n", value, offset);
 }
 
 /* Clocksource handling */
@@ -123,7 +148,7 @@ static void exynos4_mct_frc_start(u32 hi, u32 lo)
 	exynos4_mct_write(lo, EXYNOS4_MCT_G_CNT_L);
 	exynos4_mct_write(hi, EXYNOS4_MCT_G_CNT_U);
 
-	reg = __raw_readl(EXYNOS4_MCT_G_TCON);
+	reg = __raw_readl(reg_base + EXYNOS4_MCT_G_TCON);
 	reg |= MCT_G_TCON_START;
 	exynos4_mct_write(reg, EXYNOS4_MCT_G_TCON);
 }
@@ -131,12 +156,12 @@ static void exynos4_mct_frc_start(u32 hi, u32 lo)
 static cycle_t exynos4_frc_read(struct clocksource *cs)
 {
 	unsigned int lo, hi;
-	u32 hi2 = __raw_readl(EXYNOS4_MCT_G_CNT_U);
+	u32 hi2 = __raw_readl(reg_base + EXYNOS4_MCT_G_CNT_U);
 
 	do {
 		hi = hi2;
-		lo = __raw_readl(EXYNOS4_MCT_G_CNT_L);
-		hi2 = __raw_readl(EXYNOS4_MCT_G_CNT_U);
+		lo = __raw_readl(reg_base + EXYNOS4_MCT_G_CNT_L);
+		hi2 = __raw_readl(reg_base + EXYNOS4_MCT_G_CNT_U);
 	} while (hi != hi2);
 
 	return ((cycle_t)hi << 32) | lo;
@@ -168,7 +193,7 @@ static void exynos4_mct_comp0_stop(void)
 {
 	unsigned int tcon;
 
-	tcon = __raw_readl(EXYNOS4_MCT_G_TCON);
+	tcon = __raw_readl(reg_base + EXYNOS4_MCT_G_TCON);
 	tcon &= ~(MCT_G_TCON_COMP0_ENABLE | MCT_G_TCON_COMP0_AUTO_INC);
 
 	exynos4_mct_write(tcon, EXYNOS4_MCT_G_TCON);
@@ -181,7 +206,7 @@ static void exynos4_mct_comp0_start(enum clock_event_mode mode,
 	unsigned int tcon;
 	cycle_t comp_cycle;
 
-	tcon = __raw_readl(EXYNOS4_MCT_G_TCON);
+	tcon = __raw_readl(reg_base + EXYNOS4_MCT_G_TCON);
 
 	if (mode == CLOCK_EVT_MODE_PERIODIC) {
 		tcon |= MCT_G_TCON_COMP0_AUTO_INC;
@@ -278,12 +303,12 @@ static void exynos4_mct_tick_stop(struct mct_clock_event_device *mevt)
 {
 	unsigned long tmp;
 	unsigned long mask = MCT_L_TCON_INT_START | MCT_L_TCON_TIMER_START;
-	void __iomem *addr = mevt->base + MCT_L_TCON_OFFSET;
+	unsigned long offset = mevt->base + MCT_L_TCON_OFFSET;
 
-	tmp = __raw_readl(addr);
+	tmp = __raw_readl(reg_base + offset);
 	if (tmp & mask) {
 		tmp &= ~mask;
-		exynos4_mct_write(tmp, addr);
+		exynos4_mct_write(tmp, offset);
 	}
 }
 
@@ -302,7 +327,7 @@ static void exynos4_mct_tick_start(unsigned long cycles,
 	/* enable MCT tick interrupt */
 	exynos4_mct_write(0x1, mevt->base + MCT_L_INT_ENB_OFFSET);
 
-	tmp = __raw_readl(mevt->base + MCT_L_TCON_OFFSET);
+	tmp = __raw_readl(reg_base + mevt->base + MCT_L_TCON_OFFSET);
 	tmp |= MCT_L_TCON_INT_START | MCT_L_TCON_TIMER_START |
 	       MCT_L_TCON_INTERVAL_MODE;
 	exynos4_mct_write(tmp, mevt->base + MCT_L_TCON_OFFSET);
@@ -354,7 +379,7 @@ static int exynos4_mct_tick_clear(struct mct_clock_event_device *mevt)
 		exynos4_mct_tick_stop(mevt);
 
 	/* Clear the MCT tick interrupt */
-	if (__raw_readl(mevt->base + MCT_L_INT_CSTAT_OFFSET) & 1) {
+	if (__raw_readl(reg_base + mevt->base + MCT_L_INT_CSTAT_OFFSET) & 1) {
 		exynos4_mct_write(0x1, mevt->base + MCT_L_INT_CSTAT_OFFSET);
 		return 1;
 	} else {
@@ -463,6 +488,8 @@ static void __init exynos4_timer_resources(void)
 
 	clk_rate = clk_get_rate(mct_clk);
 
+	reg_base = S5P_VA_SYSTIMER;
+
 #ifdef CONFIG_LOCAL_TIMERS
 	if (mct_int_type == MCT_INT_PPI) {
 		int err;
-- 
1.7.5.4

^ permalink raw reply related

* [PATCH v4 2/7] ARM: Exynos: prepare an array of MCT interrupt numbers and use it
From: Thomas Abraham @ 2013-01-21 10:02 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1358762542-19008-1-git-send-email-thomas.abraham@linaro.org>

Instead of using soc_is_xxx macro at more than one place in the MCT
controller driver to decide the MCT interrpt number to be setup, populate
a table of known MCT global and local timer interrupts and use the values
in table to setup the MCT interrupts.

This also helps in adding device tree support for MCT controller driver by
allowing the driver to retrieve interrupt numbers from device tree and
populating them into this table, thereby supporting both legacy and dt
functionality to co-exist.

Cc: Changhwan Youn <chaos.youn@samsung.com>
Signed-off-by: Thomas Abraham <thomas.abraham@linaro.org>
---
 arch/arm/mach-exynos/mct.c |   57 +++++++++++++++++++++++++++----------------
 1 files changed, 36 insertions(+), 21 deletions(-)

diff --git a/arch/arm/mach-exynos/mct.c b/arch/arm/mach-exynos/mct.c
index 6ceb1dd..3c91511 100644
--- a/arch/arm/mach-exynos/mct.c
+++ b/arch/arm/mach-exynos/mct.c
@@ -66,9 +66,22 @@ enum {
 	MCT_INT_PPI
 };
 
+enum {
+	MCT_G0_IRQ,
+	MCT_G1_IRQ,
+	MCT_G2_IRQ,
+	MCT_G3_IRQ,
+	MCT_L0_IRQ,
+	MCT_L1_IRQ,
+	MCT_L2_IRQ,
+	MCT_L3_IRQ,
+	MCT_NR_IRQS,
+};
+
 static void __iomem *reg_base;
 static unsigned long clk_rate;
 static unsigned int mct_int_type;
+static int mct_irqs[MCT_NR_IRQS];
 
 struct mct_clock_event_device {
 	struct clock_event_device *evt;
@@ -287,11 +300,7 @@ static void exynos4_clockevent_init(void)
 		clockevent_delta2ns(0xf, &mct_comp_device);
 	mct_comp_device.cpumask = cpumask_of(0);
 	clockevents_register_device(&mct_comp_device);
-
-	if (soc_is_exynos5250())
-		setup_irq(EXYNOS5_IRQ_MCT_G0, &mct_comp_event_irq);
-	else
-		setup_irq(EXYNOS4_IRQ_MCT_G0, &mct_comp_event_irq);
+	setup_irq(mct_irqs[MCT_G0_IRQ], &mct_comp_event_irq);
 }
 
 #ifdef CONFIG_LOCAL_TIMERS
@@ -415,7 +424,6 @@ static int __cpuinit exynos4_local_timer_setup(struct clock_event_device *evt)
 {
 	struct mct_clock_event_device *mevt;
 	unsigned int cpu = smp_processor_id();
-	int mct_lx_irq;
 
 	mevt = this_cpu_ptr(&percpu_mct_tick);
 	mevt->evt = evt;
@@ -442,21 +450,17 @@ static int __cpuinit exynos4_local_timer_setup(struct clock_event_device *evt)
 
 	if (mct_int_type == MCT_INT_SPI) {
 		if (cpu == 0) {
-			mct_lx_irq = soc_is_exynos4210() ? EXYNOS4_IRQ_MCT_L0 :
-						EXYNOS5_IRQ_MCT_L0;
 			mct_tick0_event_irq.dev_id = mevt;
-			evt->irq = mct_lx_irq;
-			setup_irq(mct_lx_irq, &mct_tick0_event_irq);
+			evt->irq = mct_irqs[MCT_L0_IRQ];
+			setup_irq(evt->irq, &mct_tick0_event_irq);
 		} else {
-			mct_lx_irq = soc_is_exynos4210() ? EXYNOS4_IRQ_MCT_L1 :
-						EXYNOS5_IRQ_MCT_L1;
 			mct_tick1_event_irq.dev_id = mevt;
-			evt->irq = mct_lx_irq;
-			setup_irq(mct_lx_irq, &mct_tick1_event_irq);
-			irq_set_affinity(mct_lx_irq, cpumask_of(1));
+			evt->irq = mct_irqs[MCT_L1_IRQ];
+			setup_irq(evt->irq, &mct_tick1_event_irq);
+			irq_set_affinity(evt->irq, cpumask_of(1));
 		}
 	} else {
-		enable_percpu_irq(EXYNOS_IRQ_MCT_LOCALTIMER, 0);
+		enable_percpu_irq(mct_irqs[MCT_L0_IRQ], 0);
 	}
 
 	return 0;
@@ -472,7 +476,7 @@ static void exynos4_local_timer_stop(struct clock_event_device *evt)
 		else
 			remove_irq(evt->irq, &mct_tick1_event_irq);
 	else
-		disable_percpu_irq(EXYNOS_IRQ_MCT_LOCALTIMER);
+		disable_percpu_irq(mct_irqs[MCT_L0_IRQ]);
 }
 
 static struct local_timer_ops exynos4_mct_tick_ops __cpuinitdata = {
@@ -494,11 +498,11 @@ static void __init exynos4_timer_resources(void)
 	if (mct_int_type == MCT_INT_PPI) {
 		int err;
 
-		err = request_percpu_irq(EXYNOS_IRQ_MCT_LOCALTIMER,
+		err = request_percpu_irq(mct_irqs[MCT_L0_IRQ],
 					 exynos4_mct_tick_isr, "MCT",
 					 &percpu_mct_tick);
 		WARN(err, "MCT: can't request IRQ %d (%d)\n",
-		     EXYNOS_IRQ_MCT_LOCALTIMER, err);
+		     mct_irqs[MCT_L0_IRQ], err);
 	}
 
 	local_timer_register(&exynos4_mct_tick_ops);
@@ -512,10 +516,21 @@ void __init exynos4_timer_init(void)
 		return;
 	}
 
-	if ((soc_is_exynos4210()) || (soc_is_exynos5250()))
+	if (soc_is_exynos4210()) {
+		mct_irqs[MCT_G0_IRQ] = EXYNOS4_IRQ_MCT_G0;
+		mct_irqs[MCT_L0_IRQ] = EXYNOS4_IRQ_MCT_L0;
+		mct_irqs[MCT_L1_IRQ] = EXYNOS4_IRQ_MCT_L1;
 		mct_int_type = MCT_INT_SPI;
-	else
+	} else if (soc_is_exynos5250()) {
+		mct_irqs[MCT_G0_IRQ] = EXYNOS5_IRQ_MCT_G0;
+		mct_irqs[MCT_L0_IRQ] = EXYNOS5_IRQ_MCT_L0;
+		mct_irqs[MCT_L1_IRQ] = EXYNOS5_IRQ_MCT_L1;
+		mct_int_type = MCT_INT_SPI;
+	} else {
+		mct_irqs[MCT_G0_IRQ] = EXYNOS4_IRQ_MCT_G0;
+		mct_irqs[MCT_L0_IRQ] = EXYNOS_IRQ_MCT_LOCALTIMER;
 		mct_int_type = MCT_INT_PPI;
+	}
 
 	exynos4_timer_resources();
 	exynos4_clocksource_init();
-- 
1.7.5.4

^ permalink raw reply related

* [PATCH v4 3/7] ARM: Exynos: add device tree support for MCT controller driver
From: Thomas Abraham @ 2013-01-21 10:02 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1358762542-19008-1-git-send-email-thomas.abraham@linaro.org>

Allow the MCT controller base address and interrupts to be obtained from
device tree and remove unused static definitions of these. The non-dt support
for Exynos5250 is removed but retained for Exynos4210 based platforms.

Cc: Changhwan Youn <chaos.youn@samsung.com>
Signed-off-by: Thomas Abraham <thomas.abraham@linaro.org>
---
 .../bindings/timer/samsung,exynos4210-mct.txt      |   68 ++++++++++++++++++++
 arch/arm/mach-exynos/include/mach/irqs.h           |    6 --
 arch/arm/mach-exynos/mct.c                         |   49 +++++++++++----
 3 files changed, 105 insertions(+), 18 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/timer/samsung,exynos4210-mct.txt

diff --git a/Documentation/devicetree/bindings/timer/samsung,exynos4210-mct.txt b/Documentation/devicetree/bindings/timer/samsung,exynos4210-mct.txt
new file mode 100644
index 0000000..cb47bfb
--- /dev/null
+++ b/Documentation/devicetree/bindings/timer/samsung,exynos4210-mct.txt
@@ -0,0 +1,68 @@
+Samsung's Multi Core Timer (MCT)
+
+The Samsung's Multi Core Timer (MCT) module includes two main blocks, the
+global timer and CPU local timers. The global timer is a 64-bit free running
+up-counter and can generate 4 interrupts when the counter reaches one of the
+four preset counter values. The CPU local timers are 32-bit free running
+down-counters and generate an interrupt when the counter expires. There is
+one CPU local timer instantiated in MCT for every CPU in the system.
+
+Required properties:
+
+- compatible: should be "samsung,exynos4210-mct".
+  (a) "samsung,exynos4210-mct", for mct compatible with Exynos4210 mct.
+  (b) "samsung,exynos4412-mct", for mct compatible with Exynos4412 mct.
+
+- reg: base address of the mct controller and length of the address space
+  it occupies.
+
+- interrupts: the list of interrupts generated by the controller. The following
+  should be the order of the interrupts specified. The local timer interrupts
+  should be specified after the four global timer interrupts have been
+  specified.
+
+	0: Global Timer Interrupt 0
+	1: Global Timer Interrupt 1
+	2: Global Timer Interrupt 2
+	3: Global Timer Interrupt 3
+	4: Local Timer Interrupt 0
+	5: Local Timer Interrupt 1
+	6: ..
+	7: ..
+	i: Local Timer Interrupt n
+
+Example 1: In this example, the system uses only the first global timer
+	   interrupt generated by MCT and the remaining three global timer
+	   interrupts are unused. Two local timer interrupts have been
+	   specified.
+
+	mct at 10050000 {
+		compatible = "samsung,exynos4210-mct";
+		reg = <0x10050000 0x800>;
+		interrupts = <0 57 0>, <0 0 0>, <0 0 0>, <0 0 0>,
+			     <0 42 0>, <0 48 0>;
+	};
+
+Example 2: In this example, the MCT global and local timer interrupts are
+	   connected to two seperate interrupt controllers. Hence, an
+	   interrupt-map is created to map the interrupts to the respective
+	   interrupt controllers.
+
+	mct at 101C0000 {
+		compatible = "samsung,exynos4210-mct";
+		reg = <0x101C0000 0x800>;
+		interrupt-controller;
+		#interrups-cells = <2>;
+		interrupt-parent = <&mct_map>;
+		interrupts = <0 0>, <1 0>, <2 0>, <3 0>,
+			     <4 0>, <5 0>;
+
+		mct_map: mct-map {
+			#interrupt-cells = <2>;
+			#address-cells = <0>;
+			#size-cells = <0>;
+			interrupt-map = <0x0 0 &combiner 23 3>,
+					<0x4 0 &gic 0 120 0>,
+					<0x5 0 &gic 0 121 0>;
+		};
+	};
diff --git a/arch/arm/mach-exynos/include/mach/irqs.h b/arch/arm/mach-exynos/include/mach/irqs.h
index 6794292..35fe6d5 100644
--- a/arch/arm/mach-exynos/include/mach/irqs.h
+++ b/arch/arm/mach-exynos/include/mach/irqs.h
@@ -30,8 +30,6 @@
 
 /* For EXYNOS4 and EXYNOS5 */
 
-#define EXYNOS_IRQ_MCT_LOCALTIMER	IRQ_PPI(12)
-
 #define EXYNOS_IRQ_EINT16_31		IRQ_SPI(32)
 
 /* For EXYNOS4 SoCs */
@@ -330,8 +328,6 @@
 #define EXYNOS5_IRQ_CEC			IRQ_SPI(114)
 #define EXYNOS5_IRQ_SATA		IRQ_SPI(115)
 
-#define EXYNOS5_IRQ_MCT_L0		IRQ_SPI(120)
-#define EXYNOS5_IRQ_MCT_L1		IRQ_SPI(121)
 #define EXYNOS5_IRQ_MMC44		IRQ_SPI(123)
 #define EXYNOS5_IRQ_MDMA1		IRQ_SPI(124)
 #define EXYNOS5_IRQ_FIMC_LITE0		IRQ_SPI(125)
@@ -426,8 +422,6 @@
 #define EXYNOS5_IRQ_PMU_CPU1		COMBINER_IRQ(22, 4)
 
 #define EXYNOS5_IRQ_EINT0		COMBINER_IRQ(23, 0)
-#define EXYNOS5_IRQ_MCT_G0		COMBINER_IRQ(23, 3)
-#define EXYNOS5_IRQ_MCT_G1		COMBINER_IRQ(23, 4)
 
 #define EXYNOS5_IRQ_EINT1		COMBINER_IRQ(24, 0)
 #define EXYNOS5_IRQ_SYSMMU_LITE1_0	COMBINER_IRQ(24, 1)
diff --git a/arch/arm/mach-exynos/mct.c b/arch/arm/mach-exynos/mct.c
index 3c91511..2942bee 100644
--- a/arch/arm/mach-exynos/mct.c
+++ b/arch/arm/mach-exynos/mct.c
@@ -20,6 +20,8 @@
 #include <linux/delay.h>
 #include <linux/percpu.h>
 #include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_address.h>
 
 #include <asm/arch_timer.h>
 #include <asm/hardware/gic.h>
@@ -485,14 +487,16 @@ static struct local_timer_ops exynos4_mct_tick_ops __cpuinitdata = {
 };
 #endif /* CONFIG_LOCAL_TIMERS */
 
-static void __init exynos4_timer_resources(void)
+static void __init exynos4_timer_resources(struct device_node *np)
 {
 	struct clk *mct_clk;
 	mct_clk = clk_get(NULL, "xtal");
 
 	clk_rate = clk_get_rate(mct_clk);
 
-	reg_base = S5P_VA_SYSTIMER;
+	reg_base = np ? of_iomap(np, 0) : S5P_VA_SYSTIMER;
+	if (!reg_base)
+		panic("%s: unable to ioremap mct address space\n", __func__);
 
 #ifdef CONFIG_LOCAL_TIMERS
 	if (mct_int_type == MCT_INT_PPI) {
@@ -509,30 +513,51 @@ static void __init exynos4_timer_resources(void)
 #endif /* CONFIG_LOCAL_TIMERS */
 }
 
+static const struct of_device_id exynos_mct_ids[] = {
+	{ .compatible = "samsung,exynos4210-mct", .data = (void *)MCT_INT_SPI },
+	{ .compatible = "samsung,exynos4412-mct", .data = (void *)MCT_INT_PPI },
+};
+
 void __init exynos4_timer_init(void)
 {
+	struct device_node *np = NULL;
+	const struct of_device_id *match;
+	u32 nr_irqs, i;
+
 	if (soc_is_exynos5440()) {
 		arch_timer_of_register();
 		return;
 	}
 
-	if (soc_is_exynos4210()) {
+#ifdef CONFIG_OF
+	np = of_find_matching_node_and_match(NULL, exynos_mct_ids, &match);
+#endif
+	if (np) {
+		mct_int_type = (u32)(match->data);
+
+		/* This driver uses only one global timer interrupt */
+		mct_irqs[MCT_G0_IRQ] = irq_of_parse_and_map(np, MCT_G0_IRQ);
+
+		/*
+		 * Find out the number of local irqs specified. The local
+		 * timer irqs are specified after the four global timer
+		 * irqs are specified.
+		 */
+#ifdef CONFIG_OF
+		nr_irqs = of_irq_count(np);
+#endif
+		for (i = MCT_L0_IRQ; i < nr_irqs; i++)
+			mct_irqs[i] = irq_of_parse_and_map(np, i);
+	} else if (soc_is_exynos4210()) {
 		mct_irqs[MCT_G0_IRQ] = EXYNOS4_IRQ_MCT_G0;
 		mct_irqs[MCT_L0_IRQ] = EXYNOS4_IRQ_MCT_L0;
 		mct_irqs[MCT_L1_IRQ] = EXYNOS4_IRQ_MCT_L1;
 		mct_int_type = MCT_INT_SPI;
-	} else if (soc_is_exynos5250()) {
-		mct_irqs[MCT_G0_IRQ] = EXYNOS5_IRQ_MCT_G0;
-		mct_irqs[MCT_L0_IRQ] = EXYNOS5_IRQ_MCT_L0;
-		mct_irqs[MCT_L1_IRQ] = EXYNOS5_IRQ_MCT_L1;
-		mct_int_type = MCT_INT_SPI;
 	} else {
-		mct_irqs[MCT_G0_IRQ] = EXYNOS4_IRQ_MCT_G0;
-		mct_irqs[MCT_L0_IRQ] = EXYNOS_IRQ_MCT_LOCALTIMER;
-		mct_int_type = MCT_INT_PPI;
+		panic("unable to determine mct controller type\n");
 	}
 
-	exynos4_timer_resources();
+	exynos4_timer_resources(np);
 	exynos4_clocksource_init();
 	exynos4_clockevent_init();
 }
-- 
1.7.5.4

^ permalink raw reply related

* [PATCH v4 4/7] ARM: Exynos: allow dt based discovery of mct controller using clocksource_of_init
From: Thomas Abraham @ 2013-01-21 10:02 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1358762542-19008-1-git-send-email-thomas.abraham@linaro.org>

Add entries to __clksrc_of_table so that Exynos MCT controller is discoverable
using call to clocksource_of_init. With this change, it would be appropriate to
rename the function 'exynos4_timer_init' as 'mct_init' since it aptly describes
this function. Additionally, the 'init_time' callback of all machine descriptors
for exynos platforms that were previously set to 'exynos4_timer_init' are now
set to either 'mct_init' or 'clocksource_of_init'.

Signed-off-by: Thomas Abraham <thomas.abraham@linaro.org>
---
 arch/arm/mach-exynos/Kconfig           |    2 ++
 arch/arm/mach-exynos/common.h          |    2 +-
 arch/arm/mach-exynos/mach-armlex4210.c |    2 +-
 arch/arm/mach-exynos/mach-exynos4-dt.c |    3 ++-
 arch/arm/mach-exynos/mach-exynos5-dt.c |    3 ++-
 arch/arm/mach-exynos/mach-nuri.c       |    2 +-
 arch/arm/mach-exynos/mach-origen.c     |    2 +-
 arch/arm/mach-exynos/mach-smdk4x12.c   |    4 ++--
 arch/arm/mach-exynos/mach-smdkv310.c   |    4 ++--
 arch/arm/mach-exynos/mct.c             |   12 ++++++------
 10 files changed, 20 insertions(+), 16 deletions(-)

diff --git a/arch/arm/mach-exynos/Kconfig b/arch/arm/mach-exynos/Kconfig
index e103c29..8bdeaa5 100644
--- a/arch/arm/mach-exynos/Kconfig
+++ b/arch/arm/mach-exynos/Kconfig
@@ -416,6 +416,7 @@ config MACH_EXYNOS4_DT
 	select PINCTRL
 	select PINCTRL_EXYNOS4
 	select USE_OF
+	select CLKSRC_OF
 	help
 	  Machine support for Samsung Exynos4 machine with device tree enabled.
 	  Select this if a fdt blob is available for the Exynos4 SoC based board.
@@ -428,6 +429,7 @@ config MACH_EXYNOS5_DT
 	depends on ARCH_EXYNOS5
 	select ARM_AMBA
 	select USE_OF
+	select CLKSRC_OF
 	help
 	  Machine support for Samsung EXYNOS5 machine with device tree enabled.
 	  Select this if a fdt blob is available for the EXYNOS5 SoC based board.
diff --git a/arch/arm/mach-exynos/common.h b/arch/arm/mach-exynos/common.h
index 3ab3c03..be3ea62 100644
--- a/arch/arm/mach-exynos/common.h
+++ b/arch/arm/mach-exynos/common.h
@@ -12,7 +12,7 @@
 #ifndef __ARCH_ARM_MACH_EXYNOS_COMMON_H
 #define __ARCH_ARM_MACH_EXYNOS_COMMON_H
 
-extern void exynos4_timer_init(void);
+extern void mct_init(void);
 
 struct map_desc;
 void exynos_init_io(struct map_desc *mach_desc, int size);
diff --git a/arch/arm/mach-exynos/mach-armlex4210.c b/arch/arm/mach-exynos/mach-armlex4210.c
index 2f18130..27b51d2 100644
--- a/arch/arm/mach-exynos/mach-armlex4210.c
+++ b/arch/arm/mach-exynos/mach-armlex4210.c
@@ -204,6 +204,6 @@ MACHINE_START(ARMLEX4210, "ARMLEX4210")
 	.handle_irq	= gic_handle_irq,
 	.init_machine	= armlex4210_machine_init,
 	.init_late	= exynos_init_late,
-	.init_time	= exynos4_timer_init,
+	.init_time	= mct_init,
 	.restart	= exynos4_restart,
 MACHINE_END
diff --git a/arch/arm/mach-exynos/mach-exynos4-dt.c b/arch/arm/mach-exynos/mach-exynos4-dt.c
index 2a2c96a..6a75e96 100644
--- a/arch/arm/mach-exynos/mach-exynos4-dt.c
+++ b/arch/arm/mach-exynos/mach-exynos4-dt.c
@@ -13,6 +13,7 @@
 
 #include <linux/of_platform.h>
 #include <linux/serial_core.h>
+#include <linux/clocksource.h>
 
 #include <asm/mach/arch.h>
 #include <asm/hardware/gic.h>
@@ -111,7 +112,7 @@ DT_MACHINE_START(EXYNOS4210_DT, "Samsung Exynos4 (Flattened Device Tree)")
 	.init_early	= exynos_firmware_init,
 	.init_machine	= exynos4_dt_machine_init,
 	.init_late	= exynos_init_late,
-	.init_time	= exynos4_timer_init,
+	.init_time	= clocksource_of_init,
 	.dt_compat	= exynos4_dt_compat,
 	.restart        = exynos4_restart,
 MACHINE_END
diff --git a/arch/arm/mach-exynos/mach-exynos5-dt.c b/arch/arm/mach-exynos/mach-exynos5-dt.c
index 4e074c6..39563ce 100644
--- a/arch/arm/mach-exynos/mach-exynos5-dt.c
+++ b/arch/arm/mach-exynos/mach-exynos5-dt.c
@@ -14,6 +14,7 @@
 #include <linux/serial_core.h>
 #include <linux/memblock.h>
 #include <linux/io.h>
+#include <linux/clocksource.h>
 
 #include <asm/mach/arch.h>
 #include <asm/hardware/gic.h>
@@ -182,7 +183,7 @@ DT_MACHINE_START(EXYNOS5_DT, "SAMSUNG EXYNOS5 (Flattened Device Tree)")
 	.handle_irq	= gic_handle_irq,
 	.init_machine	= exynos5_dt_machine_init,
 	.init_late	= exynos_init_late,
-	.init_time	= exynos4_timer_init,
+	.init_time	= clocksource_of_init,
 	.dt_compat	= exynos5_dt_compat,
 	.restart        = exynos5_restart,
 	.reserve	= exynos5_reserve,
diff --git a/arch/arm/mach-exynos/mach-nuri.c b/arch/arm/mach-exynos/mach-nuri.c
index dccd1d1..e4a7ae5 100644
--- a/arch/arm/mach-exynos/mach-nuri.c
+++ b/arch/arm/mach-exynos/mach-nuri.c
@@ -1382,7 +1382,7 @@ MACHINE_START(NURI, "NURI")
 	.handle_irq	= gic_handle_irq,
 	.init_machine	= nuri_machine_init,
 	.init_late	= exynos_init_late,
-	.init_time	= exynos4_timer_init,
+	.init_time	= mct_init,
 	.reserve        = &nuri_reserve,
 	.restart	= exynos4_restart,
 MACHINE_END
diff --git a/arch/arm/mach-exynos/mach-origen.c b/arch/arm/mach-exynos/mach-origen.c
index 4e11563..16a7019 100644
--- a/arch/arm/mach-exynos/mach-origen.c
+++ b/arch/arm/mach-exynos/mach-origen.c
@@ -817,7 +817,7 @@ MACHINE_START(ORIGEN, "ORIGEN")
 	.handle_irq	= gic_handle_irq,
 	.init_machine	= origen_machine_init,
 	.init_late	= exynos_init_late,
-	.init_time	= exynos4_timer_init,
+	.init_time	= mct_init,
 	.reserve	= &origen_reserve,
 	.restart	= exynos4_restart,
 MACHINE_END
diff --git a/arch/arm/mach-exynos/mach-smdk4x12.c b/arch/arm/mach-exynos/mach-smdk4x12.c
index e9c9c29..a66e916e 100644
--- a/arch/arm/mach-exynos/mach-smdk4x12.c
+++ b/arch/arm/mach-exynos/mach-smdk4x12.c
@@ -378,7 +378,7 @@ MACHINE_START(SMDK4212, "SMDK4212")
 	.map_io		= smdk4x12_map_io,
 	.handle_irq	= gic_handle_irq,
 	.init_machine	= smdk4x12_machine_init,
-	.init_time	= exynos4_timer_init,
+	.init_time	= mct_init,
 	.restart	= exynos4_restart,
 	.reserve	= &smdk4x12_reserve,
 MACHINE_END
@@ -393,7 +393,7 @@ MACHINE_START(SMDK4412, "SMDK4412")
 	.handle_irq	= gic_handle_irq,
 	.init_machine	= smdk4x12_machine_init,
 	.init_late	= exynos_init_late,
-	.init_time	= exynos4_timer_init,
+	.init_time	= mct_init,
 	.restart	= exynos4_restart,
 	.reserve	= &smdk4x12_reserve,
 MACHINE_END
diff --git a/arch/arm/mach-exynos/mach-smdkv310.c b/arch/arm/mach-exynos/mach-smdkv310.c
index b228ab9..ecf4723 100644
--- a/arch/arm/mach-exynos/mach-smdkv310.c
+++ b/arch/arm/mach-exynos/mach-smdkv310.c
@@ -425,7 +425,7 @@ MACHINE_START(SMDKV310, "SMDKV310")
 	.map_io		= smdkv310_map_io,
 	.handle_irq	= gic_handle_irq,
 	.init_machine	= smdkv310_machine_init,
-	.init_time	= exynos4_timer_init,
+	.init_time	= mct_init,
 	.reserve	= &smdkv310_reserve,
 	.restart	= exynos4_restart,
 MACHINE_END
@@ -439,7 +439,7 @@ MACHINE_START(SMDKC210, "SMDKC210")
 	.handle_irq	= gic_handle_irq,
 	.init_machine	= smdkv310_machine_init,
 	.init_late	= exynos_init_late,
-	.init_time	= exynos4_timer_init,
+	.init_time	= mct_init,
 	.reserve	= &smdkv310_reserve,
 	.restart	= exynos4_restart,
 MACHINE_END
diff --git a/arch/arm/mach-exynos/mct.c b/arch/arm/mach-exynos/mct.c
index 2942bee..1d3c3f4 100644
--- a/arch/arm/mach-exynos/mct.c
+++ b/arch/arm/mach-exynos/mct.c
@@ -22,6 +22,7 @@
 #include <linux/of.h>
 #include <linux/of_irq.h>
 #include <linux/of_address.h>
+#include <linux/clocksource.h>
 
 #include <asm/arch_timer.h>
 #include <asm/hardware/gic.h>
@@ -518,17 +519,12 @@ static const struct of_device_id exynos_mct_ids[] = {
 	{ .compatible = "samsung,exynos4412-mct", .data = (void *)MCT_INT_PPI },
 };
 
-void __init exynos4_timer_init(void)
+void __init mct_init(void)
 {
 	struct device_node *np = NULL;
 	const struct of_device_id *match;
 	u32 nr_irqs, i;
 
-	if (soc_is_exynos5440()) {
-		arch_timer_of_register();
-		return;
-	}
-
 #ifdef CONFIG_OF
 	np = of_find_matching_node_and_match(NULL, exynos_mct_ids, &match);
 #endif
@@ -561,3 +557,7 @@ void __init exynos4_timer_init(void)
 	exynos4_clocksource_init();
 	exynos4_clockevent_init();
 }
+#ifdef CONFIG_CLKSRC_OF
+CLOCKSOURCE_OF_DECLARE(exynos4210, "samsung,exynos4210-mct", mct_init)
+CLOCKSOURCE_OF_DECLARE(exynos4412, "samsung,exynos4412-mct", mct_init)
+#endif
-- 
1.7.5.4

^ permalink raw reply related

* [PATCH v4 5/7] ARM: dts: add mct device tree node for all supported Exynos SoC's
From: Thomas Abraham @ 2013-01-21 10:02 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1358762542-19008-1-git-send-email-thomas.abraham@linaro.org>

Add MCT device tree node for Exynos4210, Exynos4212, Exynos4412 and Exynos5250.

Cc: Changhwan Youn <chaos.youn@samsung.com>
Signed-off-by: Thomas Abraham <thomas.abraham@linaro.org>
---
 arch/arm/boot/dts/exynos4210.dtsi |    7 +++++++
 arch/arm/boot/dts/exynos4212.dtsi |    9 +++++++++
 arch/arm/boot/dts/exynos4412.dtsi |    7 +++++++
 arch/arm/boot/dts/exynos5250.dtsi |   20 ++++++++++++++++++++
 4 files changed, 43 insertions(+), 0 deletions(-)

diff --git a/arch/arm/boot/dts/exynos4210.dtsi b/arch/arm/boot/dts/exynos4210.dtsi
index 89c7dd0..b1c76fa 100644
--- a/arch/arm/boot/dts/exynos4210.dtsi
+++ b/arch/arm/boot/dts/exynos4210.dtsi
@@ -47,6 +47,13 @@
 			     <0 12 0>, <0 13 0>, <0 14 0>, <0 15 0>;
 	};
 
+	mct at 10050000 {
+		compatible = "samsung,exynos4210-mct";
+		reg = <0x10050000 0x800>;
+		interrupts = <0 57 0>, <0 0 0>, <0 0 0>, <0 0 0>,
+			     <0 42 0>, <0 48 0>;
+	};
+
 	pmu {
 		compatible = "arm,cortex-a9-pmu";
 		interrupt-parent = <&combiner>;
diff --git a/arch/arm/boot/dts/exynos4212.dtsi b/arch/arm/boot/dts/exynos4212.dtsi
index c6ae200..113adcf 100644
--- a/arch/arm/boot/dts/exynos4212.dtsi
+++ b/arch/arm/boot/dts/exynos4212.dtsi
@@ -25,4 +25,13 @@
 	gic:interrupt-controller at 10490000 {
 		cpu-offset = <0x8000>;
 	};
+
+	mct at 10050000 {
+		compatible = "samsung,exynos4412-mct";
+		reg = <0x10050000 0x800>;
+		interrupts = <0 57 0>, <0 0 0>, <0 0 0>, <0 0 0>,
+			     <1 12 0>, <1 12 0>;
+	};
+
+
 };
diff --git a/arch/arm/boot/dts/exynos4412.dtsi b/arch/arm/boot/dts/exynos4412.dtsi
index d7dfe31..78ed377 100644
--- a/arch/arm/boot/dts/exynos4412.dtsi
+++ b/arch/arm/boot/dts/exynos4412.dtsi
@@ -25,4 +25,11 @@
 	gic:interrupt-controller at 10490000 {
 		cpu-offset = <0x4000>;
 	};
+
+	mct at 10050000 {
+		compatible = "samsung,exynos4412-mct";
+		reg = <0x10050000 0x800>;
+		interrupts = <0 57 0>, <0 0 0>, <0 0 0>, <0 0 0>,
+			     <1 12 0>, <1 12 0>, <1 12 0>, <1 12 0>;
+	};
 };
diff --git a/arch/arm/boot/dts/exynos5250.dtsi b/arch/arm/boot/dts/exynos5250.dtsi
index 30485de..7e8fcaf 100644
--- a/arch/arm/boot/dts/exynos5250.dtsi
+++ b/arch/arm/boot/dts/exynos5250.dtsi
@@ -69,6 +69,26 @@
 			     <0 28 0>, <0 29 0>, <0 30 0>, <0 31 0>;
 	};
 
+	mct at 101C0000 {
+		compatible = "samsung,exynos4210-mct";
+		reg = <0x101C0000 0x800>;
+		interrupt-controller;
+		#interrups-cells = <2>;
+		interrupt-parent = <&mct_map>;
+		interrupts = <0 0>, <0 0>, <0 0>, <0 0>,
+			     <4 0>, <5 0>;
+
+		mct_map: mct-map {
+			compatible = "samsung,mct-map";
+			#interrupt-cells = <2>;
+			#address-cells = <0>;
+			#size-cells = <0>;
+			interrupt-map = <0x0 0 &combiner 23 3>,
+					<0x4 0 &gic 0 120 0>,
+					<0x5 0 &gic 0 121 0>;
+		};
+	};
+
 	pmu {
 		compatible = "arm,cortex-a15-pmu";
 		interrupt-parent = <&combiner>;
-- 
1.7.5.4

^ permalink raw reply related

* [PATCH v4 6/7] ARM: Exynos: remove static io-remapping of mct registers for Exynos5
From: Thomas Abraham @ 2013-01-21 10:02 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1358762542-19008-1-git-send-email-thomas.abraham@linaro.org>

With device tree support enabled for MCT controller, the staticio-remapping
of the MCT controller address space is removed for Exynos5 platforms (which
supports only device tree based boot).

Cc: Changhwan Youn <chaos.youn@samsung.com>
Signed-off-by: Thomas Abraham <thomas.abraham@linaro.org>
---
 arch/arm/mach-exynos/common.c           |    5 -----
 arch/arm/mach-exynos/include/mach/map.h |    1 -
 2 files changed, 0 insertions(+), 6 deletions(-)

diff --git a/arch/arm/mach-exynos/common.c b/arch/arm/mach-exynos/common.c
index cdaa55f..ffc72c4 100644
--- a/arch/arm/mach-exynos/common.c
+++ b/arch/arm/mach-exynos/common.c
@@ -283,11 +283,6 @@ static struct map_desc exynos5_iodesc[] __initdata = {
 		.length		= SZ_4K,
 		.type		= MT_DEVICE,
 	}, {
-		.virtual	= (unsigned long)S5P_VA_SYSTIMER,
-		.pfn		= __phys_to_pfn(EXYNOS5_PA_SYSTIMER),
-		.length		= SZ_4K,
-		.type		= MT_DEVICE,
-	}, {
 		.virtual	= (unsigned long)S5P_VA_SYSRAM,
 		.pfn		= __phys_to_pfn(EXYNOS5_PA_SYSRAM),
 		.length		= SZ_4K,
diff --git a/arch/arm/mach-exynos/include/mach/map.h b/arch/arm/mach-exynos/include/mach/map.h
index b8ea67e..99e0a79 100644
--- a/arch/arm/mach-exynos/include/mach/map.h
+++ b/arch/arm/mach-exynos/include/mach/map.h
@@ -68,7 +68,6 @@
 #define EXYNOS5_PA_CMU			0x10010000
 
 #define EXYNOS4_PA_SYSTIMER		0x10050000
-#define EXYNOS5_PA_SYSTIMER		0x101C0000
 
 #define EXYNOS4_PA_WATCHDOG		0x10060000
 #define EXYNOS5_PA_WATCHDOG		0x101D0000
-- 
1.7.5.4

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox