From d1cb3ecf327066137fb6245b13030cde60241dd6 Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 26 Nov 2013 19:44:18 +0000 Subject: [PATCH 01/87] ARM: plat-versatile: LEDs initialise to off state There really is no excuse to turn on all 8 LEDs at boot time, such that on the Versatile PB/926 we end up with 6 LEDs on continuously and forever. We're not a christmas decoration! Signed-off-by: Russell King Signed-off-by: Linus Walleij --- arch/arm/plat-versatile/leds.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/plat-versatile/leds.c b/arch/arm/plat-versatile/leds.c index d2490d00b46c..2018f307f32e 100644 --- a/arch/arm/plat-versatile/leds.c +++ b/arch/arm/plat-versatile/leds.c @@ -72,8 +72,8 @@ static int __init versatile_leds_init(void) { int i; - /* All ON */ - writel(0xff, LEDREG); + /* All off */ + writel(0, LEDREG); for (i = 0; i < ARRAY_SIZE(versatile_leds); i++) { struct versatile_led *led; From e4ecf2bda239ddef5f4edd0e05d48bfdf88a475d Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 27 Feb 2014 14:29:22 +0100 Subject: [PATCH 02/87] ARM: plat-versatile: convert LEDs to platform device The LEDs were initialized unconditionally with an fs_initcall() which doesn't play well with multiplatform. Convert the driver to a platform device and convert all boards with these LEDs to register a platform device and pass the register as a resource instead. Tested successfully on the Versatile/AB and RealView PB1176. Cc: Bryan Wu Cc: Richard Purdie Cc: Russell King Cc: Pawel Moll Signed-off-by: Linus Walleij --- arch/arm/mach-realview/core.c | 15 ++++++++ arch/arm/mach-realview/core.h | 1 + arch/arm/mach-realview/realview_eb.c | 1 + arch/arm/mach-realview/realview_pb1176.c | 1 + arch/arm/mach-realview/realview_pb11mp.c | 1 + arch/arm/mach-realview/realview_pba8.c | 1 + arch/arm/mach-realview/realview_pbx.c | 1 + arch/arm/mach-versatile/core.c | 16 ++++++++ arch/arm/plat-versatile/leds.c | 49 ++++++++++++++---------- 9 files changed, 65 insertions(+), 21 deletions(-) diff --git a/arch/arm/mach-realview/core.c b/arch/arm/mach-realview/core.c index 1d5ee5c9a1dc..960b8dd78c44 100644 --- a/arch/arm/mach-realview/core.c +++ b/arch/arm/mach-realview/core.c @@ -148,6 +148,21 @@ struct platform_device realview_cf_device = { }, }; +static struct resource realview_leds_resources[] = { + { + .start = REALVIEW_SYS_BASE + REALVIEW_SYS_LED_OFFSET, + .end = REALVIEW_SYS_BASE + REALVIEW_SYS_LED_OFFSET + 4, + .flags = IORESOURCE_MEM, + }, +}; + +struct platform_device realview_leds_device = { + .name = "versatile-leds", + .id = -1, + .num_resources = ARRAY_SIZE(realview_leds_resources), + .resource = realview_leds_resources, +}; + static struct resource realview_i2c_resource = { .start = REALVIEW_I2C_BASE, .end = REALVIEW_I2C_BASE + SZ_4K - 1, diff --git a/arch/arm/mach-realview/core.h b/arch/arm/mach-realview/core.h index 602ca5ec52c5..13dc830ef469 100644 --- a/arch/arm/mach-realview/core.h +++ b/arch/arm/mach-realview/core.h @@ -37,6 +37,7 @@ struct machine_desc; extern struct platform_device realview_flash_device; extern struct platform_device realview_cf_device; +extern struct platform_device realview_leds_device; extern struct platform_device realview_i2c_device; extern struct mmci_platform_data realview_mmc0_plat_data; extern struct mmci_platform_data realview_mmc1_plat_data; diff --git a/arch/arm/mach-realview/realview_eb.c b/arch/arm/mach-realview/realview_eb.c index c85ddb2a0ad0..6bb070e80128 100644 --- a/arch/arm/mach-realview/realview_eb.c +++ b/arch/arm/mach-realview/realview_eb.c @@ -452,6 +452,7 @@ static void __init realview_eb_init(void) realview_flash_register(&realview_eb_flash_resource, 1); platform_device_register(&realview_i2c_device); platform_device_register(&char_lcd_device); + platform_device_register(&realview_leds_device); eth_device_register(); realview_usb_register(realview_eb_isp1761_resources); diff --git a/arch/arm/mach-realview/realview_pb1176.c b/arch/arm/mach-realview/realview_pb1176.c index c5eade76461b..173f2c15de49 100644 --- a/arch/arm/mach-realview/realview_pb1176.c +++ b/arch/arm/mach-realview/realview_pb1176.c @@ -367,6 +367,7 @@ static void __init realview_pb1176_init(void) realview_usb_register(realview_pb1176_isp1761_resources); platform_device_register(&pmu_device); platform_device_register(&char_lcd_device); + platform_device_register(&realview_leds_device); for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { struct amba_device *d = amba_devs[i]; diff --git a/arch/arm/mach-realview/realview_pb11mp.c b/arch/arm/mach-realview/realview_pb11mp.c index f4b0962578fe..bde7e6b1fd44 100644 --- a/arch/arm/mach-realview/realview_pb11mp.c +++ b/arch/arm/mach-realview/realview_pb11mp.c @@ -347,6 +347,7 @@ static void __init realview_pb11mp_init(void) realview_eth_register(NULL, realview_pb11mp_smsc911x_resources); platform_device_register(&realview_i2c_device); platform_device_register(&realview_cf_device); + platform_device_register(&realview_leds_device); realview_usb_register(realview_pb11mp_isp1761_resources); platform_device_register(&pmu_device); diff --git a/arch/arm/mach-realview/realview_pba8.c b/arch/arm/mach-realview/realview_pba8.c index 10a3e1d76891..4e57a8599265 100644 --- a/arch/arm/mach-realview/realview_pba8.c +++ b/arch/arm/mach-realview/realview_pba8.c @@ -289,6 +289,7 @@ static void __init realview_pba8_init(void) realview_eth_register(NULL, realview_pba8_smsc911x_resources); platform_device_register(&realview_i2c_device); platform_device_register(&realview_cf_device); + platform_device_register(&realview_leds_device); realview_usb_register(realview_pba8_isp1761_resources); platform_device_register(&pmu_device); diff --git a/arch/arm/mach-realview/realview_pbx.c b/arch/arm/mach-realview/realview_pbx.c index 9d75493e3f0c..72c96caebefa 100644 --- a/arch/arm/mach-realview/realview_pbx.c +++ b/arch/arm/mach-realview/realview_pbx.c @@ -385,6 +385,7 @@ static void __init realview_pbx_init(void) realview_eth_register(NULL, realview_pbx_smsc911x_resources); platform_device_register(&realview_i2c_device); platform_device_register(&realview_cf_device); + platform_device_register(&realview_leds_device); realview_usb_register(realview_pbx_isp1761_resources); for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c index a335126ae18f..b31878570a00 100644 --- a/arch/arm/mach-versatile/core.c +++ b/arch/arm/mach-versatile/core.c @@ -310,6 +310,21 @@ static struct platform_device char_lcd_device = { .resource = char_lcd_resources, }; +static struct resource leds_resources[] = { + { + .start = VERSATILE_SYS_BASE + VERSATILE_SYS_LED_OFFSET, + .end = VERSATILE_SYS_BASE + VERSATILE_SYS_LED_OFFSET + 4, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device leds_device = { + .name = "versatile-leds", + .id = -1, + .num_resources = ARRAY_SIZE(leds_resources), + .resource = leds_resources, +}; + /* * Clock handling */ @@ -795,6 +810,7 @@ void __init versatile_init(void) platform_device_register(&versatile_i2c_device); platform_device_register(&smc91x_device); platform_device_register(&char_lcd_device); + platform_device_register(&leds_device); for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { struct amba_device *d = amba_devs[i]; diff --git a/arch/arm/plat-versatile/leds.c b/arch/arm/plat-versatile/leds.c index 2018f307f32e..80553022d661 100644 --- a/arch/arm/plat-versatile/leds.c +++ b/arch/arm/plat-versatile/leds.c @@ -7,22 +7,14 @@ */ #include #include +#include #include #include #include - -#include -#include - -#ifdef VERSATILE_SYS_BASE -#define LEDREG (__io_address(VERSATILE_SYS_BASE) + VERSATILE_SYS_LED_OFFSET) -#endif - -#ifdef REALVIEW_SYS_BASE -#define LEDREG (__io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_LED_OFFSET) -#endif +#include struct versatile_led { + void __iomem *base; struct led_classdev cdev; u8 mask; }; @@ -50,30 +42,37 @@ static void versatile_led_set(struct led_classdev *cdev, { struct versatile_led *led = container_of(cdev, struct versatile_led, cdev); - u32 reg = readl(LEDREG); + u32 reg = readl(led->base); if (b != LED_OFF) reg |= led->mask; else reg &= ~led->mask; - writel(reg, LEDREG); + writel(reg, led->base); } static enum led_brightness versatile_led_get(struct led_classdev *cdev) { struct versatile_led *led = container_of(cdev, struct versatile_led, cdev); - u32 reg = readl(LEDREG); + u32 reg = readl(led->base); return (reg & led->mask) ? LED_FULL : LED_OFF; } -static int __init versatile_leds_init(void) +static int versatile_leds_probe(struct platform_device *dev) { int i; + struct resource *res; + void __iomem *base; + + res = platform_get_resource(dev, IORESOURCE_MEM, 0); + base = devm_ioremap_resource(&dev->dev, res); + if (IS_ERR(base)) + return PTR_ERR(base); /* All off */ - writel(0, LEDREG); + writel(0, base); for (i = 0; i < ARRAY_SIZE(versatile_leds); i++) { struct versatile_led *led; @@ -81,6 +80,7 @@ static int __init versatile_leds_init(void) if (!led) break; + led->base = base; led->cdev.name = versatile_leds[i].name; led->cdev.brightness_set = versatile_led_set; led->cdev.brightness_get = versatile_led_get; @@ -96,8 +96,15 @@ static int __init versatile_leds_init(void) return 0; } -/* - * Since we may have triggers on any subsystem, defer registration - * until after subsystem_init. - */ -fs_initcall(versatile_leds_init); +static struct platform_driver versatile_leds_driver = { + .driver = { + .name = "versatile-leds", + }, + .probe = versatile_leds_probe, +}; + +module_platform_driver(versatile_leds_driver); + +MODULE_AUTHOR("Linus Walleij "); +MODULE_DESCRIPTION("ARM Versatile LED driver"); +MODULE_LICENSE("GPL v2"); From 1dc7d8374dccf2815294ceb6a1092253f45ba860 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 27 Feb 2014 14:44:17 +0100 Subject: [PATCH 03/87] ARM/leds: move ARM Versatile LED driver to leds subsystem Now that we have converted this driver to a real platform device module-based thing, we move the driver down into the LEDs subsystem and rename the config option to LEDS_VERSATILE. Cc: Richard Purdie Cc: Russell King Cc: Pawel Moll Acked-by: Bryan Wu Signed-off-by: Linus Walleij --- arch/arm/plat-versatile/Kconfig | 6 ------ arch/arm/plat-versatile/Makefile | 1 - drivers/leds/Kconfig | 8 ++++++++ drivers/leds/Makefile | 1 + .../leds.c => drivers/leds/leds-versatile.c | 0 5 files changed, 9 insertions(+), 7 deletions(-) rename arch/arm/plat-versatile/leds.c => drivers/leds/leds-versatile.c (100%) diff --git a/arch/arm/plat-versatile/Kconfig b/arch/arm/plat-versatile/Kconfig index 2c4332b9f948..fce41e93b6a4 100644 --- a/arch/arm/plat-versatile/Kconfig +++ b/arch/arm/plat-versatile/Kconfig @@ -6,12 +6,6 @@ config PLAT_VERSATILE_CLOCK config PLAT_VERSATILE_CLCD bool -config PLAT_VERSATILE_LEDS - def_bool y if NEW_LEDS - depends on ARCH_REALVIEW || ARCH_VERSATILE - select LEDS_CLASS - select LEDS_TRIGGERS - config PLAT_VERSATILE_SCHED_CLOCK def_bool y diff --git a/arch/arm/plat-versatile/Makefile b/arch/arm/plat-versatile/Makefile index f88d448b629c..2e0c472958ae 100644 --- a/arch/arm/plat-versatile/Makefile +++ b/arch/arm/plat-versatile/Makefile @@ -2,6 +2,5 @@ ccflags-$(CONFIG_ARCH_MULTIPLATFORM) := -I$(srctree)/$(src)/include obj-$(CONFIG_PLAT_VERSATILE_CLOCK) += clock.o obj-$(CONFIG_PLAT_VERSATILE_CLCD) += clcd.o -obj-$(CONFIG_PLAT_VERSATILE_LEDS) += leds.o obj-$(CONFIG_PLAT_VERSATILE_SCHED_CLOCK) += sched-clock.o obj-$(CONFIG_SMP) += headsmp.o platsmp.o diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index 72156c123033..93235f7378ba 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig @@ -487,6 +487,14 @@ config LEDS_BLINKM This option enables support for the BlinkM RGB LED connected through I2C. Say Y to enable support for the BlinkM LED. +config LEDS_VERSATILE + bool "LED support for the ARM Versatile and RealView" + depends on ARCH_REALVIEW || ARCH_VERSATILE + depends on LEDS_CLASS + help + This option enabled support for the LEDs on the ARM Versatile + and RealView boards. Say Y to enabled these. + comment "LED Triggers" source "drivers/leds/trigger/Kconfig" diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile index 3cd76dbd9be2..8b4c956e11ba 100644 --- a/drivers/leds/Makefile +++ b/drivers/leds/Makefile @@ -54,6 +54,7 @@ obj-$(CONFIG_LEDS_ASIC3) += leds-asic3.o obj-$(CONFIG_LEDS_MAX8997) += leds-max8997.o obj-$(CONFIG_LEDS_LM355x) += leds-lm355x.o obj-$(CONFIG_LEDS_BLINKM) += leds-blinkm.o +obj-$(CONFIG_LEDS_VERSATILE) += leds-versatile.o # LED SPI Drivers obj-$(CONFIG_LEDS_DAC124S085) += leds-dac124s085.o diff --git a/arch/arm/plat-versatile/leds.c b/drivers/leds/leds-versatile.c similarity index 100% rename from arch/arm/plat-versatile/leds.c rename to drivers/leds/leds-versatile.c From 9b58d187fdce9df05fd331ad5790bf503d7e3dfe Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 27 Feb 2014 14:51:28 +0100 Subject: [PATCH 04/87] ARM: plat-versatile: update defconfigs for Versatile LEDs As we moved the Versatile LEDs to the LEDs subsystem and made it a module, the config options are no more default-selected. Make sure all users still experience LEDs properly by updating all RealView and Versatile defconfigs. Cc: Bryan Wu Cc: Richard Purdie Cc: Russell King Cc: Pawel Moll Signed-off-by: Linus Walleij --- arch/arm/configs/realview-smp_defconfig | 2 ++ arch/arm/configs/realview_defconfig | 2 ++ arch/arm/configs/versatile_defconfig | 3 +++ 3 files changed, 7 insertions(+) diff --git a/arch/arm/configs/realview-smp_defconfig b/arch/arm/configs/realview-smp_defconfig index abe61bf379d2..1da5d9e48224 100644 --- a/arch/arm/configs/realview-smp_defconfig +++ b/arch/arm/configs/realview-smp_defconfig @@ -76,8 +76,10 @@ CONFIG_MMC=y CONFIG_MMC_ARMMMCI=y CONFIG_NEW_LEDS=y CONFIG_LEDS_CLASS=y +CONFIG_LEDS_VERSATILE=y CONFIG_LEDS_TRIGGERS=y CONFIG_LEDS_TRIGGER_HEARTBEAT=y +CONFIG_LEDS_TRIGGER_CPU=y CONFIG_RTC_CLASS=y CONFIG_RTC_DRV_DS1307=y CONFIG_RTC_DRV_PL031=y diff --git a/arch/arm/configs/realview_defconfig b/arch/arm/configs/realview_defconfig index 7079cbe898a8..d02e9d911bb7 100644 --- a/arch/arm/configs/realview_defconfig +++ b/arch/arm/configs/realview_defconfig @@ -75,8 +75,10 @@ CONFIG_MMC=y CONFIG_MMC_ARMMMCI=y CONFIG_NEW_LEDS=y CONFIG_LEDS_CLASS=y +CONFIG_LEDS_VERSATILE=y CONFIG_LEDS_TRIGGERS=y CONFIG_LEDS_TRIGGER_HEARTBEAT=y +CONFIG_LEDS_TRIGGER_CPU=y CONFIG_RTC_CLASS=y CONFIG_RTC_DRV_DS1307=y CONFIG_RTC_DRV_PL031=y diff --git a/arch/arm/configs/versatile_defconfig b/arch/arm/configs/versatile_defconfig index 073541a50e23..d52b4ffe2012 100644 --- a/arch/arm/configs/versatile_defconfig +++ b/arch/arm/configs/versatile_defconfig @@ -61,6 +61,9 @@ CONFIG_SND_ARMAACI=m CONFIG_MMC=y CONFIG_MMC_ARMMMCI=m CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y +CONFIG_LEDS_VERSATILE=y +CONFIG_LEDS_TRIGGERS=y CONFIG_LEDS_TRIGGER_HEARTBEAT=y CONFIG_LEDS_TRIGGER_CPU=y CONFIG_EXT2_FS=y From 1668a7a699f8c96bc99a50e94aadfe328adf9b76 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 18 Mar 2014 10:39:23 +0100 Subject: [PATCH 05/87] ARM: shmobile: armadillo800eva: Spelling and grammar Signed-off-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- arch/arm/mach-shmobile/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig index 0f92ba8e7884..edb1a914deb3 100644 --- a/arch/arm/mach-shmobile/Kconfig +++ b/arch/arm/mach-shmobile/Kconfig @@ -205,8 +205,8 @@ config MACH_ARMADILLO800EVA_REFERENCE select SND_SOC_WM8978 if SND_SIMPLE_CARD select USE_OF ---help--- - Use reference implementation of Aramdillo800 EVA board support - which makes a greater use of device tree at the expense + Use reference implementation of Armadillo800 EVA board support + which makes greater use of device tree at the expense of not supporting a number of devices. This is intended to aid developers From 06654acb6698a92bb7e6deb6897006ed501cdc47 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Wed, 19 Feb 2014 09:25:36 +0900 Subject: [PATCH 06/87] clk: samsung: add pll_6552 variant for s3c2416 According to the manual s3c2416 and s3c2450 use a pll 6552 and 6553 and while the pll_6553 matches exactly the one already implemented the pll_6552 differs to the one from the s3c64xx series. The change is solely in the bit locations of the mdiv and pdiv values. All calculations are the same for both implementatons and even the proposed divider-values for specific frequencies in the manuals are the same. Therefore implement a variant that simply uses the changed bit locations if necessary. Signed-off-by: Heiko Stuebner Acked-by: Tomasz Figa Acked-by: Mike Turquette Signed-off-by: Kukjin Kim --- drivers/clk/samsung/clk-pll.c | 12 ++++++++++-- drivers/clk/samsung/clk-pll.h | 1 + 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c index 81e6d2f49aa0..f9a35a612705 100644 --- a/drivers/clk/samsung/clk-pll.c +++ b/drivers/clk/samsung/clk-pll.c @@ -564,7 +564,9 @@ static const struct clk_ops samsung_pll46xx_clk_min_ops = { #define PLL6552_PDIV_MASK 0x3f #define PLL6552_SDIV_MASK 0x7 #define PLL6552_MDIV_SHIFT 16 +#define PLL6552_MDIV_SHIFT_2416 14 #define PLL6552_PDIV_SHIFT 8 +#define PLL6552_PDIV_SHIFT_2416 5 #define PLL6552_SDIV_SHIFT 0 static unsigned long samsung_pll6552_recalc_rate(struct clk_hw *hw, @@ -575,8 +577,13 @@ static unsigned long samsung_pll6552_recalc_rate(struct clk_hw *hw, u64 fvco = parent_rate; pll_con = __raw_readl(pll->con_reg); - mdiv = (pll_con >> PLL6552_MDIV_SHIFT) & PLL6552_MDIV_MASK; - pdiv = (pll_con >> PLL6552_PDIV_SHIFT) & PLL6552_PDIV_MASK; + if (pll->type == pll_6552_s3c2416) { + mdiv = (pll_con >> PLL6552_MDIV_SHIFT_2416) & PLL6552_MDIV_MASK; + pdiv = (pll_con >> PLL6552_PDIV_SHIFT_2416) & PLL6552_PDIV_MASK; + } else { + mdiv = (pll_con >> PLL6552_MDIV_SHIFT) & PLL6552_MDIV_MASK; + pdiv = (pll_con >> PLL6552_PDIV_SHIFT) & PLL6552_PDIV_MASK; + } sdiv = (pll_con >> PLL6552_SDIV_SHIFT) & PLL6552_SDIV_MASK; fvco *= mdiv; @@ -773,6 +780,7 @@ static void __init _samsung_clk_register_pll(struct samsung_pll_clock *pll_clk, init.ops = &samsung_pll36xx_clk_ops; break; case pll_6552: + case pll_6552_s3c2416: init.ops = &samsung_pll6552_clk_ops; break; case pll_6553: diff --git a/drivers/clk/samsung/clk-pll.h b/drivers/clk/samsung/clk-pll.h index 6c39030080fb..ddf9029c13c9 100644 --- a/drivers/clk/samsung/clk-pll.h +++ b/drivers/clk/samsung/clk-pll.h @@ -24,6 +24,7 @@ enum samsung_pll_type { pll_4650, pll_4650c, pll_6552, + pll_6552_s3c2416, pll_6553, }; From a951b1d91dcca8d373c92666c5e006de8234d34b Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Wed, 19 Feb 2014 09:25:41 +0900 Subject: [PATCH 07/87] clk: samsung: add plls used by the s3c2443 The s3c2443 uses different plls that are not present yet. Therefore add the two needed types. Signed-off-by: Heiko Stuebner Acked-by: Tomasz Figa Acked-by: Mike Turquette Signed-off-by: Kukjin Kim --- drivers/clk/samsung/clk-pll.c | 72 +++++++++++++++++++++++++++++++++++ drivers/clk/samsung/clk-pll.h | 2 + 2 files changed, 74 insertions(+) diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c index f9a35a612705..8c9c015a4538 100644 --- a/drivers/clk/samsung/clk-pll.c +++ b/drivers/clk/samsung/clk-pll.c @@ -58,6 +58,72 @@ static long samsung_pll_round_rate(struct clk_hw *hw, return rate_table[i - 1].rate; } +/* + * PLL2126 Clock Type + */ + +#define PLL2126_MDIV_MASK (0xff) +#define PLL2126_PDIV_MASK (0x3f) +#define PLL2126_SDIV_MASK (0x3) +#define PLL2126_MDIV_SHIFT (16) +#define PLL2126_PDIV_SHIFT (8) +#define PLL2126_SDIV_SHIFT (0) + +static unsigned long samsung_pll2126_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct samsung_clk_pll *pll = to_clk_pll(hw); + u32 pll_con, mdiv, pdiv, sdiv; + u64 fvco = parent_rate; + + pll_con = __raw_readl(pll->con_reg); + mdiv = (pll_con >> PLL2126_MDIV_SHIFT) & PLL2126_MDIV_MASK; + pdiv = (pll_con >> PLL2126_PDIV_SHIFT) & PLL2126_PDIV_MASK; + sdiv = (pll_con >> PLL2126_SDIV_SHIFT) & PLL2126_SDIV_MASK; + + fvco *= (mdiv + 8); + do_div(fvco, (pdiv + 2) << sdiv); + + return (unsigned long)fvco; +} + +static const struct clk_ops samsung_pll2126_clk_ops = { + .recalc_rate = samsung_pll2126_recalc_rate, +}; + +/* + * PLL3000 Clock Type + */ + +#define PLL3000_MDIV_MASK (0xff) +#define PLL3000_PDIV_MASK (0x3) +#define PLL3000_SDIV_MASK (0x3) +#define PLL3000_MDIV_SHIFT (16) +#define PLL3000_PDIV_SHIFT (8) +#define PLL3000_SDIV_SHIFT (0) + +static unsigned long samsung_pll3000_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct samsung_clk_pll *pll = to_clk_pll(hw); + u32 pll_con, mdiv, pdiv, sdiv; + u64 fvco = parent_rate; + + pll_con = __raw_readl(pll->con_reg); + mdiv = (pll_con >> PLL3000_MDIV_SHIFT) & PLL3000_MDIV_MASK; + pdiv = (pll_con >> PLL3000_PDIV_SHIFT) & PLL3000_PDIV_MASK; + sdiv = (pll_con >> PLL3000_SDIV_SHIFT) & PLL3000_SDIV_MASK; + + fvco *= (2 * (mdiv + 8)); + do_div(fvco, pdiv << sdiv); + + return (unsigned long)fvco; +} + +static const struct clk_ops samsung_pll3000_clk_ops = { + .recalc_rate = samsung_pll3000_recalc_rate, +}; + /* * PLL35xx Clock Type */ @@ -753,6 +819,12 @@ static void __init _samsung_clk_register_pll(struct samsung_pll_clock *pll_clk, } switch (pll_clk->type) { + case pll_2126: + init.ops = &samsung_pll2126_clk_ops; + break; + case pll_3000: + init.ops = &samsung_pll3000_clk_ops; + break; /* clk_ops for 35xx and 2550 are similar */ case pll_35xx: case pll_2550: diff --git a/drivers/clk/samsung/clk-pll.h b/drivers/clk/samsung/clk-pll.h index ddf9029c13c9..5b64bdbb0906 100644 --- a/drivers/clk/samsung/clk-pll.h +++ b/drivers/clk/samsung/clk-pll.h @@ -13,6 +13,8 @@ #define __SAMSUNG_CLK_PLL_H enum samsung_pll_type { + pll_2126, + pll_3000, pll_35xx, pll_36xx, pll_2550, From 78435c812afa70b8ddee789c7f37fc88738079a0 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Wed, 19 Feb 2014 09:25:45 +0900 Subject: [PATCH 08/87] dt-bindings: add binding for clock-controller of s3c2443 and following Starting with the s3c2443 the s3c24xx series got a new clock tree compared to the previous s3c24xx socs. This binding describes the clock controller found in the s3c2443, s3c2416 and s3c2450 socs. Signed-off-by: Heiko Stuebner Acked-by: Tomasz Figa Signed-off-by: Kukjin Kim --- .../bindings/clock/samsung,s3c2443-clock.txt | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/samsung,s3c2443-clock.txt diff --git a/Documentation/devicetree/bindings/clock/samsung,s3c2443-clock.txt b/Documentation/devicetree/bindings/clock/samsung,s3c2443-clock.txt new file mode 100644 index 000000000000..e67bb05478af --- /dev/null +++ b/Documentation/devicetree/bindings/clock/samsung,s3c2443-clock.txt @@ -0,0 +1,56 @@ +* Samsung S3C2443 Clock Controller + +The S3C2443 clock controller generates and supplies clock to various controllers +within the SoC. The clock binding described here is applicable to all SoCs in +the s3c24x family starting with the s3c2443. + +Required Properties: + +- compatible: should be one of the following. + - "samsung,s3c2416-clock" - controller compatible with S3C2416 SoC. + - "samsung,s3c2443-clock" - controller compatible with S3C2443 SoC. + - "samsung,s3c2450-clock" - controller compatible with S3C2450 SoC. +- reg: physical base address of the controller and length of memory mapped + region. +- #clock-cells: should be 1. + +Each clock is assigned an identifier and client nodes can use this identifier +to specify the clock which they consume. Some of the clocks are available only +on a particular SoC. + +All available clocks are defined as preprocessor macros in +dt-bindings/clock/s3c2443.h header and can be used in device +tree sources. + +External clocks: + +There are several clocks that are generated outside the SoC. It is expected +that they are defined using standard clock bindings with following +clock-output-names: + - "xti" - crystal input - required, + - "ext" - external clock source - optional, + - "ext_i2s" - external I2S clock - optional, + - "ext_uart" - external uart clock - optional, + +Example: Clock controller node: + + clocks: clock-controller@4c000000 { + compatible = "samsung,s3c2416-clock"; + reg = <0x4c000000 0x40>; + #clock-cells = <1>; + }; + +Example: UART controller node that consumes the clock generated by the clock + controller (refer to the standard clock bindings for information about + "clocks" and "clock-names" properties): + + serial@50004000 { + compatible = "samsung,s3c2440-uart"; + reg = <0x50004000 0x4000>; + interrupts = <1 23 3 4>, <1 23 4 4>; + clock-names = "uart", "clk_uart_baud2", + "clk_uart_baud3"; + clocks = <&clocks PCLK_UART0>, <&clocks PCLK_UART0>, + <&clocks SCLK_UART>; + status = "disabled"; + }; From 61fbb1d278cf09f29d67629b139b3ca08acbf177 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Wed, 19 Feb 2014 09:25:49 +0900 Subject: [PATCH 09/87] clk: samsung: add clock-driver for s3c2416, s3c2443 and s3c2450 The three SoCs share a common clock tree which only differs in the existence of some special clocks. As with all parts common to these three SoCs the driver is named after the s3c2443, as it was the first SoC introducing this structure and there exists no other label to describe this s3c24xx epoch. The clock structure is built according to the manuals of the included SoCs and might include changes in comparison to the previous clock structure. As an example the sclk_uart gate was never handled previously and the div_uart was made to be the clock used by the serial driver. Signed-off-by: Heiko Stuebner Acked-by: Tomasz Figa Signed-off-by: Kukjin Kim --- arch/arm/mach-s3c24xx/Kconfig | 6 + drivers/clk/samsung/Makefile | 1 + drivers/clk/samsung/clk-s3c2443.c | 462 ++++++++++++++++++++++++++++ include/dt-bindings/clock/s3c2443.h | 92 ++++++ 4 files changed, 561 insertions(+) create mode 100644 drivers/clk/samsung/clk-s3c2443.c create mode 100644 include/dt-bindings/clock/s3c2443.h diff --git a/arch/arm/mach-s3c24xx/Kconfig b/arch/arm/mach-s3c24xx/Kconfig index 40cf50b9940c..abf9179c9d03 100644 --- a/arch/arm/mach-s3c24xx/Kconfig +++ b/arch/arm/mach-s3c24xx/Kconfig @@ -647,6 +647,12 @@ config S3C2443_COMMON Common code for the S3C2443 and similar processors, which includes the S3C2416 and S3C2450. +config S3C2443_COMMON_CLK + bool + help + Temporary symbol to build the clock driver based on the common clock + framework. + config S3C2443_DMA bool help diff --git a/drivers/clk/samsung/Makefile b/drivers/clk/samsung/Makefile index 8eb4799237f0..4c892c63a8dd 100644 --- a/drivers/clk/samsung/Makefile +++ b/drivers/clk/samsung/Makefile @@ -8,4 +8,5 @@ obj-$(CONFIG_SOC_EXYNOS5250) += clk-exynos5250.o obj-$(CONFIG_SOC_EXYNOS5420) += clk-exynos5420.o obj-$(CONFIG_SOC_EXYNOS5440) += clk-exynos5440.o obj-$(CONFIG_ARCH_EXYNOS) += clk-exynos-audss.o +obj-$(CONFIG_S3C2443_COMMON_CLK)+= clk-s3c2443.o obj-$(CONFIG_ARCH_S3C64XX) += clk-s3c64xx.o diff --git a/drivers/clk/samsung/clk-s3c2443.c b/drivers/clk/samsung/clk-s3c2443.c new file mode 100644 index 000000000000..8e4f4517e95c --- /dev/null +++ b/drivers/clk/samsung/clk-s3c2443.c @@ -0,0 +1,462 @@ +/* + * Copyright (c) 2013 Heiko Stuebner + * + * 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. + * + * Common Clock Framework support for S3C2443 and following SoCs. + */ + +#include +#include +#include +#include +#include +#include + +#include + +#include "clk.h" +#include "clk-pll.h" + +/* S3C2416 clock controller register offsets */ +#define LOCKCON0 0x00 +#define LOCKCON1 0x04 +#define MPLLCON 0x10 +#define EPLLCON 0x18 +#define EPLLCON_K 0x1C +#define CLKSRC 0x20 +#define CLKDIV0 0x24 +#define CLKDIV1 0x28 +#define CLKDIV2 0x2C +#define HCLKCON 0x30 +#define PCLKCON 0x34 +#define SCLKCON 0x38 + +/* the soc types */ +enum supported_socs { + S3C2416, + S3C2443, + S3C2450, +}; + +/* list of PLLs to be registered */ +enum s3c2443_plls { + mpll, epll, +}; + +static void __iomem *reg_base; + +#ifdef CONFIG_PM_SLEEP +static struct samsung_clk_reg_dump *s3c2443_save; + +/* + * list of controller registers to be saved and restored during a + * suspend/resume cycle. + */ +static unsigned long s3c2443_clk_regs[] __initdata = { + LOCKCON0, + LOCKCON1, + MPLLCON, + EPLLCON, + EPLLCON_K, + CLKSRC, + CLKDIV0, + CLKDIV1, + CLKDIV2, + PCLKCON, + HCLKCON, + SCLKCON, +}; + +static int s3c2443_clk_suspend(void) +{ + samsung_clk_save(reg_base, s3c2443_save, + ARRAY_SIZE(s3c2443_clk_regs)); + + return 0; +} + +static void s3c2443_clk_resume(void) +{ + samsung_clk_restore(reg_base, s3c2443_save, + ARRAY_SIZE(s3c2443_clk_regs)); +} + +static struct syscore_ops s3c2443_clk_syscore_ops = { + .suspend = s3c2443_clk_suspend, + .resume = s3c2443_clk_resume, +}; + +static void s3c2443_clk_sleep_init(void) +{ + s3c2443_save = samsung_clk_alloc_reg_dump(s3c2443_clk_regs, + ARRAY_SIZE(s3c2443_clk_regs)); + if (!s3c2443_save) { + pr_warn("%s: failed to allocate sleep save data, no sleep support!\n", + __func__); + return; + } + + register_syscore_ops(&s3c2443_clk_syscore_ops); + return; +} +#else +static void s3c2443_clk_sleep_init(void) {} +#endif + +PNAME(epllref_p) = { "mpllref", "mpllref", "xti", "ext" }; +PNAME(esysclk_p) = { "epllref", "epll" }; +PNAME(mpllref_p) = { "xti", "mdivclk" }; +PNAME(msysclk_p) = { "mpllref", "mpll" }; +PNAME(armclk_p) = { "armdiv" , "hclk" }; +PNAME(i2s0_p) = { "div_i2s0", "ext_i2s", "epllref", "epllref" }; + +struct samsung_mux_clock s3c2443_common_muxes[] __initdata = { + MUX(0, "epllref", epllref_p, CLKSRC, 7, 2), + MUX(ESYSCLK, "esysclk", esysclk_p, CLKSRC, 6, 1), + MUX(0, "mpllref", mpllref_p, CLKSRC, 3, 1), + MUX_A(MSYSCLK, "msysclk", msysclk_p, CLKSRC, 4, 1, "msysclk"), + MUX_A(ARMCLK, "armclk", armclk_p, CLKDIV0, 13, 1, "armclk"), + MUX(0, "mux_i2s0", i2s0_p, CLKSRC, 14, 2), +}; + +static struct clk_div_table hclk_d[] = { + { .val = 0, .div = 1 }, + { .val = 1, .div = 2 }, + { .val = 3, .div = 4 }, + { /* sentinel */ }, +}; + +static struct clk_div_table mdivclk_d[] = { + { .val = 0, .div = 1 }, + { .val = 1, .div = 3 }, + { .val = 2, .div = 5 }, + { .val = 3, .div = 7 }, + { .val = 4, .div = 9 }, + { .val = 5, .div = 11 }, + { .val = 6, .div = 13 }, + { .val = 7, .div = 15 }, + { /* sentinel */ }, +}; + +struct samsung_div_clock s3c2443_common_dividers[] __initdata = { + DIV_T(0, "mdivclk", "xti", CLKDIV0, 6, 3, mdivclk_d), + DIV(0, "prediv", "msysclk", CLKDIV0, 4, 2), + DIV_T(HCLK, "hclk", "prediv", CLKDIV0, 0, 2, hclk_d), + DIV(PCLK, "pclk", "hclk", CLKDIV0, 2, 1), + DIV(0, "div_hsspi0_epll", "esysclk", CLKDIV1, 24, 2), + DIV(0, "div_fimd", "esysclk", CLKDIV1, 16, 8), + DIV(0, "div_i2s0", "esysclk", CLKDIV1, 12, 4), + DIV(0, "div_uart", "esysclk", CLKDIV1, 8, 4), + DIV(0, "div_hsmmc1", "esysclk", CLKDIV1, 6, 2), + DIV(0, "div_usbhost", "esysclk", CLKDIV1, 4, 2), +}; + +struct samsung_gate_clock s3c2443_common_gates[] __initdata = { + GATE(SCLK_HSMMC_EXT, "sclk_hsmmcext", "ext", SCLKCON, 13, 0, 0), + GATE(SCLK_HSMMC1, "sclk_hsmmc1", "div_hsmmc1", SCLKCON, 12, 0, 0), + GATE(SCLK_FIMD, "sclk_fimd", "div_fimd", SCLKCON, 10, 0, 0), + GATE(SCLK_I2S0, "sclk_i2s0", "mux_i2s0", SCLKCON, 9, 0, 0), + GATE(SCLK_UART, "sclk_uart", "div_uart", SCLKCON, 8, 0, 0), + GATE(SCLK_USBH, "sclk_usbhost", "div_usbhost", SCLKCON, 1, 0, 0), + GATE(HCLK_DRAM, "dram", "hclk", HCLKCON, 19, CLK_IGNORE_UNUSED, 0), + GATE(HCLK_SSMC, "ssmc", "hclk", HCLKCON, 18, CLK_IGNORE_UNUSED, 0), + GATE(HCLK_HSMMC1, "hsmmc1", "hclk", HCLKCON, 16, 0, 0), + GATE(HCLK_USBD, "usb-device", "hclk", HCLKCON, 12, 0, 0), + GATE(HCLK_USBH, "usb-host", "hclk", HCLKCON, 11, 0, 0), + GATE(HCLK_LCD, "lcd", "hclk", HCLKCON, 9, 0, 0), + GATE(HCLK_DMA5, "dma5", "hclk", HCLKCON, 5, CLK_IGNORE_UNUSED, 0), + GATE(HCLK_DMA4, "dma4", "hclk", HCLKCON, 4, CLK_IGNORE_UNUSED, 0), + GATE(HCLK_DMA3, "dma3", "hclk", HCLKCON, 3, CLK_IGNORE_UNUSED, 0), + GATE(HCLK_DMA2, "dma2", "hclk", HCLKCON, 2, CLK_IGNORE_UNUSED, 0), + GATE(HCLK_DMA1, "dma1", "hclk", HCLKCON, 1, CLK_IGNORE_UNUSED, 0), + GATE(HCLK_DMA0, "dma0", "hclk", HCLKCON, 0, CLK_IGNORE_UNUSED, 0), + GATE(PCLK_GPIO, "gpio", "pclk", PCLKCON, 13, CLK_IGNORE_UNUSED, 0), + GATE(PCLK_RTC, "rtc", "pclk", PCLKCON, 12, 0, 0), + GATE(PCLK_WDT, "wdt", "pclk", PCLKCON, 11, 0, 0), + GATE(PCLK_PWM, "pwm", "pclk", PCLKCON, 10, 0, 0), + GATE(PCLK_I2S0, "i2s0", "pclk", PCLKCON, 9, 0, 0), + GATE(PCLK_AC97, "ac97", "pclk", PCLKCON, 8, 0, 0), + GATE(PCLK_ADC, "adc", "pclk", PCLKCON, 7, 0, 0), + GATE(PCLK_SPI0, "spi0", "pclk", PCLKCON, 6, 0, 0), + GATE(PCLK_I2C0, "i2c0", "pclk", PCLKCON, 4, 0, 0), + GATE(PCLK_UART3, "uart3", "pclk", PCLKCON, 3, 0, 0), + GATE(PCLK_UART2, "uart2", "pclk", PCLKCON, 2, 0, 0), + GATE(PCLK_UART1, "uart1", "pclk", PCLKCON, 1, 0, 0), + GATE(PCLK_UART0, "uart0", "pclk", PCLKCON, 0, 0, 0), +}; + +struct samsung_clock_alias s3c2443_common_aliases[] __initdata = { + ALIAS(HCLK, NULL, "hclk"), + ALIAS(HCLK_SSMC, NULL, "nand"), + ALIAS(PCLK_UART0, "s3c2440-uart.0", "uart"), + ALIAS(PCLK_UART1, "s3c2440-uart.1", "uart"), + ALIAS(PCLK_UART2, "s3c2440-uart.2", "uart"), + ALIAS(PCLK_UART3, "s3c2440-uart.3", "uart"), + ALIAS(PCLK_UART0, "s3c2440-uart.0", "clk_uart_baud2"), + ALIAS(PCLK_UART1, "s3c2440-uart.1", "clk_uart_baud2"), + ALIAS(PCLK_UART2, "s3c2440-uart.2", "clk_uart_baud2"), + ALIAS(PCLK_UART3, "s3c2440-uart.3", "clk_uart_baud2"), + ALIAS(SCLK_UART, NULL, "clk_uart_baud3"), + ALIAS(PCLK_PWM, NULL, "timers"), + ALIAS(PCLK_RTC, NULL, "rtc"), + ALIAS(PCLK_WDT, NULL, "watchdog"), + ALIAS(PCLK_ADC, NULL, "adc"), + ALIAS(PCLK_I2C0, "s3c2410-i2c.0", "i2c"), + ALIAS(HCLK_USBD, NULL, "usb-device"), + ALIAS(HCLK_USBH, NULL, "usb-host"), + ALIAS(SCLK_USBH, NULL, "usb-bus-host"), + ALIAS(PCLK_SPI0, "s3c2443-spi.0", "spi"), + ALIAS(PCLK_SPI0, "s3c2443-spi.0", "spi_busclk0"), + ALIAS(HCLK_HSMMC1, "s3c-sdhci.1", "hsmmc"), + ALIAS(HCLK_HSMMC1, "s3c-sdhci.1", "mmc_busclk.0"), + ALIAS(PCLK_I2S0, "samsung-i2s.0", "iis"), + ALIAS(SCLK_I2S0, NULL, "i2s-if"), + ALIAS(HCLK_LCD, NULL, "lcd"), + ALIAS(SCLK_FIMD, NULL, "sclk_fimd"), +}; + +/* S3C2416 specific clocks */ + +static struct samsung_pll_clock s3c2416_pll_clks[] __initdata = { + [mpll] = PLL(pll_6552_s3c2416, 0, "mpll", "mpllref", + LOCKCON0, MPLLCON, NULL), + [epll] = PLL(pll_6553, 0, "epll", "epllref", + LOCKCON1, EPLLCON, NULL), +}; + +PNAME(s3c2416_hsmmc0_p) = { "sclk_hsmmc0", "sclk_hsmmcext" }; +PNAME(s3c2416_hsmmc1_p) = { "sclk_hsmmc1", "sclk_hsmmcext" }; +PNAME(s3c2416_hsspi0_p) = { "hsspi0_epll", "hsspi0_mpll" }; + +static struct clk_div_table armdiv_s3c2416_d[] = { + { .val = 0, .div = 1 }, + { .val = 1, .div = 2 }, + { .val = 2, .div = 3 }, + { .val = 3, .div = 4 }, + { .val = 5, .div = 6 }, + { .val = 7, .div = 8 }, + { /* sentinel */ }, +}; + +struct samsung_div_clock s3c2416_dividers[] __initdata = { + DIV_T(ARMDIV, "armdiv", "msysclk", CLKDIV0, 9, 3, armdiv_s3c2416_d), + DIV(0, "div_hsspi0_mpll", "msysclk", CLKDIV2, 0, 4), + DIV(0, "div_hsmmc0", "esysclk", CLKDIV2, 6, 2), +}; + +struct samsung_mux_clock s3c2416_muxes[] __initdata = { + MUX(MUX_HSMMC0, "mux_hsmmc0", s3c2416_hsmmc0_p, CLKSRC, 16, 1), + MUX(MUX_HSMMC1, "mux_hsmmc1", s3c2416_hsmmc1_p, CLKSRC, 17, 1), + MUX(MUX_HSSPI0, "mux_hsspi0", s3c2416_hsspi0_p, CLKSRC, 18, 1), +}; + +struct samsung_gate_clock s3c2416_gates[] __initdata = { + GATE(0, "hsspi0_mpll", "div_hsspi0_mpll", SCLKCON, 19, 0, 0), + GATE(0, "hsspi0_epll", "div_hsspi0_epll", SCLKCON, 14, 0, 0), + GATE(0, "sclk_hsmmc0", "div_hsmmc0", SCLKCON, 6, 0, 0), + GATE(HCLK_2D, "2d", "hclk", HCLKCON, 20, 0, 0), + GATE(HCLK_HSMMC0, "hsmmc0", "hclk", HCLKCON, 15, 0, 0), + GATE(HCLK_IROM, "irom", "hclk", HCLKCON, 13, CLK_IGNORE_UNUSED, 0), + GATE(PCLK_PCM, "pcm", "pclk", PCLKCON, 19, 0, 0), +}; + +struct samsung_clock_alias s3c2416_aliases[] __initdata = { + ALIAS(HCLK_HSMMC0, "s3c-sdhci.0", "hsmmc"), + ALIAS(HCLK_HSMMC0, "s3c-sdhci.0", "mmc_busclk.0"), + ALIAS(MUX_HSMMC0, "s3c-sdhci.0", "mmc_busclk.2"), + ALIAS(MUX_HSMMC1, "s3c-sdhci.1", "mmc_busclk.2"), + ALIAS(MUX_HSSPI0, "s3c2443-spi.0", "spi_busclk2"), + ALIAS(ARMDIV, NULL, "armdiv"), +}; + +/* S3C2443 specific clocks */ + +static struct samsung_pll_clock s3c2443_pll_clks[] __initdata = { + [mpll] = PLL(pll_3000, 0, "mpll", "mpllref", + LOCKCON0, MPLLCON, NULL), + [epll] = PLL(pll_2126, 0, "epll", "epllref", + LOCKCON1, EPLLCON, NULL), +}; + +static struct clk_div_table armdiv_s3c2443_d[] = { + { .val = 0, .div = 1 }, + { .val = 8, .div = 2 }, + { .val = 2, .div = 3 }, + { .val = 9, .div = 4 }, + { .val = 10, .div = 6 }, + { .val = 11, .div = 8 }, + { .val = 13, .div = 12 }, + { .val = 15, .div = 16 }, + { /* sentinel */ }, +}; + +struct samsung_div_clock s3c2443_dividers[] __initdata = { + DIV_T(ARMDIV, "armdiv", "msysclk", CLKDIV0, 9, 4, armdiv_s3c2443_d), + DIV(0, "div_cam", "esysclk", CLKDIV1, 26, 4), +}; + +struct samsung_gate_clock s3c2443_gates[] __initdata = { + GATE(SCLK_HSSPI0, "sclk_hsspi0", "div_hsspi0_epll", SCLKCON, 14, 0, 0), + GATE(SCLK_CAM, "sclk_cam", "div_cam", SCLKCON, 11, 0, 0), + GATE(HCLK_CFC, "cfc", "hclk", HCLKCON, 17, CLK_IGNORE_UNUSED, 0), + GATE(HCLK_CAM, "cam", "hclk", HCLKCON, 8, 0, 0), + GATE(PCLK_SPI1, "spi1", "pclk", PCLKCON, 15, 0, 0), + GATE(PCLK_SDI, "sdi", "pclk", PCLKCON, 5, 0, 0), +}; + +struct samsung_clock_alias s3c2443_aliases[] __initdata = { + ALIAS(SCLK_HSSPI0, "s3c2443-spi.0", "spi_busclk2"), + ALIAS(SCLK_HSMMC1, "s3c-sdhci.1", "mmc_busclk.2"), + ALIAS(SCLK_CAM, NULL, "camif-upll"), + ALIAS(PCLK_SPI1, "s3c2410-spi.0", "spi"), + ALIAS(PCLK_SDI, NULL, "sdi"), + ALIAS(HCLK_CFC, NULL, "cfc"), + ALIAS(ARMDIV, NULL, "armdiv"), +}; + +/* S3C2450 specific clocks */ + +PNAME(s3c2450_cam_p) = { "div_cam", "hclk" }; +PNAME(s3c2450_hsspi1_p) = { "hsspi1_epll", "hsspi1_mpll" }; +PNAME(i2s1_p) = { "div_i2s1", "ext_i2s", "epllref", "epllref" }; + +struct samsung_div_clock s3c2450_dividers[] __initdata = { + DIV(0, "div_cam", "esysclk", CLKDIV1, 26, 4), + DIV(0, "div_hsspi1_epll", "esysclk", CLKDIV2, 24, 2), + DIV(0, "div_hsspi1_mpll", "msysclk", CLKDIV2, 16, 4), + DIV(0, "div_i2s1", "esysclk", CLKDIV2, 12, 4), +}; + +struct samsung_mux_clock s3c2450_muxes[] __initdata = { + MUX(0, "mux_cam", s3c2450_cam_p, CLKSRC, 20, 1), + MUX(MUX_HSSPI1, "mux_hsspi1", s3c2450_hsspi1_p, CLKSRC, 19, 1), + MUX(0, "mux_i2s1", i2s1_p, CLKSRC, 12, 2), +}; + +struct samsung_gate_clock s3c2450_gates[] __initdata = { + GATE(SCLK_I2S1, "sclk_i2s1", "div_i2s1", SCLKCON, 5, 0, 0), + GATE(HCLK_CFC, "cfc", "hclk", HCLKCON, 17, 0, 0), + GATE(HCLK_CAM, "cam", "hclk", HCLKCON, 8, 0, 0), + GATE(HCLK_DMA7, "dma7", "hclk", HCLKCON, 7, CLK_IGNORE_UNUSED, 0), + GATE(HCLK_DMA6, "dma6", "hclk", HCLKCON, 6, CLK_IGNORE_UNUSED, 0), + GATE(PCLK_I2S1, "i2s1", "pclk", PCLKCON, 17, 0, 0), + GATE(PCLK_I2C1, "i2c1", "pclk", PCLKCON, 16, 0, 0), + GATE(PCLK_SPI1, "spi1", "pclk", PCLKCON, 14, 0, 0), +}; + +struct samsung_clock_alias s3c2450_aliases[] __initdata = { + ALIAS(PCLK_SPI1, "s3c2443-spi.1", "spi"), + ALIAS(PCLK_SPI1, "s3c2443-spi.1", "spi_busclk0"), + ALIAS(MUX_HSSPI1, "s3c2443-spi.1", "spi_busclk2"), + ALIAS(PCLK_I2C1, "s3c2410-i2c.1", "i2c"), +}; + +/* + * fixed rate clocks generated outside the soc + * Only necessary until the devicetree-move is complete + */ +struct samsung_fixed_rate_clock s3c2443_common_frate_clks[] __initdata = { + FRATE(0, "xti", NULL, CLK_IS_ROOT, 0), + FRATE(0, "ext", NULL, CLK_IS_ROOT, 0), + FRATE(0, "ext_i2s", NULL, CLK_IS_ROOT, 0), + FRATE(0, "ext_uart", NULL, CLK_IS_ROOT, 0), +}; + +static void __init s3c2443_common_clk_register_fixed_ext(unsigned long xti_f) +{ + s3c2443_common_frate_clks[0].fixed_rate = xti_f; + samsung_clk_register_fixed_rate(s3c2443_common_frate_clks, + ARRAY_SIZE(s3c2443_common_frate_clks)); +} + +void __init s3c2443_common_clk_init(struct device_node *np, unsigned long xti_f, + int current_soc, + void __iomem *base) +{ + reg_base = base; + + if (np) { + reg_base = of_iomap(np, 0); + if (!reg_base) + panic("%s: failed to map registers\n", __func__); + } + + samsung_clk_init(np, reg_base, NR_CLKS); + + /* Register external clocks only in non-dt cases */ + if (!np) + s3c2443_common_clk_register_fixed_ext(xti_f); + + /* Register PLLs. */ + if (current_soc == S3C2416 || current_soc == S3C2450) + samsung_clk_register_pll(s3c2416_pll_clks, + ARRAY_SIZE(s3c2416_pll_clks), reg_base); + else + samsung_clk_register_pll(s3c2443_pll_clks, + ARRAY_SIZE(s3c2443_pll_clks), reg_base); + + /* Register common internal clocks. */ + samsung_clk_register_mux(s3c2443_common_muxes, + ARRAY_SIZE(s3c2443_common_muxes)); + samsung_clk_register_div(s3c2443_common_dividers, + ARRAY_SIZE(s3c2443_common_dividers)); + samsung_clk_register_gate(s3c2443_common_gates, + ARRAY_SIZE(s3c2443_common_gates)); + samsung_clk_register_alias(s3c2443_common_aliases, + ARRAY_SIZE(s3c2443_common_aliases)); + + /* Register SoC-specific clocks. */ + switch (current_soc) { + case S3C2450: + samsung_clk_register_div(s3c2450_dividers, + ARRAY_SIZE(s3c2450_dividers)); + samsung_clk_register_mux(s3c2450_muxes, + ARRAY_SIZE(s3c2450_muxes)); + samsung_clk_register_gate(s3c2450_gates, + ARRAY_SIZE(s3c2450_gates)); + samsung_clk_register_alias(s3c2450_aliases, + ARRAY_SIZE(s3c2450_aliases)); + /* fall through, as s3c2450 extends the s3c2416 clocks */ + case S3C2416: + samsung_clk_register_div(s3c2416_dividers, + ARRAY_SIZE(s3c2416_dividers)); + samsung_clk_register_mux(s3c2416_muxes, + ARRAY_SIZE(s3c2416_muxes)); + samsung_clk_register_gate(s3c2416_gates, + ARRAY_SIZE(s3c2416_gates)); + samsung_clk_register_alias(s3c2416_aliases, + ARRAY_SIZE(s3c2416_aliases)); + break; + case S3C2443: + samsung_clk_register_div(s3c2443_dividers, + ARRAY_SIZE(s3c2443_dividers)); + samsung_clk_register_gate(s3c2443_gates, + ARRAY_SIZE(s3c2443_gates)); + samsung_clk_register_alias(s3c2443_aliases, + ARRAY_SIZE(s3c2443_aliases)); + break; + } + + s3c2443_clk_sleep_init(); +} + +static void __init s3c2416_clk_init(struct device_node *np) +{ + s3c2443_common_clk_init(np, 0, S3C2416, 0); +} +CLK_OF_DECLARE(s3c2416_clk, "samsung,s3c2416-clock", s3c2416_clk_init); + +static void __init s3c2443_clk_init(struct device_node *np) +{ + s3c2443_common_clk_init(np, 0, S3C2443, 0); +} +CLK_OF_DECLARE(s3c2443_clk, "samsung,s3c2443-clock", s3c2443_clk_init); + +static void __init s3c2450_clk_init(struct device_node *np) +{ + s3c2443_common_clk_init(np, 0, S3C2450, 0); +} +CLK_OF_DECLARE(s3c2450_clk, "samsung,s3c2450-clock", s3c2450_clk_init); diff --git a/include/dt-bindings/clock/s3c2443.h b/include/dt-bindings/clock/s3c2443.h new file mode 100644 index 000000000000..37e66b054d64 --- /dev/null +++ b/include/dt-bindings/clock/s3c2443.h @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2013 Heiko Stuebner + * + * 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. + * + * Device Tree binding constants clock controllers of Samsung S3C2443 and later. + */ + +#ifndef _DT_BINDINGS_CLOCK_SAMSUNG_S3C2443_CLOCK_H +#define _DT_BINDINGS_CLOCK_SAMSUNG_S3C2443_CLOCK_H + +/* + * Let each exported clock get a unique index, which is used on DT-enabled + * platforms to lookup the clock from a clock specifier. These indices are + * therefore considered an ABI and so must not be changed. This implies + * that new clocks should be added either in free spaces between clock groups + * or at the end. + */ + +/* Core clocks. */ +#define MSYSCLK 1 +#define ESYSCLK 2 +#define ARMDIV 3 +#define ARMCLK 4 +#define HCLK 5 +#define PCLK 6 + +/* Special clocks */ +#define SCLK_HSSPI0 16 +#define SCLK_FIMD 17 +#define SCLK_I2S0 18 +#define SCLK_I2S1 19 +#define SCLK_HSMMC1 20 +#define SCLK_HSMMC_EXT 21 +#define SCLK_CAM 22 +#define SCLK_UART 23 +#define SCLK_USBH 24 + +/* Muxes */ +#define MUX_HSSPI0 32 +#define MUX_HSSPI1 33 +#define MUX_HSMMC0 34 +#define MUX_HSMMC1 35 + +/* hclk-gates */ +#define HCLK_DMA0 48 +#define HCLK_DMA1 49 +#define HCLK_DMA2 50 +#define HCLK_DMA3 51 +#define HCLK_DMA4 52 +#define HCLK_DMA5 53 +#define HCLK_DMA6 54 +#define HCLK_DMA7 55 +#define HCLK_CAM 56 +#define HCLK_LCD 57 +#define HCLK_USBH 58 +#define HCLK_USBD 59 +#define HCLK_IROM 60 +#define HCLK_HSMMC0 61 +#define HCLK_HSMMC1 62 +#define HCLK_CFC 63 +#define HCLK_SSMC 64 +#define HCLK_DRAM 65 +#define HCLK_2D 66 + +/* pclk-gates */ +#define PCLK_UART0 72 +#define PCLK_UART1 73 +#define PCLK_UART2 74 +#define PCLK_UART3 75 +#define PCLK_I2C0 76 +#define PCLK_SDI 77 +#define PCLK_SPI0 78 +#define PCLK_ADC 79 +#define PCLK_AC97 80 +#define PCLK_I2S0 81 +#define PCLK_PWM 82 +#define PCLK_WDT 83 +#define PCLK_RTC 84 +#define PCLK_GPIO 85 +#define PCLK_SPI1 86 +#define PCLK_CHIPID 87 +#define PCLK_I2C1 88 +#define PCLK_I2S1 89 +#define PCLK_PCM 90 + +/* Total number of clocks. */ +#define NR_CLKS (PCLK_PCM + 1) + +#endif /* _DT_BINDINGS_CLOCK_SAMSUNG_S3C2443_CLOCK_H */ From 5ab9a428cf1d118779554b6a20161d7b339310db Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Wed, 19 Feb 2014 09:25:54 +0900 Subject: [PATCH 10/87] ARM: S3C24XX: prevent conflicts between ccf and non-ccf s3c24xx-socs As the conversion to the common-clock-framework is done in multiple steps, it is necessary to prevent conflicts between the different struct clk implementations. For this include the s3c24xx_setup_clocks function only when SAMSUNG_CLOCK is selected and make the socs we don't convert this time explicitly depend on SAMSUNG_CLOCK, which gets only selected automatically if COMMON_CLK is not enabled. Signed-off-by: Heiko Stuebner Reviewed-by: Tomasz Figa Signed-off-by: Kukjin Kim --- arch/arm/mach-s3c24xx/Kconfig | 4 ++++ arch/arm/mach-s3c24xx/common.c | 2 ++ 2 files changed, 6 insertions(+) diff --git a/arch/arm/mach-s3c24xx/Kconfig b/arch/arm/mach-s3c24xx/Kconfig index abf9179c9d03..f10af7faec98 100644 --- a/arch/arm/mach-s3c24xx/Kconfig +++ b/arch/arm/mach-s3c24xx/Kconfig @@ -25,6 +25,7 @@ comment "S3C24XX SoCs" config CPU_S3C2410 bool "SAMSUNG S3C2410" default y + depends on SAMSUNG_CLOCK select CPU_ARM920T select CPU_LLSERIAL_S3C2410 select S3C2410_CLOCK @@ -38,6 +39,7 @@ config CPU_S3C2410 config CPU_S3C2412 bool "SAMSUNG S3C2412" + depends on SAMSUNG_CLOCK select CPU_ARM926T select CPU_LLSERIAL_S3C2440 select S3C2412_DMA if S3C24XX_DMA @@ -58,6 +60,7 @@ config CPU_S3C2416 config CPU_S3C2440 bool "SAMSUNG S3C2440" + depends on SAMSUNG_CLOCK select CPU_ARM920T select CPU_LLSERIAL_S3C2440 select S3C2410_CLOCK @@ -68,6 +71,7 @@ config CPU_S3C2440 config CPU_S3C2442 bool "SAMSUNG S3C2442" + depends on SAMSUNG_CLOCK select CPU_ARM920T select CPU_LLSERIAL_S3C2440 select S3C2410_CLOCK diff --git a/arch/arm/mach-s3c24xx/common.c b/arch/arm/mach-s3c24xx/common.c index 1bc8e73c94f9..0fc6641ac57d 100644 --- a/arch/arm/mach-s3c24xx/common.c +++ b/arch/arm/mach-s3c24xx/common.c @@ -318,6 +318,7 @@ struct s3c24xx_uart_resources s3c2410_uart_resources[] __initdata = { /* initialise all the clocks */ +#ifdef CONFIG_SAMSUNG_CLOCK void __init_or_cpufreq s3c24xx_setup_clocks(unsigned long fclk, unsigned long hclk, unsigned long pclk) @@ -330,6 +331,7 @@ void __init_or_cpufreq s3c24xx_setup_clocks(unsigned long fclk, clk_p.rate = pclk; clk_f.rate = fclk; } +#endif #if defined(CONFIG_CPU_S3C2410) || defined(CONFIG_CPU_S3C2412) || \ defined(CONFIG_CPU_S3C2440) || defined(CONFIG_CPU_S3C2442) From 8cb28748154db139180ea4e24252530aecc3745b Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Wed, 19 Feb 2014 09:26:17 +0900 Subject: [PATCH 11/87] ARM: dts: add clock data for s3c2416 This adds the clock controller itself, the xti clock on the smdk2416 as well as the clock references in the individual device nodes. Signed-off-by: Heiko Stuebner Reviewed-by: Tomasz Figa Signed-off-by: Kukjin Kim --- arch/arm/boot/dts/s3c2416-smdk2416.dts | 13 ++++++++ arch/arm/boot/dts/s3c2416.dtsi | 42 ++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) diff --git a/arch/arm/boot/dts/s3c2416-smdk2416.dts b/arch/arm/boot/dts/s3c2416-smdk2416.dts index 59594cf15998..ea92fd69529a 100644 --- a/arch/arm/boot/dts/s3c2416-smdk2416.dts +++ b/arch/arm/boot/dts/s3c2416-smdk2416.dts @@ -19,6 +19,19 @@ reg = <0x30000000 0x4000000>; }; + clocks { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + + xti: xti { + compatible = "fixed-clock"; + clock-frequency = <12000000>; + clock-output-names = "xti"; + #clock-cells = <0>; + }; + }; + serial@50000000 { status = "okay"; pinctrl-names = "default"; diff --git a/arch/arm/boot/dts/s3c2416.dtsi b/arch/arm/boot/dts/s3c2416.dtsi index e6555bdd81b8..955e4a4f8c31 100644 --- a/arch/arm/boot/dts/s3c2416.dtsi +++ b/arch/arm/boot/dts/s3c2416.dtsi @@ -8,6 +8,7 @@ * published by the Free Software Foundation. */ +#include #include "s3c24xx.dtsi" #include "s3c2416-pinctrl.dtsi" @@ -28,26 +29,53 @@ compatible = "samsung,s3c2416-irq"; }; + clocks: clock-controller@0x4c000000 { + compatible = "samsung,s3c2416-clock"; + reg = <0x4c000000 0x40>; + #clock-cells = <1>; + }; + pinctrl@56000000 { compatible = "samsung,s3c2416-pinctrl"; }; + timer@51000000 { + clocks = <&clocks PCLK_PWM>; + clock-names = "timers"; + }; + serial@50000000 { compatible = "samsung,s3c2440-uart"; + clock-names = "uart", "clk_uart_baud2", + "clk_uart_baud3"; + clocks = <&clocks PCLK_UART0>, <&clocks PCLK_UART0>, + <&clocks SCLK_UART>; }; serial@50004000 { compatible = "samsung,s3c2440-uart"; + clock-names = "uart", "clk_uart_baud2", + "clk_uart_baud3"; + clocks = <&clocks PCLK_UART1>, <&clocks PCLK_UART1>, + <&clocks SCLK_UART>; }; serial@50008000 { compatible = "samsung,s3c2440-uart"; + clock-names = "uart", "clk_uart_baud2", + "clk_uart_baud3"; + clocks = <&clocks PCLK_UART2>, <&clocks PCLK_UART2>, + <&clocks SCLK_UART>; }; serial@5000C000 { compatible = "samsung,s3c2440-uart"; reg = <0x5000C000 0x4000>; interrupts = <1 18 24 4>, <1 18 25 4>; + clock-names = "uart", "clk_uart_baud2", + "clk_uart_baud3"; + clocks = <&clocks PCLK_UART3>, <&clocks PCLK_UART3>, + <&clocks SCLK_UART>; status = "disabled"; }; @@ -55,6 +83,10 @@ compatible = "samsung,s3c6410-sdhci"; reg = <0x4AC00000 0x100>; interrupts = <0 0 21 3>; + clock-names = "hsmmc", "mmc_busclk.0", + "mmc_busclk.2"; + clocks = <&clocks HCLK_HSMMC0>, <&clocks HCLK_HSMMC0>, + <&clocks MUX_HSMMC0>; status = "disabled"; }; @@ -62,18 +94,28 @@ compatible = "samsung,s3c6410-sdhci"; reg = <0x4A800000 0x100>; interrupts = <0 0 20 3>; + clock-names = "hsmmc", "mmc_busclk.0", + "mmc_busclk.2"; + clocks = <&clocks HCLK_HSMMC1>, <&clocks HCLK_HSMMC1>, + <&clocks MUX_HSMMC1>; status = "disabled"; }; watchdog@53000000 { interrupts = <1 9 27 3>; + clocks = <&clocks PCLK_WDT>; + clock-names = "watchdog"; }; rtc@57000000 { compatible = "samsung,s3c2416-rtc"; + clocks = <&clocks PCLK_RTC>; + clock-names = "rtc"; }; i2c@54000000 { compatible = "samsung,s3c2440-i2c"; + clocks = <&clocks PCLK_I2C0>; + clock-names = "i2c"; }; }; From dfc0f5099a83f8633fc4480e2f0e8e5f6ac1331d Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Wed, 19 Feb 2014 09:26:21 +0900 Subject: [PATCH 12/87] ARM: S3C24XX: Convert s3c2416 and s3c2443 to common clock framework This converts the mentioned platforms to use the newly introduced driver for the common clock framework for them. With this the whole legacy clock structure can go away too. Signed-off-by: Heiko Stuebner Reviewed-by: Tomasz Figa Signed-off-by: Kukjin Kim --- arch/arm/mach-s3c24xx/Kconfig | 14 +- arch/arm/mach-s3c24xx/Makefile | 5 +- arch/arm/mach-s3c24xx/clock-s3c2416.c | 171 ------ arch/arm/mach-s3c24xx/clock-s3c2443.c | 212 -------- arch/arm/mach-s3c24xx/common-s3c2443.c | 675 ------------------------ arch/arm/mach-s3c24xx/common.c | 16 +- arch/arm/mach-s3c24xx/common.h | 6 + arch/arm/mach-s3c24xx/mach-s3c2416-dt.c | 38 +- arch/arm/mach-s3c24xx/mach-smdk2416.c | 9 +- arch/arm/mach-s3c24xx/mach-smdk2443.c | 9 +- 10 files changed, 41 insertions(+), 1114 deletions(-) delete mode 100644 arch/arm/mach-s3c24xx/clock-s3c2416.c delete mode 100644 arch/arm/mach-s3c24xx/clock-s3c2443.c delete mode 100644 arch/arm/mach-s3c24xx/common-s3c2443.c diff --git a/arch/arm/mach-s3c24xx/Kconfig b/arch/arm/mach-s3c24xx/Kconfig index f10af7faec98..52f1c40ccf07 100644 --- a/arch/arm/mach-s3c24xx/Kconfig +++ b/arch/arm/mach-s3c24xx/Kconfig @@ -49,12 +49,12 @@ config CPU_S3C2412 config CPU_S3C2416 bool "SAMSUNG S3C2416/S3C2450" + select COMMON_CLK select CPU_ARM926T select CPU_LLSERIAL_S3C2440 select S3C2416_PM if PM - select S3C2443_COMMON + select S3C2443_COMMON_CLK select S3C2443_DMA if S3C24XX_DMA - select SAMSUNG_CLKSRC help Support for the S3C2416 SoC from the S3C24XX line @@ -87,11 +87,11 @@ config CPU_S3C244X config CPU_S3C2443 bool "SAMSUNG S3C2443" + select COMMON_CLK select CPU_ARM920T select CPU_LLSERIAL_S3C2440 - select S3C2443_COMMON + select S3C2443_COMMON_CLK select S3C2443_DMA if S3C24XX_DMA - select SAMSUNG_CLKSRC help Support for the S3C2443 SoC from the S3C24XX line @@ -645,12 +645,6 @@ endif # CPU_S3C2442 if CPU_S3C2443 || CPU_S3C2416 -config S3C2443_COMMON - bool - help - Common code for the S3C2443 and similar processors, which includes - the S3C2416 and S3C2450. - config S3C2443_COMMON_CLK bool help diff --git a/arch/arm/mach-s3c24xx/Makefile b/arch/arm/mach-s3c24xx/Makefile index 7f54e5b954ca..ba0e5475a807 100644 --- a/arch/arm/mach-s3c24xx/Makefile +++ b/arch/arm/mach-s3c24xx/Makefile @@ -26,7 +26,7 @@ obj-$(CONFIG_S3C2412_DMA) += dma-s3c2412.o obj-$(CONFIG_S3C2412_PM) += pm-s3c2412.o obj-$(CONFIG_S3C2412_PM_SLEEP) += sleep-s3c2412.o -obj-$(CONFIG_CPU_S3C2416) += s3c2416.o clock-s3c2416.o +obj-$(CONFIG_CPU_S3C2416) += s3c2416.o obj-$(CONFIG_S3C2416_PM) += pm-s3c2416.o obj-$(CONFIG_CPU_S3C2440) += s3c2440.o clock-s3c2440.o @@ -36,7 +36,7 @@ obj-$(CONFIG_S3C2440_DMA) += dma-s3c2440.o obj-$(CONFIG_S3C2440_PLL_12000000) += pll-s3c2440-12000000.o obj-$(CONFIG_S3C2440_PLL_16934400) += pll-s3c2440-16934400.o -obj-$(CONFIG_CPU_S3C2443) += s3c2443.o clock-s3c2443.o +obj-$(CONFIG_CPU_S3C2443) += s3c2443.o # PM @@ -53,7 +53,6 @@ obj-$(CONFIG_S3C2410_CPUFREQ_UTILS) += cpufreq-utils.o obj-$(CONFIG_S3C2410_IOTIMING) += iotiming-s3c2410.o obj-$(CONFIG_S3C2412_IOTIMING) += iotiming-s3c2412.o -obj-$(CONFIG_S3C2443_COMMON) += common-s3c2443.o obj-$(CONFIG_S3C2443_DMA) += dma-s3c2443.o # diff --git a/arch/arm/mach-s3c24xx/clock-s3c2416.c b/arch/arm/mach-s3c24xx/clock-s3c2416.c deleted file mode 100644 index d421a72920a5..000000000000 --- a/arch/arm/mach-s3c24xx/clock-s3c2416.c +++ /dev/null @@ -1,171 +0,0 @@ -/* linux/arch/arm/mach-s3c2416/clock.c - * - * Copyright (c) 2010 Simtec Electronics - * Copyright (c) 2010 Ben Dooks - * - * S3C2416 Clock control support - * - * 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. - */ - -#include -#include - -#include -#include -#include - -#include -#include - -#include - -#include -#include - -/* armdiv - * - * this clock is sourced from msysclk and can have a number of - * divider values applied to it to then be fed into armclk. - * The real clock definition is done in s3c2443-clock.c, - * only the armdiv divisor table must be defined here. -*/ - -static unsigned int armdiv[8] = { - [0] = 1, - [1] = 2, - [2] = 3, - [3] = 4, - [5] = 6, - [7] = 8, -}; - -static struct clksrc_clk hsspi_eplldiv = { - .clk = { - .name = "hsspi-eplldiv", - .parent = &clk_esysclk.clk, - .ctrlbit = (1 << 14), - .enable = s3c2443_clkcon_enable_s, - }, - .reg_div = { .reg = S3C2443_CLKDIV1, .size = 2, .shift = 24 }, -}; - -static struct clk *hsspi_sources[] = { - [0] = &hsspi_eplldiv.clk, - [1] = NULL, /* to fix */ -}; - -static struct clksrc_clk hsspi_mux = { - .clk = { - .name = "hsspi-if", - }, - .sources = &(struct clksrc_sources) { - .sources = hsspi_sources, - .nr_sources = ARRAY_SIZE(hsspi_sources), - }, - .reg_src = { .reg = S3C2443_CLKSRC, .size = 1, .shift = 18 }, -}; - -static struct clksrc_clk hsmmc_div[] = { - [0] = { - .clk = { - .name = "hsmmc-div", - .devname = "s3c-sdhci.0", - .parent = &clk_esysclk.clk, - }, - .reg_div = { .reg = S3C2416_CLKDIV2, .size = 2, .shift = 6 }, - }, - [1] = { - .clk = { - .name = "hsmmc-div", - .devname = "s3c-sdhci.1", - .parent = &clk_esysclk.clk, - }, - .reg_div = { .reg = S3C2443_CLKDIV1, .size = 2, .shift = 6 }, - }, -}; - -static struct clksrc_clk hsmmc_mux0 = { - .clk = { - .name = "hsmmc-if", - .devname = "s3c-sdhci.0", - .ctrlbit = (1 << 6), - .enable = s3c2443_clkcon_enable_s, - }, - .sources = &(struct clksrc_sources) { - .nr_sources = 2, - .sources = (struct clk * []) { - [0] = &hsmmc_div[0].clk, - [1] = NULL, /* to fix */ - }, - }, - .reg_src = { .reg = S3C2443_CLKSRC, .size = 1, .shift = 16 }, -}; - -static struct clksrc_clk hsmmc_mux1 = { - .clk = { - .name = "hsmmc-if", - .devname = "s3c-sdhci.1", - .ctrlbit = (1 << 12), - .enable = s3c2443_clkcon_enable_s, - }, - .sources = &(struct clksrc_sources) { - .nr_sources = 2, - .sources = (struct clk * []) { - [0] = &hsmmc_div[1].clk, - [1] = NULL, /* to fix */ - }, - }, - .reg_src = { .reg = S3C2443_CLKSRC, .size = 1, .shift = 17 }, -}; - -static struct clk hsmmc0_clk = { - .name = "hsmmc", - .devname = "s3c-sdhci.0", - .parent = &clk_h, - .enable = s3c2443_clkcon_enable_h, - .ctrlbit = S3C2416_HCLKCON_HSMMC0, -}; - -static struct clksrc_clk *clksrcs[] __initdata = { - &hsspi_eplldiv, - &hsspi_mux, - &hsmmc_div[0], - &hsmmc_div[1], - &hsmmc_mux0, - &hsmmc_mux1, -}; - -static struct clk_lookup s3c2416_clk_lookup[] = { - CLKDEV_INIT("s3c-sdhci.0", "mmc_busclk.0", &hsmmc0_clk), - CLKDEV_INIT("s3c-sdhci.0", "mmc_busclk.2", &hsmmc_mux0.clk), - CLKDEV_INIT("s3c-sdhci.1", "mmc_busclk.2", &hsmmc_mux1.clk), - /* s3c2443-spi.0 is used on s3c2416 and s3c2450 as well */ - CLKDEV_INIT("s3c2443-spi.0", "spi_busclk2", &hsspi_mux.clk), -}; - -void __init s3c2416_init_clocks(int xtal) -{ - u32 epllcon = __raw_readl(S3C2443_EPLLCON); - u32 epllcon1 = __raw_readl(S3C2443_EPLLCON+4); - int ptr; - - /* s3c2416 EPLL compatible with s3c64xx */ - clk_epll.rate = s3c_get_pll6553x(xtal, epllcon, epllcon1); - - clk_epll.parent = &clk_epllref.clk; - - s3c2443_common_init_clocks(xtal, s3c2416_get_pll, - armdiv, ARRAY_SIZE(armdiv), - S3C2416_CLKDIV0_ARMDIV_MASK); - - for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++) - s3c_register_clksrc(clksrcs[ptr], 1); - - s3c24xx_register_clock(&hsmmc0_clk); - clkdev_add_table(s3c2416_clk_lookup, ARRAY_SIZE(s3c2416_clk_lookup)); - -} diff --git a/arch/arm/mach-s3c24xx/clock-s3c2443.c b/arch/arm/mach-s3c24xx/clock-s3c2443.c deleted file mode 100644 index 76cd31f7804e..000000000000 --- a/arch/arm/mach-s3c24xx/clock-s3c2443.c +++ /dev/null @@ -1,212 +0,0 @@ -/* linux/arch/arm/mach-s3c2443/clock.c - * - * Copyright (c) 2007, 2010 Simtec Electronics - * Ben Dooks - * - * S3C2443 Clock control support - * - * 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 - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -#include - -#include - -#include -#include -#include - -/* We currently have to assume that the system is running - * from the XTPll input, and that all ***REFCLKs are being - * fed from it, as we cannot read the state of OM[4] from - * software. - * - * It would be possible for each board initialisation to - * set the correct muxing at initialisation -*/ - -/* clock selections */ - -/* armdiv - * - * this clock is sourced from msysclk and can have a number of - * divider values applied to it to then be fed into armclk. - * The real clock definition is done in s3c2443-clock.c, - * only the armdiv divisor table must be defined here. -*/ - -static unsigned int armdiv[16] = { - [S3C2443_CLKDIV0_ARMDIV_1 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 1, - [S3C2443_CLKDIV0_ARMDIV_2 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 2, - [S3C2443_CLKDIV0_ARMDIV_3 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 3, - [S3C2443_CLKDIV0_ARMDIV_4 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 4, - [S3C2443_CLKDIV0_ARMDIV_6 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 6, - [S3C2443_CLKDIV0_ARMDIV_8 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 8, - [S3C2443_CLKDIV0_ARMDIV_12 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 12, - [S3C2443_CLKDIV0_ARMDIV_16 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 16, -}; - -/* hsspi - * - * high-speed spi clock, sourced from esysclk -*/ - -static struct clksrc_clk clk_hsspi = { - .clk = { - .name = "hsspi-if", - .parent = &clk_esysclk.clk, - .ctrlbit = S3C2443_SCLKCON_HSSPICLK, - .enable = s3c2443_clkcon_enable_s, - }, - .reg_div = { .reg = S3C2443_CLKDIV1, .size = 2, .shift = 4 }, -}; - - -/* clk_hsmcc_div - * - * this clock is sourced from epll, and is fed through a divider, - * to a mux controlled by sclkcon where either it or a extclk can - * be fed to the hsmmc block -*/ - -static struct clksrc_clk clk_hsmmc_div = { - .clk = { - .name = "hsmmc-div", - .devname = "s3c-sdhci.1", - .parent = &clk_esysclk.clk, - }, - .reg_div = { .reg = S3C2443_CLKDIV1, .size = 2, .shift = 6 }, -}; - -static int s3c2443_setparent_hsmmc(struct clk *clk, struct clk *parent) -{ - unsigned long clksrc = __raw_readl(S3C2443_SCLKCON); - - clksrc &= ~(S3C2443_SCLKCON_HSMMCCLK_EXT | - S3C2443_SCLKCON_HSMMCCLK_EPLL); - - if (parent == &clk_epll) - clksrc |= S3C2443_SCLKCON_HSMMCCLK_EPLL; - else if (parent == &clk_ext) - clksrc |= S3C2443_SCLKCON_HSMMCCLK_EXT; - else - return -EINVAL; - - if (clk->usage > 0) { - __raw_writel(clksrc, S3C2443_SCLKCON); - } - - clk->parent = parent; - return 0; -} - -static int s3c2443_enable_hsmmc(struct clk *clk, int enable) -{ - return s3c2443_setparent_hsmmc(clk, clk->parent); -} - -static struct clk clk_hsmmc = { - .name = "hsmmc-if", - .devname = "s3c-sdhci.1", - .parent = &clk_hsmmc_div.clk, - .enable = s3c2443_enable_hsmmc, - .ops = &(struct clk_ops) { - .set_parent = s3c2443_setparent_hsmmc, - }, -}; - -/* standard clock definitions */ - -static struct clk init_clocks_off[] = { - { - .name = "sdi", - .parent = &clk_p, - .enable = s3c2443_clkcon_enable_p, - .ctrlbit = S3C2443_PCLKCON_SDI, - }, { - .name = "spi", - .devname = "s3c2410-spi.0", - .parent = &clk_p, - .enable = s3c2443_clkcon_enable_p, - .ctrlbit = S3C2443_PCLKCON_SPI1, - } -}; - -/* clocks to add straight away */ - -static struct clksrc_clk *clksrcs[] __initdata = { - &clk_hsspi, - &clk_hsmmc_div, -}; - -static struct clk *clks[] __initdata = { - &clk_hsmmc, -}; - -static struct clk_lookup s3c2443_clk_lookup[] = { - CLKDEV_INIT("s3c-sdhci.1", "mmc_busclk.2", &clk_hsmmc), - CLKDEV_INIT("s3c2443-spi.0", "spi_busclk2", &clk_hsspi.clk), -}; - -void __init s3c2443_init_clocks(int xtal) -{ - unsigned long epllcon = __raw_readl(S3C2443_EPLLCON); - int ptr; - - clk_epll.rate = s3c2443_get_epll(epllcon, xtal); - clk_epll.parent = &clk_epllref.clk; - - s3c2443_common_init_clocks(xtal, s3c2443_get_mpll, - armdiv, ARRAY_SIZE(armdiv), - S3C2443_CLKDIV0_ARMDIV_MASK); - - s3c24xx_register_clocks(clks, ARRAY_SIZE(clks)); - - for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++) - s3c_register_clksrc(clksrcs[ptr], 1); - - /* We must be careful disabling the clocks we are not intending to - * be using at boot time, as subsystems such as the LCD which do - * their own DMA requests to the bus can cause the system to lockup - * if they where in the middle of requesting bus access. - * - * Disabling the LCD clock if the LCD is active is very dangerous, - * and therefore the bootloader should be careful to not enable - * the LCD clock if it is not needed. - */ - - /* install (and disable) the clocks we do not need immediately */ - - s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off)); - s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off)); - clkdev_add_table(s3c2443_clk_lookup, ARRAY_SIZE(s3c2443_clk_lookup)); -} diff --git a/arch/arm/mach-s3c24xx/common-s3c2443.c b/arch/arm/mach-s3c24xx/common-s3c2443.c deleted file mode 100644 index 65d3eef73090..000000000000 --- a/arch/arm/mach-s3c24xx/common-s3c2443.c +++ /dev/null @@ -1,675 +0,0 @@ -/* - * Common code for SoCs starting with the S3C2443 - * - * Copyright (c) 2007, 2010 Simtec Electronics - * Ben Dooks - * - * 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. - */ - -#include -#include -#include - -#include - -#include -#include -#include - -#include - - -static int s3c2443_gate(void __iomem *reg, struct clk *clk, int enable) -{ - u32 ctrlbit = clk->ctrlbit; - u32 con = __raw_readl(reg); - - if (enable) - con |= ctrlbit; - else - con &= ~ctrlbit; - - __raw_writel(con, reg); - return 0; -} - -int s3c2443_clkcon_enable_h(struct clk *clk, int enable) -{ - return s3c2443_gate(S3C2443_HCLKCON, clk, enable); -} - -int s3c2443_clkcon_enable_p(struct clk *clk, int enable) -{ - return s3c2443_gate(S3C2443_PCLKCON, clk, enable); -} - -int s3c2443_clkcon_enable_s(struct clk *clk, int enable) -{ - return s3c2443_gate(S3C2443_SCLKCON, clk, enable); -} - -/* mpllref is a direct descendant of clk_xtal by default, but it is not - * elided as the EPLL can be either sourced by the XTAL or EXTCLK and as - * such directly equating the two source clocks is impossible. - */ -static struct clk clk_mpllref = { - .name = "mpllref", - .parent = &clk_xtal, -}; - -static struct clk *clk_epllref_sources[] = { - [0] = &clk_mpllref, - [1] = &clk_mpllref, - [2] = &clk_xtal, - [3] = &clk_ext, -}; - -struct clksrc_clk clk_epllref = { - .clk = { - .name = "epllref", - }, - .sources = &(struct clksrc_sources) { - .sources = clk_epllref_sources, - .nr_sources = ARRAY_SIZE(clk_epllref_sources), - }, - .reg_src = { .reg = S3C2443_CLKSRC, .size = 2, .shift = 7 }, -}; - -/* esysclk - * - * this is sourced from either the EPLL or the EPLLref clock -*/ - -static struct clk *clk_sysclk_sources[] = { - [0] = &clk_epllref.clk, - [1] = &clk_epll, -}; - -struct clksrc_clk clk_esysclk = { - .clk = { - .name = "esysclk", - .parent = &clk_epll, - }, - .sources = &(struct clksrc_sources) { - .sources = clk_sysclk_sources, - .nr_sources = ARRAY_SIZE(clk_sysclk_sources), - }, - .reg_src = { .reg = S3C2443_CLKSRC, .size = 1, .shift = 6 }, -}; - -static unsigned long s3c2443_getrate_mdivclk(struct clk *clk) -{ - unsigned long parent_rate = clk_get_rate(clk->parent); - unsigned long div = __raw_readl(S3C2443_CLKDIV0); - - div &= S3C2443_CLKDIV0_EXTDIV_MASK; - div >>= (S3C2443_CLKDIV0_EXTDIV_SHIFT-1); /* x2 */ - - return parent_rate / (div + 1); -} - -static struct clk clk_mdivclk = { - .name = "mdivclk", - .parent = &clk_mpllref, - .ops = &(struct clk_ops) { - .get_rate = s3c2443_getrate_mdivclk, - }, -}; - -static struct clk *clk_msysclk_sources[] = { - [0] = &clk_mpllref, - [1] = &clk_mpll, - [2] = &clk_mdivclk, - [3] = &clk_mpllref, -}; - -static struct clksrc_clk clk_msysclk = { - .clk = { - .name = "msysclk", - .parent = &clk_xtal, - }, - .sources = &(struct clksrc_sources) { - .sources = clk_msysclk_sources, - .nr_sources = ARRAY_SIZE(clk_msysclk_sources), - }, - .reg_src = { .reg = S3C2443_CLKSRC, .size = 2, .shift = 3 }, -}; - -/* prediv - * - * this divides the msysclk down to pass to h/p/etc. - */ - -static unsigned long s3c2443_prediv_getrate(struct clk *clk) -{ - unsigned long rate = clk_get_rate(clk->parent); - unsigned long clkdiv0 = __raw_readl(S3C2443_CLKDIV0); - - clkdiv0 &= S3C2443_CLKDIV0_PREDIV_MASK; - clkdiv0 >>= S3C2443_CLKDIV0_PREDIV_SHIFT; - - return rate / (clkdiv0 + 1); -} - -static struct clk clk_prediv = { - .name = "prediv", - .parent = &clk_msysclk.clk, - .ops = &(struct clk_ops) { - .get_rate = s3c2443_prediv_getrate, - }, -}; - -/* hclk divider - * - * divides the prediv and provides the hclk. - */ - -static unsigned long s3c2443_hclkdiv_getrate(struct clk *clk) -{ - unsigned long rate = clk_get_rate(clk->parent); - unsigned long clkdiv0 = __raw_readl(S3C2443_CLKDIV0); - - clkdiv0 &= S3C2443_CLKDIV0_HCLKDIV_MASK; - - return rate / (clkdiv0 + 1); -} - -static struct clk_ops clk_h_ops = { - .get_rate = s3c2443_hclkdiv_getrate, -}; - -/* pclk divider - * - * divides the hclk and provides the pclk. - */ - -static unsigned long s3c2443_pclkdiv_getrate(struct clk *clk) -{ - unsigned long rate = clk_get_rate(clk->parent); - unsigned long clkdiv0 = __raw_readl(S3C2443_CLKDIV0); - - clkdiv0 = ((clkdiv0 & S3C2443_CLKDIV0_HALF_PCLK) ? 1 : 0); - - return rate / (clkdiv0 + 1); -} - -static struct clk_ops clk_p_ops = { - .get_rate = s3c2443_pclkdiv_getrate, -}; - -/* armdiv - * - * this clock is sourced from msysclk and can have a number of - * divider values applied to it to then be fed into armclk. -*/ - -static unsigned int *armdiv; -static int nr_armdiv; -static int armdivmask; - -static unsigned long s3c2443_armclk_roundrate(struct clk *clk, - unsigned long rate) -{ - unsigned long parent = clk_get_rate(clk->parent); - unsigned long calc; - unsigned best = 256; /* bigger than any value */ - unsigned div; - int ptr; - - if (!nr_armdiv) - return -EINVAL; - - for (ptr = 0; ptr < nr_armdiv; ptr++) { - div = armdiv[ptr]; - if (div) { - /* cpufreq provides 266mhz as 266666000 not 266666666 */ - calc = (parent / div / 1000) * 1000; - if (calc <= rate && div < best) - best = div; - } - } - - return parent / best; -} - -static unsigned long s3c2443_armclk_getrate(struct clk *clk) -{ - unsigned long rate = clk_get_rate(clk->parent); - unsigned long clkcon0; - int val; - - if (!nr_armdiv || !armdivmask) - return -EINVAL; - - clkcon0 = __raw_readl(S3C2443_CLKDIV0); - clkcon0 &= armdivmask; - val = clkcon0 >> S3C2443_CLKDIV0_ARMDIV_SHIFT; - - return rate / armdiv[val]; -} - -static int s3c2443_armclk_setrate(struct clk *clk, unsigned long rate) -{ - unsigned long parent = clk_get_rate(clk->parent); - unsigned long calc; - unsigned div; - unsigned best = 256; /* bigger than any value */ - int ptr; - int val = -1; - - if (!nr_armdiv || !armdivmask) - return -EINVAL; - - for (ptr = 0; ptr < nr_armdiv; ptr++) { - div = armdiv[ptr]; - if (div) { - /* cpufreq provides 266mhz as 266666000 not 266666666 */ - calc = (parent / div / 1000) * 1000; - if (calc <= rate && div < best) { - best = div; - val = ptr; - } - } - } - - if (val >= 0) { - unsigned long clkcon0; - - clkcon0 = __raw_readl(S3C2443_CLKDIV0); - clkcon0 &= ~armdivmask; - clkcon0 |= val << S3C2443_CLKDIV0_ARMDIV_SHIFT; - __raw_writel(clkcon0, S3C2443_CLKDIV0); - } - - return (val == -1) ? -EINVAL : 0; -} - -static struct clk clk_armdiv = { - .name = "armdiv", - .parent = &clk_msysclk.clk, - .ops = &(struct clk_ops) { - .round_rate = s3c2443_armclk_roundrate, - .get_rate = s3c2443_armclk_getrate, - .set_rate = s3c2443_armclk_setrate, - }, -}; - -/* armclk - * - * this is the clock fed into the ARM core itself, from armdiv or from hclk. - */ - -static struct clk *clk_arm_sources[] = { - [0] = &clk_armdiv, - [1] = &clk_h, -}; - -static struct clksrc_clk clk_arm = { - .clk = { - .name = "armclk", - }, - .sources = &(struct clksrc_sources) { - .sources = clk_arm_sources, - .nr_sources = ARRAY_SIZE(clk_arm_sources), - }, - .reg_src = { .reg = S3C2443_CLKDIV0, .size = 1, .shift = 13 }, -}; - -/* usbhost - * - * usb host bus-clock, usually 48MHz to provide USB bus clock timing -*/ - -static struct clksrc_clk clk_usb_bus_host = { - .clk = { - .name = "usb-bus-host-parent", - .parent = &clk_esysclk.clk, - .ctrlbit = S3C2443_SCLKCON_USBHOST, - .enable = s3c2443_clkcon_enable_s, - }, - .reg_div = { .reg = S3C2443_CLKDIV1, .size = 2, .shift = 4 }, -}; - -/* common clksrc clocks */ - -static struct clksrc_clk clksrc_clks[] = { - { - /* camera interface bus-clock, divided down from esysclk */ - .clk = { - .name = "camif-upll", /* same as 2440 name */ - .parent = &clk_esysclk.clk, - .ctrlbit = S3C2443_SCLKCON_CAMCLK, - .enable = s3c2443_clkcon_enable_s, - }, - .reg_div = { .reg = S3C2443_CLKDIV1, .size = 4, .shift = 26 }, - }, { - .clk = { - .name = "display-if", - .parent = &clk_esysclk.clk, - .ctrlbit = S3C2443_SCLKCON_DISPCLK, - .enable = s3c2443_clkcon_enable_s, - }, - .reg_div = { .reg = S3C2443_CLKDIV1, .size = 8, .shift = 16 }, - }, -}; - -static struct clksrc_clk clk_esys_uart = { - /* ART baud-rate clock sourced from esysclk via a divisor */ - .clk = { - .name = "uartclk", - .parent = &clk_esysclk.clk, - }, - .reg_div = { .reg = S3C2443_CLKDIV1, .size = 4, .shift = 8 }, -}; - -static struct clk clk_i2s_ext = { - .name = "i2s-ext", -}; - -/* i2s_eplldiv - * - * This clock is the output from the I2S divisor of ESYSCLK, and is separate - * from the mux that comes after it (cannot merge into one single clock) -*/ - -static struct clksrc_clk clk_i2s_eplldiv = { - .clk = { - .name = "i2s-eplldiv", - .parent = &clk_esysclk.clk, - }, - .reg_div = { .reg = S3C2443_CLKDIV1, .size = 4, .shift = 12, }, -}; - -/* i2s-ref - * - * i2s bus reference clock, selectable from external, esysclk or epllref - * - * Note, this used to be two clocks, but was compressed into one. -*/ - -static struct clk *clk_i2s_srclist[] = { - [0] = &clk_i2s_eplldiv.clk, - [1] = &clk_i2s_ext, - [2] = &clk_epllref.clk, - [3] = &clk_epllref.clk, -}; - -static struct clksrc_clk clk_i2s = { - .clk = { - .name = "i2s-if", - .ctrlbit = S3C2443_SCLKCON_I2SCLK, - .enable = s3c2443_clkcon_enable_s, - - }, - .sources = &(struct clksrc_sources) { - .sources = clk_i2s_srclist, - .nr_sources = ARRAY_SIZE(clk_i2s_srclist), - }, - .reg_src = { .reg = S3C2443_CLKSRC, .size = 2, .shift = 14 }, -}; - -static struct clk init_clocks_off[] = { - { - .name = "iis", - .parent = &clk_p, - .enable = s3c2443_clkcon_enable_p, - .ctrlbit = S3C2443_PCLKCON_IIS, - }, { - .name = "adc", - .parent = &clk_p, - .enable = s3c2443_clkcon_enable_p, - .ctrlbit = S3C2443_PCLKCON_ADC, - }, { - .name = "i2c", - .parent = &clk_p, - .enable = s3c2443_clkcon_enable_p, - .ctrlbit = S3C2443_PCLKCON_IIC, - } -}; - -static struct clk init_clocks[] = { - { - .name = "dma.0", - .parent = &clk_h, - .enable = s3c2443_clkcon_enable_h, - .ctrlbit = S3C2443_HCLKCON_DMA0, - }, { - .name = "dma.1", - .parent = &clk_h, - .enable = s3c2443_clkcon_enable_h, - .ctrlbit = S3C2443_HCLKCON_DMA1, - }, { - .name = "dma.2", - .parent = &clk_h, - .enable = s3c2443_clkcon_enable_h, - .ctrlbit = S3C2443_HCLKCON_DMA2, - }, { - .name = "dma.3", - .parent = &clk_h, - .enable = s3c2443_clkcon_enable_h, - .ctrlbit = S3C2443_HCLKCON_DMA3, - }, { - .name = "dma.4", - .parent = &clk_h, - .enable = s3c2443_clkcon_enable_h, - .ctrlbit = S3C2443_HCLKCON_DMA4, - }, { - .name = "dma.5", - .parent = &clk_h, - .enable = s3c2443_clkcon_enable_h, - .ctrlbit = S3C2443_HCLKCON_DMA5, - }, { - .name = "gpio", - .parent = &clk_p, - .enable = s3c2443_clkcon_enable_p, - .ctrlbit = S3C2443_PCLKCON_GPIO, - }, { - .name = "usb-host", - .parent = &clk_h, - .enable = s3c2443_clkcon_enable_h, - .ctrlbit = S3C2443_HCLKCON_USBH, - }, { - .name = "usb-device", - .parent = &clk_h, - .enable = s3c2443_clkcon_enable_h, - .ctrlbit = S3C2443_HCLKCON_USBD, - }, { - .name = "lcd", - .parent = &clk_h, - .enable = s3c2443_clkcon_enable_h, - .ctrlbit = S3C2443_HCLKCON_LCDC, - - }, { - .name = "timers", - .parent = &clk_p, - .enable = s3c2443_clkcon_enable_p, - .ctrlbit = S3C2443_PCLKCON_PWMT, - }, { - .name = "cfc", - .parent = &clk_h, - .enable = s3c2443_clkcon_enable_h, - .ctrlbit = S3C2443_HCLKCON_CFC, - }, { - .name = "ssmc", - .parent = &clk_h, - .enable = s3c2443_clkcon_enable_h, - .ctrlbit = S3C2443_HCLKCON_SSMC, - }, { - .name = "uart", - .devname = "s3c2440-uart.0", - .parent = &clk_p, - .enable = s3c2443_clkcon_enable_p, - .ctrlbit = S3C2443_PCLKCON_UART0, - }, { - .name = "uart", - .devname = "s3c2440-uart.1", - .parent = &clk_p, - .enable = s3c2443_clkcon_enable_p, - .ctrlbit = S3C2443_PCLKCON_UART1, - }, { - .name = "uart", - .devname = "s3c2440-uart.2", - .parent = &clk_p, - .enable = s3c2443_clkcon_enable_p, - .ctrlbit = S3C2443_PCLKCON_UART2, - }, { - .name = "uart", - .devname = "s3c2440-uart.3", - .parent = &clk_p, - .enable = s3c2443_clkcon_enable_p, - .ctrlbit = S3C2443_PCLKCON_UART3, - }, { - .name = "rtc", - .parent = &clk_p, - .enable = s3c2443_clkcon_enable_p, - .ctrlbit = S3C2443_PCLKCON_RTC, - }, { - .name = "watchdog", - .parent = &clk_p, - .ctrlbit = S3C2443_PCLKCON_WDT, - }, { - .name = "ac97", - .parent = &clk_p, - .ctrlbit = S3C2443_PCLKCON_AC97, - }, { - .name = "nand", - .parent = &clk_h, - }, { - .name = "usb-bus-host", - .parent = &clk_usb_bus_host.clk, - } -}; - -static struct clk hsmmc1_clk = { - .name = "hsmmc", - .devname = "s3c-sdhci.1", - .parent = &clk_h, - .enable = s3c2443_clkcon_enable_h, - .ctrlbit = S3C2443_HCLKCON_HSMMC, -}; - -static struct clk hsspi_clk = { - .name = "spi", - .devname = "s3c2443-spi.0", - .parent = &clk_p, - .enable = s3c2443_clkcon_enable_p, - .ctrlbit = S3C2443_PCLKCON_HSSPI, -}; - -/* EPLLCON compatible enough to get on/off information */ - -void __init_or_cpufreq s3c2443_common_setup_clocks(pll_fn get_mpll) -{ - unsigned long epllcon = __raw_readl(S3C2443_EPLLCON); - unsigned long mpllcon = __raw_readl(S3C2443_MPLLCON); - struct clk *xtal_clk; - unsigned long xtal; - unsigned long pll; - int ptr; - - xtal_clk = clk_get(NULL, "xtal"); - xtal = clk_get_rate(xtal_clk); - clk_put(xtal_clk); - - pll = get_mpll(mpllcon, xtal); - clk_msysclk.clk.rate = pll; - clk_mpll.rate = pll; - - printk("CPU: MPLL %s %ld.%03ld MHz, cpu %ld.%03ld MHz, mem %ld.%03ld MHz, pclk %ld.%03ld MHz\n", - (mpllcon & S3C2443_PLLCON_OFF) ? "off" : "on", - print_mhz(pll), print_mhz(clk_get_rate(&clk_armdiv)), - print_mhz(clk_get_rate(&clk_h)), - print_mhz(clk_get_rate(&clk_p))); - - for (ptr = 0; ptr < ARRAY_SIZE(clksrc_clks); ptr++) - s3c_set_clksrc(&clksrc_clks[ptr], true); - - /* ensure usb bus clock is within correct rate of 48MHz */ - - if (clk_get_rate(&clk_usb_bus_host.clk) != (48 * 1000 * 1000)) { - printk(KERN_INFO "Warning: USB host bus not at 48MHz\n"); - clk_set_rate(&clk_usb_bus_host.clk, 48*1000*1000); - } - - printk("CPU: EPLL %s %ld.%03ld MHz, usb-bus %ld.%03ld MHz\n", - (epllcon & S3C2443_PLLCON_OFF) ? "off" : "on", - print_mhz(clk_get_rate(&clk_epll)), - print_mhz(clk_get_rate(&clk_usb_bus))); -} - -static struct clk *clks[] __initdata = { - &clk_prediv, - &clk_mpllref, - &clk_mdivclk, - &clk_ext, - &clk_epll, - &clk_usb_bus, - &clk_armdiv, - &hsmmc1_clk, - &hsspi_clk, -}; - -static struct clksrc_clk *clksrcs[] __initdata = { - &clk_i2s_eplldiv, - &clk_i2s, - &clk_usb_bus_host, - &clk_epllref, - &clk_esysclk, - &clk_msysclk, - &clk_arm, -}; - -static struct clk_lookup s3c2443_clk_lookup[] = { - CLKDEV_INIT(NULL, "clk_uart_baud1", &s3c24xx_uclk), - CLKDEV_INIT(NULL, "clk_uart_baud2", &clk_p), - CLKDEV_INIT(NULL, "clk_uart_baud3", &clk_esys_uart.clk), - CLKDEV_INIT("s3c-sdhci.1", "mmc_busclk.0", &hsmmc1_clk), - CLKDEV_INIT("s3c2443-spi.0", "spi_busclk0", &hsspi_clk), -}; - -void __init s3c2443_common_init_clocks(int xtal, pll_fn get_mpll, - unsigned int *divs, int nr_divs, - int divmask) -{ - int ptr; - - armdiv = divs; - nr_armdiv = nr_divs; - armdivmask = divmask; - - /* s3c2443 parents h clock from prediv */ - clk_h.parent = &clk_prediv; - clk_h.ops = &clk_h_ops; - - /* and p clock from h clock */ - clk_p.parent = &clk_h; - clk_p.ops = &clk_p_ops; - - clk_usb_bus.parent = &clk_usb_bus_host.clk; - clk_epll.parent = &clk_epllref.clk; - - s3c24xx_register_baseclocks(xtal); - s3c24xx_register_clocks(clks, ARRAY_SIZE(clks)); - - for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++) - s3c_register_clksrc(clksrcs[ptr], 1); - - s3c_register_clksrc(clksrc_clks, ARRAY_SIZE(clksrc_clks)); - s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks)); - - /* See s3c2443/etc notes on disabling clocks at init time */ - s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off)); - s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off)); - clkdev_add_table(s3c2443_clk_lookup, ARRAY_SIZE(s3c2443_clk_lookup)); - - s3c2443_common_setup_clocks(get_mpll); -} diff --git a/arch/arm/mach-s3c24xx/common.c b/arch/arm/mach-s3c24xx/common.c index 0fc6641ac57d..412ca006fcce 100644 --- a/arch/arm/mach-s3c24xx/common.c +++ b/arch/arm/mach-s3c24xx/common.c @@ -145,7 +145,6 @@ static struct cpu_table cpu_ids[] __initdata = { .idcode = 0x32450003, .idmask = 0xffffffff, .map_io = s3c2416_map_io, - .init_clocks = s3c2416_init_clocks, .init_uarts = s3c2416_init_uarts, .init = s3c2416_init, .name = name_s3c2416, @@ -154,7 +153,6 @@ static struct cpu_table cpu_ids[] __initdata = { .idcode = 0x32443001, .idmask = 0xffffffff, .map_io = s3c2443_map_io, - .init_clocks = s3c2443_init_clocks, .init_uarts = s3c2443_init_uarts, .init = s3c2443_init, .name = name_s3c2443, @@ -536,3 +534,17 @@ struct platform_device s3c2443_device_dma = { }, }; #endif + +#ifdef CONFIG_CPU_S3C2416 +void __init s3c2416_init_clocks(int xtal) +{ + s3c2443_common_clk_init(NULL, xtal, 0, S3C24XX_VA_CLKPWR); +} +#endif + +#ifdef CONFIG_CPU_S3C2443 +void __init s3c2443_init_clocks(int xtal) +{ + s3c2443_common_clk_init(NULL, xtal, 1, S3C24XX_VA_CLKPWR); +} +#endif diff --git a/arch/arm/mach-s3c24xx/common.h b/arch/arm/mach-s3c24xx/common.h index e46c10417216..d7323f16427f 100644 --- a/arch/arm/mach-s3c24xx/common.h +++ b/arch/arm/mach-s3c24xx/common.h @@ -114,4 +114,10 @@ extern struct platform_device s3c2412_device_dma; extern struct platform_device s3c2440_device_dma; extern struct platform_device s3c2443_device_dma; +#ifdef CONFIG_S3C2443_COMMON_CLK +void __init s3c2443_common_clk_init(struct device_node *np, unsigned long xti_f, + int current_soc, + void __iomem *reg_base); +#endif + #endif /* __ARCH_ARM_MACH_S3C24XX_COMMON_H */ diff --git a/arch/arm/mach-s3c24xx/mach-s3c2416-dt.c b/arch/arm/mach-s3c24xx/mach-s3c2416-dt.c index 70f0900d4bca..e4dcb9aa2ca2 100644 --- a/arch/arm/mach-s3c24xx/mach-s3c2416-dt.c +++ b/arch/arm/mach-s3c24xx/mach-s3c2416-dt.c @@ -18,7 +18,6 @@ #include #include #include -#include #include #include @@ -29,48 +28,14 @@ #include "common.h" -/* - * The following lookup table is used to override device names when devices - * are registered from device tree. This is temporarily added to enable - * device tree support addition for the S3C2416 architecture. - * - * For drivers that require platform data to be provided from the machine - * file, a platform data pointer can also be supplied along with the - * devices names. Usually, the platform data elements that cannot be parsed - * from the device tree by the drivers (example: function pointers) are - * supplied. But it should be noted that this is a temporary mechanism and - * at some point, the drivers should be capable of parsing all the platform - * data from the device tree. - */ -static const struct of_dev_auxdata s3c2416_auxdata_lookup[] __initconst = { - OF_DEV_AUXDATA("samsung,s3c2440-uart", S3C24XX_PA_UART, - "s3c2440-uart.0", NULL), - OF_DEV_AUXDATA("samsung,s3c2440-uart", S3C24XX_PA_UART + 0x4000, - "s3c2440-uart.1", NULL), - OF_DEV_AUXDATA("samsung,s3c2440-uart", S3C24XX_PA_UART + 0x8000, - "s3c2440-uart.2", NULL), - OF_DEV_AUXDATA("samsung,s3c2440-uart", S3C24XX_PA_UART + 0xC000, - "s3c2440-uart.3", NULL), - OF_DEV_AUXDATA("samsung,s3c6410-sdhci", S3C_PA_HSMMC0, - "s3c-sdhci.0", NULL), - OF_DEV_AUXDATA("samsung,s3c6410-sdhci", S3C_PA_HSMMC1, - "s3c-sdhci.1", NULL), - OF_DEV_AUXDATA("samsung,s3c2440-i2c", S3C_PA_IIC, - "s3c2440-i2c.0", NULL), - {}, -}; - static void __init s3c2416_dt_map_io(void) { s3c24xx_init_io(NULL, 0); - s3c24xx_init_clocks(12000000); } static void __init s3c2416_dt_machine_init(void) { - of_platform_populate(NULL, of_default_bus_match_table, - s3c2416_auxdata_lookup, NULL); - + of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); s3c_pm_init(); } @@ -86,6 +51,5 @@ DT_MACHINE_START(S3C2416_DT, "Samsung S3C2416 (Flattened Device Tree)") .map_io = s3c2416_dt_map_io, .init_irq = irqchip_init, .init_machine = s3c2416_dt_machine_init, - .init_time = clocksource_of_init, .restart = s3c2416_restart, MACHINE_END diff --git a/arch/arm/mach-s3c24xx/mach-smdk2416.c b/arch/arm/mach-s3c24xx/mach-smdk2416.c index b3b54d8e1410..fa6f30d23601 100644 --- a/arch/arm/mach-s3c24xx/mach-smdk2416.c +++ b/arch/arm/mach-s3c24xx/mach-smdk2416.c @@ -219,10 +219,15 @@ static struct platform_device *smdk2416_devices[] __initdata = { &s3c2443_device_dma, }; +static void __init smdk2416_init_time(void) +{ + s3c2416_init_clocks(12000000); + samsung_timer_init(); +} + static void __init smdk2416_map_io(void) { s3c24xx_init_io(smdk2416_iodesc, ARRAY_SIZE(smdk2416_iodesc)); - s3c24xx_init_clocks(12000000); s3c24xx_init_uarts(smdk2416_uartcfgs, ARRAY_SIZE(smdk2416_uartcfgs)); samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4); } @@ -257,6 +262,6 @@ MACHINE_START(SMDK2416, "SMDK2416") .init_irq = s3c2416_init_irq, .map_io = smdk2416_map_io, .init_machine = smdk2416_machine_init, - .init_time = samsung_timer_init, + .init_time = smdk2416_init_time, .restart = s3c2416_restart, MACHINE_END diff --git a/arch/arm/mach-s3c24xx/mach-smdk2443.c b/arch/arm/mach-s3c24xx/mach-smdk2443.c index 06c4d77de3a5..ef5d5ea33182 100644 --- a/arch/arm/mach-s3c24xx/mach-smdk2443.c +++ b/arch/arm/mach-s3c24xx/mach-smdk2443.c @@ -121,11 +121,16 @@ static struct platform_device *smdk2443_devices[] __initdata = { static void __init smdk2443_map_io(void) { s3c24xx_init_io(smdk2443_iodesc, ARRAY_SIZE(smdk2443_iodesc)); - s3c24xx_init_clocks(12000000); s3c24xx_init_uarts(smdk2443_uartcfgs, ARRAY_SIZE(smdk2443_uartcfgs)); samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4); } +static void __init smdk2443_init_time(void) +{ + s3c2443_init_clocks(12000000); + samsung_timer_init(); +} + static void __init smdk2443_machine_init(void) { s3c_i2c0_set_platdata(NULL); @@ -145,6 +150,6 @@ MACHINE_START(SMDK2443, "SMDK2443") .init_irq = s3c2443_init_irq, .map_io = smdk2443_map_io, .init_machine = smdk2443_machine_init, - .init_time = samsung_timer_init, + .init_time = smdk2443_init_time, .restart = s3c2443_restart, MACHINE_END From 42637c59f36198a58069f94676007c62477321b7 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Tue, 25 Feb 2014 09:50:43 +0900 Subject: [PATCH 13/87] ARM: S3C24XX: only store clock registers when old clock code is active The Samsung ccf driver already handles the save and restore of the clock registers on suspend and resume. The architecture code should not duplicate this when the ccf is active. Signed-off-by: Heiko Stuebner Reviewed-by: Tomasz Figa Signed-off-by: Kukjin Kim --- arch/arm/mach-s3c24xx/pm.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/arch/arm/mach-s3c24xx/pm.c b/arch/arm/mach-s3c24xx/pm.c index 68ea5b7e5dc7..16281bdc750a 100644 --- a/arch/arm/mach-s3c24xx/pm.c +++ b/arch/arm/mach-s3c24xx/pm.c @@ -51,9 +51,6 @@ #define PFX "s3c24xx-pm: " static struct sleep_save core_save[] = { - SAVE_ITEM(S3C2410_LOCKTIME), - SAVE_ITEM(S3C2410_CLKCON), - /* we restore the timings here, with the proviso that the board * brings the system up in an slower, or equal frequency setting * to the original system. @@ -70,6 +67,9 @@ static struct sleep_save core_save[] = { SAVE_ITEM(S3C2410_BANKCON4), SAVE_ITEM(S3C2410_BANKCON5), +#ifdef CONFIG_SAMSUNG_CLOCK + SAVE_ITEM(S3C2410_LOCKTIME), + SAVE_ITEM(S3C2410_CLKCON), #ifndef CONFIG_CPU_FREQ SAVE_ITEM(S3C2410_CLKDIVN), SAVE_ITEM(S3C2410_MPLLCON), @@ -77,11 +77,14 @@ static struct sleep_save core_save[] = { #endif SAVE_ITEM(S3C2410_UPLLCON), SAVE_ITEM(S3C2410_CLKSLOW), +#endif /* CONFIG_SAMSUNG_CLOCK */ }; +#ifdef CONFIG_SAMSUNG_CLOCK static struct sleep_save misc_save[] = { SAVE_ITEM(S3C2410_DCLKCON), }; +#endif /* s3c_pm_check_resume_pin * @@ -140,12 +143,16 @@ void s3c_pm_configure_extint(void) void s3c_pm_restore_core(void) { s3c_pm_do_restore_core(core_save, ARRAY_SIZE(core_save)); +#ifdef CONFIG_SAMSUNG_CLOCK s3c_pm_do_restore(misc_save, ARRAY_SIZE(misc_save)); +#endif } void s3c_pm_save_core(void) { +#ifdef CONFIG_SAMSUNG_CLOCK s3c_pm_do_save(misc_save, ARRAY_SIZE(misc_save)); +#endif s3c_pm_do_save(core_save, ARRAY_SIZE(core_save)); } From ea5d6a8d3ee606086118d3b4d4b3a49693e92960 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Tue, 25 Feb 2014 09:50:43 +0900 Subject: [PATCH 14/87] clk: samsung: add plls used by the early s3c24xx cpus The manuals do not give them explicit names like in later socs, so more generic names with a s3c2410-prefix were used for them. As it was common to do so in the previous implementation, functionality to change the pll rate is already included. Signed-off-by: Heiko Stuebner Acked-by: Mike Turquette Acked-by: Tomasz Figa Signed-off-by: Kukjin Kim --- drivers/clk/samsung/clk-pll.c | 182 ++++++++++++++++++++++++++++++++++ drivers/clk/samsung/clk-pll.h | 3 + 2 files changed, 185 insertions(+) diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c index 8c9c015a4538..7fb0a28e65d5 100644 --- a/drivers/clk/samsung/clk-pll.c +++ b/drivers/clk/samsung/clk-pll.c @@ -11,6 +11,7 @@ #include #include +#include #include "clk.h" #include "clk-pll.h" @@ -700,6 +701,169 @@ static const struct clk_ops samsung_pll6553_clk_ops = { .recalc_rate = samsung_pll6553_recalc_rate, }; +/* + * PLL Clock Type of S3C24XX before S3C2443 + */ + +#define PLLS3C2410_MDIV_MASK (0xff) +#define PLLS3C2410_PDIV_MASK (0x1f) +#define PLLS3C2410_SDIV_MASK (0x3) +#define PLLS3C2410_MDIV_SHIFT (12) +#define PLLS3C2410_PDIV_SHIFT (4) +#define PLLS3C2410_SDIV_SHIFT (0) + +#define PLLS3C2410_ENABLE_REG_OFFSET 0x10 + +static unsigned long samsung_s3c2410_pll_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct samsung_clk_pll *pll = to_clk_pll(hw); + u32 pll_con, mdiv, pdiv, sdiv; + u64 fvco = parent_rate; + + pll_con = __raw_readl(pll->con_reg); + mdiv = (pll_con >> PLLS3C2410_MDIV_SHIFT) & PLLS3C2410_MDIV_MASK; + pdiv = (pll_con >> PLLS3C2410_PDIV_SHIFT) & PLLS3C2410_PDIV_MASK; + sdiv = (pll_con >> PLLS3C2410_SDIV_SHIFT) & PLLS3C2410_SDIV_MASK; + + fvco *= (mdiv + 8); + do_div(fvco, (pdiv + 2) << sdiv); + + return (unsigned int)fvco; +} + +static unsigned long samsung_s3c2440_mpll_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct samsung_clk_pll *pll = to_clk_pll(hw); + u32 pll_con, mdiv, pdiv, sdiv; + u64 fvco = parent_rate; + + pll_con = __raw_readl(pll->con_reg); + mdiv = (pll_con >> PLLS3C2410_MDIV_SHIFT) & PLLS3C2410_MDIV_MASK; + pdiv = (pll_con >> PLLS3C2410_PDIV_SHIFT) & PLLS3C2410_PDIV_MASK; + sdiv = (pll_con >> PLLS3C2410_SDIV_SHIFT) & PLLS3C2410_SDIV_MASK; + + fvco *= (2 * (mdiv + 8)); + do_div(fvco, (pdiv + 2) << sdiv); + + return (unsigned int)fvco; +} + +static int samsung_s3c2410_pll_set_rate(struct clk_hw *hw, unsigned long drate, + unsigned long prate) +{ + struct samsung_clk_pll *pll = to_clk_pll(hw); + const struct samsung_pll_rate_table *rate; + u32 tmp; + + /* Get required rate settings from table */ + rate = samsung_get_pll_settings(pll, drate); + if (!rate) { + pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__, + drate, __clk_get_name(hw->clk)); + return -EINVAL; + } + + tmp = __raw_readl(pll->con_reg); + + /* Change PLL PMS values */ + tmp &= ~((PLLS3C2410_MDIV_MASK << PLLS3C2410_MDIV_SHIFT) | + (PLLS3C2410_PDIV_MASK << PLLS3C2410_PDIV_SHIFT) | + (PLLS3C2410_SDIV_MASK << PLLS3C2410_SDIV_SHIFT)); + tmp |= (rate->mdiv << PLLS3C2410_MDIV_SHIFT) | + (rate->pdiv << PLLS3C2410_PDIV_SHIFT) | + (rate->sdiv << PLLS3C2410_SDIV_SHIFT); + __raw_writel(tmp, pll->con_reg); + + /* Time to settle according to the manual */ + udelay(300); + + return 0; +} + +static int samsung_s3c2410_pll_enable(struct clk_hw *hw, int bit, bool enable) +{ + struct samsung_clk_pll *pll = to_clk_pll(hw); + u32 pll_en = __raw_readl(pll->lock_reg + PLLS3C2410_ENABLE_REG_OFFSET); + u32 pll_en_orig = pll_en; + + if (enable) + pll_en &= ~BIT(bit); + else + pll_en |= BIT(bit); + + __raw_writel(pll_en, pll->lock_reg + PLLS3C2410_ENABLE_REG_OFFSET); + + /* if we started the UPLL, then allow to settle */ + if (enable && (pll_en_orig & BIT(bit))) + udelay(300); + + return 0; +} + +static int samsung_s3c2410_mpll_enable(struct clk_hw *hw) +{ + return samsung_s3c2410_pll_enable(hw, 5, true); +} + +static void samsung_s3c2410_mpll_disable(struct clk_hw *hw) +{ + samsung_s3c2410_pll_enable(hw, 5, false); +} + +static int samsung_s3c2410_upll_enable(struct clk_hw *hw) +{ + return samsung_s3c2410_pll_enable(hw, 7, true); +} + +static void samsung_s3c2410_upll_disable(struct clk_hw *hw) +{ + samsung_s3c2410_pll_enable(hw, 7, false); +} + +static const struct clk_ops samsung_s3c2410_mpll_clk_min_ops = { + .recalc_rate = samsung_s3c2410_pll_recalc_rate, + .enable = samsung_s3c2410_mpll_enable, + .disable = samsung_s3c2410_mpll_disable, +}; + +static const struct clk_ops samsung_s3c2410_upll_clk_min_ops = { + .recalc_rate = samsung_s3c2410_pll_recalc_rate, + .enable = samsung_s3c2410_upll_enable, + .disable = samsung_s3c2410_upll_disable, +}; + +static const struct clk_ops samsung_s3c2440_mpll_clk_min_ops = { + .recalc_rate = samsung_s3c2440_mpll_recalc_rate, + .enable = samsung_s3c2410_mpll_enable, + .disable = samsung_s3c2410_mpll_disable, +}; + +static const struct clk_ops samsung_s3c2410_mpll_clk_ops = { + .recalc_rate = samsung_s3c2410_pll_recalc_rate, + .enable = samsung_s3c2410_mpll_enable, + .disable = samsung_s3c2410_mpll_disable, + .round_rate = samsung_pll_round_rate, + .set_rate = samsung_s3c2410_pll_set_rate, +}; + +static const struct clk_ops samsung_s3c2410_upll_clk_ops = { + .recalc_rate = samsung_s3c2410_pll_recalc_rate, + .enable = samsung_s3c2410_upll_enable, + .disable = samsung_s3c2410_upll_disable, + .round_rate = samsung_pll_round_rate, + .set_rate = samsung_s3c2410_pll_set_rate, +}; + +static const struct clk_ops samsung_s3c2440_mpll_clk_ops = { + .recalc_rate = samsung_s3c2440_mpll_recalc_rate, + .enable = samsung_s3c2410_mpll_enable, + .disable = samsung_s3c2410_mpll_disable, + .round_rate = samsung_pll_round_rate, + .set_rate = samsung_s3c2410_pll_set_rate, +}; + /* * PLL2550x Clock Type */ @@ -866,6 +1030,24 @@ static void __init _samsung_clk_register_pll(struct samsung_pll_clock *pll_clk, else init.ops = &samsung_pll46xx_clk_ops; break; + case pll_s3c2410_mpll: + if (!pll->rate_table) + init.ops = &samsung_s3c2410_mpll_clk_min_ops; + else + init.ops = &samsung_s3c2410_mpll_clk_ops; + break; + case pll_s3c2410_upll: + if (!pll->rate_table) + init.ops = &samsung_s3c2410_upll_clk_min_ops; + else + init.ops = &samsung_s3c2410_upll_clk_ops; + break; + case pll_s3c2440_mpll: + if (!pll->rate_table) + init.ops = &samsung_s3c2440_mpll_clk_min_ops; + else + init.ops = &samsung_s3c2440_mpll_clk_ops; + break; default: pr_warn("%s: Unknown pll type for pll clk %s\n", __func__, pll_clk->name); diff --git a/drivers/clk/samsung/clk-pll.h b/drivers/clk/samsung/clk-pll.h index 5b64bdbb0906..6428bcc6df6f 100644 --- a/drivers/clk/samsung/clk-pll.h +++ b/drivers/clk/samsung/clk-pll.h @@ -28,6 +28,9 @@ enum samsung_pll_type { pll_6552, pll_6552_s3c2416, pll_6553, + pll_s3c2410_mpll, + pll_s3c2410_upll, + pll_s3c2440_mpll, }; #define PLL_35XX_RATE(_rate, _m, _p, _s) \ From 7d03fed8e56ba5ffdae67c64d181a010a2a56d9b Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Tue, 25 Feb 2014 09:50:44 +0900 Subject: [PATCH 15/87] dt-bindings: add documentation for s3c2412 clock controller Describe the clock controller of the s3c2412. Signed-off-by: Heiko Stuebner Signed-off-by: Kukjin Kim --- .../bindings/clock/samsung,s3c2412-clock.txt | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/samsung,s3c2412-clock.txt diff --git a/Documentation/devicetree/bindings/clock/samsung,s3c2412-clock.txt b/Documentation/devicetree/bindings/clock/samsung,s3c2412-clock.txt new file mode 100644 index 000000000000..2b430960ba47 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/samsung,s3c2412-clock.txt @@ -0,0 +1,50 @@ +* Samsung S3C2412 Clock Controller + +The S3C2412 clock controller generates and supplies clock to various controllers +within the SoC. The clock binding described here is applicable to the s3c2412 +and s3c2413 SoCs in the s3c24x family. + +Required Properties: + +- compatible: should be "samsung,s3c2412-clock" +- reg: physical base address of the controller and length of memory mapped + region. +- #clock-cells: should be 1. + +Each clock is assigned an identifier and client nodes can use this identifier +to specify the clock which they consume. Some of the clocks are available only +on a particular SoC. + +All available clocks are defined as preprocessor macros in +dt-bindings/clock/s3c2412.h header and can be used in device +tree sources. + +External clocks: + +There are several clocks that are generated outside the SoC. It is expected +that they are defined using standard clock bindings with following +clock-output-names: + - "xti" - crystal input - required, + - "ext" - external clock source - optional, + +Example: Clock controller node: + + clocks: clock-controller@4c000000 { + compatible = "samsung,s3c2412-clock"; + reg = <0x4c000000 0x20>; + #clock-cells = <1>; + }; + +Example: UART controller node that consumes the clock generated by the clock + controller (refer to the standard clock bindings for information about + "clocks" and "clock-names" properties): + + serial@50004000 { + compatible = "samsung,s3c2412-uart"; + reg = <0x50004000 0x4000>; + interrupts = <1 23 3 4>, <1 23 4 4>; + clock-names = "uart", "clk_uart_baud2", "clk_uart_baud3"; + clocks = <&clocks PCLK_UART0>, <&clocks PCLK_UART0>, + <&clocks SCLK_UART>; + status = "disabled"; + }; From ca2e90ac1809c49c2306df4e23e17dad67c785b6 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Tue, 25 Feb 2014 09:50:44 +0900 Subject: [PATCH 16/87] clk: samsung: add clock controller driver for s3c2412 This driver can handle the clock controller in the s3c2412 soc. The clock structure is built according to the manuals of the included SoCs and might include changes in comparison to the previous clock structure. Signed-off-by: Heiko Stuebner Reviewed-by: Tomasz Figa Acked-by: Mike Turquette Signed-off-by: Kukjin Kim --- drivers/clk/samsung/Makefile | 1 + drivers/clk/samsung/clk-s3c2412.c | 269 ++++++++++++++++++++++++++++ include/dt-bindings/clock/s3c2412.h | 73 ++++++++ 3 files changed, 343 insertions(+) create mode 100644 drivers/clk/samsung/clk-s3c2412.c create mode 100644 include/dt-bindings/clock/s3c2412.h diff --git a/drivers/clk/samsung/Makefile b/drivers/clk/samsung/Makefile index 4c892c63a8dd..77313e27bc39 100644 --- a/drivers/clk/samsung/Makefile +++ b/drivers/clk/samsung/Makefile @@ -8,5 +8,6 @@ obj-$(CONFIG_SOC_EXYNOS5250) += clk-exynos5250.o obj-$(CONFIG_SOC_EXYNOS5420) += clk-exynos5420.o obj-$(CONFIG_SOC_EXYNOS5440) += clk-exynos5440.o obj-$(CONFIG_ARCH_EXYNOS) += clk-exynos-audss.o +obj-$(CONFIG_S3C2412_COMMON_CLK)+= clk-s3c2412.o obj-$(CONFIG_S3C2443_COMMON_CLK)+= clk-s3c2443.o obj-$(CONFIG_ARCH_S3C64XX) += clk-s3c64xx.o diff --git a/drivers/clk/samsung/clk-s3c2412.c b/drivers/clk/samsung/clk-s3c2412.c new file mode 100644 index 000000000000..0f11a07d5c01 --- /dev/null +++ b/drivers/clk/samsung/clk-s3c2412.c @@ -0,0 +1,269 @@ +/* + * Copyright (c) 2013 Heiko Stuebner + * + * 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. + * + * Common Clock Framework support for S3C2412 and S3C2413. + */ + +#include +#include +#include +#include +#include +#include + +#include + +#include "clk.h" +#include "clk-pll.h" + +#define LOCKTIME 0x00 +#define MPLLCON 0x04 +#define UPLLCON 0x08 +#define CLKCON 0x0c +#define CLKDIVN 0x14 +#define CLKSRC 0x1c + +/* list of PLLs to be registered */ +enum s3c2412_plls { + mpll, upll, +}; + +static void __iomem *reg_base; + +#ifdef CONFIG_PM_SLEEP +static struct samsung_clk_reg_dump *s3c2412_save; + +/* + * list of controller registers to be saved and restored during a + * suspend/resume cycle. + */ +static unsigned long s3c2412_clk_regs[] __initdata = { + LOCKTIME, + MPLLCON, + UPLLCON, + CLKCON, + CLKDIVN, + CLKSRC, +}; + +static int s3c2412_clk_suspend(void) +{ + samsung_clk_save(reg_base, s3c2412_save, + ARRAY_SIZE(s3c2412_clk_regs)); + + return 0; +} + +static void s3c2412_clk_resume(void) +{ + samsung_clk_restore(reg_base, s3c2412_save, + ARRAY_SIZE(s3c2412_clk_regs)); +} + +static struct syscore_ops s3c2412_clk_syscore_ops = { + .suspend = s3c2412_clk_suspend, + .resume = s3c2412_clk_resume, +}; + +static void s3c2412_clk_sleep_init(void) +{ + s3c2412_save = samsung_clk_alloc_reg_dump(s3c2412_clk_regs, + ARRAY_SIZE(s3c2412_clk_regs)); + if (!s3c2412_save) { + pr_warn("%s: failed to allocate sleep save data, no sleep support!\n", + __func__); + return; + } + + register_syscore_ops(&s3c2412_clk_syscore_ops); + return; +} +#else +static void s3c2412_clk_sleep_init(void) {} +#endif + +static struct clk_div_table divxti_d[] = { + { .val = 0, .div = 1 }, + { .val = 1, .div = 2 }, + { .val = 2, .div = 4 }, + { .val = 3, .div = 6 }, + { .val = 4, .div = 8 }, + { .val = 5, .div = 10 }, + { .val = 6, .div = 12 }, + { .val = 7, .div = 14 }, + { /* sentinel */ }, +}; + +struct samsung_div_clock s3c2412_dividers[] __initdata = { + DIV_T(0, "div_xti", "xti", CLKSRC, 0, 3, divxti_d), + DIV(0, "div_cam", "mux_cam", CLKDIVN, 16, 4), + DIV(0, "div_i2s", "mux_i2s", CLKDIVN, 12, 4), + DIV(0, "div_uart", "mux_uart", CLKDIVN, 8, 4), + DIV(0, "div_usb", "mux_usb", CLKDIVN, 6, 1), + DIV(0, "div_hclk_half", "hclk", CLKDIVN, 5, 1), + DIV(ARMDIV, "armdiv", "msysclk", CLKDIVN, 3, 1), + DIV(PCLK, "pclk", "hclk", CLKDIVN, 2, 1), + DIV(HCLK, "hclk", "armdiv", CLKDIVN, 0, 2), +}; + +struct samsung_fixed_factor_clock s3c2412_ffactor[] __initdata = { + FFACTOR(0, "ff_hclk", "hclk", 2, 1, CLK_SET_RATE_PARENT), +}; + +/* + * The first two use the OM[4] setting, which is not readable from + * software, so assume it is set to xti. + */ +PNAME(erefclk_p) = { "xti", "xti", "xti", "ext" }; +PNAME(urefclk_p) = { "xti", "xti", "xti", "ext" }; + +PNAME(camclk_p) = { "usysclk", "hclk" }; +PNAME(usbclk_p) = { "usysclk", "hclk" }; +PNAME(i2sclk_p) = { "erefclk", "mpll" }; +PNAME(uartclk_p) = { "erefclk", "mpll" }; +PNAME(usysclk_p) = { "urefclk", "upll" }; +PNAME(msysclk_p) = { "mdivclk", "mpll" }; +PNAME(mdivclk_p) = { "xti", "div_xti" }; +PNAME(armclk_p) = { "armdiv", "hclk" }; + +struct samsung_mux_clock s3c2412_muxes[] __initdata = { + MUX(0, "erefclk", erefclk_p, CLKSRC, 14, 2), + MUX(0, "urefclk", urefclk_p, CLKSRC, 12, 2), + MUX(0, "mux_cam", camclk_p, CLKSRC, 11, 1), + MUX(0, "mux_usb", usbclk_p, CLKSRC, 10, 1), + MUX(0, "mux_i2s", i2sclk_p, CLKSRC, 9, 1), + MUX(0, "mux_uart", uartclk_p, CLKSRC, 8, 1), + MUX(USYSCLK, "usysclk", usysclk_p, CLKSRC, 5, 1), + MUX(MSYSCLK, "msysclk", msysclk_p, CLKSRC, 4, 1), + MUX(MDIVCLK, "mdivclk", mdivclk_p, CLKSRC, 3, 1), + MUX(ARMCLK, "armclk", armclk_p, CLKDIVN, 4, 1), +}; + +static struct samsung_pll_clock s3c2412_plls[] __initdata = { + [mpll] = PLL(pll_s3c2440_mpll, MPLL, "mpll", "xti", + LOCKTIME, MPLLCON, NULL), + [upll] = PLL(pll_s3c2410_upll, UPLL, "upll", "urefclk", + LOCKTIME, UPLLCON, NULL), +}; + +struct samsung_gate_clock s3c2412_gates[] __initdata = { + GATE(PCLK_WDT, "wdt", "pclk", CLKCON, 28, 0, 0), + GATE(PCLK_SPI, "spi", "pclk", CLKCON, 27, 0, 0), + GATE(PCLK_I2S, "i2s", "pclk", CLKCON, 26, 0, 0), + GATE(PCLK_I2C, "i2c", "pclk", CLKCON, 25, 0, 0), + GATE(PCLK_ADC, "adc", "pclk", CLKCON, 24, 0, 0), + GATE(PCLK_RTC, "rtc", "pclk", CLKCON, 23, 0, 0), + GATE(PCLK_GPIO, "gpio", "pclk", CLKCON, 22, CLK_IGNORE_UNUSED, 0), + GATE(PCLK_UART2, "uart2", "pclk", CLKCON, 21, 0, 0), + GATE(PCLK_UART1, "uart1", "pclk", CLKCON, 20, 0, 0), + GATE(PCLK_UART0, "uart0", "pclk", CLKCON, 19, 0, 0), + GATE(PCLK_SDI, "sdi", "pclk", CLKCON, 18, 0, 0), + GATE(PCLK_PWM, "pwm", "pclk", CLKCON, 17, 0, 0), + GATE(PCLK_USBD, "usb-device", "pclk", CLKCON, 16, 0, 0), + GATE(SCLK_CAM, "sclk_cam", "div_cam", CLKCON, 15, 0, 0), + GATE(SCLK_UART, "sclk_uart", "div_uart", CLKCON, 14, 0, 0), + GATE(SCLK_I2S, "sclk_i2s", "div_i2s", CLKCON, 13, 0, 0), + GATE(SCLK_USBH, "sclk_usbh", "div_usb", CLKCON, 12, 0, 0), + GATE(SCLK_USBD, "sclk_usbd", "div_usb", CLKCON, 11, 0, 0), + GATE(HCLK_HALF, "hclk_half", "div_hclk_half", CLKCON, 10, CLK_IGNORE_UNUSED, 0), + GATE(HCLK_X2, "hclkx2", "ff_hclk", CLKCON, 9, CLK_IGNORE_UNUSED, 0), + GATE(HCLK_SDRAM, "sdram", "hclk", CLKCON, 8, CLK_IGNORE_UNUSED, 0), + GATE(HCLK_USBH, "usb-host", "hclk", CLKCON, 6, 0, 0), + GATE(HCLK_LCD, "lcd", "hclk", CLKCON, 5, 0, 0), + GATE(HCLK_NAND, "nand", "hclk", CLKCON, 4, 0, 0), + GATE(HCLK_DMA3, "dma3", "hclk", CLKCON, 3, CLK_IGNORE_UNUSED, 0), + GATE(HCLK_DMA2, "dma2", "hclk", CLKCON, 2, CLK_IGNORE_UNUSED, 0), + GATE(HCLK_DMA1, "dma1", "hclk", CLKCON, 1, CLK_IGNORE_UNUSED, 0), + GATE(HCLK_DMA0, "dma0", "hclk", CLKCON, 0, CLK_IGNORE_UNUSED, 0), +}; + +struct samsung_clock_alias s3c2412_aliases[] __initdata = { + ALIAS(PCLK_UART0, "s3c2412-uart.0", "uart"), + ALIAS(PCLK_UART1, "s3c2412-uart.1", "uart"), + ALIAS(PCLK_UART2, "s3c2412-uart.2", "uart"), + ALIAS(PCLK_UART0, "s3c2412-uart.0", "clk_uart_baud2"), + ALIAS(PCLK_UART1, "s3c2412-uart.1", "clk_uart_baud2"), + ALIAS(PCLK_UART2, "s3c2412-uart.2", "clk_uart_baud2"), + ALIAS(SCLK_UART, NULL, "clk_uart_baud3"), + ALIAS(PCLK_I2C, "s3c2410-i2c.0", "i2c"), + ALIAS(PCLK_ADC, NULL, "adc"), + ALIAS(PCLK_RTC, NULL, "rtc"), + ALIAS(PCLK_PWM, NULL, "timers"), + ALIAS(HCLK_LCD, NULL, "lcd"), + ALIAS(PCLK_USBD, NULL, "usb-device"), + ALIAS(SCLK_USBD, NULL, "usb-bus-gadget"), + ALIAS(HCLK_USBH, NULL, "usb-host"), + ALIAS(SCLK_USBH, NULL, "usb-bus-host"), + ALIAS(ARMCLK, NULL, "armclk"), + ALIAS(HCLK, NULL, "hclk"), + ALIAS(MPLL, NULL, "mpll"), + ALIAS(MSYSCLK, NULL, "fclk"), +}; + +/* + * fixed rate clocks generated outside the soc + * Only necessary until the devicetree-move is complete + */ +#define XTI 1 +struct samsung_fixed_rate_clock s3c2412_common_frate_clks[] __initdata = { + FRATE(XTI, "xti", NULL, CLK_IS_ROOT, 0), + FRATE(0, "ext", NULL, CLK_IS_ROOT, 0), +}; + +static void __init s3c2412_common_clk_register_fixed_ext(unsigned long xti_f, + unsigned long ext_f) +{ + /* xtal alias is necessary for the current cpufreq driver */ + struct samsung_clock_alias xti_alias = ALIAS(XTI, NULL, "xtal"); + + s3c2412_common_frate_clks[0].fixed_rate = xti_f; + s3c2412_common_frate_clks[1].fixed_rate = ext_f; + samsung_clk_register_fixed_rate(s3c2412_common_frate_clks, + ARRAY_SIZE(s3c2412_common_frate_clks)); + + samsung_clk_register_alias(&xti_alias, 1); +} + +void __init s3c2412_common_clk_init(struct device_node *np, unsigned long xti_f, + unsigned long ext_f, void __iomem *base) +{ + reg_base = base; + + if (np) { + reg_base = of_iomap(np, 0); + if (!reg_base) + panic("%s: failed to map registers\n", __func__); + } + + samsung_clk_init(np, reg_base, NR_CLKS); + + /* Register external clocks only in non-dt cases */ + if (!np) + s3c2412_common_clk_register_fixed_ext(xti_f, ext_f); + + /* Register PLLs. */ + samsung_clk_register_pll(s3c2412_plls, ARRAY_SIZE(s3c2412_plls), + reg_base); + + /* Register common internal clocks. */ + samsung_clk_register_mux(s3c2412_muxes, ARRAY_SIZE(s3c2412_muxes)); + samsung_clk_register_div(s3c2412_dividers, + ARRAY_SIZE(s3c2412_dividers)); + samsung_clk_register_gate(s3c2412_gates, ARRAY_SIZE(s3c2412_gates)); + samsung_clk_register_fixed_factor(s3c2412_ffactor, + ARRAY_SIZE(s3c2412_ffactor)); + samsung_clk_register_alias(s3c2412_aliases, + ARRAY_SIZE(s3c2412_aliases)); + + s3c2412_clk_sleep_init(); +} + +static void __init s3c2412_clk_init(struct device_node *np) +{ + s3c2412_common_clk_init(np, 0, 0, 0); +} +CLK_OF_DECLARE(s3c2412_clk, "samsung,s3c2412-clock", s3c2412_clk_init); diff --git a/include/dt-bindings/clock/s3c2412.h b/include/dt-bindings/clock/s3c2412.h new file mode 100644 index 000000000000..aac1dcfda81c --- /dev/null +++ b/include/dt-bindings/clock/s3c2412.h @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2013 Heiko Stuebner + * + * 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. + * + * Device Tree binding constants clock controllers of Samsung S3C2412. + */ + +#ifndef _DT_BINDINGS_CLOCK_SAMSUNG_S3C2412_CLOCK_H +#define _DT_BINDINGS_CLOCK_SAMSUNG_S3C2412_CLOCK_H + +/* + * Let each exported clock get a unique index, which is used on DT-enabled + * platforms to lookup the clock from a clock specifier. These indices are + * therefore considered an ABI and so must not be changed. This implies + * that new clocks should be added either in free spaces between clock groups + * or at the end. + */ + +/* Core clocks. */ + +/* id 1 is reserved */ +#define MPLL 2 +#define UPLL 3 +#define MDIVCLK 4 +#define MSYSCLK 5 +#define USYSCLK 6 +#define HCLK 7 +#define PCLK 8 +#define ARMDIV 9 +#define ARMCLK 10 + + +/* Special clocks */ +#define SCLK_CAM 16 +#define SCLK_UART 17 +#define SCLK_I2S 18 +#define SCLK_USBD 19 +#define SCLK_USBH 20 + +/* pclk-gates */ +#define PCLK_WDT 32 +#define PCLK_SPI 33 +#define PCLK_I2S 34 +#define PCLK_I2C 35 +#define PCLK_ADC 36 +#define PCLK_RTC 37 +#define PCLK_GPIO 38 +#define PCLK_UART2 39 +#define PCLK_UART1 40 +#define PCLK_UART0 41 +#define PCLK_SDI 42 +#define PCLK_PWM 43 +#define PCLK_USBD 44 + +/* hclk-gates */ +#define HCLK_HALF 48 +#define HCLK_X2 49 +#define HCLK_SDRAM 50 +#define HCLK_USBH 51 +#define HCLK_LCD 52 +#define HCLK_NAND 53 +#define HCLK_DMA3 54 +#define HCLK_DMA2 55 +#define HCLK_DMA1 56 +#define HCLK_DMA0 57 + +/* Total number of clocks. */ +#define NR_CLKS (HCLK_DMA0 + 1) + +#endif /* _DT_BINDINGS_CLOCK_SAMSUNG_S3C2412_CLOCK_H */ From 3c27f314c676ee31eafd423ce2c640ed129cd5e0 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Tue, 25 Feb 2014 09:50:44 +0900 Subject: [PATCH 17/87] ARM: S3C24XX: convert s3c2412 to common clock framework Convert all machines using these cpus to use the ccf clock driver instead of the legacy Samsung clock implementation. Signed-off-by: Heiko Stuebner Reviewed-by: Tomasz Figa Signed-off-by: Kukjin Kim --- arch/arm/mach-s3c24xx/Kconfig | 8 +- arch/arm/mach-s3c24xx/Makefile | 2 +- arch/arm/mach-s3c24xx/clock-s3c2412.c | 760 -------------------------- arch/arm/mach-s3c24xx/common.c | 9 +- arch/arm/mach-s3c24xx/common.h | 4 + arch/arm/mach-s3c24xx/mach-jive.c | 9 +- arch/arm/mach-s3c24xx/mach-smdk2413.c | 9 +- arch/arm/mach-s3c24xx/mach-vstms.c | 9 +- arch/arm/mach-s3c24xx/s3c2412.c | 43 -- 9 files changed, 40 insertions(+), 813 deletions(-) delete mode 100644 arch/arm/mach-s3c24xx/clock-s3c2412.c diff --git a/arch/arm/mach-s3c24xx/Kconfig b/arch/arm/mach-s3c24xx/Kconfig index 52f1c40ccf07..fbafb9a1975b 100644 --- a/arch/arm/mach-s3c24xx/Kconfig +++ b/arch/arm/mach-s3c24xx/Kconfig @@ -39,9 +39,10 @@ config CPU_S3C2410 config CPU_S3C2412 bool "SAMSUNG S3C2412" - depends on SAMSUNG_CLOCK + select COMMON_CLK select CPU_ARM926T select CPU_LLSERIAL_S3C2440 + select S3C2412_COMMON_CLK select S3C2412_DMA if S3C24XX_DMA select S3C2412_PM if PM help @@ -363,6 +364,11 @@ config S3C2412_PM_SLEEP if CPU_S3C2412 +config S3C2412_COMMON_CLK + bool + help + Build the s3c2412 clock driver based on the common clock framework. + config CPU_S3C2412_ONLY bool depends on !CPU_S3C2410 && !CPU_S3C2416 && !CPU_S3C2440 && \ diff --git a/arch/arm/mach-s3c24xx/Makefile b/arch/arm/mach-s3c24xx/Makefile index ba0e5475a807..f25479721dc9 100644 --- a/arch/arm/mach-s3c24xx/Makefile +++ b/arch/arm/mach-s3c24xx/Makefile @@ -21,7 +21,7 @@ obj-$(CONFIG_S3C2410_DMA) += dma-s3c2410.o obj-$(CONFIG_S3C2410_PLL) += pll-s3c2410.o obj-$(CONFIG_S3C2410_PM) += pm-s3c2410.o sleep-s3c2410.o -obj-$(CONFIG_CPU_S3C2412) += s3c2412.o clock-s3c2412.o +obj-$(CONFIG_CPU_S3C2412) += s3c2412.o obj-$(CONFIG_S3C2412_DMA) += dma-s3c2412.o obj-$(CONFIG_S3C2412_PM) += pm-s3c2412.o obj-$(CONFIG_S3C2412_PM_SLEEP) += sleep-s3c2412.o diff --git a/arch/arm/mach-s3c24xx/clock-s3c2412.c b/arch/arm/mach-s3c24xx/clock-s3c2412.c deleted file mode 100644 index 192a5b2550b0..000000000000 --- a/arch/arm/mach-s3c24xx/clock-s3c2412.c +++ /dev/null @@ -1,760 +0,0 @@ -/* linux/arch/arm/mach-s3c2412/clock.c - * - * Copyright (c) 2006 Simtec Electronics - * Ben Dooks - * - * S3C2412,S3C2413 Clock control support - * - * 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include - -#include -#include - -/* We currently have to assume that the system is running - * from the XTPll input, and that all ***REFCLKs are being - * fed from it, as we cannot read the state of OM[4] from - * software. - * - * It would be possible for each board initialisation to - * set the correct muxing at initialisation -*/ - -static int s3c2412_clkcon_enable(struct clk *clk, int enable) -{ - unsigned int clocks = clk->ctrlbit; - unsigned long clkcon; - - clkcon = __raw_readl(S3C2410_CLKCON); - - if (enable) - clkcon |= clocks; - else - clkcon &= ~clocks; - - __raw_writel(clkcon, S3C2410_CLKCON); - - return 0; -} - -static int s3c2412_upll_enable(struct clk *clk, int enable) -{ - unsigned long upllcon = __raw_readl(S3C2410_UPLLCON); - unsigned long orig = upllcon; - - if (!enable) - upllcon |= S3C2412_PLLCON_OFF; - else - upllcon &= ~S3C2412_PLLCON_OFF; - - __raw_writel(upllcon, S3C2410_UPLLCON); - - /* allow ~150uS for the PLL to settle and lock */ - - if (enable && (orig & S3C2412_PLLCON_OFF)) - udelay(150); - - return 0; -} - -/* clock selections */ - -static struct clk clk_erefclk = { - .name = "erefclk", -}; - -static struct clk clk_urefclk = { - .name = "urefclk", -}; - -static int s3c2412_setparent_usysclk(struct clk *clk, struct clk *parent) -{ - unsigned long clksrc = __raw_readl(S3C2412_CLKSRC); - - if (parent == &clk_urefclk) - clksrc &= ~S3C2412_CLKSRC_USYSCLK_UPLL; - else if (parent == &clk_upll) - clksrc |= S3C2412_CLKSRC_USYSCLK_UPLL; - else - return -EINVAL; - - clk->parent = parent; - - __raw_writel(clksrc, S3C2412_CLKSRC); - return 0; -} - -static struct clk clk_usysclk = { - .name = "usysclk", - .parent = &clk_xtal, - .ops = &(struct clk_ops) { - .set_parent = s3c2412_setparent_usysclk, - }, -}; - -static struct clk clk_mrefclk = { - .name = "mrefclk", - .parent = &clk_xtal, -}; - -static struct clk clk_mdivclk = { - .name = "mdivclk", - .parent = &clk_xtal, -}; - -static int s3c2412_setparent_usbsrc(struct clk *clk, struct clk *parent) -{ - unsigned long clksrc = __raw_readl(S3C2412_CLKSRC); - - if (parent == &clk_usysclk) - clksrc &= ~S3C2412_CLKSRC_USBCLK_HCLK; - else if (parent == &clk_h) - clksrc |= S3C2412_CLKSRC_USBCLK_HCLK; - else - return -EINVAL; - - clk->parent = parent; - - __raw_writel(clksrc, S3C2412_CLKSRC); - return 0; -} - -static unsigned long s3c2412_roundrate_usbsrc(struct clk *clk, - unsigned long rate) -{ - unsigned long parent_rate = clk_get_rate(clk->parent); - int div; - - if (rate > parent_rate) - return parent_rate; - - div = parent_rate / rate; - if (div > 2) - div = 2; - - return parent_rate / div; -} - -static unsigned long s3c2412_getrate_usbsrc(struct clk *clk) -{ - unsigned long parent_rate = clk_get_rate(clk->parent); - unsigned long div = __raw_readl(S3C2410_CLKDIVN); - - return parent_rate / ((div & S3C2412_CLKDIVN_USB48DIV) ? 2 : 1); -} - -static int s3c2412_setrate_usbsrc(struct clk *clk, unsigned long rate) -{ - unsigned long parent_rate = clk_get_rate(clk->parent); - unsigned long clkdivn = __raw_readl(S3C2410_CLKDIVN); - - rate = s3c2412_roundrate_usbsrc(clk, rate); - - if ((parent_rate / rate) == 2) - clkdivn |= S3C2412_CLKDIVN_USB48DIV; - else - clkdivn &= ~S3C2412_CLKDIVN_USB48DIV; - - __raw_writel(clkdivn, S3C2410_CLKDIVN); - return 0; -} - -static struct clk clk_usbsrc = { - .name = "usbsrc", - .ops = &(struct clk_ops) { - .get_rate = s3c2412_getrate_usbsrc, - .set_rate = s3c2412_setrate_usbsrc, - .round_rate = s3c2412_roundrate_usbsrc, - .set_parent = s3c2412_setparent_usbsrc, - }, -}; - -static int s3c2412_setparent_msysclk(struct clk *clk, struct clk *parent) -{ - unsigned long clksrc = __raw_readl(S3C2412_CLKSRC); - - if (parent == &clk_mdivclk) - clksrc &= ~S3C2412_CLKSRC_MSYSCLK_MPLL; - else if (parent == &clk_mpll) - clksrc |= S3C2412_CLKSRC_MSYSCLK_MPLL; - else - return -EINVAL; - - clk->parent = parent; - - __raw_writel(clksrc, S3C2412_CLKSRC); - return 0; -} - -static struct clk clk_msysclk = { - .name = "msysclk", - .ops = &(struct clk_ops) { - .set_parent = s3c2412_setparent_msysclk, - }, -}; - -static int s3c2412_setparent_armclk(struct clk *clk, struct clk *parent) -{ - unsigned long flags; - unsigned long clkdiv; - unsigned long dvs; - - /* Note, we current equate fclk andf msysclk for S3C2412 */ - - if (parent == &clk_msysclk || parent == &clk_f) - dvs = 0; - else if (parent == &clk_h) - dvs = S3C2412_CLKDIVN_DVSEN; - else - return -EINVAL; - - clk->parent = parent; - - /* update this under irq lockdown, clkdivn is not protected - * by the clock system. */ - - local_irq_save(flags); - - clkdiv = __raw_readl(S3C2410_CLKDIVN); - clkdiv &= ~S3C2412_CLKDIVN_DVSEN; - clkdiv |= dvs; - __raw_writel(clkdiv, S3C2410_CLKDIVN); - - local_irq_restore(flags); - - return 0; -} - -static struct clk clk_armclk = { - .name = "armclk", - .parent = &clk_msysclk, - .ops = &(struct clk_ops) { - .set_parent = s3c2412_setparent_armclk, - }, -}; - -/* these next clocks have an divider immediately after them, - * so we can register them with their divider and leave out the - * intermediate clock stage -*/ -static unsigned long s3c2412_roundrate_clksrc(struct clk *clk, - unsigned long rate) -{ - unsigned long parent_rate = clk_get_rate(clk->parent); - int div; - - if (rate > parent_rate) - return parent_rate; - - /* note, we remove the +/- 1 calculations as they cancel out */ - - div = (rate / parent_rate); - - if (div < 1) - div = 1; - else if (div > 16) - div = 16; - - return parent_rate / div; -} - -static int s3c2412_setparent_uart(struct clk *clk, struct clk *parent) -{ - unsigned long clksrc = __raw_readl(S3C2412_CLKSRC); - - if (parent == &clk_erefclk) - clksrc &= ~S3C2412_CLKSRC_UARTCLK_MPLL; - else if (parent == &clk_mpll) - clksrc |= S3C2412_CLKSRC_UARTCLK_MPLL; - else - return -EINVAL; - - clk->parent = parent; - - __raw_writel(clksrc, S3C2412_CLKSRC); - return 0; -} - -static unsigned long s3c2412_getrate_uart(struct clk *clk) -{ - unsigned long parent_rate = clk_get_rate(clk->parent); - unsigned long div = __raw_readl(S3C2410_CLKDIVN); - - div &= S3C2412_CLKDIVN_UARTDIV_MASK; - div >>= S3C2412_CLKDIVN_UARTDIV_SHIFT; - - return parent_rate / (div + 1); -} - -static int s3c2412_setrate_uart(struct clk *clk, unsigned long rate) -{ - unsigned long parent_rate = clk_get_rate(clk->parent); - unsigned long clkdivn = __raw_readl(S3C2410_CLKDIVN); - - rate = s3c2412_roundrate_clksrc(clk, rate); - - clkdivn &= ~S3C2412_CLKDIVN_UARTDIV_MASK; - clkdivn |= ((parent_rate / rate) - 1) << S3C2412_CLKDIVN_UARTDIV_SHIFT; - - __raw_writel(clkdivn, S3C2410_CLKDIVN); - return 0; -} - -static struct clk clk_uart = { - .name = "uartclk", - .ops = &(struct clk_ops) { - .get_rate = s3c2412_getrate_uart, - .set_rate = s3c2412_setrate_uart, - .set_parent = s3c2412_setparent_uart, - .round_rate = s3c2412_roundrate_clksrc, - }, -}; - -static int s3c2412_setparent_i2s(struct clk *clk, struct clk *parent) -{ - unsigned long clksrc = __raw_readl(S3C2412_CLKSRC); - - if (parent == &clk_erefclk) - clksrc &= ~S3C2412_CLKSRC_I2SCLK_MPLL; - else if (parent == &clk_mpll) - clksrc |= S3C2412_CLKSRC_I2SCLK_MPLL; - else - return -EINVAL; - - clk->parent = parent; - - __raw_writel(clksrc, S3C2412_CLKSRC); - return 0; -} - -static unsigned long s3c2412_getrate_i2s(struct clk *clk) -{ - unsigned long parent_rate = clk_get_rate(clk->parent); - unsigned long div = __raw_readl(S3C2410_CLKDIVN); - - div &= S3C2412_CLKDIVN_I2SDIV_MASK; - div >>= S3C2412_CLKDIVN_I2SDIV_SHIFT; - - return parent_rate / (div + 1); -} - -static int s3c2412_setrate_i2s(struct clk *clk, unsigned long rate) -{ - unsigned long parent_rate = clk_get_rate(clk->parent); - unsigned long clkdivn = __raw_readl(S3C2410_CLKDIVN); - - rate = s3c2412_roundrate_clksrc(clk, rate); - - clkdivn &= ~S3C2412_CLKDIVN_I2SDIV_MASK; - clkdivn |= ((parent_rate / rate) - 1) << S3C2412_CLKDIVN_I2SDIV_SHIFT; - - __raw_writel(clkdivn, S3C2410_CLKDIVN); - return 0; -} - -static struct clk clk_i2s = { - .name = "i2sclk", - .ops = &(struct clk_ops) { - .get_rate = s3c2412_getrate_i2s, - .set_rate = s3c2412_setrate_i2s, - .set_parent = s3c2412_setparent_i2s, - .round_rate = s3c2412_roundrate_clksrc, - }, -}; - -static int s3c2412_setparent_cam(struct clk *clk, struct clk *parent) -{ - unsigned long clksrc = __raw_readl(S3C2412_CLKSRC); - - if (parent == &clk_usysclk) - clksrc &= ~S3C2412_CLKSRC_CAMCLK_HCLK; - else if (parent == &clk_h) - clksrc |= S3C2412_CLKSRC_CAMCLK_HCLK; - else - return -EINVAL; - - clk->parent = parent; - - __raw_writel(clksrc, S3C2412_CLKSRC); - return 0; -} -static unsigned long s3c2412_getrate_cam(struct clk *clk) -{ - unsigned long parent_rate = clk_get_rate(clk->parent); - unsigned long div = __raw_readl(S3C2410_CLKDIVN); - - div &= S3C2412_CLKDIVN_CAMDIV_MASK; - div >>= S3C2412_CLKDIVN_CAMDIV_SHIFT; - - return parent_rate / (div + 1); -} - -static int s3c2412_setrate_cam(struct clk *clk, unsigned long rate) -{ - unsigned long parent_rate = clk_get_rate(clk->parent); - unsigned long clkdivn = __raw_readl(S3C2410_CLKDIVN); - - rate = s3c2412_roundrate_clksrc(clk, rate); - - clkdivn &= ~S3C2412_CLKDIVN_CAMDIV_MASK; - clkdivn |= ((parent_rate / rate) - 1) << S3C2412_CLKDIVN_CAMDIV_SHIFT; - - __raw_writel(clkdivn, S3C2410_CLKDIVN); - return 0; -} - -static struct clk clk_cam = { - .name = "camif-upll", /* same as 2440 name */ - .ops = &(struct clk_ops) { - .get_rate = s3c2412_getrate_cam, - .set_rate = s3c2412_setrate_cam, - .set_parent = s3c2412_setparent_cam, - .round_rate = s3c2412_roundrate_clksrc, - }, -}; - -/* standard clock definitions */ - -static struct clk init_clocks_disable[] = { - { - .name = "nand", - .parent = &clk_h, - .enable = s3c2412_clkcon_enable, - .ctrlbit = S3C2412_CLKCON_NAND, - }, { - .name = "sdi", - .parent = &clk_p, - .enable = s3c2412_clkcon_enable, - .ctrlbit = S3C2412_CLKCON_SDI, - }, { - .name = "adc", - .parent = &clk_p, - .enable = s3c2412_clkcon_enable, - .ctrlbit = S3C2412_CLKCON_ADC, - }, { - .name = "i2c", - .parent = &clk_p, - .enable = s3c2412_clkcon_enable, - .ctrlbit = S3C2412_CLKCON_IIC, - }, { - .name = "iis", - .parent = &clk_p, - .enable = s3c2412_clkcon_enable, - .ctrlbit = S3C2412_CLKCON_IIS, - }, { - .name = "spi", - .parent = &clk_p, - .enable = s3c2412_clkcon_enable, - .ctrlbit = S3C2412_CLKCON_SPI, - } -}; - -static struct clk init_clocks[] = { - { - .name = "dma.0", - .parent = &clk_h, - .enable = s3c2412_clkcon_enable, - .ctrlbit = S3C2412_CLKCON_DMA0, - }, { - .name = "dma.1", - .parent = &clk_h, - .enable = s3c2412_clkcon_enable, - .ctrlbit = S3C2412_CLKCON_DMA1, - }, { - .name = "dma.2", - .parent = &clk_h, - .enable = s3c2412_clkcon_enable, - .ctrlbit = S3C2412_CLKCON_DMA2, - }, { - .name = "dma.3", - .parent = &clk_h, - .enable = s3c2412_clkcon_enable, - .ctrlbit = S3C2412_CLKCON_DMA3, - }, { - .name = "lcd", - .parent = &clk_h, - .enable = s3c2412_clkcon_enable, - .ctrlbit = S3C2412_CLKCON_LCDC, - }, { - .name = "gpio", - .parent = &clk_p, - .enable = s3c2412_clkcon_enable, - .ctrlbit = S3C2412_CLKCON_GPIO, - }, { - .name = "usb-host", - .parent = &clk_h, - .enable = s3c2412_clkcon_enable, - .ctrlbit = S3C2412_CLKCON_USBH, - }, { - .name = "usb-device", - .parent = &clk_h, - .enable = s3c2412_clkcon_enable, - .ctrlbit = S3C2412_CLKCON_USBD, - }, { - .name = "timers", - .parent = &clk_p, - .enable = s3c2412_clkcon_enable, - .ctrlbit = S3C2412_CLKCON_PWMT, - }, { - .name = "uart", - .devname = "s3c2412-uart.0", - .parent = &clk_p, - .enable = s3c2412_clkcon_enable, - .ctrlbit = S3C2412_CLKCON_UART0, - }, { - .name = "uart", - .devname = "s3c2412-uart.1", - .parent = &clk_p, - .enable = s3c2412_clkcon_enable, - .ctrlbit = S3C2412_CLKCON_UART1, - }, { - .name = "uart", - .devname = "s3c2412-uart.2", - .parent = &clk_p, - .enable = s3c2412_clkcon_enable, - .ctrlbit = S3C2412_CLKCON_UART2, - }, { - .name = "rtc", - .parent = &clk_p, - .enable = s3c2412_clkcon_enable, - .ctrlbit = S3C2412_CLKCON_RTC, - }, { - .name = "watchdog", - .parent = &clk_p, - .ctrlbit = 0, - }, { - .name = "usb-bus-gadget", - .parent = &clk_usb_bus, - .enable = s3c2412_clkcon_enable, - .ctrlbit = S3C2412_CLKCON_USB_DEV48, - }, { - .name = "usb-bus-host", - .parent = &clk_usb_bus, - .enable = s3c2412_clkcon_enable, - .ctrlbit = S3C2412_CLKCON_USB_HOST48, - } -}; - -/* clocks to add where we need to check their parentage */ - -struct clk_init { - struct clk *clk; - unsigned int bit; - struct clk *src_0; - struct clk *src_1; -}; - -static struct clk_init clks_src[] __initdata = { - { - .clk = &clk_usysclk, - .bit = S3C2412_CLKSRC_USBCLK_HCLK, - .src_0 = &clk_urefclk, - .src_1 = &clk_upll, - }, { - .clk = &clk_i2s, - .bit = S3C2412_CLKSRC_I2SCLK_MPLL, - .src_0 = &clk_erefclk, - .src_1 = &clk_mpll, - }, { - .clk = &clk_cam, - .bit = S3C2412_CLKSRC_CAMCLK_HCLK, - .src_0 = &clk_usysclk, - .src_1 = &clk_h, - }, { - .clk = &clk_msysclk, - .bit = S3C2412_CLKSRC_MSYSCLK_MPLL, - .src_0 = &clk_mdivclk, - .src_1 = &clk_mpll, - }, { - .clk = &clk_uart, - .bit = S3C2412_CLKSRC_UARTCLK_MPLL, - .src_0 = &clk_erefclk, - .src_1 = &clk_mpll, - }, { - .clk = &clk_usbsrc, - .bit = S3C2412_CLKSRC_USBCLK_HCLK, - .src_0 = &clk_usysclk, - .src_1 = &clk_h, - /* here we assume OM[4] select xtal */ - }, { - .clk = &clk_erefclk, - .bit = S3C2412_CLKSRC_EREFCLK_EXTCLK, - .src_0 = &clk_xtal, - .src_1 = &clk_ext, - }, { - .clk = &clk_urefclk, - .bit = S3C2412_CLKSRC_UREFCLK_EXTCLK, - .src_0 = &clk_xtal, - .src_1 = &clk_ext, - }, -}; - -/* s3c2412_clk_initparents - * - * Initialise the parents for the clocks that we get at start-time -*/ - -static void __init s3c2412_clk_initparents(void) -{ - unsigned long clksrc = __raw_readl(S3C2412_CLKSRC); - struct clk_init *cip = clks_src; - struct clk *src; - int ptr; - int ret; - - for (ptr = 0; ptr < ARRAY_SIZE(clks_src); ptr++, cip++) { - ret = s3c24xx_register_clock(cip->clk); - if (ret < 0) { - printk(KERN_ERR "Failed to register clock %s (%d)\n", - cip->clk->name, ret); - } - - src = (clksrc & cip->bit) ? cip->src_1 : cip->src_0; - - printk(KERN_INFO "%s: parent %s\n", cip->clk->name, src->name); - clk_set_parent(cip->clk, src); - } -} - -/* clocks to add straight away */ - -static struct clk *clks[] __initdata = { - &clk_ext, - &clk_usb_bus, - &clk_mrefclk, - &clk_armclk, -}; - -static struct clk_lookup s3c2412_clk_lookup[] = { - CLKDEV_INIT(NULL, "clk_uart_baud1", &s3c24xx_uclk), - CLKDEV_INIT(NULL, "clk_uart_baud2", &clk_p), - CLKDEV_INIT(NULL, "clk_uart_baud3", &clk_usysclk), -}; - -int __init s3c2412_baseclk_add(void) -{ - unsigned long clkcon = __raw_readl(S3C2410_CLKCON); - unsigned int dvs; - struct clk *clkp; - int ret; - int ptr; - - clk_upll.enable = s3c2412_upll_enable; - clk_usb_bus.parent = &clk_usbsrc; - clk_usb_bus.rate = 0x0; - - clk_f.parent = &clk_msysclk; - - s3c2412_clk_initparents(); - - for (ptr = 0; ptr < ARRAY_SIZE(clks); ptr++) { - clkp = clks[ptr]; - - ret = s3c24xx_register_clock(clkp); - if (ret < 0) { - printk(KERN_ERR "Failed to register clock %s (%d)\n", - clkp->name, ret); - } - } - - /* set the dvs state according to what we got at boot time */ - - dvs = __raw_readl(S3C2410_CLKDIVN) & S3C2412_CLKDIVN_DVSEN; - - if (dvs) - clk_armclk.parent = &clk_h; - - printk(KERN_INFO "S3C2412: DVS is %s\n", dvs ? "on" : "off"); - - /* ensure usb bus clock is within correct rate of 48MHz */ - - if (clk_get_rate(&clk_usb_bus) != (48 * 1000 * 1000)) { - printk(KERN_INFO "Warning: USB bus clock not at 48MHz\n"); - - /* for the moment, let's use the UPLL, and see if we can - * get 48MHz */ - - clk_set_parent(&clk_usysclk, &clk_upll); - clk_set_parent(&clk_usbsrc, &clk_usysclk); - clk_set_rate(&clk_usbsrc, 48*1000*1000); - } - - printk("S3C2412: upll %s, %ld.%03ld MHz, usb-bus %ld.%03ld MHz\n", - (__raw_readl(S3C2410_UPLLCON) & S3C2412_PLLCON_OFF) ? "off":"on", - print_mhz(clk_get_rate(&clk_upll)), - print_mhz(clk_get_rate(&clk_usb_bus))); - - /* register clocks from clock array */ - - clkp = init_clocks; - for (ptr = 0; ptr < ARRAY_SIZE(init_clocks); ptr++, clkp++) { - /* ensure that we note the clock state */ - - clkp->usage = clkcon & clkp->ctrlbit ? 1 : 0; - - ret = s3c24xx_register_clock(clkp); - if (ret < 0) { - printk(KERN_ERR "Failed to register clock %s (%d)\n", - clkp->name, ret); - } - } - - /* We must be careful disabling the clocks we are not intending to - * be using at boot time, as subsystems such as the LCD which do - * their own DMA requests to the bus can cause the system to lockup - * if they where in the middle of requesting bus access. - * - * Disabling the LCD clock if the LCD is active is very dangerous, - * and therefore the bootloader should be careful to not enable - * the LCD clock if it is not needed. - */ - - /* install (and disable) the clocks we do not need immediately */ - - clkp = init_clocks_disable; - for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) { - - ret = s3c24xx_register_clock(clkp); - if (ret < 0) { - printk(KERN_ERR "Failed to register clock %s (%d)\n", - clkp->name, ret); - } - - s3c2412_clkcon_enable(clkp, 0); - } - - clkdev_add_table(s3c2412_clk_lookup, ARRAY_SIZE(s3c2412_clk_lookup)); - return 0; -} diff --git a/arch/arm/mach-s3c24xx/common.c b/arch/arm/mach-s3c24xx/common.c index 412ca006fcce..ad5b76bf4d51 100644 --- a/arch/arm/mach-s3c24xx/common.c +++ b/arch/arm/mach-s3c24xx/common.c @@ -127,7 +127,6 @@ static struct cpu_table cpu_ids[] __initdata = { .idcode = 0x32412001, .idmask = 0xffffffff, .map_io = s3c2412_map_io, - .init_clocks = s3c2412_init_clocks, .init_uarts = s3c2412_init_uarts, .init = s3c2412_init, .name = name_s3c2412, @@ -136,7 +135,6 @@ static struct cpu_table cpu_ids[] __initdata = { .idcode = 0x32412003, .idmask = 0xffffffff, .map_io = s3c2412_map_io, - .init_clocks = s3c2412_init_clocks, .init_uarts = s3c2412_init_uarts, .init = s3c2412_init, .name = name_s3c2412, @@ -535,6 +533,13 @@ struct platform_device s3c2443_device_dma = { }; #endif +#ifdef CONFIG_CPU_S3C2412 +void __init s3c2412_init_clocks(int xtal) +{ + s3c2412_common_clk_init(NULL, xtal, 0, S3C24XX_VA_CLKPWR); +} +#endif + #ifdef CONFIG_CPU_S3C2416 void __init s3c2416_init_clocks(int xtal) { diff --git a/arch/arm/mach-s3c24xx/common.h b/arch/arm/mach-s3c24xx/common.h index d7323f16427f..3fade6d796f9 100644 --- a/arch/arm/mach-s3c24xx/common.h +++ b/arch/arm/mach-s3c24xx/common.h @@ -114,6 +114,10 @@ extern struct platform_device s3c2412_device_dma; extern struct platform_device s3c2440_device_dma; extern struct platform_device s3c2443_device_dma; +#ifdef CONFIG_S3C2412_COMMON_CLK +void __init s3c2412_common_clk_init(struct device_node *np, unsigned long xti_f, + unsigned long ext_f, void __iomem *reg_base); +#endif #ifdef CONFIG_S3C2443_COMMON_CLK void __init s3c2443_common_clk_init(struct device_node *np, unsigned long xti_f, int current_soc, diff --git a/arch/arm/mach-s3c24xx/mach-jive.c b/arch/arm/mach-s3c24xx/mach-jive.c index 5faa7239e7d6..e81ea82c55f9 100644 --- a/arch/arm/mach-s3c24xx/mach-jive.c +++ b/arch/arm/mach-s3c24xx/mach-jive.c @@ -507,11 +507,16 @@ static struct syscore_ops jive_pm_syscore_ops = { static void __init jive_map_io(void) { s3c24xx_init_io(jive_iodesc, ARRAY_SIZE(jive_iodesc)); - s3c24xx_init_clocks(12000000); s3c24xx_init_uarts(jive_uartcfgs, ARRAY_SIZE(jive_uartcfgs)); samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4); } +static void __init jive_init_time(void) +{ + s3c2412_init_clocks(12000000); + samsung_timer_init(); +} + static void jive_power_off(void) { printk(KERN_INFO "powering system down...\n"); @@ -665,6 +670,6 @@ MACHINE_START(JIVE, "JIVE") .init_irq = s3c2412_init_irq, .map_io = jive_map_io, .init_machine = jive_machine_init, - .init_time = samsung_timer_init, + .init_time = jive_init_time, .restart = s3c2412_restart, MACHINE_END diff --git a/arch/arm/mach-s3c24xx/mach-smdk2413.c b/arch/arm/mach-s3c24xx/mach-smdk2413.c index 233fe52d2015..a38f8a049e22 100644 --- a/arch/arm/mach-s3c24xx/mach-smdk2413.c +++ b/arch/arm/mach-s3c24xx/mach-smdk2413.c @@ -106,11 +106,16 @@ static void __init smdk2413_fixup(struct tag *tags, char **cmdline, static void __init smdk2413_map_io(void) { s3c24xx_init_io(smdk2413_iodesc, ARRAY_SIZE(smdk2413_iodesc)); - s3c24xx_init_clocks(12000000); s3c24xx_init_uarts(smdk2413_uartcfgs, ARRAY_SIZE(smdk2413_uartcfgs)); samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4); } +static void __init smdk2413_init_time(void) +{ + s3c2412_init_clocks(12000000); + samsung_timer_init(); +} + static void __init smdk2413_machine_init(void) { /* Turn off suspend on both USB ports, and switch the * selectable USB port to USB device mode. */ @@ -159,6 +164,6 @@ MACHINE_START(SMDK2413, "SMDK2413") .init_irq = s3c2412_init_irq, .map_io = smdk2413_map_io, .init_machine = smdk2413_machine_init, - .init_time = samsung_timer_init, + .init_time = smdk2413_init_time, .restart = s3c2412_restart, MACHINE_END diff --git a/arch/arm/mach-s3c24xx/mach-vstms.c b/arch/arm/mach-s3c24xx/mach-vstms.c index 40868c0e0a68..6b706c915387 100644 --- a/arch/arm/mach-s3c24xx/mach-vstms.c +++ b/arch/arm/mach-s3c24xx/mach-vstms.c @@ -142,11 +142,16 @@ static void __init vstms_fixup(struct tag *tags, char **cmdline, static void __init vstms_map_io(void) { s3c24xx_init_io(vstms_iodesc, ARRAY_SIZE(vstms_iodesc)); - s3c24xx_init_clocks(12000000); s3c24xx_init_uarts(vstms_uartcfgs, ARRAY_SIZE(vstms_uartcfgs)); samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4); } +static void __init vstms_init_time(void) +{ + s3c2412_init_clocks(12000000); + samsung_timer_init(); +} + static void __init vstms_init(void) { s3c_i2c0_set_platdata(NULL); @@ -162,6 +167,6 @@ MACHINE_START(VSTMS, "VSTMS") .init_irq = s3c2412_init_irq, .init_machine = vstms_init, .map_io = vstms_map_io, - .init_time = samsung_timer_init, + .init_time = vstms_init_time, .restart = s3c2412_restart, MACHINE_END diff --git a/arch/arm/mach-s3c24xx/s3c2412.c b/arch/arm/mach-s3c24xx/s3c2412.c index 657cbaca80ac..d49f52fbc842 100644 --- a/arch/arm/mach-s3c24xx/s3c2412.c +++ b/arch/arm/mach-s3c24xx/s3c2412.c @@ -173,49 +173,6 @@ void __init s3c2412_map_io(void) void __init_or_cpufreq s3c2412_setup_clocks(void) { - struct clk *xtal_clk; - unsigned long tmp; - unsigned long xtal; - unsigned long fclk; - unsigned long hclk; - unsigned long pclk; - - xtal_clk = clk_get(NULL, "xtal"); - xtal = clk_get_rate(xtal_clk); - clk_put(xtal_clk); - - /* now we've got our machine bits initialised, work out what - * clocks we've got */ - - fclk = s3c24xx_get_pll(__raw_readl(S3C2410_MPLLCON), xtal * 2); - - clk_mpll.rate = fclk; - - tmp = __raw_readl(S3C2410_CLKDIVN); - - /* work out clock scalings */ - - hclk = fclk / ((tmp & S3C2412_CLKDIVN_HDIVN_MASK) + 1); - hclk /= ((tmp & S3C2412_CLKDIVN_ARMDIVN) ? 2 : 1); - pclk = hclk / ((tmp & S3C2412_CLKDIVN_PDIVN) ? 2 : 1); - - /* print brieft summary of clocks, etc */ - - printk("S3C2412: core %ld.%03ld MHz, memory %ld.%03ld MHz, peripheral %ld.%03ld MHz\n", - print_mhz(fclk), print_mhz(hclk), print_mhz(pclk)); - - s3c24xx_setup_clocks(fclk, hclk, pclk); -} - -void __init s3c2412_init_clocks(int xtal) -{ - /* initialise the clocks here, to allow other things like the - * console to use them - */ - - s3c24xx_register_baseclocks(xtal); - s3c2412_setup_clocks(); - s3c2412_baseclk_add(); } /* need to register the subsystem before we actually register the device, and From 72dc392ae5bbad3477053ac4c5708dba6706ffa0 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 15 Apr 2014 14:33:57 +0200 Subject: [PATCH 18/87] ARM: shmobile: r8a7740: Remove unused r8a7740_add_early_devices_dt() It was removed in commit 744fdc8dc0e22cc5b61ee1bcde9375f188daa330 ("ARM: shmobile: r8a7740: Prepare for reference DT setup"), but accidentally resurrected in commit 88378837780166d67a11142cd6f76596c0a2d8c3 ("ARM: shmobile: Remove unused r8a7740 auxdata table"). Signed-off-by: Geert Uytterhoeven Reviewed-by: Laurent Pinchart Signed-off-by: Simon Horman --- arch/arm/mach-shmobile/setup-r8a7740.c | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/arch/arm/mach-shmobile/setup-r8a7740.c b/arch/arm/mach-shmobile/setup-r8a7740.c index 8f3c68101d59..cba3a07a97c2 100644 --- a/arch/arm/mach-shmobile/setup-r8a7740.c +++ b/arch/arm/mach-shmobile/setup-r8a7740.c @@ -869,17 +869,6 @@ void __init r8a7740_add_early_devices(void) #ifdef CONFIG_USE_OF -void __init r8a7740_add_early_devices_dt(void) -{ - shmobile_setup_delay(800, 1, 3); /* Cortex-A9 @ 800MHz */ - - early_platform_add_devices(r8a7740_early_devices, - ARRAY_SIZE(r8a7740_early_devices)); - - /* setup early console here as well */ - shmobile_setup_console(); -} - void __init r8a7740_add_standard_devices_dt(void) { platform_add_devices(r8a7740_devices_dt, From 1fba31f047639a6c7accf4f6d075a6cf9eacecc0 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 15 Apr 2014 14:33:59 +0200 Subject: [PATCH 19/87] ARM: shmobile: sh7372: Call sh7372_add_early_devices() instead of open coding Signed-off-by: Geert Uytterhoeven Reviewed-by: Laurent Pinchart Signed-off-by: Simon Horman --- arch/arm/mach-shmobile/setup-sh7372.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/arch/arm/mach-shmobile/setup-sh7372.c b/arch/arm/mach-shmobile/setup-sh7372.c index 27301278c208..f8176b051be4 100644 --- a/arch/arm/mach-shmobile/setup-sh7372.c +++ b/arch/arm/mach-shmobile/setup-sh7372.c @@ -1037,11 +1037,7 @@ void __init sh7372_add_early_devices_dt(void) { shmobile_setup_delay(800, 1, 3); /* Cortex-A8 @ 800MHz */ - early_platform_add_devices(sh7372_early_devices, - ARRAY_SIZE(sh7372_early_devices)); - - /* setup early console here as well */ - shmobile_setup_console(); + sh7372_add_early_devices(); } void __init sh7372_add_standard_devices_dt(void) From bb6c3d58c36adb205b4bf233fd1c4079e02a6811 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 15 Apr 2014 14:33:58 +0200 Subject: [PATCH 20/87] ARM: shmobile: r8a7740: Make r8a7740_meram_workaround() __init It's called from eva_init() only, which is __init Signed-off-by: Geert Uytterhoeven Reviewed-by: Laurent Pinchart Signed-off-by: Simon Horman --- arch/arm/mach-shmobile/setup-r8a7740.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-shmobile/setup-r8a7740.c b/arch/arm/mach-shmobile/setup-r8a7740.c index cba3a07a97c2..a177a7b3bdbd 100644 --- a/arch/arm/mach-shmobile/setup-r8a7740.c +++ b/arch/arm/mach-shmobile/setup-r8a7740.c @@ -765,7 +765,7 @@ static struct platform_device *r8a7740_late_devices[] __initdata = { * "Media RAM (MERAM)" on r8a7740 documentation */ #define MEBUFCNTR 0xFE950098 -void r8a7740_meram_workaround(void) +void __init r8a7740_meram_workaround(void) { void __iomem *reg; From 55400f3a1f89e39761f45c19f6e4235a329c400b Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Tue, 22 Apr 2014 14:15:52 -0500 Subject: [PATCH 21/87] ARM: mvebu: clean-up unneeded kconfig selects Multi-platform support implies all these options are already selected and individual platforms don't need to select them. Signed-off-by: Rob Herring Cc: Jason Cooper Cc: Andrew Lunn Cc: Gregory Clement Cc: Sebastian Hesselbarth --- arch/arm/mach-mvebu/Kconfig | 6 ------ 1 file changed, 6 deletions(-) diff --git a/arch/arm/mach-mvebu/Kconfig b/arch/arm/mach-mvebu/Kconfig index 3f73eecbcfb0..bfc5af18e483 100644 --- a/arch/arm/mach-mvebu/Kconfig +++ b/arch/arm/mach-mvebu/Kconfig @@ -3,7 +3,6 @@ config ARCH_MVEBU select ARCH_SUPPORTS_BIG_ENDIAN select CLKSRC_MMIO select GENERIC_IRQ_CHIP - select IRQ_DOMAIN select PINCTRL select PLAT_ORION select MVEBU_MBUS @@ -11,7 +10,6 @@ config ARCH_MVEBU select ARCH_REQUIRE_GPIOLIB select MIGHT_HAVE_PCI select PCI_QUIRKS if PCI - select OF_ADDRESS_PCI if ARCH_MVEBU @@ -38,7 +36,6 @@ config MACH_ARMADA_375 select ARM_ERRATA_753970 select ARM_GIC select ARMADA_375_CLK - select CPU_V7 select MACH_MVEBU_V7 select PINCTRL_ARMADA_375 help @@ -51,7 +48,6 @@ config MACH_ARMADA_38X select ARM_ERRATA_753970 select ARM_GIC select ARMADA_38X_CLK - select CPU_V7 select MACH_MVEBU_V7 select PINCTRL_ARMADA_38X help @@ -86,13 +82,11 @@ config MACH_KIRKWOOD select ARCH_REQUIRE_GPIOLIB select CPU_FEROCEON select KIRKWOOD_CLK - select OF_IRQ select ORION_IRQCHIP select ORION_TIMER select PCI select PCI_QUIRKS select PINCTRL_KIRKWOOD - select USE_OF help Say 'Y' here if you want your kernel to support boards based on the Marvell Kirkwood device tree. From 9f0db8b9c466e0e5f3bc86a1389c790ca16643a8 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Tue, 22 Apr 2014 14:29:01 -0500 Subject: [PATCH 22/87] ARM: bcm: clean-up unneeded kconfig selects Multi-platform support implies all these options are already selected and individual platforms don't need to select them. Signed-off-by: Rob Herring Cc: Christian Daudt Cc: Matt Porter Cc: bcm-kernel-feedback-list@broadcom.com --- arch/arm/mach-bcm/Kconfig | 8 -------- 1 file changed, 8 deletions(-) diff --git a/arch/arm/mach-bcm/Kconfig b/arch/arm/mach-bcm/Kconfig index 49c914cd9c7a..9f19636fea2f 100644 --- a/arch/arm/mach-bcm/Kconfig +++ b/arch/arm/mach-bcm/Kconfig @@ -11,7 +11,6 @@ menu "Broadcom SoC Selection" config ARCH_BCM_MOBILE bool "Broadcom Mobile SoC" if ARCH_MULTI_V7 - depends on MMU select ARCH_REQUIRE_GPIOLIB select ARM_ERRATA_754322 select ARM_ERRATA_764369 if SMP @@ -33,10 +32,7 @@ config ARCH_BCM2835 select ARM_AMBA select ARM_ERRATA_411920 select ARM_TIMER_SP804 - select CLKDEV_LOOKUP select CLKSRC_OF - select CPU_V6 - select GENERIC_CLOCKEVENTS select PINCTRL select PINCTRL_BCM2835 help @@ -45,14 +41,10 @@ config ARCH_BCM2835 config ARCH_BCM_5301X bool "Broadcom BCM470X / BCM5301X ARM SoC" if ARCH_MULTI_V7 - depends on MMU select ARM_GIC select CACHE_L2X0 select HAVE_ARM_SCU if SMP select HAVE_ARM_TWD if SMP - select HAVE_SMP - select COMMON_CLK - select GENERIC_CLOCKEVENTS select ARM_GLOBAL_TIMER select CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK select MIGHT_HAVE_PCI From e7062b101537a0c4f4a8d725321772eb78100074 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Tue, 22 Apr 2014 14:29:01 -0500 Subject: [PATCH 23/87] ARM: qcom: clean-up unneeded kconfig selects Multi-platform support implies all these options are already selected and individual platforms don't need to select them. Signed-off-by: Rob Herring Cc: Kumar Gala Cc: David Brown Cc: linux-arm-msm@vger.kernel.org --- arch/arm/mach-qcom/Kconfig | 2 -- 1 file changed, 2 deletions(-) diff --git a/arch/arm/mach-qcom/Kconfig b/arch/arm/mach-qcom/Kconfig index a028be234334..6aa22147cace 100644 --- a/arch/arm/mach-qcom/Kconfig +++ b/arch/arm/mach-qcom/Kconfig @@ -3,8 +3,6 @@ config ARCH_QCOM select ARCH_REQUIRE_GPIOLIB select ARM_GIC select CLKSRC_OF - select GENERIC_CLOCKEVENTS - select HAVE_SMP select QCOM_SCM if SMP help Support for Qualcomm's devicetree based systems. From 1892bbcdd41b5e2582000ab21e9f6b734d005a71 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Tue, 15 Apr 2014 07:37:19 -0500 Subject: [PATCH 24/87] ARM: bcm: clean up config and build targets Currently CONFIG_ARCH_BCM_MOBILE is used to select all (both) Broadcom mobile SoC families. Instead, use that only as a config menu switch, and define specific symbols like ARCH_BCM_281XX to select a particular SoC family. If ARCH_BCM_MOBILE is selected, all of the SoCs will be selected by default, but this way each can be disabled individually as well. Note that BCM281xx and BCM21664 both require the SMC and L2 cache control code, so that code will be built based on ARCH_BCM_MOBILE. Signed-off-by: Alex Elder [mporter: added ARM: to the description] Signed-off-by: Matt Porter --- arch/arm/mach-bcm/Kconfig | 28 ++++++++++++++++++++++++---- arch/arm/mach-bcm/Makefile | 15 ++++++++++++--- 2 files changed, 36 insertions(+), 7 deletions(-) diff --git a/arch/arm/mach-bcm/Kconfig b/arch/arm/mach-bcm/Kconfig index 49c914cd9c7a..5f5740fc334f 100644 --- a/arch/arm/mach-bcm/Kconfig +++ b/arch/arm/mach-bcm/Kconfig @@ -10,7 +10,7 @@ if ARCH_BCM menu "Broadcom SoC Selection" config ARCH_BCM_MOBILE - bool "Broadcom Mobile SoC" if ARCH_MULTI_V7 + bool "Broadcom Mobile SoC Support" if ARCH_MULTI_V7 depends on MMU select ARCH_REQUIRE_GPIOLIB select ARM_ERRATA_754322 @@ -23,9 +23,29 @@ config ARCH_BCM_MOBILE select PINCTRL help This enables support for systems based on Broadcom mobile SoCs. - It currently supports the 'BCM281XX' family, which includes - BCM11130, BCM11140, BCM11351, BCM28145 and - BCM28155 variants. + +if ARCH_BCM_MOBILE + +menu "Broadcom Mobile SoC Selection" + +config ARCH_BCM_281XX + bool "Broadcom BCM281XX SoC family" + default y + help + Enable support for the the BCM281XX family, which includes + BCM11130, BCM11140, BCM11351, BCM28145 and BCM28155 + variants. + +config ARCH_BCM_21664 + bool "Broadcom BCM21664 SoC family" + default y + help + Enable support for the the BCM21664 family, which includes + BCM21663 and BCM21664 variants. + +endmenu + +endif config ARCH_BCM2835 bool "Broadcom BCM2835 family" if ARCH_MULTI_V6 diff --git a/arch/arm/mach-bcm/Makefile b/arch/arm/mach-bcm/Makefile index a326b28c4406..7fb9b0402204 100644 --- a/arch/arm/mach-bcm/Makefile +++ b/arch/arm/mach-bcm/Makefile @@ -10,10 +10,19 @@ # of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. -obj-$(CONFIG_ARCH_BCM_MOBILE) := board_bcm281xx.o board_bcm21664.o \ - bcm_kona_smc.o bcm_kona_smc_asm.o kona.o -obj-$(CONFIG_ARCH_BCM2835) += board_bcm2835.o +# BCM281XX +obj-$(CONFIG_ARCH_BCM_281XX) += board_bcm281xx.o +# BCM21664 +obj-$(CONFIG_ARCH_BCM_21664) += board_bcm21664.o + +# BCM281XX and BCM21664 L2 cache control +obj-$(CONFIG_ARCH_BCM_MOBILE) += bcm_kona_smc.o bcm_kona_smc_asm.o kona.o plus_sec := $(call as-instr,.arch_extension sec,+sec) AFLAGS_bcm_kona_smc_asm.o :=-Wa,-march=armv7-a$(plus_sec) + +# BCM2835 +obj-$(CONFIG_ARCH_BCM2835) += board_bcm2835.o + +# BCM5301X obj-$(CONFIG_ARCH_BCM_5301X) += bcm_5301x.o From e80eef33f4596a247fdcf7d67d54d95d9dfaf7d3 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 21 Apr 2014 16:53:02 -0500 Subject: [PATCH 25/87] ARM: bcm: use memory accessors for ioremapped area The pointer used to pass parameters to an "smc" call is produced through a call to ioremap(). As such, we should be using functions like writel() to access it. Signed-off-by: Alex Elder Reviewed-by: Tim Kryger Reviewed-by: Markus Mayer Reviewed-by: Matt Porter Signed-off-by: Matt Porter --- arch/arm/mach-bcm/bcm_kona_smc.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/arm/mach-bcm/bcm_kona_smc.c b/arch/arm/mach-bcm/bcm_kona_smc.c index 5e31e918f325..d881c72ee878 100644 --- a/arch/arm/mach-bcm/bcm_kona_smc.c +++ b/arch/arm/mach-bcm/bcm_kona_smc.c @@ -79,11 +79,11 @@ static void __bcm_kona_smc(void *info) /* Check map in the bounce area */ BUG_ON(!bridge_data.initialized); - /* Copy one 32 bit word into the bounce area */ - args[0] = data->arg0; - args[1] = data->arg1; - args[2] = data->arg2; - args[3] = data->arg3; + /* Copy the four 32 bit argument values into the bounce area */ + writel_relaxed(data->arg0, args++); + writel_relaxed(data->arg1, args++); + writel_relaxed(data->arg2, args++); + writel(data->arg3, args); /* Flush caches for input data passed to Secure Monitor */ if (data->service_id != SSAPI_BRCM_START_VC_CORE) From 5c4cee2fe8de7c14e60502b02e7c3bc7acba0530 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 21 Apr 2014 16:53:03 -0500 Subject: [PATCH 26/87] ARM: bcm: err, don't BUG() on SMC init failures Several conditions in bcm_kona_smc_init() are handled with BUG_ON(). That function is capable of returning an error, so do that instead. Also, don't assume of_get_address() returns a valid pointer. Signed-off-by: Alex Elder Reviewed-by: Tim Kryger Reviewed-by: Markus Mayer Reviewed-by: Matt Porter Signed-off-by: Matt Porter --- arch/arm/mach-bcm/bcm_kona_smc.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/arch/arm/mach-bcm/bcm_kona_smc.c b/arch/arm/mach-bcm/bcm_kona_smc.c index d881c72ee878..ddc2f17217ee 100644 --- a/arch/arm/mach-bcm/bcm_kona_smc.c +++ b/arch/arm/mach-bcm/bcm_kona_smc.c @@ -45,6 +45,7 @@ static const struct of_device_id bcm_kona_smc_ids[] __initconst = { int __init bcm_kona_smc_init(void) { struct device_node *node; + const __be32 *prop_val; /* Read buffer addr and size from the device tree node */ node = of_find_matching_node(NULL, bcm_kona_smc_ids); @@ -52,12 +53,17 @@ int __init bcm_kona_smc_init(void) return -ENODEV; /* Don't care about size or flags of the DT node */ - bridge_data.buffer_addr = - be32_to_cpu(*of_get_address(node, 0, NULL, NULL)); - BUG_ON(!bridge_data.buffer_addr); + prop_val = of_get_address(node, 0, NULL, NULL); + if (!prop_val) + return -EINVAL; + + bridge_data.buffer_addr = be32_to_cpu(*prop_val); + if (!bridge_data.buffer_addr) + return -EINVAL; bridge_data.bounce = of_iomap(node, 0); - BUG_ON(!bridge_data.bounce); + if (!bridge_data.bounce) + return -ENOMEM; bridge_data.initialized = 1; From c64756cca2fb4da96fcc71e376d712297aedc4a2 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 21 Apr 2014 16:53:04 -0500 Subject: [PATCH 27/87] ARM: bcm: clean up SMC code This patch just does some simple cleanup in "bcm_kona_smc.c": - Get rid of the secure_bridge_data structure. Instead, just define two globals that record the physical and virtual addresses of the SMC arguments buffer. Use "buffer" instead of "bounce" in their names. Drop of the erroneous __iomem annotation for the physical address. - Get rid of the initialized flag and just use a non-null buffer address to indicate that. - Get the size of the memory region when fetching the SMC arguments buffer location from the device tree. Use it to call ioremap() directly rather than requiring of_iomap() to go look it up again. - Do some additional validation on that memory region size. - Flush caches unconditionally in __bcm_kona_smc(); nothing supplies SSAPI_BRCM_START_VC_CORE as a service id. - Drop a needless initialization of "rc" in __bcm_kona_smc(). It also deletes most of the content of "bcm_kona_smc.h" because it's never actually used and is of questionable value anyway. Signed-off-by: Alex Elder Reviewed-by: Tim Kryger Reviewed-by: Markus Mayer Reviewed-by: Matt Porter Signed-off-by: Matt Porter --- arch/arm/mach-bcm/bcm_kona_smc.c | 45 +++++++++++++++---------------- arch/arm/mach-bcm/bcm_kona_smc.h | 46 ++------------------------------ 2 files changed, 24 insertions(+), 67 deletions(-) diff --git a/arch/arm/mach-bcm/bcm_kona_smc.c b/arch/arm/mach-bcm/bcm_kona_smc.c index ddc2f17217ee..0d2bfe2bcfa8 100644 --- a/arch/arm/mach-bcm/bcm_kona_smc.c +++ b/arch/arm/mach-bcm/bcm_kona_smc.c @@ -21,11 +21,8 @@ #include "bcm_kona_smc.h" -struct secure_bridge_data { - void __iomem *bounce; /* virtual address */ - u32 __iomem buffer_addr; /* physical address */ - int initialized; -} bridge_data; +static u32 bcm_smc_buffer_phys; /* physical address */ +static void __iomem *bcm_smc_buffer; /* virtual address */ struct bcm_kona_smc_data { unsigned service_id; @@ -41,31 +38,37 @@ static const struct of_device_id bcm_kona_smc_ids[] __initconst = { {}, }; -/* Map in the bounce area */ +/* Map in the args buffer area */ int __init bcm_kona_smc_init(void) { struct device_node *node; const __be32 *prop_val; + u64 prop_size = 0; + unsigned long buffer_size; + u32 buffer_phys; /* Read buffer addr and size from the device tree node */ node = of_find_matching_node(NULL, bcm_kona_smc_ids); if (!node) return -ENODEV; - /* Don't care about size or flags of the DT node */ - prop_val = of_get_address(node, 0, NULL, NULL); + prop_val = of_get_address(node, 0, &prop_size, NULL); if (!prop_val) return -EINVAL; - bridge_data.buffer_addr = be32_to_cpu(*prop_val); - if (!bridge_data.buffer_addr) + /* We assume space for four 32-bit arguments */ + if (prop_size < 4 * sizeof(u32) || prop_size > (u64)ULONG_MAX) + return -EINVAL; + buffer_size = (unsigned long)prop_size; + + buffer_phys = be32_to_cpup(prop_val); + if (!buffer_phys) return -EINVAL; - bridge_data.bounce = of_iomap(node, 0); - if (!bridge_data.bounce) + bcm_smc_buffer = ioremap(buffer_phys, buffer_size); + if (!bcm_smc_buffer) return -ENOMEM; - - bridge_data.initialized = 1; + bcm_smc_buffer_phys = buffer_phys; pr_info("Kona Secure API initialized\n"); @@ -76,14 +79,11 @@ int __init bcm_kona_smc_init(void) static void __bcm_kona_smc(void *info) { struct bcm_kona_smc_data *data = info; - u32 *args = bridge_data.bounce; - int rc = 0; + u32 *args = bcm_smc_buffer; + int rc; - /* Must run on CPU 0 */ BUG_ON(smp_processor_id() != 0); - - /* Check map in the bounce area */ - BUG_ON(!bridge_data.initialized); + BUG_ON(!args); /* Copy the four 32 bit argument values into the bounce area */ writel_relaxed(data->arg0, args++); @@ -92,11 +92,10 @@ static void __bcm_kona_smc(void *info) writel(data->arg3, args); /* Flush caches for input data passed to Secure Monitor */ - if (data->service_id != SSAPI_BRCM_START_VC_CORE) - flush_cache_all(); + flush_cache_all(); /* Trap into Secure Monitor */ - rc = bcm_kona_smc_asm(data->service_id, bridge_data.buffer_addr); + rc = bcm_kona_smc_asm(data->service_id, bcm_smc_buffer_phys); if (rc != SEC_ROM_RET_OK) pr_err("Secure Monitor call failed (0x%x)!\n", rc); diff --git a/arch/arm/mach-bcm/bcm_kona_smc.h b/arch/arm/mach-bcm/bcm_kona_smc.h index d098a7e76744..629e64a89982 100644 --- a/arch/arm/mach-bcm/bcm_kona_smc.h +++ b/arch/arm/mach-bcm/bcm_kona_smc.h @@ -15,54 +15,12 @@ #define BCM_KONA_SMC_H #include -#define FLAGS (SEC_ROM_ICACHE_ENABLE_MASK | SEC_ROM_DCACHE_ENABLE_MASK | \ - SEC_ROM_IRQ_ENABLE_MASK | SEC_ROM_FIQ_ENABLE_MASK) -/*! - * Definitions for IRQ & FIQ Mask for ARM - */ - -#define FIQ_IRQ_MASK 0xC0 -#define FIQ_MASK 0x40 -#define IRQ_MASK 0x80 - -/*! - * Secure Mode FLAGs - */ - -/* When set, enables ICache within the secure mode */ -#define SEC_ROM_ICACHE_ENABLE_MASK 0x00000001 - -/* When set, enables DCache within the secure mode */ -#define SEC_ROM_DCACHE_ENABLE_MASK 0x00000002 - -/* When set, enables IRQ within the secure mode */ -#define SEC_ROM_IRQ_ENABLE_MASK 0x00000004 - -/* When set, enables FIQ within the secure mode */ -#define SEC_ROM_FIQ_ENABLE_MASK 0x00000008 - -/* When set, enables Unified L2 cache within the secure mode */ -#define SEC_ROM_UL2_CACHE_ENABLE_MASK 0x00000010 - -/* Broadcom Secure Service API Service IDs */ -#define SSAPI_DORMANT_ENTRY_SERV 0x01000000 -#define SSAPI_PUBLIC_OTP_SERV 0x01000001 -#define SSAPI_ENABLE_L2_CACHE 0x01000002 -#define SSAPI_DISABLE_L2_CACHE 0x01000003 -#define SSAPI_WRITE_SCU_STATUS 0x01000004 -#define SSAPI_WRITE_PWR_GATE 0x01000005 - -/* Broadcom Secure Service API Return Codes */ +/* Broadcom Secure Service API service IDs, return codes, and exit codes */ +#define SSAPI_ENABLE_L2_CACHE 0x01000002 #define SEC_ROM_RET_OK 0x00000001 -#define SEC_ROM_RET_FAIL 0x00000009 - -#define SSAPI_RET_FROM_INT_SERV 0x4 #define SEC_EXIT_NORMAL 0x1 -#define SSAPI_ROW_AES 0x0E000006 -#define SSAPI_BRCM_START_VC_CORE 0x0E000008 - #ifndef __ASSEMBLY__ extern int __init bcm_kona_smc_init(void); From 6c90f10864d1f7492ebe4c90465a9c9797ce649e Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 21 Apr 2014 16:53:05 -0500 Subject: [PATCH 28/87] ARM: bcm: have bcm_kona_smc() return request result Currently it is assumed that SEC_ROM_RET_OK is the only valid "good" result of a secure monitor request. However the values that can be returned by a secure monitor request are dependent on which service id was provided. We therefore should handle the result in a request-dependent way. The most natural way to do that is to have the initiator of the request--where bcm_kona_smc() is called--handle the result in a way appropriate to the request. An "smc" operation must be performed only on core 0, while the request can be initiated from any core. To pass back the request result, we add a new field to the bcm_kona_smc_data structure, and have bcm_kona_smc() return that value rather than 0. There's only one caller right now. Move the existing check of the result out of __bcm_kona_smc() and into the kona_l2_cache_init() where the SSAPI_ENABLE_L2_CACHE request is initiated. Signed-off-by: Alex Elder Reviewed-by: Tim Kryger Reviewed-by: Markus Mayer Reviewed-by: Matt Porter Signed-off-by: Matt Porter --- arch/arm/mach-bcm/bcm_kona_smc.c | 12 +++++------- arch/arm/mach-bcm/kona.c | 8 +++++++- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/arch/arm/mach-bcm/bcm_kona_smc.c b/arch/arm/mach-bcm/bcm_kona_smc.c index 0d2bfe2bcfa8..47cf360f985b 100644 --- a/arch/arm/mach-bcm/bcm_kona_smc.c +++ b/arch/arm/mach-bcm/bcm_kona_smc.c @@ -30,6 +30,7 @@ struct bcm_kona_smc_data { unsigned arg1; unsigned arg2; unsigned arg3; + unsigned result; }; static const struct of_device_id bcm_kona_smc_ids[] __initconst = { @@ -80,7 +81,6 @@ static void __bcm_kona_smc(void *info) { struct bcm_kona_smc_data *data = info; u32 *args = bcm_smc_buffer; - int rc; BUG_ON(smp_processor_id() != 0); BUG_ON(!args); @@ -94,11 +94,8 @@ static void __bcm_kona_smc(void *info) /* Flush caches for input data passed to Secure Monitor */ flush_cache_all(); - /* Trap into Secure Monitor */ - rc = bcm_kona_smc_asm(data->service_id, bcm_smc_buffer_phys); - - if (rc != SEC_ROM_RET_OK) - pr_err("Secure Monitor call failed (0x%x)!\n", rc); + /* Trap into Secure Monitor and record the request result */ + data->result = bcm_kona_smc_asm(data->service_id, bcm_smc_buffer_phys); } unsigned bcm_kona_smc(unsigned service_id, unsigned arg0, unsigned arg1, @@ -111,6 +108,7 @@ unsigned bcm_kona_smc(unsigned service_id, unsigned arg0, unsigned arg1, data.arg1 = arg1; data.arg2 = arg2; data.arg3 = arg3; + data.result = 0; /* * Due to a limitation of the secure monitor, we must use the SMP @@ -123,5 +121,5 @@ unsigned bcm_kona_smc(unsigned service_id, unsigned arg0, unsigned arg1, put_cpu(); - return 0; + return data.result; } diff --git a/arch/arm/mach-bcm/kona.c b/arch/arm/mach-bcm/kona.c index 768bc2837bf5..ecdd71340a46 100644 --- a/arch/arm/mach-bcm/kona.c +++ b/arch/arm/mach-bcm/kona.c @@ -19,6 +19,7 @@ void __init kona_l2_cache_init(void) { + unsigned int result; int ret; if (!IS_ENABLED(CONFIG_CACHE_L2X0)) @@ -31,7 +32,12 @@ void __init kona_l2_cache_init(void) return; } - bcm_kona_smc(SSAPI_ENABLE_L2_CACHE, 0, 0, 0, 0); + result = bcm_kona_smc(SSAPI_ENABLE_L2_CACHE, 0, 0, 0, 0); + if (result != SEC_ROM_RET_OK) { + pr_err("Secure Monitor call failed (%u)! Skipping L2 init.\n", + result); + return; + } /* * The aux_val and aux_mask have no effect since L2 cache is already From 35138d52f18c3f757f12d54c0962a755bcf218f3 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 21 Apr 2014 16:53:06 -0500 Subject: [PATCH 29/87] ARM: bcm: don't special-case CPU 0 in bcm_kona_smc() There's logic in bcm_kona_smc() to ensure __bcm_kona_smc() gets called on CPU 0; if already executing on CPU 0, that function is called directly. The direct call is not protected from interrupts, however, which is not safe. Note that smp_call_function_single() is designed to handle the case where the target cpu is the current one. It also gets a reference to the CPU and disables IRQs across the call. So we can simplify things and at the same time be protected against interrupts by calling smp_call_function_single() unconditionally. Signed-off-by: Alex Elder Reviewed-by: Tim Kryger Reviewed-by: Markus Mayer Reviewed-by: Matt Porter Signed-off-by: Matt Porter --- arch/arm/mach-bcm/bcm_kona_smc.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/arch/arm/mach-bcm/bcm_kona_smc.c b/arch/arm/mach-bcm/bcm_kona_smc.c index 47cf360f985b..6fdcf96ca54e 100644 --- a/arch/arm/mach-bcm/bcm_kona_smc.c +++ b/arch/arm/mach-bcm/bcm_kona_smc.c @@ -114,12 +114,7 @@ unsigned bcm_kona_smc(unsigned service_id, unsigned arg0, unsigned arg1, * Due to a limitation of the secure monitor, we must use the SMP * infrastructure to forward all secure monitor calls to Core 0. */ - if (get_cpu() != 0) - smp_call_function_single(0, __bcm_kona_smc, (void *)&data, 1); - else - __bcm_kona_smc(&data); - - put_cpu(); + smp_call_function_single(0, __bcm_kona_smc, &data, 1); return data.result; } From 7b5fe9c9115c92b7e6297216c789268961a19f98 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 21 Apr 2014 16:53:07 -0500 Subject: [PATCH 30/87] ARM: bcm: config option for l2 cache support Add a new config option ARCH_BCM_MOBILE_L2_CACHE that allows support for level-2 cache to be enabled or disabled at build time for BCM218XX and BCM21664 family SoCs. Build support for SMC only if it's required (currently it's only required for to support level 2 cache control). If arch/arm/mach-bcm/kona.c gets compiled, ARCH_BCM_MOBILE_L2_CACHE must have been selected, which implies CONFIG_CACHE_L2X0 is set. There is therefore no need to check CONFIG_CACHE_L2X0 at the top of kona_l2_cache_init(), so get rid of that check. Signed-off-by: Alex Elder Reviewed-by: Tim Kryger Reviewed-by: Markus Mayer Reviewed-by: Matt Porter Signed-off-by: Matt Porter --- arch/arm/mach-bcm/Kconfig | 12 +++++++++++- arch/arm/mach-bcm/Makefile | 5 ++++- arch/arm/mach-bcm/kona.c | 3 --- arch/arm/mach-bcm/kona.h | 5 +++++ 4 files changed, 20 insertions(+), 5 deletions(-) diff --git a/arch/arm/mach-bcm/Kconfig b/arch/arm/mach-bcm/Kconfig index 5f5740fc334f..28f90a01e3ac 100644 --- a/arch/arm/mach-bcm/Kconfig +++ b/arch/arm/mach-bcm/Kconfig @@ -18,7 +18,6 @@ config ARCH_BCM_MOBILE select ARM_GIC select GPIO_BCM_KONA select TICK_ONESHOT - select CACHE_L2X0 select HAVE_ARM_ARCH_TIMER select PINCTRL help @@ -43,6 +42,17 @@ config ARCH_BCM_21664 Enable support for the the BCM21664 family, which includes BCM21663 and BCM21664 variants. +config ARCH_BCM_MOBILE_L2_CACHE + bool "Broadcom mobile SoC level 2 cache support" + depends on (ARCH_BCM_281XX || ARCH_BCM_21664) + default y + select CACHE_L2X0 + select ARCH_BCM_MOBILE_SMC + +config ARCH_BCM_MOBILE_SMC + bool + depends on ARCH_BCM_281XX || ARCH_BCM_21664 + endmenu endif diff --git a/arch/arm/mach-bcm/Makefile b/arch/arm/mach-bcm/Makefile index 7fb9b0402204..51549814f7cd 100644 --- a/arch/arm/mach-bcm/Makefile +++ b/arch/arm/mach-bcm/Makefile @@ -17,7 +17,10 @@ obj-$(CONFIG_ARCH_BCM_281XX) += board_bcm281xx.o obj-$(CONFIG_ARCH_BCM_21664) += board_bcm21664.o # BCM281XX and BCM21664 L2 cache control -obj-$(CONFIG_ARCH_BCM_MOBILE) += bcm_kona_smc.o bcm_kona_smc_asm.o kona.o +obj-$(CONFIG_ARCH_BCM_MOBILE_L2_CACHE) += kona.o + +# Support for secure monitor traps +obj-$(CONFIG_ARCH_BCM_MOBILE_SMC) += bcm_kona_smc.o bcm_kona_smc_asm.o plus_sec := $(call as-instr,.arch_extension sec,+sec) AFLAGS_bcm_kona_smc_asm.o :=-Wa,-march=armv7-a$(plus_sec) diff --git a/arch/arm/mach-bcm/kona.c b/arch/arm/mach-bcm/kona.c index ecdd71340a46..60b5dd5c866c 100644 --- a/arch/arm/mach-bcm/kona.c +++ b/arch/arm/mach-bcm/kona.c @@ -22,9 +22,6 @@ void __init kona_l2_cache_init(void) unsigned int result; int ret; - if (!IS_ENABLED(CONFIG_CACHE_L2X0)) - return; - ret = bcm_kona_smc_init(); if (ret) { pr_info("Secure API not available (%d). Skipping L2 init.\n", diff --git a/arch/arm/mach-bcm/kona.h b/arch/arm/mach-bcm/kona.h index 3a7a017c29cd..110185f7aad3 100644 --- a/arch/arm/mach-bcm/kona.h +++ b/arch/arm/mach-bcm/kona.h @@ -11,4 +11,9 @@ * GNU General Public License for more details. */ +#ifdef CONFIG_ARCH_BCM_MOBILE_L2_CACHE + void __init kona_l2_cache_init(void); +#else +#define kona_l2_cache_init() ((void)0) +#endif From d5c627b5751ed44c0eff6c12e658097edf6338de Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 21 Apr 2014 16:53:08 -0500 Subject: [PATCH 31/87] ARM: bcm: tidy up a few includes Clean up a few header file includes, eliminating a few that are not really needed and putting in their place some that are. Signed-off-by: Alex Elder Reviewed-by: Matt Porter Signed-off-by: Matt Porter --- arch/arm/mach-bcm/board_bcm21664.c | 3 +-- arch/arm/mach-bcm/kona.c | 5 +++-- arch/arm/mach-bcm/kona.h | 3 +-- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/arch/arm/mach-bcm/board_bcm21664.c b/arch/arm/mach-bcm/board_bcm21664.c index acc1573fd005..1091637638f1 100644 --- a/arch/arm/mach-bcm/board_bcm21664.c +++ b/arch/arm/mach-bcm/board_bcm21664.c @@ -11,13 +11,12 @@ * GNU General Public License for more details. */ -#include #include #include +#include #include -#include "bcm_kona_smc.h" #include "kona.h" #define RSTMGR_DT_STRING "brcm,bcm21664-resetmgr" diff --git a/arch/arm/mach-bcm/kona.c b/arch/arm/mach-bcm/kona.c index 60b5dd5c866c..b31970377c20 100644 --- a/arch/arm/mach-bcm/kona.c +++ b/arch/arm/mach-bcm/kona.c @@ -11,11 +11,12 @@ * GNU General Public License for more details. */ -#include + +#include +#include #include #include "bcm_kona_smc.h" -#include "kona.h" void __init kona_l2_cache_init(void) { diff --git a/arch/arm/mach-bcm/kona.h b/arch/arm/mach-bcm/kona.h index 110185f7aad3..46f84a95ab1c 100644 --- a/arch/arm/mach-bcm/kona.h +++ b/arch/arm/mach-bcm/kona.h @@ -12,8 +12,7 @@ */ #ifdef CONFIG_ARCH_BCM_MOBILE_L2_CACHE - -void __init kona_l2_cache_init(void); +void kona_l2_cache_init(void); #else #define kona_l2_cache_init() ((void)0) #endif From 8b9c550e37ff4e4d0de2890a835f44a7813e3423 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 21 Apr 2014 16:53:09 -0500 Subject: [PATCH 32/87] ARM: bcm: use inline assembly for "smc" request Move the code that implements the "smc" call into a C function that uses inline assembly. This allows us to make that function private, and enables us to get rid of "arch/arm/mach-bcm/bcm_kona_smc_asm.S". Rename what had been the "buffer_addr" argument to be "buffer_phys" so it's consistent with other usage in this file. Since it's now easy to do, verify that r12 contains SEC_EXIT_NORMAL upon completion of the SMC. There really isn't a good way to handle the abnormal completion of a secure monitor request. Since "bcm_kona_smc.h" is now only included from C files, eliminate the #ifndef __ASSEMBLY__. Signed-off-by: Alex Elder Reviewed-by: Tim Kryger Reviewed-by: Markus Mayer Reviewed-by: Matt Porter Signed-off-by: Matt Porter --- arch/arm/mach-bcm/Makefile | 7 +++-- arch/arm/mach-bcm/bcm_kona_smc.c | 46 +++++++++++++++++++++++++++- arch/arm/mach-bcm/bcm_kona_smc.h | 6 ---- arch/arm/mach-bcm/bcm_kona_smc_asm.S | 41 ------------------------- 4 files changed, 49 insertions(+), 51 deletions(-) delete mode 100644 arch/arm/mach-bcm/bcm_kona_smc_asm.S diff --git a/arch/arm/mach-bcm/Makefile b/arch/arm/mach-bcm/Makefile index 51549814f7cd..d5b60feda8ad 100644 --- a/arch/arm/mach-bcm/Makefile +++ b/arch/arm/mach-bcm/Makefile @@ -20,9 +20,10 @@ obj-$(CONFIG_ARCH_BCM_21664) += board_bcm21664.o obj-$(CONFIG_ARCH_BCM_MOBILE_L2_CACHE) += kona.o # Support for secure monitor traps -obj-$(CONFIG_ARCH_BCM_MOBILE_SMC) += bcm_kona_smc.o bcm_kona_smc_asm.o -plus_sec := $(call as-instr,.arch_extension sec,+sec) -AFLAGS_bcm_kona_smc_asm.o :=-Wa,-march=armv7-a$(plus_sec) +obj-$(CONFIG_ARCH_BCM_MOBILE_SMC) += bcm_kona_smc.o +ifeq ($(call as-instr,.arch_extension sec,as_has_sec),as_has_sec) +CFLAGS_bcm_kona_smc.o += -Wa,-march=armv7-a+sec -DREQUIRES_SEC +endif # BCM2835 obj-$(CONFIG_ARCH_BCM2835) += board_bcm2835.o diff --git a/arch/arm/mach-bcm/bcm_kona_smc.c b/arch/arm/mach-bcm/bcm_kona_smc.c index 6fdcf96ca54e..cc81c86f24b5 100644 --- a/arch/arm/mach-bcm/bcm_kona_smc.c +++ b/arch/arm/mach-bcm/bcm_kona_smc.c @@ -76,6 +76,50 @@ int __init bcm_kona_smc_init(void) return 0; } +/* + * Since interrupts are disabled in the open mode, we must keep + * interrupts disabled in secure mode by setting R5=0x3. If interrupts + * are enabled in open mode, we can set R5=0x0 to allow interrupts in + * secure mode. If we did this, the secure monitor would return back + * control to the open mode to handle the interrupt prior to completing + * the secure service. If this happened, R12 would not be + * SEC_EXIT_NORMAL and we would need to call SMC again after resetting + * R5 (it gets clobbered by the secure monitor) and setting R4 to + * SSAPI_RET_FROM_INT_SERV to indicate that we want the secure monitor + * to finish up the previous uncompleted secure service. + */ +static int bcm_kona_do_smc(u32 service_id, u32 buffer_phys) +{ + register u32 ip asm("ip"); /* Also called r12 */ + register u32 r0 asm("r0"); + register u32 r4 asm("r4"); + register u32 r5 asm("r5"); + register u32 r6 asm("r6"); + + r4 = service_id; + r5 = 0x3; /* Keep IRQ and FIQ off in SM */ + r6 = buffer_phys; + + asm volatile ( + /* Make sure we got the registers we want */ + __asmeq("%0", "ip") + __asmeq("%1", "r0") + __asmeq("%2", "r4") + __asmeq("%3", "r5") + __asmeq("%4", "r6") +#ifdef REQUIRES_SEC + ".arch_extension sec\n" +#endif + " smc #0\n" + : "=r" (ip), "=r" (r0) + : "r" (r4), "r" (r5), "r" (r6) + : "r1", "r2", "r3", "r7", "lr"); + + BUG_ON(ip != SEC_EXIT_NORMAL); + + return r0; +} + /* __bcm_kona_smc() should only run on CPU 0, with pre-emption disabled */ static void __bcm_kona_smc(void *info) { @@ -95,7 +139,7 @@ static void __bcm_kona_smc(void *info) flush_cache_all(); /* Trap into Secure Monitor and record the request result */ - data->result = bcm_kona_smc_asm(data->service_id, bcm_smc_buffer_phys); + data->result = bcm_kona_do_smc(data->service_id, bcm_smc_buffer_phys); } unsigned bcm_kona_smc(unsigned service_id, unsigned arg0, unsigned arg1, diff --git a/arch/arm/mach-bcm/bcm_kona_smc.h b/arch/arm/mach-bcm/bcm_kona_smc.h index 629e64a89982..2e29ec67e414 100644 --- a/arch/arm/mach-bcm/bcm_kona_smc.h +++ b/arch/arm/mach-bcm/bcm_kona_smc.h @@ -21,7 +21,6 @@ #define SEC_ROM_RET_OK 0x00000001 #define SEC_EXIT_NORMAL 0x1 -#ifndef __ASSEMBLY__ extern int __init bcm_kona_smc_init(void); extern unsigned bcm_kona_smc(unsigned service_id, @@ -30,9 +29,4 @@ extern unsigned bcm_kona_smc(unsigned service_id, unsigned arg2, unsigned arg3); -extern int bcm_kona_smc_asm(u32 service_id, - u32 buffer_addr); - -#endif /* __ASSEMBLY__ */ - #endif /* BCM_KONA_SMC_H */ diff --git a/arch/arm/mach-bcm/bcm_kona_smc_asm.S b/arch/arm/mach-bcm/bcm_kona_smc_asm.S deleted file mode 100644 index a1608480d60d..000000000000 --- a/arch/arm/mach-bcm/bcm_kona_smc_asm.S +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2013 Broadcom Corporation - * - * 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 version 2. - * - * This program is distributed "as is" WITHOUT ANY WARRANTY of any - * kind, whether express or implied; without even the implied warranty - * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include -#include "bcm_kona_smc.h" - -/* - * int bcm_kona_smc_asm(u32 service_id, u32 buffer_addr) - */ - -ENTRY(bcm_kona_smc_asm) - stmfd sp!, {r4-r12, lr} - mov r4, r0 @ service_id - mov r5, #3 @ Keep IRQ and FIQ off in SM - /* - * Since interrupts are disabled in the open mode, we must keep - * interrupts disabled in secure mode by setting R5=0x3. If interrupts - * are enabled in open mode, we can set R5=0x0 to allow interrupts in - * secure mode. If we did this, the secure monitor would return back - * control to the open mode to handle the interrupt prior to completing - * the secure service. If this happened, R12 would not be - * SEC_EXIT_NORMAL and we would need to call SMC again after resetting - * R5 (it gets clobbered by the secure monitor) and setting R4 to - * SSAPI_RET_FROM_INT_SERV to indicate that we want the secure monitor - * to finish up the previous uncompleted secure service. - */ - mov r6, r1 @ buffer_addr - smc #0 - /* Check r12 for SEC_EXIT_NORMAL here if interrupts are enabled */ - ldmfd sp!, {r4-r12, pc} -ENDPROC(bcm_kona_smc_asm) From ed24f446ab82e3f39c4a45357186ca76368301e4 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 21 Apr 2014 16:53:10 -0500 Subject: [PATCH 33/87] ARM: bcm: rewrite commentary for bcm_kona_do_smc() The block of comments in bcm_kona_do_smc() are somewhat confusing. This patch attempts to clarify what's going on. Signed-off-by: Alex Elder Reviewed-by: Tim Kryger Reviewed-by: Markus Mayer Reviewed-by: Matt Porter Signed-off-by: Matt Porter --- arch/arm/mach-bcm/bcm_kona_smc.c | 38 +++++++++++++++++++++++--------- 1 file changed, 28 insertions(+), 10 deletions(-) diff --git a/arch/arm/mach-bcm/bcm_kona_smc.c b/arch/arm/mach-bcm/bcm_kona_smc.c index cc81c86f24b5..a55a7ecf146a 100644 --- a/arch/arm/mach-bcm/bcm_kona_smc.c +++ b/arch/arm/mach-bcm/bcm_kona_smc.c @@ -77,16 +77,34 @@ int __init bcm_kona_smc_init(void) } /* - * Since interrupts are disabled in the open mode, we must keep - * interrupts disabled in secure mode by setting R5=0x3. If interrupts - * are enabled in open mode, we can set R5=0x0 to allow interrupts in - * secure mode. If we did this, the secure monitor would return back - * control to the open mode to handle the interrupt prior to completing - * the secure service. If this happened, R12 would not be - * SEC_EXIT_NORMAL and we would need to call SMC again after resetting - * R5 (it gets clobbered by the secure monitor) and setting R4 to - * SSAPI_RET_FROM_INT_SERV to indicate that we want the secure monitor - * to finish up the previous uncompleted secure service. + * int bcm_kona_do_smc(u32 service_id, u32 buffer_addr) + * + * Only core 0 can run the secure monitor code. If an "smc" request + * is initiated on a different core it must be redirected to core 0 + * for execution. We rely on the caller to handle this. + * + * Each "smc" request supplies a service id and the address of a + * buffer containing parameters related to the service to be + * performed. A flags value defines the behavior of the level 2 + * cache and interrupt handling while the secure monitor executes. + * + * Parameters to the "smc" request are passed in r4-r6 as follows: + * r4 service id + * r5 flags (SEC_ROM_*) + * r6 physical address of buffer with other parameters + * + * Execution of an "smc" request produces two distinct results. + * + * First, the secure monitor call itself (regardless of the specific + * service request) can succeed, or can produce an error. When an + * "smc" request completes this value is found in r12; it should + * always be SEC_EXIT_NORMAL. + * + * In addition, the particular service performed produces a result. + * The values that should be expected depend on the service. We + * therefore return this value to the caller, so it can handle the + * request result appropriately. This result value is found in r0 + * when the "smc" request completes. */ static int bcm_kona_do_smc(u32 service_id, u32 buffer_phys) { From eeda4cb92ee0fb63a5917738e107b0bc8168079e Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 21 Apr 2014 16:53:11 -0500 Subject: [PATCH 34/87] ARM: bcm: rename "kona.h" and "kona.c" These source files contain only level-2 cache initialization code, so rename them to make that fact more obvious. Signed-off-by: Alex Elder Reviewed-by: Tim Kryger Reviewed-by: Markus Mayer Reviewed-by: Matt Porter Signed-off-by: Matt Porter --- arch/arm/mach-bcm/Makefile | 2 +- arch/arm/mach-bcm/board_bcm21664.c | 2 +- arch/arm/mach-bcm/board_bcm281xx.c | 2 +- arch/arm/mach-bcm/{kona.c => kona_l2_cache.c} | 0 arch/arm/mach-bcm/{kona.h => kona_l2_cache.h} | 0 5 files changed, 3 insertions(+), 3 deletions(-) rename arch/arm/mach-bcm/{kona.c => kona_l2_cache.c} (100%) rename arch/arm/mach-bcm/{kona.h => kona_l2_cache.h} (100%) diff --git a/arch/arm/mach-bcm/Makefile b/arch/arm/mach-bcm/Makefile index d5b60feda8ad..731292114975 100644 --- a/arch/arm/mach-bcm/Makefile +++ b/arch/arm/mach-bcm/Makefile @@ -17,7 +17,7 @@ obj-$(CONFIG_ARCH_BCM_281XX) += board_bcm281xx.o obj-$(CONFIG_ARCH_BCM_21664) += board_bcm21664.o # BCM281XX and BCM21664 L2 cache control -obj-$(CONFIG_ARCH_BCM_MOBILE_L2_CACHE) += kona.o +obj-$(CONFIG_ARCH_BCM_MOBILE_L2_CACHE) += kona_l2_cache.o # Support for secure monitor traps obj-$(CONFIG_ARCH_BCM_MOBILE_SMC) += bcm_kona_smc.o diff --git a/arch/arm/mach-bcm/board_bcm21664.c b/arch/arm/mach-bcm/board_bcm21664.c index 1091637638f1..f0521cc0640d 100644 --- a/arch/arm/mach-bcm/board_bcm21664.c +++ b/arch/arm/mach-bcm/board_bcm21664.c @@ -17,7 +17,7 @@ #include -#include "kona.h" +#include "kona_l2_cache.h" #define RSTMGR_DT_STRING "brcm,bcm21664-resetmgr" diff --git a/arch/arm/mach-bcm/board_bcm281xx.c b/arch/arm/mach-bcm/board_bcm281xx.c index 6be54c10f8cb..1ac59fc0cb15 100644 --- a/arch/arm/mach-bcm/board_bcm281xx.c +++ b/arch/arm/mach-bcm/board_bcm281xx.c @@ -17,7 +17,7 @@ #include -#include "kona.h" +#include "kona_l2_cache.h" #define SECWDOG_OFFSET 0x00000000 #define SECWDOG_RESERVED_MASK 0xe2000000 diff --git a/arch/arm/mach-bcm/kona.c b/arch/arm/mach-bcm/kona_l2_cache.c similarity index 100% rename from arch/arm/mach-bcm/kona.c rename to arch/arm/mach-bcm/kona_l2_cache.c diff --git a/arch/arm/mach-bcm/kona.h b/arch/arm/mach-bcm/kona_l2_cache.h similarity index 100% rename from arch/arm/mach-bcm/kona.h rename to arch/arm/mach-bcm/kona_l2_cache.h From edfaf05c2fcb853fcf35f12aeb9c340f5913337f Mon Sep 17 00:00:00 2001 From: Victor Kamensky Date: Tue, 15 Apr 2014 20:37:46 +0300 Subject: [PATCH 35/87] ARM: OMAP2+: raw read and write endian fix All OMAP IP blocks expect LE data, but CPU may operate in BE mode. Need to use endian neutral functions to read/write h/w registers. I.e instead of __raw_read[lw] and __raw_write[lw] functions code need to use read[lw]_relaxed and write[lw]_relaxed functions. If the first simply reads/writes register, the second will byteswap it if host operates in BE mode. Changes are trivial sed like replacement of __raw_xxx functions with xxx_relaxed variant. Signed-off-by: Victor Kamensky Signed-off-by: Taras Kondratiuk Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/board-flash.c | 4 +-- arch/arm/mach-omap2/clkt2xxx_dpllcore.c | 2 +- arch/arm/mach-omap2/clkt2xxx_osc.c | 8 ++--- arch/arm/mach-omap2/clkt2xxx_sys.c | 2 +- arch/arm/mach-omap2/cm2xxx_3xxx.h | 4 +-- arch/arm/mach-omap2/cm33xx.c | 4 +-- arch/arm/mach-omap2/cm3xxx.c | 8 ++--- arch/arm/mach-omap2/cm44xx.c | 8 ++--- arch/arm/mach-omap2/cminst44xx.c | 4 +-- arch/arm/mach-omap2/control.c | 20 +++++------ arch/arm/mach-omap2/dma.c | 4 +-- arch/arm/mach-omap2/gpmc.c | 8 ++--- arch/arm/mach-omap2/id.c | 2 +- arch/arm/mach-omap2/irq.c | 4 +-- arch/arm/mach-omap2/mux.c | 8 ++--- arch/arm/mach-omap2/omap-hotplug.c | 4 +-- arch/arm/mach-omap2/omap-mpuss-lowpower.c | 18 +++++----- arch/arm/mach-omap2/omap-smp.c | 6 ++-- arch/arm/mach-omap2/omap-wakeupgen.c | 42 +++++++++++------------ arch/arm/mach-omap2/omap4-common.c | 18 +++++----- arch/arm/mach-omap2/omap_hwmod.c | 10 +++--- arch/arm/mach-omap2/omap_phy_internal.c | 6 ++-- arch/arm/mach-omap2/prcm_mpu44xx.c | 4 +-- arch/arm/mach-omap2/prm2xxx.h | 2 +- arch/arm/mach-omap2/prm2xxx_3xxx.h | 4 +-- arch/arm/mach-omap2/prm33xx.c | 4 +-- arch/arm/mach-omap2/prm3xxx.h | 2 +- arch/arm/mach-omap2/prm44xx.c | 4 +-- arch/arm/mach-omap2/prminst44xx.c | 4 +-- arch/arm/mach-omap2/sdrc.h | 8 ++--- arch/arm/mach-omap2/sdrc2xxx.c | 4 +-- arch/arm/mach-omap2/sr_device.c | 2 +- arch/arm/mach-omap2/sram.c | 16 ++++----- arch/arm/mach-omap2/timer.c | 8 ++--- arch/arm/mach-omap2/vc.c | 4 +-- arch/arm/mach-omap2/wd_timer.c | 8 ++--- 36 files changed, 134 insertions(+), 134 deletions(-) diff --git a/arch/arm/mach-omap2/board-flash.c b/arch/arm/mach-omap2/board-flash.c index ac82512b9c8c..84cc1482e584 100644 --- a/arch/arm/mach-omap2/board-flash.c +++ b/arch/arm/mach-omap2/board-flash.c @@ -160,13 +160,13 @@ static u8 get_gpmc0_type(void) if (!fpga_map_addr) return -ENOMEM; - if (!(__raw_readw(fpga_map_addr + REG_FPGA_REV))) + if (!(readw_relaxed(fpga_map_addr + REG_FPGA_REV))) /* we dont have an DEBUG FPGA??? */ /* Depend on #defines!! default to strata boot return param */ goto unmap; /* S8-DIP-OFF = 1, S8-DIP-ON = 0 */ - cs = __raw_readw(fpga_map_addr + REG_FPGA_DIP_SWITCH_INPUT2) & 0xf; + cs = readw_relaxed(fpga_map_addr + REG_FPGA_DIP_SWITCH_INPUT2) & 0xf; /* ES2.0 SDP's onwards 4 dip switches are provided for CS */ if (omap_rev() >= OMAP3430_REV_ES1_0) diff --git a/arch/arm/mach-omap2/clkt2xxx_dpllcore.c b/arch/arm/mach-omap2/clkt2xxx_dpllcore.c index 3ff32543493c..59cf310bc1e9 100644 --- a/arch/arm/mach-omap2/clkt2xxx_dpllcore.c +++ b/arch/arm/mach-omap2/clkt2xxx_dpllcore.c @@ -138,7 +138,7 @@ int omap2_reprogram_dpllcore(struct clk_hw *hw, unsigned long rate, if (!dd) return -EINVAL; - tmpset.cm_clksel1_pll = __raw_readl(dd->mult_div1_reg); + tmpset.cm_clksel1_pll = readl_relaxed(dd->mult_div1_reg); tmpset.cm_clksel1_pll &= ~(dd->mult_mask | dd->div1_mask); div = ((curr_prcm_set->xtal_speed / 1000000) - 1); diff --git a/arch/arm/mach-omap2/clkt2xxx_osc.c b/arch/arm/mach-omap2/clkt2xxx_osc.c index 19f54d433490..0717dff1bc04 100644 --- a/arch/arm/mach-omap2/clkt2xxx_osc.c +++ b/arch/arm/mach-omap2/clkt2xxx_osc.c @@ -39,9 +39,9 @@ int omap2_enable_osc_ck(struct clk_hw *clk) { u32 pcc; - pcc = __raw_readl(prcm_clksrc_ctrl); + pcc = readl_relaxed(prcm_clksrc_ctrl); - __raw_writel(pcc & ~OMAP_AUTOEXTCLKMODE_MASK, prcm_clksrc_ctrl); + writel_relaxed(pcc & ~OMAP_AUTOEXTCLKMODE_MASK, prcm_clksrc_ctrl); return 0; } @@ -57,9 +57,9 @@ void omap2_disable_osc_ck(struct clk_hw *clk) { u32 pcc; - pcc = __raw_readl(prcm_clksrc_ctrl); + pcc = readl_relaxed(prcm_clksrc_ctrl); - __raw_writel(pcc | OMAP_AUTOEXTCLKMODE_MASK, prcm_clksrc_ctrl); + writel_relaxed(pcc | OMAP_AUTOEXTCLKMODE_MASK, prcm_clksrc_ctrl); } unsigned long omap2_osc_clk_recalc(struct clk_hw *clk, diff --git a/arch/arm/mach-omap2/clkt2xxx_sys.c b/arch/arm/mach-omap2/clkt2xxx_sys.c index f467d072cd02..58dd3a9b726c 100644 --- a/arch/arm/mach-omap2/clkt2xxx_sys.c +++ b/arch/arm/mach-omap2/clkt2xxx_sys.c @@ -33,7 +33,7 @@ u32 omap2xxx_get_sysclkdiv(void) { u32 div; - div = __raw_readl(prcm_clksrc_ctrl); + div = readl_relaxed(prcm_clksrc_ctrl); div &= OMAP_SYSCLKDIV_MASK; div >>= OMAP_SYSCLKDIV_SHIFT; diff --git a/arch/arm/mach-omap2/cm2xxx_3xxx.h b/arch/arm/mach-omap2/cm2xxx_3xxx.h index bfbd16fe9151..72928a3ce2aa 100644 --- a/arch/arm/mach-omap2/cm2xxx_3xxx.h +++ b/arch/arm/mach-omap2/cm2xxx_3xxx.h @@ -52,12 +52,12 @@ static inline u32 omap2_cm_read_mod_reg(s16 module, u16 idx) { - return __raw_readl(cm_base + module + idx); + return readl_relaxed(cm_base + module + idx); } static inline void omap2_cm_write_mod_reg(u32 val, s16 module, u16 idx) { - __raw_writel(val, cm_base + module + idx); + writel_relaxed(val, cm_base + module + idx); } /* Read-modify-write a register in a CM module. Caller must lock */ diff --git a/arch/arm/mach-omap2/cm33xx.c b/arch/arm/mach-omap2/cm33xx.c index 40a22e5649ae..b3f99e93def0 100644 --- a/arch/arm/mach-omap2/cm33xx.c +++ b/arch/arm/mach-omap2/cm33xx.c @@ -50,13 +50,13 @@ /* Read a register in a CM instance */ static inline u32 am33xx_cm_read_reg(u16 inst, u16 idx) { - return __raw_readl(cm_base + inst + idx); + return readl_relaxed(cm_base + inst + idx); } /* Write into a register in a CM */ static inline void am33xx_cm_write_reg(u32 val, u16 inst, u16 idx) { - __raw_writel(val, cm_base + inst + idx); + writel_relaxed(val, cm_base + inst + idx); } /* Read-modify-write a register in CM */ diff --git a/arch/arm/mach-omap2/cm3xxx.c b/arch/arm/mach-omap2/cm3xxx.c index f6f028867bfe..9079f2558b1b 100644 --- a/arch/arm/mach-omap2/cm3xxx.c +++ b/arch/arm/mach-omap2/cm3xxx.c @@ -388,7 +388,7 @@ void omap3_cm_save_context(void) omap2_cm_read_mod_reg(OMAP3430_IVA2_MOD, CM_CLKSEL1); cm_context.iva2_cm_clksel2 = omap2_cm_read_mod_reg(OMAP3430_IVA2_MOD, CM_CLKSEL2); - cm_context.cm_sysconfig = __raw_readl(OMAP3430_CM_SYSCONFIG); + cm_context.cm_sysconfig = readl_relaxed(OMAP3430_CM_SYSCONFIG); cm_context.sgx_cm_clksel = omap2_cm_read_mod_reg(OMAP3430ES2_SGX_MOD, CM_CLKSEL); cm_context.dss_cm_clksel = @@ -418,7 +418,7 @@ void omap3_cm_save_context(void) omap2_cm_read_mod_reg(PLL_MOD, OMAP3430ES2_CM_CLKSEL5); cm_context.pll_cm_clken2 = omap2_cm_read_mod_reg(PLL_MOD, OMAP3430ES2_CM_CLKEN2); - cm_context.cm_polctrl = __raw_readl(OMAP3430_CM_POLCTRL); + cm_context.cm_polctrl = readl_relaxed(OMAP3430_CM_POLCTRL); cm_context.iva2_cm_fclken = omap2_cm_read_mod_reg(OMAP3430_IVA2_MOD, CM_FCLKEN); cm_context.iva2_cm_clken_pll = @@ -519,7 +519,7 @@ void omap3_cm_restore_context(void) CM_CLKSEL1); omap2_cm_write_mod_reg(cm_context.iva2_cm_clksel2, OMAP3430_IVA2_MOD, CM_CLKSEL2); - __raw_writel(cm_context.cm_sysconfig, OMAP3430_CM_SYSCONFIG); + writel_relaxed(cm_context.cm_sysconfig, OMAP3430_CM_SYSCONFIG); omap2_cm_write_mod_reg(cm_context.sgx_cm_clksel, OMAP3430ES2_SGX_MOD, CM_CLKSEL); omap2_cm_write_mod_reg(cm_context.dss_cm_clksel, OMAP3430_DSS_MOD, @@ -547,7 +547,7 @@ void omap3_cm_restore_context(void) OMAP3430ES2_CM_CLKSEL5); omap2_cm_write_mod_reg(cm_context.pll_cm_clken2, PLL_MOD, OMAP3430ES2_CM_CLKEN2); - __raw_writel(cm_context.cm_polctrl, OMAP3430_CM_POLCTRL); + writel_relaxed(cm_context.cm_polctrl, OMAP3430_CM_POLCTRL); omap2_cm_write_mod_reg(cm_context.iva2_cm_fclken, OMAP3430_IVA2_MOD, CM_FCLKEN); omap2_cm_write_mod_reg(cm_context.iva2_cm_clken_pll, OMAP3430_IVA2_MOD, diff --git a/arch/arm/mach-omap2/cm44xx.c b/arch/arm/mach-omap2/cm44xx.c index 535d66e2822c..30b6d9743b73 100644 --- a/arch/arm/mach-omap2/cm44xx.c +++ b/arch/arm/mach-omap2/cm44xx.c @@ -30,23 +30,23 @@ /* Read a register in CM1 */ u32 omap4_cm1_read_inst_reg(s16 inst, u16 reg) { - return __raw_readl(OMAP44XX_CM1_REGADDR(inst, reg)); + return readl_relaxed(OMAP44XX_CM1_REGADDR(inst, reg)); } /* Write into a register in CM1 */ void omap4_cm1_write_inst_reg(u32 val, s16 inst, u16 reg) { - __raw_writel(val, OMAP44XX_CM1_REGADDR(inst, reg)); + writel_relaxed(val, OMAP44XX_CM1_REGADDR(inst, reg)); } /* Read a register in CM2 */ u32 omap4_cm2_read_inst_reg(s16 inst, u16 reg) { - return __raw_readl(OMAP44XX_CM2_REGADDR(inst, reg)); + return readl_relaxed(OMAP44XX_CM2_REGADDR(inst, reg)); } /* Write into a register in CM2 */ void omap4_cm2_write_inst_reg(u32 val, s16 inst, u16 reg) { - __raw_writel(val, OMAP44XX_CM2_REGADDR(inst, reg)); + writel_relaxed(val, OMAP44XX_CM2_REGADDR(inst, reg)); } diff --git a/arch/arm/mach-omap2/cminst44xx.c b/arch/arm/mach-omap2/cminst44xx.c index f5c4731b6f06..2f44257171dd 100644 --- a/arch/arm/mach-omap2/cminst44xx.c +++ b/arch/arm/mach-omap2/cminst44xx.c @@ -116,7 +116,7 @@ u32 omap4_cminst_read_inst_reg(u8 part, u16 inst, u16 idx) BUG_ON(part >= OMAP4_MAX_PRCM_PARTITIONS || part == OMAP4430_INVALID_PRCM_PARTITION || !_cm_bases[part]); - return __raw_readl(_cm_bases[part] + inst + idx); + return readl_relaxed(_cm_bases[part] + inst + idx); } /* Write into a register in a CM instance */ @@ -125,7 +125,7 @@ void omap4_cminst_write_inst_reg(u32 val, u8 part, u16 inst, u16 idx) BUG_ON(part >= OMAP4_MAX_PRCM_PARTITIONS || part == OMAP4430_INVALID_PRCM_PARTITION || !_cm_bases[part]); - __raw_writel(val, _cm_bases[part] + inst + idx); + writel_relaxed(val, _cm_bases[part] + inst + idx); } /* Read-modify-write a register in CM1. Caller must lock */ diff --git a/arch/arm/mach-omap2/control.c b/arch/arm/mach-omap2/control.c index 44bb4d544dcf..751f3549bf6f 100644 --- a/arch/arm/mach-omap2/control.c +++ b/arch/arm/mach-omap2/control.c @@ -151,32 +151,32 @@ void __iomem *omap_ctrl_base_get(void) u8 omap_ctrl_readb(u16 offset) { - return __raw_readb(OMAP_CTRL_REGADDR(offset)); + return readb_relaxed(OMAP_CTRL_REGADDR(offset)); } u16 omap_ctrl_readw(u16 offset) { - return __raw_readw(OMAP_CTRL_REGADDR(offset)); + return readw_relaxed(OMAP_CTRL_REGADDR(offset)); } u32 omap_ctrl_readl(u16 offset) { - return __raw_readl(OMAP_CTRL_REGADDR(offset)); + return readl_relaxed(OMAP_CTRL_REGADDR(offset)); } void omap_ctrl_writeb(u8 val, u16 offset) { - __raw_writeb(val, OMAP_CTRL_REGADDR(offset)); + writeb_relaxed(val, OMAP_CTRL_REGADDR(offset)); } void omap_ctrl_writew(u16 val, u16 offset) { - __raw_writew(val, OMAP_CTRL_REGADDR(offset)); + writew_relaxed(val, OMAP_CTRL_REGADDR(offset)); } void omap_ctrl_writel(u32 val, u16 offset) { - __raw_writel(val, OMAP_CTRL_REGADDR(offset)); + writel_relaxed(val, OMAP_CTRL_REGADDR(offset)); } /* @@ -188,12 +188,12 @@ void omap_ctrl_writel(u32 val, u16 offset) u32 omap4_ctrl_pad_readl(u16 offset) { - return __raw_readl(OMAP4_CTRL_PAD_REGADDR(offset)); + return readl_relaxed(OMAP4_CTRL_PAD_REGADDR(offset)); } void omap4_ctrl_pad_writel(u32 val, u16 offset) { - __raw_writel(val, OMAP4_CTRL_PAD_REGADDR(offset)); + writel_relaxed(val, OMAP4_CTRL_PAD_REGADDR(offset)); } #ifdef CONFIG_ARCH_OMAP3 @@ -222,7 +222,7 @@ void omap3_ctrl_write_boot_mode(u8 bootmode) * * XXX This should use some omap_ctrl_writel()-type function */ - __raw_writel(l, OMAP2_L4_IO_ADDRESS(OMAP343X_SCRATCHPAD + 4)); + writel_relaxed(l, OMAP2_L4_IO_ADDRESS(OMAP343X_SCRATCHPAD + 4)); } #endif @@ -285,7 +285,7 @@ void omap3_clear_scratchpad_contents(void) if (omap2_prm_read_mod_reg(OMAP3430_GR_MOD, OMAP3_PRM_RSTST_OFFSET) & OMAP3430_GLOBAL_COLD_RST_MASK) { for ( ; offset <= max_offset; offset += 0x4) - __raw_writel(0x0, (v_addr + offset)); + writel_relaxed(0x0, (v_addr + offset)); omap2_prm_set_mod_reg_bits(OMAP3430_GLOBAL_COLD_RST_MASK, OMAP3430_GR_MOD, OMAP3_PRM_RSTST_OFFSET); diff --git a/arch/arm/mach-omap2/dma.c b/arch/arm/mach-omap2/dma.c index 5689c88d986d..a6d2cf1f8d02 100644 --- a/arch/arm/mach-omap2/dma.c +++ b/arch/arm/mach-omap2/dma.c @@ -91,7 +91,7 @@ static inline void dma_write(u32 val, int reg, int lch) addr += reg_map[reg].offset; addr += reg_map[reg].stride * lch; - __raw_writel(val, addr); + writel_relaxed(val, addr); } static inline u32 dma_read(int reg, int lch) @@ -101,7 +101,7 @@ static inline u32 dma_read(int reg, int lch) addr += reg_map[reg].offset; addr += reg_map[reg].stride * lch; - return __raw_readl(addr); + return readl_relaxed(addr); } static void omap2_clear_dma(int lch) diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c index 9fe8c949305c..852b19a367f0 100644 --- a/arch/arm/mach-omap2/gpmc.c +++ b/arch/arm/mach-omap2/gpmc.c @@ -170,12 +170,12 @@ static irqreturn_t gpmc_handle_irq(int irq, void *dev); static void gpmc_write_reg(int idx, u32 val) { - __raw_writel(val, gpmc_base + idx); + writel_relaxed(val, gpmc_base + idx); } static u32 gpmc_read_reg(int idx) { - return __raw_readl(gpmc_base + idx); + return readl_relaxed(gpmc_base + idx); } void gpmc_cs_write_reg(int cs, int idx, u32 val) @@ -183,7 +183,7 @@ void gpmc_cs_write_reg(int cs, int idx, u32 val) void __iomem *reg_addr; reg_addr = gpmc_base + GPMC_CS0_OFFSET + (cs * GPMC_CS_SIZE) + idx; - __raw_writel(val, reg_addr); + writel_relaxed(val, reg_addr); } static u32 gpmc_cs_read_reg(int cs, int idx) @@ -191,7 +191,7 @@ static u32 gpmc_cs_read_reg(int cs, int idx) void __iomem *reg_addr; reg_addr = gpmc_base + GPMC_CS0_OFFSET + (cs * GPMC_CS_SIZE) + idx; - return __raw_readl(reg_addr); + return readl_relaxed(reg_addr); } /* TODO: Add support for gpmc_fck to clock framework and use it */ diff --git a/arch/arm/mach-omap2/id.c b/arch/arm/mach-omap2/id.c index 157412e4273a..f61f1bf68df4 100644 --- a/arch/arm/mach-omap2/id.c +++ b/arch/arm/mach-omap2/id.c @@ -94,7 +94,7 @@ EXPORT_SYMBOL(omap_type); #define OMAP_TAP_DIE_ID_44XX_2 0x020c #define OMAP_TAP_DIE_ID_44XX_3 0x0210 -#define read_tap_reg(reg) __raw_readl(tap_base + (reg)) +#define read_tap_reg(reg) readl_relaxed(tap_base + (reg)) struct omap_id { u16 hawkeye; /* Silicon type (Hawkeye id) */ diff --git a/arch/arm/mach-omap2/irq.c b/arch/arm/mach-omap2/irq.c index 6037a9a01ed5..35b8590c322e 100644 --- a/arch/arm/mach-omap2/irq.c +++ b/arch/arm/mach-omap2/irq.c @@ -83,12 +83,12 @@ struct omap3_intc_regs { static void intc_bank_write_reg(u32 val, struct omap_irq_bank *bank, u16 reg) { - __raw_writel(val, bank->base_reg + reg); + writel_relaxed(val, bank->base_reg + reg); } static u32 intc_bank_read_reg(struct omap_irq_bank *bank, u16 reg) { - return __raw_readl(bank->base_reg + reg); + return readl_relaxed(bank->base_reg + reg); } /* XXX: FIQ and additional INTC support (only MPU at the moment) */ diff --git a/arch/arm/mach-omap2/mux.c b/arch/arm/mach-omap2/mux.c index 48094b58c88f..fd88edeb027f 100644 --- a/arch/arm/mach-omap2/mux.c +++ b/arch/arm/mach-omap2/mux.c @@ -70,18 +70,18 @@ struct omap_mux_partition *omap_mux_get(const char *name) u16 omap_mux_read(struct omap_mux_partition *partition, u16 reg) { if (partition->flags & OMAP_MUX_REG_8BIT) - return __raw_readb(partition->base + reg); + return readb_relaxed(partition->base + reg); else - return __raw_readw(partition->base + reg); + return readw_relaxed(partition->base + reg); } void omap_mux_write(struct omap_mux_partition *partition, u16 val, u16 reg) { if (partition->flags & OMAP_MUX_REG_8BIT) - __raw_writeb(val, partition->base + reg); + writeb_relaxed(val, partition->base + reg); else - __raw_writew(val, partition->base + reg); + writew_relaxed(val, partition->base + reg); } void omap_mux_write_array(struct omap_mux_partition *partition, diff --git a/arch/arm/mach-omap2/omap-hotplug.c b/arch/arm/mach-omap2/omap-hotplug.c index 458f72f9dc8f..971791fe9a3f 100644 --- a/arch/arm/mach-omap2/omap-hotplug.c +++ b/arch/arm/mach-omap2/omap-hotplug.c @@ -39,7 +39,7 @@ void __ref omap4_cpu_die(unsigned int cpu) if (omap_modify_auxcoreboot0(0x0, 0x200) != 0x0) pr_err("Secure clear status failed\n"); } else { - __raw_writel(0, base + OMAP_AUX_CORE_BOOT_0); + writel_relaxed(0, base + OMAP_AUX_CORE_BOOT_0); } @@ -53,7 +53,7 @@ void __ref omap4_cpu_die(unsigned int cpu) boot_cpu = omap_read_auxcoreboot0(); else boot_cpu = - __raw_readl(base + OMAP_AUX_CORE_BOOT_0) >> 5; + readl_relaxed(base + OMAP_AUX_CORE_BOOT_0) >> 5; if (boot_cpu == smp_processor_id()) { /* diff --git a/arch/arm/mach-omap2/omap-mpuss-lowpower.c b/arch/arm/mach-omap2/omap-mpuss-lowpower.c index 667915d236f3..eb76e47091ad 100644 --- a/arch/arm/mach-omap2/omap-mpuss-lowpower.c +++ b/arch/arm/mach-omap2/omap-mpuss-lowpower.c @@ -116,7 +116,7 @@ static inline void set_cpu_wakeup_addr(unsigned int cpu_id, u32 addr) { struct omap4_cpu_pm_info *pm_info = &per_cpu(omap4_pm_info, cpu_id); - __raw_writel(addr, pm_info->wkup_sar_addr); + writel_relaxed(addr, pm_info->wkup_sar_addr); } /* @@ -141,7 +141,7 @@ static void scu_pwrst_prepare(unsigned int cpu_id, unsigned int cpu_state) break; } - __raw_writel(scu_pwr_st, pm_info->scu_sar_addr); + writel_relaxed(scu_pwr_st, pm_info->scu_sar_addr); } /* Helper functions for MPUSS OSWR */ @@ -179,7 +179,7 @@ static void l2x0_pwrst_prepare(unsigned int cpu_id, unsigned int save_state) { struct omap4_cpu_pm_info *pm_info = &per_cpu(omap4_pm_info, cpu_id); - __raw_writel(save_state, pm_info->l2x0_sar_addr); + writel_relaxed(save_state, pm_info->l2x0_sar_addr); } /* @@ -192,10 +192,10 @@ static void save_l2x0_context(void) u32 val; void __iomem *l2x0_base = omap4_get_l2cache_base(); if (l2x0_base) { - val = __raw_readl(l2x0_base + L2X0_AUX_CTRL); - __raw_writel(val, sar_base + L2X0_AUXCTRL_OFFSET); - val = __raw_readl(l2x0_base + L2X0_PREFETCH_CTRL); - __raw_writel(val, sar_base + L2X0_PREFETCH_CTRL_OFFSET); + val = readl_relaxed(l2x0_base + L2X0_AUX_CTRL); + writel_relaxed(val, sar_base + L2X0_AUXCTRL_OFFSET); + val = readl_relaxed(l2x0_base + L2X0_PREFETCH_CTRL); + writel_relaxed(val, sar_base + L2X0_PREFETCH_CTRL_OFFSET); } } #else @@ -386,9 +386,9 @@ int __init omap4_mpuss_init(void) /* Save device type on scratchpad for low level code to use */ if (omap_type() != OMAP2_DEVICE_TYPE_GP) - __raw_writel(1, sar_base + OMAP_TYPE_OFFSET); + writel_relaxed(1, sar_base + OMAP_TYPE_OFFSET); else - __raw_writel(0, sar_base + OMAP_TYPE_OFFSET); + writel_relaxed(0, sar_base + OMAP_TYPE_OFFSET); save_l2x0_context(); diff --git a/arch/arm/mach-omap2/omap-smp.c b/arch/arm/mach-omap2/omap-smp.c index 17550aa39d0f..256e84ef0f67 100644 --- a/arch/arm/mach-omap2/omap-smp.c +++ b/arch/arm/mach-omap2/omap-smp.c @@ -99,7 +99,7 @@ static int omap4_boot_secondary(unsigned int cpu, struct task_struct *idle) if (omap_secure_apis_support()) omap_modify_auxcoreboot0(0x200, 0xfffffdff); else - __raw_writel(0x20, base + OMAP_AUX_CORE_BOOT_0); + writel_relaxed(0x20, base + OMAP_AUX_CORE_BOOT_0); if (!cpu1_clkdm && !cpu1_pwrdm) { cpu1_clkdm = clkdm_lookup("mpu1_clkdm"); @@ -227,8 +227,8 @@ static void __init omap4_smp_prepare_cpus(unsigned int max_cpus) if (omap_secure_apis_support()) omap_auxcoreboot_addr(virt_to_phys(startup_addr)); else - __raw_writel(virt_to_phys(omap5_secondary_startup), - base + OMAP_AUX_CORE_BOOT_1); + writel_relaxed(virt_to_phys(omap5_secondary_startup), + base + OMAP_AUX_CORE_BOOT_1); } diff --git a/arch/arm/mach-omap2/omap-wakeupgen.c b/arch/arm/mach-omap2/omap-wakeupgen.c index 693fe486e917..37843a7d3639 100644 --- a/arch/arm/mach-omap2/omap-wakeupgen.c +++ b/arch/arm/mach-omap2/omap-wakeupgen.c @@ -60,19 +60,19 @@ static unsigned int omap_secure_apis; */ static inline u32 wakeupgen_readl(u8 idx, u32 cpu) { - return __raw_readl(wakeupgen_base + OMAP_WKG_ENB_A_0 + + return readl_relaxed(wakeupgen_base + OMAP_WKG_ENB_A_0 + (cpu * CPU_ENA_OFFSET) + (idx * 4)); } static inline void wakeupgen_writel(u32 val, u8 idx, u32 cpu) { - __raw_writel(val, wakeupgen_base + OMAP_WKG_ENB_A_0 + + writel_relaxed(val, wakeupgen_base + OMAP_WKG_ENB_A_0 + (cpu * CPU_ENA_OFFSET) + (idx * 4)); } static inline void sar_writel(u32 val, u32 offset, u8 idx) { - __raw_writel(val, sar_base + offset + (idx * 4)); + writel_relaxed(val, sar_base + offset + (idx * 4)); } static inline int _wakeupgen_get_irq_info(u32 irq, u32 *bit_posn, u8 *reg_index) @@ -231,21 +231,21 @@ static inline void omap4_irq_save_context(void) } /* Save AuxBoot* registers */ - val = __raw_readl(wakeupgen_base + OMAP_AUX_CORE_BOOT_0); - __raw_writel(val, sar_base + AUXCOREBOOT0_OFFSET); - val = __raw_readl(wakeupgen_base + OMAP_AUX_CORE_BOOT_1); - __raw_writel(val, sar_base + AUXCOREBOOT1_OFFSET); + val = readl_relaxed(wakeupgen_base + OMAP_AUX_CORE_BOOT_0); + writel_relaxed(val, sar_base + AUXCOREBOOT0_OFFSET); + val = readl_relaxed(wakeupgen_base + OMAP_AUX_CORE_BOOT_1); + writel_relaxed(val, sar_base + AUXCOREBOOT1_OFFSET); /* Save SyncReq generation logic */ - val = __raw_readl(wakeupgen_base + OMAP_PTMSYNCREQ_MASK); - __raw_writel(val, sar_base + PTMSYNCREQ_MASK_OFFSET); - val = __raw_readl(wakeupgen_base + OMAP_PTMSYNCREQ_EN); - __raw_writel(val, sar_base + PTMSYNCREQ_EN_OFFSET); + val = readl_relaxed(wakeupgen_base + OMAP_PTMSYNCREQ_MASK); + writel_relaxed(val, sar_base + PTMSYNCREQ_MASK_OFFSET); + val = readl_relaxed(wakeupgen_base + OMAP_PTMSYNCREQ_EN); + writel_relaxed(val, sar_base + PTMSYNCREQ_EN_OFFSET); /* Set the Backup Bit Mask status */ - val = __raw_readl(sar_base + SAR_BACKUP_STATUS_OFFSET); + val = readl_relaxed(sar_base + SAR_BACKUP_STATUS_OFFSET); val |= SAR_BACKUP_STATUS_WAKEUPGEN; - __raw_writel(val, sar_base + SAR_BACKUP_STATUS_OFFSET); + writel_relaxed(val, sar_base + SAR_BACKUP_STATUS_OFFSET); } @@ -264,15 +264,15 @@ static inline void omap5_irq_save_context(void) } /* Save AuxBoot* registers */ - val = __raw_readl(wakeupgen_base + OMAP_AUX_CORE_BOOT_0); - __raw_writel(val, sar_base + OMAP5_AUXCOREBOOT0_OFFSET); - val = __raw_readl(wakeupgen_base + OMAP_AUX_CORE_BOOT_0); - __raw_writel(val, sar_base + OMAP5_AUXCOREBOOT1_OFFSET); + val = readl_relaxed(wakeupgen_base + OMAP_AUX_CORE_BOOT_0); + writel_relaxed(val, sar_base + OMAP5_AUXCOREBOOT0_OFFSET); + val = readl_relaxed(wakeupgen_base + OMAP_AUX_CORE_BOOT_0); + writel_relaxed(val, sar_base + OMAP5_AUXCOREBOOT1_OFFSET); /* Set the Backup Bit Mask status */ - val = __raw_readl(sar_base + OMAP5_SAR_BACKUP_STATUS_OFFSET); + val = readl_relaxed(sar_base + OMAP5_SAR_BACKUP_STATUS_OFFSET); val |= SAR_BACKUP_STATUS_WAKEUPGEN; - __raw_writel(val, sar_base + OMAP5_SAR_BACKUP_STATUS_OFFSET); + writel_relaxed(val, sar_base + OMAP5_SAR_BACKUP_STATUS_OFFSET); } @@ -306,9 +306,9 @@ static void irq_sar_clear(void) if (soc_is_omap54xx()) offset = OMAP5_SAR_BACKUP_STATUS_OFFSET; - val = __raw_readl(sar_base + offset); + val = readl_relaxed(sar_base + offset); val &= ~SAR_BACKUP_STATUS_WAKEUPGEN; - __raw_writel(val, sar_base + offset); + writel_relaxed(val, sar_base + offset); } /* diff --git a/arch/arm/mach-omap2/omap4-common.c b/arch/arm/mach-omap2/omap4-common.c index 95e171a055f3..99b0154493a4 100644 --- a/arch/arm/mach-omap2/omap4-common.c +++ b/arch/arm/mach-omap2/omap4-common.c @@ -125,25 +125,25 @@ void __init gic_init_irq(void) void gic_dist_disable(void) { if (gic_dist_base_addr) - __raw_writel(0x0, gic_dist_base_addr + GIC_DIST_CTRL); + writel_relaxed(0x0, gic_dist_base_addr + GIC_DIST_CTRL); } void gic_dist_enable(void) { if (gic_dist_base_addr) - __raw_writel(0x1, gic_dist_base_addr + GIC_DIST_CTRL); + writel_relaxed(0x1, gic_dist_base_addr + GIC_DIST_CTRL); } bool gic_dist_disabled(void) { - return !(__raw_readl(gic_dist_base_addr + GIC_DIST_CTRL) & 0x1); + return !(readl_relaxed(gic_dist_base_addr + GIC_DIST_CTRL) & 0x1); } void gic_timer_retrigger(void) { - u32 twd_int = __raw_readl(twd_base + TWD_TIMER_INTSTAT); - u32 gic_int = __raw_readl(gic_dist_base_addr + GIC_DIST_PENDING_SET); - u32 twd_ctrl = __raw_readl(twd_base + TWD_TIMER_CONTROL); + u32 twd_int = readl_relaxed(twd_base + TWD_TIMER_INTSTAT); + u32 gic_int = readl_relaxed(gic_dist_base_addr + GIC_DIST_PENDING_SET); + u32 twd_ctrl = readl_relaxed(twd_base + TWD_TIMER_CONTROL); if (twd_int && !(gic_int & BIT(IRQ_LOCALTIMER))) { /* @@ -151,11 +151,11 @@ void gic_timer_retrigger(void) * disabled. Ack the pending interrupt, and retrigger it. */ pr_warn("%s: lost localtimer interrupt\n", __func__); - __raw_writel(1, twd_base + TWD_TIMER_INTSTAT); + writel_relaxed(1, twd_base + TWD_TIMER_INTSTAT); if (!(twd_ctrl & TWD_TIMER_CONTROL_PERIODIC)) { - __raw_writel(1, twd_base + TWD_TIMER_COUNTER); + writel_relaxed(1, twd_base + TWD_TIMER_COUNTER); twd_ctrl |= TWD_TIMER_CONTROL_ENABLE; - __raw_writel(twd_ctrl, twd_base + TWD_TIMER_CONTROL); + writel_relaxed(twd_ctrl, twd_base + TWD_TIMER_CONTROL); } } } diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index 66c60fe1104c..f7bb435bb543 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -72,7 +72,7 @@ * | (../mach-omap2/omap_hwmod*) | * +-------------------------------+ * | OMAP clock/PRCM/register fns | - * | (__raw_{read,write}l, clk*) | + * | ({read,write}l_relaxed, clk*) | * +-------------------------------+ * * Device drivers should not contain any OMAP-specific code or data in @@ -3230,17 +3230,17 @@ static int _am33xx_is_hardreset_asserted(struct omap_hwmod *oh, u32 omap_hwmod_read(struct omap_hwmod *oh, u16 reg_offs) { if (oh->flags & HWMOD_16BIT_REG) - return __raw_readw(oh->_mpu_rt_va + reg_offs); + return readw_relaxed(oh->_mpu_rt_va + reg_offs); else - return __raw_readl(oh->_mpu_rt_va + reg_offs); + return readl_relaxed(oh->_mpu_rt_va + reg_offs); } void omap_hwmod_write(u32 v, struct omap_hwmod *oh, u16 reg_offs) { if (oh->flags & HWMOD_16BIT_REG) - __raw_writew(v, oh->_mpu_rt_va + reg_offs); + writew_relaxed(v, oh->_mpu_rt_va + reg_offs); else - __raw_writel(v, oh->_mpu_rt_va + reg_offs); + writel_relaxed(v, oh->_mpu_rt_va + reg_offs); } /** diff --git a/arch/arm/mach-omap2/omap_phy_internal.c b/arch/arm/mach-omap2/omap_phy_internal.c index eb8a25de67ed..50640b38f0bf 100644 --- a/arch/arm/mach-omap2/omap_phy_internal.c +++ b/arch/arm/mach-omap2/omap_phy_internal.c @@ -57,7 +57,7 @@ static int __init omap4430_phy_power_down(void) } /* Power down the phy */ - __raw_writel(PHY_PD, ctrl_base + CONTROL_DEV_CONF); + writel_relaxed(PHY_PD, ctrl_base + CONTROL_DEV_CONF); iounmap(ctrl_base); @@ -162,7 +162,7 @@ void ti81xx_musb_phy_power(u8 on) return; } - usbphycfg = __raw_readl(scm_base + USBCTRL0); + usbphycfg = readl_relaxed(scm_base + USBCTRL0); if (on) { if (cpu_is_ti816x()) { @@ -181,7 +181,7 @@ void ti81xx_musb_phy_power(u8 on) usbphycfg |= USBPHY_CM_PWRDN | USBPHY_OTG_PWRDN; } - __raw_writel(usbphycfg, scm_base + USBCTRL0); + writel_relaxed(usbphycfg, scm_base + USBCTRL0); iounmap(scm_base); } diff --git a/arch/arm/mach-omap2/prcm_mpu44xx.c b/arch/arm/mach-omap2/prcm_mpu44xx.c index c30e44a7fab0..cdbee6326d29 100644 --- a/arch/arm/mach-omap2/prcm_mpu44xx.c +++ b/arch/arm/mach-omap2/prcm_mpu44xx.c @@ -30,12 +30,12 @@ void __iomem *prcm_mpu_base; u32 omap4_prcm_mpu_read_inst_reg(s16 inst, u16 reg) { - return __raw_readl(OMAP44XX_PRCM_MPU_REGADDR(inst, reg)); + return readl_relaxed(OMAP44XX_PRCM_MPU_REGADDR(inst, reg)); } void omap4_prcm_mpu_write_inst_reg(u32 val, s16 inst, u16 reg) { - __raw_writel(val, OMAP44XX_PRCM_MPU_REGADDR(inst, reg)); + writel_relaxed(val, OMAP44XX_PRCM_MPU_REGADDR(inst, reg)); } u32 omap4_prcm_mpu_rmw_inst_reg_bits(u32 mask, u32 bits, s16 inst, s16 reg) diff --git a/arch/arm/mach-omap2/prm2xxx.h b/arch/arm/mach-omap2/prm2xxx.h index 3194dd87e0e4..d2cb6365716f 100644 --- a/arch/arm/mach-omap2/prm2xxx.h +++ b/arch/arm/mach-omap2/prm2xxx.h @@ -27,7 +27,7 @@ /* * OMAP2-specific global PRM registers - * Use __raw_{read,write}l() with these registers. + * Use {read,write}l_relaxed() with these registers. * * With a few exceptions, these are the register names beginning with * PRCM_* on 24xx. (The exceptions are the IRQSTATUS and IRQENABLE diff --git a/arch/arm/mach-omap2/prm2xxx_3xxx.h b/arch/arm/mach-omap2/prm2xxx_3xxx.h index 9624b40836d4..1a3a96392b97 100644 --- a/arch/arm/mach-omap2/prm2xxx_3xxx.h +++ b/arch/arm/mach-omap2/prm2xxx_3xxx.h @@ -55,12 +55,12 @@ /* Power/reset management domain register get/set */ static inline u32 omap2_prm_read_mod_reg(s16 module, u16 idx) { - return __raw_readl(prm_base + module + idx); + return readl_relaxed(prm_base + module + idx); } static inline void omap2_prm_write_mod_reg(u32 val, s16 module, u16 idx) { - __raw_writel(val, prm_base + module + idx); + writel_relaxed(val, prm_base + module + idx); } /* Read-modify-write a register in a PRM module. Caller must lock */ diff --git a/arch/arm/mach-omap2/prm33xx.c b/arch/arm/mach-omap2/prm33xx.c index 720440737744..93ba48a7d907 100644 --- a/arch/arm/mach-omap2/prm33xx.c +++ b/arch/arm/mach-omap2/prm33xx.c @@ -27,13 +27,13 @@ /* Read a register in a PRM instance */ u32 am33xx_prm_read_reg(s16 inst, u16 idx) { - return __raw_readl(prm_base + inst + idx); + return readl_relaxed(prm_base + inst + idx); } /* Write into a register in a PRM instance */ void am33xx_prm_write_reg(u32 val, s16 inst, u16 idx) { - __raw_writel(val, prm_base + inst + idx); + writel_relaxed(val, prm_base + inst + idx); } /* Read-modify-write a register in PRM. Caller must lock */ diff --git a/arch/arm/mach-omap2/prm3xxx.h b/arch/arm/mach-omap2/prm3xxx.h index f8eb83323b1a..1dacfc5b1959 100644 --- a/arch/arm/mach-omap2/prm3xxx.h +++ b/arch/arm/mach-omap2/prm3xxx.h @@ -26,7 +26,7 @@ /* * OMAP3-specific global PRM registers - * Use __raw_{read,write}l() with these registers. + * Use {read,write}l_relaxed() with these registers. * * With a few exceptions, these are the register names beginning with * PRM_* on 34xx. (The exceptions are the IRQSTATUS and IRQENABLE diff --git a/arch/arm/mach-omap2/prm44xx.c b/arch/arm/mach-omap2/prm44xx.c index 03a603476cfc..94a43b3cf0f0 100644 --- a/arch/arm/mach-omap2/prm44xx.c +++ b/arch/arm/mach-omap2/prm44xx.c @@ -81,13 +81,13 @@ static struct prm_reset_src_map omap44xx_prm_reset_src_map[] = { /* Read a register in a CM/PRM instance in the PRM module */ u32 omap4_prm_read_inst_reg(s16 inst, u16 reg) { - return __raw_readl(prm_base + inst + reg); + return readl_relaxed(prm_base + inst + reg); } /* Write into a register in a CM/PRM instance in the PRM module */ void omap4_prm_write_inst_reg(u32 val, s16 inst, u16 reg) { - __raw_writel(val, prm_base + inst + reg); + writel_relaxed(val, prm_base + inst + reg); } /* Read-modify-write a register in a PRM module. Caller must lock */ diff --git a/arch/arm/mach-omap2/prminst44xx.c b/arch/arm/mach-omap2/prminst44xx.c index 05fcf6de44ee..69f0dd08629c 100644 --- a/arch/arm/mach-omap2/prminst44xx.c +++ b/arch/arm/mach-omap2/prminst44xx.c @@ -49,7 +49,7 @@ u32 omap4_prminst_read_inst_reg(u8 part, s16 inst, u16 idx) BUG_ON(part >= OMAP4_MAX_PRCM_PARTITIONS || part == OMAP4430_INVALID_PRCM_PARTITION || !_prm_bases[part]); - return __raw_readl(_prm_bases[part] + inst + idx); + return readl_relaxed(_prm_bases[part] + inst + idx); } /* Write into a register in a PRM instance */ @@ -58,7 +58,7 @@ void omap4_prminst_write_inst_reg(u32 val, u8 part, s16 inst, u16 idx) BUG_ON(part >= OMAP4_MAX_PRCM_PARTITIONS || part == OMAP4430_INVALID_PRCM_PARTITION || !_prm_bases[part]); - __raw_writel(val, _prm_bases[part] + inst + idx); + writel_relaxed(val, _prm_bases[part] + inst + idx); } /* Read-modify-write a register in PRM. Caller must lock */ diff --git a/arch/arm/mach-omap2/sdrc.h b/arch/arm/mach-omap2/sdrc.h index 446aa13511fd..645a2a46b213 100644 --- a/arch/arm/mach-omap2/sdrc.h +++ b/arch/arm/mach-omap2/sdrc.h @@ -31,24 +31,24 @@ extern void __iomem *omap2_sms_base; static inline void sdrc_write_reg(u32 val, u16 reg) { - __raw_writel(val, OMAP_SDRC_REGADDR(reg)); + writel_relaxed(val, OMAP_SDRC_REGADDR(reg)); } static inline u32 sdrc_read_reg(u16 reg) { - return __raw_readl(OMAP_SDRC_REGADDR(reg)); + return readl_relaxed(OMAP_SDRC_REGADDR(reg)); } /* SMS global register get/set */ static inline void sms_write_reg(u32 val, u16 reg) { - __raw_writel(val, OMAP_SMS_REGADDR(reg)); + writel_relaxed(val, OMAP_SMS_REGADDR(reg)); } static inline u32 sms_read_reg(u16 reg) { - return __raw_readl(OMAP_SMS_REGADDR(reg)); + return readl_relaxed(OMAP_SMS_REGADDR(reg)); } extern void omap2_set_globals_sdrc(void __iomem *sdrc, void __iomem *sms); diff --git a/arch/arm/mach-omap2/sdrc2xxx.c b/arch/arm/mach-omap2/sdrc2xxx.c index 907291714643..ae3f1553158d 100644 --- a/arch/arm/mach-omap2/sdrc2xxx.c +++ b/arch/arm/mach-omap2/sdrc2xxx.c @@ -103,9 +103,9 @@ u32 omap2xxx_sdrc_reprogram(u32 level, u32 force) * prm2xxx.c function */ if (cpu_is_omap2420()) - __raw_writel(0xffff, OMAP2420_PRCM_VOLTSETUP); + writel_relaxed(0xffff, OMAP2420_PRCM_VOLTSETUP); else - __raw_writel(0xffff, OMAP2430_PRCM_VOLTSETUP); + writel_relaxed(0xffff, OMAP2430_PRCM_VOLTSETUP); omap2_sram_reprogram_sdrc(level, dll_ctrl, m_type); curr_perf_level = level; local_irq_restore(flags); diff --git a/arch/arm/mach-omap2/sr_device.c b/arch/arm/mach-omap2/sr_device.c index d7bc33f15344..1b91ef0c182a 100644 --- a/arch/arm/mach-omap2/sr_device.c +++ b/arch/arm/mach-omap2/sr_device.c @@ -57,7 +57,7 @@ static void __init sr_set_nvalues(struct omap_volt_data *volt_data, /* * In OMAP4 the efuse registers are 24 bit aligned. - * A __raw_readl will fail for non-32 bit aligned address + * A readl_relaxed will fail for non-32 bit aligned address * and hence the 8-bit read and shift. */ if (cpu_is_omap44xx()) { diff --git a/arch/arm/mach-omap2/sram.c b/arch/arm/mach-omap2/sram.c index 4bd096836235..ddf1818af228 100644 --- a/arch/arm/mach-omap2/sram.c +++ b/arch/arm/mach-omap2/sram.c @@ -70,16 +70,16 @@ static int is_sram_locked(void) if (OMAP2_DEVICE_TYPE_GP == omap_type()) { /* RAMFW: R/W access to all initiators for all qualifier sets */ if (cpu_is_omap242x()) { - __raw_writel(0xFF, OMAP24XX_VA_REQINFOPERM0); /* all q-vects */ - __raw_writel(0xCFDE, OMAP24XX_VA_READPERM0); /* all i-read */ - __raw_writel(0xCFDE, OMAP24XX_VA_WRITEPERM0); /* all i-write */ + writel_relaxed(0xFF, OMAP24XX_VA_REQINFOPERM0); /* all q-vects */ + writel_relaxed(0xCFDE, OMAP24XX_VA_READPERM0); /* all i-read */ + writel_relaxed(0xCFDE, OMAP24XX_VA_WRITEPERM0); /* all i-write */ } if (cpu_is_omap34xx()) { - __raw_writel(0xFFFF, OMAP34XX_VA_REQINFOPERM0); /* all q-vects */ - __raw_writel(0xFFFF, OMAP34XX_VA_READPERM0); /* all i-read */ - __raw_writel(0xFFFF, OMAP34XX_VA_WRITEPERM0); /* all i-write */ - __raw_writel(0x0, OMAP34XX_VA_ADDR_MATCH2); - __raw_writel(0xFFFFFFFF, OMAP34XX_VA_SMS_RG_ATT0); + writel_relaxed(0xFFFF, OMAP34XX_VA_REQINFOPERM0); /* all q-vects */ + writel_relaxed(0xFFFF, OMAP34XX_VA_READPERM0); /* all i-read */ + writel_relaxed(0xFFFF, OMAP34XX_VA_WRITEPERM0); /* all i-write */ + writel_relaxed(0x0, OMAP34XX_VA_ADDR_MATCH2); + writel_relaxed(0xFFFFFFFF, OMAP34XX_VA_SMS_RG_ATT0); } return 0; } else diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c index b62de9f9d05c..a8ec16787170 100644 --- a/arch/arm/mach-omap2/timer.c +++ b/arch/arm/mach-omap2/timer.c @@ -546,15 +546,15 @@ static void __init realtime_counter_init(void) } /* Program numerator and denumerator registers */ - reg = __raw_readl(base + INCREMENTER_NUMERATOR_OFFSET) & + reg = readl_relaxed(base + INCREMENTER_NUMERATOR_OFFSET) & NUMERATOR_DENUMERATOR_MASK; reg |= num; - __raw_writel(reg, base + INCREMENTER_NUMERATOR_OFFSET); + writel_relaxed(reg, base + INCREMENTER_NUMERATOR_OFFSET); - reg = __raw_readl(base + INCREMENTER_DENUMERATOR_RELOAD_OFFSET) & + reg = readl_relaxed(base + INCREMENTER_DENUMERATOR_RELOAD_OFFSET) & NUMERATOR_DENUMERATOR_MASK; reg |= den; - __raw_writel(reg, base + INCREMENTER_DENUMERATOR_RELOAD_OFFSET); + writel_relaxed(reg, base + INCREMENTER_DENUMERATOR_RELOAD_OFFSET); arch_timer_freq = (rate / den) * num; set_cntfreq(); diff --git a/arch/arm/mach-omap2/vc.c b/arch/arm/mach-omap2/vc.c index 49ac7977e03e..267f204559c3 100644 --- a/arch/arm/mach-omap2/vc.c +++ b/arch/arm/mach-omap2/vc.c @@ -462,7 +462,7 @@ static void omap4_set_timings(struct voltagedomain *voltdm, bool off_mode) val |= omap4_usec_to_val_scrm(tshut, OMAP4_DOWNTIME_SHIFT, OMAP4_DOWNTIME_MASK); - __raw_writel(val, OMAP4_SCRM_CLKSETUPTIME); + writel_relaxed(val, OMAP4_SCRM_CLKSETUPTIME); } /* OMAP4 specific voltage init functions */ @@ -584,7 +584,7 @@ static void __init omap4_vc_i2c_timing_init(struct voltagedomain *voltdm) val = i2c_data->loadbits << 25 | i2c_data->loadbits << 29; /* Write to SYSCTRL_PADCONF_WKUP_CTRL_I2C_2 to setup I2C pull */ - __raw_writel(val, OMAP2_L4_IO_ADDRESS(OMAP4_CTRL_MODULE_PAD_WKUP + + writel_relaxed(val, OMAP2_L4_IO_ADDRESS(OMAP4_CTRL_MODULE_PAD_WKUP + OMAP4_CTRL_MODULE_PAD_WKUP_CONTROL_I2C_2)); /* HSSCLH can always be zero */ diff --git a/arch/arm/mach-omap2/wd_timer.c b/arch/arm/mach-omap2/wd_timer.c index d15c7bbab8e2..97d6607d447a 100644 --- a/arch/arm/mach-omap2/wd_timer.c +++ b/arch/arm/mach-omap2/wd_timer.c @@ -49,12 +49,12 @@ int omap2_wd_timer_disable(struct omap_hwmod *oh) } /* sequence required to disable watchdog */ - __raw_writel(0xAAAA, base + OMAP_WDT_SPR); - while (__raw_readl(base + OMAP_WDT_WPS) & 0x10) + writel_relaxed(0xAAAA, base + OMAP_WDT_SPR); + while (readl_relaxed(base + OMAP_WDT_WPS) & 0x10) cpu_relax(); - __raw_writel(0x5555, base + OMAP_WDT_SPR); - while (__raw_readl(base + OMAP_WDT_WPS) & 0x10) + writel_relaxed(0x5555, base + OMAP_WDT_SPR); + while (readl_relaxed(base + OMAP_WDT_WPS) & 0x10) cpu_relax(); return 0; From 834cacfbef09afc5566eae4dbdc08a422e90451b Mon Sep 17 00:00:00 2001 From: Victor Kamensky Date: Tue, 15 Apr 2014 20:37:47 +0300 Subject: [PATCH 36/87] ARM: OMAP: dmtimer: raw read and write endian fix All OMAP IP blocks expect LE data, but CPU may operate in BE mode. Need to use endian neutral functions to read/write h/w registers. I.e instead of __raw_read[lw] and __raw_write[lw] functions code need to use read[lw]_relaxed and write[lw]_relaxed functions. If the first simply reads/writes register, the second will byteswap it if host operates in BE mode. Changes are trivial sed like replacement of __raw_xxx functions with xxx_relaxed variant. Signed-off-by: Victor Kamensky Signed-off-by: Taras Kondratiuk Signed-off-by: Tony Lindgren --- arch/arm/plat-omap/dmtimer.c | 8 ++++---- arch/arm/plat-omap/include/plat/dmtimer.h | 16 ++++++++-------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c index 869254cebf84..db10169a08de 100644 --- a/arch/arm/plat-omap/dmtimer.c +++ b/arch/arm/plat-omap/dmtimer.c @@ -103,7 +103,7 @@ static void omap_timer_restore_context(struct omap_dm_timer *timer) timer->context.tmar); omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG, timer->context.tsicr); - __raw_writel(timer->context.tier, timer->irq_ena); + writel_relaxed(timer->context.tier, timer->irq_ena); omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, timer->context.tclr); } @@ -699,9 +699,9 @@ int omap_dm_timer_set_int_disable(struct omap_dm_timer *timer, u32 mask) omap_dm_timer_enable(timer); if (timer->revision == 1) - l = __raw_readl(timer->irq_ena) & ~mask; + l = readl_relaxed(timer->irq_ena) & ~mask; - __raw_writel(l, timer->irq_dis); + writel_relaxed(l, timer->irq_dis); l = omap_dm_timer_read_reg(timer, OMAP_TIMER_WAKEUP_EN_REG) & ~mask; omap_dm_timer_write_reg(timer, OMAP_TIMER_WAKEUP_EN_REG, l); @@ -722,7 +722,7 @@ unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer) return 0; } - l = __raw_readl(timer->irq_stat); + l = readl_relaxed(timer->irq_stat); return l; } diff --git a/arch/arm/plat-omap/include/plat/dmtimer.h b/arch/arm/plat-omap/include/plat/dmtimer.h index 2861b155485a..dd79f3005cdf 100644 --- a/arch/arm/plat-omap/include/plat/dmtimer.h +++ b/arch/arm/plat-omap/include/plat/dmtimer.h @@ -280,20 +280,20 @@ static inline u32 __omap_dm_timer_read(struct omap_dm_timer *timer, u32 reg, int posted) { if (posted) - while (__raw_readl(timer->pend) & (reg >> WPSHIFT)) + while (readl_relaxed(timer->pend) & (reg >> WPSHIFT)) cpu_relax(); - return __raw_readl(timer->func_base + (reg & 0xff)); + return readl_relaxed(timer->func_base + (reg & 0xff)); } static inline void __omap_dm_timer_write(struct omap_dm_timer *timer, u32 reg, u32 val, int posted) { if (posted) - while (__raw_readl(timer->pend) & (reg >> WPSHIFT)) + while (readl_relaxed(timer->pend) & (reg >> WPSHIFT)) cpu_relax(); - __raw_writel(val, timer->func_base + (reg & 0xff)); + writel_relaxed(val, timer->func_base + (reg & 0xff)); } static inline void __omap_dm_timer_init_regs(struct omap_dm_timer *timer) @@ -301,7 +301,7 @@ static inline void __omap_dm_timer_init_regs(struct omap_dm_timer *timer) u32 tidr; /* Assume v1 ip if bits [31:16] are zero */ - tidr = __raw_readl(timer->io_base); + tidr = readl_relaxed(timer->io_base); if (!(tidr >> 16)) { timer->revision = 1; timer->irq_stat = timer->io_base + OMAP_TIMER_V1_STAT_OFFSET; @@ -385,7 +385,7 @@ static inline void __omap_dm_timer_stop(struct omap_dm_timer *timer, } /* Ack possibly pending interrupt */ - __raw_writel(OMAP_TIMER_INT_OVERFLOW, timer->irq_stat); + writel_relaxed(OMAP_TIMER_INT_OVERFLOW, timer->irq_stat); } static inline void __omap_dm_timer_load_start(struct omap_dm_timer *timer, @@ -399,7 +399,7 @@ static inline void __omap_dm_timer_load_start(struct omap_dm_timer *timer, static inline void __omap_dm_timer_int_enable(struct omap_dm_timer *timer, unsigned int value) { - __raw_writel(value, timer->irq_ena); + writel_relaxed(value, timer->irq_ena); __omap_dm_timer_write(timer, OMAP_TIMER_WAKEUP_EN_REG, value, 0); } @@ -412,7 +412,7 @@ __omap_dm_timer_read_counter(struct omap_dm_timer *timer, int posted) static inline void __omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value) { - __raw_writel(value, timer->irq_stat); + writel_relaxed(value, timer->irq_stat); } #endif /* __ASM_ARCH_DMTIMER_H */ From f6f3b50f996b938b034b14b5084108b2acfcae7d Mon Sep 17 00:00:00 2001 From: Victor Kamensky Date: Tue, 15 Apr 2014 20:37:48 +0300 Subject: [PATCH 37/87] ARM: OMAP: counter-32k: raw read and write endian fix All OMAP IP blocks expect LE data, but CPU may operate in BE mode. Need to use endian neutral functions to read/write h/w registers. I.e instead of __raw_read[lw] and __raw_write[lw] functions code need to use read[lw]_relaxed and write[lw]_relaxed functions. If the first simply reads/writes register, the second will byteswap it if host operates in BE mode. Changes are trivial sed like replacement of __raw_xxx functions with xxx_relaxed variant. Signed-off-by: Victor Kamensky Signed-off-by: Taras Kondratiuk Signed-off-by: Tony Lindgren --- arch/arm/plat-omap/counter_32k.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm/plat-omap/counter_32k.c b/arch/arm/plat-omap/counter_32k.c index 384a776d8eb2..61b4d705c267 100644 --- a/arch/arm/plat-omap/counter_32k.c +++ b/arch/arm/plat-omap/counter_32k.c @@ -40,7 +40,7 @@ static void __iomem *sync32k_cnt_reg; static u64 notrace omap_32k_read_sched_clock(void) { - return sync32k_cnt_reg ? __raw_readl(sync32k_cnt_reg) : 0; + return sync32k_cnt_reg ? readl_relaxed(sync32k_cnt_reg) : 0; } /** @@ -64,7 +64,7 @@ static void omap_read_persistent_clock(struct timespec *ts) spin_lock_irqsave(&read_persistent_clock_lock, flags); last_cycles = cycles; - cycles = sync32k_cnt_reg ? __raw_readl(sync32k_cnt_reg) : 0; + cycles = sync32k_cnt_reg ? readl_relaxed(sync32k_cnt_reg) : 0; nsecs = clocksource_cyc2ns(cycles - last_cycles, persistent_mult, persistent_shift); @@ -95,7 +95,7 @@ int __init omap_init_clocksource_32k(void __iomem *vbase) * The 'SCHEME' bits(30-31) of the revision register is used * to identify the version. */ - if (__raw_readl(vbase + OMAP2_32KSYNCNT_REV_OFF) & + if (readl_relaxed(vbase + OMAP2_32KSYNCNT_REV_OFF) & OMAP2_32KSYNCNT_REV_SCHEME) sync32k_cnt_reg = vbase + OMAP2_32KSYNCNT_CR_OFF_HIGH; else From be2d62844819b3536233b7fc726b8f17d9fa7f05 Mon Sep 17 00:00:00 2001 From: Victor Kamensky Date: Tue, 15 Apr 2014 20:37:49 +0300 Subject: [PATCH 38/87] ARM: OMAP: debug-leds: raw read and write endian fix All OMAP IP blocks expect LE data, but CPU may operate in BE mode. Need to use endian neutral functions to read/write h/w registers. I.e instead of __raw_read[lw] and __raw_write[lw] functions code need to use read[lw]_relaxed and write[lw]_relaxed functions. If the first simply reads/writes register, the second will byteswap it if host operates in BE mode. Changes are trivial sed like replacement of __raw_xxx functions with xxx_relaxed variant. Signed-off-by: Victor Kamensky Signed-off-by: Taras Kondratiuk Signed-off-by: Tony Lindgren --- arch/arm/plat-omap/debug-leds.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/arch/arm/plat-omap/debug-leds.c b/arch/arm/plat-omap/debug-leds.c index aa7ebc6bcd65..48b69de89a5d 100644 --- a/arch/arm/plat-omap/debug-leds.c +++ b/arch/arm/plat-omap/debug-leds.c @@ -85,12 +85,12 @@ static void dbg_led_set(struct led_classdev *cdev, struct dbg_led *led = container_of(cdev, struct dbg_led, cdev); u16 reg; - reg = __raw_readw(&fpga->leds); + reg = readw_relaxed(&fpga->leds); if (b != LED_OFF) reg |= led->mask; else reg &= ~led->mask; - __raw_writew(reg, &fpga->leds); + writew_relaxed(reg, &fpga->leds); } static enum led_brightness dbg_led_get(struct led_classdev *cdev) @@ -98,7 +98,7 @@ static enum led_brightness dbg_led_get(struct led_classdev *cdev) struct dbg_led *led = container_of(cdev, struct dbg_led, cdev); u16 reg; - reg = __raw_readw(&fpga->leds); + reg = readw_relaxed(&fpga->leds); return (reg & led->mask) ? LED_FULL : LED_OFF; } @@ -112,7 +112,7 @@ static int fpga_probe(struct platform_device *pdev) return -ENODEV; fpga = ioremap(iomem->start, resource_size(iomem)); - __raw_writew(0xff, &fpga->leds); + writew_relaxed(0xff, &fpga->leds); for (i = 0; i < ARRAY_SIZE(dbg_leds); i++) { struct dbg_led *led; @@ -138,15 +138,15 @@ static int fpga_probe(struct platform_device *pdev) static int fpga_suspend_noirq(struct device *dev) { - fpga_led_state = __raw_readw(&fpga->leds); - __raw_writew(0xff, &fpga->leds); + fpga_led_state = readw_relaxed(&fpga->leds); + writew_relaxed(0xff, &fpga->leds); return 0; } static int fpga_resume_noirq(struct device *dev) { - __raw_writew(~fpga_led_state, &fpga->leds); + writew_relaxed(~fpga_led_state, &fpga->leds); return 0; } From d8b532578f39fdec159105bc415938910351a699 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Fri, 9 May 2014 05:48:44 +0900 Subject: [PATCH 39/87] ARM: S3C24XX: cpufreq-utils: don't write raw values to MPLLCON when using ccf The s3c24xx cpufreq driver needs to change the mpll speed and was doing this by writing raw values from a translation table into the MPLLCON register. Change this to use a regular clk_set_rate call when using the common clock framework and only write the raw value in the samsung_clock case. The s3c cpufreq driver does already aquire the mpll, so simply add a reference to struct s3c_cpufreq_config to let set_fvco access it. While struct clk is opaque the differenciation between samsung clock and common clock is kept, as the samsung-clock mpll clk does not implement a real set_rate. Signed-off-by: Heiko Stuebner Acked-by: Tomasz Figa Signed-off-by: Kukjin Kim --- arch/arm/mach-s3c24xx/cpufreq-utils.c | 8 ++++++++ arch/arm/plat-samsung/include/plat/cpu-freq-core.h | 1 + drivers/cpufreq/s3c24xx-cpufreq.c | 1 + 3 files changed, 10 insertions(+) diff --git a/arch/arm/mach-s3c24xx/cpufreq-utils.c b/arch/arm/mach-s3c24xx/cpufreq-utils.c index 2a0aa5684e72..c1b7508523ad 100644 --- a/arch/arm/mach-s3c24xx/cpufreq-utils.c +++ b/arch/arm/mach-s3c24xx/cpufreq-utils.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -60,5 +61,12 @@ void s3c2410_cpufreq_setrefresh(struct s3c_cpufreq_config *cfg) */ void s3c2410_set_fvco(struct s3c_cpufreq_config *cfg) { +#ifdef CONFIG_SAMSUNG_CLOCK __raw_writel(cfg->pll.driver_data, S3C2410_MPLLCON); +#endif + +#ifdef CONFIG_COMMON_CLK + if (!IS_ERR(cfg->mpll)) + clk_set_rate(cfg->mpll, cfg->pll.frequency); +#endif } diff --git a/arch/arm/plat-samsung/include/plat/cpu-freq-core.h b/arch/arm/plat-samsung/include/plat/cpu-freq-core.h index 7231c8e4975e..72d4178ad23b 100644 --- a/arch/arm/plat-samsung/include/plat/cpu-freq-core.h +++ b/arch/arm/plat-samsung/include/plat/cpu-freq-core.h @@ -119,6 +119,7 @@ struct s3c_plltab { struct s3c_cpufreq_config { struct s3c_freq freq; struct s3c_freq max; + struct clk *mpll; struct cpufreq_frequency_table pll; struct s3c_clkdivs divs; struct s3c_cpufreq_info *info; /* for core, not drivers */ diff --git a/drivers/cpufreq/s3c24xx-cpufreq.c b/drivers/cpufreq/s3c24xx-cpufreq.c index be1b2b5c9753..227ebf7c1eea 100644 --- a/drivers/cpufreq/s3c24xx-cpufreq.c +++ b/drivers/cpufreq/s3c24xx-cpufreq.c @@ -141,6 +141,7 @@ static int s3c_cpufreq_calcdivs(struct s3c_cpufreq_config *cfg) static void s3c_cpufreq_setfvco(struct s3c_cpufreq_config *cfg) { + cfg->mpll = _clk_mpll; (cfg->info->set_fvco)(cfg); } From 5799ea12a41286d9588155a1abd828f43bc63d6b Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Fri, 9 May 2014 05:48:51 +0900 Subject: [PATCH 40/87] clk: samsung: add clock driver for external clock outputs This adds a driver for controlling the external clock outputs of s3c24xx architectures including the dclk muxes and dividers. The driver at the moment only supports the legacy non-dt boards using these clock outputs. The clock-output control itself is part of the system-controller mainly controlled by the pinctrl drivers. So it should most likely be integrated there for dt platforms. Signed-off-by: Heiko Stuebner Acked-by: Mike Turquette Signed-off-by: Kukjin Kim --- drivers/clk/samsung/Makefile | 1 + drivers/clk/samsung/clk-s3c2410-dclk.c | 440 +++++++++++++++++++++++++ 2 files changed, 441 insertions(+) create mode 100644 drivers/clk/samsung/clk-s3c2410-dclk.c diff --git a/drivers/clk/samsung/Makefile b/drivers/clk/samsung/Makefile index 77313e27bc39..9892de4978e3 100644 --- a/drivers/clk/samsung/Makefile +++ b/drivers/clk/samsung/Makefile @@ -8,6 +8,7 @@ obj-$(CONFIG_SOC_EXYNOS5250) += clk-exynos5250.o obj-$(CONFIG_SOC_EXYNOS5420) += clk-exynos5420.o obj-$(CONFIG_SOC_EXYNOS5440) += clk-exynos5440.o obj-$(CONFIG_ARCH_EXYNOS) += clk-exynos-audss.o +obj-$(CONFIG_S3C2410_COMMON_DCLK)+= clk-s3c2410-dclk.o obj-$(CONFIG_S3C2412_COMMON_CLK)+= clk-s3c2412.o obj-$(CONFIG_S3C2443_COMMON_CLK)+= clk-s3c2443.o obj-$(CONFIG_ARCH_S3C64XX) += clk-s3c64xx.o diff --git a/drivers/clk/samsung/clk-s3c2410-dclk.c b/drivers/clk/samsung/clk-s3c2410-dclk.c new file mode 100644 index 000000000000..8d8dff005c10 --- /dev/null +++ b/drivers/clk/samsung/clk-s3c2410-dclk.c @@ -0,0 +1,440 @@ +/* + * Copyright (c) 2013 Heiko Stuebner + * + * 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. + * + * Common Clock Framework support for s3c24xx external clock output. + */ + +#include +#include +#include "clk.h" + +/* legacy access to misccr, until dt conversion is finished */ +#include +#include + +#define MUX_DCLK0 0 +#define MUX_DCLK1 1 +#define DIV_DCLK0 2 +#define DIV_DCLK1 3 +#define GATE_DCLK0 4 +#define GATE_DCLK1 5 +#define MUX_CLKOUT0 6 +#define MUX_CLKOUT1 7 +#define DCLK_MAX_CLKS (MUX_CLKOUT1 + 1) + +enum supported_socs { + S3C2410, + S3C2412, + S3C2440, + S3C2443, +}; + +struct s3c24xx_dclk_drv_data { + const char **clkout0_parent_names; + int clkout0_num_parents; + const char **clkout1_parent_names; + int clkout1_num_parents; + const char **mux_parent_names; + int mux_num_parents; +}; + +/* + * Clock for output-parent selection in misccr + */ + +struct s3c24xx_clkout { + struct clk_hw hw; + u32 mask; + u8 shift; +}; + +#define to_s3c24xx_clkout(_hw) container_of(_hw, struct s3c24xx_clkout, hw) + +static u8 s3c24xx_clkout_get_parent(struct clk_hw *hw) +{ + struct s3c24xx_clkout *clkout = to_s3c24xx_clkout(hw); + int num_parents = __clk_get_num_parents(hw->clk); + u32 val; + + val = readl_relaxed(S3C24XX_MISCCR) >> clkout->shift; + val >>= clkout->shift; + val &= clkout->mask; + + if (val >= num_parents) + return -EINVAL; + + return val; +} + +static int s3c24xx_clkout_set_parent(struct clk_hw *hw, u8 index) +{ + struct s3c24xx_clkout *clkout = to_s3c24xx_clkout(hw); + int ret = 0; + + s3c2410_modify_misccr((clkout->mask << clkout->shift), + (index << clkout->shift)); + + return ret; +} + +const struct clk_ops s3c24xx_clkout_ops = { + .get_parent = s3c24xx_clkout_get_parent, + .set_parent = s3c24xx_clkout_set_parent, + .determine_rate = __clk_mux_determine_rate, +}; + +struct clk *s3c24xx_register_clkout(struct device *dev, const char *name, + const char **parent_names, u8 num_parents, + u8 shift, u32 mask) +{ + struct s3c24xx_clkout *clkout; + struct clk *clk; + struct clk_init_data init; + + /* allocate the clkout */ + clkout = kzalloc(sizeof(*clkout), GFP_KERNEL); + if (!clkout) + return ERR_PTR(-ENOMEM); + + init.name = name; + init.ops = &s3c24xx_clkout_ops; + init.flags = CLK_IS_BASIC; + init.parent_names = parent_names; + init.num_parents = num_parents; + + clkout->shift = shift; + clkout->mask = mask; + clkout->hw.init = &init; + + clk = clk_register(dev, &clkout->hw); + + return clk; +} + +/* + * dclk and clkout init + */ + +struct s3c24xx_dclk { + struct device *dev; + void __iomem *base; + struct clk_onecell_data clk_data; + struct notifier_block dclk0_div_change_nb; + struct notifier_block dclk1_div_change_nb; + spinlock_t dclk_lock; + unsigned long reg_save; +}; + +#define to_s3c24xx_dclk0(x) \ + container_of(x, struct s3c24xx_dclk, dclk0_div_change_nb) + +#define to_s3c24xx_dclk1(x) \ + container_of(x, struct s3c24xx_dclk, dclk1_div_change_nb) + +PNAME(dclk_s3c2410_p) = { "pclk", "uclk" }; +PNAME(clkout0_s3c2410_p) = { "mpll", "upll", "fclk", "hclk", "pclk", + "gate_dclk0" }; +PNAME(clkout1_s3c2410_p) = { "mpll", "upll", "fclk", "hclk", "pclk", + "gate_dclk1" }; + +PNAME(clkout0_s3c2412_p) = { "mpll", "upll", "rtc_clkout", + "hclk", "pclk", "gate_dclk0" }; +PNAME(clkout1_s3c2412_p) = { "xti", "upll", "fclk", "hclk", "pclk", + "gate_dclk1" }; + +PNAME(clkout0_s3c2440_p) = { "xti", "upll", "fclk", "hclk", "pclk", + "gate_dclk0" }; +PNAME(clkout1_s3c2440_p) = { "mpll", "upll", "rtc_clkout", + "hclk", "pclk", "gate_dclk1" }; + +PNAME(dclk_s3c2443_p) = { "pclk", "epll" }; +PNAME(clkout0_s3c2443_p) = { "xti", "epll", "armclk", "hclk", "pclk", + "gate_dclk0" }; +PNAME(clkout1_s3c2443_p) = { "dummy", "epll", "rtc_clkout", + "hclk", "pclk", "gate_dclk1" }; + +#define DCLKCON_DCLK_DIV_MASK 0xf +#define DCLKCON_DCLK0_DIV_SHIFT 4 +#define DCLKCON_DCLK0_CMP_SHIFT 8 +#define DCLKCON_DCLK1_DIV_SHIFT 20 +#define DCLKCON_DCLK1_CMP_SHIFT 24 + +static void s3c24xx_dclk_update_cmp(struct s3c24xx_dclk *s3c24xx_dclk, + int div_shift, int cmp_shift) +{ + unsigned long flags = 0; + u32 dclk_con, div, cmp; + + spin_lock_irqsave(&s3c24xx_dclk->dclk_lock, flags); + + dclk_con = readl_relaxed(s3c24xx_dclk->base); + + div = ((dclk_con >> div_shift) & DCLKCON_DCLK_DIV_MASK) + 1; + cmp = ((div + 1) / 2) - 1; + + dclk_con &= ~(DCLKCON_DCLK_DIV_MASK << cmp_shift); + dclk_con |= (cmp << cmp_shift); + + writel_relaxed(dclk_con, s3c24xx_dclk->base); + + spin_unlock_irqrestore(&s3c24xx_dclk->dclk_lock, flags); +} + +static int s3c24xx_dclk0_div_notify(struct notifier_block *nb, + unsigned long event, void *data) +{ + struct s3c24xx_dclk *s3c24xx_dclk = to_s3c24xx_dclk0(nb); + + if (event == POST_RATE_CHANGE) { + s3c24xx_dclk_update_cmp(s3c24xx_dclk, + DCLKCON_DCLK0_DIV_SHIFT, DCLKCON_DCLK0_CMP_SHIFT); + } + + return NOTIFY_DONE; +} + +static int s3c24xx_dclk1_div_notify(struct notifier_block *nb, + unsigned long event, void *data) +{ + struct s3c24xx_dclk *s3c24xx_dclk = to_s3c24xx_dclk1(nb); + + if (event == POST_RATE_CHANGE) { + s3c24xx_dclk_update_cmp(s3c24xx_dclk, + DCLKCON_DCLK1_DIV_SHIFT, DCLKCON_DCLK1_CMP_SHIFT); + } + + return NOTIFY_DONE; +} + +#ifdef CONFIG_PM_SLEEP +static int s3c24xx_dclk_suspend(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct s3c24xx_dclk *s3c24xx_dclk = platform_get_drvdata(pdev); + + s3c24xx_dclk->reg_save = readl_relaxed(s3c24xx_dclk->base); + return 0; +} + +static int s3c24xx_dclk_resume(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct s3c24xx_dclk *s3c24xx_dclk = platform_get_drvdata(pdev); + + writel_relaxed(s3c24xx_dclk->reg_save, s3c24xx_dclk->base); + return 0; +} +#endif + +static SIMPLE_DEV_PM_OPS(s3c24xx_dclk_pm_ops, + s3c24xx_dclk_suspend, s3c24xx_dclk_resume); + +static int s3c24xx_dclk_probe(struct platform_device *pdev) +{ + struct s3c24xx_dclk *s3c24xx_dclk; + struct resource *mem; + struct clk **clk_table; + struct s3c24xx_dclk_drv_data *dclk_variant; + int ret, i; + + s3c24xx_dclk = devm_kzalloc(&pdev->dev, sizeof(*s3c24xx_dclk), + GFP_KERNEL); + if (!s3c24xx_dclk) + return -ENOMEM; + + s3c24xx_dclk->dev = &pdev->dev; + platform_set_drvdata(pdev, s3c24xx_dclk); + spin_lock_init(&s3c24xx_dclk->dclk_lock); + + clk_table = devm_kzalloc(&pdev->dev, + sizeof(struct clk *) * DCLK_MAX_CLKS, + GFP_KERNEL); + if (!clk_table) + return -ENOMEM; + + s3c24xx_dclk->clk_data.clks = clk_table; + s3c24xx_dclk->clk_data.clk_num = DCLK_MAX_CLKS; + + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + s3c24xx_dclk->base = devm_ioremap_resource(&pdev->dev, mem); + if (IS_ERR(s3c24xx_dclk->base)) + return PTR_ERR(s3c24xx_dclk->base); + + dclk_variant = (struct s3c24xx_dclk_drv_data *) + platform_get_device_id(pdev)->driver_data; + + + clk_table[MUX_DCLK0] = clk_register_mux(&pdev->dev, "mux_dclk0", + dclk_variant->mux_parent_names, + dclk_variant->mux_num_parents, 0, + s3c24xx_dclk->base, 1, 1, 0, + &s3c24xx_dclk->dclk_lock); + clk_table[MUX_DCLK1] = clk_register_mux(&pdev->dev, "mux_dclk1", + dclk_variant->mux_parent_names, + dclk_variant->mux_num_parents, 0, + s3c24xx_dclk->base, 17, 1, 0, + &s3c24xx_dclk->dclk_lock); + + clk_table[DIV_DCLK0] = clk_register_divider(&pdev->dev, "div_dclk0", + "mux_dclk0", 0, s3c24xx_dclk->base, + 4, 4, 0, &s3c24xx_dclk->dclk_lock); + clk_table[DIV_DCLK1] = clk_register_divider(&pdev->dev, "div_dclk1", + "mux_dclk1", 0, s3c24xx_dclk->base, + 20, 4, 0, &s3c24xx_dclk->dclk_lock); + + clk_table[GATE_DCLK0] = clk_register_gate(&pdev->dev, "gate_dclk0", + "div_dclk0", CLK_SET_RATE_PARENT, + s3c24xx_dclk->base, 0, 0, + &s3c24xx_dclk->dclk_lock); + clk_table[GATE_DCLK1] = clk_register_gate(&pdev->dev, "gate_dclk1", + "div_dclk1", CLK_SET_RATE_PARENT, + s3c24xx_dclk->base, 16, 0, + &s3c24xx_dclk->dclk_lock); + + clk_table[MUX_CLKOUT0] = s3c24xx_register_clkout(&pdev->dev, + "clkout0", dclk_variant->clkout0_parent_names, + dclk_variant->clkout0_num_parents, 4, 7); + clk_table[MUX_CLKOUT1] = s3c24xx_register_clkout(&pdev->dev, + "clkout1", dclk_variant->clkout1_parent_names, + dclk_variant->clkout1_num_parents, 8, 7); + + for (i = 0; i < DCLK_MAX_CLKS; i++) + if (IS_ERR(clk_table[i])) { + dev_err(&pdev->dev, "clock %d failed to register\n", i); + ret = PTR_ERR(clk_table[i]); + goto err_clk_register; + } + + ret = clk_register_clkdev(clk_table[MUX_DCLK0], "dclk0", NULL); + if (!ret) + ret = clk_register_clkdev(clk_table[MUX_DCLK1], "dclk1", NULL); + if (!ret) + ret = clk_register_clkdev(clk_table[MUX_CLKOUT0], + "clkout0", NULL); + if (!ret) + ret = clk_register_clkdev(clk_table[MUX_CLKOUT1], + "clkout1", NULL); + if (ret) { + dev_err(&pdev->dev, "failed to register aliases, %d\n", ret); + goto err_clk_register; + } + + s3c24xx_dclk->dclk0_div_change_nb.notifier_call = + s3c24xx_dclk0_div_notify; + + s3c24xx_dclk->dclk1_div_change_nb.notifier_call = + s3c24xx_dclk1_div_notify; + + ret = clk_notifier_register(clk_table[DIV_DCLK0], + &s3c24xx_dclk->dclk0_div_change_nb); + if (ret) + goto err_clk_register; + + ret = clk_notifier_register(clk_table[DIV_DCLK1], + &s3c24xx_dclk->dclk1_div_change_nb); + if (ret) + goto err_dclk_notify; + + return 0; + +err_dclk_notify: + clk_notifier_unregister(clk_table[DIV_DCLK0], + &s3c24xx_dclk->dclk0_div_change_nb); +err_clk_register: + for (i = 0; i < DCLK_MAX_CLKS; i++) + if (clk_table[i] && !IS_ERR(clk_table[i])) + clk_unregister(clk_table[i]); + + return ret; +} + +static int s3c24xx_dclk_remove(struct platform_device *pdev) +{ + struct s3c24xx_dclk *s3c24xx_dclk = platform_get_drvdata(pdev); + struct clk **clk_table = s3c24xx_dclk->clk_data.clks; + int i; + + clk_notifier_unregister(clk_table[DIV_DCLK1], + &s3c24xx_dclk->dclk1_div_change_nb); + clk_notifier_unregister(clk_table[DIV_DCLK0], + &s3c24xx_dclk->dclk0_div_change_nb); + + for (i = 0; i < DCLK_MAX_CLKS; i++) + clk_unregister(clk_table[i]); + + return 0; +} + +static struct s3c24xx_dclk_drv_data dclk_variants[] = { + [S3C2410] = { + .clkout0_parent_names = clkout0_s3c2410_p, + .clkout0_num_parents = ARRAY_SIZE(clkout0_s3c2410_p), + .clkout1_parent_names = clkout1_s3c2410_p, + .clkout1_num_parents = ARRAY_SIZE(clkout1_s3c2410_p), + .mux_parent_names = dclk_s3c2410_p, + .mux_num_parents = ARRAY_SIZE(dclk_s3c2410_p), + }, + [S3C2412] = { + .clkout0_parent_names = clkout0_s3c2412_p, + .clkout0_num_parents = ARRAY_SIZE(clkout0_s3c2412_p), + .clkout1_parent_names = clkout1_s3c2412_p, + .clkout1_num_parents = ARRAY_SIZE(clkout1_s3c2412_p), + .mux_parent_names = dclk_s3c2410_p, + .mux_num_parents = ARRAY_SIZE(dclk_s3c2410_p), + }, + [S3C2440] = { + .clkout0_parent_names = clkout0_s3c2440_p, + .clkout0_num_parents = ARRAY_SIZE(clkout0_s3c2440_p), + .clkout1_parent_names = clkout1_s3c2440_p, + .clkout1_num_parents = ARRAY_SIZE(clkout1_s3c2440_p), + .mux_parent_names = dclk_s3c2410_p, + .mux_num_parents = ARRAY_SIZE(dclk_s3c2410_p), + }, + [S3C2443] = { + .clkout0_parent_names = clkout0_s3c2443_p, + .clkout0_num_parents = ARRAY_SIZE(clkout0_s3c2443_p), + .clkout1_parent_names = clkout1_s3c2443_p, + .clkout1_num_parents = ARRAY_SIZE(clkout1_s3c2443_p), + .mux_parent_names = dclk_s3c2443_p, + .mux_num_parents = ARRAY_SIZE(dclk_s3c2443_p), + }, +}; + +static struct platform_device_id s3c24xx_dclk_driver_ids[] = { + { + .name = "s3c2410-dclk", + .driver_data = (kernel_ulong_t)&dclk_variants[S3C2410], + }, { + .name = "s3c2412-dclk", + .driver_data = (kernel_ulong_t)&dclk_variants[S3C2412], + }, { + .name = "s3c2440-dclk", + .driver_data = (kernel_ulong_t)&dclk_variants[S3C2440], + }, { + .name = "s3c2443-dclk", + .driver_data = (kernel_ulong_t)&dclk_variants[S3C2443], + }, + { } +}; + +MODULE_DEVICE_TABLE(platform, s3c24xx_dclk_driver_ids); + +static struct platform_driver s3c24xx_dclk_driver = { + .driver = { + .name = "s3c24xx-dclk", + .owner = THIS_MODULE, + .pm = &s3c24xx_dclk_pm_ops, + }, + .probe = s3c24xx_dclk_probe, + .remove = s3c24xx_dclk_remove, + .id_table = s3c24xx_dclk_driver_ids, +}; +module_platform_driver(s3c24xx_dclk_driver); + +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Heiko Stuebner "); +MODULE_DESCRIPTION("Driver for the S3C24XX external clock outputs"); From a501fd37f77a703a8710af8f6964e0ae269df973 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 6 May 2014 14:58:22 +0200 Subject: [PATCH 41/87] leds: Fix build for LEDS_CLASS=m on versatile I got a build error today, since LEDS_VERSATILE can be built-in while LEDS_CLASS is a module: drivers/built-in.o: In function `versatile_leds_probe': :(.text+0x155020): undefined reference to `led_classdev_register' I suggest we turn this option into 'tristate' so that the dependency tracking works correctly. Signed-off-by: Arnd Bergmann Acked-by: Linus Walleij Signed-off-by: Olof Johansson --- drivers/leds/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index 9adc79406ff3..39e717797cc0 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig @@ -488,7 +488,7 @@ config LEDS_BLINKM through I2C. Say Y to enable support for the BlinkM LED. config LEDS_VERSATILE - bool "LED support for the ARM Versatile and RealView" + tristate "LED support for the ARM Versatile and RealView" depends on ARCH_REALVIEW || ARCH_VERSATILE depends on LEDS_CLASS help From b21be7bcd8871014a5e446886ea7fb9ae9d6e591 Mon Sep 17 00:00:00 2001 From: Tero Kristo Date: Tue, 4 Mar 2014 18:19:01 +0200 Subject: [PATCH 42/87] ARM: OMAP3: CM: remove a few OMAP34XX_CM_REGADDR defines Remove a few OMAP34XX_CM_REGADDR defines and replace these with offset based register accesses instead. Signed-off-by: Tero Kristo Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/cm3xxx.c | 12 ++++++++---- arch/arm/mach-omap2/cm3xxx.h | 5 ++--- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/arch/arm/mach-omap2/cm3xxx.c b/arch/arm/mach-omap2/cm3xxx.c index f6f028867bfe..60c2c9f9438a 100644 --- a/arch/arm/mach-omap2/cm3xxx.c +++ b/arch/arm/mach-omap2/cm3xxx.c @@ -388,7 +388,8 @@ void omap3_cm_save_context(void) omap2_cm_read_mod_reg(OMAP3430_IVA2_MOD, CM_CLKSEL1); cm_context.iva2_cm_clksel2 = omap2_cm_read_mod_reg(OMAP3430_IVA2_MOD, CM_CLKSEL2); - cm_context.cm_sysconfig = __raw_readl(OMAP3430_CM_SYSCONFIG); + cm_context.cm_sysconfig = + omap2_cm_read_mod_reg(OCP_MOD, OMAP3430_CM_SYSCONFIG); cm_context.sgx_cm_clksel = omap2_cm_read_mod_reg(OMAP3430ES2_SGX_MOD, CM_CLKSEL); cm_context.dss_cm_clksel = @@ -418,7 +419,8 @@ void omap3_cm_save_context(void) omap2_cm_read_mod_reg(PLL_MOD, OMAP3430ES2_CM_CLKSEL5); cm_context.pll_cm_clken2 = omap2_cm_read_mod_reg(PLL_MOD, OMAP3430ES2_CM_CLKEN2); - cm_context.cm_polctrl = __raw_readl(OMAP3430_CM_POLCTRL); + cm_context.cm_polctrl = + omap2_cm_read_mod_reg(OCP_MOD, OMAP3430_CM_POLCTRL); cm_context.iva2_cm_fclken = omap2_cm_read_mod_reg(OMAP3430_IVA2_MOD, CM_FCLKEN); cm_context.iva2_cm_clken_pll = @@ -519,7 +521,8 @@ void omap3_cm_restore_context(void) CM_CLKSEL1); omap2_cm_write_mod_reg(cm_context.iva2_cm_clksel2, OMAP3430_IVA2_MOD, CM_CLKSEL2); - __raw_writel(cm_context.cm_sysconfig, OMAP3430_CM_SYSCONFIG); + omap2_cm_write_mod_reg(cm_context.cm_sysconfig, OCP_MOD, + OMAP3430_CM_SYSCONFIG); omap2_cm_write_mod_reg(cm_context.sgx_cm_clksel, OMAP3430ES2_SGX_MOD, CM_CLKSEL); omap2_cm_write_mod_reg(cm_context.dss_cm_clksel, OMAP3430_DSS_MOD, @@ -547,7 +550,8 @@ void omap3_cm_restore_context(void) OMAP3430ES2_CM_CLKSEL5); omap2_cm_write_mod_reg(cm_context.pll_cm_clken2, PLL_MOD, OMAP3430ES2_CM_CLKEN2); - __raw_writel(cm_context.cm_polctrl, OMAP3430_CM_POLCTRL); + omap2_cm_write_mod_reg(cm_context.cm_polctrl, OCP_MOD, + OMAP3430_CM_POLCTRL); omap2_cm_write_mod_reg(cm_context.iva2_cm_fclken, OMAP3430_IVA2_MOD, CM_FCLKEN); omap2_cm_write_mod_reg(cm_context.iva2_cm_clken_pll, OMAP3430_IVA2_MOD, diff --git a/arch/arm/mach-omap2/cm3xxx.h b/arch/arm/mach-omap2/cm3xxx.h index 8224c91b4d7a..7a16b5598127 100644 --- a/arch/arm/mach-omap2/cm3xxx.h +++ b/arch/arm/mach-omap2/cm3xxx.h @@ -29,9 +29,8 @@ * These registers appear once per CM module. */ -#define OMAP3430_CM_REVISION OMAP34XX_CM_REGADDR(OCP_MOD, 0x0000) -#define OMAP3430_CM_SYSCONFIG OMAP34XX_CM_REGADDR(OCP_MOD, 0x0010) -#define OMAP3430_CM_POLCTRL OMAP34XX_CM_REGADDR(OCP_MOD, 0x009c) +#define OMAP3430_CM_SYSCONFIG 0x0010 +#define OMAP3430_CM_POLCTRL 0x009c #define OMAP3_CM_CLKOUT_CTRL_OFFSET 0x0070 #define OMAP3430_CM_CLKOUT_CTRL OMAP_CM_REGADDR(OMAP3430_CCR_MOD, 0x0070) From a2a2568311e2207d0c8874e28f578c0bbe3c63b3 Mon Sep 17 00:00:00 2001 From: Xianglong Du Date: Wed, 7 May 2014 15:08:21 +0800 Subject: [PATCH 43/87] ARM: prima2: rstc: fix some minor checkpatch issues this patch fixes the below minor issues: WARNING: line over 80 characters 39: FILE: arch/arm/mach-prima2/rstc.c:39: + * Writing 1 to this bit resets corresponding block. Writing 0 to this WARNING: line over 80 characters 41: FILE: arch/arm/mach-prima2/rstc.c:41: + * datasheet doesn't require explicit delay between the set and clear WARNING: line over 80 characters 44: FILE: arch/arm/mach-prima2/rstc.c:44: + writel(readl(sirfsoc_rstc_base + (reset_bit / 32) * 4) | (1 << reset_bit), WARNING: msleep < 20ms can sleep for up to 20ms; see Documentation/timers/timers-howto.txt 46: FILE: arch/arm/mach-prima2/rstc.c:46: + msleep(10); WARNING: line over 80 characters 47: FILE: arch/arm/mach-prima2/rstc.c:47: + writel(readl(sirfsoc_rstc_base + (reset_bit / 32) * 4) & ~(1 << reset_bit), WARNING: line over 80 characters 52: FILE: arch/arm/mach-prima2/rstc.c:52: + * Writing 1 to SET register resets corresponding block. Writing 1 to CLEAR WARNING: line over 80 characters 54: FILE: arch/arm/mach-prima2/rstc.c:54: + * datasheet doesn't require explicit delay between the set and clear WARNING: line over 80 characters 57: FILE: arch/arm/mach-prima2/rstc.c:57: + writel(1 << reset_bit, sirfsoc_rstc_base + (reset_bit / 32) * 8); WARNING: msleep < 20ms can sleep for up to 20ms; see Documentation/timers/timers-howto.txt 58: FILE: arch/arm/mach-prima2/rstc.c:58: + msleep(10); WARNING: line over 80 characters 59: FILE: arch/arm/mach-prima2/rstc.c:59: + writel(1 << reset_bit, sirfsoc_rstc_base + (reset_bit / 32) * 8 + 4); total: 0 errors, 10 warnings, 120 lines checked Signed-off-by: Xianglong Du Signed-off-by: Barry Song --- arch/arm/mach-prima2/rstc.c | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/arch/arm/mach-prima2/rstc.c b/arch/arm/mach-prima2/rstc.c index 4887a2a4c698..3dffcb2d714e 100644 --- a/arch/arm/mach-prima2/rstc.c +++ b/arch/arm/mach-prima2/rstc.c @@ -36,27 +36,33 @@ static int sirfsoc_reset_module(struct reset_controller_dev *rcdev, if (of_device_is_compatible(rcdev->of_node, "sirf,prima2-rstc")) { /* - * Writing 1 to this bit resets corresponding block. Writing 0 to this - * bit de-asserts reset signal of the corresponding block. - * datasheet doesn't require explicit delay between the set and clear - * of reset bit. it could be shorter if tests pass. + * Writing 1 to this bit resets corresponding block. + * Writing 0 to this bit de-asserts reset signal of the + * corresponding block. datasheet doesn't require explicit + * delay between the set and clear of reset bit. it could + * be shorter if tests pass. */ - writel(readl(sirfsoc_rstc_base + (reset_bit / 32) * 4) | (1 << reset_bit), + writel(readl(sirfsoc_rstc_base + + (reset_bit / 32) * 4) | (1 << reset_bit), sirfsoc_rstc_base + (reset_bit / 32) * 4); - msleep(10); - writel(readl(sirfsoc_rstc_base + (reset_bit / 32) * 4) & ~(1 << reset_bit), + msleep(20); + writel(readl(sirfsoc_rstc_base + + (reset_bit / 32) * 4) & ~(1 << reset_bit), sirfsoc_rstc_base + (reset_bit / 32) * 4); } else { /* * For MARCO and POLO - * Writing 1 to SET register resets corresponding block. Writing 1 to CLEAR - * register de-asserts reset signal of the corresponding block. - * datasheet doesn't require explicit delay between the set and clear - * of reset bit. it could be shorter if tests pass. + * Writing 1 to SET register resets corresponding block. + * Writing 1 to CLEAR register de-asserts reset signal of the + * corresponding block. + * datasheet doesn't require explicit delay between the set and + * clear of reset bit. it could be shorter if tests pass. */ - writel(1 << reset_bit, sirfsoc_rstc_base + (reset_bit / 32) * 8); - msleep(10); - writel(1 << reset_bit, sirfsoc_rstc_base + (reset_bit / 32) * 8 + 4); + writel(1 << reset_bit, + sirfsoc_rstc_base + (reset_bit / 32) * 8); + msleep(20); + writel(1 << reset_bit, + sirfsoc_rstc_base + (reset_bit / 32) * 8 + 4); } mutex_unlock(&rstc_lock); From 4c1ad70921caa9831b4926e83481c9f825016dd6 Mon Sep 17 00:00:00 2001 From: Bin Shi Date: Tue, 6 May 2014 22:42:29 +0800 Subject: [PATCH 44/87] clocksource: prima2: fix some minor checkpatch issues Fix the "line over 80 characters". users of the codes - key customers really care about that. WARNING: line over 80 characters 64: FILE: timer-prima2.c:64: + WARN_ON(!(readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_STATUS) & BIT(0))); WARNING: line over 80 characters 80: FILE: timer-prima2.c:80: + writel_relaxed(SIRFSOC_TIMER_LATCH_BIT, sirfsoc_timer_base + SIRFSOC_TIMER_LATCH); WARNING: line over 80 characters 82: FILE: timer-prima2.c:82: + cycles = (cycles << 32) | readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_LATCHED_LO); WARNING: line over 80 characters 92: FILE: timer-prima2.c:92: + writel_relaxed(SIRFSOC_TIMER_LATCH_BIT, sirfsoc_timer_base + SIRFSOC_TIMER_LATCH); WARNING: line over 80 characters 96: FILE: timer-prima2.c:96: + writel_relaxed(SIRFSOC_TIMER_LATCH_BIT, sirfsoc_timer_base + SIRFSOC_TIMER_LATCH); WARNING: line over 80 characters 111: FILE: timer-prima2.c:111: + writel_relaxed(val | BIT(0), sirfsoc_timer_base + SIRFSOC_TIMER_INT_EN); WARNING: line over 80 characters 114: FILE: timer-prima2.c:114: + writel_relaxed(val & ~BIT(0), sirfsoc_timer_base + SIRFSOC_TIMER_INT_EN); WARNING: line over 80 characters 126: FILE: timer-prima2.c:126: + writel_relaxed(SIRFSOC_TIMER_LATCH_BIT, sirfsoc_timer_base + SIRFSOC_TIMER_LATCH); WARNING: line over 80 characters 129: FILE: timer-prima2.c:129: + sirfsoc_timer_reg_val[i] = readl_relaxed(sirfsoc_timer_base + sirfsoc_timer_reg_list[i]); WARNING: line over 80 characters 137: FILE: timer-prima2.c:137: + writel_relaxed(sirfsoc_timer_reg_val[i], sirfsoc_timer_base + sirfsoc_timer_reg_list[i]); WARNING: line over 80 characters 139: FILE: timer-prima2.c:139: + writel_relaxed(sirfsoc_timer_reg_val[SIRFSOC_TIMER_REG_CNT - 2], sirfsoc_timer_base + SIRFSOC_TIMER_COUNTER_LO); WARNING: line over 80 characters 140: FILE: timer-prima2.c:140: + writel_relaxed(sirfsoc_timer_reg_val[SIRFSOC_TIMER_REG_CNT - 1], sirfsoc_timer_base + SIRFSOC_TIMER_COUNTER_HI); WARNING: line over 80 characters 216: FILE: timer-prima2.c:216: +CLOCKSOURCE_OF_DECLARE(sirfsoc_prima2_timer, "sirf,prima2-tick", sirfsoc_prima2_timer_init); total: 0 errors, 13 warnings, 216 lines checked timer-prima2.c has style problems, please review. If any of these errors are false positives, please report them to the maintainer, see CHECKPATCH in MAINTAINERS. Signed-off-by: Bin Shi Signed-off-by: Barry Song --- drivers/clocksource/timer-prima2.c | 42 ++++++++++++++++++++---------- 1 file changed, 28 insertions(+), 14 deletions(-) diff --git a/drivers/clocksource/timer-prima2.c b/drivers/clocksource/timer-prima2.c index 1a6b2d6356d6..84fdb15eae79 100644 --- a/drivers/clocksource/timer-prima2.c +++ b/drivers/clocksource/timer-prima2.c @@ -61,7 +61,8 @@ static irqreturn_t sirfsoc_timer_interrupt(int irq, void *dev_id) { struct clock_event_device *ce = dev_id; - WARN_ON(!(readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_STATUS) & BIT(0))); + WARN_ON(!(readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_STATUS) & + BIT(0))); /* clear timer0 interrupt */ writel_relaxed(BIT(0), sirfsoc_timer_base + SIRFSOC_TIMER_STATUS); @@ -77,9 +78,11 @@ static cycle_t sirfsoc_timer_read(struct clocksource *cs) u64 cycles; /* latch the 64-bit timer counter */ - writel_relaxed(SIRFSOC_TIMER_LATCH_BIT, sirfsoc_timer_base + SIRFSOC_TIMER_LATCH); + writel_relaxed(SIRFSOC_TIMER_LATCH_BIT, + sirfsoc_timer_base + SIRFSOC_TIMER_LATCH); cycles = readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_LATCHED_HI); - cycles = (cycles << 32) | readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_LATCHED_LO); + cycles = (cycles << 32) | + readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_LATCHED_LO); return cycles; } @@ -89,11 +92,13 @@ static int sirfsoc_timer_set_next_event(unsigned long delta, { unsigned long now, next; - writel_relaxed(SIRFSOC_TIMER_LATCH_BIT, sirfsoc_timer_base + SIRFSOC_TIMER_LATCH); + writel_relaxed(SIRFSOC_TIMER_LATCH_BIT, + sirfsoc_timer_base + SIRFSOC_TIMER_LATCH); now = readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_LATCHED_LO); next = now + delta; writel_relaxed(next, sirfsoc_timer_base + SIRFSOC_TIMER_MATCH_0); - writel_relaxed(SIRFSOC_TIMER_LATCH_BIT, sirfsoc_timer_base + SIRFSOC_TIMER_LATCH); + writel_relaxed(SIRFSOC_TIMER_LATCH_BIT, + sirfsoc_timer_base + SIRFSOC_TIMER_LATCH); now = readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_LATCHED_LO); return next - now > delta ? -ETIME : 0; @@ -108,10 +113,12 @@ static void sirfsoc_timer_set_mode(enum clock_event_mode mode, WARN_ON(1); break; case CLOCK_EVT_MODE_ONESHOT: - writel_relaxed(val | BIT(0), sirfsoc_timer_base + SIRFSOC_TIMER_INT_EN); + writel_relaxed(val | BIT(0), + sirfsoc_timer_base + SIRFSOC_TIMER_INT_EN); break; case CLOCK_EVT_MODE_SHUTDOWN: - writel_relaxed(val & ~BIT(0), sirfsoc_timer_base + SIRFSOC_TIMER_INT_EN); + writel_relaxed(val & ~BIT(0), + sirfsoc_timer_base + SIRFSOC_TIMER_INT_EN); break; case CLOCK_EVT_MODE_UNUSED: case CLOCK_EVT_MODE_RESUME: @@ -123,10 +130,13 @@ static void sirfsoc_clocksource_suspend(struct clocksource *cs) { int i; - writel_relaxed(SIRFSOC_TIMER_LATCH_BIT, sirfsoc_timer_base + SIRFSOC_TIMER_LATCH); + writel_relaxed(SIRFSOC_TIMER_LATCH_BIT, + sirfsoc_timer_base + SIRFSOC_TIMER_LATCH); for (i = 0; i < SIRFSOC_TIMER_REG_CNT; i++) - sirfsoc_timer_reg_val[i] = readl_relaxed(sirfsoc_timer_base + sirfsoc_timer_reg_list[i]); + sirfsoc_timer_reg_val[i] = + readl_relaxed(sirfsoc_timer_base + + sirfsoc_timer_reg_list[i]); } static void sirfsoc_clocksource_resume(struct clocksource *cs) @@ -134,10 +144,13 @@ 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[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_COUNTER_LO); - writel_relaxed(sirfsoc_timer_reg_val[SIRFSOC_TIMER_REG_CNT - 1], sirfsoc_timer_base + SIRFSOC_TIMER_COUNTER_HI); + writel_relaxed(sirfsoc_timer_reg_val[SIRFSOC_TIMER_REG_CNT - 2], + sirfsoc_timer_base + SIRFSOC_TIMER_COUNTER_LO); + writel_relaxed(sirfsoc_timer_reg_val[SIRFSOC_TIMER_REG_CNT - 1], + sirfsoc_timer_base + SIRFSOC_TIMER_COUNTER_HI); } static struct clock_event_device sirfsoc_clockevent = { @@ -202,7 +215,7 @@ static void __init sirfsoc_prima2_timer_init(struct device_node *np) sirfsoc_timer_irq.irq = irq_of_parse_and_map(np, 0); writel_relaxed(rate / PRIMA2_CLOCK_FREQ / 2 - 1, - sirfsoc_timer_base + SIRFSOC_TIMER_DIV); + sirfsoc_timer_base + SIRFSOC_TIMER_DIV); writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_COUNTER_LO); writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_COUNTER_HI); writel_relaxed(BIT(0), sirfsoc_timer_base + SIRFSOC_TIMER_STATUS); @@ -216,4 +229,5 @@ static void __init sirfsoc_prima2_timer_init(struct device_node *np) sirfsoc_clockevent_init(); } -CLOCKSOURCE_OF_DECLARE(sirfsoc_prima2_timer, "sirf,prima2-tick", sirfsoc_prima2_timer_init); +CLOCKSOURCE_OF_DECLARE(sirfsoc_prima2_timer, + "sirf,prima2-tick", sirfsoc_prima2_timer_init); From 7caf6852018a7550a2451972522688caef350549 Mon Sep 17 00:00:00 2001 From: Bin Shi Date: Tue, 6 May 2014 22:58:36 +0800 Subject: [PATCH 45/87] irqchip: sirf: fix one minor checkpatch issue fix "line line over 80 characters" for the below: static int __init sirfsoc_irq_init(struct device_node *np, struct device_node *parent) the users of the codes - key customers really care about that. Signed-off-by: Bin Shi Signed-off-by: Barry Song --- drivers/irqchip/irq-sirfsoc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/irqchip/irq-sirfsoc.c b/drivers/irqchip/irq-sirfsoc.c index 581eefe331ae..5e54f6d71e77 100644 --- a/drivers/irqchip/irq-sirfsoc.c +++ b/drivers/irqchip/irq-sirfsoc.c @@ -58,7 +58,8 @@ static void __exception_irq_entry sirfsoc_handle_irq(struct pt_regs *regs) handle_IRQ(irqnr, regs); } -static int __init sirfsoc_irq_init(struct device_node *np, struct device_node *parent) +static int __init sirfsoc_irq_init(struct device_node *np, + struct device_node *parent) { void __iomem *base = of_iomap(np, 0); if (!base) From c7cff54d5926e3f419c23eff2ebaf6f5e12da05d Mon Sep 17 00:00:00 2001 From: Zhiwu Song Date: Mon, 5 May 2014 19:30:04 +0800 Subject: [PATCH 46/87] clocksource:sirf: remove the hardcode for the clk of timers Nobody want to know the connection between io clk and timer clk, so exposing this information to timer module is not reasonable. this patch moves to define the timers' clk in dt. Signed-off-by: Zhiwu Song Signed-off-by: Barry Song --- arch/arm/boot/dts/atlas6.dtsi | 1 + arch/arm/boot/dts/prima2.dtsi | 1 + drivers/clocksource/timer-marco.c | 8 +++----- drivers/clocksource/timer-prima2.c | 5 +---- 4 files changed, 6 insertions(+), 9 deletions(-) diff --git a/arch/arm/boot/dts/atlas6.dtsi b/arch/arm/boot/dts/atlas6.dtsi index 9d72674049d6..317bc590a4d0 100644 --- a/arch/arm/boot/dts/atlas6.dtsi +++ b/arch/arm/boot/dts/atlas6.dtsi @@ -195,6 +195,7 @@ compatible = "sirf,prima2-tick"; reg = <0xb0020000 0x1000>; interrupts = <0>; + clocks = <&clks 11>; }; nand@b0030000 { diff --git a/arch/arm/boot/dts/prima2.dtsi b/arch/arm/boot/dts/prima2.dtsi index 1e82571d6823..7e7d8843abaf 100644 --- a/arch/arm/boot/dts/prima2.dtsi +++ b/arch/arm/boot/dts/prima2.dtsi @@ -201,6 +201,7 @@ compatible = "sirf,prima2-tick"; reg = <0xb0020000 0x1000>; interrupts = <0>; + clocks = <&clks 11>; }; nand@b0030000 { diff --git a/drivers/clocksource/timer-marco.c b/drivers/clocksource/timer-marco.c index b52e1c078b99..571d10974139 100644 --- a/drivers/clocksource/timer-marco.c +++ b/drivers/clocksource/timer-marco.c @@ -252,15 +252,13 @@ static void __init sirfsoc_clockevent_init(void) } /* initialize the kernel jiffy timer source */ -static void __init sirfsoc_marco_timer_init(void) +static void __init sirfsoc_marco_timer_init(struct device_node *np) { unsigned long rate; u32 timer_div; struct clk *clk; - /* timer's input clock is io clock */ - clk = clk_get_sys("io", NULL); - + clk = of_clk_get(np, 0); BUG_ON(IS_ERR(clk)); rate = clk_get_rate(clk); @@ -303,6 +301,6 @@ static void __init sirfsoc_of_timer_init(struct device_node *np) if (!sirfsoc_timer1_irq.irq) panic("No irq passed for timer1 via DT\n"); - sirfsoc_marco_timer_init(); + sirfsoc_marco_timer_init(np); } CLOCKSOURCE_OF_DECLARE(sirfsoc_marco_timer, "sirf,marco-tick", sirfsoc_of_timer_init ); diff --git a/drivers/clocksource/timer-prima2.c b/drivers/clocksource/timer-prima2.c index 84fdb15eae79..a722aac7ac02 100644 --- a/drivers/clocksource/timer-prima2.c +++ b/drivers/clocksource/timer-prima2.c @@ -198,11 +198,8 @@ static void __init sirfsoc_prima2_timer_init(struct device_node *np) unsigned long rate; struct clk *clk; - /* timer's input clock is io clock */ - clk = clk_get_sys("io", NULL); - + clk = of_clk_get(np, 0); BUG_ON(IS_ERR(clk)); - rate = clk_get_rate(clk); BUG_ON(rate < PRIMA2_CLOCK_FREQ); From 51cb128987d96538fdea4ce3704e79257afad4a5 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Fri, 9 May 2014 05:48:57 +0900 Subject: [PATCH 47/87] ARM: S3C24XX: enable usage of common dclk if common clock framework is enabled Add platform device and select the correct implementation automatically depending on wether the old samsung_clock or the common clock framework is enabled. This is only done for machines already using the old dclk implementation, as everybody else should move to use dt anyway. The machine-specific settings for the external clocks will have to be set by somebody with knowledge about the specific hardware. Signed-off-by: Heiko Stuebner Reviewed-by: Tomasz Figa [pebolle@tiscali.nl: pointed out typo and fixed] Signed-off-by: Kukjin Kim --- arch/arm/mach-s3c24xx/Kconfig | 22 +++++++++++++++++----- arch/arm/mach-s3c24xx/common.c | 14 ++++++++++++++ arch/arm/mach-s3c24xx/common.h | 2 ++ arch/arm/mach-s3c24xx/mach-anubis.c | 5 +++++ arch/arm/mach-s3c24xx/mach-bast.c | 5 +++++ arch/arm/mach-s3c24xx/mach-osiris.c | 5 +++++ arch/arm/mach-s3c24xx/mach-rx1950.c | 5 +++++ arch/arm/mach-s3c24xx/mach-vr1000.c | 5 +++++ arch/arm/mach-s3c24xx/s3c244x.c | 2 ++ 9 files changed, 60 insertions(+), 5 deletions(-) diff --git a/arch/arm/mach-s3c24xx/Kconfig b/arch/arm/mach-s3c24xx/Kconfig index fbafb9a1975b..c9378806b9e8 100644 --- a/arch/arm/mach-s3c24xx/Kconfig +++ b/arch/arm/mach-s3c24xx/Kconfig @@ -18,6 +18,13 @@ config PLAT_S3C24XX help Base platform code for any Samsung S3C24XX device +config S3C2410_COMMON_DCLK + bool + select REGMAP_MMIO + help + Temporary symbol to build the dclk driver based on the common clock + framework. + menu "SAMSUNG S3C24XX SoCs Support" comment "S3C24XX SoCs" @@ -263,8 +270,9 @@ config ARCH_BAST bool "Simtec Electronics BAST (EB2410ITX)" select ISA select MACH_BAST_IDE + select S3C2410_COMMON_DCLK if COMMON_CLK select S3C2410_IOTIMING if ARM_S3C2410_CPUFREQ - select S3C24XX_DCLK + select S3C24XX_DCLK if SAMSUNG_CLOCK select S3C24XX_SIMTEC_NOR select S3C24XX_SIMTEC_PM if PM select S3C24XX_SIMTEC_USB @@ -345,7 +353,8 @@ config MACH_TCT_HAMMER config MACH_VR1000 bool "Thorcom VR1000" select MACH_BAST_IDE - select S3C24XX_DCLK + select S3C2410_COMMON_DCLK if COMMON_CLK + select S3C24XX_DCLK if SAMSUNG_CLOCK select S3C24XX_SIMTEC_NOR select S3C24XX_SIMTEC_PM if PM select S3C24XX_SIMTEC_USB @@ -529,8 +538,9 @@ comment "S3C2440 Boards" config MACH_ANUBIS bool "Simtec Electronics ANUBIS" select HAVE_PATA_PLATFORM + select S3C2410_COMMON_DCLK if COMMON_CLK select S3C2440_XTAL_12000000 - select S3C24XX_DCLK + select S3C24XX_DCLK if SAMSUNG_CLOCK select S3C24XX_SIMTEC_PM if PM select S3C_DEV_USB_HOST help @@ -568,9 +578,10 @@ config MACH_NEXCODER_2440 config MACH_OSIRIS bool "Simtec IM2440D20 (OSIRIS) module" + select S3C2410_COMMON_DCLK if COMMON_CLK select S3C2410_IOTIMING if ARM_S3C2440_CPUFREQ select S3C2440_XTAL_12000000 - select S3C24XX_DCLK + select S3C24XX_DCLK if SAMSUNG_CLOCK select S3C24XX_SIMTEC_PM if PM select S3C_DEV_NAND select S3C_DEV_USB_HOST @@ -639,9 +650,10 @@ config MACH_RX1950 bool "HP iPAQ rx1950" select I2C select PM_H1940 if PM + select S3C2410_COMMON_DCLK if COMMON_CLK select S3C2410_IOTIMING if ARM_S3C2440_CPUFREQ select S3C2440_XTAL_16934400 - select S3C24XX_DCLK + select S3C24XX_DCLK if SAMSUNG_CLOCK select S3C24XX_PWM select S3C_DEV_NAND help diff --git a/arch/arm/mach-s3c24xx/common.c b/arch/arm/mach-s3c24xx/common.c index ad5b76bf4d51..7cc6d944c820 100644 --- a/arch/arm/mach-s3c24xx/common.c +++ b/arch/arm/mach-s3c24xx/common.c @@ -553,3 +553,17 @@ void __init s3c2443_init_clocks(int xtal) s3c2443_common_clk_init(NULL, xtal, 1, S3C24XX_VA_CLKPWR); } #endif + +#if defined(CONFIG_CPU_S3C2410) || defined(CONFIG_CPU_S3C2440) || \ + defined(CONFIG_CPU_S3C2442) +static struct resource s3c2410_dclk_resource[] = { + [0] = DEFINE_RES_MEM(0x56000084, 0x4), +}; + +struct platform_device s3c2410_device_dclk = { + .name = "s3c2410-dclk", + .id = 0, + .num_resources = ARRAY_SIZE(s3c2410_dclk_resource), + .resource = s3c2410_dclk_resource, +}; +#endif diff --git a/arch/arm/mach-s3c24xx/common.h b/arch/arm/mach-s3c24xx/common.h index 3fade6d796f9..50504c77fa00 100644 --- a/arch/arm/mach-s3c24xx/common.h +++ b/arch/arm/mach-s3c24xx/common.h @@ -114,6 +114,8 @@ extern struct platform_device s3c2412_device_dma; extern struct platform_device s3c2440_device_dma; extern struct platform_device s3c2443_device_dma; +extern struct platform_device s3c2410_device_dclk; + #ifdef CONFIG_S3C2412_COMMON_CLK void __init s3c2412_common_clk_init(struct device_node *np, unsigned long xti_f, unsigned long ext_f, void __iomem *reg_base); diff --git a/arch/arm/mach-s3c24xx/mach-anubis.c b/arch/arm/mach-s3c24xx/mach-anubis.c index 81a270af2336..f81944f3217d 100644 --- a/arch/arm/mach-s3c24xx/mach-anubis.c +++ b/arch/arm/mach-s3c24xx/mach-anubis.c @@ -352,6 +352,7 @@ static struct platform_device anubis_device_sm501 = { /* Standard Anubis devices */ static struct platform_device *anubis_devices[] __initdata = { + &s3c2410_device_dclk, &s3c_device_ohci, &s3c_device_wdt, &s3c_device_adc, @@ -364,6 +365,7 @@ static struct platform_device *anubis_devices[] __initdata = { &anubis_device_sm501, }; +#ifdef CONFIG_SAMSUNG_CLOCK static struct clk *anubis_clocks[] __initdata = { &s3c24xx_dclk0, &s3c24xx_dclk1, @@ -371,6 +373,7 @@ static struct clk *anubis_clocks[] __initdata = { &s3c24xx_clkout1, &s3c24xx_uclk, }; +#endif /* I2C devices. */ @@ -394,6 +397,7 @@ static struct s3c24xx_audio_simtec_pdata __initdata anubis_audio = { static void __init anubis_map_io(void) { +#ifdef CONFIG_SAMSUNG_CLOCK /* initialise the clocks */ s3c24xx_dclk0.parent = &clk_upll; @@ -408,6 +412,7 @@ static void __init anubis_map_io(void) s3c24xx_uclk.parent = &s3c24xx_clkout1; s3c24xx_register_clocks(anubis_clocks, ARRAY_SIZE(anubis_clocks)); +#endif s3c24xx_init_io(anubis_iodesc, ARRAY_SIZE(anubis_iodesc)); s3c24xx_init_clocks(0); diff --git a/arch/arm/mach-s3c24xx/mach-bast.c b/arch/arm/mach-s3c24xx/mach-bast.c index e371ff53a408..dcdc4a575690 100644 --- a/arch/arm/mach-s3c24xx/mach-bast.c +++ b/arch/arm/mach-s3c24xx/mach-bast.c @@ -523,6 +523,7 @@ static struct s3c_hwmon_pdata bast_hwmon_info = { // cat /sys/devices/platform/s3c24xx-adc/s3c-hwmon/in_0 static struct platform_device *bast_devices[] __initdata = { + &s3c2410_device_dclk, &s3c_device_ohci, &s3c_device_lcd, &s3c_device_wdt, @@ -537,6 +538,7 @@ static struct platform_device *bast_devices[] __initdata = { &bast_sio, }; +#ifdef CONFIG_SAMSUNG_CLK static struct clk *bast_clocks[] __initdata = { &s3c24xx_dclk0, &s3c24xx_dclk1, @@ -544,6 +546,7 @@ static struct clk *bast_clocks[] __initdata = { &s3c24xx_clkout1, &s3c24xx_uclk, }; +#endif static struct s3c_cpufreq_board __initdata bast_cpufreq = { .refresh = 7800, /* 7.8usec */ @@ -558,6 +561,7 @@ static struct s3c24xx_audio_simtec_pdata __initdata bast_audio = { static void __init bast_map_io(void) { +#ifdef CONFIG_SAMSUNG_CLOCK /* initialise the clocks */ s3c24xx_dclk0.parent = &clk_upll; @@ -572,6 +576,7 @@ static void __init bast_map_io(void) s3c24xx_uclk.parent = &s3c24xx_clkout1; s3c24xx_register_clocks(bast_clocks, ARRAY_SIZE(bast_clocks)); +#endif s3c_hwmon_set_platdata(&bast_hwmon_info); diff --git a/arch/arm/mach-s3c24xx/mach-osiris.c b/arch/arm/mach-s3c24xx/mach-osiris.c index a4ae4bb3666d..487be02e4f2c 100644 --- a/arch/arm/mach-s3c24xx/mach-osiris.c +++ b/arch/arm/mach-s3c24xx/mach-osiris.c @@ -344,12 +344,14 @@ static struct i2c_board_info osiris_i2c_devs[] __initdata = { /* Standard Osiris devices */ static struct platform_device *osiris_devices[] __initdata = { + &s3c2410_device_dclk, &s3c_device_i2c0, &s3c_device_wdt, &s3c_device_nand, &osiris_pcmcia, }; +#ifdef CONFIG_SAMSUNG_CLOCK static struct clk *osiris_clocks[] __initdata = { &s3c24xx_dclk0, &s3c24xx_dclk1, @@ -357,6 +359,7 @@ static struct clk *osiris_clocks[] __initdata = { &s3c24xx_clkout1, &s3c24xx_uclk, }; +#endif static struct s3c_cpufreq_board __initdata osiris_cpufreq = { .refresh = 7800, /* refresh period is 7.8usec */ @@ -368,6 +371,7 @@ static void __init osiris_map_io(void) { unsigned long flags; +#ifdef CONFIG_SAMSUNG_CLOCK /* initialise the clocks */ s3c24xx_dclk0.parent = &clk_upll; @@ -382,6 +386,7 @@ static void __init osiris_map_io(void) s3c24xx_uclk.parent = &s3c24xx_clkout1; s3c24xx_register_clocks(osiris_clocks, ARRAY_SIZE(osiris_clocks)); +#endif s3c24xx_init_io(osiris_iodesc, ARRAY_SIZE(osiris_iodesc)); s3c24xx_init_clocks(0); diff --git a/arch/arm/mach-s3c24xx/mach-rx1950.c b/arch/arm/mach-s3c24xx/mach-rx1950.c index afb784e934c8..219454c93db4 100644 --- a/arch/arm/mach-s3c24xx/mach-rx1950.c +++ b/arch/arm/mach-s3c24xx/mach-rx1950.c @@ -710,6 +710,7 @@ static struct i2c_board_info rx1950_i2c_devices[] = { }; static struct platform_device *rx1950_devices[] __initdata = { + &s3c2410_device_dclk, &s3c_device_lcd, &s3c_device_wdt, &s3c_device_i2c0, @@ -728,17 +729,21 @@ static struct platform_device *rx1950_devices[] __initdata = { &rx1950_leds, }; +#ifdef CONFIG_SAMSUNG_CLOCK static struct clk *rx1950_clocks[] __initdata = { &s3c24xx_clkout0, &s3c24xx_clkout1, }; +#endif static void __init rx1950_map_io(void) { +#ifdef CONFIG_SAMSUNG_CLOCK s3c24xx_clkout0.parent = &clk_h; s3c24xx_clkout1.parent = &clk_f; s3c24xx_register_clocks(rx1950_clocks, ARRAY_SIZE(rx1950_clocks)); +#endif s3c24xx_init_io(rx1950_iodesc, ARRAY_SIZE(rx1950_iodesc)); s3c24xx_init_clocks(16934000); diff --git a/arch/arm/mach-s3c24xx/mach-vr1000.c b/arch/arm/mach-s3c24xx/mach-vr1000.c index 1cc5b1bd51cd..bedaeefdc9f0 100644 --- a/arch/arm/mach-s3c24xx/mach-vr1000.c +++ b/arch/arm/mach-s3c24xx/mach-vr1000.c @@ -286,6 +286,7 @@ static struct i2c_board_info vr1000_i2c_devs[] __initdata = { /* devices for this board */ static struct platform_device *vr1000_devices[] __initdata = { + &s3c2410_device_dclk, &s3c_device_ohci, &s3c_device_lcd, &s3c_device_wdt, @@ -299,6 +300,7 @@ static struct platform_device *vr1000_devices[] __initdata = { &vr1000_led3, }; +#ifdef CONFIG_SAMSUNG_CLOCK static struct clk *vr1000_clocks[] __initdata = { &s3c24xx_dclk0, &s3c24xx_dclk1, @@ -306,6 +308,7 @@ static struct clk *vr1000_clocks[] __initdata = { &s3c24xx_clkout1, &s3c24xx_uclk, }; +#endif static void vr1000_power_off(void) { @@ -314,6 +317,7 @@ static void vr1000_power_off(void) static void __init vr1000_map_io(void) { +#if CONFIG_SAMSUNG_CLOCK /* initialise clock sources */ s3c24xx_dclk0.parent = &clk_upll; @@ -328,6 +332,7 @@ static void __init vr1000_map_io(void) s3c24xx_uclk.parent = &s3c24xx_clkout1; s3c24xx_register_clocks(vr1000_clocks, ARRAY_SIZE(vr1000_clocks)); +#endif pm_power_off = vr1000_power_off; diff --git a/arch/arm/mach-s3c24xx/s3c244x.c b/arch/arm/mach-s3c24xx/s3c244x.c index fe30ebb234d2..76b691bf724e 100644 --- a/arch/arm/mach-s3c24xx/s3c244x.c +++ b/arch/arm/mach-s3c24xx/s3c244x.c @@ -46,6 +46,7 @@ #include #include +#include "common.h" #include "regs-dsc.h" static struct map_desc s3c244x_iodesc[] __initdata = { @@ -74,6 +75,7 @@ void __init s3c244x_map_io(void) s3c_nand_setname("s3c2440-nand"); s3c_device_ts.name = "s3c2440-ts"; s3c_device_usbgadget.name = "s3c2440-usbgadget"; + s3c2410_device_dclk.name = "s3c2440-dclk"; } void __init_or_cpufreq s3c244x_setup_clocks(void) From f11cadd58280e3aed7f16eb648d50a8faf4ebb1a Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Fri, 9 May 2014 05:49:05 +0900 Subject: [PATCH 48/87] dt-bindings: add documentation for s3c2410 clock controller Describe the clock controller of s3c2410, s3c2440 and s3c2442. Signed-off-by: Heiko Stuebner Acked-by: Tomasz Figa Signed-off-by: Kukjin Kim --- .../bindings/clock/samsung,s3c2410-clock.txt | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/samsung,s3c2410-clock.txt diff --git a/Documentation/devicetree/bindings/clock/samsung,s3c2410-clock.txt b/Documentation/devicetree/bindings/clock/samsung,s3c2410-clock.txt new file mode 100644 index 000000000000..0b64ad8dadf6 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/samsung,s3c2410-clock.txt @@ -0,0 +1,50 @@ +* Samsung S3C2410 Clock Controller + +The S3C2410 clock controller generates and supplies clock to various controllers +within the SoC. The clock binding described here is applicable to the s3c2410, +s3c2440 and s3c2442 SoCs in the s3c24x family. + +Required Properties: + +- compatible: should be one of the following. + - "samsung,s3c2410-clock" - controller compatible with S3C2410 SoC. + - "samsung,s3c2440-clock" - controller compatible with S3C2440 SoC. + - "samsung,s3c2442-clock" - controller compatible with S3C2442 SoC. +- reg: physical base address of the controller and length of memory mapped + region. +- #clock-cells: should be 1. + +Each clock is assigned an identifier and client nodes can use this identifier +to specify the clock which they consume. Some of the clocks are available only +on a particular SoC. + +All available clocks are defined as preprocessor macros in +dt-bindings/clock/samsung,s3c2410-clock.h header and can be used in device +tree sources. + +External clocks: + +The xti clock used as input for the plls is generated outside the SoC. It is +expected that is are defined using standard clock bindings with a +clock-output-names value of "xti". + +Example: Clock controller node: + + clocks: clock-controller@4c000000 { + compatible = "samsung,s3c2410-clock"; + reg = <0x4c000000 0x20>; + #clock-cells = <1>; + }; + +Example: UART controller node that consumes the clock generated by the clock + controller (refer to the standard clock bindings for information about + "clocks" and "clock-names" properties): + + serial@50004000 { + compatible = "samsung,s3c2440-uart"; + reg = <0x50004000 0x4000>; + interrupts = <1 23 3 4>, <1 23 4 4>; + clock-names = "uart", "clk_uart_baud2"; + clocks = <&clocks PCLK_UART0>, <&clocks PCLK_UART0>; + status = "disabled"; + }; From 3f7c01ade226e7006d76e42f8c9b99ada7085312 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Fri, 9 May 2014 05:49:10 +0900 Subject: [PATCH 49/87] clk: samsung: add clock controller driver for s3c2410, s3c2440 and s3c2442 This driver can handle the clock controllers of the socs mentioned above, as they share a common clock tree with only small differences. The clock structure is built according to the manuals of the included SoCs and might include changes in comparison to the previous clock structure. As pll-rate-tables only the 12mhz variants are currently included. The original code was wrongly checking for 169mhz xti values [a 0 to much at the end], so the original 16mhz pll table would have never been included and its values are so obscure that I have no possibility to at least check their sane-ness. When using the formula from the manual the resulting frequency is near the table value but still slightly off. Signed-off-by: Heiko Stuebner Acked-by: Mike Turquette Signed-off-by: Kukjin Kim --- drivers/clk/samsung/Makefile | 1 + drivers/clk/samsung/clk-s3c2410.c | 477 ++++++++++++++++++++++++++++ include/dt-bindings/clock/s3c2410.h | 62 ++++ 3 files changed, 540 insertions(+) create mode 100644 drivers/clk/samsung/clk-s3c2410.c create mode 100644 include/dt-bindings/clock/s3c2410.h diff --git a/drivers/clk/samsung/Makefile b/drivers/clk/samsung/Makefile index 9892de4978e3..2cb62f87e068 100644 --- a/drivers/clk/samsung/Makefile +++ b/drivers/clk/samsung/Makefile @@ -8,6 +8,7 @@ obj-$(CONFIG_SOC_EXYNOS5250) += clk-exynos5250.o obj-$(CONFIG_SOC_EXYNOS5420) += clk-exynos5420.o obj-$(CONFIG_SOC_EXYNOS5440) += clk-exynos5440.o obj-$(CONFIG_ARCH_EXYNOS) += clk-exynos-audss.o +obj-$(CONFIG_S3C2410_COMMON_CLK)+= clk-s3c2410.o obj-$(CONFIG_S3C2410_COMMON_DCLK)+= clk-s3c2410-dclk.o obj-$(CONFIG_S3C2412_COMMON_CLK)+= clk-s3c2412.o obj-$(CONFIG_S3C2443_COMMON_CLK)+= clk-s3c2443.o diff --git a/drivers/clk/samsung/clk-s3c2410.c b/drivers/clk/samsung/clk-s3c2410.c new file mode 100644 index 000000000000..7b4182186a30 --- /dev/null +++ b/drivers/clk/samsung/clk-s3c2410.c @@ -0,0 +1,477 @@ +/* + * Copyright (c) 2013 Heiko Stuebner + * + * 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. + * + * Common Clock Framework support for S3C2410 and following SoCs. + */ + +#include +#include +#include +#include +#include +#include + +#include + +#include "clk.h" +#include "clk-pll.h" + +#define LOCKTIME 0x00 +#define MPLLCON 0x04 +#define UPLLCON 0x08 +#define CLKCON 0x0c +#define CLKSLOW 0x10 +#define CLKDIVN 0x14 +#define CAMDIVN 0x18 + +/* the soc types */ +enum supported_socs { + S3C2410, + S3C2440, + S3C2442, +}; + +/* list of PLLs to be registered */ +enum s3c2410_plls { + mpll, upll, +}; + +static void __iomem *reg_base; + +#ifdef CONFIG_PM_SLEEP +static struct samsung_clk_reg_dump *s3c2410_save; + +/* + * list of controller registers to be saved and restored during a + * suspend/resume cycle. + */ +static unsigned long s3c2410_clk_regs[] __initdata = { + LOCKTIME, + MPLLCON, + UPLLCON, + CLKCON, + CLKSLOW, + CLKDIVN, + CAMDIVN, +}; + +static int s3c2410_clk_suspend(void) +{ + samsung_clk_save(reg_base, s3c2410_save, + ARRAY_SIZE(s3c2410_clk_regs)); + + return 0; +} + +static void s3c2410_clk_resume(void) +{ + samsung_clk_restore(reg_base, s3c2410_save, + ARRAY_SIZE(s3c2410_clk_regs)); +} + +static struct syscore_ops s3c2410_clk_syscore_ops = { + .suspend = s3c2410_clk_suspend, + .resume = s3c2410_clk_resume, +}; + +static void s3c2410_clk_sleep_init(void) +{ + s3c2410_save = samsung_clk_alloc_reg_dump(s3c2410_clk_regs, + ARRAY_SIZE(s3c2410_clk_regs)); + if (!s3c2410_save) { + pr_warn("%s: failed to allocate sleep save data, no sleep support!\n", + __func__); + return; + } + + register_syscore_ops(&s3c2410_clk_syscore_ops); + return; +} +#else +static void s3c2410_clk_sleep_init(void) {} +#endif + +PNAME(fclk_p) = { "mpll", "div_slow" }; + +struct samsung_mux_clock s3c2410_common_muxes[] __initdata = { + MUX(FCLK, "fclk", fclk_p, CLKSLOW, 4, 1), +}; + +static struct clk_div_table divslow_d[] = { + { .val = 0, .div = 1 }, + { .val = 1, .div = 2 }, + { .val = 2, .div = 4 }, + { .val = 3, .div = 6 }, + { .val = 4, .div = 8 }, + { .val = 5, .div = 10 }, + { .val = 6, .div = 12 }, + { .val = 7, .div = 14 }, + { /* sentinel */ }, +}; + +struct samsung_div_clock s3c2410_common_dividers[] __initdata = { + DIV_T(0, "div_slow", "xti", CLKSLOW, 0, 3, divslow_d), + DIV(PCLK, "pclk", "hclk", CLKDIVN, 0, 1), +}; + +struct samsung_gate_clock s3c2410_common_gates[] __initdata = { + GATE(PCLK_SPI, "spi", "pclk", CLKCON, 18, 0, 0), + GATE(PCLK_I2S, "i2s", "pclk", CLKCON, 17, 0, 0), + GATE(PCLK_I2C, "i2c", "pclk", CLKCON, 16, 0, 0), + GATE(PCLK_ADC, "adc", "pclk", CLKCON, 15, 0, 0), + GATE(PCLK_RTC, "rtc", "pclk", CLKCON, 14, 0, 0), + GATE(PCLK_GPIO, "gpio", "pclk", CLKCON, 13, CLK_IGNORE_UNUSED, 0), + GATE(PCLK_UART2, "uart2", "pclk", CLKCON, 12, 0, 0), + GATE(PCLK_UART1, "uart1", "pclk", CLKCON, 11, 0, 0), + GATE(PCLK_UART0, "uart0", "pclk", CLKCON, 10, 0, 0), + GATE(PCLK_SDI, "sdi", "pclk", CLKCON, 9, 0, 0), + GATE(PCLK_PWM, "pwm", "pclk", CLKCON, 8, 0, 0), + GATE(HCLK_USBD, "usb-device", "hclk", CLKCON, 7, 0, 0), + GATE(HCLK_USBH, "usb-host", "hclk", CLKCON, 6, 0, 0), + GATE(HCLK_LCD, "lcd", "hclk", CLKCON, 5, 0, 0), + GATE(HCLK_NAND, "nand", "hclk", CLKCON, 4, 0, 0), +}; + +/* should be added _after_ the soc-specific clocks are created */ +struct samsung_clock_alias s3c2410_common_aliases[] __initdata = { + ALIAS(PCLK_I2C, "s3c2410-i2c.0", "i2c"), + ALIAS(PCLK_ADC, NULL, "adc"), + ALIAS(PCLK_RTC, NULL, "rtc"), + ALIAS(PCLK_PWM, NULL, "timers"), + ALIAS(HCLK_LCD, NULL, "lcd"), + ALIAS(HCLK_USBD, NULL, "usb-device"), + ALIAS(HCLK_USBH, NULL, "usb-host"), + ALIAS(UCLK, NULL, "usb-bus-host"), + ALIAS(UCLK, NULL, "usb-bus-gadget"), + ALIAS(ARMCLK, NULL, "armclk"), + ALIAS(UCLK, NULL, "uclk"), + ALIAS(HCLK, NULL, "hclk"), + ALIAS(MPLL, NULL, "mpll"), + ALIAS(FCLK, NULL, "fclk"), +}; + +/* S3C2410 specific clocks */ + +static struct samsung_pll_rate_table pll_s3c2410_12mhz_tbl[] __initdata = { + /* sorted in descending order */ + /* 2410A extras */ + PLL_35XX_RATE(270000000, 127, 1, 1), + PLL_35XX_RATE(268000000, 126, 1, 1), + PLL_35XX_RATE(266000000, 125, 1, 1), + PLL_35XX_RATE(226000000, 105, 1, 1), + PLL_35XX_RATE(210000000, 132, 2, 1), + /* 2410 common */ + PLL_35XX_RATE(203000000, 161, 3, 1), + PLL_35XX_RATE(192000000, 88, 1, 1), + PLL_35XX_RATE(186000000, 85, 1, 1), + PLL_35XX_RATE(180000000, 82, 1, 1), + PLL_35XX_RATE(170000000, 77, 1, 1), + PLL_35XX_RATE(158000000, 71, 1, 1), + PLL_35XX_RATE(152000000, 68, 1, 1), + PLL_35XX_RATE(147000000, 90, 2, 1), + PLL_35XX_RATE(135000000, 82, 2, 1), + PLL_35XX_RATE(124000000, 116, 1, 2), + PLL_35XX_RATE(118000000, 150, 2, 2), + PLL_35XX_RATE(113000000, 105, 1, 2), + PLL_35XX_RATE(101000000, 127, 2, 2), + PLL_35XX_RATE(90000000, 112, 2, 2), + PLL_35XX_RATE(85000000, 105, 2, 2), + PLL_35XX_RATE(79000000, 71, 1, 2), + PLL_35XX_RATE(68000000, 82, 2, 2), + PLL_35XX_RATE(56000000, 142, 2, 3), + PLL_35XX_RATE(48000000, 120, 2, 3), + PLL_35XX_RATE(51000000, 161, 3, 3), + PLL_35XX_RATE(45000000, 82, 1, 3), + PLL_35XX_RATE(34000000, 82, 2, 3), + { /* sentinel */ }, +}; + +static struct samsung_pll_clock s3c2410_plls[] __initdata = { + [mpll] = PLL(pll_s3c2410_mpll, MPLL, "mpll", "xti", + LOCKTIME, MPLLCON, NULL), + [upll] = PLL(pll_s3c2410_upll, UPLL, "upll", "xti", + LOCKTIME, UPLLCON, NULL), +}; + +struct samsung_div_clock s3c2410_dividers[] __initdata = { + DIV(HCLK, "hclk", "mpll", CLKDIVN, 1, 1), +}; + +struct samsung_fixed_factor_clock s3c2410_ffactor[] __initdata = { + /* + * armclk is directly supplied by the fclk, without + * switching possibility like on the s3c244x below. + */ + FFACTOR(ARMCLK, "armclk", "fclk", 1, 1, 0), + + /* uclk is fed from the unmodified upll */ + FFACTOR(UCLK, "uclk", "upll", 1, 1, 0), +}; + +struct samsung_clock_alias s3c2410_aliases[] __initdata = { + ALIAS(PCLK_UART0, "s3c2410-uart.0", "uart"), + ALIAS(PCLK_UART1, "s3c2410-uart.1", "uart"), + ALIAS(PCLK_UART2, "s3c2410-uart.2", "uart"), + ALIAS(PCLK_UART0, "s3c2410-uart.0", "clk_uart_baud0"), + ALIAS(PCLK_UART1, "s3c2410-uart.1", "clk_uart_baud0"), + ALIAS(PCLK_UART2, "s3c2410-uart.2", "clk_uart_baud0"), + ALIAS(UCLK, NULL, "clk_uart_baud1"), +}; + +/* S3C244x specific clocks */ + +static struct samsung_pll_rate_table pll_s3c244x_12mhz_tbl[] __initdata = { + /* sorted in descending order */ + PLL_35XX_RATE(400000000, 0x5c, 1, 1), + PLL_35XX_RATE(390000000, 0x7a, 2, 1), + PLL_35XX_RATE(380000000, 0x57, 1, 1), + PLL_35XX_RATE(370000000, 0xb1, 4, 1), + PLL_35XX_RATE(360000000, 0x70, 2, 1), + PLL_35XX_RATE(350000000, 0xa7, 4, 1), + PLL_35XX_RATE(340000000, 0x4d, 1, 1), + PLL_35XX_RATE(330000000, 0x66, 2, 1), + PLL_35XX_RATE(320000000, 0x98, 4, 1), + PLL_35XX_RATE(310000000, 0x93, 4, 1), + PLL_35XX_RATE(300000000, 0x75, 3, 1), + PLL_35XX_RATE(240000000, 0x70, 1, 2), + PLL_35XX_RATE(230000000, 0x6b, 1, 2), + PLL_35XX_RATE(220000000, 0x66, 1, 2), + PLL_35XX_RATE(210000000, 0x84, 2, 2), + PLL_35XX_RATE(200000000, 0x5c, 1, 2), + PLL_35XX_RATE(190000000, 0x57, 1, 2), + PLL_35XX_RATE(180000000, 0x70, 2, 2), + PLL_35XX_RATE(170000000, 0x4d, 1, 2), + PLL_35XX_RATE(160000000, 0x98, 4, 2), + PLL_35XX_RATE(150000000, 0x75, 3, 2), + PLL_35XX_RATE(120000000, 0x70, 1, 3), + PLL_35XX_RATE(110000000, 0x66, 1, 3), + PLL_35XX_RATE(100000000, 0x5c, 1, 3), + PLL_35XX_RATE(90000000, 0x70, 2, 3), + PLL_35XX_RATE(80000000, 0x98, 4, 3), + PLL_35XX_RATE(75000000, 0x75, 3, 3), + { /* sentinel */ }, +}; + +static struct samsung_pll_clock s3c244x_common_plls[] __initdata = { + [mpll] = PLL(pll_s3c2440_mpll, MPLL, "mpll", "xti", + LOCKTIME, MPLLCON, NULL), + [upll] = PLL(pll_s3c2410_upll, UPLL, "upll", "xti", + LOCKTIME, UPLLCON, NULL), +}; + +PNAME(hclk_p) = { "fclk", "div_hclk_2", "div_hclk_4", "div_hclk_3" }; +PNAME(armclk_p) = { "fclk", "hclk" }; + +struct samsung_mux_clock s3c244x_common_muxes[] __initdata = { + MUX(HCLK, "hclk", hclk_p, CLKDIVN, 1, 2), + MUX(ARMCLK, "armclk", armclk_p, CAMDIVN, 12, 1), +}; + +struct samsung_fixed_factor_clock s3c244x_common_ffactor[] __initdata = { + FFACTOR(0, "div_hclk_2", "fclk", 1, 2, 0), + FFACTOR(0, "ff_cam", "div_cam", 2, 1, CLK_SET_RATE_PARENT), +}; + +static struct clk_div_table div_hclk_4_d[] = { + { .val = 0, .div = 4 }, + { .val = 1, .div = 8 }, + { /* sentinel */ }, +}; + +static struct clk_div_table div_hclk_3_d[] = { + { .val = 0, .div = 3 }, + { .val = 1, .div = 6 }, + { /* sentinel */ }, +}; + +struct samsung_div_clock s3c244x_common_dividers[] __initdata = { + DIV(UCLK, "uclk", "upll", CLKDIVN, 3, 1), + DIV(0, "div_hclk", "fclk", CLKDIVN, 1, 1), + DIV_T(0, "div_hclk_4", "fclk", CAMDIVN, 9, 1, div_hclk_4_d), + DIV_T(0, "div_hclk_3", "fclk", CAMDIVN, 8, 1, div_hclk_3_d), + DIV(0, "div_cam", "upll", CAMDIVN, 0, 3), +}; + +struct samsung_gate_clock s3c244x_common_gates[] __initdata = { + GATE(HCLK_CAM, "cam", "hclk", CLKCON, 19, 0, 0), +}; + +struct samsung_clock_alias s3c244x_common_aliases[] __initdata = { + ALIAS(PCLK_UART0, "s3c2440-uart.0", "uart"), + ALIAS(PCLK_UART1, "s3c2440-uart.1", "uart"), + ALIAS(PCLK_UART2, "s3c2440-uart.2", "uart"), + ALIAS(PCLK_UART0, "s3c2440-uart.0", "clk_uart_baud2"), + ALIAS(PCLK_UART1, "s3c2440-uart.1", "clk_uart_baud2"), + ALIAS(PCLK_UART2, "s3c2440-uart.2", "clk_uart_baud2"), + ALIAS(HCLK_CAM, NULL, "camif"), + ALIAS(CAMIF, NULL, "camif-upll"), +}; + +/* S3C2440 specific clocks */ + +PNAME(s3c2440_camif_p) = { "upll", "ff_cam" }; + +struct samsung_mux_clock s3c2440_muxes[] __initdata = { + MUX(CAMIF, "camif", s3c2440_camif_p, CAMDIVN, 4, 1), +}; + +struct samsung_gate_clock s3c2440_gates[] __initdata = { + GATE(PCLK_AC97, "ac97", "pclk", CLKCON, 20, 0, 0), +}; + +/* S3C2442 specific clocks */ + +struct samsung_fixed_factor_clock s3c2442_ffactor[] __initdata = { + FFACTOR(0, "upll_3", "upll", 1, 3, 0), +}; + +PNAME(s3c2442_camif_p) = { "upll", "ff_cam", "upll", "upll_3" }; + +struct samsung_mux_clock s3c2442_muxes[] __initdata = { + MUX(CAMIF, "camif", s3c2442_camif_p, CAMDIVN, 4, 2), +}; + +/* + * fixed rate clocks generated outside the soc + * Only necessary until the devicetree-move is complete + */ +#define XTI 1 +struct samsung_fixed_rate_clock s3c2410_common_frate_clks[] __initdata = { + FRATE(XTI, "xti", NULL, CLK_IS_ROOT, 0), +}; + +static void __init s3c2410_common_clk_register_fixed_ext(unsigned long xti_f) +{ + struct samsung_clock_alias xti_alias = ALIAS(XTI, NULL, "xtal"); + + s3c2410_common_frate_clks[0].fixed_rate = xti_f; + samsung_clk_register_fixed_rate(s3c2410_common_frate_clks, + ARRAY_SIZE(s3c2410_common_frate_clks)); + + samsung_clk_register_alias(&xti_alias, 1); +} + +void __init s3c2410_common_clk_init(struct device_node *np, unsigned long xti_f, + int current_soc, + void __iomem *base) +{ + reg_base = base; + + if (np) { + reg_base = of_iomap(np, 0); + if (!reg_base) + panic("%s: failed to map registers\n", __func__); + } + + samsung_clk_init(np, reg_base, NR_CLKS); + + /* Register external clocks only in non-dt cases */ + if (!np) + s3c2410_common_clk_register_fixed_ext(xti_f); + + if (current_soc == 2410) { + if (_get_rate("xti") == 12 * MHZ) { + s3c2410_plls[mpll].rate_table = pll_s3c2410_12mhz_tbl; + s3c2410_plls[upll].rate_table = pll_s3c2410_12mhz_tbl; + } + + /* Register PLLs. */ + samsung_clk_register_pll(s3c2410_plls, + ARRAY_SIZE(s3c2410_plls), reg_base); + + } else { /* S3C2440, S3C2442 */ + if (_get_rate("xti") == 12 * MHZ) { + /* + * plls follow different calculation schemes, with the + * upll following the same scheme as the s3c2410 plls + */ + s3c244x_common_plls[mpll].rate_table = + pll_s3c244x_12mhz_tbl; + s3c244x_common_plls[upll].rate_table = + pll_s3c2410_12mhz_tbl; + } + + /* Register PLLs. */ + samsung_clk_register_pll(s3c244x_common_plls, + ARRAY_SIZE(s3c244x_common_plls), reg_base); + } + + /* Register common internal clocks. */ + samsung_clk_register_mux(s3c2410_common_muxes, + ARRAY_SIZE(s3c2410_common_muxes)); + samsung_clk_register_div(s3c2410_common_dividers, + ARRAY_SIZE(s3c2410_common_dividers)); + samsung_clk_register_gate(s3c2410_common_gates, + ARRAY_SIZE(s3c2410_common_gates)); + + if (current_soc == S3C2440 || current_soc == S3C2442) { + samsung_clk_register_div(s3c244x_common_dividers, + ARRAY_SIZE(s3c244x_common_dividers)); + samsung_clk_register_gate(s3c244x_common_gates, + ARRAY_SIZE(s3c244x_common_gates)); + samsung_clk_register_mux(s3c244x_common_muxes, + ARRAY_SIZE(s3c244x_common_muxes)); + samsung_clk_register_fixed_factor(s3c244x_common_ffactor, + ARRAY_SIZE(s3c244x_common_ffactor)); + } + + /* Register SoC-specific clocks. */ + switch (current_soc) { + case S3C2410: + samsung_clk_register_div(s3c2410_dividers, + ARRAY_SIZE(s3c2410_dividers)); + samsung_clk_register_fixed_factor(s3c2410_ffactor, + ARRAY_SIZE(s3c2410_ffactor)); + samsung_clk_register_alias(s3c2410_aliases, + ARRAY_SIZE(s3c2410_common_aliases)); + break; + case S3C2440: + samsung_clk_register_mux(s3c2440_muxes, + ARRAY_SIZE(s3c2440_muxes)); + samsung_clk_register_gate(s3c2440_gates, + ARRAY_SIZE(s3c2440_gates)); + break; + case S3C2442: + samsung_clk_register_mux(s3c2442_muxes, + ARRAY_SIZE(s3c2442_muxes)); + samsung_clk_register_fixed_factor(s3c2442_ffactor, + ARRAY_SIZE(s3c2442_ffactor)); + break; + } + + /* + * Register common aliases at the end, as some of the aliased clocks + * are SoC specific. + */ + samsung_clk_register_alias(s3c2410_common_aliases, + ARRAY_SIZE(s3c2410_common_aliases)); + + if (current_soc == S3C2440 || current_soc == S3C2442) { + samsung_clk_register_alias(s3c244x_common_aliases, + ARRAY_SIZE(s3c244x_common_aliases)); + } + + s3c2410_clk_sleep_init(); +} + +static void __init s3c2410_clk_init(struct device_node *np) +{ + s3c2410_common_clk_init(np, 0, S3C2410, 0); +} +CLK_OF_DECLARE(s3c2410_clk, "samsung,s3c2410-clock", s3c2410_clk_init); + +static void __init s3c2440_clk_init(struct device_node *np) +{ + s3c2410_common_clk_init(np, 0, S3C2440, 0); +} +CLK_OF_DECLARE(s3c2440_clk, "samsung,s3c2440-clock", s3c2440_clk_init); + +static void __init s3c2442_clk_init(struct device_node *np) +{ + s3c2410_common_clk_init(np, 0, S3C2442, 0); +} +CLK_OF_DECLARE(s3c2442_clk, "samsung,s3c2442-clock", s3c2442_clk_init); diff --git a/include/dt-bindings/clock/s3c2410.h b/include/dt-bindings/clock/s3c2410.h new file mode 100644 index 000000000000..352a7673fc69 --- /dev/null +++ b/include/dt-bindings/clock/s3c2410.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2013 Heiko Stuebner + * + * 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. + * + * Device Tree binding constants clock controllers of Samsung S3C2410 and later. + */ + +#ifndef _DT_BINDINGS_CLOCK_SAMSUNG_S3C2410_CLOCK_H +#define _DT_BINDINGS_CLOCK_SAMSUNG_S3C2410_CLOCK_H + +/* + * Let each exported clock get a unique index, which is used on DT-enabled + * platforms to lookup the clock from a clock specifier. These indices are + * therefore considered an ABI and so must not be changed. This implies + * that new clocks should be added either in free spaces between clock groups + * or at the end. + */ + +/* Core clocks. */ + +/* id 1 is reserved */ +#define MPLL 2 +#define UPLL 3 +#define FCLK 4 +#define HCLK 5 +#define PCLK 6 +#define UCLK 7 +#define ARMCLK 8 + +/* pclk-gates */ +#define PCLK_UART0 16 +#define PCLK_UART1 17 +#define PCLK_UART2 18 +#define PCLK_I2C 19 +#define PCLK_SDI 20 +#define PCLK_SPI 21 +#define PCLK_ADC 22 +#define PCLK_AC97 23 +#define PCLK_I2S 24 +#define PCLK_PWM 25 +#define PCLK_RTC 26 +#define PCLK_GPIO 27 + + +/* hclk-gates */ +#define HCLK_LCD 32 +#define HCLK_USBH 33 +#define HCLK_USBD 34 +#define HCLK_NAND 35 +#define HCLK_CAM 36 + + +#define CAMIF 40 + + +/* Total number of clocks. */ +#define NR_CLKS (CAMIF + 1) + +#endif /* _DT_BINDINGS_CLOCK_SAMSUNG_S3C2443_CLOCK_H */ From 4659c534834c33c698c9400e0aedd1e1aa48e9b6 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Fri, 9 May 2014 05:49:14 +0900 Subject: [PATCH 50/87] ARM: S3C24XX: add platform code for conversion to the common clock framework This adds the necessary init functions to init the clocks from the common clock framework and necessary CONFIG_SAMSUNG_CLOCK ifdefs around the legacy clock code. This also includes empty stubs for the *_setup_clocks functions that are called from the cpufreq driver on resume. Signed-off-by: Heiko Stuebner Reviewed-by: Tomasz Figa Signed-off-by: Kukjin Kim --- arch/arm/mach-s3c24xx/Kconfig | 5 +++++ arch/arm/mach-s3c24xx/common.c | 25 +++++++++++++++++++++++++ arch/arm/mach-s3c24xx/common.h | 7 +++++++ arch/arm/mach-s3c24xx/s3c2410.c | 6 ++++++ arch/arm/mach-s3c24xx/s3c2442.c | 3 ++- arch/arm/mach-s3c24xx/s3c244x.c | 6 ++++++ 6 files changed, 51 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-s3c24xx/Kconfig b/arch/arm/mach-s3c24xx/Kconfig index c9378806b9e8..6a0fcb1c3303 100644 --- a/arch/arm/mach-s3c24xx/Kconfig +++ b/arch/arm/mach-s3c24xx/Kconfig @@ -18,6 +18,11 @@ config PLAT_S3C24XX help Base platform code for any Samsung S3C24XX device +config S3C2410_COMMON_CLK + bool + help + Build the s3c2410 clock driver based on the common clock framework. + config S3C2410_COMMON_DCLK bool select REGMAP_MMIO diff --git a/arch/arm/mach-s3c24xx/common.c b/arch/arm/mach-s3c24xx/common.c index 7cc6d944c820..35cf88e1fa83 100644 --- a/arch/arm/mach-s3c24xx/common.c +++ b/arch/arm/mach-s3c24xx/common.c @@ -53,6 +53,7 @@ #include #include #include +#include #include "common.h" @@ -533,6 +534,14 @@ struct platform_device s3c2443_device_dma = { }; #endif +#if defined(CONFIG_COMMON_CLK) && defined(CONFIG_CPU_S3C2410) +void __init s3c2410_init_clocks(int xtal) +{ + s3c2410_common_clk_init(NULL, xtal, 0, S3C24XX_VA_CLKPWR); + samsung_wdt_reset_init(S3C24XX_VA_WATCHDOG); +} +#endif + #ifdef CONFIG_CPU_S3C2412 void __init s3c2412_init_clocks(int xtal) { @@ -547,6 +556,22 @@ void __init s3c2416_init_clocks(int xtal) } #endif +#if defined(CONFIG_COMMON_CLK) && defined(CONFIG_CPU_S3C2440) +void __init s3c2440_init_clocks(int xtal) +{ + s3c2410_common_clk_init(NULL, xtal, 1, S3C24XX_VA_CLKPWR); + samsung_wdt_reset_init(S3C24XX_VA_WATCHDOG); +} +#endif + +#if defined(CONFIG_COMMON_CLK) && defined(CONFIG_CPU_S3C2442) +void __init s3c2442_init_clocks(int xtal) +{ + s3c2410_common_clk_init(NULL, xtal, 2, S3C24XX_VA_CLKPWR); + samsung_wdt_reset_init(S3C24XX_VA_WATCHDOG); +} +#endif + #ifdef CONFIG_CPU_S3C2443 void __init s3c2443_init_clocks(int xtal) { diff --git a/arch/arm/mach-s3c24xx/common.h b/arch/arm/mach-s3c24xx/common.h index 50504c77fa00..2d6554140161 100644 --- a/arch/arm/mach-s3c24xx/common.h +++ b/arch/arm/mach-s3c24xx/common.h @@ -77,6 +77,7 @@ extern void s3c244x_restart(enum reboot_mode mode, const char *cmd); #ifdef CONFIG_CPU_S3C2440 extern int s3c2440_init(void); extern void s3c2440_map_io(void); +extern void s3c2440_init_clocks(int xtal); extern void s3c2440_init_irq(void); #else #define s3c2440_init NULL @@ -86,6 +87,7 @@ extern void s3c2440_init_irq(void); #ifdef CONFIG_CPU_S3C2442 extern int s3c2442_init(void); extern void s3c2442_map_io(void); +extern void s3c2442_init_clocks(int xtal); extern void s3c2442_init_irq(void); #else #define s3c2442_init NULL @@ -116,6 +118,11 @@ extern struct platform_device s3c2443_device_dma; extern struct platform_device s3c2410_device_dclk; +#ifdef CONFIG_S3C2410_COMMON_CLK +void __init s3c2410_common_clk_init(struct device_node *np, unsigned long xti_f, + int current_soc, + void __iomem *reg_base); +#endif #ifdef CONFIG_S3C2412_COMMON_CLK void __init s3c2412_common_clk_init(struct device_node *np, unsigned long xti_f, unsigned long ext_f, void __iomem *reg_base); diff --git a/arch/arm/mach-s3c24xx/s3c2410.c b/arch/arm/mach-s3c24xx/s3c2410.c index 04b58cb49888..52801730ab24 100644 --- a/arch/arm/mach-s3c24xx/s3c2410.c +++ b/arch/arm/mach-s3c24xx/s3c2410.c @@ -83,6 +83,7 @@ void __init s3c2410_map_io(void) iotable_init(s3c2410_iodesc, ARRAY_SIZE(s3c2410_iodesc)); } +#ifdef CONFIG_SAMSUNG_CLOCK void __init_or_cpufreq s3c2410_setup_clocks(void) { struct clk *xtal_clk; @@ -142,6 +143,11 @@ void __init s3c2410_init_clocks(int xtal) clkdev_add_table(s3c2410_clk_lookup, ARRAY_SIZE(s3c2410_clk_lookup)); samsung_wdt_reset_init(S3C24XX_VA_WATCHDOG); } +#else +void __init_or_cpufreq s3c2410_setup_clocks(void) +{ +} +#endif struct bus_type s3c2410_subsys = { .name = "s3c2410-core", diff --git a/arch/arm/mach-s3c24xx/s3c2442.c b/arch/arm/mach-s3c24xx/s3c2442.c index 2c8adc028538..564c65037ff2 100644 --- a/arch/arm/mach-s3c24xx/s3c2442.c +++ b/arch/arm/mach-s3c24xx/s3c2442.c @@ -53,6 +53,7 @@ #include "common.h" +#ifdef CONFIG_SAMSUNG_CLOCK /* S3C2442 extended clock support */ static unsigned long s3c2442_camif_upll_round(struct clk *clk, @@ -162,7 +163,7 @@ static __init int s3c2442_clk_init(void) } arch_initcall(s3c2442_clk_init); - +#endif static struct device s3c2442_dev = { .bus = &s3c2442_subsys, diff --git a/arch/arm/mach-s3c24xx/s3c244x.c b/arch/arm/mach-s3c24xx/s3c244x.c index 76b691bf724e..1d665d50b034 100644 --- a/arch/arm/mach-s3c24xx/s3c244x.c +++ b/arch/arm/mach-s3c24xx/s3c244x.c @@ -78,6 +78,7 @@ void __init s3c244x_map_io(void) s3c2410_device_dclk.name = "s3c2440-dclk"; } +#ifdef CONFIG_SAMSUNG_CLOCK void __init_or_cpufreq s3c244x_setup_clocks(void) { struct clk *xtal_clk; @@ -138,6 +139,11 @@ void __init s3c244x_init_clocks(int xtal) s3c2410_baseclk_add(); samsung_wdt_reset_init(S3C24XX_VA_WATCHDOG); } +#else +void __init_or_cpufreq s3c244x_setup_clocks(void) +{ +} +#endif /* Since the S3C2442 and S3C2440 share items, put both subsystems here */ From a28d618e2e424483afd47de6373665cd78352b25 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Fri, 9 May 2014 05:49:19 +0900 Subject: [PATCH 51/87] ARM: S3C24XX: convert s3c2440 and s3c2442 to common clock framework Convert all machines using these cpus to use the ccf clock driver instead of the legacy Samsung clock implementation. Some of the more esotheric machines will probably need a fixup, as they do strange things to the clkout outputs, that I did not really understand nor have the hardware to check. Signed-off-by: Heiko Stuebner Reviewed-by: Tomasz Figa Signed-off-by: Kukjin Kim --- arch/arm/mach-s3c24xx/Kconfig | 8 ++++---- arch/arm/mach-s3c24xx/Makefile | 4 ++-- arch/arm/mach-s3c24xx/common.c | 4 ---- arch/arm/mach-s3c24xx/mach-anubis.c | 10 +++++++--- arch/arm/mach-s3c24xx/mach-at2440evb.c | 10 +++++++--- arch/arm/mach-s3c24xx/mach-gta02.c | 8 ++++++-- arch/arm/mach-s3c24xx/mach-mini2440.c | 10 +++++++--- arch/arm/mach-s3c24xx/mach-nexcoder.c | 15 ++++++++++++--- arch/arm/mach-s3c24xx/mach-osiris.c | 10 +++++++--- arch/arm/mach-s3c24xx/mach-rx1950.c | 10 +++++++--- arch/arm/mach-s3c24xx/mach-rx3715.c | 10 +++++++--- arch/arm/mach-s3c24xx/mach-smdk2440.c | 10 +++++++--- 12 files changed, 73 insertions(+), 36 deletions(-) diff --git a/arch/arm/mach-s3c24xx/Kconfig b/arch/arm/mach-s3c24xx/Kconfig index 6a0fcb1c3303..56ce1c6a283c 100644 --- a/arch/arm/mach-s3c24xx/Kconfig +++ b/arch/arm/mach-s3c24xx/Kconfig @@ -73,10 +73,10 @@ config CPU_S3C2416 config CPU_S3C2440 bool "SAMSUNG S3C2440" - depends on SAMSUNG_CLOCK + select COMMON_CLK select CPU_ARM920T select CPU_LLSERIAL_S3C2440 - select S3C2410_CLOCK + select S3C2410_COMMON_CLK select S3C2410_PM if PM select S3C2440_DMA if S3C24XX_DMA help @@ -84,10 +84,10 @@ config CPU_S3C2440 config CPU_S3C2442 bool "SAMSUNG S3C2442" - depends on SAMSUNG_CLOCK + select COMMON_CLK select CPU_ARM920T select CPU_LLSERIAL_S3C2440 - select S3C2410_CLOCK + select S3C2410_COMMON_CLK select S3C2410_DMA if S3C24XX_DMA select S3C2410_PM if PM help diff --git a/arch/arm/mach-s3c24xx/Makefile b/arch/arm/mach-s3c24xx/Makefile index f25479721dc9..9010ebaafff6 100644 --- a/arch/arm/mach-s3c24xx/Makefile +++ b/arch/arm/mach-s3c24xx/Makefile @@ -29,9 +29,9 @@ obj-$(CONFIG_S3C2412_PM_SLEEP) += sleep-s3c2412.o obj-$(CONFIG_CPU_S3C2416) += s3c2416.o obj-$(CONFIG_S3C2416_PM) += pm-s3c2416.o -obj-$(CONFIG_CPU_S3C2440) += s3c2440.o clock-s3c2440.o +obj-$(CONFIG_CPU_S3C2440) += s3c2440.o obj-$(CONFIG_CPU_S3C2442) += s3c2442.o -obj-$(CONFIG_CPU_S3C244X) += s3c244x.o clock-s3c244x.o +obj-$(CONFIG_CPU_S3C244X) += s3c244x.o obj-$(CONFIG_S3C2440_DMA) += dma-s3c2440.o obj-$(CONFIG_S3C2440_PLL_12000000) += pll-s3c2440-12000000.o obj-$(CONFIG_S3C2440_PLL_16934400) += pll-s3c2440-16934400.o diff --git a/arch/arm/mach-s3c24xx/common.c b/arch/arm/mach-s3c24xx/common.c index 35cf88e1fa83..bda9dd4abae3 100644 --- a/arch/arm/mach-s3c24xx/common.c +++ b/arch/arm/mach-s3c24xx/common.c @@ -92,7 +92,6 @@ static struct cpu_table cpu_ids[] __initdata = { .idcode = 0x32440000, .idmask = 0xffffffff, .map_io = s3c2440_map_io, - .init_clocks = s3c244x_init_clocks, .init_uarts = s3c244x_init_uarts, .init = s3c2440_init, .name = name_s3c2440 @@ -101,7 +100,6 @@ static struct cpu_table cpu_ids[] __initdata = { .idcode = 0x32440001, .idmask = 0xffffffff, .map_io = s3c2440_map_io, - .init_clocks = s3c244x_init_clocks, .init_uarts = s3c244x_init_uarts, .init = s3c2440_init, .name = name_s3c2440a @@ -110,7 +108,6 @@ static struct cpu_table cpu_ids[] __initdata = { .idcode = 0x32440aaa, .idmask = 0xffffffff, .map_io = s3c2442_map_io, - .init_clocks = s3c244x_init_clocks, .init_uarts = s3c244x_init_uarts, .init = s3c2442_init, .name = name_s3c2442 @@ -119,7 +116,6 @@ static struct cpu_table cpu_ids[] __initdata = { .idcode = 0x32440aab, .idmask = 0xffffffff, .map_io = s3c2442_map_io, - .init_clocks = s3c244x_init_clocks, .init_uarts = s3c244x_init_uarts, .init = s3c2442_init, .name = name_s3c2442b diff --git a/arch/arm/mach-s3c24xx/mach-anubis.c b/arch/arm/mach-s3c24xx/mach-anubis.c index f81944f3217d..7a0d83b2f93a 100644 --- a/arch/arm/mach-s3c24xx/mach-anubis.c +++ b/arch/arm/mach-s3c24xx/mach-anubis.c @@ -46,7 +46,6 @@ #include -#include #include #include #include @@ -415,7 +414,6 @@ static void __init anubis_map_io(void) #endif s3c24xx_init_io(anubis_iodesc, ARRAY_SIZE(anubis_iodesc)); - s3c24xx_init_clocks(0); s3c24xx_init_uarts(anubis_uartcfgs, ARRAY_SIZE(anubis_uartcfgs)); samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4); @@ -433,6 +431,12 @@ static void __init anubis_map_io(void) } } +static void __init anubis_init_time(void) +{ + s3c2440_init_clocks(12000000); + samsung_timer_init(); +} + static void __init anubis_init(void) { s3c_i2c0_set_platdata(NULL); @@ -452,6 +456,6 @@ MACHINE_START(ANUBIS, "Simtec-Anubis") .map_io = anubis_map_io, .init_machine = anubis_init, .init_irq = s3c2440_init_irq, - .init_time = samsung_timer_init, + .init_time = anubis_init_time, .restart = s3c244x_restart, MACHINE_END diff --git a/arch/arm/mach-s3c24xx/mach-at2440evb.c b/arch/arm/mach-s3c24xx/mach-at2440evb.c index d8f6bb1096cb..9db768f448a5 100644 --- a/arch/arm/mach-s3c24xx/mach-at2440evb.c +++ b/arch/arm/mach-s3c24xx/mach-at2440evb.c @@ -45,7 +45,6 @@ #include #include -#include #include #include #include @@ -192,11 +191,16 @@ static struct platform_device *at2440evb_devices[] __initdata = { static void __init at2440evb_map_io(void) { s3c24xx_init_io(at2440evb_iodesc, ARRAY_SIZE(at2440evb_iodesc)); - s3c24xx_init_clocks(16934400); s3c24xx_init_uarts(at2440evb_uartcfgs, ARRAY_SIZE(at2440evb_uartcfgs)); samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4); } +static void __init at2440evb_init_time(void) +{ + s3c2440_init_clocks(16934400); + samsung_timer_init(); +} + static void __init at2440evb_init(void) { s3c24xx_fb_set_platdata(&at2440evb_fb_info); @@ -213,6 +217,6 @@ MACHINE_START(AT2440EVB, "AT2440EVB") .map_io = at2440evb_map_io, .init_machine = at2440evb_init, .init_irq = s3c2440_init_irq, - .init_time = samsung_timer_init, + .init_time = at2440evb_init_time, .restart = s3c244x_restart, MACHINE_END diff --git a/arch/arm/mach-s3c24xx/mach-gta02.c b/arch/arm/mach-s3c24xx/mach-gta02.c index dc4db849f0fd..fc3a08d0cb3f 100644 --- a/arch/arm/mach-s3c24xx/mach-gta02.c +++ b/arch/arm/mach-s3c24xx/mach-gta02.c @@ -501,7 +501,6 @@ static struct platform_device gta02_buttons_device = { static void __init gta02_map_io(void) { s3c24xx_init_io(gta02_iodesc, ARRAY_SIZE(gta02_iodesc)); - s3c24xx_init_clocks(12000000); s3c24xx_init_uarts(gta02_uartcfgs, ARRAY_SIZE(gta02_uartcfgs)); samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4); } @@ -585,6 +584,11 @@ static void __init gta02_machine_init(void) regulator_has_full_constraints(); } +static void __init gta02_init_time(void) +{ + s3c2442_init_clocks(12000000); + samsung_timer_init(); +} MACHINE_START(NEO1973_GTA02, "GTA02") /* Maintainer: Nelson Castillo */ @@ -592,6 +596,6 @@ MACHINE_START(NEO1973_GTA02, "GTA02") .map_io = gta02_map_io, .init_irq = s3c2442_init_irq, .init_machine = gta02_machine_init, - .init_time = samsung_timer_init, + .init_time = gta02_init_time, .restart = s3c244x_restart, MACHINE_END diff --git a/arch/arm/mach-s3c24xx/mach-mini2440.c b/arch/arm/mach-s3c24xx/mach-mini2440.c index 9e57fd9f4f3b..5cc40ec1d254 100644 --- a/arch/arm/mach-s3c24xx/mach-mini2440.c +++ b/arch/arm/mach-s3c24xx/mach-mini2440.c @@ -54,7 +54,6 @@ #include #include -#include #include #include #include @@ -525,11 +524,16 @@ static struct platform_device *mini2440_devices[] __initdata = { static void __init mini2440_map_io(void) { s3c24xx_init_io(mini2440_iodesc, ARRAY_SIZE(mini2440_iodesc)); - s3c24xx_init_clocks(12000000); s3c24xx_init_uarts(mini2440_uartcfgs, ARRAY_SIZE(mini2440_uartcfgs)); samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4); } +static void __init mini2440_init_time(void) +{ + s3c2440_init_clocks(12000000); + samsung_timer_init(); +} + /* * mini2440_features string * @@ -690,6 +694,6 @@ MACHINE_START(MINI2440, "MINI2440") .map_io = mini2440_map_io, .init_machine = mini2440_init, .init_irq = s3c2440_init_irq, - .init_time = samsung_timer_init, + .init_time = mini2440_init_time, .restart = s3c244x_restart, MACHINE_END diff --git a/arch/arm/mach-s3c24xx/mach-nexcoder.c b/arch/arm/mach-s3c24xx/mach-nexcoder.c index 3066851f584d..05627c2b5116 100644 --- a/arch/arm/mach-s3c24xx/mach-nexcoder.c +++ b/arch/arm/mach-s3c24xx/mach-nexcoder.c @@ -42,7 +42,6 @@ #include #include -#include #include #include #include @@ -135,13 +134,23 @@ static void __init nexcoder_sensorboard_init(void) static void __init nexcoder_map_io(void) { s3c24xx_init_io(nexcoder_iodesc, ARRAY_SIZE(nexcoder_iodesc)); - s3c24xx_init_clocks(0); s3c24xx_init_uarts(nexcoder_uartcfgs, ARRAY_SIZE(nexcoder_uartcfgs)); samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4); nexcoder_sensorboard_init(); } +static void __init nexcoder_init_time(void) +{ + /* + * for whatever reason the nexcoder called s3c24xx_init_clocks(0) + * meaning a xti value of 0Hz, so this machine will most likely + * not work out of the box and needs a fixup. + */ + s3c2440_init_clocks(0); + samsung_timer_init(); +} + static void __init nexcoder_init(void) { s3c_i2c0_set_platdata(NULL); @@ -154,6 +163,6 @@ MACHINE_START(NEXCODER_2440, "NexVision - Nexcoder 2440") .map_io = nexcoder_map_io, .init_machine = nexcoder_init, .init_irq = s3c2440_init_irq, - .init_time = samsung_timer_init, + .init_time = nexcoder_init_time, .restart = s3c244x_restart, MACHINE_END diff --git a/arch/arm/mach-s3c24xx/mach-osiris.c b/arch/arm/mach-s3c24xx/mach-osiris.c index 487be02e4f2c..3bc2c9bad8b3 100644 --- a/arch/arm/mach-s3c24xx/mach-osiris.c +++ b/arch/arm/mach-s3c24xx/mach-osiris.c @@ -40,7 +40,6 @@ #include #include -#include #include #include #include @@ -389,7 +388,6 @@ static void __init osiris_map_io(void) #endif s3c24xx_init_io(osiris_iodesc, ARRAY_SIZE(osiris_iodesc)); - s3c24xx_init_clocks(0); s3c24xx_init_uarts(osiris_uartcfgs, ARRAY_SIZE(osiris_uartcfgs)); samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4); @@ -413,6 +411,12 @@ static void __init osiris_map_io(void) local_irq_restore(flags); } +static void __init osiris_init_time(void) +{ + s3c2440_init_clocks(12000000); + samsung_timer_init(); +} + static void __init osiris_init(void) { register_syscore_ops(&osiris_pm_syscore_ops); @@ -434,6 +438,6 @@ MACHINE_START(OSIRIS, "Simtec-OSIRIS") .map_io = osiris_map_io, .init_irq = s3c2440_init_irq, .init_machine = osiris_init, - .init_time = samsung_timer_init, + .init_time = osiris_init_time, .restart = s3c244x_restart, MACHINE_END diff --git a/arch/arm/mach-s3c24xx/mach-rx1950.c b/arch/arm/mach-s3c24xx/mach-rx1950.c index 219454c93db4..5f37f5262e65 100644 --- a/arch/arm/mach-s3c24xx/mach-rx1950.c +++ b/arch/arm/mach-s3c24xx/mach-rx1950.c @@ -54,7 +54,6 @@ #include #include -#include #include #include #include @@ -746,7 +745,6 @@ static void __init rx1950_map_io(void) #endif s3c24xx_init_io(rx1950_iodesc, ARRAY_SIZE(rx1950_iodesc)); - s3c24xx_init_clocks(16934000); s3c24xx_init_uarts(rx1950_uartcfgs, ARRAY_SIZE(rx1950_uartcfgs)); samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4); @@ -759,6 +757,12 @@ static void __init rx1950_map_io(void) s3c_pm_init(); } +static void __init rx1950_init_time(void) +{ + s3c2442_init_clocks(16934000); + samsung_timer_init(); +} + static void __init rx1950_init_machine(void) { int i; @@ -821,6 +825,6 @@ MACHINE_START(RX1950, "HP iPAQ RX1950") .reserve = rx1950_reserve, .init_irq = s3c2442_init_irq, .init_machine = rx1950_init_machine, - .init_time = samsung_timer_init, + .init_time = rx1950_init_time, .restart = s3c244x_restart, MACHINE_END diff --git a/arch/arm/mach-s3c24xx/mach-rx3715.c b/arch/arm/mach-s3c24xx/mach-rx3715.c index e6535ce1bc5c..6e749ec3a2ea 100644 --- a/arch/arm/mach-s3c24xx/mach-rx3715.c +++ b/arch/arm/mach-s3c24xx/mach-rx3715.c @@ -46,7 +46,6 @@ #include #include -#include #include #include #include @@ -179,11 +178,16 @@ static struct platform_device *rx3715_devices[] __initdata = { static void __init rx3715_map_io(void) { s3c24xx_init_io(rx3715_iodesc, ARRAY_SIZE(rx3715_iodesc)); - s3c24xx_init_clocks(16934000); s3c24xx_init_uarts(rx3715_uartcfgs, ARRAY_SIZE(rx3715_uartcfgs)); samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4); } +static void __init rx3715_init_time(void) +{ + s3c2440_init_clocks(16934000); + samsung_timer_init(); +} + /* H1940 and RX3715 need to reserve this for suspend */ static void __init rx3715_reserve(void) { @@ -210,6 +214,6 @@ MACHINE_START(RX3715, "IPAQ-RX3715") .reserve = rx3715_reserve, .init_irq = s3c2440_init_irq, .init_machine = rx3715_init_machine, - .init_time = samsung_timer_init, + .init_time = rx3715_init_time, .restart = s3c244x_restart, MACHINE_END diff --git a/arch/arm/mach-s3c24xx/mach-smdk2440.c b/arch/arm/mach-s3c24xx/mach-smdk2440.c index d071dcfea548..5fb89c0ae17a 100644 --- a/arch/arm/mach-s3c24xx/mach-smdk2440.c +++ b/arch/arm/mach-s3c24xx/mach-smdk2440.c @@ -38,7 +38,6 @@ #include #include -#include #include #include #include @@ -159,11 +158,16 @@ static struct platform_device *smdk2440_devices[] __initdata = { static void __init smdk2440_map_io(void) { s3c24xx_init_io(smdk2440_iodesc, ARRAY_SIZE(smdk2440_iodesc)); - s3c24xx_init_clocks(16934400); s3c24xx_init_uarts(smdk2440_uartcfgs, ARRAY_SIZE(smdk2440_uartcfgs)); samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4); } +static void __init smdk2440_init_time(void) +{ + s3c2440_init_clocks(16934400); + samsung_timer_init(); +} + static void __init smdk2440_machine_init(void) { s3c24xx_fb_set_platdata(&smdk2440_fb_info); @@ -180,6 +184,6 @@ MACHINE_START(S3C2440, "SMDK2440") .init_irq = s3c2440_init_irq, .map_io = smdk2440_map_io, .init_machine = smdk2440_machine_init, - .init_time = samsung_timer_init, + .init_time = smdk2440_init_time, .restart = s3c244x_restart, MACHINE_END From 07ee5e7c3ec00b30996160e9a378471872ea779e Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Fri, 9 May 2014 05:49:29 +0900 Subject: [PATCH 52/87] ARM: S3C24XX: convert s3c2410 to common clock framework Convert the machines using the s3c2410 to use the new driver based on the common clock framework instead of the legacy Samsung clock driver. As with the s3c244x, machines using the clkout output will need a fixup from someone with the hardware. Signed-off-by: Heiko Stuebner Reviewed-by: Tomasz Figa Signed-off-by: Kukjin Kim --- arch/arm/mach-s3c24xx/Kconfig | 4 ++-- arch/arm/mach-s3c24xx/common.c | 2 -- arch/arm/mach-s3c24xx/mach-amlm5900.c | 9 +++++++-- arch/arm/mach-s3c24xx/mach-bast.c | 10 +++++++--- arch/arm/mach-s3c24xx/mach-h1940.c | 10 +++++++--- arch/arm/mach-s3c24xx/mach-n30.c | 12 ++++++++---- arch/arm/mach-s3c24xx/mach-nexcoder.c | 7 +------ arch/arm/mach-s3c24xx/mach-otom.c | 10 +++++++--- arch/arm/mach-s3c24xx/mach-qt2410.c | 9 +++++++-- arch/arm/mach-s3c24xx/mach-smdk2410.c | 9 +++++++-- arch/arm/mach-s3c24xx/mach-tct_hammer.c | 9 +++++++-- arch/arm/mach-s3c24xx/mach-vr1000.c | 10 +++++++--- 12 files changed, 67 insertions(+), 34 deletions(-) diff --git a/arch/arm/mach-s3c24xx/Kconfig b/arch/arm/mach-s3c24xx/Kconfig index 56ce1c6a283c..23968c661415 100644 --- a/arch/arm/mach-s3c24xx/Kconfig +++ b/arch/arm/mach-s3c24xx/Kconfig @@ -37,10 +37,10 @@ comment "S3C24XX SoCs" config CPU_S3C2410 bool "SAMSUNG S3C2410" default y - depends on SAMSUNG_CLOCK + select COMMON_CLK select CPU_ARM920T select CPU_LLSERIAL_S3C2410 - select S3C2410_CLOCK + select S3C2410_COMMON_CLK select S3C2410_DMA if S3C24XX_DMA select ARM_S3C2410_CPUFREQ if ARM_S3C24XX_CPUFREQ select S3C2410_PM if PM diff --git a/arch/arm/mach-s3c24xx/common.c b/arch/arm/mach-s3c24xx/common.c index bda9dd4abae3..600a1be5696b 100644 --- a/arch/arm/mach-s3c24xx/common.c +++ b/arch/arm/mach-s3c24xx/common.c @@ -74,7 +74,6 @@ static struct cpu_table cpu_ids[] __initdata = { .idcode = 0x32410000, .idmask = 0xffffffff, .map_io = s3c2410_map_io, - .init_clocks = s3c2410_init_clocks, .init_uarts = s3c2410_init_uarts, .init = s3c2410_init, .name = name_s3c2410 @@ -83,7 +82,6 @@ static struct cpu_table cpu_ids[] __initdata = { .idcode = 0x32410002, .idmask = 0xffffffff, .map_io = s3c2410_map_io, - .init_clocks = s3c2410_init_clocks, .init_uarts = s3c2410_init_uarts, .init = s3c2410a_init, .name = name_s3c2410a diff --git a/arch/arm/mach-s3c24xx/mach-amlm5900.c b/arch/arm/mach-s3c24xx/mach-amlm5900.c index 8ac9554aa996..5157e250dd13 100644 --- a/arch/arm/mach-s3c24xx/mach-amlm5900.c +++ b/arch/arm/mach-s3c24xx/mach-amlm5900.c @@ -161,11 +161,16 @@ static struct platform_device *amlm5900_devices[] __initdata = { static void __init amlm5900_map_io(void) { s3c24xx_init_io(amlm5900_iodesc, ARRAY_SIZE(amlm5900_iodesc)); - s3c24xx_init_clocks(0); s3c24xx_init_uarts(amlm5900_uartcfgs, ARRAY_SIZE(amlm5900_uartcfgs)); samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4); } +static void __init amlm5900_init_time(void) +{ + s3c2410_init_clocks(12000000); + samsung_timer_init(); +} + #ifdef CONFIG_FB_S3C2410 static struct s3c2410fb_display __initdata amlm5900_lcd_info = { .width = 160, @@ -241,6 +246,6 @@ MACHINE_START(AML_M5900, "AML_M5900") .map_io = amlm5900_map_io, .init_irq = s3c2410_init_irq, .init_machine = amlm5900_init, - .init_time = samsung_timer_init, + .init_time = amlm5900_init_time, .restart = s3c2410_restart, MACHINE_END diff --git a/arch/arm/mach-s3c24xx/mach-bast.c b/arch/arm/mach-s3c24xx/mach-bast.c index dcdc4a575690..ea762f20099b 100644 --- a/arch/arm/mach-s3c24xx/mach-bast.c +++ b/arch/arm/mach-s3c24xx/mach-bast.c @@ -51,7 +51,6 @@ #include #include -#include #include #include #include @@ -581,11 +580,16 @@ static void __init bast_map_io(void) s3c_hwmon_set_platdata(&bast_hwmon_info); s3c24xx_init_io(bast_iodesc, ARRAY_SIZE(bast_iodesc)); - s3c24xx_init_clocks(0); s3c24xx_init_uarts(bast_uartcfgs, ARRAY_SIZE(bast_uartcfgs)); samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4); } +static void __init bast_init_time(void) +{ + s3c2410_init_clocks(12000000); + samsung_timer_init(); +} + static void __init bast_init(void) { register_syscore_ops(&bast_pm_syscore_ops); @@ -613,6 +617,6 @@ MACHINE_START(BAST, "Simtec-BAST") .map_io = bast_map_io, .init_irq = s3c2410_init_irq, .init_machine = bast_init, - .init_time = samsung_timer_init, + .init_time = bast_init_time, .restart = s3c2410_restart, MACHINE_END diff --git a/arch/arm/mach-s3c24xx/mach-h1940.c b/arch/arm/mach-s3c24xx/mach-h1940.c index e453acd92cbf..fbf5487ae5d1 100644 --- a/arch/arm/mach-s3c24xx/mach-h1940.c +++ b/arch/arm/mach-s3c24xx/mach-h1940.c @@ -57,7 +57,6 @@ #include #include -#include #include #include #include @@ -646,7 +645,6 @@ static struct platform_device *h1940_devices[] __initdata = { static void __init h1940_map_io(void) { s3c24xx_init_io(h1940_iodesc, ARRAY_SIZE(h1940_iodesc)); - s3c24xx_init_clocks(0); s3c24xx_init_uarts(h1940_uartcfgs, ARRAY_SIZE(h1940_uartcfgs)); samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4); @@ -662,6 +660,12 @@ static void __init h1940_map_io(void) WARN_ON(gpiochip_add(&h1940_latch_gpiochip)); } +static void __init h1940_init_time(void) +{ + s3c2410_init_clocks(12000000); + samsung_timer_init(); +} + /* H1940 and RX3715 need to reserve this for suspend */ static void __init h1940_reserve(void) { @@ -739,6 +743,6 @@ MACHINE_START(H1940, "IPAQ-H1940") .reserve = h1940_reserve, .init_irq = s3c2410_init_irq, .init_machine = h1940_init, - .init_time = samsung_timer_init, + .init_time = h1940_init_time, .restart = s3c2410_restart, MACHINE_END diff --git a/arch/arm/mach-s3c24xx/mach-n30.c b/arch/arm/mach-s3c24xx/mach-n30.c index 4cccaad34847..3ac2a54348d6 100644 --- a/arch/arm/mach-s3c24xx/mach-n30.c +++ b/arch/arm/mach-s3c24xx/mach-n30.c @@ -45,7 +45,6 @@ #include -#include #include #include #include @@ -535,11 +534,16 @@ static void __init n30_map_io(void) { s3c24xx_init_io(n30_iodesc, ARRAY_SIZE(n30_iodesc)); n30_hwinit(); - s3c24xx_init_clocks(0); s3c24xx_init_uarts(n30_uartcfgs, ARRAY_SIZE(n30_uartcfgs)); samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4); } +static void __init n30_init_time(void) +{ + s3c2410_init_clocks(12000000); + samsung_timer_init(); +} + /* GPB3 is the line that controls the pull-up for the USB D+ line */ static void __init n30_init(void) @@ -591,7 +595,7 @@ MACHINE_START(N30, "Acer-N30") Ben Dooks */ .atag_offset = 0x100, - .init_time = samsung_timer_init, + .init_time = n30_init_time, .init_machine = n30_init, .init_irq = s3c2410_init_irq, .map_io = n30_map_io, @@ -602,7 +606,7 @@ MACHINE_START(N35, "Acer-N35") /* Maintainer: Christer Weinigel */ .atag_offset = 0x100, - .init_time = samsung_timer_init, + .init_time = n30_init_time, .init_machine = n30_init, .init_irq = s3c2410_init_irq, .map_io = n30_map_io, diff --git a/arch/arm/mach-s3c24xx/mach-nexcoder.c b/arch/arm/mach-s3c24xx/mach-nexcoder.c index 05627c2b5116..c82c281ce351 100644 --- a/arch/arm/mach-s3c24xx/mach-nexcoder.c +++ b/arch/arm/mach-s3c24xx/mach-nexcoder.c @@ -142,12 +142,7 @@ static void __init nexcoder_map_io(void) static void __init nexcoder_init_time(void) { - /* - * for whatever reason the nexcoder called s3c24xx_init_clocks(0) - * meaning a xti value of 0Hz, so this machine will most likely - * not work out of the box and needs a fixup. - */ - s3c2440_init_clocks(0); + s3c2440_init_clocks(12000000); samsung_timer_init(); } diff --git a/arch/arm/mach-s3c24xx/mach-otom.c b/arch/arm/mach-s3c24xx/mach-otom.c index bdb3faac2d9b..45833001186d 100644 --- a/arch/arm/mach-s3c24xx/mach-otom.c +++ b/arch/arm/mach-s3c24xx/mach-otom.c @@ -30,7 +30,6 @@ #include #include -#include #include #include #include @@ -100,11 +99,16 @@ static struct platform_device *otom11_devices[] __initdata = { static void __init otom11_map_io(void) { s3c24xx_init_io(otom11_iodesc, ARRAY_SIZE(otom11_iodesc)); - s3c24xx_init_clocks(0); s3c24xx_init_uarts(otom11_uartcfgs, ARRAY_SIZE(otom11_uartcfgs)); samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4); } +static void __init otom11_init_time(void) +{ + s3c2410_init_clocks(12000000); + samsung_timer_init(); +} + static void __init otom11_init(void) { s3c_i2c0_set_platdata(NULL); @@ -117,6 +121,6 @@ MACHINE_START(OTOM, "Nex Vision - Otom 1.1") .map_io = otom11_map_io, .init_machine = otom11_init, .init_irq = s3c2410_init_irq, - .init_time = samsung_timer_init, + .init_time = otom11_init_time, .restart = s3c2410_restart, MACHINE_END diff --git a/arch/arm/mach-s3c24xx/mach-qt2410.c b/arch/arm/mach-s3c24xx/mach-qt2410.c index 8c12787a8fd3..228c9094519d 100644 --- a/arch/arm/mach-s3c24xx/mach-qt2410.c +++ b/arch/arm/mach-s3c24xx/mach-qt2410.c @@ -304,11 +304,16 @@ __setup("tft=", qt2410_tft_setup); static void __init qt2410_map_io(void) { s3c24xx_init_io(qt2410_iodesc, ARRAY_SIZE(qt2410_iodesc)); - s3c24xx_init_clocks(12*1000*1000); s3c24xx_init_uarts(smdk2410_uartcfgs, ARRAY_SIZE(smdk2410_uartcfgs)); samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4); } +static void __init qt2410_init_time(void) +{ + s3c2410_init_clocks(12000000); + samsung_timer_init(); +} + static void __init qt2410_machine_init(void) { s3c_nand_set_platdata(&qt2410_nand_info); @@ -346,6 +351,6 @@ MACHINE_START(QT2410, "QT2410") .map_io = qt2410_map_io, .init_irq = s3c2410_init_irq, .init_machine = qt2410_machine_init, - .init_time = samsung_timer_init, + .init_time = qt2410_init_time, .restart = s3c2410_restart, MACHINE_END diff --git a/arch/arm/mach-s3c24xx/mach-smdk2410.c b/arch/arm/mach-s3c24xx/mach-smdk2410.c index f32924ee0e9f..419fadd6e446 100644 --- a/arch/arm/mach-s3c24xx/mach-smdk2410.c +++ b/arch/arm/mach-s3c24xx/mach-smdk2410.c @@ -99,11 +99,16 @@ static struct platform_device *smdk2410_devices[] __initdata = { static void __init smdk2410_map_io(void) { s3c24xx_init_io(smdk2410_iodesc, ARRAY_SIZE(smdk2410_iodesc)); - s3c24xx_init_clocks(0); s3c24xx_init_uarts(smdk2410_uartcfgs, ARRAY_SIZE(smdk2410_uartcfgs)); samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4); } +static void __init smdk2410_init_time(void) +{ + s3c2410_init_clocks(12000000); + samsung_timer_init(); +} + static void __init smdk2410_init(void) { s3c_i2c0_set_platdata(NULL); @@ -118,6 +123,6 @@ MACHINE_START(SMDK2410, "SMDK2410") /* @TODO: request a new identifier and switc .map_io = smdk2410_map_io, .init_irq = s3c2410_init_irq, .init_machine = smdk2410_init, - .init_time = samsung_timer_init, + .init_time = smdk2410_init_time, .restart = s3c2410_restart, MACHINE_END diff --git a/arch/arm/mach-s3c24xx/mach-tct_hammer.c b/arch/arm/mach-s3c24xx/mach-tct_hammer.c index 4108b2f0cede..c616ca2d409e 100644 --- a/arch/arm/mach-s3c24xx/mach-tct_hammer.c +++ b/arch/arm/mach-s3c24xx/mach-tct_hammer.c @@ -135,11 +135,16 @@ static struct platform_device *tct_hammer_devices[] __initdata = { static void __init tct_hammer_map_io(void) { s3c24xx_init_io(tct_hammer_iodesc, ARRAY_SIZE(tct_hammer_iodesc)); - s3c24xx_init_clocks(0); s3c24xx_init_uarts(tct_hammer_uartcfgs, ARRAY_SIZE(tct_hammer_uartcfgs)); samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4); } +static void __init tct_hammer_init_time(void) +{ + s3c2410_init_clocks(12000000); + samsung_timer_init(); +} + static void __init tct_hammer_init(void) { s3c_i2c0_set_platdata(NULL); @@ -151,6 +156,6 @@ MACHINE_START(TCT_HAMMER, "TCT_HAMMER") .map_io = tct_hammer_map_io, .init_irq = s3c2410_init_irq, .init_machine = tct_hammer_init, - .init_time = samsung_timer_init, + .init_time = tct_hammer_init_time, .restart = s3c2410_restart, MACHINE_END diff --git a/arch/arm/mach-s3c24xx/mach-vr1000.c b/arch/arm/mach-s3c24xx/mach-vr1000.c index bedaeefdc9f0..5f588bf20f43 100644 --- a/arch/arm/mach-s3c24xx/mach-vr1000.c +++ b/arch/arm/mach-s3c24xx/mach-vr1000.c @@ -43,7 +43,6 @@ #include #include -#include #include #include #include @@ -337,11 +336,16 @@ static void __init vr1000_map_io(void) pm_power_off = vr1000_power_off; s3c24xx_init_io(vr1000_iodesc, ARRAY_SIZE(vr1000_iodesc)); - s3c24xx_init_clocks(0); s3c24xx_init_uarts(vr1000_uartcfgs, ARRAY_SIZE(vr1000_uartcfgs)); samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4); } +static void __init vr1000_init_time(void) +{ + s3c2410_init_clocks(12000000); + samsung_timer_init(); +} + static void __init vr1000_init(void) { s3c_i2c0_set_platdata(NULL); @@ -362,6 +366,6 @@ MACHINE_START(VR1000, "Thorcom-VR1000") .map_io = vr1000_map_io, .init_machine = vr1000_init, .init_irq = s3c2410_init_irq, - .init_time = samsung_timer_init, + .init_time = vr1000_init_time, .restart = s3c2410_restart, MACHINE_END From defd9da51d1a472ffa7a92ba71ffa07839bdc1a3 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Fri, 9 May 2014 05:49:36 +0900 Subject: [PATCH 53/87] ARM: S3C24XX: remove legacy clock code With the move to the common clock framework completed for s3c2410, s3c2440 and s3c2442, the legacy clock code for these machines can go away too. This also includes the legacy dclk code, as all legacy users are converted. Signed-off-by: Heiko Stuebner Reviewed-by: Tomasz Figa Signed-off-by: Kukjin Kim --- arch/arm/mach-s3c24xx/Kconfig | 11 - arch/arm/mach-s3c24xx/Makefile | 2 - arch/arm/mach-s3c24xx/clock-dclk.c | 195 ------------ arch/arm/mach-s3c24xx/clock-s3c2410.c | 284 ------------------ arch/arm/mach-s3c24xx/clock-s3c2440.c | 217 ------------- arch/arm/mach-s3c24xx/clock-s3c244x.c | 141 --------- arch/arm/mach-s3c24xx/common.h | 2 - .../mach-s3c24xx/include/mach/regs-clock.h | 18 -- .../arm/mach-s3c24xx/include/mach/regs-gpio.h | 3 - arch/arm/mach-s3c24xx/pm.c | 12 - arch/arm/mach-s3c24xx/s3c2410.c | 62 ---- arch/arm/mach-s3c24xx/s3c2442.c | 112 ------- arch/arm/mach-s3c24xx/s3c244x.c | 63 ---- 13 files changed, 1122 deletions(-) delete mode 100644 arch/arm/mach-s3c24xx/clock-dclk.c delete mode 100644 arch/arm/mach-s3c24xx/clock-s3c2410.c delete mode 100644 arch/arm/mach-s3c24xx/clock-s3c2440.c delete mode 100644 arch/arm/mach-s3c24xx/clock-s3c244x.c diff --git a/arch/arm/mach-s3c24xx/Kconfig b/arch/arm/mach-s3c24xx/Kconfig index 23968c661415..f9bb1ea14fe4 100644 --- a/arch/arm/mach-s3c24xx/Kconfig +++ b/arch/arm/mach-s3c24xx/Kconfig @@ -110,17 +110,6 @@ config CPU_S3C2443 # common code -config S3C2410_CLOCK - bool - help - Clock code for the S3C2410, and similar processors which - is currently includes the S3C2410, S3C2440, S3C2442. - -config S3C24XX_DCLK - bool - help - Clock code for supporting DCLK/CLKOUT on S3C24XX architectures - config S3C24XX_SMDK bool help diff --git a/arch/arm/mach-s3c24xx/Makefile b/arch/arm/mach-s3c24xx/Makefile index 9010ebaafff6..2235d0d3b38d 100644 --- a/arch/arm/mach-s3c24xx/Makefile +++ b/arch/arm/mach-s3c24xx/Makefile @@ -44,10 +44,8 @@ obj-$(CONFIG_PM) += pm.o irq-pm.o sleep.o # common code -obj-$(CONFIG_S3C24XX_DCLK) += clock-dclk.o obj-$(CONFIG_S3C24XX_DMA) += dma.o -obj-$(CONFIG_S3C2410_CLOCK) += clock-s3c2410.o obj-$(CONFIG_S3C2410_CPUFREQ_UTILS) += cpufreq-utils.o obj-$(CONFIG_S3C2410_IOTIMING) += iotiming-s3c2410.o diff --git a/arch/arm/mach-s3c24xx/clock-dclk.c b/arch/arm/mach-s3c24xx/clock-dclk.c deleted file mode 100644 index 1edd9b2369c5..000000000000 --- a/arch/arm/mach-s3c24xx/clock-dclk.c +++ /dev/null @@ -1,195 +0,0 @@ -/* - * Copyright (c) 2004-2008 Simtec Electronics - * Ben Dooks - * http://armlinux.simtec.co.uk/ - * - * 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. - * - * S3C24XX - definitions for DCLK and CLKOUT registers - */ - -#include -#include -#include -#include - -#include -#include - -#include -#include - -/* clocks that could be registered by external code */ - -static int s3c24xx_dclk_enable(struct clk *clk, int enable) -{ - unsigned long dclkcon = __raw_readl(S3C24XX_DCLKCON); - - if (enable) - dclkcon |= clk->ctrlbit; - else - dclkcon &= ~clk->ctrlbit; - - __raw_writel(dclkcon, S3C24XX_DCLKCON); - - return 0; -} - -static int s3c24xx_dclk_setparent(struct clk *clk, struct clk *parent) -{ - unsigned long dclkcon; - unsigned int uclk; - - if (parent == &clk_upll) - uclk = 1; - else if (parent == &clk_p) - uclk = 0; - else - return -EINVAL; - - clk->parent = parent; - - dclkcon = __raw_readl(S3C24XX_DCLKCON); - - if (clk->ctrlbit == S3C2410_DCLKCON_DCLK0EN) { - if (uclk) - dclkcon |= S3C2410_DCLKCON_DCLK0_UCLK; - else - dclkcon &= ~S3C2410_DCLKCON_DCLK0_UCLK; - } else { - if (uclk) - dclkcon |= S3C2410_DCLKCON_DCLK1_UCLK; - else - dclkcon &= ~S3C2410_DCLKCON_DCLK1_UCLK; - } - - __raw_writel(dclkcon, S3C24XX_DCLKCON); - - return 0; -} -static unsigned long s3c24xx_calc_div(struct clk *clk, unsigned long rate) -{ - unsigned long div; - - if ((rate == 0) || !clk->parent) - return 0; - - div = clk_get_rate(clk->parent) / rate; - if (div < 2) - div = 2; - else if (div > 16) - div = 16; - - return div; -} - -static unsigned long s3c24xx_round_dclk_rate(struct clk *clk, - unsigned long rate) -{ - unsigned long div = s3c24xx_calc_div(clk, rate); - - if (div == 0) - return 0; - - return clk_get_rate(clk->parent) / div; -} - -static int s3c24xx_set_dclk_rate(struct clk *clk, unsigned long rate) -{ - unsigned long mask, data, div = s3c24xx_calc_div(clk, rate); - - if (div == 0) - return -EINVAL; - - if (clk == &s3c24xx_dclk0) { - mask = S3C2410_DCLKCON_DCLK0_DIV_MASK | - S3C2410_DCLKCON_DCLK0_CMP_MASK; - data = S3C2410_DCLKCON_DCLK0_DIV(div) | - S3C2410_DCLKCON_DCLK0_CMP((div + 1) / 2); - } else if (clk == &s3c24xx_dclk1) { - mask = S3C2410_DCLKCON_DCLK1_DIV_MASK | - S3C2410_DCLKCON_DCLK1_CMP_MASK; - data = S3C2410_DCLKCON_DCLK1_DIV(div) | - S3C2410_DCLKCON_DCLK1_CMP((div + 1) / 2); - } else - return -EINVAL; - - clk->rate = clk_get_rate(clk->parent) / div; - __raw_writel(((__raw_readl(S3C24XX_DCLKCON) & ~mask) | data), - S3C24XX_DCLKCON); - return clk->rate; -} -static int s3c24xx_clkout_setparent(struct clk *clk, struct clk *parent) -{ - unsigned long mask; - unsigned long source; - - /* calculate the MISCCR setting for the clock */ - - if (parent == &clk_mpll) - source = S3C2410_MISCCR_CLK0_MPLL; - else if (parent == &clk_upll) - source = S3C2410_MISCCR_CLK0_UPLL; - else if (parent == &clk_f) - source = S3C2410_MISCCR_CLK0_FCLK; - else if (parent == &clk_h) - source = S3C2410_MISCCR_CLK0_HCLK; - else if (parent == &clk_p) - source = S3C2410_MISCCR_CLK0_PCLK; - else if (clk == &s3c24xx_clkout0 && parent == &s3c24xx_dclk0) - source = S3C2410_MISCCR_CLK0_DCLK0; - else if (clk == &s3c24xx_clkout1 && parent == &s3c24xx_dclk1) - source = S3C2410_MISCCR_CLK0_DCLK0; - else - return -EINVAL; - - clk->parent = parent; - - if (clk == &s3c24xx_clkout0) - mask = S3C2410_MISCCR_CLK0_MASK; - else { - source <<= 4; - mask = S3C2410_MISCCR_CLK1_MASK; - } - - s3c2410_modify_misccr(mask, source); - return 0; -} - -/* external clock definitions */ - -static struct clk_ops dclk_ops = { - .set_parent = s3c24xx_dclk_setparent, - .set_rate = s3c24xx_set_dclk_rate, - .round_rate = s3c24xx_round_dclk_rate, -}; - -struct clk s3c24xx_dclk0 = { - .name = "dclk0", - .ctrlbit = S3C2410_DCLKCON_DCLK0EN, - .enable = s3c24xx_dclk_enable, - .ops = &dclk_ops, -}; - -struct clk s3c24xx_dclk1 = { - .name = "dclk1", - .ctrlbit = S3C2410_DCLKCON_DCLK1EN, - .enable = s3c24xx_dclk_enable, - .ops = &dclk_ops, -}; - -static struct clk_ops clkout_ops = { - .set_parent = s3c24xx_clkout_setparent, -}; - -struct clk s3c24xx_clkout0 = { - .name = "clkout0", - .ops = &clkout_ops, -}; - -struct clk s3c24xx_clkout1 = { - .name = "clkout1", - .ops = &clkout_ops, -}; diff --git a/arch/arm/mach-s3c24xx/clock-s3c2410.c b/arch/arm/mach-s3c24xx/clock-s3c2410.c deleted file mode 100644 index d1afcf9252d1..000000000000 --- a/arch/arm/mach-s3c24xx/clock-s3c2410.c +++ /dev/null @@ -1,284 +0,0 @@ -/* - * Copyright (c) 2006 Simtec Electronics - * Ben Dooks - * - * S3C2410,S3C2440,S3C2442 Clock control support - * - * 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include - -#include -#include - -int s3c2410_clkcon_enable(struct clk *clk, int enable) -{ - unsigned int clocks = clk->ctrlbit; - unsigned long clkcon; - - clkcon = __raw_readl(S3C2410_CLKCON); - - if (enable) - clkcon |= clocks; - else - clkcon &= ~clocks; - - /* ensure none of the special function bits set */ - clkcon &= ~(S3C2410_CLKCON_IDLE|S3C2410_CLKCON_POWER); - - __raw_writel(clkcon, S3C2410_CLKCON); - - return 0; -} - -static int s3c2410_upll_enable(struct clk *clk, int enable) -{ - unsigned long clkslow = __raw_readl(S3C2410_CLKSLOW); - unsigned long orig = clkslow; - - if (enable) - clkslow &= ~S3C2410_CLKSLOW_UCLK_OFF; - else - clkslow |= S3C2410_CLKSLOW_UCLK_OFF; - - __raw_writel(clkslow, S3C2410_CLKSLOW); - - /* if we started the UPLL, then allow to settle */ - - if (enable && (orig & S3C2410_CLKSLOW_UCLK_OFF)) - udelay(200); - - return 0; -} - -/* standard clock definitions */ - -static struct clk init_clocks_off[] = { - { - .name = "nand", - .parent = &clk_h, - .enable = s3c2410_clkcon_enable, - .ctrlbit = S3C2410_CLKCON_NAND, - }, { - .name = "sdi", - .parent = &clk_p, - .enable = s3c2410_clkcon_enable, - .ctrlbit = S3C2410_CLKCON_SDI, - }, { - .name = "adc", - .parent = &clk_p, - .enable = s3c2410_clkcon_enable, - .ctrlbit = S3C2410_CLKCON_ADC, - }, { - .name = "i2c", - .parent = &clk_p, - .enable = s3c2410_clkcon_enable, - .ctrlbit = S3C2410_CLKCON_IIC, - }, { - .name = "iis", - .parent = &clk_p, - .enable = s3c2410_clkcon_enable, - .ctrlbit = S3C2410_CLKCON_IIS, - }, { - .name = "spi", - .parent = &clk_p, - .enable = s3c2410_clkcon_enable, - .ctrlbit = S3C2410_CLKCON_SPI, - } -}; - -static struct clk clk_lcd = { - .name = "lcd", - .parent = &clk_h, - .enable = s3c2410_clkcon_enable, - .ctrlbit = S3C2410_CLKCON_LCDC, -}; - -static struct clk clk_gpio = { - .name = "gpio", - .parent = &clk_p, - .enable = s3c2410_clkcon_enable, - .ctrlbit = S3C2410_CLKCON_GPIO, -}; - -static struct clk clk_usb_host = { - .name = "usb-host", - .parent = &clk_h, - .enable = s3c2410_clkcon_enable, - .ctrlbit = S3C2410_CLKCON_USBH, -}; - -static struct clk clk_usb_device = { - .name = "usb-device", - .parent = &clk_h, - .enable = s3c2410_clkcon_enable, - .ctrlbit = S3C2410_CLKCON_USBD, -}; - -static struct clk clk_timers = { - .name = "timers", - .parent = &clk_p, - .enable = s3c2410_clkcon_enable, - .ctrlbit = S3C2410_CLKCON_PWMT, -}; - -struct clk s3c24xx_clk_uart0 = { - .name = "uart", - .devname = "s3c2410-uart.0", - .parent = &clk_p, - .enable = s3c2410_clkcon_enable, - .ctrlbit = S3C2410_CLKCON_UART0, -}; - -struct clk s3c24xx_clk_uart1 = { - .name = "uart", - .devname = "s3c2410-uart.1", - .parent = &clk_p, - .enable = s3c2410_clkcon_enable, - .ctrlbit = S3C2410_CLKCON_UART1, -}; - -struct clk s3c24xx_clk_uart2 = { - .name = "uart", - .devname = "s3c2410-uart.2", - .parent = &clk_p, - .enable = s3c2410_clkcon_enable, - .ctrlbit = S3C2410_CLKCON_UART2, -}; - -static struct clk clk_rtc = { - .name = "rtc", - .parent = &clk_p, - .enable = s3c2410_clkcon_enable, - .ctrlbit = S3C2410_CLKCON_RTC, -}; - -static struct clk clk_watchdog = { - .name = "watchdog", - .parent = &clk_p, - .ctrlbit = 0, -}; - -static struct clk clk_usb_bus_host = { - .name = "usb-bus-host", - .parent = &clk_usb_bus, -}; - -static struct clk clk_usb_bus_gadget = { - .name = "usb-bus-gadget", - .parent = &clk_usb_bus, -}; - -static struct clk *init_clocks[] = { - &clk_lcd, - &clk_gpio, - &clk_usb_host, - &clk_usb_device, - &clk_timers, - &s3c24xx_clk_uart0, - &s3c24xx_clk_uart1, - &s3c24xx_clk_uart2, - &clk_rtc, - &clk_watchdog, - &clk_usb_bus_host, - &clk_usb_bus_gadget, -}; - -/* s3c2410_baseclk_add() - * - * Add all the clocks used by the s3c2410 or compatible CPUs - * such as the S3C2440 and S3C2442. - * - * We cannot use a system device as we are needed before any - * of the init-calls that initialise the devices are actually - * done. -*/ - -int __init s3c2410_baseclk_add(void) -{ - unsigned long clkslow = __raw_readl(S3C2410_CLKSLOW); - unsigned long clkcon = __raw_readl(S3C2410_CLKCON); - struct clk *xtal; - int ret; - int ptr; - - clk_upll.enable = s3c2410_upll_enable; - - if (s3c24xx_register_clock(&clk_usb_bus) < 0) - printk(KERN_ERR "failed to register usb bus clock\n"); - - /* register clocks from clock array */ - - for (ptr = 0; ptr < ARRAY_SIZE(init_clocks); ptr++) { - struct clk *clkp = init_clocks[ptr]; - - /* ensure that we note the clock state */ - - clkp->usage = clkcon & clkp->ctrlbit ? 1 : 0; - - ret = s3c24xx_register_clock(clkp); - if (ret < 0) { - printk(KERN_ERR "Failed to register clock %s (%d)\n", - clkp->name, ret); - } - } - - /* We must be careful disabling the clocks we are not intending to - * be using at boot time, as subsystems such as the LCD which do - * their own DMA requests to the bus can cause the system to lockup - * if they where in the middle of requesting bus access. - * - * Disabling the LCD clock if the LCD is active is very dangerous, - * and therefore the bootloader should be careful to not enable - * the LCD clock if it is not needed. - */ - - /* install (and disable) the clocks we do not need immediately */ - - s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off)); - s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off)); - - /* show the clock-slow value */ - - xtal = clk_get(NULL, "xtal"); - - printk("CLOCK: Slow mode (%ld.%ld MHz), %s, MPLL %s, UPLL %s\n", - print_mhz(clk_get_rate(xtal) / - ( 2 * S3C2410_CLKSLOW_GET_SLOWVAL(clkslow))), - (clkslow & S3C2410_CLKSLOW_SLOW) ? "slow" : "fast", - (clkslow & S3C2410_CLKSLOW_MPLL_OFF) ? "off" : "on", - (clkslow & S3C2410_CLKSLOW_UCLK_OFF) ? "off" : "on"); - - return 0; -} diff --git a/arch/arm/mach-s3c24xx/clock-s3c2440.c b/arch/arm/mach-s3c24xx/clock-s3c2440.c deleted file mode 100644 index 5527226fd61f..000000000000 --- a/arch/arm/mach-s3c24xx/clock-s3c2440.c +++ /dev/null @@ -1,217 +0,0 @@ -/* linux/arch/arm/mach-s3c2440/clock.c - * - * Copyright (c) 2004-2005 Simtec Electronics - * http://armlinux.simtec.co.uk/ - * Ben Dooks - * - * S3C2440 Clock support - * - * 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include - -#include -#include - -/* S3C2440 extended clock support */ - -static unsigned long s3c2440_camif_upll_round(struct clk *clk, - unsigned long rate) -{ - unsigned long parent_rate = clk_get_rate(clk->parent); - int div; - - if (rate > parent_rate) - return parent_rate; - - /* note, we remove the +/- 1 calculations for the divisor */ - - div = (parent_rate / rate) / 2; - - if (div < 1) - div = 1; - else if (div > 16) - div = 16; - - return parent_rate / (div * 2); -} - -static int s3c2440_camif_upll_setrate(struct clk *clk, unsigned long rate) -{ - unsigned long parent_rate = clk_get_rate(clk->parent); - unsigned long camdivn = __raw_readl(S3C2440_CAMDIVN); - - rate = s3c2440_camif_upll_round(clk, rate); - - camdivn &= ~(S3C2440_CAMDIVN_CAMCLK_SEL | S3C2440_CAMDIVN_CAMCLK_MASK); - - if (rate != parent_rate) { - camdivn |= S3C2440_CAMDIVN_CAMCLK_SEL; - camdivn |= (((parent_rate / rate) / 2) - 1); - } - - __raw_writel(camdivn, S3C2440_CAMDIVN); - - return 0; -} - -static unsigned long s3c2440_camif_upll_getrate(struct clk *clk) -{ - unsigned long parent_rate = clk_get_rate(clk->parent); - unsigned long camdivn = __raw_readl(S3C2440_CAMDIVN); - - if (!(camdivn & S3C2440_CAMDIVN_CAMCLK_SEL)) - return parent_rate; - - camdivn &= S3C2440_CAMDIVN_CAMCLK_MASK; - - return parent_rate / (camdivn + 1) / 2; -} - -/* Extra S3C2440 clocks */ - -static struct clk s3c2440_clk_cam = { - .name = "camif", - .enable = s3c2410_clkcon_enable, - .ctrlbit = S3C2440_CLKCON_CAMERA, -}; - -static struct clk s3c2440_clk_cam_upll = { - .name = "camif-upll", - .ops = &(struct clk_ops) { - .set_rate = s3c2440_camif_upll_setrate, - .get_rate = s3c2440_camif_upll_getrate, - .round_rate = s3c2440_camif_upll_round, - }, -}; - -static struct clk s3c2440_clk_ac97 = { - .name = "ac97", - .enable = s3c2410_clkcon_enable, - .ctrlbit = S3C2440_CLKCON_AC97, -}; - -#define S3C24XX_VA_UART0 (S3C_VA_UART) -#define S3C24XX_VA_UART1 (S3C_VA_UART + 0x4000 ) -#define S3C24XX_VA_UART2 (S3C_VA_UART + 0x8000 ) -#define S3C24XX_VA_UART3 (S3C_VA_UART + 0xC000 ) - -static unsigned long s3c2440_fclk_n_getrate(struct clk *clk) -{ - unsigned long ucon0, ucon1, ucon2, divisor; - - /* the fun of calculating the uart divisors on the s3c2440 */ - ucon0 = __raw_readl(S3C24XX_VA_UART0 + S3C2410_UCON); - ucon1 = __raw_readl(S3C24XX_VA_UART1 + S3C2410_UCON); - ucon2 = __raw_readl(S3C24XX_VA_UART2 + S3C2410_UCON); - - ucon0 &= S3C2440_UCON0_DIVMASK; - ucon1 &= S3C2440_UCON1_DIVMASK; - ucon2 &= S3C2440_UCON2_DIVMASK; - - if (ucon0 != 0) - divisor = (ucon0 >> S3C2440_UCON_DIVSHIFT) + 6; - else if (ucon1 != 0) - divisor = (ucon1 >> S3C2440_UCON_DIVSHIFT) + 21; - else if (ucon2 != 0) - divisor = (ucon2 >> S3C2440_UCON_DIVSHIFT) + 36; - else - /* manual calims 44, seems to be 9 */ - divisor = 9; - - return clk_get_rate(clk->parent) / divisor; -} - -static struct clk s3c2440_clk_fclk_n = { - .name = "fclk_n", - .parent = &clk_f, - .ops = &(struct clk_ops) { - .get_rate = s3c2440_fclk_n_getrate, - }, -}; - -static struct clk_lookup s3c2440_clk_lookup[] = { - CLKDEV_INIT(NULL, "clk_uart_baud1", &s3c24xx_uclk), - CLKDEV_INIT(NULL, "clk_uart_baud2", &clk_p), - CLKDEV_INIT(NULL, "clk_uart_baud3", &s3c2440_clk_fclk_n), - CLKDEV_INIT("s3c2440-uart.0", "uart", &s3c24xx_clk_uart0), - CLKDEV_INIT("s3c2440-uart.1", "uart", &s3c24xx_clk_uart1), - CLKDEV_INIT("s3c2440-uart.2", "uart", &s3c24xx_clk_uart2), - CLKDEV_INIT("s3c2440-camif", "camera", &s3c2440_clk_cam_upll), -}; - -static int __init_refok s3c2440_clk_add(struct device *dev, struct subsys_interface *sif) -{ - struct clk *clock_upll; - struct clk *clock_h; - struct clk *clock_p; - - clock_p = clk_get(NULL, "pclk"); - clock_h = clk_get(NULL, "hclk"); - clock_upll = clk_get(NULL, "upll"); - - if (IS_ERR(clock_p) || IS_ERR(clock_h) || IS_ERR(clock_upll)) { - printk(KERN_ERR "S3C2440: Failed to get parent clocks\n"); - return -EINVAL; - } - - s3c2440_clk_cam.parent = clock_h; - s3c2440_clk_ac97.parent = clock_p; - s3c2440_clk_cam_upll.parent = clock_upll; - s3c24xx_register_clock(&s3c2440_clk_fclk_n); - - s3c24xx_register_clock(&s3c2440_clk_ac97); - s3c24xx_register_clock(&s3c2440_clk_cam); - s3c24xx_register_clock(&s3c2440_clk_cam_upll); - clkdev_add_table(s3c2440_clk_lookup, ARRAY_SIZE(s3c2440_clk_lookup)); - - clk_disable(&s3c2440_clk_ac97); - clk_disable(&s3c2440_clk_cam); - - return 0; -} - -static struct subsys_interface s3c2440_clk_interface = { - .name = "s3c2440_clk", - .subsys = &s3c2440_subsys, - .add_dev = s3c2440_clk_add, -}; - -static __init int s3c24xx_clk_init(void) -{ - return subsys_interface_register(&s3c2440_clk_interface); -} - -arch_initcall(s3c24xx_clk_init); diff --git a/arch/arm/mach-s3c24xx/clock-s3c244x.c b/arch/arm/mach-s3c24xx/clock-s3c244x.c deleted file mode 100644 index 6d9b688c442b..000000000000 --- a/arch/arm/mach-s3c24xx/clock-s3c244x.c +++ /dev/null @@ -1,141 +0,0 @@ -/* linux/arch/arm/plat-s3c24xx/s3c24xx-clock.c - * - * Copyright (c) 2004-2008 Simtec Electronics - * http://armlinux.simtec.co.uk/ - * Ben Dooks - * - * S3C2440/S3C2442 Common clock support - * - * 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include - -#include -#include - -static int s3c2440_setparent_armclk(struct clk *clk, struct clk *parent) -{ - unsigned long camdivn; - unsigned long dvs; - - if (parent == &clk_f) - dvs = 0; - else if (parent == &clk_h) - dvs = S3C2440_CAMDIVN_DVSEN; - else - return -EINVAL; - - clk->parent = parent; - - camdivn = __raw_readl(S3C2440_CAMDIVN); - camdivn &= ~S3C2440_CAMDIVN_DVSEN; - camdivn |= dvs; - __raw_writel(camdivn, S3C2440_CAMDIVN); - - return 0; -} - -static struct clk clk_arm = { - .name = "armclk", - .id = -1, - .ops = &(struct clk_ops) { - .set_parent = s3c2440_setparent_armclk, - }, -}; - -static int s3c244x_clk_add(struct device *dev, struct subsys_interface *sif) -{ - unsigned long camdivn = __raw_readl(S3C2440_CAMDIVN); - unsigned long clkdivn; - struct clk *clock_upll; - int ret; - - printk("S3C244X: Clock Support, DVS %s\n", - (camdivn & S3C2440_CAMDIVN_DVSEN) ? "on" : "off"); - - clk_arm.parent = (camdivn & S3C2440_CAMDIVN_DVSEN) ? &clk_h : &clk_f; - - ret = s3c24xx_register_clock(&clk_arm); - if (ret < 0) { - printk(KERN_ERR "S3C24XX: Failed to add armclk (%d)\n", ret); - return ret; - } - - clock_upll = clk_get(NULL, "upll"); - if (IS_ERR(clock_upll)) { - printk(KERN_ERR "S3C244X: Failed to get upll clock\n"); - return -ENOENT; - } - - /* check rate of UPLL, and if it is near 96MHz, then change - * to using half the UPLL rate for the system */ - - if (clk_get_rate(clock_upll) > (94 * MHZ)) { - clk_usb_bus.rate = clk_get_rate(clock_upll) / 2; - - spin_lock(&clocks_lock); - - clkdivn = __raw_readl(S3C2410_CLKDIVN); - clkdivn |= S3C2440_CLKDIVN_UCLK; - __raw_writel(clkdivn, S3C2410_CLKDIVN); - - spin_unlock(&clocks_lock); - } - - return 0; -} - -static struct subsys_interface s3c2440_clk_interface = { - .name = "s3c2440_clk", - .subsys = &s3c2440_subsys, - .add_dev = s3c244x_clk_add, -}; - -static int s3c2440_clk_init(void) -{ - return subsys_interface_register(&s3c2440_clk_interface); -} - -arch_initcall(s3c2440_clk_init); - -static struct subsys_interface s3c2442_clk_interface = { - .name = "s3c2442_clk", - .subsys = &s3c2442_subsys, - .add_dev = s3c244x_clk_add, -}; - -static int s3c2442_clk_init(void) -{ - return subsys_interface_register(&s3c2442_clk_interface); -} - -arch_initcall(s3c2442_clk_init); diff --git a/arch/arm/mach-s3c24xx/common.h b/arch/arm/mach-s3c24xx/common.h index 2d6554140161..ac3ff12a0601 100644 --- a/arch/arm/mach-s3c24xx/common.h +++ b/arch/arm/mach-s3c24xx/common.h @@ -67,10 +67,8 @@ extern struct syscore_ops s3c2416_irq_syscore_ops; #if defined(CONFIG_CPU_S3C2440) || defined(CONFIG_CPU_S3C2442) extern void s3c244x_map_io(void); extern void s3c244x_init_uarts(struct s3c2410_uartcfg *cfg, int no); -extern void s3c244x_init_clocks(int xtal); extern void s3c244x_restart(enum reboot_mode mode, const char *cmd); #else -#define s3c244x_init_clocks NULL #define s3c244x_init_uarts NULL #endif diff --git a/arch/arm/mach-s3c24xx/include/mach/regs-clock.h b/arch/arm/mach-s3c24xx/include/mach/regs-clock.h index 3415b60082d7..3db6c10de023 100644 --- a/arch/arm/mach-s3c24xx/include/mach/regs-clock.h +++ b/arch/arm/mach-s3c24xx/include/mach/regs-clock.h @@ -42,24 +42,6 @@ #define S3C2410_CLKCON_IIS (1<<17) #define S3C2410_CLKCON_SPI (1<<18) -/* DCLKCON register addresses in gpio.h */ - -#define S3C2410_DCLKCON_DCLK0EN (1<<0) -#define S3C2410_DCLKCON_DCLK0_PCLK (0<<1) -#define S3C2410_DCLKCON_DCLK0_UCLK (1<<1) -#define S3C2410_DCLKCON_DCLK0_DIV(x) (((x) - 1 )<<4) -#define S3C2410_DCLKCON_DCLK0_CMP(x) (((x) - 1 )<<8) -#define S3C2410_DCLKCON_DCLK0_DIV_MASK ((0xf)<<4) -#define S3C2410_DCLKCON_DCLK0_CMP_MASK ((0xf)<<8) - -#define S3C2410_DCLKCON_DCLK1EN (1<<16) -#define S3C2410_DCLKCON_DCLK1_PCLK (0<<17) -#define S3C2410_DCLKCON_DCLK1_UCLK (1<<17) -#define S3C2410_DCLKCON_DCLK1_DIV(x) (((x) - 1) <<20) -#define S3C2410_DCLKCON_DCLK1_CMP(x) (((x) - 1) <<24) -#define S3C2410_DCLKCON_DCLK1_DIV_MASK ((0xf) <<20) -#define S3C2410_DCLKCON_DCLK1_CMP_MASK ((0xf) <<24) - #define S3C2410_CLKDIVN_PDIVN (1<<0) #define S3C2410_CLKDIVN_HDIVN (1<<1) diff --git a/arch/arm/mach-s3c24xx/include/mach/regs-gpio.h b/arch/arm/mach-s3c24xx/include/mach/regs-gpio.h index c2ef016032ab..c6583cfa5835 100644 --- a/arch/arm/mach-s3c24xx/include/mach/regs-gpio.h +++ b/arch/arm/mach-s3c24xx/include/mach/regs-gpio.h @@ -457,9 +457,6 @@ /* miscellaneous control */ #define S3C2410_MISCCR S3C2410_GPIOREG(0x80) -#define S3C2410_DCLKCON S3C2410_GPIOREG(0x84) - -#define S3C24XX_DCLKCON S3C24XX_GPIOREG2(0x84) /* see clock.h for dclk definitions */ diff --git a/arch/arm/mach-s3c24xx/pm.c b/arch/arm/mach-s3c24xx/pm.c index 16281bdc750a..3d8cf3054e7f 100644 --- a/arch/arm/mach-s3c24xx/pm.c +++ b/arch/arm/mach-s3c24xx/pm.c @@ -80,12 +80,6 @@ static struct sleep_save core_save[] = { #endif /* CONFIG_SAMSUNG_CLOCK */ }; -#ifdef CONFIG_SAMSUNG_CLOCK -static struct sleep_save misc_save[] = { - SAVE_ITEM(S3C2410_DCLKCON), -}; -#endif - /* s3c_pm_check_resume_pin * * check to see if the pin is configured correctly for sleep mode, and @@ -143,16 +137,10 @@ void s3c_pm_configure_extint(void) void s3c_pm_restore_core(void) { s3c_pm_do_restore_core(core_save, ARRAY_SIZE(core_save)); -#ifdef CONFIG_SAMSUNG_CLOCK - s3c_pm_do_restore(misc_save, ARRAY_SIZE(misc_save)); -#endif } void s3c_pm_save_core(void) { -#ifdef CONFIG_SAMSUNG_CLOCK - s3c_pm_do_save(misc_save, ARRAY_SIZE(misc_save)); -#endif s3c_pm_do_save(core_save, ARRAY_SIZE(core_save)); } diff --git a/arch/arm/mach-s3c24xx/s3c2410.c b/arch/arm/mach-s3c24xx/s3c2410.c index 52801730ab24..7eab88829883 100644 --- a/arch/arm/mach-s3c24xx/s3c2410.c +++ b/arch/arm/mach-s3c24xx/s3c2410.c @@ -83,71 +83,9 @@ void __init s3c2410_map_io(void) iotable_init(s3c2410_iodesc, ARRAY_SIZE(s3c2410_iodesc)); } -#ifdef CONFIG_SAMSUNG_CLOCK -void __init_or_cpufreq s3c2410_setup_clocks(void) -{ - struct clk *xtal_clk; - unsigned long tmp; - unsigned long xtal; - unsigned long fclk; - unsigned long hclk; - unsigned long pclk; - - xtal_clk = clk_get(NULL, "xtal"); - xtal = clk_get_rate(xtal_clk); - clk_put(xtal_clk); - - /* now we've got our machine bits initialised, work out what - * clocks we've got */ - - fclk = s3c24xx_get_pll(__raw_readl(S3C2410_MPLLCON), xtal); - - tmp = __raw_readl(S3C2410_CLKDIVN); - - /* work out clock scalings */ - - hclk = fclk / ((tmp & S3C2410_CLKDIVN_HDIVN) ? 2 : 1); - pclk = hclk / ((tmp & S3C2410_CLKDIVN_PDIVN) ? 2 : 1); - - /* print brieft summary of clocks, etc */ - - printk("S3C2410: core %ld.%03ld MHz, memory %ld.%03ld MHz, peripheral %ld.%03ld MHz\n", - print_mhz(fclk), print_mhz(hclk), print_mhz(pclk)); - - /* initialise the clocks here, to allow other things like the - * console to use them - */ - - s3c24xx_setup_clocks(fclk, hclk, pclk); -} - -/* fake ARMCLK for use with cpufreq, etc. */ - -static struct clk s3c2410_armclk = { - .name = "armclk", - .parent = &clk_f, - .id = -1, -}; - -static struct clk_lookup s3c2410_clk_lookup[] = { - CLKDEV_INIT(NULL, "clk_uart_baud0", &clk_p), - CLKDEV_INIT(NULL, "clk_uart_baud1", &s3c24xx_uclk), -}; - -void __init s3c2410_init_clocks(int xtal) -{ - s3c24xx_register_baseclocks(xtal); - s3c2410_setup_clocks(); - s3c2410_baseclk_add(); - s3c24xx_register_clock(&s3c2410_armclk); - clkdev_add_table(s3c2410_clk_lookup, ARRAY_SIZE(s3c2410_clk_lookup)); - samsung_wdt_reset_init(S3C24XX_VA_WATCHDOG); -} -#else void __init_or_cpufreq s3c2410_setup_clocks(void) { } -#endif struct bus_type s3c2410_subsys = { .name = "s3c2410-core", diff --git a/arch/arm/mach-s3c24xx/s3c2442.c b/arch/arm/mach-s3c24xx/s3c2442.c index 564c65037ff2..fb9da2b603a2 100644 --- a/arch/arm/mach-s3c24xx/s3c2442.c +++ b/arch/arm/mach-s3c24xx/s3c2442.c @@ -53,118 +53,6 @@ #include "common.h" -#ifdef CONFIG_SAMSUNG_CLOCK -/* S3C2442 extended clock support */ - -static unsigned long s3c2442_camif_upll_round(struct clk *clk, - unsigned long rate) -{ - unsigned long parent_rate = clk_get_rate(clk->parent); - int div; - - if (rate > parent_rate) - return parent_rate; - - div = parent_rate / rate; - - if (div == 3) - return parent_rate / 3; - - /* note, we remove the +/- 1 calculations for the divisor */ - - div /= 2; - - if (div < 1) - div = 1; - else if (div > 16) - div = 16; - - return parent_rate / (div * 2); -} - -static int s3c2442_camif_upll_setrate(struct clk *clk, unsigned long rate) -{ - unsigned long parent_rate = clk_get_rate(clk->parent); - unsigned long camdivn = __raw_readl(S3C2440_CAMDIVN); - - rate = s3c2442_camif_upll_round(clk, rate); - - camdivn &= ~S3C2442_CAMDIVN_CAMCLK_DIV3; - - if (rate == parent_rate) { - camdivn &= ~S3C2440_CAMDIVN_CAMCLK_SEL; - } else if ((parent_rate / rate) == 3) { - camdivn |= S3C2440_CAMDIVN_CAMCLK_SEL; - camdivn |= S3C2442_CAMDIVN_CAMCLK_DIV3; - } else { - camdivn &= ~S3C2440_CAMDIVN_CAMCLK_MASK; - camdivn |= S3C2440_CAMDIVN_CAMCLK_SEL; - camdivn |= (((parent_rate / rate) / 2) - 1); - } - - __raw_writel(camdivn, S3C2440_CAMDIVN); - - return 0; -} - -/* Extra S3C2442 clocks */ - -static struct clk s3c2442_clk_cam = { - .name = "camif", - .id = -1, - .enable = s3c2410_clkcon_enable, - .ctrlbit = S3C2440_CLKCON_CAMERA, -}; - -static struct clk s3c2442_clk_cam_upll = { - .name = "camif-upll", - .id = -1, - .ops = &(struct clk_ops) { - .set_rate = s3c2442_camif_upll_setrate, - .round_rate = s3c2442_camif_upll_round, - }, -}; - -static int s3c2442_clk_add(struct device *dev, struct subsys_interface *sif) -{ - struct clk *clock_upll; - struct clk *clock_h; - struct clk *clock_p; - - clock_p = clk_get(NULL, "pclk"); - clock_h = clk_get(NULL, "hclk"); - clock_upll = clk_get(NULL, "upll"); - - if (IS_ERR(clock_p) || IS_ERR(clock_h) || IS_ERR(clock_upll)) { - printk(KERN_ERR "S3C2442: Failed to get parent clocks\n"); - return -EINVAL; - } - - s3c2442_clk_cam.parent = clock_h; - s3c2442_clk_cam_upll.parent = clock_upll; - - s3c24xx_register_clock(&s3c2442_clk_cam); - s3c24xx_register_clock(&s3c2442_clk_cam_upll); - - clk_disable(&s3c2442_clk_cam); - - return 0; -} - -static struct subsys_interface s3c2442_clk_interface = { - .name = "s3c2442_clk", - .subsys = &s3c2442_subsys, - .add_dev = s3c2442_clk_add, -}; - -static __init int s3c2442_clk_init(void) -{ - return subsys_interface_register(&s3c2442_clk_interface); -} - -arch_initcall(s3c2442_clk_init); -#endif - static struct device s3c2442_dev = { .bus = &s3c2442_subsys, }; diff --git a/arch/arm/mach-s3c24xx/s3c244x.c b/arch/arm/mach-s3c24xx/s3c244x.c index 1d665d50b034..4a64bcc9eb51 100644 --- a/arch/arm/mach-s3c24xx/s3c244x.c +++ b/arch/arm/mach-s3c24xx/s3c244x.c @@ -78,72 +78,9 @@ void __init s3c244x_map_io(void) s3c2410_device_dclk.name = "s3c2440-dclk"; } -#ifdef CONFIG_SAMSUNG_CLOCK -void __init_or_cpufreq s3c244x_setup_clocks(void) -{ - struct clk *xtal_clk; - unsigned long clkdiv; - unsigned long camdiv; - unsigned long xtal; - unsigned long hclk, fclk, pclk; - int hdiv = 1; - - xtal_clk = clk_get(NULL, "xtal"); - xtal = clk_get_rate(xtal_clk); - clk_put(xtal_clk); - - fclk = s3c24xx_get_pll(__raw_readl(S3C2410_MPLLCON), xtal) * 2; - - clkdiv = __raw_readl(S3C2410_CLKDIVN); - camdiv = __raw_readl(S3C2440_CAMDIVN); - - /* work out clock scalings */ - - switch (clkdiv & S3C2440_CLKDIVN_HDIVN_MASK) { - case S3C2440_CLKDIVN_HDIVN_1: - hdiv = 1; - break; - - case S3C2440_CLKDIVN_HDIVN_2: - hdiv = 2; - break; - - case S3C2440_CLKDIVN_HDIVN_4_8: - hdiv = (camdiv & S3C2440_CAMDIVN_HCLK4_HALF) ? 8 : 4; - break; - - case S3C2440_CLKDIVN_HDIVN_3_6: - hdiv = (camdiv & S3C2440_CAMDIVN_HCLK3_HALF) ? 6 : 3; - break; - } - - hclk = fclk / hdiv; - pclk = hclk / ((clkdiv & S3C2440_CLKDIVN_PDIVN) ? 2 : 1); - - /* print brief summary of clocks, etc */ - - printk("S3C244X: core %ld.%03ld MHz, memory %ld.%03ld MHz, peripheral %ld.%03ld MHz\n", - print_mhz(fclk), print_mhz(hclk), print_mhz(pclk)); - - s3c24xx_setup_clocks(fclk, hclk, pclk); -} - -void __init s3c244x_init_clocks(int xtal) -{ - /* initialise the clocks here, to allow other things like the - * console to use them, and to add new ones after the initialisation - */ - - s3c24xx_register_baseclocks(xtal); - s3c244x_setup_clocks(); - s3c2410_baseclk_add(); - samsung_wdt_reset_init(S3C24XX_VA_WATCHDOG); -} -#else void __init_or_cpufreq s3c244x_setup_clocks(void) { } -#endif /* Since the S3C2442 and S3C2440 share items, put both subsystems here */ From 2916f9a2c6d9200b4c840a613cd1fa1dad04240f Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Fri, 9 May 2014 05:51:43 +0900 Subject: [PATCH 54/87] ARM: S3C24XX: remove SAMSUNG_CLOCK remnants after ccf conversion This finally removes all remaining SAMSUNG_CLOCK conditional code from s3c24xx architectures. Signed-off-by: Heiko Stuebner Signed-off-by: Kukjin Kim --- arch/arm/mach-s3c24xx/Kconfig | 3 --- arch/arm/mach-s3c24xx/common.c | 17 ----------------- arch/arm/mach-s3c24xx/cpufreq-utils.c | 6 ------ arch/arm/mach-s3c24xx/mach-anubis.c | 27 --------------------------- arch/arm/mach-s3c24xx/mach-bast.c | 27 --------------------------- arch/arm/mach-s3c24xx/mach-osiris.c | 27 --------------------------- arch/arm/mach-s3c24xx/mach-rx1950.c | 14 -------------- arch/arm/mach-s3c24xx/mach-vr1000.c | 27 --------------------------- arch/arm/mach-s3c24xx/pm.c | 12 ------------ 9 files changed, 160 deletions(-) diff --git a/arch/arm/mach-s3c24xx/Kconfig b/arch/arm/mach-s3c24xx/Kconfig index f9bb1ea14fe4..1331e784c713 100644 --- a/arch/arm/mach-s3c24xx/Kconfig +++ b/arch/arm/mach-s3c24xx/Kconfig @@ -266,7 +266,6 @@ config ARCH_BAST select MACH_BAST_IDE select S3C2410_COMMON_DCLK if COMMON_CLK select S3C2410_IOTIMING if ARM_S3C2410_CPUFREQ - select S3C24XX_DCLK if SAMSUNG_CLOCK select S3C24XX_SIMTEC_NOR select S3C24XX_SIMTEC_PM if PM select S3C24XX_SIMTEC_USB @@ -534,7 +533,6 @@ config MACH_ANUBIS select HAVE_PATA_PLATFORM select S3C2410_COMMON_DCLK if COMMON_CLK select S3C2440_XTAL_12000000 - select S3C24XX_DCLK if SAMSUNG_CLOCK select S3C24XX_SIMTEC_PM if PM select S3C_DEV_USB_HOST help @@ -575,7 +573,6 @@ config MACH_OSIRIS select S3C2410_COMMON_DCLK if COMMON_CLK select S3C2410_IOTIMING if ARM_S3C2440_CPUFREQ select S3C2440_XTAL_12000000 - select S3C24XX_DCLK if SAMSUNG_CLOCK select S3C24XX_SIMTEC_PM if PM select S3C_DEV_NAND select S3C_DEV_USB_HOST diff --git a/arch/arm/mach-s3c24xx/common.c b/arch/arm/mach-s3c24xx/common.c index 600a1be5696b..c0763b837745 100644 --- a/arch/arm/mach-s3c24xx/common.c +++ b/arch/arm/mach-s3c24xx/common.c @@ -307,23 +307,6 @@ struct s3c24xx_uart_resources s3c2410_uart_resources[] __initdata = { }, }; -/* initialise all the clocks */ - -#ifdef CONFIG_SAMSUNG_CLOCK -void __init_or_cpufreq s3c24xx_setup_clocks(unsigned long fclk, - unsigned long hclk, - unsigned long pclk) -{ - clk_upll.rate = s3c24xx_get_pll(__raw_readl(S3C2410_UPLLCON), - clk_xtal.rate); - - clk_mpll.rate = fclk; - clk_h.rate = hclk; - clk_p.rate = pclk; - clk_f.rate = fclk; -} -#endif - #if defined(CONFIG_CPU_S3C2410) || defined(CONFIG_CPU_S3C2412) || \ defined(CONFIG_CPU_S3C2440) || defined(CONFIG_CPU_S3C2442) static struct resource s3c2410_dma_resource[] = { diff --git a/arch/arm/mach-s3c24xx/cpufreq-utils.c b/arch/arm/mach-s3c24xx/cpufreq-utils.c index c1b7508523ad..d4d9514335f4 100644 --- a/arch/arm/mach-s3c24xx/cpufreq-utils.c +++ b/arch/arm/mach-s3c24xx/cpufreq-utils.c @@ -61,12 +61,6 @@ void s3c2410_cpufreq_setrefresh(struct s3c_cpufreq_config *cfg) */ void s3c2410_set_fvco(struct s3c_cpufreq_config *cfg) { -#ifdef CONFIG_SAMSUNG_CLOCK - __raw_writel(cfg->pll.driver_data, S3C2410_MPLLCON); -#endif - -#ifdef CONFIG_COMMON_CLK if (!IS_ERR(cfg->mpll)) clk_set_rate(cfg->mpll, cfg->pll.frequency); -#endif } diff --git a/arch/arm/mach-s3c24xx/mach-anubis.c b/arch/arm/mach-s3c24xx/mach-anubis.c index 7a0d83b2f93a..e053581cab0b 100644 --- a/arch/arm/mach-s3c24xx/mach-anubis.c +++ b/arch/arm/mach-s3c24xx/mach-anubis.c @@ -364,16 +364,6 @@ static struct platform_device *anubis_devices[] __initdata = { &anubis_device_sm501, }; -#ifdef CONFIG_SAMSUNG_CLOCK -static struct clk *anubis_clocks[] __initdata = { - &s3c24xx_dclk0, - &s3c24xx_dclk1, - &s3c24xx_clkout0, - &s3c24xx_clkout1, - &s3c24xx_uclk, -}; -#endif - /* I2C devices. */ static struct i2c_board_info anubis_i2c_devs[] __initdata = { @@ -396,23 +386,6 @@ static struct s3c24xx_audio_simtec_pdata __initdata anubis_audio = { static void __init anubis_map_io(void) { -#ifdef CONFIG_SAMSUNG_CLOCK - /* initialise the clocks */ - - s3c24xx_dclk0.parent = &clk_upll; - s3c24xx_dclk0.rate = 12*1000*1000; - - s3c24xx_dclk1.parent = &clk_upll; - s3c24xx_dclk1.rate = 24*1000*1000; - - s3c24xx_clkout0.parent = &s3c24xx_dclk0; - s3c24xx_clkout1.parent = &s3c24xx_dclk1; - - s3c24xx_uclk.parent = &s3c24xx_clkout1; - - s3c24xx_register_clocks(anubis_clocks, ARRAY_SIZE(anubis_clocks)); -#endif - s3c24xx_init_io(anubis_iodesc, ARRAY_SIZE(anubis_iodesc)); s3c24xx_init_uarts(anubis_uartcfgs, ARRAY_SIZE(anubis_uartcfgs)); samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4); diff --git a/arch/arm/mach-s3c24xx/mach-bast.c b/arch/arm/mach-s3c24xx/mach-bast.c index ea762f20099b..f9112b801a33 100644 --- a/arch/arm/mach-s3c24xx/mach-bast.c +++ b/arch/arm/mach-s3c24xx/mach-bast.c @@ -537,16 +537,6 @@ static struct platform_device *bast_devices[] __initdata = { &bast_sio, }; -#ifdef CONFIG_SAMSUNG_CLK -static struct clk *bast_clocks[] __initdata = { - &s3c24xx_dclk0, - &s3c24xx_dclk1, - &s3c24xx_clkout0, - &s3c24xx_clkout1, - &s3c24xx_uclk, -}; -#endif - static struct s3c_cpufreq_board __initdata bast_cpufreq = { .refresh = 7800, /* 7.8usec */ .auto_io = 1, @@ -560,23 +550,6 @@ static struct s3c24xx_audio_simtec_pdata __initdata bast_audio = { static void __init bast_map_io(void) { -#ifdef CONFIG_SAMSUNG_CLOCK - /* initialise the clocks */ - - s3c24xx_dclk0.parent = &clk_upll; - s3c24xx_dclk0.rate = 12*1000*1000; - - s3c24xx_dclk1.parent = &clk_upll; - s3c24xx_dclk1.rate = 24*1000*1000; - - s3c24xx_clkout0.parent = &s3c24xx_dclk0; - s3c24xx_clkout1.parent = &s3c24xx_dclk1; - - s3c24xx_uclk.parent = &s3c24xx_clkout1; - - s3c24xx_register_clocks(bast_clocks, ARRAY_SIZE(bast_clocks)); -#endif - s3c_hwmon_set_platdata(&bast_hwmon_info); s3c24xx_init_io(bast_iodesc, ARRAY_SIZE(bast_iodesc)); diff --git a/arch/arm/mach-s3c24xx/mach-osiris.c b/arch/arm/mach-s3c24xx/mach-osiris.c index 3bc2c9bad8b3..189147b80eca 100644 --- a/arch/arm/mach-s3c24xx/mach-osiris.c +++ b/arch/arm/mach-s3c24xx/mach-osiris.c @@ -350,16 +350,6 @@ static struct platform_device *osiris_devices[] __initdata = { &osiris_pcmcia, }; -#ifdef CONFIG_SAMSUNG_CLOCK -static struct clk *osiris_clocks[] __initdata = { - &s3c24xx_dclk0, - &s3c24xx_dclk1, - &s3c24xx_clkout0, - &s3c24xx_clkout1, - &s3c24xx_uclk, -}; -#endif - static struct s3c_cpufreq_board __initdata osiris_cpufreq = { .refresh = 7800, /* refresh period is 7.8usec */ .auto_io = 1, @@ -370,23 +360,6 @@ static void __init osiris_map_io(void) { unsigned long flags; -#ifdef CONFIG_SAMSUNG_CLOCK - /* initialise the clocks */ - - s3c24xx_dclk0.parent = &clk_upll; - s3c24xx_dclk0.rate = 12*1000*1000; - - s3c24xx_dclk1.parent = &clk_upll; - s3c24xx_dclk1.rate = 24*1000*1000; - - s3c24xx_clkout0.parent = &s3c24xx_dclk0; - s3c24xx_clkout1.parent = &s3c24xx_dclk1; - - s3c24xx_uclk.parent = &s3c24xx_clkout1; - - s3c24xx_register_clocks(osiris_clocks, ARRAY_SIZE(osiris_clocks)); -#endif - s3c24xx_init_io(osiris_iodesc, ARRAY_SIZE(osiris_iodesc)); s3c24xx_init_uarts(osiris_uartcfgs, ARRAY_SIZE(osiris_uartcfgs)); samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4); diff --git a/arch/arm/mach-s3c24xx/mach-rx1950.c b/arch/arm/mach-s3c24xx/mach-rx1950.c index 5f37f5262e65..e2c6541909c1 100644 --- a/arch/arm/mach-s3c24xx/mach-rx1950.c +++ b/arch/arm/mach-s3c24xx/mach-rx1950.c @@ -728,22 +728,8 @@ static struct platform_device *rx1950_devices[] __initdata = { &rx1950_leds, }; -#ifdef CONFIG_SAMSUNG_CLOCK -static struct clk *rx1950_clocks[] __initdata = { - &s3c24xx_clkout0, - &s3c24xx_clkout1, -}; -#endif - static void __init rx1950_map_io(void) { -#ifdef CONFIG_SAMSUNG_CLOCK - s3c24xx_clkout0.parent = &clk_h; - s3c24xx_clkout1.parent = &clk_f; - - s3c24xx_register_clocks(rx1950_clocks, ARRAY_SIZE(rx1950_clocks)); -#endif - s3c24xx_init_io(rx1950_iodesc, ARRAY_SIZE(rx1950_iodesc)); s3c24xx_init_uarts(rx1950_uartcfgs, ARRAY_SIZE(rx1950_uartcfgs)); samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4); diff --git a/arch/arm/mach-s3c24xx/mach-vr1000.c b/arch/arm/mach-s3c24xx/mach-vr1000.c index 5f588bf20f43..f88c584c3001 100644 --- a/arch/arm/mach-s3c24xx/mach-vr1000.c +++ b/arch/arm/mach-s3c24xx/mach-vr1000.c @@ -299,16 +299,6 @@ static struct platform_device *vr1000_devices[] __initdata = { &vr1000_led3, }; -#ifdef CONFIG_SAMSUNG_CLOCK -static struct clk *vr1000_clocks[] __initdata = { - &s3c24xx_dclk0, - &s3c24xx_dclk1, - &s3c24xx_clkout0, - &s3c24xx_clkout1, - &s3c24xx_uclk, -}; -#endif - static void vr1000_power_off(void) { gpio_direction_output(S3C2410_GPB(9), 1); @@ -316,23 +306,6 @@ static void vr1000_power_off(void) static void __init vr1000_map_io(void) { -#if CONFIG_SAMSUNG_CLOCK - /* initialise clock sources */ - - s3c24xx_dclk0.parent = &clk_upll; - s3c24xx_dclk0.rate = 12*1000*1000; - - s3c24xx_dclk1.parent = NULL; - s3c24xx_dclk1.rate = 3692307; - - s3c24xx_clkout0.parent = &s3c24xx_dclk0; - s3c24xx_clkout1.parent = &s3c24xx_dclk1; - - s3c24xx_uclk.parent = &s3c24xx_clkout1; - - s3c24xx_register_clocks(vr1000_clocks, ARRAY_SIZE(vr1000_clocks)); -#endif - pm_power_off = vr1000_power_off; s3c24xx_init_io(vr1000_iodesc, ARRAY_SIZE(vr1000_iodesc)); diff --git a/arch/arm/mach-s3c24xx/pm.c b/arch/arm/mach-s3c24xx/pm.c index 3d8cf3054e7f..b19256ec8d40 100644 --- a/arch/arm/mach-s3c24xx/pm.c +++ b/arch/arm/mach-s3c24xx/pm.c @@ -66,18 +66,6 @@ static struct sleep_save core_save[] = { SAVE_ITEM(S3C2410_BANKCON3), SAVE_ITEM(S3C2410_BANKCON4), SAVE_ITEM(S3C2410_BANKCON5), - -#ifdef CONFIG_SAMSUNG_CLOCK - SAVE_ITEM(S3C2410_LOCKTIME), - SAVE_ITEM(S3C2410_CLKCON), -#ifndef CONFIG_CPU_FREQ - SAVE_ITEM(S3C2410_CLKDIVN), - SAVE_ITEM(S3C2410_MPLLCON), - SAVE_ITEM(S3C2410_REFRESH), -#endif - SAVE_ITEM(S3C2410_UPLLCON), - SAVE_ITEM(S3C2410_CLKSLOW), -#endif /* CONFIG_SAMSUNG_CLOCK */ }; /* s3c_pm_check_resume_pin From 34c453ce16633539a94a2e876faeb731ac1be899 Mon Sep 17 00:00:00 2001 From: Kukjin Kim Date: Fri, 9 May 2014 05:51:43 +0900 Subject: [PATCH 55/87] ARM: S3C24XX: fix merge conflict Missed some changes during re-sorting this branch. So fixed it. Signed-off-by: Kukjin Kim --- arch/arm/mach-s3c24xx/Kconfig | 2 -- 1 file changed, 2 deletions(-) diff --git a/arch/arm/mach-s3c24xx/Kconfig b/arch/arm/mach-s3c24xx/Kconfig index 1331e784c713..22d149bcfcc6 100644 --- a/arch/arm/mach-s3c24xx/Kconfig +++ b/arch/arm/mach-s3c24xx/Kconfig @@ -347,7 +347,6 @@ config MACH_VR1000 bool "Thorcom VR1000" select MACH_BAST_IDE select S3C2410_COMMON_DCLK if COMMON_CLK - select S3C24XX_DCLK if SAMSUNG_CLOCK select S3C24XX_SIMTEC_NOR select S3C24XX_SIMTEC_PM if PM select S3C24XX_SIMTEC_USB @@ -644,7 +643,6 @@ config MACH_RX1950 select S3C2410_COMMON_DCLK if COMMON_CLK select S3C2410_IOTIMING if ARM_S3C2440_CPUFREQ select S3C2440_XTAL_16934400 - select S3C24XX_DCLK if SAMSUNG_CLOCK select S3C24XX_PWM select S3C_DEV_NAND help From c6e126de43e7d4abfd6cf796b40589db3a046167 Mon Sep 17 00:00:00 2001 From: Pawel Moll Date: Thu, 15 May 2014 16:55:24 +0100 Subject: [PATCH 56/87] of: Keep track of populated platform devices In "Device Tree powered" systems, platform devices are usually massively populated with of_platform_populate() call, executed at some level of initcalls, either by generic architecture or by platform-specific code. There are situations though where certain devices must be created (and bound with drivers) before all the others. This presents a challenge, as devices created explicitly would be created again by of_platform_populate(). This patch tries to solve that issue in a generic way, adding a "populated" flag for a DT node description. Subsequent of_platform_populate() will skip such nodes (and its children) in a similar way to the non-available ones. This patch also adds of_platform_depopulate() as an operation complementary to the _populate() one. It removes a platform or an amba device populated from the Device Tree, together with its all children (leaving, however, devices without associated of_node untouched) clearing the "populated" flag on the way. Signed-off-by: Pawel Moll Reviewed-by: Rob Herring Acked-by: Grant Likely --- drivers/of/platform.c | 74 ++++++++++++++++++++++++++++++++++--- include/linux/of.h | 7 ++++ include/linux/of_platform.h | 5 +++ 3 files changed, 81 insertions(+), 5 deletions(-) diff --git a/drivers/of/platform.c b/drivers/of/platform.c index bd47fbc53dc9..e8376d646d98 100644 --- a/drivers/of/platform.c +++ b/drivers/of/platform.c @@ -206,12 +206,13 @@ static struct platform_device *of_platform_device_create_pdata( { struct platform_device *dev; - if (!of_device_is_available(np)) + if (!of_device_is_available(np) || + of_node_test_and_set_flag(np, OF_POPULATED)) return NULL; dev = of_device_alloc(np, bus_id, parent); if (!dev) - return NULL; + goto err_clear_flag; #if defined(CONFIG_MICROBLAZE) dev->archdata.dma_mask = 0xffffffffUL; @@ -229,10 +230,14 @@ static struct platform_device *of_platform_device_create_pdata( if (of_device_add(dev) != 0) { platform_device_put(dev); - return NULL; + goto err_clear_flag; } return dev; + +err_clear_flag: + of_node_clear_flag(np, OF_POPULATED); + return NULL; } /** @@ -264,14 +269,15 @@ static struct amba_device *of_amba_device_create(struct device_node *node, pr_debug("Creating amba device %s\n", node->full_name); - if (!of_device_is_available(node)) + if (!of_device_is_available(node) || + of_node_test_and_set_flag(node, OF_POPULATED)) return NULL; dev = amba_device_alloc(NULL, 0, 0); if (!dev) { pr_err("%s(): amba_device_alloc() failed for %s\n", __func__, node->full_name); - return NULL; + goto err_clear_flag; } /* setup generic device info */ @@ -311,6 +317,8 @@ static struct amba_device *of_amba_device_create(struct device_node *node, err_free: amba_device_put(dev); +err_clear_flag: + of_node_clear_flag(node, OF_POPULATED); return NULL; } #else /* CONFIG_ARM_AMBA */ @@ -487,4 +495,60 @@ int of_platform_populate(struct device_node *root, return rc; } EXPORT_SYMBOL_GPL(of_platform_populate); + +static int of_platform_device_destroy(struct device *dev, void *data) +{ + bool *children_left = data; + + /* Do not touch devices not populated from the device tree */ + if (!dev->of_node || !of_node_check_flag(dev->of_node, OF_POPULATED)) { + *children_left = true; + return 0; + } + + /* Recurse, but don't touch this device if it has any children left */ + if (of_platform_depopulate(dev) != 0) { + *children_left = true; + return 0; + } + + if (dev->bus == &platform_bus_type) + platform_device_unregister(to_platform_device(dev)); +#ifdef CONFIG_ARM_AMBA + else if (dev->bus == &amba_bustype) + amba_device_unregister(to_amba_device(dev)); +#endif + else { + *children_left = true; + return 0; + } + + of_node_clear_flag(dev->of_node, OF_POPULATED); + + return 0; +} + +/** + * of_platform_depopulate() - Remove devices populated from device tree + * @parent: device which childred will be removed + * + * Complementary to of_platform_populate(), this function removes children + * of the given device (and, recurrently, their children) that have been + * created from their respective device tree nodes (and only those, + * leaving others - eg. manually created - unharmed). + * + * Returns 0 when all children devices have been removed or + * -EBUSY when some children remained. + */ +int of_platform_depopulate(struct device *parent) +{ + bool children_left = false; + + device_for_each_child(parent, &children_left, + of_platform_device_destroy); + + return children_left ? -EBUSY : 0; +} +EXPORT_SYMBOL_GPL(of_platform_depopulate); + #endif /* CONFIG_OF_ADDRESS */ diff --git a/include/linux/of.h b/include/linux/of.h index 3bad8d106e0e..4c50d0b78b89 100644 --- a/include/linux/of.h +++ b/include/linux/of.h @@ -130,6 +130,12 @@ static inline int of_node_check_flag(struct device_node *n, unsigned long flag) return test_bit(flag, &n->_flags); } +static inline int of_node_test_and_set_flag(struct device_node *n, + unsigned long flag) +{ + return test_and_set_bit(flag, &n->_flags); +} + static inline void of_node_set_flag(struct device_node *n, unsigned long flag) { set_bit(flag, &n->_flags); @@ -197,6 +203,7 @@ static inline unsigned long of_read_ulong(const __be32 *cell, int size) /* flag descriptions */ #define OF_DYNAMIC 1 /* node and properties were allocated via kmalloc */ #define OF_DETACHED 2 /* node has been detached from the device tree */ +#define OF_POPULATED 3 /* device already created for the node */ #define OF_IS_DYNAMIC(x) test_bit(OF_DYNAMIC, &x->_flags) #define OF_MARK_DYNAMIC(x) set_bit(OF_DYNAMIC, &x->_flags) diff --git a/include/linux/of_platform.h b/include/linux/of_platform.h index 05cb4a928252..b1010eeaac0d 100644 --- a/include/linux/of_platform.h +++ b/include/linux/of_platform.h @@ -72,6 +72,7 @@ extern int of_platform_populate(struct device_node *root, const struct of_device_id *matches, const struct of_dev_auxdata *lookup, struct device *parent); +extern int of_platform_depopulate(struct device *parent); #else static inline int of_platform_populate(struct device_node *root, const struct of_device_id *matches, @@ -80,6 +81,10 @@ static inline int of_platform_populate(struct device_node *root, { return -ENODEV; } +static inline int of_platform_depopulate(struct device *parent) +{ + return -ENODEV; +} #endif #endif /* _LINUX_OF_PLATFORM_H */ From 3b9334ac835bb431e2186645230c9f1eb94b5d49 Mon Sep 17 00:00:00 2001 From: Pawel Moll Date: Wed, 30 Apr 2014 16:46:29 +0100 Subject: [PATCH 57/87] mfd: vexpress: Convert custom func API to regmap Components of the Versatile Express platform (configuration microcontrollers on motherboard and daughterboards in particular) talk to each other over a custom configuration bus. They provide miscellaneous functions (from clock generator control to energy sensors) which are represented as platform devices (and Device Tree nodes). The transactions on the bus can be generated by different "bridges" in the system, some of which are universal for the whole platform (for the price of high transfer latencies), others restricted to a subsystem (but much faster). Until now drivers for such functions were using custom "func" API, which is being replaced in this patch by regmap calls. This required: * a rework (and move to drivers/bus directory, as suggested by Samuel and Arnd) of the config bus core, which is much simpler now and uses device model infrastructure (class) to keep track of the bridges; non-DT case (soon to be retired anyway) is simply covered by a special device registration function * the new config-bus driver also takes over device population, so there is no need for special matching table for of_platform_populate nor "simple-bus" hack in the arm64 model dtsi file (relevant bindings documentation has been updated); this allows all the vexpress devices fit into normal device model, making it possible to remove plenty of early inits and other hacks in the near future * adaptation of the syscfg bridge implementation in the sysreg driver, again making it much simpler; there is a special case of the "energy" function spanning two registers, where they should be both defined in the tree now, but backward compatibility is maintained in the code * modification of the relevant drivers: * hwmon - just a straight-forward API change * power/reset driver - API change * regulator - API change plus error handling simplification * osc clock driver - this one required larger rework in order to turn in into a standard platform driver Signed-off-by: Pawel Moll Acked-by: Mark Brown Acked-by: Lee Jones Acked-by: Guenter Roeck Acked-by: Mike Turquette --- .../bindings/arm/vexpress-sysreg.txt | 43 +- .../devicetree/bindings/arm/vexpress.txt | 15 +- arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts | 5 +- arch/arm/mach-vexpress/ct-ca9x4.c | 10 +- arch/arm/mach-vexpress/v2m.c | 18 +- arch/arm64/boot/dts/rtsm_ve-motherboard.dtsi | 2 +- drivers/bus/Kconfig | 9 + drivers/bus/Makefile | 2 + drivers/bus/vexpress-config.c | 202 +++++++++ drivers/clk/versatile/clk-vexpress-osc.c | 100 ++--- drivers/hwmon/vexpress.c | 17 +- drivers/mfd/Makefile | 2 +- drivers/mfd/vexpress-config.c | 287 ------------- drivers/mfd/vexpress-sysreg.c | 389 +++++++++--------- drivers/power/reset/vexpress-poweroff.c | 16 +- drivers/regulator/vexpress.c | 50 +-- include/linux/vexpress.h | 83 +--- 17 files changed, 569 insertions(+), 681 deletions(-) create mode 100644 drivers/bus/vexpress-config.c delete mode 100644 drivers/mfd/vexpress-config.c diff --git a/Documentation/devicetree/bindings/arm/vexpress-sysreg.txt b/Documentation/devicetree/bindings/arm/vexpress-sysreg.txt index 5580e9c4bd85..57b423f78995 100644 --- a/Documentation/devicetree/bindings/arm/vexpress-sysreg.txt +++ b/Documentation/devicetree/bindings/arm/vexpress-sysreg.txt @@ -27,24 +27,45 @@ Example: This block also can also act a bridge to the platform's configuration bus via "system control" interface, addressing devices with site number, position in the board stack, config controller, function and device -numbers - see motherboard's TRM for more details. - -The node describing a config device must refer to the sysreg node via -"arm,vexpress,config-bridge" phandle (can be also defined in the node's -parent) and relies on the board topology properties - see main vexpress -node documentation for more details. It must also define the following -property: -- arm,vexpress-sysreg,func : must contain two cells: - - first cell defines function number (eg. 1 for clock generator, - 2 for voltage regulators etc.) - - device number (eg. osc 0, osc 1 etc.) +numbers - see motherboard's TRM for more details. All configuration +controller accessible via this interface must reference the sysreg +node via "arm,vexpress,config-bridge" phandle and define appropriate +topology properties - see main vexpress node documentation for more +details. Each child of such node describes one function and must +define the following properties: +- compatible value : must be one of (corresponding to the TRM): + "arm,vexpress-amp" + "arm,vexpress-dvimode" + "arm,vexpress-energy" + "arm,vexpress-muxfpga" + "arm,vexpress-osc" + "arm,vexpress-power" + "arm,vexpress-reboot" + "arm,vexpress-reset" + "arm,vexpress-scc" + "arm,vexpress-shutdown" + "arm,vexpress-temp" + "arm,vexpress-volt" +- arm,vexpress-sysreg,func : must contain a set of two cells long groups: + - first cell of each group defines the function number + (eg. 1 for clock generator, 2 for voltage regulators etc.) + - second cell of each group defines device number (eg. osc 0, + osc 1 etc.) + - some functions (eg. energy meter, with its 64 bit long counter) + are using more than one function/device number pair Example: mcc { + compatible = "arm,vexpress,config-bus"; arm,vexpress,config-bridge = <&v2m_sysreg>; osc@0 { compatible = "arm,vexpress-osc"; arm,vexpress-sysreg,func = <1 0>; }; + + energy@0 { + compatible = "arm,vexpress-energy"; + arm,vexpress-sysreg,func = <13 0>, <13 1>; + }; }; diff --git a/Documentation/devicetree/bindings/arm/vexpress.txt b/Documentation/devicetree/bindings/arm/vexpress.txt index ae49161e478a..39844cd0bcce 100644 --- a/Documentation/devicetree/bindings/arm/vexpress.txt +++ b/Documentation/devicetree/bindings/arm/vexpress.txt @@ -80,12 +80,17 @@ but also control clock generators, voltage regulators, gather environmental data like temperature, power consumption etc. Even the video output switch (FPGA) is controlled that way. -Nodes describing devices controlled by this infrastructure should -point at the bridge device node: +The controllers are not mapped into normal memory address space +and must be accessed through bridges - other devices capable +of generating transactions on the configuration bus. + +The nodes describing configuration controllers must define +the following properties: +- compatible value: + compatible = "arm,vexpress,config-bus"; - bridge phandle: arm,vexpress,config-bridge = ; -This property can be also defined in a parent node (eg. for a DCC) -and is effective for all children. +and children describing available functions. Platform topology @@ -197,7 +202,7 @@ Example of a VE tile description (simplified) }; dcc { - compatible = "simple-bus"; + compatible = "arm,vexpress,config-bus"; arm,vexpress,config-bridge = <&v2m_sysreg>; osc@0 { diff --git a/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts b/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts index 15f98cbcb75a..a25c262326dc 100644 --- a/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts +++ b/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts @@ -312,6 +312,7 @@ arm,vexpress-sysreg,func = <12 0>; label = "A15 Pcore"; }; + power@1 { /* Total power for the three A7 cores */ compatible = "arm,vexpress-power"; @@ -322,14 +323,14 @@ energy@0 { /* Total energy for the two A15 cores */ compatible = "arm,vexpress-energy"; - arm,vexpress-sysreg,func = <13 0>; + arm,vexpress-sysreg,func = <13 0>, <13 1>; label = "A15 Jcore"; }; energy@2 { /* Total energy for the three A7 cores */ compatible = "arm,vexpress-energy"; - arm,vexpress-sysreg,func = <13 2>; + arm,vexpress-sysreg,func = <13 2>, <13 3>; label = "A7 Jcore"; }; }; diff --git a/arch/arm/mach-vexpress/ct-ca9x4.c b/arch/arm/mach-vexpress/ct-ca9x4.c index 6f34497a4245..35e394aa00e5 100644 --- a/arch/arm/mach-vexpress/ct-ca9x4.c +++ b/arch/arm/mach-vexpress/ct-ca9x4.c @@ -128,6 +128,10 @@ static struct platform_device pmu_device = { .resource = pmu_resources, }; +static struct clk_lookup osc1_lookup = { + .dev_id = "ct:clcd", +}; + static struct platform_device osc1_device = { .name = "vexpress-osc", .id = 1, @@ -135,6 +139,7 @@ static struct platform_device osc1_device = { .resource = (struct resource []) { VEXPRESS_RES_FUNC(0xf, 1), }, + .dev.platform_data = &osc1_lookup, }; static void __init ct_ca9x4_init(void) @@ -155,10 +160,7 @@ static void __init ct_ca9x4_init(void) amba_device_register(ct_ca9x4_amba_devs[i], &iomem_resource); platform_device_register(&pmu_device); - platform_device_register(&osc1_device); - - WARN_ON(clk_register_clkdev(vexpress_osc_setup(&osc1_device.dev), - NULL, "ct:clcd")); + vexpress_sysreg_config_device_register(&osc1_device); } #ifdef CONFIG_SMP diff --git a/arch/arm/mach-vexpress/v2m.c b/arch/arm/mach-vexpress/v2m.c index 4f8b8cb17ff5..ac95220a5019 100644 --- a/arch/arm/mach-vexpress/v2m.c +++ b/arch/arm/mach-vexpress/v2m.c @@ -340,11 +340,6 @@ static void __init v2m_init(void) regulator_register_fixed(0, v2m_eth_supplies, ARRAY_SIZE(v2m_eth_supplies)); - platform_device_register(&v2m_muxfpga_device); - platform_device_register(&v2m_shutdown_device); - platform_device_register(&v2m_reboot_device); - platform_device_register(&v2m_dvimode_device); - platform_device_register(&v2m_sysreg_device); platform_device_register(&v2m_pcie_i2c_device); platform_device_register(&v2m_ddc_i2c_device); @@ -356,6 +351,11 @@ static void __init v2m_init(void) for (i = 0; i < ARRAY_SIZE(v2m_amba_devs); i++) amba_device_register(v2m_amba_devs[i], &iomem_resource); + vexpress_sysreg_config_device_register(&v2m_muxfpga_device); + vexpress_sysreg_config_device_register(&v2m_shutdown_device); + vexpress_sysreg_config_device_register(&v2m_reboot_device); + vexpress_sysreg_config_device_register(&v2m_dvimode_device); + ct_desc->init_tile(); } @@ -423,17 +423,11 @@ void __init v2m_dt_init_early(void) versatile_sched_clock_init(vexpress_get_24mhz_clock_base(), 24000000); } -static const struct of_device_id v2m_dt_bus_match[] __initconst = { - { .compatible = "simple-bus", }, - { .compatible = "arm,amba-bus", }, - { .compatible = "arm,vexpress,config-bus", }, - {} -}; static void __init v2m_dt_init(void) { l2x0_of_init(0x00400000, 0xfe0fffff); - of_platform_populate(NULL, v2m_dt_bus_match, NULL, NULL); + of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); } static const char * const v2m_dt_match[] __initconst = { diff --git a/arch/arm64/boot/dts/rtsm_ve-motherboard.dtsi b/arch/arm64/boot/dts/rtsm_ve-motherboard.dtsi index 2f2ecd217363..ac2cb2418025 100644 --- a/arch/arm64/boot/dts/rtsm_ve-motherboard.dtsi +++ b/arch/arm64/boot/dts/rtsm_ve-motherboard.dtsi @@ -200,7 +200,7 @@ }; mcc { - compatible = "arm,vexpress,config-bus", "simple-bus"; + compatible = "arm,vexpress,config-bus"; arm,vexpress,config-bridge = <&v2m_sysreg>; v2m_oscclk1: osc@1 { diff --git a/drivers/bus/Kconfig b/drivers/bus/Kconfig index 552373c4e362..f24e79dd51bf 100644 --- a/drivers/bus/Kconfig +++ b/drivers/bus/Kconfig @@ -41,4 +41,13 @@ config ARM_CCI help Driver supporting the CCI cache coherent interconnect for ARM platforms. + +config VEXPRESS_CONFIG + bool "Versatile Express configuration bus" + default y if ARCH_VEXPRESS + depends on ARM || ARM64 + select REGMAP + help + Platform configuration infrastructure for the ARM Ltd. + Versatile Express. endmenu diff --git a/drivers/bus/Makefile b/drivers/bus/Makefile index 8947bdd0de8b..f095aa771de9 100644 --- a/drivers/bus/Makefile +++ b/drivers/bus/Makefile @@ -10,3 +10,5 @@ obj-$(CONFIG_OMAP_OCP2SCP) += omap-ocp2scp.o obj-$(CONFIG_OMAP_INTERCONNECT) += omap_l3_smx.o omap_l3_noc.o # CCI cache coherent interconnect for ARM platforms obj-$(CONFIG_ARM_CCI) += arm-cci.o + +obj-$(CONFIG_VEXPRESS_CONFIG) += vexpress-config.o diff --git a/drivers/bus/vexpress-config.c b/drivers/bus/vexpress-config.c new file mode 100644 index 000000000000..27a07dfcd626 --- /dev/null +++ b/drivers/bus/vexpress-config.c @@ -0,0 +1,202 @@ +/* + * 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. + * + * 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. + * + * Copyright (C) 2014 ARM Limited + */ + +#include +#include +#include +#include +#include + + +struct vexpress_config_bridge { + struct vexpress_config_bridge_ops *ops; + void *context; +}; + + +static DEFINE_MUTEX(vexpress_config_mutex); +static struct class *vexpress_config_class; +static u32 vexpress_config_site_master = VEXPRESS_SITE_MASTER; + + +void vexpress_config_set_master(u32 site) +{ + vexpress_config_site_master = site; +} + +u32 vexpress_config_get_master(void) +{ + return vexpress_config_site_master; +} + +void vexpress_config_lock(void *arg) +{ + mutex_lock(&vexpress_config_mutex); +} + +void vexpress_config_unlock(void *arg) +{ + mutex_unlock(&vexpress_config_mutex); +} + + +static void vexpress_config_find_prop(struct device_node *node, + const char *name, u32 *val) +{ + /* Default value */ + *val = 0; + + of_node_get(node); + while (node) { + if (of_property_read_u32(node, name, val) == 0) { + of_node_put(node); + return; + } + node = of_get_next_parent(node); + } +} + +int vexpress_config_get_topo(struct device_node *node, u32 *site, + u32 *position, u32 *dcc) +{ + vexpress_config_find_prop(node, "arm,vexpress,site", site); + if (*site == VEXPRESS_SITE_MASTER) + *site = vexpress_config_site_master; + if (WARN_ON(vexpress_config_site_master == VEXPRESS_SITE_MASTER)) + return -EINVAL; + vexpress_config_find_prop(node, "arm,vexpress,position", position); + vexpress_config_find_prop(node, "arm,vexpress,dcc", dcc); + + return 0; +} + + +static void vexpress_config_devres_release(struct device *dev, void *res) +{ + struct vexpress_config_bridge *bridge = dev_get_drvdata(dev->parent); + struct regmap *regmap = res; + + bridge->ops->regmap_exit(regmap, bridge->context); +} + +struct regmap *devm_regmap_init_vexpress_config(struct device *dev) +{ + struct vexpress_config_bridge *bridge; + struct regmap *regmap; + struct regmap **res; + + if (WARN_ON(dev->parent->class != vexpress_config_class)) + return ERR_PTR(-ENODEV); + + bridge = dev_get_drvdata(dev->parent); + if (WARN_ON(!bridge)) + return ERR_PTR(-EINVAL); + + res = devres_alloc(vexpress_config_devres_release, sizeof(*res), + GFP_KERNEL); + if (!res) + return ERR_PTR(-ENOMEM); + + regmap = bridge->ops->regmap_init(dev, bridge->context); + if (IS_ERR(regmap)) { + devres_free(res); + return regmap; + } + + *res = regmap; + devres_add(dev, res); + + return regmap; +} + + +struct device *vexpress_config_bridge_register(struct device *parent, + struct vexpress_config_bridge_ops *ops, void *context) +{ + struct device *dev; + struct vexpress_config_bridge *bridge; + + if (!vexpress_config_class) { + vexpress_config_class = class_create(THIS_MODULE, + "vexpress-config"); + if (IS_ERR(vexpress_config_class)) + return (void *)vexpress_config_class; + } + + dev = device_create(vexpress_config_class, parent, 0, + NULL, "%s.bridge", dev_name(parent)); + + if (IS_ERR(dev)) + return dev; + + bridge = devm_kmalloc(dev, sizeof(*bridge), GFP_KERNEL); + if (!bridge) { + put_device(dev); + device_unregister(dev); + return ERR_PTR(-ENOMEM); + } + bridge->ops = ops; + bridge->context = context; + + dev_set_drvdata(dev, bridge); + + dev_dbg(parent, "Registered bridge '%s', parent node %p\n", + dev_name(dev), parent->of_node); + + return dev; +} + + +static int vexpress_config_node_match(struct device *dev, const void *data) +{ + const struct device_node *node = data; + + dev_dbg(dev, "Parent node %p, looking for %p\n", + dev->parent->of_node, node); + + return dev->parent->of_node == node; +} + +static int vexpress_config_populate(struct device_node *node) +{ + struct device_node *bridge; + struct device *parent; + + bridge = of_parse_phandle(node, "arm,vexpress,config-bridge", 0); + if (!bridge) + return -EINVAL; + + parent = class_find_device(vexpress_config_class, NULL, bridge, + vexpress_config_node_match); + if (WARN_ON(!parent)) + return -ENODEV; + + return of_platform_populate(node, NULL, NULL, parent); +} + +static int __init vexpress_config_init(void) +{ + int err = 0; + struct device_node *node; + + /* Need the config devices early, before the "normal" devices... */ + for_each_compatible_node(node, NULL, "arm,vexpress,config-bus") { + err = vexpress_config_populate(node); + if (err) + break; + } + + return err; +} +postcore_initcall(vexpress_config_init); + diff --git a/drivers/clk/versatile/clk-vexpress-osc.c b/drivers/clk/versatile/clk-vexpress-osc.c index 422391242b39..529a59c0fbfa 100644 --- a/drivers/clk/versatile/clk-vexpress-osc.c +++ b/drivers/clk/versatile/clk-vexpress-osc.c @@ -11,8 +11,6 @@ * Copyright (C) 2012 ARM Limited */ -#define pr_fmt(fmt) "vexpress-osc: " fmt - #include #include #include @@ -22,7 +20,7 @@ #include struct vexpress_osc { - struct vexpress_config_func *func; + struct regmap *reg; struct clk_hw hw; unsigned long rate_min; unsigned long rate_max; @@ -36,7 +34,7 @@ static unsigned long vexpress_osc_recalc_rate(struct clk_hw *hw, struct vexpress_osc *osc = to_vexpress_osc(hw); u32 rate; - vexpress_config_read(osc->func, 0, &rate); + regmap_read(osc->reg, 0, &rate); return rate; } @@ -60,7 +58,7 @@ static int vexpress_osc_set_rate(struct clk_hw *hw, unsigned long rate, { struct vexpress_osc *osc = to_vexpress_osc(hw); - return vexpress_config_write(osc->func, 0, rate); + return regmap_write(osc->reg, 0, rate); } static struct clk_ops vexpress_osc_ops = { @@ -70,58 +68,31 @@ static struct clk_ops vexpress_osc_ops = { }; -struct clk * __init vexpress_osc_setup(struct device *dev) -{ - struct clk_init_data init; - struct vexpress_osc *osc = kzalloc(sizeof(*osc), GFP_KERNEL); - - if (!osc) - return NULL; - - osc->func = vexpress_config_func_get_by_dev(dev); - if (!osc->func) { - kfree(osc); - return NULL; - } - - init.name = dev_name(dev); - init.ops = &vexpress_osc_ops; - init.flags = CLK_IS_ROOT; - init.num_parents = 0; - osc->hw.init = &init; - - return clk_register(NULL, &osc->hw); -} - -void __init vexpress_osc_of_setup(struct device_node *node) +static int vexpress_osc_probe(struct platform_device *pdev) { + struct clk_lookup *cl = pdev->dev.platform_data; /* Non-DT lookup */ struct clk_init_data init; struct vexpress_osc *osc; struct clk *clk; u32 range[2]; - vexpress_sysreg_of_early_init(); - - osc = kzalloc(sizeof(*osc), GFP_KERNEL); + osc = devm_kzalloc(&pdev->dev, sizeof(*osc), GFP_KERNEL); if (!osc) - return; + return -ENOMEM; - osc->func = vexpress_config_func_get_by_node(node); - if (!osc->func) { - pr_err("Failed to obtain config func for node '%s'!\n", - node->full_name); - goto error; - } + osc->reg = devm_regmap_init_vexpress_config(&pdev->dev); + if (IS_ERR(osc->reg)) + return PTR_ERR(osc->reg); - if (of_property_read_u32_array(node, "freq-range", range, + if (of_property_read_u32_array(pdev->dev.of_node, "freq-range", range, ARRAY_SIZE(range)) == 0) { osc->rate_min = range[0]; osc->rate_max = range[1]; } - of_property_read_string(node, "clock-output-names", &init.name); - if (!init.name) - init.name = node->full_name; + if (of_property_read_string(pdev->dev.of_node, "clock-output-names", + &init.name) != 0) + init.name = dev_name(&pdev->dev); init.ops = &vexpress_osc_ops; init.flags = CLK_IS_ROOT; @@ -130,20 +101,37 @@ void __init vexpress_osc_of_setup(struct device_node *node) osc->hw.init = &init; clk = clk_register(NULL, &osc->hw); - if (IS_ERR(clk)) { - pr_err("Failed to register clock '%s'!\n", init.name); - goto error; + if (IS_ERR(clk)) + return PTR_ERR(clk); + + of_clk_add_provider(pdev->dev.of_node, of_clk_src_simple_get, clk); + + /* Only happens for non-DT cases */ + if (cl) { + cl->clk = clk; + clkdev_add(cl); } - of_clk_add_provider(node, of_clk_src_simple_get, clk); + dev_dbg(&pdev->dev, "Registered clock '%s'\n", init.name); - pr_debug("Registered clock '%s'\n", init.name); - - return; - -error: - if (osc->func) - vexpress_config_func_put(osc->func); - kfree(osc); + return 0; } -CLK_OF_DECLARE(vexpress_soc, "arm,vexpress-osc", vexpress_osc_of_setup); + +static struct of_device_id vexpress_osc_of_match[] = { + { .compatible = "arm,vexpress-osc", }, + {} +}; + +static struct platform_driver vexpress_osc_driver = { + .driver = { + .name = "vexpress-osc", + .of_match_table = vexpress_osc_of_match, + }, + .probe = vexpress_osc_probe, +}; + +static int __init vexpress_osc_init(void) +{ + return platform_driver_register(&vexpress_osc_driver); +} +core_initcall(vexpress_osc_init); diff --git a/drivers/hwmon/vexpress.c b/drivers/hwmon/vexpress.c index 8242b75d96c8..611f34c7333d 100644 --- a/drivers/hwmon/vexpress.c +++ b/drivers/hwmon/vexpress.c @@ -26,7 +26,7 @@ struct vexpress_hwmon_data { struct device *hwmon_dev; - struct vexpress_config_func *func; + struct regmap *reg; const char *name; }; @@ -53,7 +53,7 @@ static ssize_t vexpress_hwmon_u32_show(struct device *dev, int err; u32 value; - err = vexpress_config_read(data->func, 0, &value); + err = regmap_read(data->reg, 0, &value); if (err) return err; @@ -68,11 +68,11 @@ static ssize_t vexpress_hwmon_u64_show(struct device *dev, int err; u32 value_hi, value_lo; - err = vexpress_config_read(data->func, 0, &value_lo); + err = regmap_read(data->reg, 0, &value_lo); if (err) return err; - err = vexpress_config_read(data->func, 1, &value_hi); + err = regmap_read(data->reg, 1, &value_hi); if (err) return err; @@ -234,9 +234,9 @@ static int vexpress_hwmon_probe(struct platform_device *pdev) type = match->data; data->name = type->name; - data->func = vexpress_config_func_get_by_dev(&pdev->dev); - if (!data->func) - return -ENODEV; + data->reg = devm_regmap_init_vexpress_config(&pdev->dev); + if (IS_ERR(data->reg)) + return PTR_ERR(data->reg); err = sysfs_create_groups(&pdev->dev.kobj, type->attr_groups); if (err) @@ -252,7 +252,6 @@ static int vexpress_hwmon_probe(struct platform_device *pdev) error: sysfs_remove_group(&pdev->dev.kobj, match->data); - vexpress_config_func_put(data->func); return err; } @@ -266,8 +265,6 @@ static int vexpress_hwmon_remove(struct platform_device *pdev) match = of_match_device(vexpress_hwmon_of_match, &pdev->dev); sysfs_remove_group(&pdev->dev.kobj, match->data); - vexpress_config_func_put(data->func); - return 0; } diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 2851275e2656..9ba838eb5131 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -161,7 +161,7 @@ obj-$(CONFIG_MFD_RC5T583) += rc5t583.o rc5t583-irq.o obj-$(CONFIG_MFD_SEC_CORE) += sec-core.o sec-irq.o obj-$(CONFIG_MFD_SYSCON) += syscon.o obj-$(CONFIG_MFD_LM3533) += lm3533-core.o lm3533-ctrlbank.o -obj-$(CONFIG_VEXPRESS_CONFIG) += vexpress-config.o vexpress-sysreg.o +obj-$(CONFIG_VEXPRESS_CONFIG) += vexpress-sysreg.o obj-$(CONFIG_MFD_RETU) += retu-mfd.o obj-$(CONFIG_MFD_AS3711) += as3711.o obj-$(CONFIG_MFD_AS3722) += as3722.o diff --git a/drivers/mfd/vexpress-config.c b/drivers/mfd/vexpress-config.c deleted file mode 100644 index d0db89d13e01..000000000000 --- a/drivers/mfd/vexpress-config.c +++ /dev/null @@ -1,287 +0,0 @@ -/* - * 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. - * - * 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. - * - * Copyright (C) 2012 ARM Limited - */ - -#define pr_fmt(fmt) "vexpress-config: " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -#define VEXPRESS_CONFIG_MAX_BRIDGES 2 - -static struct vexpress_config_bridge { - struct device_node *node; - struct vexpress_config_bridge_info *info; - struct list_head transactions; - spinlock_t transactions_lock; -} vexpress_config_bridges[VEXPRESS_CONFIG_MAX_BRIDGES]; - -static DECLARE_BITMAP(vexpress_config_bridges_map, - ARRAY_SIZE(vexpress_config_bridges)); -static DEFINE_MUTEX(vexpress_config_bridges_mutex); - -struct vexpress_config_bridge *vexpress_config_bridge_register( - struct device_node *node, - struct vexpress_config_bridge_info *info) -{ - struct vexpress_config_bridge *bridge; - int i; - - pr_debug("Registering bridge '%s'\n", info->name); - - mutex_lock(&vexpress_config_bridges_mutex); - i = find_first_zero_bit(vexpress_config_bridges_map, - ARRAY_SIZE(vexpress_config_bridges)); - if (i >= ARRAY_SIZE(vexpress_config_bridges)) { - pr_err("Can't register more bridges!\n"); - mutex_unlock(&vexpress_config_bridges_mutex); - return NULL; - } - __set_bit(i, vexpress_config_bridges_map); - bridge = &vexpress_config_bridges[i]; - - bridge->node = node; - bridge->info = info; - INIT_LIST_HEAD(&bridge->transactions); - spin_lock_init(&bridge->transactions_lock); - - mutex_unlock(&vexpress_config_bridges_mutex); - - return bridge; -} -EXPORT_SYMBOL(vexpress_config_bridge_register); - -void vexpress_config_bridge_unregister(struct vexpress_config_bridge *bridge) -{ - struct vexpress_config_bridge __bridge = *bridge; - int i; - - mutex_lock(&vexpress_config_bridges_mutex); - for (i = 0; i < ARRAY_SIZE(vexpress_config_bridges); i++) - if (&vexpress_config_bridges[i] == bridge) - __clear_bit(i, vexpress_config_bridges_map); - mutex_unlock(&vexpress_config_bridges_mutex); - - WARN_ON(!list_empty(&__bridge.transactions)); - while (!list_empty(&__bridge.transactions)) - cpu_relax(); -} -EXPORT_SYMBOL(vexpress_config_bridge_unregister); - - -struct vexpress_config_func { - struct vexpress_config_bridge *bridge; - void *func; -}; - -struct vexpress_config_func *__vexpress_config_func_get(struct device *dev, - struct device_node *node) -{ - struct device_node *bridge_node; - struct vexpress_config_func *func; - int i; - - if (WARN_ON(dev && node && dev->of_node != node)) - return NULL; - if (dev && !node) - node = dev->of_node; - - func = kzalloc(sizeof(*func), GFP_KERNEL); - if (!func) - return NULL; - - bridge_node = of_node_get(node); - while (bridge_node) { - const __be32 *prop = of_get_property(bridge_node, - "arm,vexpress,config-bridge", NULL); - - if (prop) { - bridge_node = of_find_node_by_phandle( - be32_to_cpup(prop)); - break; - } - - bridge_node = of_get_next_parent(bridge_node); - } - - mutex_lock(&vexpress_config_bridges_mutex); - for (i = 0; i < ARRAY_SIZE(vexpress_config_bridges); i++) { - struct vexpress_config_bridge *bridge = - &vexpress_config_bridges[i]; - - if (test_bit(i, vexpress_config_bridges_map) && - bridge->node == bridge_node) { - func->bridge = bridge; - func->func = bridge->info->func_get(dev, node); - break; - } - } - mutex_unlock(&vexpress_config_bridges_mutex); - - if (!func->func) { - of_node_put(node); - kfree(func); - return NULL; - } - - return func; -} -EXPORT_SYMBOL(__vexpress_config_func_get); - -void vexpress_config_func_put(struct vexpress_config_func *func) -{ - func->bridge->info->func_put(func->func); - of_node_put(func->bridge->node); - kfree(func); -} -EXPORT_SYMBOL(vexpress_config_func_put); - -struct vexpress_config_trans { - struct vexpress_config_func *func; - int offset; - bool write; - u32 *data; - int status; - struct completion completion; - struct list_head list; -}; - -static void vexpress_config_dump_trans(const char *what, - struct vexpress_config_trans *trans) -{ - pr_debug("%s %s trans %p func 0x%p offset %d data 0x%x status %d\n", - what, trans->write ? "write" : "read", trans, - trans->func->func, trans->offset, - trans->data ? *trans->data : 0, trans->status); -} - -static int vexpress_config_schedule(struct vexpress_config_trans *trans) -{ - int status; - struct vexpress_config_bridge *bridge = trans->func->bridge; - unsigned long flags; - - init_completion(&trans->completion); - trans->status = -EFAULT; - - spin_lock_irqsave(&bridge->transactions_lock, flags); - - if (list_empty(&bridge->transactions)) { - vexpress_config_dump_trans("Executing", trans); - status = bridge->info->func_exec(trans->func->func, - trans->offset, trans->write, trans->data); - } else { - vexpress_config_dump_trans("Queuing", trans); - status = VEXPRESS_CONFIG_STATUS_WAIT; - } - - switch (status) { - case VEXPRESS_CONFIG_STATUS_DONE: - vexpress_config_dump_trans("Finished", trans); - trans->status = status; - break; - case VEXPRESS_CONFIG_STATUS_WAIT: - list_add_tail(&trans->list, &bridge->transactions); - break; - } - - spin_unlock_irqrestore(&bridge->transactions_lock, flags); - - return status; -} - -void vexpress_config_complete(struct vexpress_config_bridge *bridge, - int status) -{ - struct vexpress_config_trans *trans; - unsigned long flags; - const char *message = "Completed"; - - spin_lock_irqsave(&bridge->transactions_lock, flags); - - trans = list_first_entry(&bridge->transactions, - struct vexpress_config_trans, list); - trans->status = status; - - do { - vexpress_config_dump_trans(message, trans); - list_del(&trans->list); - complete(&trans->completion); - - if (list_empty(&bridge->transactions)) - break; - - trans = list_first_entry(&bridge->transactions, - struct vexpress_config_trans, list); - vexpress_config_dump_trans("Executing pending", trans); - trans->status = bridge->info->func_exec(trans->func->func, - trans->offset, trans->write, trans->data); - message = "Finished pending"; - } while (trans->status == VEXPRESS_CONFIG_STATUS_DONE); - - spin_unlock_irqrestore(&bridge->transactions_lock, flags); -} -EXPORT_SYMBOL(vexpress_config_complete); - -int vexpress_config_wait(struct vexpress_config_trans *trans) -{ - wait_for_completion(&trans->completion); - - return trans->status; -} -EXPORT_SYMBOL(vexpress_config_wait); - -int vexpress_config_read(struct vexpress_config_func *func, int offset, - u32 *data) -{ - struct vexpress_config_trans trans = { - .func = func, - .offset = offset, - .write = false, - .data = data, - .status = 0, - }; - int status = vexpress_config_schedule(&trans); - - if (status == VEXPRESS_CONFIG_STATUS_WAIT) - status = vexpress_config_wait(&trans); - - return status; -} -EXPORT_SYMBOL(vexpress_config_read); - -int vexpress_config_write(struct vexpress_config_func *func, int offset, - u32 data) -{ - struct vexpress_config_trans trans = { - .func = func, - .offset = offset, - .write = true, - .data = &data, - .status = 0, - }; - int status = vexpress_config_schedule(&trans); - - if (status == VEXPRESS_CONFIG_STATUS_WAIT) - status = vexpress_config_wait(&trans); - - return status; -} -EXPORT_SYMBOL(vexpress_config_write); diff --git a/drivers/mfd/vexpress-sysreg.c b/drivers/mfd/vexpress-sysreg.c index 35281e804e7e..b4138a7168db 100644 --- a/drivers/mfd/vexpress-sysreg.c +++ b/drivers/mfd/vexpress-sysreg.c @@ -16,8 +16,10 @@ #include #include #include +#include #include #include +#include #include #include #include @@ -72,9 +74,18 @@ static void __iomem *vexpress_sysreg_base; static struct device *vexpress_sysreg_dev; -static int vexpress_master_site; +static LIST_HEAD(vexpress_sysreg_config_funcs); +static struct device *vexpress_sysreg_config_bridge; +static int vexpress_sysreg_get_master(void) +{ + if (readl(vexpress_sysreg_base + SYS_MISC) & SYS_MISC_MASTERSITE) + return VEXPRESS_SITE_DB2; + + return VEXPRESS_SITE_DB1; +} + void vexpress_flags_set(u32 data) { writel(~0, vexpress_sysreg_base + SYS_FLAGSCLR); @@ -84,7 +95,7 @@ void vexpress_flags_set(u32 data) u32 vexpress_get_procid(int site) { if (site == VEXPRESS_SITE_MASTER) - site = vexpress_master_site; + site = vexpress_sysreg_get_master(); return readl(vexpress_sysreg_base + (site == VEXPRESS_SITE_DB1 ? SYS_PROCID0 : SYS_PROCID1)); @@ -114,130 +125,33 @@ void __iomem *vexpress_get_24mhz_clock_base(void) } -static void vexpress_sysreg_find_prop(struct device_node *node, - const char *name, u32 *val) -{ - of_node_get(node); - while (node) { - if (of_property_read_u32(node, name, val) == 0) { - of_node_put(node); - return; - } - node = of_get_next_parent(node); - } -} - -unsigned __vexpress_get_site(struct device *dev, struct device_node *node) -{ - u32 site = 0; - - WARN_ON(dev && node && dev->of_node != node); - if (dev && !node) - node = dev->of_node; - - if (node) { - vexpress_sysreg_find_prop(node, "arm,vexpress,site", &site); - } else if (dev && dev->bus == &platform_bus_type) { - struct platform_device *pdev = to_platform_device(dev); - - if (pdev->num_resources == 1 && - pdev->resource[0].flags == IORESOURCE_BUS) - site = pdev->resource[0].start; - } else if (dev && strncmp(dev_name(dev), "ct:", 3) == 0) { - site = VEXPRESS_SITE_MASTER; - } - - if (site == VEXPRESS_SITE_MASTER) - site = vexpress_master_site; - - return site; -} - - struct vexpress_sysreg_config_func { - u32 template; - u32 device; + struct list_head list; + struct regmap *regmap; + int num_templates; + u32 template[0]; /* Keep this last */ }; -static struct vexpress_config_bridge *vexpress_sysreg_config_bridge; -static struct timer_list vexpress_sysreg_config_timer; -static u32 *vexpress_sysreg_config_data; -static int vexpress_sysreg_config_tries; - -static void *vexpress_sysreg_config_func_get(struct device *dev, - struct device_node *node) +static int vexpress_sysreg_config_exec(struct vexpress_sysreg_config_func *func, + int index, bool write, u32 *data) { - struct vexpress_sysreg_config_func *config_func; - u32 site = 0; - u32 position = 0; - u32 dcc = 0; - u32 func_device[2]; - int err = -EFAULT; - - if (node) { - of_node_get(node); - vexpress_sysreg_find_prop(node, "arm,vexpress,site", &site); - vexpress_sysreg_find_prop(node, "arm,vexpress,position", - &position); - vexpress_sysreg_find_prop(node, "arm,vexpress,dcc", &dcc); - err = of_property_read_u32_array(node, - "arm,vexpress-sysreg,func", func_device, - ARRAY_SIZE(func_device)); - of_node_put(node); - } else if (dev && dev->bus == &platform_bus_type) { - struct platform_device *pdev = to_platform_device(dev); - - if (pdev->num_resources == 1 && - pdev->resource[0].flags == IORESOURCE_BUS) { - site = pdev->resource[0].start; - func_device[0] = pdev->resource[0].end; - func_device[1] = pdev->id; - err = 0; - } - } - if (err) - return NULL; - - config_func = kzalloc(sizeof(*config_func), GFP_KERNEL); - if (!config_func) - return NULL; - - config_func->template = SYS_CFGCTRL_DCC(dcc); - config_func->template |= SYS_CFGCTRL_FUNC(func_device[0]); - config_func->template |= SYS_CFGCTRL_SITE(site == VEXPRESS_SITE_MASTER ? - vexpress_master_site : site); - config_func->template |= SYS_CFGCTRL_POSITION(position); - config_func->device |= func_device[1]; - - dev_dbg(vexpress_sysreg_dev, "func 0x%p = 0x%x, %d\n", config_func, - config_func->template, config_func->device); - - return config_func; -} - -static void vexpress_sysreg_config_func_put(void *func) -{ - kfree(func); -} - -static int vexpress_sysreg_config_func_exec(void *func, int offset, - bool write, u32 *data) -{ - int status; - struct vexpress_sysreg_config_func *config_func = func; - u32 command; + u32 command, status; + int tries; + long timeout; if (WARN_ON(!vexpress_sysreg_base)) return -ENOENT; + if (WARN_ON(index > func->num_templates)) + return -EINVAL; + command = readl(vexpress_sysreg_base + SYS_CFGCTRL); if (WARN_ON(command & SYS_CFGCTRL_START)) return -EBUSY; - command = SYS_CFGCTRL_START; + command = func->template[index]; + command |= SYS_CFGCTRL_START; command |= write ? SYS_CFGCTRL_WRITE : 0; - command |= config_func->template; - command |= SYS_CFGCTRL_DEVICE(config_func->device + offset); /* Use a canary for reads */ if (!write) @@ -250,90 +164,190 @@ static int vexpress_sysreg_config_func_exec(void *func, int offset, writel(command, vexpress_sysreg_base + SYS_CFGCTRL); mb(); - if (vexpress_sysreg_dev) { - /* Schedule completion check */ - if (!write) - vexpress_sysreg_config_data = data; - vexpress_sysreg_config_tries = 100; - mod_timer(&vexpress_sysreg_config_timer, - jiffies + usecs_to_jiffies(100)); - status = VEXPRESS_CONFIG_STATUS_WAIT; - } else { - /* Early execution, no timer available, have to spin */ - u32 cfgstat; + /* The operation can take ages... Go to sleep, 100us initially */ + tries = 100; + timeout = 100; + do { + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(usecs_to_jiffies(timeout)); + if (signal_pending(current)) + return -EINTR; - do { - cpu_relax(); - cfgstat = readl(vexpress_sysreg_base + SYS_CFGSTAT); - } while (!cfgstat); + status = readl(vexpress_sysreg_base + SYS_CFGSTAT); + if (status & SYS_CFGSTAT_ERR) + return -EFAULT; - if (!write && (cfgstat & SYS_CFGSTAT_COMPLETE)) - *data = readl(vexpress_sysreg_base + SYS_CFGDATA); - status = VEXPRESS_CONFIG_STATUS_DONE; + if (timeout > 20) + timeout -= 20; + } while (--tries && !(status & SYS_CFGSTAT_COMPLETE)); + if (WARN_ON_ONCE(!tries)) + return -ETIMEDOUT; - if (cfgstat & SYS_CFGSTAT_ERR) - status = -EINVAL; + if (!write) { + *data = readl(vexpress_sysreg_base + SYS_CFGDATA); + dev_dbg(vexpress_sysreg_dev, "func %p, read data %x\n", + func, *data); } - return status; + return 0; } -struct vexpress_config_bridge_info vexpress_sysreg_config_bridge_info = { - .name = "vexpress-sysreg", - .func_get = vexpress_sysreg_config_func_get, - .func_put = vexpress_sysreg_config_func_put, - .func_exec = vexpress_sysreg_config_func_exec, +static int vexpress_sysreg_config_read(void *context, unsigned int index, + unsigned int *val) +{ + struct vexpress_sysreg_config_func *func = context; + + return vexpress_sysreg_config_exec(func, index, false, val); +} + +static int vexpress_sysreg_config_write(void *context, unsigned int index, + unsigned int val) +{ + struct vexpress_sysreg_config_func *func = context; + + return vexpress_sysreg_config_exec(func, index, true, &val); +} + +struct regmap_config vexpress_sysreg_regmap_config = { + .lock = vexpress_config_lock, + .unlock = vexpress_config_unlock, + .reg_bits = 32, + .val_bits = 32, + .reg_read = vexpress_sysreg_config_read, + .reg_write = vexpress_sysreg_config_write, + .reg_format_endian = REGMAP_ENDIAN_LITTLE, + .val_format_endian = REGMAP_ENDIAN_LITTLE, }; -static void vexpress_sysreg_config_complete(unsigned long data) +static struct regmap *vexpress_sysreg_config_regmap_init(struct device *dev, + void *context) { - int status = VEXPRESS_CONFIG_STATUS_DONE; - u32 cfgstat = readl(vexpress_sysreg_base + SYS_CFGSTAT); + struct platform_device *pdev = to_platform_device(dev); + struct vexpress_sysreg_config_func *func; + struct property *prop; + const __be32 *val = NULL; + __be32 energy_quirk[4]; + int num; + u32 site, position, dcc; + int err; + int i; - if (cfgstat & SYS_CFGSTAT_ERR) - status = -EINVAL; - if (!vexpress_sysreg_config_tries--) - status = -ETIMEDOUT; + if (dev->of_node) { + err = vexpress_config_get_topo(dev->of_node, &site, &position, + &dcc); + if (err) + return ERR_PTR(err); - if (status < 0) { - dev_err(vexpress_sysreg_dev, "error %d\n", status); - } else if (!(cfgstat & SYS_CFGSTAT_COMPLETE)) { - mod_timer(&vexpress_sysreg_config_timer, - jiffies + usecs_to_jiffies(50)); - return; + prop = of_find_property(dev->of_node, + "arm,vexpress-sysreg,func", NULL); + if (!prop) + return ERR_PTR(-EINVAL); + + num = prop->length / sizeof(u32) / 2; + val = prop->value; + } else { + if (pdev->num_resources != 1 || + pdev->resource[0].flags != IORESOURCE_BUS) + return ERR_PTR(-EFAULT); + + site = pdev->resource[0].start; + if (site == VEXPRESS_SITE_MASTER) + site = vexpress_sysreg_get_master(); + position = 0; + dcc = 0; + num = 1; } - if (vexpress_sysreg_config_data) { - *vexpress_sysreg_config_data = readl(vexpress_sysreg_base + - SYS_CFGDATA); - dev_dbg(vexpress_sysreg_dev, "read data %x\n", - *vexpress_sysreg_config_data); - vexpress_sysreg_config_data = NULL; + /* + * "arm,vexpress-energy" function used to be described + * by its first device only, now it requires both + */ + if (num == 1 && of_device_is_compatible(dev->of_node, + "arm,vexpress-energy")) { + num = 2; + energy_quirk[0] = *val; + energy_quirk[2] = *val++; + energy_quirk[1] = *val; + energy_quirk[3] = cpu_to_be32(be32_to_cpup(val) + 1); + val = energy_quirk; } - vexpress_config_complete(vexpress_sysreg_config_bridge, status); -} + func = kzalloc(sizeof(*func) + sizeof(*func->template) * num, + GFP_KERNEL); + if (!func) + return NULL; + func->num_templates = num; -void vexpress_sysreg_setup(struct device_node *node) -{ - if (WARN_ON(!vexpress_sysreg_base)) - return; + for (i = 0; i < num; i++) { + u32 function, device; - if (readl(vexpress_sysreg_base + SYS_MISC) & SYS_MISC_MASTERSITE) - vexpress_master_site = VEXPRESS_SITE_DB2; + if (dev->of_node) { + function = be32_to_cpup(val++); + device = be32_to_cpup(val++); + } else { + function = pdev->resource[0].end; + device = pdev->id; + } + + dev_dbg(dev, "func %p: %u/%u/%u/%u/%u\n", + func, site, position, dcc, + function, device); + + func->template[i] = SYS_CFGCTRL_DCC(dcc); + func->template[i] |= SYS_CFGCTRL_SITE(site); + func->template[i] |= SYS_CFGCTRL_POSITION(position); + func->template[i] |= SYS_CFGCTRL_FUNC(function); + func->template[i] |= SYS_CFGCTRL_DEVICE(device); + } + + vexpress_sysreg_regmap_config.max_register = num - 1; + + func->regmap = regmap_init(dev, NULL, func, + &vexpress_sysreg_regmap_config); + + if (IS_ERR(func->regmap)) + kfree(func); else - vexpress_master_site = VEXPRESS_SITE_DB1; + list_add(&func->list, &vexpress_sysreg_config_funcs); - vexpress_sysreg_config_bridge = vexpress_config_bridge_register( - node, &vexpress_sysreg_config_bridge_info); - WARN_ON(!vexpress_sysreg_config_bridge); + return func->regmap; } +static void vexpress_sysreg_config_regmap_exit(struct regmap *regmap, + void *context) +{ + struct vexpress_sysreg_config_func *func, *tmp; + + regmap_exit(regmap); + + list_for_each_entry_safe(func, tmp, &vexpress_sysreg_config_funcs, + list) { + if (func->regmap == regmap) { + list_del(&vexpress_sysreg_config_funcs); + kfree(func); + break; + } + } +} + +static struct vexpress_config_bridge_ops vexpress_sysreg_config_bridge_ops = { + .regmap_init = vexpress_sysreg_config_regmap_init, + .regmap_exit = vexpress_sysreg_config_regmap_exit, +}; + +int vexpress_sysreg_config_device_register(struct platform_device *pdev) +{ + pdev->dev.parent = vexpress_sysreg_config_bridge; + + return platform_device_register(pdev); +} + + void __init vexpress_sysreg_early_init(void __iomem *base) { vexpress_sysreg_base = base; - vexpress_sysreg_setup(NULL); + vexpress_config_set_master(vexpress_sysreg_get_master()); } void __init vexpress_sysreg_of_early_init(void) @@ -344,10 +358,14 @@ void __init vexpress_sysreg_of_early_init(void) return; node = of_find_compatible_node(NULL, NULL, "arm,vexpress-sysreg"); - if (node) { - vexpress_sysreg_base = of_iomap(node, 0); - vexpress_sysreg_setup(node); - } + if (WARN_ON(!node)) + return; + + vexpress_sysreg_base = of_iomap(node, 0); + if (WARN_ON(!vexpress_sysreg_base)) + return; + + vexpress_config_set_master(vexpress_sysreg_get_master()); } @@ -470,28 +488,22 @@ static int vexpress_sysreg_probe(struct platform_device *pdev) return -EBUSY; } - if (!vexpress_sysreg_base) { + if (!vexpress_sysreg_base) vexpress_sysreg_base = devm_ioremap(&pdev->dev, res->start, resource_size(res)); - vexpress_sysreg_setup(pdev->dev.of_node); - } if (!vexpress_sysreg_base) { dev_err(&pdev->dev, "Failed to obtain base address!\n"); return -EFAULT; } - setup_timer(&vexpress_sysreg_config_timer, - vexpress_sysreg_config_complete, 0); - + vexpress_config_set_master(vexpress_sysreg_get_master()); vexpress_sysreg_dev = &pdev->dev; #ifdef CONFIG_GPIOLIB vexpress_sysreg_gpio_chip.dev = &pdev->dev; err = gpiochip_add(&vexpress_sysreg_gpio_chip); if (err) { - vexpress_config_bridge_unregister( - vexpress_sysreg_config_bridge); dev_err(&pdev->dev, "Failed to register GPIO chip! (%d)\n", err); return err; @@ -502,6 +514,10 @@ static int vexpress_sysreg_probe(struct platform_device *pdev) sizeof(vexpress_sysreg_leds_pdata)); #endif + vexpress_sysreg_config_bridge = vexpress_config_bridge_register( + &pdev->dev, &vexpress_sysreg_config_bridge_ops, NULL); + WARN_ON(!vexpress_sysreg_config_bridge); + device_create_file(vexpress_sysreg_dev, &dev_attr_sys_id); return 0; @@ -522,7 +538,12 @@ static struct platform_driver vexpress_sysreg_driver = { static int __init vexpress_sysreg_init(void) { - vexpress_sysreg_of_early_init(); + struct device_node *node; + + /* Need the sysreg early, before any other device... */ + for_each_matching_node(node, vexpress_sysreg_match) + of_platform_device_create(node, NULL, NULL); + return platform_driver_register(&vexpress_sysreg_driver); } core_initcall(vexpress_sysreg_init); diff --git a/drivers/power/reset/vexpress-poweroff.c b/drivers/power/reset/vexpress-poweroff.c index b95cf71ed695..4dc102e2b230 100644 --- a/drivers/power/reset/vexpress-poweroff.c +++ b/drivers/power/reset/vexpress-poweroff.c @@ -23,10 +23,10 @@ static void vexpress_reset_do(struct device *dev, const char *what) { int err = -ENOENT; - struct vexpress_config_func *func = dev_get_drvdata(dev); + struct regmap *reg = dev_get_drvdata(dev); - if (func) { - err = vexpress_config_write(func, 0, 0); + if (reg) { + err = regmap_write(reg, 0, 0); if (!err) mdelay(1000); } @@ -91,17 +91,17 @@ static int vexpress_reset_probe(struct platform_device *pdev) enum vexpress_reset_func func; const struct of_device_id *match = of_match_device(vexpress_reset_of_match, &pdev->dev); - struct vexpress_config_func *config_func; + struct regmap *regmap; if (match) func = (enum vexpress_reset_func)match->data; else func = pdev->id_entry->driver_data; - config_func = vexpress_config_func_get_by_dev(&pdev->dev); - if (!config_func) - return -EINVAL; - dev_set_drvdata(&pdev->dev, config_func); + regmap = devm_regmap_init_vexpress_config(&pdev->dev); + if (IS_ERR(regmap)) + return PTR_ERR(regmap); + dev_set_drvdata(&pdev->dev, regmap); switch (func) { case FUNC_SHUTDOWN: diff --git a/drivers/regulator/vexpress.c b/drivers/regulator/vexpress.c index f3ae28a7e663..2863428813e4 100644 --- a/drivers/regulator/vexpress.c +++ b/drivers/regulator/vexpress.c @@ -26,14 +26,14 @@ struct vexpress_regulator { struct regulator_desc desc; struct regulator_dev *regdev; - struct vexpress_config_func *func; + struct regmap *regmap; }; static int vexpress_regulator_get_voltage(struct regulator_dev *regdev) { struct vexpress_regulator *reg = rdev_get_drvdata(regdev); u32 uV; - int err = vexpress_config_read(reg->func, 0, &uV); + int err = regmap_read(reg->regmap, 0, &uV); return err ? err : uV; } @@ -43,7 +43,7 @@ static int vexpress_regulator_set_voltage(struct regulator_dev *regdev, { struct vexpress_regulator *reg = rdev_get_drvdata(regdev); - return vexpress_config_write(reg->func, 0, min_uV); + return regmap_write(reg->regmap, 0, min_uV); } static struct regulator_ops vexpress_regulator_ops_ro = { @@ -57,22 +57,17 @@ static struct regulator_ops vexpress_regulator_ops = { static int vexpress_regulator_probe(struct platform_device *pdev) { - int err; struct vexpress_regulator *reg; struct regulator_init_data *init_data; struct regulator_config config = { }; reg = devm_kzalloc(&pdev->dev, sizeof(*reg), GFP_KERNEL); - if (!reg) { - err = -ENOMEM; - goto error_kzalloc; - } + if (!reg) + return -ENOMEM; - reg->func = vexpress_config_func_get_by_dev(&pdev->dev); - if (!reg->func) { - err = -ENXIO; - goto error_get_func; - } + reg->regmap = devm_regmap_init_vexpress_config(&pdev->dev); + if (IS_ERR(reg->regmap)) + return PTR_ERR(reg->regmap); reg->desc.name = dev_name(&pdev->dev); reg->desc.type = REGULATOR_VOLTAGE; @@ -80,10 +75,8 @@ static int vexpress_regulator_probe(struct platform_device *pdev) reg->desc.continuous_voltage_range = true; init_data = of_get_regulator_init_data(&pdev->dev, pdev->dev.of_node); - if (!init_data) { - err = -EINVAL; - goto error_get_regulator_init_data; - } + if (!init_data) + return -EINVAL; init_data->constraints.apply_uV = 0; if (init_data->constraints.min_uV && init_data->constraints.max_uV) @@ -97,29 +90,11 @@ static int vexpress_regulator_probe(struct platform_device *pdev) config.of_node = pdev->dev.of_node; reg->regdev = devm_regulator_register(&pdev->dev, ®->desc, &config); - if (IS_ERR(reg->regdev)) { - err = PTR_ERR(reg->regdev); - goto error_regulator_register; - } + if (IS_ERR(reg->regdev)) + return PTR_ERR(reg->regdev); platform_set_drvdata(pdev, reg); - return 0; - -error_regulator_register: -error_get_regulator_init_data: - vexpress_config_func_put(reg->func); -error_get_func: -error_kzalloc: - return err; -} - -static int vexpress_regulator_remove(struct platform_device *pdev) -{ - struct vexpress_regulator *reg = platform_get_drvdata(pdev); - - vexpress_config_func_put(reg->func); - return 0; } @@ -130,7 +105,6 @@ static struct of_device_id vexpress_regulator_of_match[] = { static struct platform_driver vexpress_regulator_driver = { .probe = vexpress_regulator_probe, - .remove = vexpress_regulator_remove, .driver = { .name = DRVNAME, .owner = THIS_MODULE, diff --git a/include/linux/vexpress.h b/include/linux/vexpress.h index 617c01b8f74a..6b206ba6aa0e 100644 --- a/include/linux/vexpress.h +++ b/include/linux/vexpress.h @@ -15,16 +15,15 @@ #define _LINUX_VEXPRESS_H #include +#include #include +#include #define VEXPRESS_SITE_MB 0 #define VEXPRESS_SITE_DB1 1 #define VEXPRESS_SITE_DB2 2 #define VEXPRESS_SITE_MASTER 0xf -#define VEXPRESS_CONFIG_STATUS_DONE 0 -#define VEXPRESS_CONFIG_STATUS_WAIT 1 - #define VEXPRESS_GPIO_MMC_CARDIN 0 #define VEXPRESS_GPIO_MMC_WPROT 1 #define VEXPRESS_GPIO_FLASH_WPn 2 @@ -44,63 +43,30 @@ .flags = IORESOURCE_BUS, \ } +/* Config infrastructure */ + +void vexpress_config_set_master(u32 site); +u32 vexpress_config_get_master(void); + +void vexpress_config_lock(void *arg); +void vexpress_config_unlock(void *arg); + +int vexpress_config_get_topo(struct device_node *node, u32 *site, + u32 *position, u32 *dcc); + /* Config bridge API */ -/** - * struct vexpress_config_bridge_info - description of the platform - * configuration infrastructure bridge. - * - * @name: Bridge name - * - * @func_get: Obtains pointer to a configuration function for a given - * device or a Device Tree node, to be used with @func_put - * and @func_exec. The node pointer should take precedence - * over device pointer when both are passed. - * - * @func_put: Tells the bridge that the function will not be used any - * more, so all allocated resources can be released. - * - * @func_exec: Executes a configuration function read or write operation. - * The offset selects a 32 bit word of the value accessed. - * Must return VEXPRESS_CONFIG_STATUS_DONE when operation - * is finished immediately, VEXPRESS_CONFIG_STATUS_WAIT when - * will be completed in some time or negative value in case - * of error. - */ -struct vexpress_config_bridge_info { - const char *name; - void *(*func_get)(struct device *dev, struct device_node *node); - void (*func_put)(void *func); - int (*func_exec)(void *func, int offset, bool write, u32 *data); +struct vexpress_config_bridge_ops { + struct regmap * (*regmap_init)(struct device *dev, void *context); + void (*regmap_exit)(struct regmap *regmap, void *context); }; -struct vexpress_config_bridge; +struct device *vexpress_config_bridge_register(struct device *parent, + struct vexpress_config_bridge_ops *ops, void *context); -struct vexpress_config_bridge *vexpress_config_bridge_register( - struct device_node *node, - struct vexpress_config_bridge_info *info); -void vexpress_config_bridge_unregister(struct vexpress_config_bridge *bridge); +/* Config regmap API */ -void vexpress_config_complete(struct vexpress_config_bridge *bridge, - int status); - -/* Config function API */ - -struct vexpress_config_func; - -struct vexpress_config_func *__vexpress_config_func_get(struct device *dev, - struct device_node *node); -#define vexpress_config_func_get_by_dev(dev) \ - __vexpress_config_func_get(dev, NULL) -#define vexpress_config_func_get_by_node(node) \ - __vexpress_config_func_get(NULL, node) -void vexpress_config_func_put(struct vexpress_config_func *func); - -/* Both may sleep! */ -int vexpress_config_read(struct vexpress_config_func *func, int offset, - u32 *data); -int vexpress_config_write(struct vexpress_config_func *func, int offset, - u32 data); +struct regmap *devm_regmap_init_vexpress_config(struct device *dev); /* Platform control */ @@ -109,19 +75,12 @@ u32 vexpress_get_hbi(int site); void *vexpress_get_24mhz_clock_base(void); void vexpress_flags_set(u32 data); -#define vexpress_get_site_by_node(node) __vexpress_get_site(NULL, node) -#define vexpress_get_site_by_dev(dev) __vexpress_get_site(dev, NULL) -unsigned __vexpress_get_site(struct device *dev, struct device_node *node); - void vexpress_sysreg_early_init(void __iomem *base); void vexpress_sysreg_of_early_init(void); +int vexpress_sysreg_config_device_register(struct platform_device *pdev); /* Clocks */ -struct clk *vexpress_osc_setup(struct device *dev); -void vexpress_osc_of_setup(struct device_node *node); - void vexpress_clk_init(void __iomem *sp810_base); -void vexpress_clk_of_init(void); #endif From 29f9b6cf7bff6a118130163c848811e14f8022da Mon Sep 17 00:00:00 2001 From: Pawel Moll Date: Wed, 12 Feb 2014 10:47:10 +0000 Subject: [PATCH 58/87] mfd: syscon: Add platform data with a regmap config name Define syscon platform data structure that can be used to define a regmap config name. This is particularly useful in the regmap debugfs when there is more than one syscon device registered, to distinguish the register blocks. Signed-off-by: Pawel Moll Acked-by: Lee Jones --- drivers/mfd/syscon.c | 4 ++++ include/linux/platform_data/syscon.h | 8 ++++++++ 2 files changed, 12 insertions(+) create mode 100644 include/linux/platform_data/syscon.h diff --git a/drivers/mfd/syscon.c b/drivers/mfd/syscon.c index dbea55de4397..e2a04bb8bc1e 100644 --- a/drivers/mfd/syscon.c +++ b/drivers/mfd/syscon.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -119,6 +120,7 @@ static struct regmap_config syscon_regmap_config = { static int syscon_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; + struct syscon_platform_data *pdata = dev_get_platdata(dev); struct syscon *syscon; struct resource *res; void __iomem *base; @@ -136,6 +138,8 @@ static int syscon_probe(struct platform_device *pdev) return -ENOMEM; syscon_regmap_config.max_register = res->end - res->start - 3; + if (pdata) + syscon_regmap_config.name = pdata->label; syscon->regmap = devm_regmap_init_mmio(dev, base, &syscon_regmap_config); if (IS_ERR(syscon->regmap)) { diff --git a/include/linux/platform_data/syscon.h b/include/linux/platform_data/syscon.h new file mode 100644 index 000000000000..2354c6fa3726 --- /dev/null +++ b/include/linux/platform_data/syscon.h @@ -0,0 +1,8 @@ +#ifndef PLATFORM_DATA_SYSCON_H +#define PLATFORM_DATA_SYSCON_H + +struct syscon_platform_data { + const char *label; +}; + +#endif From 974cc7b93441a0e78f030495436d1be7eb7c208d Mon Sep 17 00:00:00 2001 From: Pawel Moll Date: Wed, 23 Apr 2014 10:49:31 +0100 Subject: [PATCH 59/87] mfd: vexpress: Define the device as MFD cells This patch - finally, after over 6 months! :-( - addresses Samuel's request to split the vexpress-sysreg driver into smaller portions and define the device in a form of MFD cells: * LEDs code has been completely removed and replaced with "gpio-leds" nodes in the tree (referencing dedicated GPIO subnodes in sysreg - bindings documentation updated); this also better fits the reality as some variants of the motherboard don't have all the LEDs populated * syscfg bridge code has been extracted into a separate driver (placed in drivers/misc for no better place) * all the ID & MISC registers are defined as sysconf making them available for other drivers should they need to use them (and also to the user via /sys/kernel/debug/regmap which can be helpful in platform debugging) Signed-off-by: Pawel Moll Acked-by: Lee Jones --- .../bindings/arm/vexpress-sysreg.txt | 36 +- arch/arm/boot/dts/vexpress-v2m-rs1.dtsi | 76 ++- arch/arm/boot/dts/vexpress-v2m.dtsi | 76 ++- arch/arm/mach-vexpress/ct-ca9x4.c | 2 +- arch/arm/mach-vexpress/v2m.c | 15 +- drivers/mfd/Kconfig | 15 +- drivers/mfd/Makefile | 2 +- drivers/mfd/vexpress-sysreg.c | 547 +++++------------- drivers/misc/Kconfig | 9 + drivers/misc/Makefile | 1 + drivers/misc/vexpress-syscfg.c | 324 +++++++++++ include/linux/vexpress.h | 16 +- 12 files changed, 674 insertions(+), 445 deletions(-) create mode 100644 drivers/misc/vexpress-syscfg.c diff --git a/Documentation/devicetree/bindings/arm/vexpress-sysreg.txt b/Documentation/devicetree/bindings/arm/vexpress-sysreg.txt index 57b423f78995..00318d083c9e 100644 --- a/Documentation/devicetree/bindings/arm/vexpress-sysreg.txt +++ b/Documentation/devicetree/bindings/arm/vexpress-sysreg.txt @@ -8,6 +8,8 @@ interrupt generation, MMC and NOR Flash control etc. Required node properties: - compatible value : = "arm,vexpress,sysreg"; - reg : physical base address and the size of the registers window + +Deprecated properties, replaced by GPIO subnodes (see below): - gpio-controller : specifies that the node is a GPIO controller - #gpio-cells : size of the GPIO specifier, should be 2: - first cell is the pseudo-GPIO line number: @@ -16,12 +18,42 @@ Required node properties: 2 - NOR FLASH WPn - second cell can take standard GPIO flags (currently ignored). +Control registers providing pseudo-GPIO lines must be represented +by subnodes, each of them requiring the following properties: +- compatible value : one of + "arm,vexpress-sysreg,sys_led" + "arm,vexpress-sysreg,sys_mci" + "arm,vexpress-sysreg,sys_flash" +- gpio-controller : makes the node a GPIO controller +- #gpio-cells : size of the GPIO specifier, must be 2: + - first cell is the function number: + - for sys_led : 0..7 = LED 0..7 + - for sys_mci : 0 = MMC CARDIN, 1 = MMC WPROT + - for sys_flash : 0 = NOR FLASH WPn + - second cell can take standard GPIO flags (currently ignored). + Example: v2m_sysreg: sysreg@10000000 { compatible = "arm,vexpress-sysreg"; reg = <0x10000000 0x1000>; - gpio-controller; - #gpio-cells = <2>; + + v2m_led_gpios: sys_led@08 { + compatible = "arm,vexpress-sysreg,sys_led"; + gpio-controller; + #gpio-cells = <2>; + }; + + v2m_mmc_gpios: sys_mci@48 { + compatible = "arm,vexpress-sysreg,sys_mci"; + gpio-controller; + #gpio-cells = <2>; + }; + + v2m_flash_gpios: sys_flash@4c { + compatible = "arm,vexpress-sysreg,sys_flash"; + gpio-controller; + #gpio-cells = <2>; + }; }; This block also can also act a bridge to the platform's configuration diff --git a/arch/arm/boot/dts/vexpress-v2m-rs1.dtsi b/arch/arm/boot/dts/vexpress-v2m-rs1.dtsi index ac870fb3fa0d..756c986995a3 100644 --- a/arch/arm/boot/dts/vexpress-v2m-rs1.dtsi +++ b/arch/arm/boot/dts/vexpress-v2m-rs1.dtsi @@ -74,8 +74,24 @@ v2m_sysreg: sysreg@010000 { compatible = "arm,vexpress-sysreg"; reg = <0x010000 0x1000>; - gpio-controller; - #gpio-cells = <2>; + + v2m_led_gpios: sys_led@08 { + compatible = "arm,vexpress-sysreg,sys_led"; + gpio-controller; + #gpio-cells = <2>; + }; + + v2m_mmc_gpios: sys_mci@48 { + compatible = "arm,vexpress-sysreg,sys_mci"; + gpio-controller; + #gpio-cells = <2>; + }; + + v2m_flash_gpios: sys_flash@4c { + compatible = "arm,vexpress-sysreg,sys_flash"; + gpio-controller; + #gpio-cells = <2>; + }; }; v2m_sysctl: sysctl@020000 { @@ -113,8 +129,8 @@ compatible = "arm,pl180", "arm,primecell"; reg = <0x050000 0x1000>; interrupts = <9 10>; - cd-gpios = <&v2m_sysreg 0 0>; - wp-gpios = <&v2m_sysreg 1 0>; + cd-gpios = <&v2m_mmc_gpios 0 0>; + wp-gpios = <&v2m_mmc_gpios 1 0>; max-frequency = <12000000>; vmmc-supply = <&v2m_fixed_3v3>; clocks = <&v2m_clk24mhz>, <&smbclk>; @@ -265,6 +281,58 @@ clock-output-names = "v2m:refclk32khz"; }; + leds { + compatible = "gpio-leds"; + + user@1 { + label = "v2m:green:user1"; + gpios = <&v2m_led_gpios 0 0>; + linux,default-trigger = "heartbeat"; + }; + + user@2 { + label = "v2m:green:user2"; + gpios = <&v2m_led_gpios 1 0>; + linux,default-trigger = "mmc0"; + }; + + user@3 { + label = "v2m:green:user3"; + gpios = <&v2m_led_gpios 2 0>; + linux,default-trigger = "cpu0"; + }; + + user@4 { + label = "v2m:green:user4"; + gpios = <&v2m_led_gpios 3 0>; + linux,default-trigger = "cpu1"; + }; + + user@5 { + label = "v2m:green:user5"; + gpios = <&v2m_led_gpios 4 0>; + linux,default-trigger = "cpu2"; + }; + + user@6 { + label = "v2m:green:user6"; + gpios = <&v2m_led_gpios 5 0>; + linux,default-trigger = "cpu3"; + }; + + user@7 { + label = "v2m:green:user7"; + gpios = <&v2m_led_gpios 6 0>; + linux,default-trigger = "cpu4"; + }; + + user@8 { + label = "v2m:green:user8"; + gpios = <&v2m_led_gpios 7 0>; + linux,default-trigger = "cpu5"; + }; + }; + mcc { compatible = "arm,vexpress,config-bus"; arm,vexpress,config-bridge = <&v2m_sysreg>; diff --git a/arch/arm/boot/dts/vexpress-v2m.dtsi b/arch/arm/boot/dts/vexpress-v2m.dtsi index f1420368355b..ba856d604fb7 100644 --- a/arch/arm/boot/dts/vexpress-v2m.dtsi +++ b/arch/arm/boot/dts/vexpress-v2m.dtsi @@ -73,8 +73,24 @@ v2m_sysreg: sysreg@00000 { compatible = "arm,vexpress-sysreg"; reg = <0x00000 0x1000>; - gpio-controller; - #gpio-cells = <2>; + + v2m_led_gpios: sys_led@08 { + compatible = "arm,vexpress-sysreg,sys_led"; + gpio-controller; + #gpio-cells = <2>; + }; + + v2m_mmc_gpios: sys_mci@48 { + compatible = "arm,vexpress-sysreg,sys_mci"; + gpio-controller; + #gpio-cells = <2>; + }; + + v2m_flash_gpios: sys_flash@4c { + compatible = "arm,vexpress-sysreg,sys_flash"; + gpio-controller; + #gpio-cells = <2>; + }; }; v2m_sysctl: sysctl@01000 { @@ -112,8 +128,8 @@ compatible = "arm,pl180", "arm,primecell"; reg = <0x05000 0x1000>; interrupts = <9 10>; - cd-gpios = <&v2m_sysreg 0 0>; - wp-gpios = <&v2m_sysreg 1 0>; + cd-gpios = <&v2m_mmc_gpios 0 0>; + wp-gpios = <&v2m_mmc_gpios 1 0>; max-frequency = <12000000>; vmmc-supply = <&v2m_fixed_3v3>; clocks = <&v2m_clk24mhz>, <&smbclk>; @@ -264,6 +280,58 @@ clock-output-names = "v2m:refclk32khz"; }; + leds { + compatible = "gpio-leds"; + + user@1 { + label = "v2m:green:user1"; + gpios = <&v2m_led_gpios 0 0>; + linux,default-trigger = "heartbeat"; + }; + + user@2 { + label = "v2m:green:user2"; + gpios = <&v2m_led_gpios 1 0>; + linux,default-trigger = "mmc0"; + }; + + user@3 { + label = "v2m:green:user3"; + gpios = <&v2m_led_gpios 2 0>; + linux,default-trigger = "cpu0"; + }; + + user@4 { + label = "v2m:green:user4"; + gpios = <&v2m_led_gpios 3 0>; + linux,default-trigger = "cpu1"; + }; + + user@5 { + label = "v2m:green:user5"; + gpios = <&v2m_led_gpios 4 0>; + linux,default-trigger = "cpu2"; + }; + + user@6 { + label = "v2m:green:user6"; + gpios = <&v2m_led_gpios 5 0>; + linux,default-trigger = "cpu3"; + }; + + user@7 { + label = "v2m:green:user7"; + gpios = <&v2m_led_gpios 6 0>; + linux,default-trigger = "cpu4"; + }; + + user@8 { + label = "v2m:green:user8"; + gpios = <&v2m_led_gpios 7 0>; + linux,default-trigger = "cpu5"; + }; + }; + mcc { compatible = "arm,vexpress,config-bus"; arm,vexpress,config-bridge = <&v2m_sysreg>; diff --git a/arch/arm/mach-vexpress/ct-ca9x4.c b/arch/arm/mach-vexpress/ct-ca9x4.c index 35e394aa00e5..494d70bfddad 100644 --- a/arch/arm/mach-vexpress/ct-ca9x4.c +++ b/arch/arm/mach-vexpress/ct-ca9x4.c @@ -160,7 +160,7 @@ static void __init ct_ca9x4_init(void) amba_device_register(ct_ca9x4_amba_devs[i], &iomem_resource); platform_device_register(&pmu_device); - vexpress_sysreg_config_device_register(&osc1_device); + vexpress_syscfg_device_register(&osc1_device); } #ifdef CONFIG_SMP diff --git a/arch/arm/mach-vexpress/v2m.c b/arch/arm/mach-vexpress/v2m.c index ac95220a5019..90f04c9b11d2 100644 --- a/arch/arm/mach-vexpress/v2m.c +++ b/arch/arm/mach-vexpress/v2m.c @@ -201,8 +201,9 @@ static struct platform_device v2m_cf_device = { static struct mmci_platform_data v2m_mmci_data = { .ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34, - .gpio_wp = VEXPRESS_GPIO_MMC_WPROT, - .gpio_cd = VEXPRESS_GPIO_MMC_CARDIN, + .status = vexpress_get_mci_cardin, + .gpio_cd = -1, + .gpio_wp = -1, }; static struct resource v2m_sysreg_resources[] = { @@ -351,10 +352,10 @@ static void __init v2m_init(void) for (i = 0; i < ARRAY_SIZE(v2m_amba_devs); i++) amba_device_register(v2m_amba_devs[i], &iomem_resource); - vexpress_sysreg_config_device_register(&v2m_muxfpga_device); - vexpress_sysreg_config_device_register(&v2m_shutdown_device); - vexpress_sysreg_config_device_register(&v2m_reboot_device); - vexpress_sysreg_config_device_register(&v2m_dvimode_device); + vexpress_syscfg_device_register(&v2m_muxfpga_device); + vexpress_syscfg_device_register(&v2m_shutdown_device); + vexpress_syscfg_device_register(&v2m_reboot_device); + vexpress_syscfg_device_register(&v2m_dvimode_device); ct_desc->init_tile(); } @@ -409,8 +410,6 @@ void __init v2m_dt_init_early(void) { u32 dt_hbi; - vexpress_sysreg_of_early_init(); - /* Confirm board type against DT property, if available */ if (of_property_read_u32(of_allnodes, "arm,hbi", &dt_hbi) == 0) { u32 hbi = vexpress_get_hbi(VEXPRESS_SITE_MASTER); diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 33834120d057..490fd48a9541 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -1227,12 +1227,17 @@ config MCP_UCB1200_TS endmenu -config VEXPRESS_CONFIG - bool "ARM Versatile Express platform infrastructure" - depends on ARM || ARM64 +config MFD_VEXPRESS_SYSREG + bool "Versatile Express System Registers" + depends on VEXPRESS_CONFIG + default y + select CLKSRC_MMIO + select GPIO_GENERIC_PLATFORM + select MFD_CORE + select MFD_SYSCON help - Platform configuration infrastructure for the ARM Ltd. - Versatile Express. + System Registers are the platform configuration block + on the ARM Ltd. Versatile Express board. endmenu endif diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 9ba838eb5131..cec3487b539e 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -161,7 +161,7 @@ obj-$(CONFIG_MFD_RC5T583) += rc5t583.o rc5t583-irq.o obj-$(CONFIG_MFD_SEC_CORE) += sec-core.o sec-irq.o obj-$(CONFIG_MFD_SYSCON) += syscon.o obj-$(CONFIG_MFD_LM3533) += lm3533-core.o lm3533-ctrlbank.o -obj-$(CONFIG_VEXPRESS_CONFIG) += vexpress-sysreg.o +obj-$(CONFIG_MFD_VEXPRESS_SYSREG) += vexpress-sysreg.o obj-$(CONFIG_MFD_RETU) += retu-mfd.o obj-$(CONFIG_MFD_AS3711) += as3711.o obj-$(CONFIG_MFD_AS3722) += as3722.o diff --git a/drivers/mfd/vexpress-sysreg.c b/drivers/mfd/vexpress-sysreg.c index b4138a7168db..952df843b6be 100644 --- a/drivers/mfd/vexpress-sysreg.c +++ b/drivers/mfd/vexpress-sysreg.c @@ -11,25 +11,22 @@ * Copyright (C) 2012 ARM Limited */ +#include #include -#include #include -#include +#include #include #include +#include #include -#include -#include #include #include -#include #include #define SYS_ID 0x000 #define SYS_SW 0x004 #define SYS_LED 0x008 #define SYS_100HZ 0x024 -#define SYS_FLAGS 0x030 #define SYS_FLAGSSET 0x030 #define SYS_FLAGSCLR 0x034 #define SYS_NVFLAGS 0x038 @@ -51,36 +48,32 @@ #define SYS_ID_HBI_SHIFT 16 #define SYS_PROCIDx_HBI_SHIFT 0 -#define SYS_LED_LED(n) (1 << (n)) - #define SYS_MCI_CARDIN (1 << 0) #define SYS_MCI_WPROT (1 << 1) -#define SYS_FLASH_WPn (1 << 0) - #define SYS_MISC_MASTERSITE (1 << 14) -#define SYS_CFGCTRL_START (1 << 31) -#define SYS_CFGCTRL_WRITE (1 << 30) -#define SYS_CFGCTRL_DCC(n) (((n) & 0xf) << 26) -#define SYS_CFGCTRL_FUNC(n) (((n) & 0x3f) << 20) -#define SYS_CFGCTRL_SITE(n) (((n) & 0x3) << 16) -#define SYS_CFGCTRL_POSITION(n) (((n) & 0xf) << 12) -#define SYS_CFGCTRL_DEVICE(n) (((n) & 0xfff) << 0) -#define SYS_CFGSTAT_ERR (1 << 1) -#define SYS_CFGSTAT_COMPLETE (1 << 0) +static void __iomem *__vexpress_sysreg_base; +static void __iomem *vexpress_sysreg_base(void) +{ + if (!__vexpress_sysreg_base) { + struct device_node *node = of_find_compatible_node(NULL, NULL, + "arm,vexpress-sysreg"); -static void __iomem *vexpress_sysreg_base; -static struct device *vexpress_sysreg_dev; -static LIST_HEAD(vexpress_sysreg_config_funcs); -static struct device *vexpress_sysreg_config_bridge; + __vexpress_sysreg_base = of_iomap(node, 0); + } + + WARN_ON(!__vexpress_sysreg_base); + + return __vexpress_sysreg_base; +} static int vexpress_sysreg_get_master(void) { - if (readl(vexpress_sysreg_base + SYS_MISC) & SYS_MISC_MASTERSITE) + if (readl(vexpress_sysreg_base() + SYS_MISC) & SYS_MISC_MASTERSITE) return VEXPRESS_SITE_DB2; return VEXPRESS_SITE_DB1; @@ -88,8 +81,13 @@ static int vexpress_sysreg_get_master(void) void vexpress_flags_set(u32 data) { - writel(~0, vexpress_sysreg_base + SYS_FLAGSCLR); - writel(data, vexpress_sysreg_base + SYS_FLAGSSET); + writel(~0, vexpress_sysreg_base() + SYS_FLAGSCLR); + writel(data, vexpress_sysreg_base() + SYS_FLAGSSET); +} + +unsigned int vexpress_get_mci_cardin(struct device *dev) +{ + return readl(vexpress_sysreg_base() + SYS_MCI) & SYS_MCI_CARDIN; } u32 vexpress_get_procid(int site) @@ -97,7 +95,7 @@ u32 vexpress_get_procid(int site) if (site == VEXPRESS_SITE_MASTER) site = vexpress_sysreg_get_master(); - return readl(vexpress_sysreg_base + (site == VEXPRESS_SITE_DB1 ? + return readl(vexpress_sysreg_base() + (site == VEXPRESS_SITE_DB1 ? SYS_PROCID0 : SYS_PROCID1)); } @@ -107,7 +105,7 @@ u32 vexpress_get_hbi(int site) switch (site) { case VEXPRESS_SITE_MB: - id = readl(vexpress_sysreg_base + SYS_ID); + id = readl(vexpress_sysreg_base() + SYS_ID); return (id >> SYS_ID_HBI_SHIFT) & SYS_HBI_MASK; case VEXPRESS_SITE_MASTER: case VEXPRESS_SITE_DB1: @@ -121,406 +119,143 @@ u32 vexpress_get_hbi(int site) void __iomem *vexpress_get_24mhz_clock_base(void) { - return vexpress_sysreg_base + SYS_24MHZ; -} - - -struct vexpress_sysreg_config_func { - struct list_head list; - struct regmap *regmap; - int num_templates; - u32 template[0]; /* Keep this last */ -}; - -static int vexpress_sysreg_config_exec(struct vexpress_sysreg_config_func *func, - int index, bool write, u32 *data) -{ - u32 command, status; - int tries; - long timeout; - - if (WARN_ON(!vexpress_sysreg_base)) - return -ENOENT; - - if (WARN_ON(index > func->num_templates)) - return -EINVAL; - - command = readl(vexpress_sysreg_base + SYS_CFGCTRL); - if (WARN_ON(command & SYS_CFGCTRL_START)) - return -EBUSY; - - command = func->template[index]; - command |= SYS_CFGCTRL_START; - command |= write ? SYS_CFGCTRL_WRITE : 0; - - /* Use a canary for reads */ - if (!write) - *data = 0xdeadbeef; - - dev_dbg(vexpress_sysreg_dev, "command %x, data %x\n", - command, *data); - writel(*data, vexpress_sysreg_base + SYS_CFGDATA); - writel(0, vexpress_sysreg_base + SYS_CFGSTAT); - writel(command, vexpress_sysreg_base + SYS_CFGCTRL); - mb(); - - /* The operation can take ages... Go to sleep, 100us initially */ - tries = 100; - timeout = 100; - do { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(usecs_to_jiffies(timeout)); - if (signal_pending(current)) - return -EINTR; - - status = readl(vexpress_sysreg_base + SYS_CFGSTAT); - if (status & SYS_CFGSTAT_ERR) - return -EFAULT; - - if (timeout > 20) - timeout -= 20; - } while (--tries && !(status & SYS_CFGSTAT_COMPLETE)); - if (WARN_ON_ONCE(!tries)) - return -ETIMEDOUT; - - if (!write) { - *data = readl(vexpress_sysreg_base + SYS_CFGDATA); - dev_dbg(vexpress_sysreg_dev, "func %p, read data %x\n", - func, *data); - } - - return 0; -} - -static int vexpress_sysreg_config_read(void *context, unsigned int index, - unsigned int *val) -{ - struct vexpress_sysreg_config_func *func = context; - - return vexpress_sysreg_config_exec(func, index, false, val); -} - -static int vexpress_sysreg_config_write(void *context, unsigned int index, - unsigned int val) -{ - struct vexpress_sysreg_config_func *func = context; - - return vexpress_sysreg_config_exec(func, index, true, &val); -} - -struct regmap_config vexpress_sysreg_regmap_config = { - .lock = vexpress_config_lock, - .unlock = vexpress_config_unlock, - .reg_bits = 32, - .val_bits = 32, - .reg_read = vexpress_sysreg_config_read, - .reg_write = vexpress_sysreg_config_write, - .reg_format_endian = REGMAP_ENDIAN_LITTLE, - .val_format_endian = REGMAP_ENDIAN_LITTLE, -}; - -static struct regmap *vexpress_sysreg_config_regmap_init(struct device *dev, - void *context) -{ - struct platform_device *pdev = to_platform_device(dev); - struct vexpress_sysreg_config_func *func; - struct property *prop; - const __be32 *val = NULL; - __be32 energy_quirk[4]; - int num; - u32 site, position, dcc; - int err; - int i; - - if (dev->of_node) { - err = vexpress_config_get_topo(dev->of_node, &site, &position, - &dcc); - if (err) - return ERR_PTR(err); - - prop = of_find_property(dev->of_node, - "arm,vexpress-sysreg,func", NULL); - if (!prop) - return ERR_PTR(-EINVAL); - - num = prop->length / sizeof(u32) / 2; - val = prop->value; - } else { - if (pdev->num_resources != 1 || - pdev->resource[0].flags != IORESOURCE_BUS) - return ERR_PTR(-EFAULT); - - site = pdev->resource[0].start; - if (site == VEXPRESS_SITE_MASTER) - site = vexpress_sysreg_get_master(); - position = 0; - dcc = 0; - num = 1; - } - - /* - * "arm,vexpress-energy" function used to be described - * by its first device only, now it requires both - */ - if (num == 1 && of_device_is_compatible(dev->of_node, - "arm,vexpress-energy")) { - num = 2; - energy_quirk[0] = *val; - energy_quirk[2] = *val++; - energy_quirk[1] = *val; - energy_quirk[3] = cpu_to_be32(be32_to_cpup(val) + 1); - val = energy_quirk; - } - - func = kzalloc(sizeof(*func) + sizeof(*func->template) * num, - GFP_KERNEL); - if (!func) - return NULL; - - func->num_templates = num; - - for (i = 0; i < num; i++) { - u32 function, device; - - if (dev->of_node) { - function = be32_to_cpup(val++); - device = be32_to_cpup(val++); - } else { - function = pdev->resource[0].end; - device = pdev->id; - } - - dev_dbg(dev, "func %p: %u/%u/%u/%u/%u\n", - func, site, position, dcc, - function, device); - - func->template[i] = SYS_CFGCTRL_DCC(dcc); - func->template[i] |= SYS_CFGCTRL_SITE(site); - func->template[i] |= SYS_CFGCTRL_POSITION(position); - func->template[i] |= SYS_CFGCTRL_FUNC(function); - func->template[i] |= SYS_CFGCTRL_DEVICE(device); - } - - vexpress_sysreg_regmap_config.max_register = num - 1; - - func->regmap = regmap_init(dev, NULL, func, - &vexpress_sysreg_regmap_config); - - if (IS_ERR(func->regmap)) - kfree(func); - else - list_add(&func->list, &vexpress_sysreg_config_funcs); - - return func->regmap; -} - -static void vexpress_sysreg_config_regmap_exit(struct regmap *regmap, - void *context) -{ - struct vexpress_sysreg_config_func *func, *tmp; - - regmap_exit(regmap); - - list_for_each_entry_safe(func, tmp, &vexpress_sysreg_config_funcs, - list) { - if (func->regmap == regmap) { - list_del(&vexpress_sysreg_config_funcs); - kfree(func); - break; - } - } -} - -static struct vexpress_config_bridge_ops vexpress_sysreg_config_bridge_ops = { - .regmap_init = vexpress_sysreg_config_regmap_init, - .regmap_exit = vexpress_sysreg_config_regmap_exit, -}; - -int vexpress_sysreg_config_device_register(struct platform_device *pdev) -{ - pdev->dev.parent = vexpress_sysreg_config_bridge; - - return platform_device_register(pdev); + return vexpress_sysreg_base() + SYS_24MHZ; } void __init vexpress_sysreg_early_init(void __iomem *base) { - vexpress_sysreg_base = base; - vexpress_config_set_master(vexpress_sysreg_get_master()); -} - -void __init vexpress_sysreg_of_early_init(void) -{ - struct device_node *node; - - if (vexpress_sysreg_base) - return; - - node = of_find_compatible_node(NULL, NULL, "arm,vexpress-sysreg"); - if (WARN_ON(!node)) - return; - - vexpress_sysreg_base = of_iomap(node, 0); - if (WARN_ON(!vexpress_sysreg_base)) - return; + __vexpress_sysreg_base = base; vexpress_config_set_master(vexpress_sysreg_get_master()); } -#ifdef CONFIG_GPIOLIB +/* The sysreg block is just a random collection of various functions... */ -#define VEXPRESS_SYSREG_GPIO(_name, _reg, _value) \ - [VEXPRESS_GPIO_##_name] = { \ - .reg = _reg, \ - .value = _reg##_##_value, \ +static struct syscon_platform_data vexpress_sysreg_sys_id_pdata = { + .label = "sys_id", +}; + +static struct bgpio_pdata vexpress_sysreg_sys_led_pdata = { + .label = "sys_led", + .base = -1, + .ngpio = 8, +}; + +static struct bgpio_pdata vexpress_sysreg_sys_mci_pdata = { + .label = "sys_mci", + .base = -1, + .ngpio = 2, +}; + +static struct bgpio_pdata vexpress_sysreg_sys_flash_pdata = { + .label = "sys_flash", + .base = -1, + .ngpio = 1, +}; + +static struct syscon_platform_data vexpress_sysreg_sys_misc_pdata = { + .label = "sys_misc", +}; + +static struct syscon_platform_data vexpress_sysreg_sys_procid_pdata = { + .label = "sys_procid", +}; + +static struct mfd_cell vexpress_sysreg_cells[] = { + { + .name = "syscon", + .num_resources = 1, + .resources = (struct resource []) { + DEFINE_RES_MEM(SYS_ID, 0x4), + }, + .platform_data = &vexpress_sysreg_sys_id_pdata, + .pdata_size = sizeof(vexpress_sysreg_sys_id_pdata), + }, { + .name = "basic-mmio-gpio", + .of_compatible = "arm,vexpress-sysreg,sys_led", + .num_resources = 1, + .resources = (struct resource []) { + DEFINE_RES_MEM_NAMED(SYS_LED, 0x4, "dat"), + }, + .platform_data = &vexpress_sysreg_sys_led_pdata, + .pdata_size = sizeof(vexpress_sysreg_sys_led_pdata), + }, { + .name = "basic-mmio-gpio", + .of_compatible = "arm,vexpress-sysreg,sys_mci", + .num_resources = 1, + .resources = (struct resource []) { + DEFINE_RES_MEM_NAMED(SYS_MCI, 0x4, "dat"), + }, + .platform_data = &vexpress_sysreg_sys_mci_pdata, + .pdata_size = sizeof(vexpress_sysreg_sys_mci_pdata), + }, { + .name = "basic-mmio-gpio", + .of_compatible = "arm,vexpress-sysreg,sys_flash", + .num_resources = 1, + .resources = (struct resource []) { + DEFINE_RES_MEM_NAMED(SYS_FLASH, 0x4, "dat"), + }, + .platform_data = &vexpress_sysreg_sys_flash_pdata, + .pdata_size = sizeof(vexpress_sysreg_sys_flash_pdata), + }, { + .name = "syscon", + .num_resources = 1, + .resources = (struct resource []) { + DEFINE_RES_MEM(SYS_MISC, 0x4), + }, + .platform_data = &vexpress_sysreg_sys_misc_pdata, + .pdata_size = sizeof(vexpress_sysreg_sys_misc_pdata), + }, { + .name = "syscon", + .num_resources = 1, + .resources = (struct resource []) { + DEFINE_RES_MEM(SYS_PROCID0, 0x8), + }, + .platform_data = &vexpress_sysreg_sys_procid_pdata, + .pdata_size = sizeof(vexpress_sysreg_sys_procid_pdata), + }, { + .name = "vexpress-syscfg", + .num_resources = 1, + .resources = (struct resource []) { + DEFINE_RES_MEM(SYS_CFGDATA, 0xc), + }, } - -static struct vexpress_sysreg_gpio { - unsigned long reg; - u32 value; -} vexpress_sysreg_gpios[] = { - VEXPRESS_SYSREG_GPIO(MMC_CARDIN, SYS_MCI, CARDIN), - VEXPRESS_SYSREG_GPIO(MMC_WPROT, SYS_MCI, WPROT), - VEXPRESS_SYSREG_GPIO(FLASH_WPn, SYS_FLASH, WPn), - VEXPRESS_SYSREG_GPIO(LED0, SYS_LED, LED(0)), - VEXPRESS_SYSREG_GPIO(LED1, SYS_LED, LED(1)), - VEXPRESS_SYSREG_GPIO(LED2, SYS_LED, LED(2)), - VEXPRESS_SYSREG_GPIO(LED3, SYS_LED, LED(3)), - VEXPRESS_SYSREG_GPIO(LED4, SYS_LED, LED(4)), - VEXPRESS_SYSREG_GPIO(LED5, SYS_LED, LED(5)), - VEXPRESS_SYSREG_GPIO(LED6, SYS_LED, LED(6)), - VEXPRESS_SYSREG_GPIO(LED7, SYS_LED, LED(7)), }; -static int vexpress_sysreg_gpio_direction_input(struct gpio_chip *chip, - unsigned offset) -{ - return 0; -} - -static int vexpress_sysreg_gpio_get(struct gpio_chip *chip, - unsigned offset) -{ - struct vexpress_sysreg_gpio *gpio = &vexpress_sysreg_gpios[offset]; - u32 reg_value = readl(vexpress_sysreg_base + gpio->reg); - - return !!(reg_value & gpio->value); -} - -static void vexpress_sysreg_gpio_set(struct gpio_chip *chip, - unsigned offset, int value) -{ - struct vexpress_sysreg_gpio *gpio = &vexpress_sysreg_gpios[offset]; - u32 reg_value = readl(vexpress_sysreg_base + gpio->reg); - - if (value) - reg_value |= gpio->value; - else - reg_value &= ~gpio->value; - - writel(reg_value, vexpress_sysreg_base + gpio->reg); -} - -static int vexpress_sysreg_gpio_direction_output(struct gpio_chip *chip, - unsigned offset, int value) -{ - vexpress_sysreg_gpio_set(chip, offset, value); - - return 0; -} - -static struct gpio_chip vexpress_sysreg_gpio_chip = { - .label = "vexpress-sysreg", - .direction_input = vexpress_sysreg_gpio_direction_input, - .direction_output = vexpress_sysreg_gpio_direction_output, - .get = vexpress_sysreg_gpio_get, - .set = vexpress_sysreg_gpio_set, - .ngpio = ARRAY_SIZE(vexpress_sysreg_gpios), - .base = 0, -}; - - -#define VEXPRESS_SYSREG_GREEN_LED(_name, _default_trigger, _gpio) \ - { \ - .name = "v2m:green:"_name, \ - .default_trigger = _default_trigger, \ - .gpio = VEXPRESS_GPIO_##_gpio, \ - } - -struct gpio_led vexpress_sysreg_leds[] = { - VEXPRESS_SYSREG_GREEN_LED("user1", "heartbeat", LED0), - VEXPRESS_SYSREG_GREEN_LED("user2", "mmc0", LED1), - VEXPRESS_SYSREG_GREEN_LED("user3", "cpu0", LED2), - VEXPRESS_SYSREG_GREEN_LED("user4", "cpu1", LED3), - VEXPRESS_SYSREG_GREEN_LED("user5", "cpu2", LED4), - VEXPRESS_SYSREG_GREEN_LED("user6", "cpu3", LED5), - VEXPRESS_SYSREG_GREEN_LED("user7", "cpu4", LED6), - VEXPRESS_SYSREG_GREEN_LED("user8", "cpu5", LED7), -}; - -struct gpio_led_platform_data vexpress_sysreg_leds_pdata = { - .num_leds = ARRAY_SIZE(vexpress_sysreg_leds), - .leds = vexpress_sysreg_leds, -}; - -#endif - - -static ssize_t vexpress_sysreg_sys_id_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - return sprintf(buf, "0x%08x\n", readl(vexpress_sysreg_base + SYS_ID)); -} - -DEVICE_ATTR(sys_id, S_IRUGO, vexpress_sysreg_sys_id_show, NULL); - static int vexpress_sysreg_probe(struct platform_device *pdev) { - int err; - struct resource *res = platform_get_resource(pdev, - IORESOURCE_MEM, 0); + struct resource *mem; + void __iomem *base; + struct bgpio_chip *mmc_gpio_chip; - if (!devm_request_mem_region(&pdev->dev, res->start, - resource_size(res), pdev->name)) { - dev_err(&pdev->dev, "Failed to request memory region!\n"); - return -EBUSY; - } + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!mem) + return -EINVAL; - if (!vexpress_sysreg_base) - vexpress_sysreg_base = devm_ioremap(&pdev->dev, res->start, - resource_size(res)); - - if (!vexpress_sysreg_base) { - dev_err(&pdev->dev, "Failed to obtain base address!\n"); - return -EFAULT; - } + base = devm_ioremap(&pdev->dev, mem->start, resource_size(mem)); + if (!base) + return -ENOMEM; vexpress_config_set_master(vexpress_sysreg_get_master()); - vexpress_sysreg_dev = &pdev->dev; -#ifdef CONFIG_GPIOLIB - vexpress_sysreg_gpio_chip.dev = &pdev->dev; - err = gpiochip_add(&vexpress_sysreg_gpio_chip); - if (err) { - dev_err(&pdev->dev, "Failed to register GPIO chip! (%d)\n", - err); - return err; - } + /* + * Duplicated SYS_MCI pseudo-GPIO controller for compatibility with + * older trees using sysreg node for MMC control lines. + */ + mmc_gpio_chip = devm_kzalloc(&pdev->dev, sizeof(*mmc_gpio_chip), + GFP_KERNEL); + if (!mmc_gpio_chip) + return -ENOMEM; + bgpio_init(mmc_gpio_chip, &pdev->dev, 0x4, base + SYS_MCI, + NULL, NULL, NULL, NULL, 0); + mmc_gpio_chip->gc.ngpio = 2; + gpiochip_add(&mmc_gpio_chip->gc); - platform_device_register_data(vexpress_sysreg_dev, "leds-gpio", - PLATFORM_DEVID_AUTO, &vexpress_sysreg_leds_pdata, - sizeof(vexpress_sysreg_leds_pdata)); -#endif - - vexpress_sysreg_config_bridge = vexpress_config_bridge_register( - &pdev->dev, &vexpress_sysreg_config_bridge_ops, NULL); - WARN_ON(!vexpress_sysreg_config_bridge); - - device_create_file(vexpress_sysreg_dev, &dev_attr_sys_id); - - return 0; + return mfd_add_devices(&pdev->dev, PLATFORM_DEVID_AUTO, + vexpress_sysreg_cells, + ARRAY_SIZE(vexpress_sysreg_cells), mem, 0, NULL); } static const struct of_device_id vexpress_sysreg_match[] = { diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 8baff0effc7d..d9663ef90ce8 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -515,6 +515,15 @@ config SRAM the genalloc API. It is supposed to be used for small on-chip SRAM areas found on many SoCs. +config VEXPRESS_SYSCFG + bool "Versatile Express System Configuration driver" + depends on VEXPRESS_CONFIG + default y + help + ARM Ltd. Versatile Express uses specialised platform configuration + bus. System Configuration interface is one of the possible means + of generating transactions on this bus. + source "drivers/misc/c2port/Kconfig" source "drivers/misc/eeprom/Kconfig" source "drivers/misc/cb710/Kconfig" diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index 7eb4b69580c0..d59ce1261b38 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -55,3 +55,4 @@ obj-$(CONFIG_SRAM) += sram.o obj-y += mic/ obj-$(CONFIG_GENWQE) += genwqe/ obj-$(CONFIG_ECHO) += echo/ +obj-$(CONFIG_VEXPRESS_SYSCFG) += vexpress-syscfg.o diff --git a/drivers/misc/vexpress-syscfg.c b/drivers/misc/vexpress-syscfg.c new file mode 100644 index 000000000000..73068e50e56d --- /dev/null +++ b/drivers/misc/vexpress-syscfg.c @@ -0,0 +1,324 @@ +/* + * 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. + * + * 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. + * + * Copyright (C) 2014 ARM Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define SYS_CFGDATA 0x0 + +#define SYS_CFGCTRL 0x4 +#define SYS_CFGCTRL_START (1 << 31) +#define SYS_CFGCTRL_WRITE (1 << 30) +#define SYS_CFGCTRL_DCC(n) (((n) & 0xf) << 26) +#define SYS_CFGCTRL_FUNC(n) (((n) & 0x3f) << 20) +#define SYS_CFGCTRL_SITE(n) (((n) & 0x3) << 16) +#define SYS_CFGCTRL_POSITION(n) (((n) & 0xf) << 12) +#define SYS_CFGCTRL_DEVICE(n) (((n) & 0xfff) << 0) + +#define SYS_CFGSTAT 0x8 +#define SYS_CFGSTAT_ERR (1 << 1) +#define SYS_CFGSTAT_COMPLETE (1 << 0) + + +struct vexpress_syscfg { + struct device *dev; + void __iomem *base; + struct list_head funcs; +}; + +struct vexpress_syscfg_func { + struct list_head list; + struct vexpress_syscfg *syscfg; + struct regmap *regmap; + int num_templates; + u32 template[0]; /* Keep it last! */ +}; + + +static int vexpress_syscfg_exec(struct vexpress_syscfg_func *func, + int index, bool write, u32 *data) +{ + struct vexpress_syscfg *syscfg = func->syscfg; + u32 command, status; + int tries; + long timeout; + + if (WARN_ON(index > func->num_templates)) + return -EINVAL; + + command = readl(syscfg->base + SYS_CFGCTRL); + if (WARN_ON(command & SYS_CFGCTRL_START)) + return -EBUSY; + + command = func->template[index]; + command |= SYS_CFGCTRL_START; + command |= write ? SYS_CFGCTRL_WRITE : 0; + + /* Use a canary for reads */ + if (!write) + *data = 0xdeadbeef; + + dev_dbg(syscfg->dev, "func %p, command %x, data %x\n", + func, command, *data); + writel(*data, syscfg->base + SYS_CFGDATA); + writel(0, syscfg->base + SYS_CFGSTAT); + writel(command, syscfg->base + SYS_CFGCTRL); + mb(); + + /* The operation can take ages... Go to sleep, 100us initially */ + tries = 100; + timeout = 100; + do { + if (!irqs_disabled()) { + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(usecs_to_jiffies(timeout)); + if (signal_pending(current)) + return -EINTR; + } else { + udelay(timeout); + } + + status = readl(syscfg->base + SYS_CFGSTAT); + if (status & SYS_CFGSTAT_ERR) + return -EFAULT; + + if (timeout > 20) + timeout -= 20; + } while (--tries && !(status & SYS_CFGSTAT_COMPLETE)); + if (WARN_ON_ONCE(!tries)) + return -ETIMEDOUT; + + if (!write) { + *data = readl(syscfg->base + SYS_CFGDATA); + dev_dbg(syscfg->dev, "func %p, read data %x\n", func, *data); + } + + return 0; +} + +static int vexpress_syscfg_read(void *context, unsigned int index, + unsigned int *val) +{ + struct vexpress_syscfg_func *func = context; + + return vexpress_syscfg_exec(func, index, false, val); +} + +static int vexpress_syscfg_write(void *context, unsigned int index, + unsigned int val) +{ + struct vexpress_syscfg_func *func = context; + + return vexpress_syscfg_exec(func, index, true, &val); +} + +struct regmap_config vexpress_syscfg_regmap_config = { + .lock = vexpress_config_lock, + .unlock = vexpress_config_unlock, + .reg_bits = 32, + .val_bits = 32, + .reg_read = vexpress_syscfg_read, + .reg_write = vexpress_syscfg_write, + .reg_format_endian = REGMAP_ENDIAN_LITTLE, + .val_format_endian = REGMAP_ENDIAN_LITTLE, +}; + + +static struct regmap *vexpress_syscfg_regmap_init(struct device *dev, + void *context) +{ + struct platform_device *pdev = to_platform_device(dev); + struct vexpress_syscfg *syscfg = context; + struct vexpress_syscfg_func *func; + struct property *prop; + const __be32 *val = NULL; + __be32 energy_quirk[4]; + int num; + u32 site, position, dcc; + int i; + + if (dev->of_node) { + int err = vexpress_config_get_topo(dev->of_node, &site, + &position, &dcc); + + if (err) + return ERR_PTR(err); + + prop = of_find_property(dev->of_node, + "arm,vexpress-sysreg,func", NULL); + if (!prop) + return ERR_PTR(-EINVAL); + + num = prop->length / sizeof(u32) / 2; + val = prop->value; + } else { + if (pdev->num_resources != 1 || + pdev->resource[0].flags != IORESOURCE_BUS) + return ERR_PTR(-EFAULT); + + site = pdev->resource[0].start; + if (site == VEXPRESS_SITE_MASTER) + site = vexpress_config_get_master(); + position = 0; + dcc = 0; + num = 1; + } + + /* + * "arm,vexpress-energy" function used to be described + * by its first device only, now it requires both + */ + if (num == 1 && of_device_is_compatible(dev->of_node, + "arm,vexpress-energy")) { + num = 2; + energy_quirk[0] = *val; + energy_quirk[2] = *val++; + energy_quirk[1] = *val; + energy_quirk[3] = cpu_to_be32(be32_to_cpup(val) + 1); + val = energy_quirk; + } + + func = kzalloc(sizeof(*func) + sizeof(*func->template) * num, + GFP_KERNEL); + if (!func) + return NULL; + + func->syscfg = syscfg; + func->num_templates = num; + + for (i = 0; i < num; i++) { + u32 function, device; + + if (dev->of_node) { + function = be32_to_cpup(val++); + device = be32_to_cpup(val++); + } else { + function = pdev->resource[0].end; + device = pdev->id; + } + + dev_dbg(dev, "func %p: %u/%u/%u/%u/%u\n", + func, site, position, dcc, + function, device); + + func->template[i] = SYS_CFGCTRL_DCC(dcc); + func->template[i] |= SYS_CFGCTRL_SITE(site); + func->template[i] |= SYS_CFGCTRL_POSITION(position); + func->template[i] |= SYS_CFGCTRL_FUNC(function); + func->template[i] |= SYS_CFGCTRL_DEVICE(device); + } + + vexpress_syscfg_regmap_config.max_register = num - 1; + + func->regmap = regmap_init(dev, NULL, func, + &vexpress_syscfg_regmap_config); + + if (IS_ERR(func->regmap)) + kfree(func); + else + list_add(&func->list, &syscfg->funcs); + + return func->regmap; +} + +static void vexpress_syscfg_regmap_exit(struct regmap *regmap, void *context) +{ + struct vexpress_syscfg *syscfg = context; + struct vexpress_syscfg_func *func, *tmp; + + regmap_exit(regmap); + + list_for_each_entry_safe(func, tmp, &syscfg->funcs, list) { + if (func->regmap == regmap) { + list_del(&syscfg->funcs); + kfree(func); + break; + } + } +} + +static struct vexpress_config_bridge_ops vexpress_syscfg_bridge_ops = { + .regmap_init = vexpress_syscfg_regmap_init, + .regmap_exit = vexpress_syscfg_regmap_exit, +}; + + +/* Non-DT hack, to be gone... */ +static struct device *vexpress_syscfg_bridge; + +int vexpress_syscfg_device_register(struct platform_device *pdev) +{ + pdev->dev.parent = vexpress_syscfg_bridge; + + return platform_device_register(pdev); +} + + +int vexpress_syscfg_probe(struct platform_device *pdev) +{ + struct vexpress_syscfg *syscfg; + struct resource *res; + struct device *bridge; + + syscfg = devm_kzalloc(&pdev->dev, sizeof(*syscfg), GFP_KERNEL); + if (!syscfg) + return -ENOMEM; + syscfg->dev = &pdev->dev; + INIT_LIST_HEAD(&syscfg->funcs); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!devm_request_mem_region(&pdev->dev, res->start, + resource_size(res), pdev->name)) + return -EBUSY; + + syscfg->base = devm_ioremap(&pdev->dev, res->start, resource_size(res)); + if (!syscfg->base) + return -EFAULT; + + /* Must use dev.parent (MFD), as that's where DT phandle points at... */ + bridge = vexpress_config_bridge_register(pdev->dev.parent, + &vexpress_syscfg_bridge_ops, syscfg); + if (IS_ERR(bridge)) + return PTR_ERR(bridge); + + /* Non-DT case */ + if (!pdev->dev.of_node) + vexpress_syscfg_bridge = bridge; + + return 0; +} + +static const struct platform_device_id vexpress_syscfg_id_table[] = { + { "vexpress-syscfg", }, + {}, +}; + +static struct platform_driver vexpress_syscfg_driver = { + .driver.name = "vexpress-syscfg", + .id_table = vexpress_syscfg_id_table, + .probe = vexpress_syscfg_probe, +}; + +static int __init vexpress_syscfg_init(void) +{ + return platform_driver_register(&vexpress_syscfg_driver); +} +core_initcall(vexpress_syscfg_init); diff --git a/include/linux/vexpress.h b/include/linux/vexpress.h index 6b206ba6aa0e..46636e3f43fd 100644 --- a/include/linux/vexpress.h +++ b/include/linux/vexpress.h @@ -24,18 +24,6 @@ #define VEXPRESS_SITE_DB2 2 #define VEXPRESS_SITE_MASTER 0xf -#define VEXPRESS_GPIO_MMC_CARDIN 0 -#define VEXPRESS_GPIO_MMC_WPROT 1 -#define VEXPRESS_GPIO_FLASH_WPn 2 -#define VEXPRESS_GPIO_LED0 3 -#define VEXPRESS_GPIO_LED1 4 -#define VEXPRESS_GPIO_LED2 5 -#define VEXPRESS_GPIO_LED3 6 -#define VEXPRESS_GPIO_LED4 7 -#define VEXPRESS_GPIO_LED5 8 -#define VEXPRESS_GPIO_LED6 9 -#define VEXPRESS_GPIO_LED7 10 - #define VEXPRESS_RES_FUNC(_site, _func) \ { \ .start = (_site), \ @@ -70,14 +58,14 @@ struct regmap *devm_regmap_init_vexpress_config(struct device *dev); /* Platform control */ +unsigned int vexpress_get_mci_cardin(struct device *dev); u32 vexpress_get_procid(int site); u32 vexpress_get_hbi(int site); void *vexpress_get_24mhz_clock_base(void); void vexpress_flags_set(u32 data); void vexpress_sysreg_early_init(void __iomem *base); -void vexpress_sysreg_of_early_init(void); -int vexpress_sysreg_config_device_register(struct platform_device *pdev); +int vexpress_syscfg_device_register(struct platform_device *pdev); /* Clocks */ From 5ee2b877793d89f1d73338d08af12f73fbbfed4a Mon Sep 17 00:00:00 2001 From: Pawel Moll Date: Tue, 17 Sep 2013 17:16:15 +0100 Subject: [PATCH 60/87] clk: versatile: Split config options for sp810 and vexpress_osc Move the Kconfig entry for Versatile (& Express) clock drivers into a separate file and add individual options for sp810 and vexpress_osc drivers, as they are optional in some configurations and may have separate dependencies. Signed-off-by: Pawel Moll Acked-by: Mike Turquette --- drivers/clk/Kconfig | 9 +-------- drivers/clk/versatile/Kconfig | 26 ++++++++++++++++++++++++++ drivers/clk/versatile/Makefile | 5 +++-- 3 files changed, 30 insertions(+), 10 deletions(-) create mode 100644 drivers/clk/versatile/Kconfig diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index 6f56d3a4f010..4fdfd6c70bd3 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -30,14 +30,7 @@ config COMMON_CLK_WM831X Supports the clocking subsystem of the WM831x/2x series of PMICs from Wolfson Microlectronics. -config COMMON_CLK_VERSATILE - bool "Clock driver for ARM Reference designs" - depends on ARCH_INTEGRATOR || ARCH_REALVIEW || ARCH_VEXPRESS || ARM64 - ---help--- - Supports clocking on ARM Reference designs: - - Integrator/AP and Integrator/CP - - RealView PB1176, EB, PB11MP and PBX - - Versatile Express +source "drivers/clk/versatile/Kconfig" config COMMON_CLK_MAX77686 tristate "Clock driver for Maxim 77686 MFD" diff --git a/drivers/clk/versatile/Kconfig b/drivers/clk/versatile/Kconfig new file mode 100644 index 000000000000..1530c9352a76 --- /dev/null +++ b/drivers/clk/versatile/Kconfig @@ -0,0 +1,26 @@ +config COMMON_CLK_VERSATILE + bool "Clock driver for ARM Reference designs" + depends on ARCH_INTEGRATOR || ARCH_REALVIEW || ARCH_VEXPRESS || ARM64 + ---help--- + Supports clocking on ARM Reference designs: + - Integrator/AP and Integrator/CP + - RealView PB1176, EB, PB11MP and PBX + - Versatile Express + +config CLK_SP810 + bool "Clock driver for ARM SP810 System Controller" + depends on COMMON_CLK_VERSATILE + default y if ARCH_VEXPRESS + ---help--- + Supports clock muxing (REFCLK/TIMCLK to TIMERCLKEN0-3) capabilities + of the ARM SP810 System Controller cell. + +config CLK_VEXPRESS_OSC + bool "Clock driver for Versatile Express OSC clock generators" + depends on COMMON_CLK_VERSATILE + depends on VEXPRESS_CONFIG + default y if ARCH_VEXPRESS + ---help--- + Simple regmap-based driver driving clock generators on Versatile + Express platforms hidden behind its configuration infrastructure, + commonly known as OSCs. diff --git a/drivers/clk/versatile/Makefile b/drivers/clk/versatile/Makefile index c16ca787170a..fd449f9b006d 100644 --- a/drivers/clk/versatile/Makefile +++ b/drivers/clk/versatile/Makefile @@ -3,5 +3,6 @@ obj-$(CONFIG_ICST) += clk-icst.o obj-$(CONFIG_ARCH_INTEGRATOR) += clk-integrator.o obj-$(CONFIG_INTEGRATOR_IMPD1) += clk-impd1.o obj-$(CONFIG_ARCH_REALVIEW) += clk-realview.o -obj-$(CONFIG_ARCH_VEXPRESS) += clk-vexpress.o clk-sp810.o -obj-$(CONFIG_VEXPRESS_CONFIG) += clk-vexpress-osc.o +obj-$(CONFIG_ARCH_VEXPRESS) += clk-vexpress.o +obj-$(CONFIG_CLK_SP810) += clk-sp810.o +obj-$(CONFIG_CLK_VEXPRESS_OSC) += clk-vexpress-osc.o From 220e2a8d22cd57d5ec8111465923c6c25691394d Mon Sep 17 00:00:00 2001 From: Pawel Moll Date: Wed, 16 Apr 2014 18:22:59 +0100 Subject: [PATCH 61/87] clocksource: Sched clock source for Versatile Express This patch adds a trival sched clock source using free running, 24MHz clocked counter present in the ARM Ltd. reference platforms (Versatile, RealView, Versatile Express) System Registers block. This code replaces the call in the VE machine code. Signed-off-by: Pawel Moll Reviewed-by: Linus Walleij --- arch/arm/mach-vexpress/v2m.c | 2 -- drivers/clocksource/Kconfig | 11 +++++++++ drivers/clocksource/Makefile | 1 + drivers/clocksource/versatile.c | 40 +++++++++++++++++++++++++++++++++ 4 files changed, 52 insertions(+), 2 deletions(-) create mode 100644 drivers/clocksource/versatile.c diff --git a/arch/arm/mach-vexpress/v2m.c b/arch/arm/mach-vexpress/v2m.c index 90f04c9b11d2..d8a9fd7a695d 100644 --- a/arch/arm/mach-vexpress/v2m.c +++ b/arch/arm/mach-vexpress/v2m.c @@ -418,8 +418,6 @@ void __init v2m_dt_init_early(void) pr_warning("vexpress: DT HBI (%x) is not matching " "hardware (%x)!\n", dt_hbi, hbi); } - - versatile_sched_clock_init(vexpress_get_24mhz_clock_base(), 24000000); } diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index 96918e1f26a3..2c27b02f0860 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -191,3 +191,14 @@ config EM_TIMER_STI config CLKSRC_QCOM bool + +config CLKSRC_VERSATILE + bool "ARM Versatile (Express) reference platforms clock source" + depends on GENERIC_SCHED_CLOCK + select CLKSRC_OF + default y if MFD_VEXPRESS_SYSREG + help + This option enables clock source based on free running + counter available in the "System Registers" block of + ARM Versatile, RealView and Versatile Express reference + platforms. diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile index 98cb6c51aa87..6f25bdffc176 100644 --- a/drivers/clocksource/Makefile +++ b/drivers/clocksource/Makefile @@ -39,3 +39,4 @@ obj-$(CONFIG_ARM_GLOBAL_TIMER) += arm_global_timer.o obj-$(CONFIG_CLKSRC_METAG_GENERIC) += metag_generic.o obj-$(CONFIG_ARCH_HAS_TICK_BROADCAST) += dummy_timer.o obj-$(CONFIG_ARCH_KEYSTONE) += timer-keystone.o +obj-$(CONFIG_CLKSRC_VERSATILE) += versatile.o diff --git a/drivers/clocksource/versatile.c b/drivers/clocksource/versatile.c new file mode 100644 index 000000000000..e4c50ad2f9d9 --- /dev/null +++ b/drivers/clocksource/versatile.c @@ -0,0 +1,40 @@ +/* + * 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. + * + * 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. + * + * Copyright (C) 2014 ARM Limited + */ + +#include +#include +#include +#include + +#define SYS_24MHZ 0x05c + +static void __iomem *versatile_sys_24mhz; + +static u32 notrace versatile_sys_24mhz_read(void) +{ + return readl(versatile_sys_24mhz); +} + +static void __init versatile_sched_clock_init(struct device_node *node) +{ + void __iomem *base = of_iomap(node, 0); + + if (!base) + return; + + versatile_sys_24mhz = base + SYS_24MHZ; + + setup_sched_clock(versatile_sys_24mhz_read, 32, 24000000); +} +CLOCKSOURCE_OF_DECLARE(versatile, "arm,vexpress-sysreg", + versatile_sched_clock_init); From dcdea6295d3b2ec1aafd8480860f34062d2d3a93 Mon Sep 17 00:00:00 2001 From: Sudeep KarkadaNagesha Date: Tue, 23 Jul 2013 12:32:41 +0100 Subject: [PATCH 62/87] ARM: vexpress: remove redundant vexpress_dt_cpus_num to get cpu count arm_dt_init_cpu_maps parses the device tree, validates and sets the cpu_possible_mask appropriately. It is unnecessary to do another DT parse to get the number of cpus, use num_possible_cpus instead. This patch also removes setting cpu_present_mask as platforms should only re-initialize it in smp_prepare_cpus() if present != possible. Signed-off-by: Sudeep KarkadaNagesha Signed-off-by: Pawel Moll --- arch/arm/mach-vexpress/platsmp.c | 31 +------------------------------ 1 file changed, 1 insertion(+), 30 deletions(-) diff --git a/arch/arm/mach-vexpress/platsmp.c b/arch/arm/mach-vexpress/platsmp.c index 993c9ae5dc5e..12a875182836 100644 --- a/arch/arm/mach-vexpress/platsmp.c +++ b/arch/arm/mach-vexpress/platsmp.c @@ -77,39 +77,13 @@ void __init vexpress_dt_smp_map_io(void) WARN_ON(of_scan_flat_dt(vexpress_dt_find_scu, NULL)); } -static int __init vexpress_dt_cpus_num(unsigned long node, const char *uname, - int depth, void *data) -{ - static int prev_depth = -1; - static int nr_cpus = -1; - - if (prev_depth > depth && nr_cpus > 0) - return nr_cpus; - - if (nr_cpus < 0 && strcmp(uname, "cpus") == 0) - nr_cpus = 0; - - if (nr_cpus >= 0) { - const char *device_type = of_get_flat_dt_prop(node, - "device_type", NULL); - - if (device_type && strcmp(device_type, "cpu") == 0) - nr_cpus++; - } - - prev_depth = depth; - - return 0; -} - static void __init vexpress_dt_smp_init_cpus(void) { int ncores = 0, i; switch (vexpress_dt_scu) { case GENERIC_SCU: - ncores = of_scan_flat_dt(vexpress_dt_cpus_num, NULL); - break; + return; case CORTEX_A9_SCU: ncores = scu_get_core_count(vexpress_dt_cortex_a9_scu_base); break; @@ -133,12 +107,9 @@ static void __init vexpress_dt_smp_init_cpus(void) static void __init vexpress_dt_smp_prepare_cpus(unsigned int max_cpus) { - int i; switch (vexpress_dt_scu) { case GENERIC_SCU: - for (i = 0; i < max_cpus; i++) - set_cpu_present(i, true); break; case CORTEX_A9_SCU: scu_enable(vexpress_dt_cortex_a9_scu_base); From d2606f81d5632f873884f1988fb2e9d3f057fcb6 Mon Sep 17 00:00:00 2001 From: Pawel Moll Date: Tue, 17 Sep 2013 18:30:58 +0100 Subject: [PATCH 63/87] ARM: vexpress: Simplify SMP operations for DT-powered system As all cores must be properly described in the Device Tree, there is no point in getting their numbers from SCU on A5/A9 platforms. This significantly simplifies the code, removing the need for flat-tree scanning and early static mapping. Signed-off-by: Pawel Moll --- arch/arm/mach-vexpress/core.h | 3 +- arch/arm/mach-vexpress/platsmp.c | 158 ++++++++----------------------- arch/arm/mach-vexpress/v2m.c | 6 +- 3 files changed, 41 insertions(+), 126 deletions(-) diff --git a/arch/arm/mach-vexpress/core.h b/arch/arm/mach-vexpress/core.h index bde4374ab6d5..152fad91b3ae 100644 --- a/arch/arm/mach-vexpress/core.h +++ b/arch/arm/mach-vexpress/core.h @@ -4,10 +4,9 @@ /* Tile's peripherals static mappings should start here */ #define V2T_PERIPH 0xf8200000 -void vexpress_dt_smp_map_io(void); - bool vexpress_smp_init_ops(void); extern struct smp_operations vexpress_smp_ops; +extern struct smp_operations vexpress_smp_dt_ops; extern void vexpress_cpu_die(unsigned int cpu); diff --git a/arch/arm/mach-vexpress/platsmp.c b/arch/arm/mach-vexpress/platsmp.c index 12a875182836..a1f3804fd5a5 100644 --- a/arch/arm/mach-vexpress/platsmp.c +++ b/arch/arm/mach-vexpress/platsmp.c @@ -12,8 +12,7 @@ #include #include #include -#include -#include +#include #include #include @@ -26,125 +25,13 @@ #include "core.h" -#if defined(CONFIG_OF) - -static enum { - GENERIC_SCU, - CORTEX_A9_SCU, -} vexpress_dt_scu __initdata = GENERIC_SCU; - -static struct map_desc vexpress_dt_cortex_a9_scu_map __initdata = { - .virtual = V2T_PERIPH, - /* .pfn set in vexpress_dt_init_cortex_a9_scu() */ - .length = SZ_128, - .type = MT_DEVICE, -}; - -static void *vexpress_dt_cortex_a9_scu_base __initdata; - -const static char *vexpress_dt_cortex_a9_match[] __initconst = { - "arm,cortex-a5-scu", - "arm,cortex-a9-scu", - NULL -}; - -static int __init vexpress_dt_find_scu(unsigned long node, - const char *uname, int depth, void *data) -{ - if (of_flat_dt_match(node, vexpress_dt_cortex_a9_match)) { - phys_addr_t phys_addr; - __be32 *reg = of_get_flat_dt_prop(node, "reg", NULL); - - if (WARN_ON(!reg)) - return -EINVAL; - - phys_addr = be32_to_cpup(reg); - vexpress_dt_scu = CORTEX_A9_SCU; - - vexpress_dt_cortex_a9_scu_map.pfn = __phys_to_pfn(phys_addr); - iotable_init(&vexpress_dt_cortex_a9_scu_map, 1); - vexpress_dt_cortex_a9_scu_base = ioremap(phys_addr, SZ_256); - if (WARN_ON(!vexpress_dt_cortex_a9_scu_base)) - return -EFAULT; - } - - return 0; -} - -void __init vexpress_dt_smp_map_io(void) -{ - if (initial_boot_params) - WARN_ON(of_scan_flat_dt(vexpress_dt_find_scu, NULL)); -} - -static void __init vexpress_dt_smp_init_cpus(void) -{ - int ncores = 0, i; - - switch (vexpress_dt_scu) { - case GENERIC_SCU: - return; - case CORTEX_A9_SCU: - ncores = scu_get_core_count(vexpress_dt_cortex_a9_scu_base); - break; - default: - WARN_ON(1); - break; - } - - if (ncores < 2) - return; - - if (ncores > nr_cpu_ids) { - pr_warn("SMP: %u cores greater than maximum (%u), clipping\n", - ncores, nr_cpu_ids); - ncores = nr_cpu_ids; - } - - for (i = 0; i < ncores; ++i) - set_cpu_possible(i, true); -} - -static void __init vexpress_dt_smp_prepare_cpus(unsigned int max_cpus) -{ - - switch (vexpress_dt_scu) { - case GENERIC_SCU: - break; - case CORTEX_A9_SCU: - scu_enable(vexpress_dt_cortex_a9_scu_base); - break; - default: - WARN_ON(1); - break; - } -} - -#else - -static void __init vexpress_dt_smp_init_cpus(void) -{ - WARN_ON(1); -} - -void __init vexpress_dt_smp_prepare_cpus(unsigned int max_cpus) -{ - WARN_ON(1); -} - -#endif - /* * Initialise the CPU possible map early - this describes the CPUs * which may be present or become present in the system. */ static void __init vexpress_smp_init_cpus(void) { - if (ct_desc) - ct_desc->init_cpu_map(); - else - vexpress_dt_smp_init_cpus(); - + ct_desc->init_cpu_map(); } static void __init vexpress_smp_prepare_cpus(unsigned int max_cpus) @@ -153,10 +40,7 @@ static void __init vexpress_smp_prepare_cpus(unsigned int max_cpus) * Initialise the present map, which describes the set of CPUs * actually populated at the present time. */ - if (ct_desc) - ct_desc->smp_enable(max_cpus); - else - vexpress_dt_smp_prepare_cpus(max_cpus); + ct_desc->smp_enable(max_cpus); /* * Write the address of secondary startup into the @@ -194,3 +78,39 @@ bool __init vexpress_smp_init_ops(void) #endif return false; } + +#if defined(CONFIG_OF) + +static const struct of_device_id vexpress_smp_dt_scu_match[] __initconst = { + { .compatible = "arm,cortex-a5-scu", }, + { .compatible = "arm,cortex-a9-scu", }, + {} +}; + +static void __init vexpress_smp_dt_prepare_cpus(unsigned int max_cpus) +{ + struct device_node *scu = of_find_matching_node(NULL, + vexpress_smp_dt_scu_match); + + if (scu) + scu_enable(of_iomap(scu, 0)); + + /* + * Write the address of secondary startup into the + * system-wide flags register. The boot monitor waits + * until it receives a soft interrupt, and then the + * secondary CPU branches to this address. + */ + vexpress_flags_set(virt_to_phys(versatile_secondary_startup)); +} + +struct smp_operations __initdata vexpress_smp_dt_ops = { + .smp_prepare_cpus = vexpress_smp_dt_prepare_cpus, + .smp_secondary_init = versatile_secondary_init, + .smp_boot_secondary = versatile_boot_secondary, +#ifdef CONFIG_HOTPLUG_CPU + .cpu_die = vexpress_cpu_die, +#endif +}; + +#endif diff --git a/arch/arm/mach-vexpress/v2m.c b/arch/arm/mach-vexpress/v2m.c index d8a9fd7a695d..d8b419bcf3c3 100644 --- a/arch/arm/mach-vexpress/v2m.c +++ b/arch/arm/mach-vexpress/v2m.c @@ -400,10 +400,6 @@ void __init v2m_dt_map_io(void) iotable_init(&v2m_rs1_io_desc, 1); else iotable_init(v2m_io_desc, ARRAY_SIZE(v2m_io_desc)); - -#if defined(CONFIG_SMP) - vexpress_dt_smp_map_io(); -#endif } void __init v2m_dt_init_early(void) @@ -434,7 +430,7 @@ static const char * const v2m_dt_match[] __initconst = { DT_MACHINE_START(VEXPRESS_DT, "ARM-Versatile Express") .dt_compat = v2m_dt_match, - .smp = smp_ops(vexpress_smp_ops), + .smp = smp_ops(vexpress_smp_dt_ops), .smp_init = smp_init_ops(vexpress_smp_init_ops), .map_io = v2m_dt_map_io, .init_early = v2m_dt_init_early, From 6b2c31c71d6fa8896c5f3f2354d790a5bd3f0a1e Mon Sep 17 00:00:00 2001 From: Pawel Moll Date: Thu, 6 Feb 2014 14:33:44 +0000 Subject: [PATCH 64/87] ARM: vexpress: move HBI check to sysreg driver The last reason for static memory mapping is the HBI (board identification number) check early in the machine code. Moving the check to the sysreg driver makes it possible to completely remove the early mapping and init functions. Signed-off-by: Pawel Moll Acked-by: Lee Jones --- arch/arm/mach-vexpress/v2m.c | 49 ----------------------------------- drivers/mfd/vexpress-sysreg.c | 30 ++++++++------------- include/linux/vexpress.h | 1 - 3 files changed, 11 insertions(+), 69 deletions(-) diff --git a/arch/arm/mach-vexpress/v2m.c b/arch/arm/mach-vexpress/v2m.c index d8b419bcf3c3..38f4f6f37770 100644 --- a/arch/arm/mach-vexpress/v2m.c +++ b/arch/arm/mach-vexpress/v2m.c @@ -370,53 +370,6 @@ MACHINE_START(VEXPRESS, "ARM-Versatile Express") .init_machine = v2m_init, MACHINE_END -static struct map_desc v2m_rs1_io_desc __initdata = { - .virtual = V2M_PERIPH, - .pfn = __phys_to_pfn(0x1c000000), - .length = SZ_2M, - .type = MT_DEVICE, -}; - -static int __init v2m_dt_scan_memory_map(unsigned long node, const char *uname, - int depth, void *data) -{ - const char **map = data; - - if (strcmp(uname, "motherboard") != 0) - return 0; - - *map = of_get_flat_dt_prop(node, "arm,v2m-memory-map", NULL); - - return 1; -} - -void __init v2m_dt_map_io(void) -{ - const char *map = NULL; - - of_scan_flat_dt(v2m_dt_scan_memory_map, &map); - - if (map && strcmp(map, "rs1") == 0) - iotable_init(&v2m_rs1_io_desc, 1); - else - iotable_init(v2m_io_desc, ARRAY_SIZE(v2m_io_desc)); -} - -void __init v2m_dt_init_early(void) -{ - u32 dt_hbi; - - /* Confirm board type against DT property, if available */ - if (of_property_read_u32(of_allnodes, "arm,hbi", &dt_hbi) == 0) { - u32 hbi = vexpress_get_hbi(VEXPRESS_SITE_MASTER); - - if (WARN_ON(dt_hbi != hbi)) - pr_warning("vexpress: DT HBI (%x) is not matching " - "hardware (%x)!\n", dt_hbi, hbi); - } -} - - static void __init v2m_dt_init(void) { l2x0_of_init(0x00400000, 0xfe0fffff); @@ -432,7 +385,5 @@ DT_MACHINE_START(VEXPRESS_DT, "ARM-Versatile Express") .dt_compat = v2m_dt_match, .smp = smp_ops(vexpress_smp_dt_ops), .smp_init = smp_init_ops(vexpress_smp_init_ops), - .map_io = v2m_dt_map_io, - .init_early = v2m_dt_init_early, .init_machine = v2m_dt_init, MACHINE_END diff --git a/drivers/mfd/vexpress-sysreg.c b/drivers/mfd/vexpress-sysreg.c index 952df843b6be..9e21e4fc9599 100644 --- a/drivers/mfd/vexpress-sysreg.c +++ b/drivers/mfd/vexpress-sysreg.c @@ -45,7 +45,6 @@ #define SYS_CFGSTAT 0x0a8 #define SYS_HBI_MASK 0xfff -#define SYS_ID_HBI_SHIFT 16 #define SYS_PROCIDx_HBI_SHIFT 0 #define SYS_MCI_CARDIN (1 << 0) @@ -99,24 +98,6 @@ u32 vexpress_get_procid(int site) SYS_PROCID0 : SYS_PROCID1)); } -u32 vexpress_get_hbi(int site) -{ - u32 id; - - switch (site) { - case VEXPRESS_SITE_MB: - id = readl(vexpress_sysreg_base() + SYS_ID); - return (id >> SYS_ID_HBI_SHIFT) & SYS_HBI_MASK; - case VEXPRESS_SITE_MASTER: - case VEXPRESS_SITE_DB1: - case VEXPRESS_SITE_DB2: - id = vexpress_get_procid(site); - return (id >> SYS_PROCIDx_HBI_SHIFT) & SYS_HBI_MASK; - } - - return ~0; -} - void __iomem *vexpress_get_24mhz_clock_base(void) { return vexpress_sysreg_base() + SYS_24MHZ; @@ -229,6 +210,7 @@ static int vexpress_sysreg_probe(struct platform_device *pdev) struct resource *mem; void __iomem *base; struct bgpio_chip *mmc_gpio_chip; + u32 dt_hbi; mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!mem) @@ -240,6 +222,16 @@ static int vexpress_sysreg_probe(struct platform_device *pdev) vexpress_config_set_master(vexpress_sysreg_get_master()); + /* Confirm board type against DT property, if available */ + if (of_property_read_u32(of_allnodes, "arm,hbi", &dt_hbi) == 0) { + u32 id = vexpress_get_procid(VEXPRESS_SITE_MASTER); + u32 hbi = (id >> SYS_PROCIDx_HBI_SHIFT) & SYS_HBI_MASK; + + if (WARN_ON(dt_hbi != hbi)) + dev_warn(&pdev->dev, "DT HBI (%x) is not matching hardware (%x)!\n", + dt_hbi, hbi); + } + /* * Duplicated SYS_MCI pseudo-GPIO controller for compatibility with * older trees using sysreg node for MMC control lines. diff --git a/include/linux/vexpress.h b/include/linux/vexpress.h index 46636e3f43fd..a4c9547aae64 100644 --- a/include/linux/vexpress.h +++ b/include/linux/vexpress.h @@ -60,7 +60,6 @@ struct regmap *devm_regmap_init_vexpress_config(struct device *dev); unsigned int vexpress_get_mci_cardin(struct device *dev); u32 vexpress_get_procid(int site); -u32 vexpress_get_hbi(int site); void *vexpress_get_24mhz_clock_base(void); void vexpress_flags_set(u32 data); From 250e27ee950bf67ceeb812eb4c8f2fea58d3e2b6 Mon Sep 17 00:00:00 2001 From: Tero Kristo Date: Tue, 4 Mar 2014 18:19:02 +0200 Subject: [PATCH 65/87] ARM: OMAP2+: prcm: add omap_test_timeout to prcm-common.h Done in preparation to move cm/prm to drivers. These will still use omap_test_timeout, but will not have access to common.h header under mach-omap2 anymore. Signed-off-by: Tero Kristo Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/prcm-common.h | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/arch/arm/mach-omap2/prcm-common.h b/arch/arm/mach-omap2/prcm-common.h index 0e841fd9498a..e982598386a5 100644 --- a/arch/arm/mach-omap2/prcm-common.h +++ b/arch/arm/mach-omap2/prcm-common.h @@ -428,6 +428,26 @@ #define MAX_IOPAD_LATCH_TIME 100 # ifndef __ASSEMBLER__ +/** + * omap_test_timeout - busy-loop, testing a condition + * @cond: condition to test until it evaluates to true + * @timeout: maximum number of microseconds in the timeout + * @index: loop index (integer) + * + * Loop waiting for @cond to become true or until at least @timeout + * microseconds have passed. To use, define some integer @index in the + * calling code. After running, if @index == @timeout, then the loop has + * timed out. + */ +#define omap_test_timeout(cond, timeout, index) \ +({ \ + for (index = 0; index < timeout; index++) { \ + if (cond) \ + break; \ + udelay(1); \ + } \ +}) + /** * struct omap_prcm_irq - describes a PRCM interrupt bit * @name: a short name describing the interrupt type, e.g. "wkup" or "io" From 7af1363742e0e2752e90d5de2ddb9c48665fc567 Mon Sep 17 00:00:00 2001 From: Tero Kristo Date: Tue, 4 Mar 2014 18:19:03 +0200 Subject: [PATCH 66/87] ARM: OMAP2/3: CM: remove some external dependencies Done in preparation to move the CM driver to its own driver folder. These drivers will not have access to functionality under mach-omap2 anymore. Signed-off-by: Tero Kristo Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/cm2xxx.c | 15 ++------------- arch/arm/mach-omap2/cm3xxx.c | 13 +------------ 2 files changed, 3 insertions(+), 25 deletions(-) diff --git a/arch/arm/mach-omap2/cm2xxx.c b/arch/arm/mach-omap2/cm2xxx.c index ce25abbcffae..8be6ea50c092 100644 --- a/arch/arm/mach-omap2/cm2xxx.c +++ b/arch/arm/mach-omap2/cm2xxx.c @@ -18,9 +18,6 @@ #include #include -#include "soc.h" -#include "iomap.h" -#include "common.h" #include "prm2xxx.h" #include "cm.h" #include "cm2xxx.h" @@ -390,7 +387,7 @@ void omap2xxx_cm_set_mod_dividers(u32 mpu, u32 dsp, u32 gfx, u32 core, u32 mdm) tmp = omap2_cm_read_mod_reg(CORE_MOD, CM_CLKSEL1) & OMAP24XX_CLKSEL_DSS2_MASK; omap2_cm_write_mod_reg(core | tmp, CORE_MOD, CM_CLKSEL1); - if (cpu_is_omap2430()) + if (mdm) omap2_cm_write_mod_reg(mdm, OMAP2430_MDM_MOD, CM_CLKSEL); } @@ -405,19 +402,11 @@ static struct cm_ll_data omap2xxx_cm_ll_data = { int __init omap2xxx_cm_init(void) { - if (!cpu_is_omap24xx()) - return 0; - return cm_register(&omap2xxx_cm_ll_data); } static void __exit omap2xxx_cm_exit(void) { - if (!cpu_is_omap24xx()) - return; - - /* Should never happen */ - WARN(cm_unregister(&omap2xxx_cm_ll_data), - "%s: cm_ll_data function pointer mismatch\n", __func__); + cm_unregister(&omap2xxx_cm_ll_data); } __exitcall(omap2xxx_cm_exit); diff --git a/arch/arm/mach-omap2/cm3xxx.c b/arch/arm/mach-omap2/cm3xxx.c index 60c2c9f9438a..129a4e7f6ef5 100644 --- a/arch/arm/mach-omap2/cm3xxx.c +++ b/arch/arm/mach-omap2/cm3xxx.c @@ -18,9 +18,6 @@ #include #include -#include "soc.h" -#include "iomap.h" -#include "common.h" #include "prm2xxx_3xxx.h" #include "cm.h" #include "cm3xxx.h" @@ -673,19 +670,11 @@ static struct cm_ll_data omap3xxx_cm_ll_data = { int __init omap3xxx_cm_init(void) { - if (!cpu_is_omap34xx()) - return 0; - return cm_register(&omap3xxx_cm_ll_data); } static void __exit omap3xxx_cm_exit(void) { - if (!cpu_is_omap34xx()) - return; - - /* Should never happen */ - WARN(cm_unregister(&omap3xxx_cm_ll_data), - "%s: cm_ll_data function pointer mismatch\n", __func__); + cm_unregister(&omap3xxx_cm_ll_data); } __exitcall(omap3xxx_cm_exit); From cdb445147a4e45f716c078f78277ea6524b76dd0 Mon Sep 17 00:00:00 2001 From: Tero Kristo Date: Mon, 31 Mar 2014 18:15:40 +0300 Subject: [PATCH 67/87] ARM: OMAP4: CM: use cm_base* in register address calculations OMAP44XX_CM*_REGADDR macros should be avoided, instead use the cm_base* iomaps. Signed-off-by: Tero Kristo Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/cm44xx.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/arm/mach-omap2/cm44xx.c b/arch/arm/mach-omap2/cm44xx.c index 535d66e2822c..5627072d4d86 100644 --- a/arch/arm/mach-omap2/cm44xx.c +++ b/arch/arm/mach-omap2/cm44xx.c @@ -30,23 +30,23 @@ /* Read a register in CM1 */ u32 omap4_cm1_read_inst_reg(s16 inst, u16 reg) { - return __raw_readl(OMAP44XX_CM1_REGADDR(inst, reg)); + return __raw_readl(cm_base + inst + reg); } /* Write into a register in CM1 */ void omap4_cm1_write_inst_reg(u32 val, s16 inst, u16 reg) { - __raw_writel(val, OMAP44XX_CM1_REGADDR(inst, reg)); + __raw_writel(val, cm_base + inst + reg); } /* Read a register in CM2 */ u32 omap4_cm2_read_inst_reg(s16 inst, u16 reg) { - return __raw_readl(OMAP44XX_CM2_REGADDR(inst, reg)); + return __raw_readl(cm2_base + inst + reg); } /* Write into a register in CM2 */ void omap4_cm2_write_inst_reg(u32 val, s16 inst, u16 reg) { - __raw_writel(val, OMAP44XX_CM2_REGADDR(inst, reg)); + __raw_writel(val, cm2_base + inst + reg); } From 4794208c5b0122e51e3e13830bb707466b638c4c Mon Sep 17 00:00:00 2001 From: Tero Kristo Date: Sun, 11 May 2014 19:41:50 -0600 Subject: [PATCH 68/87] ARM: OMAP2+: PRCM: cleanup some header includes Some of the includes are totally unnecessary, remove some others in preparation to make the PRCM its own driver. Signed-off-by: Tero Kristo [paul@pwsan.com: updated to apply; fixed build error on OMAP2xxx-only configs] Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/clockdomain.h | 3 ++- arch/arm/mach-omap2/cm33xx.h | 3 --- arch/arm/mach-omap2/cm44xx.c | 2 -- arch/arm/mach-omap2/cm_common.c | 2 +- arch/arm/mach-omap2/cminst44xx.c | 2 -- arch/arm/mach-omap2/omap_hwmod_33xx_43xx_ipblock_data.c | 1 + arch/arm/mach-omap2/powerdomain.c | 1 + arch/arm/mach-omap2/powerdomain.h | 3 +-- arch/arm/mach-omap2/prcm-common.h | 2 ++ arch/arm/mach-omap2/prcm_mpu44xx.h | 1 - arch/arm/mach-omap2/prm2xxx_3xxx.c | 1 - arch/arm/mach-omap2/prm33xx.c | 1 - 12 files changed, 8 insertions(+), 14 deletions(-) diff --git a/arch/arm/mach-omap2/clockdomain.h b/arch/arm/mach-omap2/clockdomain.h index f17f00697cc0..82c37b1becc4 100644 --- a/arch/arm/mach-omap2/clockdomain.h +++ b/arch/arm/mach-omap2/clockdomain.h @@ -18,7 +18,6 @@ #include "powerdomain.h" #include "clock.h" -#include "omap_hwmod.h" /* * Clockdomain flags @@ -98,6 +97,8 @@ struct clkdm_dep { /* Possible flags for struct clockdomain._flags */ #define _CLKDM_FLAG_HWSUP_ENABLED BIT(0) +struct omap_hwmod; + /** * struct clockdomain - OMAP clockdomain * @name: clockdomain name diff --git a/arch/arm/mach-omap2/cm33xx.h b/arch/arm/mach-omap2/cm33xx.h index cfb8891b0c0e..15a778ce7707 100644 --- a/arch/arm/mach-omap2/cm33xx.h +++ b/arch/arm/mach-omap2/cm33xx.h @@ -17,11 +17,8 @@ #ifndef __ARCH_ARM_MACH_OMAP2_CM_33XX_H #define __ARCH_ARM_MACH_OMAP2_CM_33XX_H -#include "common.h" - #include "cm.h" #include "cm-regbits-33xx.h" -#include "iomap.h" /* CM base address */ #define AM33XX_CM_BASE 0x44e00000 diff --git a/arch/arm/mach-omap2/cm44xx.c b/arch/arm/mach-omap2/cm44xx.c index 5627072d4d86..37ba6e8f9505 100644 --- a/arch/arm/mach-omap2/cm44xx.c +++ b/arch/arm/mach-omap2/cm44xx.c @@ -18,8 +18,6 @@ #include #include -#include "iomap.h" -#include "common.h" #include "cm.h" #include "cm1_44xx.h" #include "cm2_44xx.h" diff --git a/arch/arm/mach-omap2/cm_common.c b/arch/arm/mach-omap2/cm_common.c index 40b3b5a84458..8f6c4710877e 100644 --- a/arch/arm/mach-omap2/cm_common.c +++ b/arch/arm/mach-omap2/cm_common.c @@ -14,11 +14,11 @@ #include #include #include +#include #include "cm2xxx.h" #include "cm3xxx.h" #include "cm44xx.h" -#include "common.h" /* * cm_ll_data: function pointers to SoC-specific implementations of diff --git a/arch/arm/mach-omap2/cminst44xx.c b/arch/arm/mach-omap2/cminst44xx.c index f5c4731b6f06..434b52af0364 100644 --- a/arch/arm/mach-omap2/cminst44xx.c +++ b/arch/arm/mach-omap2/cminst44xx.c @@ -21,8 +21,6 @@ #include #include -#include "iomap.h" -#include "common.h" #include "clockdomain.h" #include "cm.h" #include "cm1_44xx.h" diff --git a/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_ipblock_data.c b/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_ipblock_data.c index 0f178623e7da..a579b89ce9b7 100644 --- a/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_ipblock_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_ipblock_data.c @@ -24,6 +24,7 @@ #include "prm33xx.h" #include "omap_hwmod_33xx_43xx_common_data.h" #include "prcm43xx.h" +#include "common.h" #define CLKCTRL(oh, clkctrl) ((oh).prcm.omap4.clkctrl_offs = (clkctrl)) #define RSTCTRL(oh, rstctrl) ((oh).prcm.omap4.rstctrl_offs = (rstctrl)) diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c index 93a2a6e4260f..faebd5f076af 100644 --- a/arch/arm/mach-omap2/powerdomain.c +++ b/arch/arm/mach-omap2/powerdomain.c @@ -32,6 +32,7 @@ #include "powerdomain.h" #include "clockdomain.h" +#include "voltage.h" #include "soc.h" #include "pm.h" diff --git a/arch/arm/mach-omap2/powerdomain.h b/arch/arm/mach-omap2/powerdomain.h index da5a59ae77b6..f4727117f6cc 100644 --- a/arch/arm/mach-omap2/powerdomain.h +++ b/arch/arm/mach-omap2/powerdomain.h @@ -21,8 +21,6 @@ #include #include -#include "voltage.h" - /* Powerdomain basic power states */ #define PWRDM_POWER_OFF 0x0 #define PWRDM_POWER_RET 0x1 @@ -75,6 +73,7 @@ struct clockdomain; struct powerdomain; +struct voltagedomain; /** * struct powerdomain - OMAP powerdomain diff --git a/arch/arm/mach-omap2/prcm-common.h b/arch/arm/mach-omap2/prcm-common.h index e982598386a5..ee2384a983bc 100644 --- a/arch/arm/mach-omap2/prcm-common.h +++ b/arch/arm/mach-omap2/prcm-common.h @@ -428,6 +428,8 @@ #define MAX_IOPAD_LATCH_TIME 100 # ifndef __ASSEMBLER__ +#include + /** * omap_test_timeout - busy-loop, testing a condition * @cond: condition to test until it evaluates to true diff --git a/arch/arm/mach-omap2/prcm_mpu44xx.h b/arch/arm/mach-omap2/prcm_mpu44xx.h index 059bd4f49035..ac9cb4550239 100644 --- a/arch/arm/mach-omap2/prcm_mpu44xx.h +++ b/arch/arm/mach-omap2/prcm_mpu44xx.h @@ -26,7 +26,6 @@ #define __ARCH_ARM_MACH_OMAP2_PRCM_MPU44XX_H #include "prcm_mpu_44xx_54xx.h" -#include "common.h" #define OMAP4430_PRCM_MPU_BASE 0x48243000 diff --git a/arch/arm/mach-omap2/prm2xxx_3xxx.c b/arch/arm/mach-omap2/prm2xxx_3xxx.c index 947f6adfed0c..c13b4e293ffa 100644 --- a/arch/arm/mach-omap2/prm2xxx_3xxx.c +++ b/arch/arm/mach-omap2/prm2xxx_3xxx.c @@ -16,7 +16,6 @@ #include #include -#include "common.h" #include "powerdomain.h" #include "prm2xxx_3xxx.h" #include "prm-regbits-24xx.h" diff --git a/arch/arm/mach-omap2/prm33xx.c b/arch/arm/mach-omap2/prm33xx.c index 720440737744..0660105366e3 100644 --- a/arch/arm/mach-omap2/prm33xx.c +++ b/arch/arm/mach-omap2/prm33xx.c @@ -19,7 +19,6 @@ #include #include -#include "common.h" #include "powerdomain.h" #include "prm33xx.h" #include "prm-regbits-33xx.h" From d8871cd245ece932ced994457e044d0f68b0aab4 Mon Sep 17 00:00:00 2001 From: Tero Kristo Date: Sun, 11 May 2014 19:54:58 -0600 Subject: [PATCH 69/87] ARM: OMAP2+: PRM: remove unnecessary cpu_is_XXX calls from prm_init / exit Done in preparation to make PRM its own driver, as the cpu_is_XXX calls are not available outside mach-omap2 folder. The init functions are called only from cpu specific init chain, and thus don't need to double check against cpu type. The exit calls check against the data provided during init-time registration and thus don't need cpu check either. Signed-off-by: Tero Kristo [paul@pwsan.com: updated to apply] Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/prm2xxx.c | 13 +------------ arch/arm/mach-omap2/prm3xxx.c | 10 +--------- arch/arm/mach-omap2/prm44xx.c | 10 +--------- 3 files changed, 3 insertions(+), 30 deletions(-) diff --git a/arch/arm/mach-omap2/prm2xxx.c b/arch/arm/mach-omap2/prm2xxx.c index 418de9c3b319..a3a3cca2bcc4 100644 --- a/arch/arm/mach-omap2/prm2xxx.c +++ b/arch/arm/mach-omap2/prm2xxx.c @@ -18,9 +18,6 @@ #include #include -#include "soc.h" -#include "common.h" -#include "vp.h" #include "powerdomain.h" #include "clockdomain.h" #include "prm2xxx.h" @@ -201,19 +198,11 @@ static struct prm_ll_data omap2xxx_prm_ll_data = { int __init omap2xxx_prm_init(void) { - if (!cpu_is_omap24xx()) - return 0; - return prm_register(&omap2xxx_prm_ll_data); } static void __exit omap2xxx_prm_exit(void) { - if (!cpu_is_omap24xx()) - return; - - /* Should never happen */ - WARN(prm_unregister(&omap2xxx_prm_ll_data), - "%s: prm_ll_data function pointer mismatch\n", __func__); + prm_unregister(&omap2xxx_prm_ll_data); } __exitcall(omap2xxx_prm_exit); diff --git a/arch/arm/mach-omap2/prm3xxx.c b/arch/arm/mach-omap2/prm3xxx.c index 7721990d2006..4c89aa2f1e81 100644 --- a/arch/arm/mach-omap2/prm3xxx.c +++ b/arch/arm/mach-omap2/prm3xxx.c @@ -406,9 +406,6 @@ static struct prm_ll_data omap3xxx_prm_ll_data = { int __init omap3xxx_prm_init(void) { - if (!cpu_is_omap34xx()) - return 0; - return prm_register(&omap3xxx_prm_ll_data); } @@ -431,11 +428,6 @@ omap_subsys_initcall(omap3xxx_prm_late_init); static void __exit omap3xxx_prm_exit(void) { - if (!cpu_is_omap34xx()) - return; - - /* Should never happen */ - WARN(prm_unregister(&omap3xxx_prm_ll_data), - "%s: prm_ll_data function pointer mismatch\n", __func__); + prm_unregister(&omap3xxx_prm_ll_data); } __exitcall(omap3xxx_prm_exit); diff --git a/arch/arm/mach-omap2/prm44xx.c b/arch/arm/mach-omap2/prm44xx.c index 03a603476cfc..15171890f805 100644 --- a/arch/arm/mach-omap2/prm44xx.c +++ b/arch/arm/mach-omap2/prm44xx.c @@ -660,9 +660,6 @@ static struct prm_ll_data omap44xx_prm_ll_data = { int __init omap44xx_prm_init(void) { - if (!cpu_is_omap44xx() && !soc_is_omap54xx() && !soc_is_dra7xx()) - return 0; - return prm_register(&omap44xx_prm_ll_data); } @@ -679,11 +676,6 @@ omap_subsys_initcall(omap44xx_prm_late_init); static void __exit omap44xx_prm_exit(void) { - if (!cpu_is_omap44xx()) - return; - - /* Should never happen */ - WARN(prm_unregister(&omap44xx_prm_ll_data), - "%s: prm_ll_data function pointer mismatch\n", __func__); + prm_unregister(&omap44xx_prm_ll_data); } __exitcall(omap44xx_prm_exit); From 81243651ba25c4418af26c3c6f1aeabb41f734e0 Mon Sep 17 00:00:00 2001 From: Tero Kristo Date: Mon, 31 Mar 2014 18:15:43 +0300 Subject: [PATCH 70/87] ARM: OMAP3/4: PRM: provide io chain reconfig function through irq setup This helps to make the PRM registration modular, and also gets rid of a cpu type check done later. Signed-off-by: Tero Kristo Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/prcm-common.h | 2 ++ arch/arm/mach-omap2/prm3xxx.c | 1 + arch/arm/mach-omap2/prm44xx.c | 1 + arch/arm/mach-omap2/prm_common.c | 7 +------ 4 files changed, 5 insertions(+), 6 deletions(-) diff --git a/arch/arm/mach-omap2/prcm-common.h b/arch/arm/mach-omap2/prcm-common.h index ee2384a983bc..a8e4b582c527 100644 --- a/arch/arm/mach-omap2/prcm-common.h +++ b/arch/arm/mach-omap2/prcm-common.h @@ -480,6 +480,7 @@ struct omap_prcm_irq { * @ocp_barrier: fn ptr to force buffered PRM writes to complete * @save_and_clear_irqen: fn ptr to save and clear IRQENABLE regs * @restore_irqen: fn ptr to save and clear IRQENABLE regs + * @reconfigure_io_chain: fn ptr to reconfigure IO chain * @saved_mask: IRQENABLE regs are saved here during suspend * @priority_mask: 1 bit per IRQ, set to 1 if omap_prcm_irq.priority = true * @base_irq: base dynamic IRQ number, returned from irq_alloc_descs() in init @@ -501,6 +502,7 @@ struct omap_prcm_irq_setup { void (*ocp_barrier)(void); void (*save_and_clear_irqen)(u32 *saved_mask); void (*restore_irqen)(u32 *saved_mask); + void (*reconfigure_io_chain)(void); u32 *saved_mask; u32 *priority_mask; int base_irq; diff --git a/arch/arm/mach-omap2/prm3xxx.c b/arch/arm/mach-omap2/prm3xxx.c index 4c89aa2f1e81..2631b9f2b3d8 100644 --- a/arch/arm/mach-omap2/prm3xxx.c +++ b/arch/arm/mach-omap2/prm3xxx.c @@ -43,6 +43,7 @@ static struct omap_prcm_irq_setup omap3_prcm_irq_setup = { .ocp_barrier = &omap3xxx_prm_ocp_barrier, .save_and_clear_irqen = &omap3xxx_prm_save_and_clear_irqen, .restore_irqen = &omap3xxx_prm_restore_irqen, + .reconfigure_io_chain = &omap3xxx_prm_reconfigure_io_chain, }; /* diff --git a/arch/arm/mach-omap2/prm44xx.c b/arch/arm/mach-omap2/prm44xx.c index 15171890f805..f464179eb82b 100644 --- a/arch/arm/mach-omap2/prm44xx.c +++ b/arch/arm/mach-omap2/prm44xx.c @@ -47,6 +47,7 @@ static struct omap_prcm_irq_setup omap4_prcm_irq_setup = { .ocp_barrier = &omap44xx_prm_ocp_barrier, .save_and_clear_irqen = &omap44xx_prm_save_and_clear_irqen, .restore_irqen = &omap44xx_prm_restore_irqen, + .reconfigure_io_chain = &omap44xx_prm_reconfigure_io_chain, }; /* diff --git a/arch/arm/mach-omap2/prm_common.c b/arch/arm/mach-omap2/prm_common.c index b4c4ab9c8044..bd746fc05d18 100644 --- a/arch/arm/mach-omap2/prm_common.c +++ b/arch/arm/mach-omap2/prm_common.c @@ -330,12 +330,7 @@ int omap_prcm_register_chain_handler(struct omap_prcm_irq_setup *irq_setup) if (of_have_populated_dt()) { int irq = omap_prcm_event_to_irq("io"); - if (cpu_is_omap34xx()) - omap_pcs_legacy_init(irq, - omap3xxx_prm_reconfigure_io_chain); - else - omap_pcs_legacy_init(irq, - omap44xx_prm_reconfigure_io_chain); + omap_pcs_legacy_init(irq, irq_setup->reconfigure_io_chain); } return 0; From 2541d15f16479fd56debe1ea55dee03c3886e33c Mon Sep 17 00:00:00 2001 From: Tero Kristo Date: Mon, 31 Mar 2014 18:15:44 +0300 Subject: [PATCH 71/87] ARM: OMAP3/OMAP4: PRM: add prm_features flags and add IO wakeup under it prm_features flag will contain SoC specific feature enabler flags. Initially IO wakeup is added under this. Helps to get rid of runtime cpu_is_X checks. Signed-off-by: Tero Kristo Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/prm.h | 8 ++++++++ arch/arm/mach-omap2/prm3xxx.c | 8 +++++++- arch/arm/mach-omap2/prm44xx.c | 6 ++++++ arch/arm/mach-omap2/prm_common.c | 2 ++ 4 files changed, 23 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-omap2/prm.h b/arch/arm/mach-omap2/prm.h index 623db40fdbbd..04426c441fff 100644 --- a/arch/arm/mach-omap2/prm.h +++ b/arch/arm/mach-omap2/prm.h @@ -17,10 +17,18 @@ # ifndef __ASSEMBLER__ extern void __iomem *prm_base; +extern u16 prm_features; extern void omap2_set_globals_prm(void __iomem *prm); int of_prcm_init(void); # endif +/* + * prm_features flag values + * + * PRM_HAS_IO_WAKEUP: has IO wakeup capability + * PRM_HAS_VOLTAGE: has voltage domains + */ +#define PRM_HAS_IO_WAKEUP (1 << 0) /* * MAX_MODULE_SOFTRESET_WAIT: Maximum microseconds to wait for OMAP diff --git a/arch/arm/mach-omap2/prm3xxx.c b/arch/arm/mach-omap2/prm3xxx.c index 2631b9f2b3d8..9c95ac21c5b3 100644 --- a/arch/arm/mach-omap2/prm3xxx.c +++ b/arch/arm/mach-omap2/prm3xxx.c @@ -247,7 +247,7 @@ void omap3xxx_prm_reconfigure_io_chain(void) */ static void __init omap3xxx_prm_enable_io_wakeup(void) { - if (omap3_has_io_wakeup()) + if (prm_features & PRM_HAS_IO_WAKEUP) omap2_prm_set_mod_reg_bits(OMAP3430_EN_IO_MASK, WKUP_MOD, PM_WKEN); } @@ -407,6 +407,9 @@ static struct prm_ll_data omap3xxx_prm_ll_data = { int __init omap3xxx_prm_init(void) { + if (omap3_has_io_wakeup()) + prm_features |= PRM_HAS_IO_WAKEUP; + return prm_register(&omap3xxx_prm_ll_data); } @@ -417,6 +420,9 @@ static int __init omap3xxx_prm_late_init(void) if (!cpu_is_omap34xx()) return 0; + if (!(prm_features & PRM_HAS_IO_WAKEUP)) + return 0; + omap3xxx_prm_enable_io_wakeup(); ret = omap_prcm_register_chain_handler(&omap3_prcm_irq_setup); if (!ret) diff --git a/arch/arm/mach-omap2/prm44xx.c b/arch/arm/mach-omap2/prm44xx.c index f464179eb82b..e4e52f14dbbf 100644 --- a/arch/arm/mach-omap2/prm44xx.c +++ b/arch/arm/mach-omap2/prm44xx.c @@ -661,6 +661,9 @@ static struct prm_ll_data omap44xx_prm_ll_data = { int __init omap44xx_prm_init(void) { + if (cpu_is_omap44xx()) + prm_features |= PRM_HAS_IO_WAKEUP; + return prm_register(&omap44xx_prm_ll_data); } @@ -669,6 +672,9 @@ static int __init omap44xx_prm_late_init(void) if (!cpu_is_omap44xx()) return 0; + if (!(prm_features & PRM_HAS_IO_WAKEUP)) + return 0; + omap44xx_prm_enable_io_wakeup(); return omap_prcm_register_chain_handler(&omap4_prcm_irq_setup); diff --git a/arch/arm/mach-omap2/prm_common.c b/arch/arm/mach-omap2/prm_common.c index bd746fc05d18..aa2550dd2ac1 100644 --- a/arch/arm/mach-omap2/prm_common.c +++ b/arch/arm/mach-omap2/prm_common.c @@ -62,6 +62,8 @@ static struct omap_prcm_irq_setup *prcm_irq_setup; /* prm_base: base virtual address of the PRM IP block */ void __iomem *prm_base; +u16 prm_features; + /* * prm_ll_data: function pointers to SoC-specific implementations of * common PRM functions From b550e47f5e9e74999f754371bdc79331d19f84a3 Mon Sep 17 00:00:00 2001 From: Tero Kristo Date: Mon, 31 Mar 2014 18:15:45 +0300 Subject: [PATCH 72/87] ARM: OMAP3/4: PRM: add support of late_init call to prm_ll_ops SoC specific late_init call is now registered during PRM init, and will be called automatically by PRM core. This helps to get rid of some redundant initcalls and cpu_is_X checks from the PRM code. Signed-off-by: Tero Kristo Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/prm.h | 2 ++ arch/arm/mach-omap2/prm3xxx.c | 7 +++---- arch/arm/mach-omap2/prm44xx.c | 7 +++---- arch/arm/mach-omap2/prm_common.c | 8 ++++++++ 4 files changed, 16 insertions(+), 8 deletions(-) diff --git a/arch/arm/mach-omap2/prm.h b/arch/arm/mach-omap2/prm.h index 04426c441fff..48480d557b61 100644 --- a/arch/arm/mach-omap2/prm.h +++ b/arch/arm/mach-omap2/prm.h @@ -126,6 +126,7 @@ struct prm_reset_src_map { * @read_reset_sources: ptr to the SoC PRM-specific get_reset_source impl * @was_any_context_lost_old: ptr to the SoC PRM context loss test fn * @clear_context_loss_flags_old: ptr to the SoC PRM context loss flag clear fn + * @late_init: ptr to the late init function * * XXX @was_any_context_lost_old and @clear_context_loss_flags_old are * deprecated. @@ -134,6 +135,7 @@ struct prm_ll_data { u32 (*read_reset_sources)(void); bool (*was_any_context_lost_old)(u8 part, s16 inst, u16 idx); void (*clear_context_loss_flags_old)(u8 part, s16 inst, u16 idx); + int (*late_init)(void); }; extern int prm_register(struct prm_ll_data *pld); diff --git a/arch/arm/mach-omap2/prm3xxx.c b/arch/arm/mach-omap2/prm3xxx.c index 9c95ac21c5b3..4a792fd1363c 100644 --- a/arch/arm/mach-omap2/prm3xxx.c +++ b/arch/arm/mach-omap2/prm3xxx.c @@ -401,8 +401,11 @@ struct pwrdm_ops omap3_pwrdm_operations = { * */ +static int omap3xxx_prm_late_init(void); + static struct prm_ll_data omap3xxx_prm_ll_data = { .read_reset_sources = &omap3xxx_prm_read_reset_sources, + .late_init = &omap3xxx_prm_late_init, }; int __init omap3xxx_prm_init(void) @@ -417,9 +420,6 @@ static int __init omap3xxx_prm_late_init(void) { int ret; - if (!cpu_is_omap34xx()) - return 0; - if (!(prm_features & PRM_HAS_IO_WAKEUP)) return 0; @@ -431,7 +431,6 @@ static int __init omap3xxx_prm_late_init(void) return ret; } -omap_subsys_initcall(omap3xxx_prm_late_init); static void __exit omap3xxx_prm_exit(void) { diff --git a/arch/arm/mach-omap2/prm44xx.c b/arch/arm/mach-omap2/prm44xx.c index e4e52f14dbbf..edf49ef867e1 100644 --- a/arch/arm/mach-omap2/prm44xx.c +++ b/arch/arm/mach-omap2/prm44xx.c @@ -650,6 +650,8 @@ struct pwrdm_ops omap4_pwrdm_operations = { .pwrdm_has_voltdm = omap4_check_vcvp, }; +static int omap44xx_prm_late_init(void); + /* * XXX document */ @@ -657,6 +659,7 @@ static struct prm_ll_data omap44xx_prm_ll_data = { .read_reset_sources = &omap44xx_prm_read_reset_sources, .was_any_context_lost_old = &omap44xx_prm_was_any_context_lost_old, .clear_context_loss_flags_old = &omap44xx_prm_clear_context_loss_flags_old, + .late_init = &omap44xx_prm_late_init, }; int __init omap44xx_prm_init(void) @@ -669,9 +672,6 @@ int __init omap44xx_prm_init(void) static int __init omap44xx_prm_late_init(void) { - if (!cpu_is_omap44xx()) - return 0; - if (!(prm_features & PRM_HAS_IO_WAKEUP)) return 0; @@ -679,7 +679,6 @@ static int __init omap44xx_prm_late_init(void) return omap_prcm_register_chain_handler(&omap4_prcm_irq_setup); } -omap_subsys_initcall(omap44xx_prm_late_init); static void __exit omap44xx_prm_exit(void) { diff --git a/arch/arm/mach-omap2/prm_common.c b/arch/arm/mach-omap2/prm_common.c index aa2550dd2ac1..25e8b8232115 100644 --- a/arch/arm/mach-omap2/prm_common.c +++ b/arch/arm/mach-omap2/prm_common.c @@ -527,3 +527,11 @@ int __init of_prcm_init(void) return 0; } + +static int __init prm_late_init(void) +{ + if (prm_ll_data->late_init) + return prm_ll_data->late_init(); + return 0; +} +subsys_initcall(prm_late_init); From 70fcebf1965b66d73bd8ae7955bd663ab8012c56 Mon Sep 17 00:00:00 2001 From: Tero Kristo Date: Mon, 31 Mar 2014 18:15:52 +0300 Subject: [PATCH 73/87] ARM: OMAP4: PRCM: remove references to cm-regbits-44xx.h from PRCM core files Done in preparation to make PRCM a standalone driver. Signed-off-by: Tero Kristo Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/cm44xx.c | 1 - arch/arm/mach-omap2/cminst44xx.c | 8 +++++++- arch/arm/mach-omap2/powerdomain-common.c | 1 - 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/arch/arm/mach-omap2/cm44xx.c b/arch/arm/mach-omap2/cm44xx.c index 37ba6e8f9505..c440ba753882 100644 --- a/arch/arm/mach-omap2/cm44xx.c +++ b/arch/arm/mach-omap2/cm44xx.c @@ -21,7 +21,6 @@ #include "cm.h" #include "cm1_44xx.h" #include "cm2_44xx.h" -#include "cm-regbits-44xx.h" /* CM1 hardware module low-level functions */ diff --git a/arch/arm/mach-omap2/cminst44xx.c b/arch/arm/mach-omap2/cminst44xx.c index 434b52af0364..82984b2f2715 100644 --- a/arch/arm/mach-omap2/cminst44xx.c +++ b/arch/arm/mach-omap2/cminst44xx.c @@ -28,12 +28,18 @@ #include "cm44xx.h" #include "cminst44xx.h" #include "cm-regbits-34xx.h" -#include "cm-regbits-44xx.h" #include "prcm44xx.h" #include "prm44xx.h" #include "prcm_mpu44xx.h" #include "prcm-common.h" +#define OMAP4430_IDLEST_SHIFT 16 +#define OMAP4430_IDLEST_MASK (0x3 << 16) +#define OMAP4430_CLKTRCTRL_SHIFT 0 +#define OMAP4430_CLKTRCTRL_MASK (0x3 << 0) +#define OMAP4430_MODULEMODE_SHIFT 0 +#define OMAP4430_MODULEMODE_MASK (0x3 << 0) + /* * CLKCTRL_IDLEST_*: possible values for the CM_*_CLKCTRL.IDLEST bitfield: * diff --git a/arch/arm/mach-omap2/powerdomain-common.c b/arch/arm/mach-omap2/powerdomain-common.c index c0aeabfcf009..c40e5f009826 100644 --- a/arch/arm/mach-omap2/powerdomain-common.c +++ b/arch/arm/mach-omap2/powerdomain-common.c @@ -17,7 +17,6 @@ #include "pm.h" #include "cm.h" #include "cm-regbits-34xx.h" -#include "cm-regbits-44xx.h" #include "prm-regbits-34xx.h" #include "prm-regbits-44xx.h" From 75ad2ab28f0f184a7ba7f816b62be04c3c0ba80a Mon Sep 17 00:00:00 2001 From: Leela Krishna Amudala Date: Fri, 9 May 2014 22:51:04 +0900 Subject: [PATCH 74/87] ARM: EXYNOS: use v7_exit_coherency_flush macro for cache disabling A common macro v7_exit_coherency_flush available which does the below tasks in the seqeunce. -clearing C bit -clearing L1 cache -exit SMP -instruction and data synchronization So removing the local functions which does the same thing and use the macro instead. Signed-off-by: Leela Krishna Amudala Acked-by: Nicolas Pitre [cw00.choi@samsung.com: tested on exynos3250 based board] Tested-by: Chanwoo Choi Signed-off-by: Kukjin Kim --- arch/arm/mach-exynos/hotplug.c | 63 +--------------------------------- 1 file changed, 1 insertion(+), 62 deletions(-) diff --git a/arch/arm/mach-exynos/hotplug.c b/arch/arm/mach-exynos/hotplug.c index 5eead530c6f8..9ca692d2744e 100644 --- a/arch/arm/mach-exynos/hotplug.c +++ b/arch/arm/mach-exynos/hotplug.c @@ -24,56 +24,6 @@ #include "common.h" #include "regs-pmu.h" -static inline void cpu_enter_lowpower_a9(void) -{ - unsigned int v; - - asm volatile( - " mcr p15, 0, %1, c7, c5, 0\n" - " mcr p15, 0, %1, c7, c10, 4\n" - /* - * Turn off coherency - */ - " mrc p15, 0, %0, c1, c0, 1\n" - " bic %0, %0, %3\n" - " mcr p15, 0, %0, c1, c0, 1\n" - " mrc p15, 0, %0, c1, c0, 0\n" - " bic %0, %0, %2\n" - " mcr p15, 0, %0, c1, c0, 0\n" - : "=&r" (v) - : "r" (0), "Ir" (CR_C), "Ir" (0x40) - : "cc"); -} - -static inline void cpu_enter_lowpower_a15(void) -{ - unsigned int v; - - asm volatile( - " mrc p15, 0, %0, c1, c0, 0\n" - " bic %0, %0, %1\n" - " mcr p15, 0, %0, c1, c0, 0\n" - : "=&r" (v) - : "Ir" (CR_C) - : "cc"); - - flush_cache_louis(); - - asm volatile( - /* - * Turn off coherency - */ - " mrc p15, 0, %0, c1, c0, 1\n" - " bic %0, %0, %1\n" - " mcr p15, 0, %0, c1, c0, 1\n" - : "=&r" (v) - : "Ir" (0x40) - : "cc"); - - isb(); - dsb(); -} - static inline void cpu_leave_lowpower(void) { unsigned int v; @@ -132,19 +82,8 @@ static inline void platform_do_lowpower(unsigned int cpu, int *spurious) void __ref exynos_cpu_die(unsigned int cpu) { int spurious = 0; - int primary_part = 0; - /* - * we're ready for shutdown now, so do it. - * Exynos4 is A9 based while Exynos5 is A15; check the CPU part - * number by reading the Main ID register and then perform the - * appropriate sequence for entering low power. - */ - asm("mrc p15, 0, %0, c0, c0, 0" : "=r"(primary_part) : : "cc"); - if ((primary_part & 0xfff0) == 0xc0f0) - cpu_enter_lowpower_a15(); - else - cpu_enter_lowpower_a9(); + v7_exit_coherency_flush(louis); platform_do_lowpower(cpu, &spurious); From fd5770658f3f2ad9c9c9d7afd11a77d9980429d6 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Tue, 13 May 2014 07:11:50 +0900 Subject: [PATCH 75/87] ARM: EXYNOS: Remove duplicate lines in Makefile Group all files compiled under common config option together. Signed-off-by: Sachin Kamat Reviewed-by: Tomasz Figa Signed-off-by: Kukjin Kim --- arch/arm/mach-exynos/Makefile | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/arch/arm/mach-exynos/Makefile b/arch/arm/mach-exynos/Makefile index a656dbe3b78c..f6dcc256db56 100644 --- a/arch/arm/mach-exynos/Makefile +++ b/arch/arm/mach-exynos/Makefile @@ -12,20 +12,15 @@ obj- := # Core -obj-$(CONFIG_ARCH_EXYNOS) += exynos.o +obj-$(CONFIG_ARCH_EXYNOS) += exynos.o pmu.o exynos-smc.o firmware.o obj-$(CONFIG_PM_SLEEP) += pm.o sleep.o obj-$(CONFIG_PM_GENERIC_DOMAINS) += pm_domains.o obj-$(CONFIG_CPU_IDLE) += cpuidle.o -obj-$(CONFIG_ARCH_EXYNOS) += pmu.o - obj-$(CONFIG_SMP) += platsmp.o headsmp.o obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o -obj-$(CONFIG_ARCH_EXYNOS) += exynos-smc.o -obj-$(CONFIG_ARCH_EXYNOS) += firmware.o - plus_sec := $(call as-instr,.arch_extension sec,+sec) AFLAGS_exynos-smc.o :=-Wa,-march=armv7-a$(plus_sec) From ced2d24584da35c5cd45faecf3c6db7abb7e16c9 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Tue, 13 May 2014 07:11:53 +0900 Subject: [PATCH 76/87] ARM: EXYNOS: Remove exynos_subsys registration 'exynos_subsys' has no users. Remove this code. Signed-off-by: Sachin Kamat Reviewed-by: Tomasz Figa Signed-off-by: Kukjin Kim --- arch/arm/mach-exynos/exynos.c | 11 ----------- arch/arm/plat-samsung/include/plat/cpu.h | 1 - 2 files changed, 12 deletions(-) diff --git a/arch/arm/mach-exynos/exynos.c b/arch/arm/mach-exynos/exynos.c index b32a907d021d..eb1a431a894a 100644 --- a/arch/arm/mach-exynos/exynos.c +++ b/arch/arm/mach-exynos/exynos.c @@ -308,17 +308,6 @@ void __init exynos_init_io(void) exynos_map_io(); } -struct bus_type exynos_subsys = { - .name = "exynos-core", - .dev_name = "exynos-core", -}; - -static int __init exynos_core_init(void) -{ - return subsys_system_register(&exynos_subsys, NULL); -} -core_initcall(exynos_core_init); - static int __init exynos4_l2x0_cache_init(void) { int ret; diff --git a/arch/arm/plat-samsung/include/plat/cpu.h b/arch/arm/plat-samsung/include/plat/cpu.h index 5992b8dd9b89..930b4be832cd 100644 --- a/arch/arm/plat-samsung/include/plat/cpu.h +++ b/arch/arm/plat-samsung/include/plat/cpu.h @@ -239,7 +239,6 @@ extern struct bus_type s3c2443_subsys; extern struct bus_type s3c6410_subsys; extern struct bus_type s5p64x0_subsys; extern struct bus_type s5pv210_subsys; -extern struct bus_type exynos_subsys; extern void (*s5pc1xx_idle)(void); From 7cb2ded128ab34d8172f25e6da417d732d7e3520 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Tue, 13 May 2014 07:11:57 +0900 Subject: [PATCH 77/87] ARM: EXYNOS: Migrate Exynos specific macros from plat to mach Move Exynos specific macros to mach-exynos from plat-samsung to avoid unnecessary dependency on plat based header files. Signed-off-by: Sachin Kamat Reviewed-by: Tomasz Figa Signed-off-by: Kukjin Kim --- arch/arm/mach-exynos/common.h | 72 ++++++++++++++++++++++++ arch/arm/plat-samsung/include/plat/cpu.h | 60 -------------------- 2 files changed, 72 insertions(+), 60 deletions(-) diff --git a/arch/arm/mach-exynos/common.h b/arch/arm/mach-exynos/common.h index 9ef3f83efaff..c1a2f2207af0 100644 --- a/arch/arm/mach-exynos/common.h +++ b/arch/arm/mach-exynos/common.h @@ -15,6 +15,75 @@ #include #include +#define EXYNOS4210_CPU_ID 0x43210000 +#define EXYNOS4212_CPU_ID 0x43220000 +#define EXYNOS4412_CPU_ID 0xE4412200 +#define EXYNOS4_CPU_MASK 0xFFFE0000 + +#define EXYNOS5250_SOC_ID 0x43520000 +#define EXYNOS5420_SOC_ID 0xE5420000 +#define EXYNOS5440_SOC_ID 0xE5440000 +#define EXYNOS5_SOC_MASK 0xFFFFF000 + +extern unsigned long samsung_cpu_id; + +#define IS_SAMSUNG_CPU(name, id, mask) \ +static inline int is_samsung_##name(void) \ +{ \ + return ((samsung_cpu_id & mask) == (id & mask)); \ +} + +IS_SAMSUNG_CPU(exynos4210, EXYNOS4210_CPU_ID, EXYNOS4_CPU_MASK) +IS_SAMSUNG_CPU(exynos4212, EXYNOS4212_CPU_ID, EXYNOS4_CPU_MASK) +IS_SAMSUNG_CPU(exynos4412, EXYNOS4412_CPU_ID, EXYNOS4_CPU_MASK) +IS_SAMSUNG_CPU(exynos5250, EXYNOS5250_SOC_ID, EXYNOS5_SOC_MASK) +IS_SAMSUNG_CPU(exynos5420, EXYNOS5420_SOC_ID, EXYNOS5_SOC_MASK) +IS_SAMSUNG_CPU(exynos5440, EXYNOS5440_SOC_ID, EXYNOS5_SOC_MASK) + +#if defined(CONFIG_CPU_EXYNOS4210) +# define soc_is_exynos4210() is_samsung_exynos4210() +#else +# define soc_is_exynos4210() 0 +#endif + +#if defined(CONFIG_SOC_EXYNOS4212) +# define soc_is_exynos4212() is_samsung_exynos4212() +#else +# define soc_is_exynos4212() 0 +#endif + +#if defined(CONFIG_SOC_EXYNOS4412) +# define soc_is_exynos4412() is_samsung_exynos4412() +#else +# define soc_is_exynos4412() 0 +#endif + +#define EXYNOS4210_REV_0 (0x0) +#define EXYNOS4210_REV_1_0 (0x10) +#define EXYNOS4210_REV_1_1 (0x11) + +#if defined(CONFIG_SOC_EXYNOS5250) +# define soc_is_exynos5250() is_samsung_exynos5250() +#else +# define soc_is_exynos5250() 0 +#endif + +#if defined(CONFIG_SOC_EXYNOS5420) +# define soc_is_exynos5420() is_samsung_exynos5420() +#else +# define soc_is_exynos5420() 0 +#endif + +#if defined(CONFIG_SOC_EXYNOS5440) +# define soc_is_exynos5440() is_samsung_exynos5440() +#else +# define soc_is_exynos5440() 0 +#endif + +#define soc_is_exynos4() (soc_is_exynos4210() || soc_is_exynos4212() || \ + soc_is_exynos4412()) +#define soc_is_exynos5() (soc_is_exynos5250() || soc_is_exynos5420()) + void mct_init(void __iomem *base, int irq_g0, int irq_l0, int irq_l1); struct map_desc; @@ -63,4 +132,7 @@ struct exynos_pmu_conf { extern void exynos_sys_powerdown_conf(enum sys_powerdown mode); +extern void s5p_init_cpu(void __iomem *cpuid_addr); +extern unsigned int samsung_rev(void); + #endif /* __ARCH_ARM_MACH_EXYNOS_COMMON_H */ diff --git a/arch/arm/plat-samsung/include/plat/cpu.h b/arch/arm/plat-samsung/include/plat/cpu.h index 930b4be832cd..5a237db9f9eb 100644 --- a/arch/arm/plat-samsung/include/plat/cpu.h +++ b/arch/arm/plat-samsung/include/plat/cpu.h @@ -43,16 +43,6 @@ extern unsigned long samsung_cpu_id; #define S5PV210_CPU_ID 0x43110000 #define S5PV210_CPU_MASK 0xFFFFF000 -#define EXYNOS4210_CPU_ID 0x43210000 -#define EXYNOS4212_CPU_ID 0x43220000 -#define EXYNOS4412_CPU_ID 0xE4412200 -#define EXYNOS4_CPU_MASK 0xFFFE0000 - -#define EXYNOS5250_SOC_ID 0x43520000 -#define EXYNOS5420_SOC_ID 0xE5420000 -#define EXYNOS5440_SOC_ID 0xE5440000 -#define EXYNOS5_SOC_MASK 0xFFFFF000 - #define IS_SAMSUNG_CPU(name, id, mask) \ static inline int is_samsung_##name(void) \ { \ @@ -68,12 +58,6 @@ IS_SAMSUNG_CPU(s5p6440, S5P6440_CPU_ID, S5P64XX_CPU_MASK) IS_SAMSUNG_CPU(s5p6450, S5P6450_CPU_ID, S5P64XX_CPU_MASK) IS_SAMSUNG_CPU(s5pc100, S5PC100_CPU_ID, S5PC100_CPU_MASK) IS_SAMSUNG_CPU(s5pv210, S5PV210_CPU_ID, S5PV210_CPU_MASK) -IS_SAMSUNG_CPU(exynos4210, EXYNOS4210_CPU_ID, EXYNOS4_CPU_MASK) -IS_SAMSUNG_CPU(exynos4212, EXYNOS4212_CPU_ID, EXYNOS4_CPU_MASK) -IS_SAMSUNG_CPU(exynos4412, EXYNOS4412_CPU_ID, EXYNOS4_CPU_MASK) -IS_SAMSUNG_CPU(exynos5250, EXYNOS5250_SOC_ID, EXYNOS5_SOC_MASK) -IS_SAMSUNG_CPU(exynos5420, EXYNOS5420_SOC_ID, EXYNOS5_SOC_MASK) -IS_SAMSUNG_CPU(exynos5440, EXYNOS5440_SOC_ID, EXYNOS5_SOC_MASK) #if defined(CONFIG_CPU_S3C2410) || defined(CONFIG_CPU_S3C2412) || \ defined(CONFIG_CPU_S3C2416) || defined(CONFIG_CPU_S3C2440) || \ @@ -126,50 +110,6 @@ IS_SAMSUNG_CPU(exynos5440, EXYNOS5440_SOC_ID, EXYNOS5_SOC_MASK) # define soc_is_s5pv210() 0 #endif -#if defined(CONFIG_CPU_EXYNOS4210) -# define soc_is_exynos4210() is_samsung_exynos4210() -#else -# define soc_is_exynos4210() 0 -#endif - -#if defined(CONFIG_SOC_EXYNOS4212) -# define soc_is_exynos4212() is_samsung_exynos4212() -#else -# define soc_is_exynos4212() 0 -#endif - -#if defined(CONFIG_SOC_EXYNOS4412) -# define soc_is_exynos4412() is_samsung_exynos4412() -#else -# define soc_is_exynos4412() 0 -#endif - -#define EXYNOS4210_REV_0 (0x0) -#define EXYNOS4210_REV_1_0 (0x10) -#define EXYNOS4210_REV_1_1 (0x11) - -#if defined(CONFIG_SOC_EXYNOS5250) -# define soc_is_exynos5250() is_samsung_exynos5250() -#else -# define soc_is_exynos5250() 0 -#endif - -#if defined(CONFIG_SOC_EXYNOS5420) -# define soc_is_exynos5420() is_samsung_exynos5420() -#else -# define soc_is_exynos5420() 0 -#endif - -#if defined(CONFIG_SOC_EXYNOS5440) -# define soc_is_exynos5440() is_samsung_exynos5440() -#else -# define soc_is_exynos5440() 0 -#endif - -#define soc_is_exynos4() (soc_is_exynos4210() || soc_is_exynos4212() || \ - soc_is_exynos4412()) -#define soc_is_exynos5() (soc_is_exynos5250() || soc_is_exynos5420()) - #define IODESC_ENT(x) { (unsigned long)S3C24XX_VA_##x, __phys_to_pfn(S3C24XX_PA_##x), S3C24XX_SZ_##x, MT_DEVICE } #ifndef KHZ From 4b245edc99f056f05a61cb2b1fd4604875cf8eab Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Tue, 13 May 2014 07:12:00 +0900 Subject: [PATCH 78/87] ARM: EXYNOS: Remove unnecessary inclusion of cpu.h Exynos specific macros and declarations have been moved to mach-exynos. Inclusion of plat/cpu.h is no more necessary. Signed-off-by: Sachin Kamat Reviewed-by: Tomasz Figa Signed-off-by: Kukjin Kim --- arch/arm/mach-exynos/cpuidle.c | 1 - arch/arm/mach-exynos/exynos.c | 2 -- arch/arm/mach-exynos/firmware.c | 3 +-- arch/arm/mach-exynos/hotplug.c | 2 -- arch/arm/mach-exynos/platsmp.c | 2 -- arch/arm/mach-exynos/pm.c | 1 - arch/arm/mach-exynos/pmu.c | 2 -- 7 files changed, 1 insertion(+), 12 deletions(-) diff --git a/arch/arm/mach-exynos/cpuidle.c b/arch/arm/mach-exynos/cpuidle.c index c57cae0e8779..3dd385ebf195 100644 --- a/arch/arm/mach-exynos/cpuidle.c +++ b/arch/arm/mach-exynos/cpuidle.c @@ -24,7 +24,6 @@ #include #include -#include #include #include diff --git a/arch/arm/mach-exynos/exynos.c b/arch/arm/mach-exynos/exynos.c index eb1a431a894a..59aab756702e 100644 --- a/arch/arm/mach-exynos/exynos.c +++ b/arch/arm/mach-exynos/exynos.c @@ -26,8 +26,6 @@ #include #include -#include - #include "common.h" #include "mfc.h" #include "regs-pmu.h" diff --git a/arch/arm/mach-exynos/firmware.c b/arch/arm/mach-exynos/firmware.c index aa01c4222b40..f6cb510aee85 100644 --- a/arch/arm/mach-exynos/firmware.c +++ b/arch/arm/mach-exynos/firmware.c @@ -18,8 +18,7 @@ #include -#include - +#include "common.h" #include "smc.h" static int exynos_do_idle(void) diff --git a/arch/arm/mach-exynos/hotplug.c b/arch/arm/mach-exynos/hotplug.c index 9ca692d2744e..3cab3f506689 100644 --- a/arch/arm/mach-exynos/hotplug.c +++ b/arch/arm/mach-exynos/hotplug.c @@ -19,8 +19,6 @@ #include #include -#include - #include "common.h" #include "regs-pmu.h" diff --git a/arch/arm/mach-exynos/platsmp.c b/arch/arm/mach-exynos/platsmp.c index 03e5e9f94705..c28cdb1c82cd 100644 --- a/arch/arm/mach-exynos/platsmp.c +++ b/arch/arm/mach-exynos/platsmp.c @@ -26,8 +26,6 @@ #include #include -#include - #include "common.h" #include "regs-pmu.h" diff --git a/arch/arm/mach-exynos/pm.c b/arch/arm/mach-exynos/pm.c index 15af0ceb0a66..ca672e24b5cd 100644 --- a/arch/arm/mach-exynos/pm.c +++ b/arch/arm/mach-exynos/pm.c @@ -26,7 +26,6 @@ #include #include -#include #include #include #include diff --git a/arch/arm/mach-exynos/pmu.c b/arch/arm/mach-exynos/pmu.c index 05c7ce15322a..fb0deda3b3a4 100644 --- a/arch/arm/mach-exynos/pmu.c +++ b/arch/arm/mach-exynos/pmu.c @@ -13,8 +13,6 @@ #include #include -#include - #include "common.h" #include "regs-pmu.h" From 46f34abc750c66fdb4daa9a8bc9d7f955e95eb9c Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Fri, 16 May 2014 06:59:18 +0900 Subject: [PATCH 79/87] ARM: compressed/head.S: remove s3c24xx special case addruart from the generic debug macro is doing exactly the same using the common lowlevel uart definition, so there is no cause for this special casing for s3c24xx. Signed-off-by: Heiko Stuebner Signed-off-by: Kukjin Kim --- arch/arm/boot/compressed/head.S | 5 ----- 1 file changed, 5 deletions(-) diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S index 066b03480b63..3a8b32df6b31 100644 --- a/arch/arm/boot/compressed/head.S +++ b/arch/arm/boot/compressed/head.S @@ -60,11 +60,6 @@ add \rb, \rb, #0x00010000 @ Ser1 #endif .endm -#elif defined(CONFIG_ARCH_S3C24XX) - .macro loadsp, rb, tmp - mov \rb, #0x50000000 - add \rb, \rb, #0x4000 * CONFIG_S3C_LOWLEVEL_UART_PORT - .endm #else .macro loadsp, rb, tmp addruart \rb, \tmp From daf67dfc5989495c887cfdbe76be72b7db724e60 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Fri, 16 May 2014 06:59:18 +0900 Subject: [PATCH 80/87] ARM: S3C24XX: trim down debug uart handling Using the lowlevel debug uart is a corner case - even more so in a multiplatform environment. So it seems reasonable to simply let the developer set the appropriate uart type for the debugged SoC. Signed-off-by: Heiko Stuebner Signed-off-by: Kukjin Kim --- arch/arm/Kconfig.debug | 30 +++++++++++ arch/arm/mach-s3c24xx/Kconfig | 28 ---------- .../mach-s3c24xx/include/mach/debug-macro.S | 52 +------------------ 3 files changed, 31 insertions(+), 79 deletions(-) diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug index eab8ecbe69c1..8c72e1003b9a 100644 --- a/arch/arm/Kconfig.debug +++ b/arch/arm/Kconfig.debug @@ -670,6 +670,33 @@ choice The uncompressor code port configuration is now handled by CONFIG_S3C_LOWLEVEL_UART_PORT. + config DEBUG_S3C2410_UART0 + depends on ARCH_S3C24XX + select DEBUG_S3C2410_UART + bool "Use S3C2410/S3C2412 UART 0 for low-level debug" + help + Say Y here if you want the debug print routines to direct + their output to UART 0. The port must have been initialised + by the boot-loader before use. + + config DEBUG_S3C2410_UART1 + depends on ARCH_S3C24XX + select DEBUG_S3C2410_UART + bool "Use S3C2410/S3C2412 UART 1 for low-level debug" + help + Say Y here if you want the debug print routines to direct + their output to UART 1. The port must have been initialised + by the boot-loader before use. + + config DEBUG_S3C2410_UART2 + depends on ARCH_S3C24XX + select DEBUG_S3C2410_UART + bool "Use S3C2410/S3C2412 UART 2 for low-level debug" + help + Say Y here if you want the debug print routines to direct + their output to UART 2. The port must have been initialised + by the boot-loader before use. + config DEBUG_SOCFPGA_UART depends on ARCH_SOCFPGA bool "Use SOCFPGA UART for low-level debug" @@ -921,6 +948,9 @@ endchoice config DEBUG_EXYNOS_UART bool +config DEBUG_S3C2410_UART + bool + config DEBUG_OMAP2PLUS_UART bool depends on ARCH_OMAP2PLUS diff --git a/arch/arm/mach-s3c24xx/Kconfig b/arch/arm/mach-s3c24xx/Kconfig index 22d149bcfcc6..45a7026e9419 100644 --- a/arch/arm/mach-s3c24xx/Kconfig +++ b/arch/arm/mach-s3c24xx/Kconfig @@ -39,7 +39,6 @@ config CPU_S3C2410 default y select COMMON_CLK select CPU_ARM920T - select CPU_LLSERIAL_S3C2410 select S3C2410_COMMON_CLK select S3C2410_DMA if S3C24XX_DMA select ARM_S3C2410_CPUFREQ if ARM_S3C24XX_CPUFREQ @@ -53,7 +52,6 @@ config CPU_S3C2412 bool "SAMSUNG S3C2412" select COMMON_CLK select CPU_ARM926T - select CPU_LLSERIAL_S3C2440 select S3C2412_COMMON_CLK select S3C2412_DMA if S3C24XX_DMA select S3C2412_PM if PM @@ -64,7 +62,6 @@ config CPU_S3C2416 bool "SAMSUNG S3C2416/S3C2450" select COMMON_CLK select CPU_ARM926T - select CPU_LLSERIAL_S3C2440 select S3C2416_PM if PM select S3C2443_COMMON_CLK select S3C2443_DMA if S3C24XX_DMA @@ -75,7 +72,6 @@ config CPU_S3C2440 bool "SAMSUNG S3C2440" select COMMON_CLK select CPU_ARM920T - select CPU_LLSERIAL_S3C2440 select S3C2410_COMMON_CLK select S3C2410_PM if PM select S3C2440_DMA if S3C24XX_DMA @@ -86,7 +82,6 @@ config CPU_S3C2442 bool "SAMSUNG S3C2442" select COMMON_CLK select CPU_ARM920T - select CPU_LLSERIAL_S3C2440 select S3C2410_COMMON_CLK select S3C2410_DMA if S3C24XX_DMA select S3C2410_PM if PM @@ -102,7 +97,6 @@ config CPU_S3C2443 bool "SAMSUNG S3C2443" select COMMON_CLK select CPU_ARM920T - select CPU_LLSERIAL_S3C2440 select S3C2443_COMMON_CLK select S3C2443_DMA if S3C24XX_DMA help @@ -164,28 +158,6 @@ config S3C2410_PM help Power Management code common to S3C2410 and better -# low-level serial option nodes - -config CPU_LLSERIAL_S3C2410_ONLY - bool - default y if CPU_LLSERIAL_S3C2410 && !CPU_LLSERIAL_S3C2440 - -config CPU_LLSERIAL_S3C2440_ONLY - bool - default y if CPU_LLSERIAL_S3C2440 && !CPU_LLSERIAL_S3C2410 - -config CPU_LLSERIAL_S3C2410 - bool - help - Selected if there is an S3C2410 (or register compatible) serial - low-level implementation needed - -config CPU_LLSERIAL_S3C2440 - bool - help - Selected if there is an S3C2440 (or register compatible) serial - low-level implementation needed - config S3C24XX_PLL bool "Support CPUfreq changing of PLL frequency (EXPERIMENTAL)" depends on ARM_S3C24XX_CPUFREQ diff --git a/arch/arm/mach-s3c24xx/include/mach/debug-macro.S b/arch/arm/mach-s3c24xx/include/mach/debug-macro.S index 2f39737544c0..fbe3e711ebab 100644 --- a/arch/arm/mach-s3c24xx/include/mach/debug-macro.S +++ b/arch/arm/mach-s3c24xx/include/mach/debug-macro.S @@ -13,11 +13,9 @@ */ #include -#include #include #define S3C2410_UART1_OFF (0x4000) -#define SHIFT_2440TXF (14-9) .macro addruart, rp, rv, tmp ldr \rp, = S3C24XX_PA_UART @@ -28,56 +26,11 @@ #endif .endm - .macro fifo_full_s3c24xx rd, rx - @ check for arm920 vs arm926. currently assume all arm926 - @ devices have an 64 byte FIFO identical to the s3c2440 - mrc p15, 0, \rd, c0, c0 - and \rd, \rd, #0xff0 - teq \rd, #0x260 - beq 1004f - mrc p15, 0, \rd, c1, c0 - tst \rd, #1 - addeq \rd, \rx, #(S3C24XX_PA_GPIO - S3C24XX_PA_UART) - addne \rd, \rx, #(S3C24XX_VA_GPIO - S3C24XX_VA_UART) - bic \rd, \rd, #0xff000 - ldr \rd, [\rd, # S3C2410_GSTATUS1 - S3C2410_GPIOREG(0)] - and \rd, \rd, #0x00ff0000 - teq \rd, #0x00440000 @ is it 2440? -1004: - ldr \rd, [\rx, # S3C2410_UFSTAT] - moveq \rd, \rd, lsr #SHIFT_2440TXF - tst \rd, #S3C2410_UFSTAT_TXFULL - .endm - .macro fifo_full_s3c2410 rd, rx ldr \rd, [\rx, # S3C2410_UFSTAT] tst \rd, #S3C2410_UFSTAT_TXFULL .endm -/* fifo level reading */ - - .macro fifo_level_s3c24xx rd, rx - @ check for arm920 vs arm926. currently assume all arm926 - @ devices have an 64 byte FIFO identical to the s3c2440 - mrc p15, 0, \rd, c0, c0 - and \rd, \rd, #0xff0 - teq \rd, #0x260 - beq 10000f - mrc p15, 0, \rd, c1, c0 - tst \rd, #1 - addeq \rd, \rx, #(S3C24XX_PA_GPIO - S3C24XX_PA_UART) - addne \rd, \rx, #(S3C24XX_VA_GPIO - S3C24XX_VA_UART) - bic \rd, \rd, #0xff000 - ldr \rd, [\rd, # S3C2410_GSTATUS1 - S3C2410_GPIOREG(0)] - and \rd, \rd, #0x00ff0000 - teq \rd, #0x00440000 @ is it 2440? - -10000: - ldr \rd, [\rx, # S3C2410_UFSTAT] - andne \rd, \rd, #S3C2410_UFSTAT_TXMASK - andeq \rd, \rd, #S3C2440_UFSTAT_TXMASK - .endm - .macro fifo_level_s3c2410 rd, rx ldr \rd, [\rx, # S3C2410_UFSTAT] and \rd, \rd, #S3C2410_UFSTAT_TXMASK @@ -88,12 +41,9 @@ * used variants of these */ -#if defined(CONFIG_CPU_LLSERIAL_S3C2410_ONLY) +#if defined(CONFIG_DEBUG_S3C2410_UART) #define fifo_full fifo_full_s3c2410 #define fifo_level fifo_level_s3c2410 -#elif !defined(CONFIG_CPU_LLSERIAL_S3C2440_ONLY) -#define fifo_full fifo_full_s3c24xx -#define fifo_level fifo_level_s3c24xx #endif /* include the reset of the code which will do the work */ From 1899de2894970fbeece3a97dd69d5321fb00972b Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Fri, 16 May 2014 06:59:18 +0900 Subject: [PATCH 81/87] ARM: S3C24XX: use generic DEBUG_UART_PHY/_VIRT in debug macro This removes the need for mach/-headers in the debug macro. Signed-off-by: Heiko Stuebner Signed-off-by: Kukjin Kim --- arch/arm/Kconfig.debug | 23 +++++++++++++++++-- .../mach-s3c24xx/include/mach/debug-macro.S | 9 ++------ 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug index 8c72e1003b9a..104c8fb818ed 100644 --- a/arch/arm/Kconfig.debug +++ b/arch/arm/Kconfig.debug @@ -625,6 +625,7 @@ choice config DEBUG_S3C_UART0 depends on PLAT_SAMSUNG select DEBUG_EXYNOS_UART if ARCH_EXYNOS + select DEBUG_S3C24XX_UART if ARCH_S3C24XX bool "Use S3C UART 0 for low-level debug" help Say Y here if you want the debug print routines to direct @@ -637,6 +638,7 @@ choice config DEBUG_S3C_UART1 depends on PLAT_SAMSUNG select DEBUG_EXYNOS_UART if ARCH_EXYNOS + select DEBUG_S3C24XX_UART if ARCH_S3C24XX bool "Use S3C UART 1 for low-level debug" help Say Y here if you want the debug print routines to direct @@ -649,6 +651,7 @@ choice config DEBUG_S3C_UART2 depends on PLAT_SAMSUNG select DEBUG_EXYNOS_UART if ARCH_EXYNOS + select DEBUG_S3C24XX_UART if ARCH_S3C24XX bool "Use S3C UART 2 for low-level debug" help Say Y here if you want the debug print routines to direct @@ -950,6 +953,10 @@ config DEBUG_EXYNOS_UART config DEBUG_S3C2410_UART bool + select DEBUG_S3C24XX_UART + +config DEBUG_S3C24XX_UART + bool config DEBUG_OMAP2PLUS_UART bool @@ -1059,6 +1066,12 @@ config DEBUG_UART_PHYS default 0x40090000 if ARCH_LPC32XX default 0x40100000 if DEBUG_PXA_UART1 default 0x42000000 if ARCH_GEMINI + default 0x50000000 if DEBUG_S3C24XX_UART && (DEBUG_S3C_UART0 || \ + DEBUG_S3C2410_UART0) + default 0x50004000 if DEBUG_S3C24XX_UART && (DEBUG_S3C_UART1 || \ + DEBUG_S3C2410_UART1) + default 0x50008000 if DEBUG_S3C24XX_UART && (DEBUG_S3C_UART2 || \ + DEBUG_S3C2410_UART2) default 0x7c0003f8 if FOOTBRIDGE default 0x80070000 if DEBUG_IMX23_UART default 0x80074000 if DEBUG_IMX28_UART @@ -1088,7 +1101,7 @@ config DEBUG_UART_PHYS default 0xfffff700 if ARCH_IOP33X depends on DEBUG_LL_UART_8250 || DEBUG_LL_UART_PL01X || \ DEBUG_LL_UART_EFM32 || \ - DEBUG_UART_8250 || DEBUG_UART_PL01X + DEBUG_UART_8250 || DEBUG_UART_PL01X || DEBUG_S3C24XX_UART config DEBUG_UART_VIRT hex "Virtual base address of debug UART" @@ -1105,6 +1118,12 @@ config DEBUG_UART_VIRT default 0xf2100000 if DEBUG_PXA_UART1 default 0xf4090000 if ARCH_LPC32XX default 0xf4200000 if ARCH_GEMINI + default 0xf7000000 if DEBUG_S3C24XX_UART && (DEBUG_S3C_UART0 || \ + DEBUG_S3C2410_UART0) + default 0xf7004000 if DEBUG_S3C24XX_UART && (DEBUG_S3C_UART1 || \ + DEBUG_S3C2410_UART1) + default 0xf7008000 if DEBUG_S3C24XX_UART && (DEBUG_S3C_UART2 || \ + DEBUG_S3C2410_UART2) default 0xf7fc9000 if DEBUG_BERLIN_UART default 0xf8009000 if DEBUG_VEXPRESS_UART0_CA9 default 0xf8090000 if DEBUG_VEXPRESS_UART0_RS1 @@ -1146,7 +1165,7 @@ config DEBUG_UART_VIRT default 0xff003000 if DEBUG_U300_UART default DEBUG_UART_PHYS if !MMU depends on DEBUG_LL_UART_8250 || DEBUG_LL_UART_PL01X || \ - DEBUG_UART_8250 || DEBUG_UART_PL01X + DEBUG_UART_8250 || DEBUG_UART_PL01X || DEBUG_S3C24XX_UART config DEBUG_UART_8250_SHIFT int "Register offset shift for the 8250 debug UART" diff --git a/arch/arm/mach-s3c24xx/include/mach/debug-macro.S b/arch/arm/mach-s3c24xx/include/mach/debug-macro.S index fbe3e711ebab..b1f54dc4888c 100644 --- a/arch/arm/mach-s3c24xx/include/mach/debug-macro.S +++ b/arch/arm/mach-s3c24xx/include/mach/debug-macro.S @@ -12,18 +12,13 @@ * published by the Free Software Foundation. */ -#include #include #define S3C2410_UART1_OFF (0x4000) .macro addruart, rp, rv, tmp - ldr \rp, = S3C24XX_PA_UART - ldr \rv, = S3C24XX_VA_UART -#if CONFIG_DEBUG_S3C_UART != 0 - add \rp, \rp, #(S3C2410_UART1_OFF * CONFIG_DEBUG_S3C_UART) - add \rv, \rv, #(S3C2410_UART1_OFF * CONFIG_DEBUG_S3C_UART) -#endif + ldr \rp, = CONFIG_DEBUG_UART_PHYS + ldr \rv, = CONFIG_DEBUG_UART_VIRT .endm .macro fifo_full_s3c2410 rd, rx From 2cd62bd4e5226ae5fa61f58ade8148f2e4643335 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Fri, 16 May 2014 06:59:18 +0900 Subject: [PATCH 82/87] ARM: S3C24XX: move debug-macro.S into the common space Move debug-macro.S from mach/include to include/debug where all other common debug macros are. Signed-off-by: Heiko Stuebner Signed-off-by: Kukjin Kim --- arch/arm/Kconfig.debug | 1 + .../include/mach/debug-macro.S => include/debug/s3c24xx.S} | 0 2 files changed, 1 insertion(+) rename arch/arm/{mach-s3c24xx/include/mach/debug-macro.S => include/debug/s3c24xx.S} (100%) diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug index 104c8fb818ed..4678870f8ee8 100644 --- a/arch/arm/Kconfig.debug +++ b/arch/arm/Kconfig.debug @@ -1010,6 +1010,7 @@ config DEBUG_LL_INCLUDE DEBUG_IMX6SL_UART default "debug/msm.S" if DEBUG_MSM_UART default "debug/omap2plus.S" if DEBUG_OMAP2PLUS_UART + default "debug/s3c24xx.S" if DEBUG_S3C24XX_UART default "debug/sirf.S" if DEBUG_SIRFPRIMA2_UART1 || DEBUG_SIRFMARCO_UART1 default "debug/sti.S" if DEBUG_STI_UART default "debug/tegra.S" if DEBUG_TEGRA_UART diff --git a/arch/arm/mach-s3c24xx/include/mach/debug-macro.S b/arch/arm/include/debug/s3c24xx.S similarity index 100% rename from arch/arm/mach-s3c24xx/include/mach/debug-macro.S rename to arch/arm/include/debug/s3c24xx.S From be1f7c8d7e2bc8b8c76846aa6f276e8d2ef8975a Mon Sep 17 00:00:00 2001 From: Jonghwan Choi Date: Sat, 17 May 2014 08:19:30 +0900 Subject: [PATCH 83/87] cpufreq: exynos: Fix the compile error Commit 7da83a80 ("ARM: EXYNOS: Migrate Exynos specific macros from plat to mach") which lands in samsung tree causes build breakage for cpufreq-exynos like following: drivers/cpufreq/exynos-cpufreq.c: In function 'exynos_cpufreq_probe': drivers/cpufreq/exynos-cpufreq.c:166:2: error: implicit declaration of function 'soc_is_exynos4210' [-Werror=implicit-function-declaration] drivers/cpufreq/exynos-cpufreq.c:168:2: error: implicit declaration of function 'soc_is_exynos4212' [-Werror=implicit-function-declaration] drivers/cpufreq/exynos-cpufreq.c:168:2: error: implicit declaration of function 'soc_is_exynos4412' [-Werror=implicit-function-declaration] drivers/cpufreq/exynos-cpufreq.c:170:2: error: implicit declaration of function 'soc_is_exynos5250' [-Werror=implicit-function-declaration] cc1: some warnings being treated as errors make[2]: *** [drivers/cpufreq/exynos-cpufreq.o] Error 1 make[2]: *** Waiting for unfinished jobs.... drivers/cpufreq/exynos4x12-cpufreq.c: In function 'exynos4x12_set_clkdiv': drivers/cpufreq/exynos4x12-cpufreq.c:118:2: error: implicit declaration of function 'soc_is_exynos4212' [-Werror=implicit-function-declaration] cc1: some warnings being treated as errors make[2]: *** [drivers/cpufreq/exynos4x12-cpufreq.o] Error 1 make[1]: *** [drivers/cpufreq] Error 2 This fixes above error with getting SoC information via of_machine_is_compatible() instead of soc_is_exynosXXXX(). Suggested-by: Tomasz Figa Signed-off-by: Jonghwan Choi [kgene.kim@samsung.com: fixed typo and modified as per Viresh's suggestion] [kgene.kim@samsung.com: Rafael agreed] Signed-off-by: Kukjin Kim --- drivers/cpufreq/exynos-cpufreq.c | 19 ++++++++++++++----- drivers/cpufreq/exynos-cpufreq.h | 8 ++++++++ drivers/cpufreq/exynos4x12-cpufreq.c | 11 ++++------- 3 files changed, 26 insertions(+), 12 deletions(-) diff --git a/drivers/cpufreq/exynos-cpufreq.c b/drivers/cpufreq/exynos-cpufreq.c index f99cfe24e7bc..e8a4a7ed38c1 100644 --- a/drivers/cpufreq/exynos-cpufreq.c +++ b/drivers/cpufreq/exynos-cpufreq.c @@ -17,6 +17,7 @@ #include #include #include +#include #include @@ -163,14 +164,22 @@ static int exynos_cpufreq_probe(struct platform_device *pdev) if (!exynos_info) return -ENOMEM; - if (soc_is_exynos4210()) + if (of_machine_is_compatible("samsung,exynos4210")) { + exynos_info->type = EXYNOS_SOC_4210; ret = exynos4210_cpufreq_init(exynos_info); - else if (soc_is_exynos4212() || soc_is_exynos4412()) + } else if (of_machine_is_compatible("samsung,exynos4212")) { + exynos_info->type = EXYNOS_SOC_4212; ret = exynos4x12_cpufreq_init(exynos_info); - else if (soc_is_exynos5250()) + } else if (of_machine_is_compatible("samsung,exynos4412")) { + exynos_info->type = EXYNOS_SOC_4412; + ret = exynos4x12_cpufreq_init(exynos_info); + } else if (of_machine_is_compatible("samsung,exynos5250")) { + exynos_info->type = EXYNOS_SOC_5250; ret = exynos5250_cpufreq_init(exynos_info); - else - return 0; + } else { + pr_err("%s: Unknown SoC type\n", __func__); + return -ENODEV; + } if (ret) goto err_vdd_arm; diff --git a/drivers/cpufreq/exynos-cpufreq.h b/drivers/cpufreq/exynos-cpufreq.h index 3ddade8a5125..f189547bb447 100644 --- a/drivers/cpufreq/exynos-cpufreq.h +++ b/drivers/cpufreq/exynos-cpufreq.h @@ -17,6 +17,13 @@ enum cpufreq_level_index { L20, }; +enum exynos_soc_type { + EXYNOS_SOC_4210, + EXYNOS_SOC_4212, + EXYNOS_SOC_4412, + EXYNOS_SOC_5250, +}; + #define APLL_FREQ(f, a0, a1, a2, a3, a4, a5, a6, a7, b0, b1, b2, m, p, s) \ { \ .freq = (f) * 1000, \ @@ -34,6 +41,7 @@ struct apll_freq { }; struct exynos_dvfs_info { + enum exynos_soc_type type; unsigned long mpll_freq_khz; unsigned int pll_safe_idx; struct clk *cpu_clk; diff --git a/drivers/cpufreq/exynos4x12-cpufreq.c b/drivers/cpufreq/exynos4x12-cpufreq.c index 466c76ad335b..63a3907ce578 100644 --- a/drivers/cpufreq/exynos4x12-cpufreq.c +++ b/drivers/cpufreq/exynos4x12-cpufreq.c @@ -100,7 +100,6 @@ static struct apll_freq apll_freq_4412[] = { static void exynos4x12_set_clkdiv(unsigned int div_index) { unsigned int tmp; - unsigned int stat_cpu1; /* Change Divider - CPU0 */ @@ -115,13 +114,11 @@ static void exynos4x12_set_clkdiv(unsigned int div_index) tmp = apll_freq_4x12[div_index].clk_div_cpu1; __raw_writel(tmp, EXYNOS4_CLKDIV_CPU1); - if (soc_is_exynos4212()) - stat_cpu1 = 0x11; - else - stat_cpu1 = 0x111; - while (__raw_readl(EXYNOS4_CLKDIV_STATCPU1) & stat_cpu1) + do { cpu_relax(); + tmp = __raw_readl(EXYNOS4_CLKDIV_STATCPU1); + } while (tmp != 0x0); } static void exynos4x12_set_apll(unsigned int index) @@ -184,7 +181,7 @@ int exynos4x12_cpufreq_init(struct exynos_dvfs_info *info) if (IS_ERR(mout_apll)) goto err_mout_apll; - if (soc_is_exynos4212()) + if (info->type == EXYNOS_SOC_4212) apll_freq_4x12 = apll_freq_4212; else apll_freq_4x12 = apll_freq_4412; From 5a3babfcd2354fb1063de2895cab0320fb2027ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Heiko=20St=C3=BCbner?= Date: Fri, 23 May 2014 22:58:53 +0200 Subject: [PATCH 84/87] clk: samsung: clk-s3c2410-dlck: do not use PNAME macro as it declares __initdata The originally used PNAME macro from the core samsung clock infrastructure declares the created array as initdata, creating section mismatch warnings in the dclk driver. Thus declare them directly, removing these warning. Reported-by: Olof Johansson Signed-off-by: Heiko Stuebner Signed-off-by: Olof Johansson --- drivers/clk/samsung/clk-s3c2410-dclk.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/clk/samsung/clk-s3c2410-dclk.c b/drivers/clk/samsung/clk-s3c2410-dclk.c index 8d8dff005c10..c1726f46eddd 100644 --- a/drivers/clk/samsung/clk-s3c2410-dclk.c +++ b/drivers/clk/samsung/clk-s3c2410-dclk.c @@ -135,26 +135,26 @@ struct s3c24xx_dclk { #define to_s3c24xx_dclk1(x) \ container_of(x, struct s3c24xx_dclk, dclk1_div_change_nb) -PNAME(dclk_s3c2410_p) = { "pclk", "uclk" }; -PNAME(clkout0_s3c2410_p) = { "mpll", "upll", "fclk", "hclk", "pclk", +static const char *dclk_s3c2410_p[] = { "pclk", "uclk" }; +static const char *clkout0_s3c2410_p[] = { "mpll", "upll", "fclk", "hclk", "pclk", "gate_dclk0" }; -PNAME(clkout1_s3c2410_p) = { "mpll", "upll", "fclk", "hclk", "pclk", +static const char *clkout1_s3c2410_p[] = { "mpll", "upll", "fclk", "hclk", "pclk", "gate_dclk1" }; -PNAME(clkout0_s3c2412_p) = { "mpll", "upll", "rtc_clkout", +static const char *clkout0_s3c2412_p[] = { "mpll", "upll", "rtc_clkout", "hclk", "pclk", "gate_dclk0" }; -PNAME(clkout1_s3c2412_p) = { "xti", "upll", "fclk", "hclk", "pclk", +static const char *clkout1_s3c2412_p) = { "xti", "upll", "fclk", "hclk", "pclk", "gate_dclk1" }; -PNAME(clkout0_s3c2440_p) = { "xti", "upll", "fclk", "hclk", "pclk", +static const char *clkout0_s3c2440_p[] = { "xti", "upll", "fclk", "hclk", "pclk", "gate_dclk0" }; -PNAME(clkout1_s3c2440_p) = { "mpll", "upll", "rtc_clkout", +static const char *clkout1_s3c2440_p[] = { "mpll", "upll", "rtc_clkout", "hclk", "pclk", "gate_dclk1" }; -PNAME(dclk_s3c2443_p) = { "pclk", "epll" }; -PNAME(clkout0_s3c2443_p) = { "xti", "epll", "armclk", "hclk", "pclk", +static const char *dclk_s3c2443_p[] = { "pclk", "epll" }; +static const char *clkout0_s3c2443_p[] = { "xti", "epll", "armclk", "hclk", "pclk", "gate_dclk0" }; -PNAME(clkout1_s3c2443_p) = { "dummy", "epll", "rtc_clkout", +static const char *clkout1_s3c2443_p[] = { "dummy", "epll", "rtc_clkout", "hclk", "pclk", "gate_dclk1" }; #define DCLKCON_DCLK_DIV_MASK 0xf From b33cdd283bd917d431469c29419c2cf2624bd683 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 26 May 2014 17:25:22 +0200 Subject: [PATCH 85/87] ARM: vexpress: refine dependencies for new code The versatile express changes for 3.16 introduced a number of build regressions for randconfig kernels by not tracking dependencies between the components right. This patch tries to rectify that: * the mach-vexpress code cannot link without the syscfg driver, which in turn needs MFD_VEXPRESS_SYSREG * various drivers call devm_regmap_init_vexpress_config(), which has to be exported so it can be used by loadable modules * the configuration bus uses OF DT helper functions that are not available to platforms disable CONFIG_OF * The sysreg driver exports GPIOs through gpiolib, which can be disabled on some platforms. * The clocksource code cannot be built on platforms that don't use modern timekeeping but rely on gettimeoffset. Signed-off-by: Arnd Bergmann --- arch/arm/mach-vexpress/Kconfig | 2 ++ drivers/bus/Kconfig | 1 + drivers/bus/vexpress-config.c | 2 +- drivers/clocksource/Kconfig | 2 +- drivers/mfd/Kconfig | 2 +- 5 files changed, 6 insertions(+), 3 deletions(-) diff --git a/arch/arm/mach-vexpress/Kconfig b/arch/arm/mach-vexpress/Kconfig index 657d52d0391f..b8ac752fd24b 100644 --- a/arch/arm/mach-vexpress/Kconfig +++ b/arch/arm/mach-vexpress/Kconfig @@ -18,6 +18,8 @@ config ARCH_VEXPRESS select POWER_SUPPLY select REGULATOR_FIXED_VOLTAGE if REGULATOR select VEXPRESS_CONFIG + select VEXPRESS_SYSCFG + select MFD_VEXPRESS_SYSREG help This option enables support for systems using Cortex processor based ARM core and logic (FPGA) tiles on the Versatile Express motherboard, diff --git a/drivers/bus/Kconfig b/drivers/bus/Kconfig index f24e79dd51bf..286342778884 100644 --- a/drivers/bus/Kconfig +++ b/drivers/bus/Kconfig @@ -46,6 +46,7 @@ config VEXPRESS_CONFIG bool "Versatile Express configuration bus" default y if ARCH_VEXPRESS depends on ARM || ARM64 + depends on OF select REGMAP help Platform configuration infrastructure for the ARM Ltd. diff --git a/drivers/bus/vexpress-config.c b/drivers/bus/vexpress-config.c index 27a07dfcd626..a64763b6b5fd 100644 --- a/drivers/bus/vexpress-config.c +++ b/drivers/bus/vexpress-config.c @@ -118,7 +118,7 @@ struct regmap *devm_regmap_init_vexpress_config(struct device *dev) return regmap; } - +EXPORT_SYMBOL_GPL(devm_regmap_init_vexpress_config); struct device *vexpress_config_bridge_register(struct device *parent, struct vexpress_config_bridge_ops *ops, void *context) diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index 2c27b02f0860..43f1acf0d1d2 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -194,7 +194,7 @@ config CLKSRC_QCOM config CLKSRC_VERSATILE bool "ARM Versatile (Express) reference platforms clock source" - depends on GENERIC_SCHED_CLOCK + depends on GENERIC_SCHED_CLOCK && !ARCH_USES_GETTIMEOFFSET select CLKSRC_OF default y if MFD_VEXPRESS_SYSREG help diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 490fd48a9541..f04ac62dd76b 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -1229,7 +1229,7 @@ endmenu config MFD_VEXPRESS_SYSREG bool "Versatile Express System Registers" - depends on VEXPRESS_CONFIG + depends on VEXPRESS_CONFIG && GPIOLIB default y select CLKSRC_MMIO select GPIO_GENERIC_PLATFORM From 708cec66429cf1ad56d0e849acc3367e8469b1af Mon Sep 17 00:00:00 2001 From: Olof Johansson Date: Mon, 26 May 2014 14:19:34 -0700 Subject: [PATCH 86/87] clk: samsung: fix build error "clk: samsung: clk-s3c2410-dlck: do not use PNAME macro as it declares __initdata" had a typo in it which caused build failure. Trivial fix. Signed-off-by: Olof Johansson --- drivers/clk/samsung/clk-s3c2410-dclk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/samsung/clk-s3c2410-dclk.c b/drivers/clk/samsung/clk-s3c2410-dclk.c index c1726f46eddd..0449cc0458ed 100644 --- a/drivers/clk/samsung/clk-s3c2410-dclk.c +++ b/drivers/clk/samsung/clk-s3c2410-dclk.c @@ -143,7 +143,7 @@ static const char *clkout1_s3c2410_p[] = { "mpll", "upll", "fclk", "hclk", "pclk static const char *clkout0_s3c2412_p[] = { "mpll", "upll", "rtc_clkout", "hclk", "pclk", "gate_dclk0" }; -static const char *clkout1_s3c2412_p) = { "xti", "upll", "fclk", "hclk", "pclk", +static const char *clkout1_s3c2412_p[] = { "xti", "upll", "fclk", "hclk", "pclk", "gate_dclk1" }; static const char *clkout0_s3c2440_p[] = { "xti", "upll", "fclk", "hclk", "pclk", From 08d38bebb4dcd6414944f8277ea5ea30010664fe Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Tue, 27 May 2014 23:26:35 +0100 Subject: [PATCH 87/87] ARM: kconfig: allow PCI support to be selected with ARCH_MULTIPLATFORM When targetting ARCH_MULTIPLATFORM, we may include support for SoCs with PCI-capable devices (e.g. mach-virt with virtio-pci). This patch allows PCI support to be selected for these SoCs by selecting CONFIG_MIGHT_HAVE_PCI when CONFIG_ARCH_MULTIPLATFORM=y and removes the individual selections from multi-platform enabled SoCs. Acked-by: Rob Herring Signed-off-by: Will Deacon Signed-off-by: Olof Johansson --- arch/arm/Kconfig | 1 + arch/arm/mach-bcm/Kconfig | 1 - arch/arm/mach-cns3xxx/Kconfig | 1 - arch/arm/mach-imx/Kconfig | 1 - arch/arm/mach-mvebu/Kconfig | 1 - arch/arm/mach-shmobile/Kconfig | 1 - arch/arm/mach-tegra/Kconfig | 1 - 7 files changed, 1 insertion(+), 6 deletions(-) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index db3c5414223e..860bea828ac4 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -314,6 +314,7 @@ config ARCH_MULTIPLATFORM select CLKSRC_OF select COMMON_CLK select GENERIC_CLOCKEVENTS + select MIGHT_HAVE_PCI select MULTI_IRQ_HANDLER select SPARSE_IRQ select USE_OF diff --git a/arch/arm/mach-bcm/Kconfig b/arch/arm/mach-bcm/Kconfig index b8cc9e8992f1..2113d92c668a 100644 --- a/arch/arm/mach-bcm/Kconfig +++ b/arch/arm/mach-bcm/Kconfig @@ -77,7 +77,6 @@ config ARCH_BCM_5301X select HAVE_ARM_TWD if SMP select ARM_GLOBAL_TIMER select CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK - select MIGHT_HAVE_PCI help Support for Broadcom BCM470X and BCM5301X SoCs with ARM CPU cores. diff --git a/arch/arm/mach-cns3xxx/Kconfig b/arch/arm/mach-cns3xxx/Kconfig index dce8decd5d46..66838f42037f 100644 --- a/arch/arm/mach-cns3xxx/Kconfig +++ b/arch/arm/mach-cns3xxx/Kconfig @@ -1,7 +1,6 @@ config ARCH_CNS3XXX bool "Cavium Networks CNS3XXX family" if ARCH_MULTI_V6 select ARM_GIC - select MIGHT_HAVE_PCI select PCI_DOMAINS if PCI help Support for Cavium Networks CNS3XXX platform. diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig index 5740296dc429..50bb546b893a 100644 --- a/arch/arm/mach-imx/Kconfig +++ b/arch/arm/mach-imx/Kconfig @@ -796,7 +796,6 @@ config SOC_IMX6Q select ARM_ERRATA_764369 if SMP select HAVE_ARM_SCU if SMP select HAVE_ARM_TWD if SMP - select MIGHT_HAVE_PCI select PCI_DOMAINS if PCI select PINCTRL_IMX6Q select SOC_IMX6 diff --git a/arch/arm/mach-mvebu/Kconfig b/arch/arm/mach-mvebu/Kconfig index bfc5af18e483..2052a90d9981 100644 --- a/arch/arm/mach-mvebu/Kconfig +++ b/arch/arm/mach-mvebu/Kconfig @@ -8,7 +8,6 @@ config ARCH_MVEBU select MVEBU_MBUS select ZONE_DMA if ARM_LPAE select ARCH_REQUIRE_GPIOLIB - select MIGHT_HAVE_PCI select PCI_QUIRKS if PCI if ARCH_MVEBU diff --git a/arch/arm/mach-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig index edb1a914deb3..62eaa42cb13a 100644 --- a/arch/arm/mach-shmobile/Kconfig +++ b/arch/arm/mach-shmobile/Kconfig @@ -8,7 +8,6 @@ config ARCH_SHMOBILE_MULTI select HAVE_ARM_SCU if SMP select HAVE_ARM_TWD if SMP select ARM_GIC - select MIGHT_HAVE_PCI select ARCH_DMA_ADDR_T_64BIT if ARM_LPAE select NO_IOPORT_MAP select PINCTRL diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig index 55b305d51669..e16999e5b735 100644 --- a/arch/arm/mach-tegra/Kconfig +++ b/arch/arm/mach-tegra/Kconfig @@ -7,7 +7,6 @@ config ARCH_TEGRA select CLKSRC_MMIO select HAVE_ARM_SCU if SMP select HAVE_ARM_TWD if SMP - select MIGHT_HAVE_PCI select PINCTRL select ARCH_HAS_RESET_CONTROLLER select RESET_CONTROLLER