* Re: [PATCH 2/2] ARM: SH-Mobile: sh73a0: Add CPU Hotplug
From: Rob Herring @ 2012-12-14 18:08 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CABYn4syb8yBRwUqbS=2dp1i3FYFt1edYPRh9xa=aHTY9RsWw8A@mail.gmail.com>
On 12/14/2012 09:33 AM, Bastian Hecht wrote:
> Hi,
>
> 2012/12/14 Rob Herring <robherring2@gmail.com>:
>> On 12/06/2012 06:08 AM, Bastian Hecht wrote:
>>> From: Bastian Hecht <hechtb@gmail.com>
>>>
>>> Add the capability to add and remove CPUs on the fly.
>>> The Cortex-A9 offers the possibility to take single cores out of the
>>> MP Core. We add this capabilty taking care that caches are kept
>>> coherent. For the actual shutdown via a WFI instruction, a code snippet
>>> from the omap2 code tree is copied. Thanks for that! For verifying the
>>> shutdown we rely on the internal SH73A0 Power Status Register
>>> PSTR.
>>>
>>> Signed-off-by: Bastian Hecht <hechtb+renesas@gmail.com>
>>> ---
>>> arch/arm/mach-shmobile/headsmp-sh73a0.S | 46 ++++++++++++++++++++++++++
>>> arch/arm/mach-shmobile/include/mach/common.h | 1 +
>>> arch/arm/mach-shmobile/smp-sh73a0.c | 41 +++++++++++++++++++----
>>> 3 files changed, 82 insertions(+), 6 deletions(-)
>>>
>>> diff --git a/arch/arm/mach-shmobile/headsmp-sh73a0.S b/arch/arm/mach-shmobile/headsmp-sh73a0.S
>>> index bec4c0d..be463a3 100644
>>> --- a/arch/arm/mach-shmobile/headsmp-sh73a0.S
>>> +++ b/arch/arm/mach-shmobile/headsmp-sh73a0.S
>>> @@ -23,6 +23,52 @@
>>> #include <linux/init.h>
>>> #include <asm/memory.h>
>>>
>>> +/* Taken from arch/arm/mach-omap2/sleep44xx.S. Thanks! */
>>> +ENTRY(sh73a0_do_wfi)
>>> + stmfd sp!, {lr}
>>
>> Why does the lr need to be pushed to the stack?
>
> Yes I must admit this is paradox - we never return but prepare to do
> so... In the OMAP code they've got a lead out code in case the WFI
> doesn't succeed. I see no reason how this could ever happen here but
> to take a safe route I've decided to keep the mechanism to be able to
> return and spit out an error message back in the C code.
It's not clear to me that OMAP needed this either. The lr value would
have to get lost during wfi.
>>> +
>>> + /*
>>> + * Execute an ISB instruction to ensure that all of the
>>> + * CP15 register changes have been committed.
>>> + */
>>> + isb
>>
>> Generally writes to cp15 registers that need an isb already do so.
>
> Ok nice, I'll check that and throw it out.
>
>>> +
>>> + /*
>>> + * Execute a barrier instruction to ensure that all cache,
>>> + * TLB and branch predictor maintenance operations issued
>>> + * by any CPU in the cluster have completed.
>>> + */
>>> + dsb
>>> + dmb
>>
>> A dsb is a superset of a dmb, so you should not need both.
>
> Same here.
>
>>> +
>>> + /*
>>> + * Execute a WFI instruction and wait until the
>>> + * STANDBYWFI output is asserted to indicate that the
>>> + * CPU is in idle and low power state. CPU can specualatively
>>> + * prefetch the instructions so add NOPs after WFI. Sixteen
>>> + * NOPs as per Cortex-A9 pipeline.
>>
>> Why do you care what is prefetched? You're never coming back here, right?
>
> We can jump back to the paradox top. The idea seems to be to have a
> clean pipeline in case the WFI doesn't succeed.
> The thing about this whole code snippet is: I saw no reason to
> reinvent the wheel and tinker on my own solution when there is code
> that does the job in a clean way. I thought this could maybe be moved
> to a general ARM code base when more people rely on it.
>
Blindly copying code is reinventing the wheel. You are making it appear
that this is needed, but don't seem to have any reason why other than
OMAP did it. If it is in fact needed, then it should be common.
Use cpu_do_idle or figure out and explain why you can't. It's important
to know that if we do go and consolidate this code later.
Rob
^ permalink raw reply
* [PATCH 7/7] ARM: mackerel: add more devices to DT
From: Guennadi Liakhovetski @ 2012-12-14 16:45 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1355503531-7276-1-git-send-email-g.liakhovetski@gmx.de>
This patch adds devices, whose initialisation from DT is already supported,
into the board .dts file.
Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
---
arch/arm/boot/dts/sh7372-mackerel.dts | 96 +++++++++++++++++++++++++++++++++
1 files changed, 96 insertions(+), 0 deletions(-)
diff --git a/arch/arm/boot/dts/sh7372-mackerel.dts b/arch/arm/boot/dts/sh7372-mackerel.dts
index 2ede70d..8bc95c0 100644
--- a/arch/arm/boot/dts/sh7372-mackerel.dts
+++ b/arch/arm/boot/dts/sh7372-mackerel.dts
@@ -19,4 +19,100 @@
device_type = "memory";
reg = <0x40000000 0x10000000>;
};
+
+ reg_1p8v: regulator@0 {
+ compatible = "regulator-fixed";
+ regulator-name = "1P8V";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ reg_3p3v: regulator@1 {
+ compatible = "regulator-fixed";
+ regulator-name = "3P3V";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ lan9220@14000000 {
+ compatible = "smsc,lan9220", "smsc,lan9115";
+ reg = <0x14000000 0x2000000>;
+ phy-mode = "mii";
+ interrupt-parent = <&intca_irq_pins_lo>;
+ interrupts = <0x2c0>;
+ reg-io-width = <4>;
+ smsc,irq-push-pull;
+ smsc,save-mac-address;
+ vddvario-supply = <®_1p8v>;
+ vdd33a-supply = <®_3p3v>;
+ };
+
+ i2c0: i2c@fff20000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "renesas,rmobile-iic";
+ reg = <0xfff20000 0x1000>;
+ interrupt-parent = <&intcs>;
+ interrupts = <0x4200 0x4220 0x4240 0x4260>;
+
+ clock-frequency = <100000>;
+
+ touchscreen@55 {
+ compatible = "sitronix,st1232-ts";
+ reg = <0x55>;
+ interrupt-parent = <&intca_irq_pins_lo>;
+ interrupts = <0x02e0>;
+ };
+
+ codec@13 {
+ compatible = "asahi-kasei,ak4642-codec";
+ reg = <0x13>;
+ };
+ };
+
+ i2c1: i2c@e6c20000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "renesas,rmobile-iic";
+ reg = <0xe6c20000 0x1000>;
+ interrupt-parent = <&intca>;
+ interrupts = <0x780 0x7a0 0x7c0 0x7e0>;
+
+ clock-frequency = <100000>;
+
+ accelerometer@53 {
+ compatible = "analog-devices,adxl34x";
+ reg = <0x53>;
+ interrupt-parent = <&intca_irq_pins_hi>;
+ interrupts = <0x32a0>;
+ };
+ };
+
+ mmcif0: mmcif@0xe6bd0000 {
+ compatible = "renesas,sh-mmcif", "renesas,sh7372-mmcif";
+ reg = <0xe6bd0000 0x100>;
+ interrupt-parent = <&intca>;
+ interrupts = <0x1ac0 0x1ae0>;
+ vmmc-supply = <®_1p8v>;
+ };
+
+ sdhi0: sdhi@0xe6850000 {
+ compatible = "renesas,shmobile-sdhi";
+ reg = <0xe6850000 0x100>;
+ interrupt-parent = <&intca>;
+ interrupts = <0x0e00 0x0e20 0x0e40>;
+ vmmc-supply = <®_3p3v>;
+ };
+
+ sdhi2: sdhi@0xe6870000 {
+ compatible = "renesas,shmobile-sdhi";
+ reg = <0xe6870000 0x100>;
+ interrupt-parent = <&intca>;
+ interrupts = <0x1200 0x1220 0x1240>;
+ vmmc-supply = <®_3p3v>;
+ };
};
--
1.7.2.5
^ permalink raw reply related
* [PATCH 6/7] ARM: mackerel: support booting with or without DT
From: Guennadi Liakhovetski @ 2012-12-14 16:45 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1355503531-7276-1-git-send-email-g.liakhovetski@gmx.de>
This patch adds dynamic switching to booting either with or without DT.
So far only a part of the board initialisation can be done via DT. Devices,
that still need platform data are kept that way. Devices, that can be
initialised from DT will not be supplied from the platform data, if a DT
image is detected.
Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
---
arch/arm/mach-shmobile/board-mackerel.c | 84 ++++++++++++++++++++++++-------
1 files changed, 66 insertions(+), 18 deletions(-)
diff --git a/arch/arm/mach-shmobile/board-mackerel.c b/arch/arm/mach-shmobile/board-mackerel.c
index 39b8f2e..a6358c9 100644
--- a/arch/arm/mach-shmobile/board-mackerel.c
+++ b/arch/arm/mach-shmobile/board-mackerel.c
@@ -1326,7 +1326,6 @@ static struct platform_device mackerel_camera = {
static struct platform_device *mackerel_devices[] __initdata = {
&nor_flash_device,
- &smc911x_device,
&lcdc_device,
&usbhs0_device,
&usbhs1_device,
@@ -1335,17 +1334,21 @@ static struct platform_device *mackerel_devices[] __initdata = {
&fsi_ak4643_device,
&fsi_hdmi_device,
&nand_flash_device,
+ &ceu_device,
+ &mackerel_camera,
+ &hdmi_device,
+ &hdmi_lcdc_device,
+ &meram_device,
+};
+
+static struct platform_device *mackerel_devices_dt[] __initdata = {
+ &smc911x_device,
&sdhi0_device,
#if !defined(CONFIG_MMC_SH_MMCIF) && !defined(CONFIG_MMC_SH_MMCIF_MODULE)
&sdhi1_device,
#endif
&sdhi2_device,
&sh_mmcif_device,
- &ceu_device,
- &mackerel_camera,
- &hdmi_device,
- &hdmi_lcdc_device,
- &meram_device,
};
/* Keypad Initialization */
@@ -1404,6 +1407,24 @@ static struct i2c_board_info i2c1_devices[] = {
},
};
+static int mackerel_i2c_bus_notify(struct notifier_block *nb,
+ unsigned long action, void *data)
+{
+ struct device *dev = data;
+
+ if (action != BUS_NOTIFY_ADD_DEVICE ||
+ strcmp(dev_name(dev->parent), "fff20000.i2c"))
+ return NOTIFY_DONE;
+
+ i2c_new_device(to_i2c_adapter(dev), &i2c0_devices[1]);
+
+ return NOTIFY_OK;
+}
+
+static struct notifier_block mackerel_i2c_notifier = {
+ .notifier_call = mackerel_i2c_bus_notify,
+};
+
#define GPIO_PORT9CR IOMEM(0xE6051009)
#define GPIO_PORT10CR IOMEM(0xE605100A)
#define GPIO_PORT167CR IOMEM(0xE60520A7)
@@ -1420,22 +1441,26 @@ static void __init mackerel_init(void)
{ "A3SP", &usbhs0_device, },
{ "A3SP", &usbhs1_device, },
{ "A3SP", &nand_flash_device, },
+ { "A4R", &ceu_device, },
+ };
+ struct pm_domain_device domain_devices_dt[] = {
{ "A3SP", &sh_mmcif_device, },
{ "A3SP", &sdhi0_device, },
#if !defined(CONFIG_MMC_SH_MMCIF) && !defined(CONFIG_MMC_SH_MMCIF_MODULE)
{ "A3SP", &sdhi1_device, },
#endif
{ "A3SP", &sdhi2_device, },
- { "A4R", &ceu_device, },
};
u32 srcr4;
struct clk *clk;
- regulator_register_always_on(0, "fixed-1.8V", fixed1v8_power_consumers,
- ARRAY_SIZE(fixed1v8_power_consumers), 1800000);
- regulator_register_always_on(1, "fixed-3.3V", fixed3v3_power_consumers,
- ARRAY_SIZE(fixed3v3_power_consumers), 3300000);
- regulator_register_fixed(2, dummy_supplies, ARRAY_SIZE(dummy_supplies));
+ if (!of_have_populated_dt()) {
+ regulator_register_always_on(0, "fixed-1.8V", fixed1v8_power_consumers,
+ ARRAY_SIZE(fixed1v8_power_consumers), 1800000);
+ regulator_register_always_on(1, "fixed-3.3V", fixed3v3_power_consumers,
+ ARRAY_SIZE(fixed3v3_power_consumers), 3300000);
+ regulator_register_fixed(2, dummy_supplies, ARRAY_SIZE(dummy_supplies));
+ }
/* External clock source */
clk_set_rate(&sh7372_dv_clki_clk, 27000000);
@@ -1633,22 +1658,35 @@ static void __init mackerel_init(void)
udelay(50);
__raw_writel(srcr4 & ~(1 << 13), SRCR4);
- i2c_register_board_info(0, i2c0_devices,
- ARRAY_SIZE(i2c0_devices));
- i2c_register_board_info(1, i2c1_devices,
- ARRAY_SIZE(i2c1_devices));
+ if (!of_have_populated_dt()) {
+ i2c_register_board_info(0, i2c0_devices,
+ ARRAY_SIZE(i2c0_devices));
+ i2c_register_board_info(1, i2c1_devices,
+ ARRAY_SIZE(i2c1_devices));
+ } else {
+ bus_register_notifier(&i2c_bus_type,
+ &mackerel_i2c_notifier);
+ }
sh7372_add_standard_devices();
platform_add_devices(mackerel_devices, ARRAY_SIZE(mackerel_devices));
+ if (!of_have_populated_dt())
+ platform_add_devices(mackerel_devices_dt,
+ ARRAY_SIZE(mackerel_devices_dt));
rmobile_add_devices_to_domains(domain_devices,
ARRAY_SIZE(domain_devices));
+ if (!of_have_populated_dt())
+ rmobile_add_devices_to_domains(domain_devices_dt,
+ ARRAY_SIZE(domain_devices_dt));
hdmi_init_pm_clock();
sh7372_pm_init();
pm_clk_add(&fsi_device.dev, "spu2");
pm_clk_add(&hdmi_lcdc_device.dev, "hdmi");
+
+ of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
}
static const char *mackerel_boards_compat_dt[] __initdata = {
@@ -1659,10 +1697,20 @@ static const char *mackerel_boards_compat_dt[] __initdata = {
DT_MACHINE_START(MACKEREL_DT, "mackerel")
.map_io = sh7372_map_io,
.init_early = sh7372_add_early_devices,
- .init_irq = sh7372_init_irq,
+ .init_irq = sh7372_init_irq_of,
+ .handle_irq = shmobile_handle_irq_intc,
+ .init_machine = mackerel_init,
+ .init_late = sh7372_pm_init_late,
+ .timer = &shmobile_timer,
+ .dt_compat = mackerel_boards_compat_dt,
+MACHINE_END
+
+MACHINE_START(MACKEREL, "mackerel")
+ .map_io = sh7372_map_io,
+ .init_early = sh7372_add_early_devices,
+ .init_irq = sh7372_init_irq_of,
.handle_irq = shmobile_handle_irq_intc,
.init_machine = mackerel_init,
.init_late = sh7372_pm_init_late,
.timer = &shmobile_timer,
- .dt_compat = mackerel_boards_compat_dt,
MACHINE_END
--
1.7.2.5
^ permalink raw reply related
* [PATCH 5/7] ARM: sh7372: allow boards supporting booting with or without DT
From: Guennadi Liakhovetski @ 2012-12-14 16:45 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1355503531-7276-1-git-send-email-g.liakhovetski@gmx.de>
For boards booting without DT no changes should be caused by this patch.
When booting with DT, devices, whose drivers support DT probing, will not
be registered.
Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
---
arch/arm/mach-shmobile/setup-sh7372.c | 17 ++++++++++++++---
1 files changed, 14 insertions(+), 3 deletions(-)
diff --git a/arch/arm/mach-shmobile/setup-sh7372.c b/arch/arm/mach-shmobile/setup-sh7372.c
index bbe6e2a..3e6bf3d 100644
--- a/arch/arm/mach-shmobile/setup-sh7372.c
+++ b/arch/arm/mach-shmobile/setup-sh7372.c
@@ -981,9 +981,12 @@ static struct platform_device *sh7372_early_devices[] __initdata = {
&tmu01_device,
};
-static struct platform_device *sh7372_late_devices[] __initdata = {
+static struct platform_device *sh7372_late_devices_dt[] __initdata = {
&iic0_device,
&iic1_device,
+};
+
+static struct platform_device *sh7372_late_devices[] __initdata = {
&dma0_device,
&dma1_device,
&dma2_device,
@@ -1012,13 +1015,11 @@ void __init sh7372_add_standard_devices(void)
{ "A3SP", &scif4_device, },
{ "A3SP", &scif5_device, },
{ "A3SP", &scif6_device, },
- { "A3SP", &iic1_device, },
{ "A3SP", &dma0_device, },
{ "A3SP", &dma1_device, },
{ "A3SP", &dma2_device, },
{ "A3SP", &usb_dma0_device, },
{ "A3SP", &usb_dma1_device, },
- { "A4R", &iic0_device, },
{ "A4R", &veu0_device, },
{ "A4R", &veu1_device, },
{ "A4R", &veu2_device, },
@@ -1027,6 +1028,10 @@ void __init sh7372_add_standard_devices(void)
{ "A4R", &tmu00_device, },
{ "A4R", &tmu01_device, },
};
+ struct pm_domain_device domain_devices_dt[] = {
+ { "A3SP", &iic1_device, },
+ { "A4R", &iic0_device, },
+ };
sh7372_init_pm_domains();
@@ -1035,9 +1040,15 @@ void __init sh7372_add_standard_devices(void)
platform_add_devices(sh7372_late_devices,
ARRAY_SIZE(sh7372_late_devices));
+ if (!of_have_populated_dt())
+ platform_add_devices(sh7372_late_devices_dt,
+ ARRAY_SIZE(sh7372_late_devices_dt));
rmobile_add_devices_to_domains(domain_devices,
ARRAY_SIZE(domain_devices));
+ if (!of_have_populated_dt())
+ rmobile_add_devices_to_domains(domain_devices_dt,
+ ARRAY_SIZE(domain_devices_dt));
}
static void __init sh7372_earlytimer_init(void)
--
1.7.2.5
^ permalink raw reply related
* [PATCH 4/7] ARM: sh7372: add clock lookup entries for DT-based devices
From: Guennadi Liakhovetski @ 2012-12-14 16:45 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1355503531-7276-1-git-send-email-g.liakhovetski@gmx.de>
When booting with DT, devices are named differently. To get their clocks
additional entries have to be added to the lookup table.
Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
---
arch/arm/mach-shmobile/clock-sh7372.c | 9 +++++++++
1 files changed, 9 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-shmobile/clock-sh7372.c b/arch/arm/mach-shmobile/clock-sh7372.c
index 430a90f..2471f77 100644
--- a/arch/arm/mach-shmobile/clock-sh7372.c
+++ b/arch/arm/mach-shmobile/clock-sh7372.c
@@ -618,6 +618,7 @@ static struct clk_lookup lookups[] = {
/* MSTP32 clocks */
CLKDEV_DEV_ID("i2c-sh_mobile.2", &mstp_clks[MSTP001]), /* IIC2 */
+ CLKDEV_DEV_ID("fff30000.i2c", &mstp_clks[MSTP001]), /* IIC2 */
CLKDEV_DEV_ID("spi_sh_msiof.0", &mstp_clks[MSTP000]), /* MSIOF0 */
CLKDEV_DEV_ID("uio_pdrv_genirq.4", &mstp_clks[MSTP131]), /* VEU3 */
CLKDEV_DEV_ID("uio_pdrv_genirq.3", &mstp_clks[MSTP130]), /* VEU2 */
@@ -630,6 +631,7 @@ static struct clk_lookup lookups[] = {
CLKDEV_DEV_ID("sh-mipi-dsi.0", &mstp_clks[MSTP118]), /* DSITX0 */
CLKDEV_DEV_ID("sh_mobile_lcdc_fb.1", &mstp_clks[MSTP117]), /* LCDC1 */
CLKDEV_DEV_ID("i2c-sh_mobile.0", &mstp_clks[MSTP116]), /* IIC0 */
+ CLKDEV_DEV_ID("fff20000.i2c", &mstp_clks[MSTP116]), /* IIC0 */
CLKDEV_DEV_ID("sh_mobile_meram.0", &mstp_clks[MSTP113]), /* MERAM */
CLKDEV_DEV_ID("uio_pdrv_genirq.5", &mstp_clks[MSTP106]), /* JPU */
CLKDEV_DEV_ID("uio_pdrv_genirq.0", &mstp_clks[MSTP101]), /* VPU */
@@ -651,18 +653,25 @@ static struct clk_lookup lookups[] = {
CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[MSTP200]), /* SCIFA4 */
CLKDEV_DEV_ID("sh_fsi2", &mstp_clks[MSTP328]), /* FSI2 */
CLKDEV_DEV_ID("i2c-sh_mobile.1", &mstp_clks[MSTP323]), /* IIC1 */
+ CLKDEV_DEV_ID("e6c20000.i2c", &mstp_clks[MSTP323]), /* IIC1 */
CLKDEV_DEV_ID("r8a66597_hcd.0", &mstp_clks[MSTP322]), /* USB0 */
CLKDEV_DEV_ID("r8a66597_udc.0", &mstp_clks[MSTP322]), /* USB0 */
CLKDEV_DEV_ID("renesas_usbhs.0", &mstp_clks[MSTP322]), /* USB0 */
CLKDEV_DEV_ID("sh_flctl.0", &mstp_clks[MSTP315]), /* FLCTL */
CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[MSTP314]), /* SDHI0 */
+ CLKDEV_DEV_ID("e6850000.sdhi", &mstp_clks[MSTP314]), /* SDHI0 */
CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[MSTP313]), /* SDHI1 */
+ CLKDEV_DEV_ID("e6860000.sdhi", &mstp_clks[MSTP313]), /* SDHI1 */
CLKDEV_DEV_ID("sh_mmcif.0", &mstp_clks[MSTP312]), /* MMC */
+ CLKDEV_DEV_ID("e6bd0000.mmcif", &mstp_clks[MSTP312]), /* MMC */
CLKDEV_DEV_ID("sh-mipi-dsi.1", &mstp_clks[MSTP423]), /* DSITX1 */
CLKDEV_DEV_ID("sh_mobile_sdhi.2", &mstp_clks[MSTP415]), /* SDHI2 */
+ CLKDEV_DEV_ID("e6870000.sdhi", &mstp_clks[MSTP415]), /* SDHI2 */
CLKDEV_DEV_ID("sh-mobile-hdmi", &mstp_clks[MSTP413]), /* HDMI */
CLKDEV_DEV_ID("i2c-sh_mobile.3", &mstp_clks[MSTP411]), /* IIC3 */
+ CLKDEV_DEV_ID("e6d20000.i2c", &mstp_clks[MSTP411]), /* IIC3 */
CLKDEV_DEV_ID("i2c-sh_mobile.4", &mstp_clks[MSTP410]), /* IIC4 */
+ CLKDEV_DEV_ID("e6d30000.i2c", &mstp_clks[MSTP410]), /* IIC4 */
CLKDEV_DEV_ID("sh-dma-engine.4", &mstp_clks[MSTP407]), /* USB-DMAC1 */
CLKDEV_DEV_ID("r8a66597_hcd.1", &mstp_clks[MSTP406]), /* USB1 */
CLKDEV_DEV_ID("r8a66597_udc.1", &mstp_clks[MSTP406]), /* USB1 */
--
1.7.2.5
^ permalink raw reply related
* [PATCH 3/7] ARM: sh7372: support mixed DT and board code interrupt controller init
From: Guennadi Liakhovetski @ 2012-12-14 16:45 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1355503531-7276-1-git-send-email-g.liakhovetski@gmx.de>
Extend DT interrupt controller initialisation to automatically fall back to
platform data based configuration, if booting without DT. This simplifies
implementing boards, capable of booting in either mode with a single kernel.
Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
---
arch/arm/mach-shmobile/intc-sh7372.c | 6 ++++++
1 files changed, 6 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-shmobile/intc-sh7372.c b/arch/arm/mach-shmobile/intc-sh7372.c
index c923518..9c13ecc 100644
--- a/arch/arm/mach-shmobile/intc-sh7372.c
+++ b/arch/arm/mach-shmobile/intc-sh7372.c
@@ -23,6 +23,7 @@
#include <linux/irq.h>
#include <linux/io.h>
#include <linux/sh_intc.h>
+#include <mach/common.h>
#include <mach/intc.h>
#include <mach/irqs.h>
#include <asm/mach-types.h>
@@ -629,6 +630,11 @@ static const struct of_device_id irq_of_match[] __initconst = {
void __init sh7372_init_irq_of(void)
{
+ if (!of_have_populated_dt()) {
+ sh7372_init_irq();
+ return;
+ }
+
of_irq_init(irq_of_match);
sh7372_init_intc(0xe6940000, 0xe6950000, 0xffd20000, 0xffd50000,
--
1.7.2.5
^ permalink raw reply related
* [PATCH 2/7] ARM: mackerel: include the correct .dtsi file
From: Guennadi Liakhovetski @ 2012-12-14 16:45 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1355503531-7276-1-git-send-email-g.liakhovetski@gmx.de>
Mackerel's .dts Device Tree description file should derive from the SoC's
.dtsi, not from skeleton.dtsi directly.
Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
---
arch/arm/boot/dts/sh7372-mackerel.dts | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/arch/arm/boot/dts/sh7372-mackerel.dts b/arch/arm/boot/dts/sh7372-mackerel.dts
index 286f0ca..2ede70d 100644
--- a/arch/arm/boot/dts/sh7372-mackerel.dts
+++ b/arch/arm/boot/dts/sh7372-mackerel.dts
@@ -9,7 +9,7 @@
*/
/dts-v1/;
-/include/ "skeleton.dtsi"
+/include/ "sh7372.dtsi"
/ {
model = "Mackerel (AP4 EVM 2nd)";
--
1.7.2.5
^ permalink raw reply related
* [PATCH 1/7] ARM: sh7372: add missing "#interrupt-cells" properties
From: Guennadi Liakhovetski @ 2012-12-14 16:45 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1355503531-7276-1-git-send-email-g.liakhovetski@gmx.de>
Two of four interrupt controllers in sh7372.dtsi are missing the compulsory
"#interrupt-cells" properties. Fix this.
Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
---
arch/arm/boot/dts/sh7372.dtsi | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/arch/arm/boot/dts/sh7372.dtsi b/arch/arm/boot/dts/sh7372.dtsi
index da03ee6..00f1645 100644
--- a/arch/arm/boot/dts/sh7372.dtsi
+++ b/arch/arm/boot/dts/sh7372.dtsi
@@ -943,6 +943,7 @@
interrupt-controller;
#address-cells = <1>;
#size-cells = <1>;
+ #interrupt-cells = <1>;
ranges;
reg = <0xe6900000 0x70>;
@@ -1052,6 +1053,7 @@
interrupt-controller;
#address-cells = <1>;
#size-cells = <1>;
+ #interrupt-cells = <1>;
ranges;
reg = <0xe6900008 0x70>;
--
1.7.2.5
^ permalink raw reply related
* [PATCH 0/7] ARM: mackerel: extended DT support
From: Guennadi Liakhovetski @ 2012-12-14 16:45 UTC (permalink / raw)
To: linux-arm-kernel
The purpose of this patch set is to continue mackerel migration to DT
booting, while preserving the ability to boot without a DT image. Further
devices will be migrated from platform data to DT as their drivers become
ready for such migration.
Guennadi Liakhovetski (7):
ARM: sh7372: add missing "#interrupt-cells" properties
ARM: mackerel: include the correct .dtsi file
ARM: sh7372: support mixed DT and board code interrupt controller
init
ARM: sh7372: add clock lookup entries for DT-based devices
ARM: sh7372: allow boards supporting booting with or without DT
ARM: mackerel: support booting with or without DT
ARM: mackerel: add more devices to DT
arch/arm/boot/dts/sh7372-mackerel.dts | 98 ++++++++++++++++++++++++++++++-
arch/arm/boot/dts/sh7372.dtsi | 2 +
arch/arm/mach-shmobile/board-mackerel.c | 84 +++++++++++++++++++++------
arch/arm/mach-shmobile/clock-sh7372.c | 9 +++
arch/arm/mach-shmobile/intc-sh7372.c | 6 ++
arch/arm/mach-shmobile/setup-sh7372.c | 17 +++++-
6 files changed, 194 insertions(+), 22 deletions(-)
--
1.7.2.5
Thanks
Guennadi
---
Guennadi Liakhovetski, Ph.D.
Freelance Open-Source Software Developer
http://www.open-technology.de/
^ permalink raw reply
* Re: [PATCH v2 00/77] SH pin control and GPIO rework with OF support
From: Linus Walleij @ 2012-12-14 15:48 UTC (permalink / raw)
To: linux-sh
In-Reply-To: <1353974596-30033-1-git-send-email-laurent.pinchart+renesas@ideasonboard.com>
On Wed, Dec 12, 2012 at 2:43 AM, Laurent Pinchart
<laurent.pinchart@ideasonboard.com> wrote:
> I will send a v3 with fixes based on your comments. I might omit the DT
> patches this time and send a pull request, as the patch set is getting too big
> for my taste. Even though the result won't be perfect (yet :-)), it's still an
> improvement, and I'll send additional patches on top of that.
Sure the SH pinctrl business is already looking severa magnitudes better
after this so I will certainly pull it in.
I think I'll create a pinctrl-sh branch based off -rc1 after the merge window,
and we'll work on the sh stuff there for a while.
Yours,
Linus Walleij
^ permalink raw reply
* Re: [PATCH 2/2] ARM: SH-Mobile: sh73a0: Add CPU Hotplug
From: Bastian Hecht @ 2012-12-14 15:33 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <50CB34F4.8060204@gmail.com>
Hi,
2012/12/14 Rob Herring <robherring2@gmail.com>:
> On 12/06/2012 06:08 AM, Bastian Hecht wrote:
>> From: Bastian Hecht <hechtb@gmail.com>
>>
>> Add the capability to add and remove CPUs on the fly.
>> The Cortex-A9 offers the possibility to take single cores out of the
>> MP Core. We add this capabilty taking care that caches are kept
>> coherent. For the actual shutdown via a WFI instruction, a code snippet
>> from the omap2 code tree is copied. Thanks for that! For verifying the
>> shutdown we rely on the internal SH73A0 Power Status Register
>> PSTR.
>>
>> Signed-off-by: Bastian Hecht <hechtb+renesas@gmail.com>
>> ---
>> arch/arm/mach-shmobile/headsmp-sh73a0.S | 46 ++++++++++++++++++++++++++
>> arch/arm/mach-shmobile/include/mach/common.h | 1 +
>> arch/arm/mach-shmobile/smp-sh73a0.c | 41 +++++++++++++++++++----
>> 3 files changed, 82 insertions(+), 6 deletions(-)
>>
>> diff --git a/arch/arm/mach-shmobile/headsmp-sh73a0.S b/arch/arm/mach-shmobile/headsmp-sh73a0.S
>> index bec4c0d..be463a3 100644
>> --- a/arch/arm/mach-shmobile/headsmp-sh73a0.S
>> +++ b/arch/arm/mach-shmobile/headsmp-sh73a0.S
>> @@ -23,6 +23,52 @@
>> #include <linux/init.h>
>> #include <asm/memory.h>
>>
>> +/* Taken from arch/arm/mach-omap2/sleep44xx.S. Thanks! */
>> +ENTRY(sh73a0_do_wfi)
>> + stmfd sp!, {lr}
>
> Why does the lr need to be pushed to the stack?
Yes I must admit this is paradox - we never return but prepare to do
so... In the OMAP code they've got a lead out code in case the WFI
doesn't succeed. I see no reason how this could ever happen here but
to take a safe route I've decided to keep the mechanism to be able to
return and spit out an error message back in the C code.
>> +
>> + /*
>> + * Execute an ISB instruction to ensure that all of the
>> + * CP15 register changes have been committed.
>> + */
>> + isb
>
> Generally writes to cp15 registers that need an isb already do so.
Ok nice, I'll check that and throw it out.
>> +
>> + /*
>> + * Execute a barrier instruction to ensure that all cache,
>> + * TLB and branch predictor maintenance operations issued
>> + * by any CPU in the cluster have completed.
>> + */
>> + dsb
>> + dmb
>
> A dsb is a superset of a dmb, so you should not need both.
Same here.
>> +
>> + /*
>> + * Execute a WFI instruction and wait until the
>> + * STANDBYWFI output is asserted to indicate that the
>> + * CPU is in idle and low power state. CPU can specualatively
>> + * prefetch the instructions so add NOPs after WFI. Sixteen
>> + * NOPs as per Cortex-A9 pipeline.
>
> Why do you care what is prefetched? You're never coming back here, right?
We can jump back to the paradox top. The idea seems to be to have a
clean pipeline in case the WFI doesn't succeed.
The thing about this whole code snippet is: I saw no reason to
reinvent the wheel and tinker on my own solution when there is code
that does the job in a clean way. I thought this could maybe be moved
to a general ARM code base when more people rely on it.
cheers,
Bastian
> Rob
>
>> + */
>> + wfi @ Wait For Interrupt
>> + nop
>> + nop
>> + nop
>> + nop
>> + nop
>> + nop
>> + nop
>> + nop
>> + nop
>> + nop
>> + nop
>> + nop
>> + nop
>> + nop
>> + nop
>> + nop
>> +
>> + ldmfd sp!, {pc}
>> +ENDPROC(sh73a0_do_wfi)
>> +
>> __CPUINIT
>> /*
>> * Reset vector for secondary CPUs.
>> diff --git a/arch/arm/mach-shmobile/include/mach/common.h b/arch/arm/mach-shmobile/include/mach/common.h
>> index f2e2c29..40f767e 100644
>> --- a/arch/arm/mach-shmobile/include/mach/common.h
>> +++ b/arch/arm/mach-shmobile/include/mach/common.h
>> @@ -55,6 +55,7 @@ extern void sh73a0_add_standard_devices(void);
>> extern void sh73a0_clock_init(void);
>> extern void sh73a0_pinmux_init(void);
>> extern void sh73a0_secondary_vector(void);
>> +extern void sh73a0_do_wfi(void);
>> extern struct clk sh73a0_extal1_clk;
>> extern struct clk sh73a0_extal2_clk;
>> extern struct clk sh73a0_extcki_clk;
>> diff --git a/arch/arm/mach-shmobile/smp-sh73a0.c b/arch/arm/mach-shmobile/smp-sh73a0.c
>> index 5e36f5d..9237e13 100644
>> --- a/arch/arm/mach-shmobile/smp-sh73a0.c
>> +++ b/arch/arm/mach-shmobile/smp-sh73a0.c
>> @@ -24,6 +24,7 @@
>> #include <linux/io.h>
>> #include <linux/delay.h>
>> #include <mach/common.h>
>> +#include <asm/cacheflush.h>
>> #include <asm/smp_plat.h>
>> #include <mach/sh73a0.h>
>> #include <asm/smp_scu.h>
>> @@ -36,6 +37,8 @@
>> #define SBAR IOMEM(0xe6180020)
>> #define APARMBAREA IOMEM(0xe6f10020)
>>
>> +#define PSTR_SHUTDOWN_MODE 3
>> +
>> static void __iomem *scu_base_addr(void)
>> {
>> return (void __iomem *)0xf0000000;
>> @@ -92,16 +95,20 @@ static void __init sh73a0_smp_init_cpus(void)
>> shmobile_smp_init_cpus(ncores);
>> }
>>
>> -static int __maybe_unused sh73a0_cpu_kill(unsigned int cpu)
>> +#ifdef CONFIG_HOTPLUG_CPU
>> +static int sh73a0_cpu_kill(unsigned int cpu)
>> {
>> +
>> int k;
>> + u32 pstr;
>>
>> - /* this function is running on another CPU than the offline target,
>> - * here we need wait for shutdown code in platform_cpu_die() to
>> - * finish before asking SoC-specific code to power off the CPU core.
>> + /*
>> + * wait until the power status register confirms the shutdown of the
>> + * offline target
>> */
>> for (k = 0; k < 1000; k++) {
>> - if (shmobile_cpu_is_dead(cpu))
>> + pstr = (__raw_readl(PSTR) >> (4 * cpu)) & 3;
>> + if (pstr = PSTR_SHUTDOWN_MODE)
>> return 1;
>>
>> mdelay(1);
>> @@ -110,6 +117,28 @@ static int __maybe_unused sh73a0_cpu_kill(unsigned int cpu)
>> return 0;
>> }
>>
>> +static void sh73a0_cpu_die(unsigned int cpu)
>> +{
>> + /*
>> + * The ARM MPcore does not issue a cache coherency request for the L1
>> + * cache when powering off single CPUs. We must take care of this and
>> + * further caches.
>> + */
>> + dsb();
>> + flush_cache_all();
>> +
>> + /* Set power off mode. This takes the CPU out of the MP cluster */
>> + scu_power_mode(scu_base_addr(), SCU_PM_POWEROFF);
>> +
>> + /* Enter shutdown mode */
>> + sh73a0_do_wfi();
>> +
>> + /* We assume success always. We never reach this */
>> + pr_err("Shutting down CPU failed. This should never happen!\n");
>> + for (;;)
>> + ;
>> +}
>> +#endif /* CONFIG_HOTPLUG_CPU */
>>
>> struct smp_operations sh73a0_smp_ops __initdata = {
>> .smp_init_cpus = sh73a0_smp_init_cpus,
>> @@ -118,7 +147,7 @@ struct smp_operations sh73a0_smp_ops __initdata = {
>> .smp_boot_secondary = sh73a0_boot_secondary,
>> #ifdef CONFIG_HOTPLUG_CPU
>> .cpu_kill = sh73a0_cpu_kill,
>> - .cpu_die = shmobile_cpu_die,
>> + .cpu_die = sh73a0_cpu_die,
>> .cpu_disable = shmobile_cpu_disable,
>> #endif
>> };
>>
>
^ permalink raw reply
* Re: [PATCH 1/2] ARM: SH-Mobile: sh73a0: Secondary CPUs handle own SCU flags
From: Bastian Hecht @ 2012-12-14 15:07 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <50CB324F.4090405@gmail.com>
Hi Rob,
thanks for commenting on this.
>>
>> -static void modify_scu_cpu_psr(unsigned long set, unsigned long clr)
>> -{
>> - void __iomem *scu_base = scu_base_addr();
>> -
>> - spin_lock(&scu_lock);
>> - tmp = __raw_readl(scu_base + 8);
>> - tmp &= ~clr;
>> - tmp |= set;
>> - spin_unlock(&scu_lock);
>> -
>> - /* disable cache coherency after releasing the lock */
>> - __raw_writel(tmp, scu_base + 8);
>
> None of this locking was needed as the power status register is byte
> accessible.
Even if we switch to byte access here we would need protection, as the
SCU power register gets touched from different CPUs.
>> -}
>> -
>> static unsigned int __init sh73a0_get_core_count(void)
>> {
>> void __iomem *scu_base = scu_base_addr();
>> @@ -82,9 +65,6 @@ static int __cpuinit sh73a0_boot_secondary(unsigned int cpu, struct task_struct
>> {
>> cpu = cpu_logical_map(cpu);
>>
>> - /* enable cache coherency */
>> - modify_scu_cpu_psr(0, 3 << (cpu * 8));
>> -
>
> So simply changing this to scu_power_mode call would accomplish the same
> thing and avoid all the assembly.
Yes that was exactly my fail try before. See
http://www.spinics.net/lists/linux-sh/msg13685.html
It broke the bringing up of secondary CPUs completely as
sh73a0_boot_secondary() is running on CPU0 when booting CPU1. So
scu_power_mode() changed the registers of the wrong CPU.
cheers,
Bastian
^ permalink raw reply
* Re: [PATCH 2/2] ARM: SH-Mobile: sh73a0: Add CPU Hotplug
From: Rob Herring @ 2012-12-14 14:17 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1354795719-5578-2-git-send-email-hechtb+renesas@gmail.com>
On 12/06/2012 06:08 AM, Bastian Hecht wrote:
> From: Bastian Hecht <hechtb@gmail.com>
>
> Add the capability to add and remove CPUs on the fly.
> The Cortex-A9 offers the possibility to take single cores out of the
> MP Core. We add this capabilty taking care that caches are kept
> coherent. For the actual shutdown via a WFI instruction, a code snippet
> from the omap2 code tree is copied. Thanks for that! For verifying the
> shutdown we rely on the internal SH73A0 Power Status Register
> PSTR.
>
> Signed-off-by: Bastian Hecht <hechtb+renesas@gmail.com>
> ---
> arch/arm/mach-shmobile/headsmp-sh73a0.S | 46 ++++++++++++++++++++++++++
> arch/arm/mach-shmobile/include/mach/common.h | 1 +
> arch/arm/mach-shmobile/smp-sh73a0.c | 41 +++++++++++++++++++----
> 3 files changed, 82 insertions(+), 6 deletions(-)
>
> diff --git a/arch/arm/mach-shmobile/headsmp-sh73a0.S b/arch/arm/mach-shmobile/headsmp-sh73a0.S
> index bec4c0d..be463a3 100644
> --- a/arch/arm/mach-shmobile/headsmp-sh73a0.S
> +++ b/arch/arm/mach-shmobile/headsmp-sh73a0.S
> @@ -23,6 +23,52 @@
> #include <linux/init.h>
> #include <asm/memory.h>
>
> +/* Taken from arch/arm/mach-omap2/sleep44xx.S. Thanks! */
> +ENTRY(sh73a0_do_wfi)
> + stmfd sp!, {lr}
Why does the lr need to be pushed to the stack?
> +
> + /*
> + * Execute an ISB instruction to ensure that all of the
> + * CP15 register changes have been committed.
> + */
> + isb
Generally writes to cp15 registers that need an isb already do so.
> +
> + /*
> + * Execute a barrier instruction to ensure that all cache,
> + * TLB and branch predictor maintenance operations issued
> + * by any CPU in the cluster have completed.
> + */
> + dsb
> + dmb
A dsb is a superset of a dmb, so you should not need both.
> +
> + /*
> + * Execute a WFI instruction and wait until the
> + * STANDBYWFI output is asserted to indicate that the
> + * CPU is in idle and low power state. CPU can specualatively
> + * prefetch the instructions so add NOPs after WFI. Sixteen
> + * NOPs as per Cortex-A9 pipeline.
Why do you care what is prefetched? You're never coming back here, right?
Rob
> + */
> + wfi @ Wait For Interrupt
> + nop
> + nop
> + nop
> + nop
> + nop
> + nop
> + nop
> + nop
> + nop
> + nop
> + nop
> + nop
> + nop
> + nop
> + nop
> + nop
> +
> + ldmfd sp!, {pc}
> +ENDPROC(sh73a0_do_wfi)
> +
> __CPUINIT
> /*
> * Reset vector for secondary CPUs.
> diff --git a/arch/arm/mach-shmobile/include/mach/common.h b/arch/arm/mach-shmobile/include/mach/common.h
> index f2e2c29..40f767e 100644
> --- a/arch/arm/mach-shmobile/include/mach/common.h
> +++ b/arch/arm/mach-shmobile/include/mach/common.h
> @@ -55,6 +55,7 @@ extern void sh73a0_add_standard_devices(void);
> extern void sh73a0_clock_init(void);
> extern void sh73a0_pinmux_init(void);
> extern void sh73a0_secondary_vector(void);
> +extern void sh73a0_do_wfi(void);
> extern struct clk sh73a0_extal1_clk;
> extern struct clk sh73a0_extal2_clk;
> extern struct clk sh73a0_extcki_clk;
> diff --git a/arch/arm/mach-shmobile/smp-sh73a0.c b/arch/arm/mach-shmobile/smp-sh73a0.c
> index 5e36f5d..9237e13 100644
> --- a/arch/arm/mach-shmobile/smp-sh73a0.c
> +++ b/arch/arm/mach-shmobile/smp-sh73a0.c
> @@ -24,6 +24,7 @@
> #include <linux/io.h>
> #include <linux/delay.h>
> #include <mach/common.h>
> +#include <asm/cacheflush.h>
> #include <asm/smp_plat.h>
> #include <mach/sh73a0.h>
> #include <asm/smp_scu.h>
> @@ -36,6 +37,8 @@
> #define SBAR IOMEM(0xe6180020)
> #define APARMBAREA IOMEM(0xe6f10020)
>
> +#define PSTR_SHUTDOWN_MODE 3
> +
> static void __iomem *scu_base_addr(void)
> {
> return (void __iomem *)0xf0000000;
> @@ -92,16 +95,20 @@ static void __init sh73a0_smp_init_cpus(void)
> shmobile_smp_init_cpus(ncores);
> }
>
> -static int __maybe_unused sh73a0_cpu_kill(unsigned int cpu)
> +#ifdef CONFIG_HOTPLUG_CPU
> +static int sh73a0_cpu_kill(unsigned int cpu)
> {
> +
> int k;
> + u32 pstr;
>
> - /* this function is running on another CPU than the offline target,
> - * here we need wait for shutdown code in platform_cpu_die() to
> - * finish before asking SoC-specific code to power off the CPU core.
> + /*
> + * wait until the power status register confirms the shutdown of the
> + * offline target
> */
> for (k = 0; k < 1000; k++) {
> - if (shmobile_cpu_is_dead(cpu))
> + pstr = (__raw_readl(PSTR) >> (4 * cpu)) & 3;
> + if (pstr = PSTR_SHUTDOWN_MODE)
> return 1;
>
> mdelay(1);
> @@ -110,6 +117,28 @@ static int __maybe_unused sh73a0_cpu_kill(unsigned int cpu)
> return 0;
> }
>
> +static void sh73a0_cpu_die(unsigned int cpu)
> +{
> + /*
> + * The ARM MPcore does not issue a cache coherency request for the L1
> + * cache when powering off single CPUs. We must take care of this and
> + * further caches.
> + */
> + dsb();
> + flush_cache_all();
> +
> + /* Set power off mode. This takes the CPU out of the MP cluster */
> + scu_power_mode(scu_base_addr(), SCU_PM_POWEROFF);
> +
> + /* Enter shutdown mode */
> + sh73a0_do_wfi();
> +
> + /* We assume success always. We never reach this */
> + pr_err("Shutting down CPU failed. This should never happen!\n");
> + for (;;)
> + ;
> +}
> +#endif /* CONFIG_HOTPLUG_CPU */
>
> struct smp_operations sh73a0_smp_ops __initdata = {
> .smp_init_cpus = sh73a0_smp_init_cpus,
> @@ -118,7 +147,7 @@ struct smp_operations sh73a0_smp_ops __initdata = {
> .smp_boot_secondary = sh73a0_boot_secondary,
> #ifdef CONFIG_HOTPLUG_CPU
> .cpu_kill = sh73a0_cpu_kill,
> - .cpu_die = shmobile_cpu_die,
> + .cpu_die = sh73a0_cpu_die,
> .cpu_disable = shmobile_cpu_disable,
> #endif
> };
>
^ permalink raw reply
* Re: [PATCH 1/2] ARM: SH-Mobile: sh73a0: Secondary CPUs handle own SCU flags
From: Rob Herring @ 2012-12-14 14:06 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1354795719-5578-1-git-send-email-hechtb+renesas@gmail.com>
On 12/06/2012 06:08 AM, Bastian Hecht wrote:
> From: Bastian Hecht <hechtb@gmail.com>
>
> When booting secondary CPUs we have used the main CPU to set up the
> Snoop Control Unit flags of these CPUs. It is a cleaner approach
> if every CPU takes care of its own flags. We avoid the need for
> locking and the program logic is more concise. With this patch the file
> headsmp-sh73a0.S is added that contains a startup vector for secondary CPUs
> that sets up its own SCU flags.
> Further in sh73a0_smp_prepare_cpus() we can rely on the generic ARM helper
> scu_power_mode(). This is possible as we don't cross borders anymore (every
> CPU handles its own flags) and need no locking. So we can throw out the
> needless function modify_scu_cpu_psr().
>
> Signed-off-by: Bastian Hecht <hechtb+renesas@gmail.com>
> ---
> arch/arm/mach-shmobile/Makefile | 2 +-
> arch/arm/mach-shmobile/headsmp-sh73a0.S | 50 ++++++++++++++++++++++++++
> arch/arm/mach-shmobile/include/mach/common.h | 1 +
> arch/arm/mach-shmobile/smp-sh73a0.c | 30 +++-------------
> 4 files changed, 56 insertions(+), 27 deletions(-)
> create mode 100644 arch/arm/mach-shmobile/headsmp-sh73a0.S
>
> diff --git a/arch/arm/mach-shmobile/Makefile b/arch/arm/mach-shmobile/Makefile
> index fe2c97c..a7beb61 100644
> --- a/arch/arm/mach-shmobile/Makefile
> +++ b/arch/arm/mach-shmobile/Makefile
> @@ -17,7 +17,7 @@ obj-$(CONFIG_ARCH_EMEV2) += setup-emev2.o clock-emev2.o
> # SMP objects
> smp-y := platsmp.o headsmp.o
> smp-$(CONFIG_HOTPLUG_CPU) += hotplug.o
> -smp-$(CONFIG_ARCH_SH73A0) += smp-sh73a0.o
> +smp-$(CONFIG_ARCH_SH73A0) += smp-sh73a0.o headsmp-sh73a0.o
> smp-$(CONFIG_ARCH_R8A7779) += smp-r8a7779.o
> smp-$(CONFIG_ARCH_EMEV2) += smp-emev2.o
>
> diff --git a/arch/arm/mach-shmobile/headsmp-sh73a0.S b/arch/arm/mach-shmobile/headsmp-sh73a0.S
> new file mode 100644
> index 0000000..bec4c0d
> --- /dev/null
> +++ b/arch/arm/mach-shmobile/headsmp-sh73a0.S
> @@ -0,0 +1,50 @@
> +/*
> + * SMP support for SoC sh73a0
> + *
> + * Copyright (C) 2012 Bastian Hecht
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of
> + * the License, or (at your option) any later version.
> + *
> + * This program is distributed in the hope that 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, write to the Free Software
> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
> + * MA 02111-1307 USA
> + */
> +
> +#include <linux/linkage.h>
> +#include <linux/init.h>
> +#include <asm/memory.h>
> +
> + __CPUINIT
> +/*
> + * Reset vector for secondary CPUs.
> + *
> + * First we turn on L1 cache coherency for our CPU. Then we jump to
> + * shmobile_invalidate_start that invalidates the cache and hands over control
> + * to the common ARM startup code.
> + * This function will be mapped to address 0 by the SBAR register.
> + * A normal branch is out of range here so we need a long jump. We jump to
> + * the physical address as the MMU is still turned off.
> + */
> + .align 12
> +ENTRY(sh73a0_secondary_vector)
> + mrc p15, 0, r0, c0, c0, 5 @ read MIPDR
> + and r0, r0, #3 @ mask out cpu ID
> + lsl r0, r0, #3 @ we will shift by cpu_id * 8 bits
> + mov r1, #0xf0000000 @ SCU base address
> + ldr r2, [r1, #8] @ SCU Power Status Register
> + mov r3, #3
> + bic r2, r2, r3, lsl r0 @ Clear bits of our CPU (Run Mode)
> + str r2, [r1, #8] @ write back
> +
> + ldr pc, 1f
> +1: .long shmobile_invalidate_start - PAGE_OFFSET + PLAT_PHYS_OFFSET
> +ENDPROC(sh73a0_secondary_vector)
> diff --git a/arch/arm/mach-shmobile/include/mach/common.h b/arch/arm/mach-shmobile/include/mach/common.h
> index d47e215..f2e2c29 100644
> --- a/arch/arm/mach-shmobile/include/mach/common.h
> +++ b/arch/arm/mach-shmobile/include/mach/common.h
> @@ -54,6 +54,7 @@ extern void sh73a0_add_early_devices(void);
> extern void sh73a0_add_standard_devices(void);
> extern void sh73a0_clock_init(void);
> extern void sh73a0_pinmux_init(void);
> +extern void sh73a0_secondary_vector(void);
> extern struct clk sh73a0_extal1_clk;
> extern struct clk sh73a0_extal2_clk;
> extern struct clk sh73a0_extcki_clk;
> diff --git a/arch/arm/mach-shmobile/smp-sh73a0.c b/arch/arm/mach-shmobile/smp-sh73a0.c
> index 624f00f..5e36f5d 100644
> --- a/arch/arm/mach-shmobile/smp-sh73a0.c
> +++ b/arch/arm/mach-shmobile/smp-sh73a0.c
> @@ -41,9 +41,6 @@ static void __iomem *scu_base_addr(void)
> return (void __iomem *)0xf0000000;
> }
>
> -static DEFINE_SPINLOCK(scu_lock);
> -static unsigned long tmp;
> -
> #ifdef CONFIG_HAVE_ARM_TWD
> static DEFINE_TWD_LOCAL_TIMER(twd_local_timer, 0xf0000600, 29);
> void __init sh73a0_register_twd(void)
> @@ -52,20 +49,6 @@ void __init sh73a0_register_twd(void)
> }
> #endif
>
> -static void modify_scu_cpu_psr(unsigned long set, unsigned long clr)
> -{
> - void __iomem *scu_base = scu_base_addr();
> -
> - spin_lock(&scu_lock);
> - tmp = __raw_readl(scu_base + 8);
> - tmp &= ~clr;
> - tmp |= set;
> - spin_unlock(&scu_lock);
> -
> - /* disable cache coherency after releasing the lock */
> - __raw_writel(tmp, scu_base + 8);
None of this locking was needed as the power status register is byte
accessible.
> -}
> -
> static unsigned int __init sh73a0_get_core_count(void)
> {
> void __iomem *scu_base = scu_base_addr();
> @@ -82,9 +65,6 @@ static int __cpuinit sh73a0_boot_secondary(unsigned int cpu, struct task_struct
> {
> cpu = cpu_logical_map(cpu);
>
> - /* enable cache coherency */
> - modify_scu_cpu_psr(0, 3 << (cpu * 8));
> -
So simply changing this to scu_power_mode call would accomplish the same
thing and avoid all the assembly.
Rob
> if (((__raw_readl(PSTR) >> (4 * cpu)) & 3) = 3)
> __raw_writel(1 << cpu, WUPCR); /* wake up */
> else
> @@ -95,16 +75,14 @@ static int __cpuinit sh73a0_boot_secondary(unsigned int cpu, struct task_struct
>
> static void __init sh73a0_smp_prepare_cpus(unsigned int max_cpus)
> {
> - int cpu = cpu_logical_map(0);
> -
> scu_enable(scu_base_addr());
>
> - /* Map the reset vector (in headsmp.S) */
> + /* Map the reset vector (in headsmp-sh73a0.S) */
> __raw_writel(0, APARMBAREA); /* 4k */
> - __raw_writel(__pa(shmobile_secondary_vector), SBAR);
> + __raw_writel(__pa(sh73a0_secondary_vector), SBAR);
>
> - /* enable cache coherency on CPU0 */
> - modify_scu_cpu_psr(0, 3 << (cpu * 8));
> + /* enable cache coherency on booting CPU */
> + scu_power_mode(scu_base_addr(), SCU_PM_NORMAL);
> }
>
> static void __init sh73a0_smp_init_cpus(void)
>
^ permalink raw reply
* Re: [PATCH 1/2] ARM: shmobile: sh73a0: Add CPU sleep suspend
From: Simon Horman @ 2012-12-14 13:47 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CANqRtoQMweOU-Azfwu3-HXKx0Hr0seQYy1hi+arLHN-q=BSh+w@mail.gmail.com>
On Fri, Dec 14, 2012 at 12:23:06PM +0900, Magnus Damm wrote:
> On Wed, Dec 5, 2012 at 9:13 PM, Bastian Hecht <hechtb@gmail.com> wrote:
> > From: Bastian Hecht <hechtb@gmail.com>
> >
> > Add the lighest possible sleep mode on Cortex-A9 cores: CPU sleep. It is
> > entered by a simple dsb and wfi instruction via cpu_do_idle(). As just
> > clocks are stopped there is no need to save or restore any state of the
> > system.
> >
> > Signed-off-by: Bastian Hecht <hechtb+renesas@gmail.com>
>
> Acked-by: Magnus Damm <damm@opensource.se>
Hi Bastian,
could you please re-spin this series on top of the soc5 or next
branches of my renesas tree on kernel.org?
Feel free to include Magnus's Ack unless you make any
non-trivial changes.
Thanks
^ permalink raw reply
* Re: [PATCH 1/2] ARM: SH-Mobile: sh73a0: Secondary CPUs handle own SCU flags
From: Simon Horman @ 2012-12-14 13:47 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CANqRtoR-HeWVgWsL654aVEx9BuHKBpSVXzRYBZY9=1JZFi267g@mail.gmail.com>
On Fri, Dec 14, 2012 at 12:20:29PM +0900, Magnus Damm wrote:
> On Thu, Dec 6, 2012 at 9:08 PM, Bastian Hecht <hechtb@gmail.com> wrote:
> > From: Bastian Hecht <hechtb@gmail.com>
> >
> > When booting secondary CPUs we have used the main CPU to set up the
> > Snoop Control Unit flags of these CPUs. It is a cleaner approach
> > if every CPU takes care of its own flags. We avoid the need for
> > locking and the program logic is more concise. With this patch the file
> > headsmp-sh73a0.S is added that contains a startup vector for secondary CPUs
> > that sets up its own SCU flags.
> > Further in sh73a0_smp_prepare_cpus() we can rely on the generic ARM helper
> > scu_power_mode(). This is possible as we don't cross borders anymore (every
> > CPU handles its own flags) and need no locking. So we can throw out the
> > needless function modify_scu_cpu_psr().
> >
> > Signed-off-by: Bastian Hecht <hechtb+renesas@gmail.com>
>
> Acked-by: Magnus Damm <damm@opensource.se>
Hi Bastian,
could you please re-spin this series on top of the soc5 or next
branches of my renesas tree on kernel.org?
Feel free to include Magnus's Ack unless you make any
non-trivial changes.
Thanks:wq
^ permalink raw reply
* Re: [PATCH] ARM: mach-shmobile: sh73a0 external IRQ wake update
From: Simon Horman @ 2012-12-14 13:32 UTC (permalink / raw)
To: linux-sh
In-Reply-To: <20121214034312.20055.61728.sendpatchset@w520>
On Fri, Dec 14, 2012 at 12:43:12PM +0900, Magnus Damm wrote:
> From: Magnus Damm <damm@opensource.se>
>
> Use sh73a0_set_wake() for external IRQ signals on sh73a0.
>
> The sh73a0 IRQ hardware for external IRQ pins consists of
> the INTCA interrupt controller and the GIC together doing
> their best to limp along. These external IRQ pins are
> treated as a special case where interrupts need to be
> managed in both interrupt controllers in parallel.
>
> The ->irq_set_wake() callback for the external IRQ pins
> can be dealt with in the same way as INTCA-only without
> involving the GIC. So this patch updates the external
> IRQ pin code for sh73a0 to no longer involve the GIC.
>
> Signed-off-by: Magnus Damm <damm@opensource.se>
Thanks applied.
I have applied this to a temporary 'soc5' branch which is based on 3.7-rc1.
I will rebase this on 3.8-rc1 once it is released and rename the branch
to the more sane 'soc'.
I have also merged this change into the next branch.
^ permalink raw reply
* [PATCH] clocksource: sh_cmt: 32-bit control register access prototype
From: Magnus Damm @ 2012-12-14 5:55 UTC (permalink / raw)
To: linux-sh
From: Magnus Damm <damm@opensource.se>
This is a 32-bit control register access prototype
for the CMT driver. It is not ready for merge but
it intends to show the reasoning behind the
register access patches included in this series:
"[PATCH 00/08] clocksource: sh_cmt: CMT driver update"
Not-Yet-Signed-off-by: Magnus Damm <damm@opensource.se>
---
drivers/clocksource/sh_cmt.c | 11 +++++++++++
1 file changed, 11 insertions(+)
--- 0006/drivers/clocksource/sh_cmt.c
+++ work/drivers/clocksource/sh_cmt.c 2012-12-14 11:53:23.000000000 +0900
@@ -79,6 +79,12 @@ struct sh_cmt_priv {
* CMCSR 0xffca0060 16-bit
* CMCNT 0xffca0064 32-bit
* CMCOR 0xffca0068 32-bit
+ *
+ * "32-bit counter and 32-bit control"
+ * CMSTR 0xe6130000 32-bit
+ * CMCSR 0xe6130010 32-bit
+ * CMCNT 0xe6130014 32-bit
+ * CMCOR 0xe6130018 32-bit
*/
static unsigned long sh_cmt_read16(void __iomem *base, unsigned long offs)
@@ -734,8 +740,13 @@ static int sh_cmt_setup(struct sh_cmt_pr
goto err1;
}
+#if 1 /* XXX: filthy prototype hack! */
+ p->read_control = sh_cmt_read32;
+ p->write_control = sh_cmt_write32;
+#else
p->read_control = sh_cmt_read16;
p->write_control = sh_cmt_write16;
+#endif
if (resource_size(res) = 6) {
p->width = 16;
^ permalink raw reply
* [PATCH 08/08] clocksource: sh_cmt: Add CMT register layout comment
From: Magnus Damm @ 2012-12-14 5:54 UTC (permalink / raw)
To: linux-kernel
Cc: linux-sh, johnstul, horms, shinya.kuribayashi.px, Magnus Damm,
tglx
In-Reply-To: <20121214055323.10081.12056.sendpatchset@w520>
From: Magnus Damm <damm@opensource.se>
Add a comment about different register layouts
supported by the CMT driver.
Signed-off-by: Magnus Damm <damm@opensource.se>
---
drivers/clocksource/sh_cmt.c | 15 +++++++++++++++
1 file changed, 15 insertions(+)
--- 0005/drivers/clocksource/sh_cmt.c
+++ work/drivers/clocksource/sh_cmt.c 2012-12-14 11:43:10.000000000 +0900
@@ -66,6 +66,21 @@ struct sh_cmt_priv {
unsigned long value);
};
+/* Examples of supported CMT timer register layouts and I/O access widths:
+ *
+ * "16-bit counter and 16-bit control" as found on sh7263:
+ * CMSTR 0xfffec000 16-bit
+ * CMCSR 0xfffec002 16-bit
+ * CMCNT 0xfffec004 16-bit
+ * CMCOR 0xfffec006 16-bit
+ *
+ * "32-bit counter and 16-bit control" as found on sh7372, sh73a0, r8a7740:
+ * CMSTR 0xffca0000 16-bit
+ * CMCSR 0xffca0060 16-bit
+ * CMCNT 0xffca0064 32-bit
+ * CMCOR 0xffca0068 32-bit
+ */
+
static unsigned long sh_cmt_read16(void __iomem *base, unsigned long offs)
{
return ioread16(base + (offs << 1));
^ permalink raw reply
* [PATCH 07/08] clocksource: sh_cmt: Add control register callbacks
From: Magnus Damm @ 2012-12-14 5:54 UTC (permalink / raw)
To: linux-kernel
Cc: linux-sh, johnstul, horms, shinya.kuribayashi.px, tglx,
Magnus Damm
In-Reply-To: <20121214055323.10081.12056.sendpatchset@w520>
From: Magnus Damm <damm@opensource.se>
This patch adds control register callbacks for the CMT
driver. At this point only 16-bit access is supported
but in the future this will be updated to allow 32-bit
access as well.
Signed-off-by: Magnus Damm <damm@opensource.se>
---
drivers/clocksource/sh_cmt.c | 16 ++++++++++++----
1 file changed, 12 insertions(+), 4 deletions(-)
--- 0004/drivers/clocksource/sh_cmt.c
+++ work/drivers/clocksource/sh_cmt.c 2012-12-14 11:28:57.000000000 +0900
@@ -55,6 +55,11 @@ struct sh_cmt_priv {
unsigned long total_cycles;
bool cs_enabled;
+ /* callbacks for CMSTR and CMCSR access */
+ unsigned long (*read_control)(void __iomem *base, unsigned long offs);
+ void (*write_control)(void __iomem *base, unsigned long offs,
+ unsigned long value);
+
/* callbacks for CMCNT and CMCOR access */
unsigned long (*read_count)(void __iomem *base, unsigned long offs);
void (*write_count)(void __iomem *base, unsigned long offs,
@@ -94,12 +99,12 @@ static inline unsigned long sh_cmt_read_
{
struct sh_timer_config *cfg = p->pdev->dev.platform_data;
- return sh_cmt_read16(p->mapbase - cfg->channel_offset, 0);
+ return p->read_control(p->mapbase - cfg->channel_offset, 0);
}
static inline unsigned long sh_cmt_read_cmcsr(struct sh_cmt_priv *p)
{
- return sh_cmt_read16(p->mapbase, CMCSR);
+ return p->read_control(p->mapbase, CMCSR);
}
static inline unsigned long sh_cmt_read_cmcnt(struct sh_cmt_priv *p)
@@ -112,13 +117,13 @@ static inline void sh_cmt_write_cmstr(st
{
struct sh_timer_config *cfg = p->pdev->dev.platform_data;
- sh_cmt_write16(p->mapbase - cfg->channel_offset, 0, value);
+ p->write_control(p->mapbase - cfg->channel_offset, 0, value);
}
static inline void sh_cmt_write_cmcsr(struct sh_cmt_priv *p,
unsigned long value)
{
- sh_cmt_write16(p->mapbase, CMCSR, value);
+ p->write_control(p->mapbase, CMCSR, value);
}
static inline void sh_cmt_write_cmcnt(struct sh_cmt_priv *p,
@@ -714,6 +719,9 @@ static int sh_cmt_setup(struct sh_cmt_pr
goto err1;
}
+ p->read_control = sh_cmt_read16;
+ p->write_control = sh_cmt_write16;
+
if (resource_size(res) = 6) {
p->width = 16;
p->read_count = sh_cmt_read16;
^ permalink raw reply
* [PATCH 06/08] clocksource: sh_cmt: CMCNT and CMCOR register access update
From: Magnus Damm @ 2012-12-14 5:54 UTC (permalink / raw)
To: linux-kernel
Cc: linux-sh, johnstul, horms, shinya.kuribayashi.px, Magnus Damm,
tglx
In-Reply-To: <20121214055323.10081.12056.sendpatchset@w520>
From: Magnus Damm <damm@opensource.se>
Break out the CMCNT and CMCOR register access code
into separate 16-bit and 32-bit functions that are
hooked into callbacks at init time. This reduces
the amount of software calculations happening at
runtime.
Signed-off-by: Magnus Damm <damm@opensource.se>
---
drivers/clocksource/sh_cmt.c | 62 +++++++++++++++++-------------------------
1 file changed, 26 insertions(+), 36 deletions(-)
--- 0006/drivers/clocksource/sh_cmt.c
+++ work/drivers/clocksource/sh_cmt.c 2012-12-14 13:00:20.000000000 +0900
@@ -54,38 +54,39 @@ struct sh_cmt_priv {
struct clocksource cs;
unsigned long total_cycles;
bool cs_enabled;
+
+ /* callbacks for CMCNT and CMCOR access */
+ unsigned long (*read_count)(void __iomem *base, unsigned long offs);
+ void (*write_count)(void __iomem *base, unsigned long offs,
+ unsigned long value);
};
-static inline unsigned long sh_cmt_read16(void __iomem *base,
- unsigned long offs)
+static unsigned long sh_cmt_read16(void __iomem *base, unsigned long offs)
{
return ioread16(base + (offs << 1));
}
-static inline void sh_cmt_write16(void __iomem *base, unsigned long offs,
- unsigned long value)
+static unsigned long sh_cmt_read32(void __iomem *base, unsigned long offs)
+{
+ return ioread32(base + (offs << 2));
+}
+
+static void sh_cmt_write16(void __iomem *base, unsigned long offs,
+ unsigned long value)
{
iowrite16(value, base + (offs << 1));
}
+static void sh_cmt_write32(void __iomem *base, unsigned long offs,
+ unsigned long value)
+{
+ iowrite32(value, base + (offs << 2));
+}
+
#define CMCSR 0 /* channel register */
#define CMCNT 1 /* channel register */
#define CMCOR 2 /* channel register */
-static inline unsigned long sh_cmt_read(struct sh_cmt_priv *p, int reg_nr)
-{
- void __iomem *base = p->mapbase;
- unsigned long offs = reg_nr;
-
- if (p->width = 16) {
- offs <<= 1;
- return ioread16(base + offs);
- } else {
- offs <<= 2;
- return ioread32(base + offs);
- }
-}
-
static inline unsigned long sh_cmt_read_cmstr(struct sh_cmt_priv *p)
{
struct sh_timer_config *cfg = p->pdev->dev.platform_data;
@@ -100,22 +101,7 @@ static inline unsigned long sh_cmt_read_
static inline unsigned long sh_cmt_read_cmcnt(struct sh_cmt_priv *p)
{
- return sh_cmt_read(p, CMCNT);
-}
-
-static inline void sh_cmt_write(struct sh_cmt_priv *p, int reg_nr,
- unsigned long value)
-{
- void __iomem *base = p->mapbase;
- unsigned long offs = reg_nr;
-
- if (p->width = 16) {
- offs <<= 1;
- iowrite16(value, base + offs);
- } else {
- offs <<= 2;
- iowrite32(value, base + offs);
- }
+ return p->read_count(p->mapbase, CMCNT);
}
static inline void sh_cmt_write_cmstr(struct sh_cmt_priv *p,
@@ -135,13 +121,13 @@ static inline void sh_cmt_write_cmcsr(st
static inline void sh_cmt_write_cmcnt(struct sh_cmt_priv *p,
unsigned long value)
{
- sh_cmt_write(p, CMCNT, value);
+ p->write_count(p->mapbase, CMCNT, value);
}
static inline void sh_cmt_write_cmcor(struct sh_cmt_priv *p,
unsigned long value)
{
- sh_cmt_write(p, CMCOR, value);
+ p->write_count(p->mapbase, CMCOR, value);
}
static unsigned long sh_cmt_get_counter(struct sh_cmt_priv *p,
@@ -718,10 +704,14 @@ static int sh_cmt_setup(struct sh_cmt_pr
if (resource_size(res) = 6) {
p->width = 16;
+ p->read_count = sh_cmt_read16;
+ p->write_count = sh_cmt_write16;
p->overflow_bit = 0x80;
p->clear_bits = ~0x80;
} else {
p->width = 32;
+ p->read_count = sh_cmt_read32;
+ p->write_count = sh_cmt_write32;
p->overflow_bit = 0x8000;
p->clear_bits = ~0xc000;
}
^ permalink raw reply
* [PATCH 05/08] clocksource: sh_cmt: CMSTR and CMCSR register access update
From: Magnus Damm @ 2012-12-14 5:54 UTC (permalink / raw)
To: linux-kernel
Cc: linux-sh, johnstul, horms, shinya.kuribayashi.px, tglx,
Magnus Damm
In-Reply-To: <20121214055323.10081.12056.sendpatchset@w520>
From: Magnus Damm <damm@opensource.se>
Update hardware register access code for CMSTR and CMCSR
from using sh_cmt_read() and sh_cmt_write() to make use
of 16-bit register access functions such as sh_cmt_read16()
and sh_cmt_write16(). Also update sh_cmt_read() and
sh_cmt_write() now when the special cases are gone.
This patch moves us one step closer to the goal of separating
counter register access functions from control control register
functions.
Signed-off-by: Magnus Damm <damm@opensource.se>
---
drivers/clocksource/sh_cmt.c | 66 +++++++++++++++++++-----------------------
1 file changed, 30 insertions(+), 36 deletions(-)
--- 0005/drivers/clocksource/sh_cmt.c
+++ work/drivers/clocksource/sh_cmt.c 2012-12-14 12:58:01.000000000 +0900
@@ -56,44 +56,46 @@ struct sh_cmt_priv {
bool cs_enabled;
};
-static DEFINE_RAW_SPINLOCK(sh_cmt_lock);
+static inline unsigned long sh_cmt_read16(void __iomem *base,
+ unsigned long offs)
+{
+ return ioread16(base + (offs << 1));
+}
+
+static inline void sh_cmt_write16(void __iomem *base, unsigned long offs,
+ unsigned long value)
+{
+ iowrite16(value, base + (offs << 1));
+}
-#define CMSTR -1 /* shared register */
#define CMCSR 0 /* channel register */
#define CMCNT 1 /* channel register */
#define CMCOR 2 /* channel register */
static inline unsigned long sh_cmt_read(struct sh_cmt_priv *p, int reg_nr)
{
- struct sh_timer_config *cfg = p->pdev->dev.platform_data;
void __iomem *base = p->mapbase;
- unsigned long offs;
+ unsigned long offs = reg_nr;
- if (reg_nr = CMSTR) {
- offs = 0;
- base -= cfg->channel_offset;
- } else
- offs = reg_nr;
-
- if (p->width = 16)
+ if (p->width = 16) {
offs <<= 1;
- else {
+ return ioread16(base + offs);
+ } else {
offs <<= 2;
- if ((reg_nr = CMCNT) || (reg_nr = CMCOR))
- return ioread32(base + offs);
+ return ioread32(base + offs);
}
-
- return ioread16(base + offs);
}
static inline unsigned long sh_cmt_read_cmstr(struct sh_cmt_priv *p)
{
- return sh_cmt_read(p, CMSTR);
+ struct sh_timer_config *cfg = p->pdev->dev.platform_data;
+
+ return sh_cmt_read16(p->mapbase - cfg->channel_offset, 0);
}
static inline unsigned long sh_cmt_read_cmcsr(struct sh_cmt_priv *p)
{
- return sh_cmt_read(p, CMCSR);
+ return sh_cmt_read16(p->mapbase, CMCSR);
}
static inline unsigned long sh_cmt_read_cmcnt(struct sh_cmt_priv *p)
@@ -104,39 +106,30 @@ static inline unsigned long sh_cmt_read_
static inline void sh_cmt_write(struct sh_cmt_priv *p, int reg_nr,
unsigned long value)
{
- struct sh_timer_config *cfg = p->pdev->dev.platform_data;
void __iomem *base = p->mapbase;
- unsigned long offs;
-
- if (reg_nr = CMSTR) {
- offs = 0;
- base -= cfg->channel_offset;
- } else
- offs = reg_nr;
+ unsigned long offs = reg_nr;
- if (p->width = 16)
+ if (p->width = 16) {
offs <<= 1;
- else {
+ iowrite16(value, base + offs);
+ } else {
offs <<= 2;
- if ((reg_nr = CMCNT) || (reg_nr = CMCOR)) {
- iowrite32(value, base + offs);
- return;
- }
+ iowrite32(value, base + offs);
}
-
- iowrite16(value, base + offs);
}
static inline void sh_cmt_write_cmstr(struct sh_cmt_priv *p,
unsigned long value)
{
- sh_cmt_write(p, CMSTR, value);
+ struct sh_timer_config *cfg = p->pdev->dev.platform_data;
+
+ sh_cmt_write16(p->mapbase - cfg->channel_offset, 0, value);
}
static inline void sh_cmt_write_cmcsr(struct sh_cmt_priv *p,
unsigned long value)
{
- sh_cmt_write(p, CMCSR, value);
+ sh_cmt_write16(p->mapbase, CMCSR, value);
}
static inline void sh_cmt_write_cmcnt(struct sh_cmt_priv *p,
@@ -173,6 +166,7 @@ static unsigned long sh_cmt_get_counter(
return v2;
}
+static DEFINE_RAW_SPINLOCK(sh_cmt_lock);
static void sh_cmt_start_stop_ch(struct sh_cmt_priv *p, int start)
{
^ permalink raw reply
* [PATCH 04/08] clocksource: sh_cmt: Introduce per-register functions
From: Magnus Damm @ 2012-12-14 5:54 UTC (permalink / raw)
To: linux-kernel
Cc: linux-sh, johnstul, horms, shinya.kuribayashi.px, Magnus Damm,
tglx
In-Reply-To: <20121214055323.10081.12056.sendpatchset@w520>
From: Magnus Damm <damm@opensource.se>
Introduce sh_cmt_read_cmstr/cmcsr/cmcnt() and
sh_cmt_write_cmstr/cmcsr/cmcnt/cmcor() to in the
future allow us to split counter registers from
control registers and reduce code complexity by
removing sh_cmt_read() and sh_cmt_write().
Signed-off-by: Magnus Damm <damm@opensource.se>
---
drivers/clocksource/sh_cmt.c | 71 ++++++++++++++++++++++++++++++++----------
1 file changed, 55 insertions(+), 16 deletions(-)
--- 0001/drivers/clocksource/sh_cmt.c
+++ work/drivers/clocksource/sh_cmt.c 2012-12-14 10:50:15.000000000 +0900
@@ -86,6 +86,21 @@ static inline unsigned long sh_cmt_read(
return ioread16(base + offs);
}
+static inline unsigned long sh_cmt_read_cmstr(struct sh_cmt_priv *p)
+{
+ return sh_cmt_read(p, CMSTR);
+}
+
+static inline unsigned long sh_cmt_read_cmcsr(struct sh_cmt_priv *p)
+{
+ return sh_cmt_read(p, CMCSR);
+}
+
+static inline unsigned long sh_cmt_read_cmcnt(struct sh_cmt_priv *p)
+{
+ return sh_cmt_read(p, CMCNT);
+}
+
static inline void sh_cmt_write(struct sh_cmt_priv *p, int reg_nr,
unsigned long value)
{
@@ -112,21 +127,45 @@ static inline void sh_cmt_write(struct s
iowrite16(value, base + offs);
}
+static inline void sh_cmt_write_cmstr(struct sh_cmt_priv *p,
+ unsigned long value)
+{
+ sh_cmt_write(p, CMSTR, value);
+}
+
+static inline void sh_cmt_write_cmcsr(struct sh_cmt_priv *p,
+ unsigned long value)
+{
+ sh_cmt_write(p, CMCSR, value);
+}
+
+static inline void sh_cmt_write_cmcnt(struct sh_cmt_priv *p,
+ unsigned long value)
+{
+ sh_cmt_write(p, CMCNT, value);
+}
+
+static inline void sh_cmt_write_cmcor(struct sh_cmt_priv *p,
+ unsigned long value)
+{
+ sh_cmt_write(p, CMCOR, value);
+}
+
static unsigned long sh_cmt_get_counter(struct sh_cmt_priv *p,
int *has_wrapped)
{
unsigned long v1, v2, v3;
int o1, o2;
- o1 = sh_cmt_read(p, CMCSR) & p->overflow_bit;
+ o1 = sh_cmt_read_cmcsr(p) & p->overflow_bit;
/* Make sure the timer value is stable. Stolen from acpi_pm.c */
do {
o2 = o1;
- v1 = sh_cmt_read(p, CMCNT);
- v2 = sh_cmt_read(p, CMCNT);
- v3 = sh_cmt_read(p, CMCNT);
- o1 = sh_cmt_read(p, CMCSR) & p->overflow_bit;
+ v1 = sh_cmt_read_cmcnt(p);
+ v2 = sh_cmt_read_cmcnt(p);
+ v3 = sh_cmt_read_cmcnt(p);
+ o1 = sh_cmt_read_cmcsr(p) & p->overflow_bit;
} while (unlikely((o1 != o2) || (v1 > v2 && v1 < v3)
|| (v2 > v3 && v2 < v1) || (v3 > v1 && v3 < v2)));
@@ -142,14 +181,14 @@ static void sh_cmt_start_stop_ch(struct
/* start stop register shared by multiple timer channels */
raw_spin_lock_irqsave(&sh_cmt_lock, flags);
- value = sh_cmt_read(p, CMSTR);
+ value = sh_cmt_read_cmstr(p);
if (start)
value |= 1 << cfg->timer_bit;
else
value &= ~(1 << cfg->timer_bit);
- sh_cmt_write(p, CMSTR, value);
+ sh_cmt_write_cmstr(p, value);
raw_spin_unlock_irqrestore(&sh_cmt_lock, flags);
}
@@ -173,14 +212,14 @@ static int sh_cmt_enable(struct sh_cmt_p
/* configure channel, periodic mode and maximum timeout */
if (p->width = 16) {
*rate = clk_get_rate(p->clk) / 512;
- sh_cmt_write(p, CMCSR, 0x43);
+ sh_cmt_write_cmcsr(p, 0x43);
} else {
*rate = clk_get_rate(p->clk) / 8;
- sh_cmt_write(p, CMCSR, 0x01a4);
+ sh_cmt_write_cmcsr(p, 0x01a4);
}
- sh_cmt_write(p, CMCOR, 0xffffffff);
- sh_cmt_write(p, CMCNT, 0);
+ sh_cmt_write_cmcor(p, 0xffffffff);
+ sh_cmt_write_cmcnt(p, 0);
/*
* According to the sh73a0 user's manual, as CMCNT can be operated
@@ -194,12 +233,12 @@ static int sh_cmt_enable(struct sh_cmt_p
* take RCLKx2 at maximum.
*/
for (k = 0; k < 100; k++) {
- if (!sh_cmt_read(p, CMCNT))
+ if (!sh_cmt_read_cmcnt(p))
break;
udelay(1);
}
- if (sh_cmt_read(p, CMCNT)) {
+ if (sh_cmt_read_cmcnt(p)) {
dev_err(&p->pdev->dev, "cannot clear CMCNT\n");
ret = -ETIMEDOUT;
goto err1;
@@ -222,7 +261,7 @@ static void sh_cmt_disable(struct sh_cmt
sh_cmt_start_stop_ch(p, 0);
/* disable interrupts in CMT block */
- sh_cmt_write(p, CMCSR, 0);
+ sh_cmt_write_cmcsr(p, 0);
/* stop clock */
clk_disable(p->clk);
@@ -270,7 +309,7 @@ static void sh_cmt_clock_event_program_v
if (new_match > p->max_match_value)
new_match = p->max_match_value;
- sh_cmt_write(p, CMCOR, new_match);
+ sh_cmt_write_cmcor(p, new_match);
now = sh_cmt_get_counter(p, &has_wrapped);
if (has_wrapped && (new_match > p->match_value)) {
@@ -346,7 +385,7 @@ static irqreturn_t sh_cmt_interrupt(int
struct sh_cmt_priv *p = dev_id;
/* clear flags */
- sh_cmt_write(p, CMCSR, sh_cmt_read(p, CMCSR) & p->clear_bits);
+ sh_cmt_write_cmcsr(p, sh_cmt_read_cmcsr(p) & p->clear_bits);
/* update clock source counter to begin with if enabled
* the wrap flag should be cleared by the timer specific
^ permalink raw reply
* [PATCH 03/08] clocksource: sh_cmt: Consolidate platform_set_drvdata() call
From: Magnus Damm @ 2012-12-14 5:53 UTC (permalink / raw)
To: linux-kernel
Cc: linux-sh, johnstul, horms, shinya.kuribayashi.px, tglx,
Magnus Damm
In-Reply-To: <20121214055323.10081.12056.sendpatchset@w520>
From: Magnus Damm <damm@opensource.se>
Cleanup the use of platform_set_drvdata() to reduce code size
Signed-off-by: Shinya Kuribayashi <shinya.kuribayashi.px@renesas.com>
Signed-off-by: Magnus Damm <damm@opensource.se>
---
drivers/clocksource/sh_cmt.c | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
--- 0003/drivers/clocksource/sh_cmt.c
+++ work/drivers/clocksource/sh_cmt.c 2012-12-14 12:54:59.000000000 +0900
@@ -649,8 +649,6 @@ static int sh_cmt_setup(struct sh_cmt_pr
goto err0;
}
- platform_set_drvdata(pdev, p);
-
res = platform_get_resource(p->pdev, IORESOURCE_MEM, 0);
if (!res) {
dev_err(&p->pdev->dev, "failed to get I/O memory\n");
@@ -718,6 +716,8 @@ static int sh_cmt_setup(struct sh_cmt_pr
goto err2;
}
+ platform_set_drvdata(pdev, p);
+
return 0;
err2:
clk_put(p->clk);
@@ -753,7 +753,6 @@ static int __devinit sh_cmt_probe(struct
ret = sh_cmt_setup(p, pdev);
if (ret) {
kfree(p);
- platform_set_drvdata(pdev, NULL);
pm_runtime_idle(&pdev->dev);
return ret;
}
^ permalink raw reply
* [PATCH 02/08] clocksource: sh_cmt: Initialize 'max_match_value' and 'lock' in sh_cmt_setup()
From: Magnus Damm @ 2012-12-14 5:53 UTC (permalink / raw)
To: linux-kernel
Cc: linux-sh, johnstul, horms, shinya.kuribayashi.px, Magnus Damm,
tglx
In-Reply-To: <20121214055323.10081.12056.sendpatchset@w520>
From: Magnus Damm <damm@opensource.se>
Move the setup of spinlock and max_match_value to sh_cmt_setup().
There's no need to defer those steps until sh_cmt_register().
Signed-off-by: Shinya Kuribayashi <shinya.kuribayashi.px@renesas.com>
Signed-off-by: Magnus Damm <damm@opensource.se>
---
drivers/clocksource/sh_cmt.c | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
--- 0002/drivers/clocksource/sh_cmt.c
+++ work/drivers/clocksource/sh_cmt.c 2012-12-14 12:52:35.000000000 +0900
@@ -625,14 +625,6 @@ static int sh_cmt_register(struct sh_cmt
unsigned long clockevent_rating,
unsigned long clocksource_rating)
{
- if (p->width = (sizeof(p->max_match_value) * 8))
- p->max_match_value = ~0;
- else
- p->max_match_value = (1 << p->width) - 1;
-
- p->match_value = p->max_match_value;
- raw_spin_lock_init(&p->lock);
-
if (clockevent_rating)
sh_cmt_register_clockevent(p, name, clockevent_rating);
@@ -703,6 +695,14 @@ static int sh_cmt_setup(struct sh_cmt_pr
p->clear_bits = ~0xc000;
}
+ if (p->width = (sizeof(p->max_match_value) * 8))
+ p->max_match_value = ~0;
+ else
+ p->max_match_value = (1 << p->width) - 1;
+
+ p->match_value = p->max_match_value;
+ raw_spin_lock_init(&p->lock);
+
ret = sh_cmt_register(p, (char *)dev_name(&p->pdev->dev),
cfg->clockevent_rating,
cfg->clocksource_rating);
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox