From 26e0ee1c62a08ee7dd39e9c38f53b5bcfe8b70b7 Mon Sep 17 00:00:00 2001 From: Xing Zheng Date: Wed, 25 May 2016 16:51:56 +0800 Subject: clk: rockchip: add a dummy clock for the watchdog pclk on rk3399 Like rk3288, the pclk supplying the watchdog is controlled via the SGRF register area. Additionally the SGRF isn't even writable in every boot mode. But still the clock control is available and in the future someone might want to use it. Therefore define a simple clock for the time being so that the watchdog driver can read its rate. Signed-off-by: Xing Zheng Reviewed-by: Stephen Barber Signed-off-by: Heiko Stuebner --- drivers/clk/rockchip/clk-rk3399.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/clk/rockchip/clk-rk3399.c b/drivers/clk/rockchip/clk-rk3399.c index 291543f52caa..b6742fad3f8d 100644 --- a/drivers/clk/rockchip/clk-rk3399.c +++ b/drivers/clk/rockchip/clk-rk3399.c @@ -1498,6 +1498,7 @@ static void __init rk3399_clk_init(struct device_node *np) { struct rockchip_clk_provider *ctx; void __iomem *reg_base; + struct clk *clk; reg_base = of_iomap(np, 0); if (!reg_base) { @@ -1511,6 +1512,14 @@ static void __init rk3399_clk_init(struct device_node *np) return; } + /* Watchdog pclk is controlled by RK3399 SECURE_GRF_SOC_CON3[8]. */ + clk = clk_register_fixed_factor(NULL, "pclk_wdt", "pclk_alive", 0, 1, 1); + if (IS_ERR(clk)) + pr_warn("%s: could not register clock pclk_wdt: %ld\n", + __func__, PTR_ERR(clk)); + else + rockchip_clk_add_lookup(ctx, clk, PCLK_WDT); + rockchip_clk_register_plls(ctx, rk3399_pll_clks, ARRAY_SIZE(rk3399_pll_clks), -1); -- cgit v1.2.3 From 4c5773f9f5462dcb372857813918bbfe8c0cdcdd Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sat, 28 May 2016 11:54:12 +0200 Subject: dt-bindings: clock: Add license and reformat Exynos5410 clock IDs Add license and copyrights (file introduced in 2014) to header with Exynos5410 clock IDs. Additionally reformat it to improve readability. Signed-off-by: Krzysztof Kozlowski Acked-by: Stephen Boyd Reviewed-by: Javier Martinez Canillas Signed-off-by: Sylwester Nawrocki --- include/dt-bindings/clock/exynos5410.h | 54 ++++++++++++++++++++-------------- 1 file changed, 32 insertions(+), 22 deletions(-) diff --git a/include/dt-bindings/clock/exynos5410.h b/include/dt-bindings/clock/exynos5410.h index 9b180f032e2d..213f19e02870 100644 --- a/include/dt-bindings/clock/exynos5410.h +++ b/include/dt-bindings/clock/exynos5410.h @@ -1,33 +1,43 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * 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 for Exynos5421 clock controller. +*/ + #ifndef _DT_BINDINGS_CLOCK_EXYNOS_5410_H #define _DT_BINDINGS_CLOCK_EXYNOS_5410_H /* core clocks */ -#define CLK_FIN_PLL 1 -#define CLK_FOUT_APLL 2 -#define CLK_FOUT_CPLL 3 -#define CLK_FOUT_MPLL 4 -#define CLK_FOUT_BPLL 5 -#define CLK_FOUT_KPLL 6 +#define CLK_FIN_PLL 1 +#define CLK_FOUT_APLL 2 +#define CLK_FOUT_CPLL 3 +#define CLK_FOUT_MPLL 4 +#define CLK_FOUT_BPLL 5 +#define CLK_FOUT_KPLL 6 /* gate for special clocks (sclk) */ -#define CLK_SCLK_UART0 128 -#define CLK_SCLK_UART1 129 -#define CLK_SCLK_UART2 130 -#define CLK_SCLK_UART3 131 -#define CLK_SCLK_MMC0 132 -#define CLK_SCLK_MMC1 133 -#define CLK_SCLK_MMC2 134 +#define CLK_SCLK_UART0 128 +#define CLK_SCLK_UART1 129 +#define CLK_SCLK_UART2 130 +#define CLK_SCLK_UART3 131 +#define CLK_SCLK_MMC0 132 +#define CLK_SCLK_MMC1 133 +#define CLK_SCLK_MMC2 134 /* gate clocks */ -#define CLK_UART0 257 -#define CLK_UART1 258 -#define CLK_UART2 259 -#define CLK_UART3 260 -#define CLK_MCT 315 -#define CLK_MMC0 351 -#define CLK_MMC1 352 -#define CLK_MMC2 353 +#define CLK_UART0 257 +#define CLK_UART1 258 +#define CLK_UART2 259 +#define CLK_UART3 260 +#define CLK_MCT 315 +#define CLK_MMC0 351 +#define CLK_MMC1 352 +#define CLK_MMC2 353 -#define CLK_NR_CLKS 512 +#define CLK_NR_CLKS 512 #endif /* _DT_BINDINGS_CLOCK_EXYNOS_5410_H */ -- cgit v1.2.3 From 5cd3535a27a7cf8fc4070b499d66e419e7e72b61 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sat, 28 May 2016 11:54:13 +0200 Subject: dt-bindings: clock: Add PWM and USB clock IDs to Exynos5410 Add IDs for PWM and USB clocks to Exynos5410. Use the same number as for Exynos5420 just in case in future these drivers were merged. Signed-off-by: Krzysztof Kozlowski Acked-by: Stephen Boyd Reviewed-by: Javier Martinez Canillas Signed-off-by: Sylwester Nawrocki --- include/dt-bindings/clock/exynos5410.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/include/dt-bindings/clock/exynos5410.h b/include/dt-bindings/clock/exynos5410.h index 213f19e02870..34c8e96987a1 100644 --- a/include/dt-bindings/clock/exynos5410.h +++ b/include/dt-bindings/clock/exynos5410.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * Copyright (c) 2016 Krzysztof Kozlowski * * 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 @@ -27,16 +28,25 @@ #define CLK_SCLK_MMC0 132 #define CLK_SCLK_MMC1 133 #define CLK_SCLK_MMC2 134 +#define CLK_SCLK_USBD300 150 +#define CLK_SCLK_USBD301 151 +#define CLK_SCLK_USBPHY300 152 +#define CLK_SCLK_USBPHY301 153 +#define CLK_SCLK_PWM 155 /* gate clocks */ #define CLK_UART0 257 #define CLK_UART1 258 #define CLK_UART2 259 #define CLK_UART3 260 +#define CLK_PWM 279 #define CLK_MCT 315 #define CLK_MMC0 351 #define CLK_MMC1 352 #define CLK_MMC2 353 +#define CLK_USBH20 365 +#define CLK_USBD300 366 +#define CLK_USBD301 367 #define CLK_NR_CLKS 512 -- cgit v1.2.3 From ed1e1505db0c116affdfab01e650c44a9c459c65 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sat, 28 May 2016 11:54:29 +0200 Subject: dt-bindings: clock: Add I2C, HSI2C and RTC clock IDs to Exynos5410 Add IDs for I2C, USI (HSI2C) and RTC clocks to Exynos5410. Use the same number as for Exynos5420 just in case in future these drivers are merged. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Javier Martinez Canillas Signed-off-by: Sylwester Nawrocki --- include/dt-bindings/clock/exynos5410.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/include/dt-bindings/clock/exynos5410.h b/include/dt-bindings/clock/exynos5410.h index 34c8e96987a1..e94b7bbfd6af 100644 --- a/include/dt-bindings/clock/exynos5410.h +++ b/include/dt-bindings/clock/exynos5410.h @@ -38,9 +38,18 @@ #define CLK_UART0 257 #define CLK_UART1 258 #define CLK_UART2 259 +#define CLK_I2C0 261 +#define CLK_I2C1 262 +#define CLK_I2C2 263 +#define CLK_I2C3 264 +#define CLK_USI0 265 +#define CLK_USI1 266 +#define CLK_USI2 267 +#define CLK_USI3 268 #define CLK_UART3 260 #define CLK_PWM 279 #define CLK_MCT 315 +#define CLK_RTC 317 #define CLK_MMC0 351 #define CLK_MMC1 352 #define CLK_MMC2 353 -- cgit v1.2.3 From 109869f522852094393b829918b56327c0feb360 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 31 May 2016 20:39:00 +0200 Subject: dt-bindings: clock: Add TMU clock ID to Exynos5410 Add ID for TMU clock to Exynos5410. Use the same number as for Exynos5420 just in case in future these drivers were merged. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Javier Martinez Canillas Signed-off-by: Sylwester Nawrocki --- include/dt-bindings/clock/exynos5410.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/dt-bindings/clock/exynos5410.h b/include/dt-bindings/clock/exynos5410.h index e94b7bbfd6af..705b2aa84317 100644 --- a/include/dt-bindings/clock/exynos5410.h +++ b/include/dt-bindings/clock/exynos5410.h @@ -50,6 +50,7 @@ #define CLK_PWM 279 #define CLK_MCT 315 #define CLK_RTC 317 +#define CLK_TMU 318 #define CLK_MMC0 351 #define CLK_MMC1 352 #define CLK_MMC2 353 -- cgit v1.2.3 From 4528dd8ed477bf202bd33ee48d38d656672d37f8 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 1 Jun 2016 11:45:49 +0200 Subject: dt-bindings: clock: Add watchdog and SSS clock IDs to Exynos5410 Add IDs for watchdog and Security SubSystem to Exynos5410. Use the same number as for Exynos5420 just in case in future these drivers were merged. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Javier Martinez Canillas Signed-off-by: Sylwester Nawrocki --- include/dt-bindings/clock/exynos5410.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/dt-bindings/clock/exynos5410.h b/include/dt-bindings/clock/exynos5410.h index 705b2aa84317..85b467b3a207 100644 --- a/include/dt-bindings/clock/exynos5410.h +++ b/include/dt-bindings/clock/exynos5410.h @@ -49,6 +49,7 @@ #define CLK_UART3 260 #define CLK_PWM 279 #define CLK_MCT 315 +#define CLK_WDT 316 #define CLK_RTC 317 #define CLK_TMU 318 #define CLK_MMC0 351 @@ -57,6 +58,7 @@ #define CLK_USBH20 365 #define CLK_USBD300 366 #define CLK_USBD301 367 +#define CLK_SSS 471 #define CLK_NR_CLKS 512 -- cgit v1.2.3 From 9da752f0e37022e40de8f00891be958d351f4526 Mon Sep 17 00:00:00 2001 From: Alim Akhtar Date: Thu, 14 Apr 2016 10:12:52 +0530 Subject: clk: samsung: exynos7: Don't gate CMU_{CCORE, FSYS0} blocks clock This patch adds CLK_IS_CRITICAL flag to ACLK_CCORE_133 and ACLK_FSYS0_200 clocks. These clocks are critical for accessing CMU_CCORE and CMU_FSYS0 blocks registers. Let these clocks to be enabled all the time. Signed-off-by: Alim Akhtar Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk-exynos7.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/clk/samsung/clk-exynos7.c b/drivers/clk/samsung/clk-exynos7.c index ad68d463b12c..03a82da63910 100644 --- a/drivers/clk/samsung/clk-exynos7.c +++ b/drivers/clk/samsung/clk-exynos7.c @@ -146,7 +146,7 @@ static struct samsung_pll_rate_table pll1460x_24mhz_tbl[] __initdata = { static struct samsung_gate_clock topc_gate_clks[] __initdata = { GATE(ACLK_CCORE_133, "aclk_ccore_133", "dout_aclk_ccore_133", - ENABLE_ACLK_TOPC0, 4, 0, 0), + ENABLE_ACLK_TOPC0, 4, CLK_IS_CRITICAL, 0), GATE(ACLK_MSCL_532, "aclk_mscl_532", "dout_aclk_mscl_532", ENABLE_ACLK_TOPC1, 20, 0, 0), @@ -539,7 +539,8 @@ static struct samsung_gate_clock top1_gate_clks[] __initdata = { ENABLE_SCLK_TOP1_FSYS11, 12, CLK_SET_RATE_PARENT, 0), GATE(CLK_ACLK_FSYS0_200, "aclk_fsys0_200", "dout_aclk_fsys0_200", - ENABLE_ACLK_TOP13, 28, CLK_SET_RATE_PARENT, 0), + ENABLE_ACLK_TOP13, 28, CLK_SET_RATE_PARENT | + CLK_IS_CRITICAL, 0), GATE(CLK_ACLK_FSYS1_200, "aclk_fsys1_200", "dout_aclk_fsys1_200", ENABLE_ACLK_TOP13, 24, CLK_SET_RATE_PARENT, 0), -- cgit v1.2.3 From dfb86ade53a94963eafe0d78360616faa90cde3b Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Mon, 9 May 2016 19:32:31 +0200 Subject: clk: samsung: Remove useless check for return value of samsung_clk_init The samsung_clk_init() cannot return NULL. Either it returns allocated memory or it panics. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Javier Martinez Canillas Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk-exynos4.c | 2 -- drivers/clk/samsung/clk-exynos5250.c | 3 +-- drivers/clk/samsung/clk-exynos5420.c | 2 -- drivers/clk/samsung/clk-exynos5440.c | 2 -- drivers/clk/samsung/clk-s3c2410.c | 2 -- drivers/clk/samsung/clk-s3c2412.c | 2 -- drivers/clk/samsung/clk-s3c2443.c | 2 -- drivers/clk/samsung/clk-s3c64xx.c | 2 -- drivers/clk/samsung/clk-s5pv210.c | 2 -- 9 files changed, 1 insertion(+), 18 deletions(-) diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c index 7b3d0f975987..2f458233908b 100644 --- a/drivers/clk/samsung/clk-exynos4.c +++ b/drivers/clk/samsung/clk-exynos4.c @@ -1450,8 +1450,6 @@ static void __init exynos4_clk_init(struct device_node *np, panic("%s: failed to map registers\n", __func__); ctx = samsung_clk_init(np, reg_base, CLK_NR_CLKS); - if (!ctx) - panic("%s: unable to allocate context.\n", __func__); samsung_clk_of_register_fixed_ext(ctx, exynos4_fixed_rate_ext_clks, ARRAY_SIZE(exynos4_fixed_rate_ext_clks), diff --git a/drivers/clk/samsung/clk-exynos5250.c b/drivers/clk/samsung/clk-exynos5250.c index 837197db4ffb..d8621cf31786 100644 --- a/drivers/clk/samsung/clk-exynos5250.c +++ b/drivers/clk/samsung/clk-exynos5250.c @@ -805,8 +805,7 @@ static void __init exynos5250_clk_init(struct device_node *np) } ctx = samsung_clk_init(np, reg_base, CLK_NR_CLKS); - if (!ctx) - panic("%s: unable to allocate context.\n", __func__); + samsung_clk_of_register_fixed_ext(ctx, exynos5250_fixed_rate_ext_clks, ARRAY_SIZE(exynos5250_fixed_rate_ext_clks), ext_clk_match); diff --git a/drivers/clk/samsung/clk-exynos5420.c b/drivers/clk/samsung/clk-exynos5420.c index 92382cef9f90..770c0f007c6b 100644 --- a/drivers/clk/samsung/clk-exynos5420.c +++ b/drivers/clk/samsung/clk-exynos5420.c @@ -1356,8 +1356,6 @@ static void __init exynos5x_clk_init(struct device_node *np, exynos5x_soc = soc; ctx = samsung_clk_init(np, reg_base, CLK_NR_CLKS); - if (!ctx) - panic("%s: unable to allocate context.\n", __func__); samsung_clk_of_register_fixed_ext(ctx, exynos5x_fixed_rate_ext_clks, ARRAY_SIZE(exynos5x_fixed_rate_ext_clks), diff --git a/drivers/clk/samsung/clk-exynos5440.c b/drivers/clk/samsung/clk-exynos5440.c index c57cff1e1798..22c73d4a5ee3 100644 --- a/drivers/clk/samsung/clk-exynos5440.c +++ b/drivers/clk/samsung/clk-exynos5440.c @@ -125,8 +125,6 @@ static void __init exynos5440_clk_init(struct device_node *np) } ctx = samsung_clk_init(np, reg_base, CLK_NR_CLKS); - if (!ctx) - panic("%s: unable to allocate context.\n", __func__); samsung_clk_of_register_fixed_ext(ctx, exynos5440_fixed_rate_ext_clks, ARRAY_SIZE(exynos5440_fixed_rate_ext_clks), ext_clk_match); diff --git a/drivers/clk/samsung/clk-s3c2410.c b/drivers/clk/samsung/clk-s3c2410.c index d7b011c1fcf8..d7a1e772d95a 100644 --- a/drivers/clk/samsung/clk-s3c2410.c +++ b/drivers/clk/samsung/clk-s3c2410.c @@ -374,8 +374,6 @@ void __init s3c2410_common_clk_init(struct device_node *np, unsigned long xti_f, } ctx = samsung_clk_init(np, reg_base, NR_CLKS); - if (!ctx) - panic("%s: unable to allocate context.\n", __func__); /* Register external clocks only in non-dt cases */ if (!np) diff --git a/drivers/clk/samsung/clk-s3c2412.c b/drivers/clk/samsung/clk-s3c2412.c index effe3736ec6b..ec873ee15d37 100644 --- a/drivers/clk/samsung/clk-s3c2412.c +++ b/drivers/clk/samsung/clk-s3c2412.c @@ -265,8 +265,6 @@ void __init s3c2412_common_clk_init(struct device_node *np, unsigned long xti_f, } ctx = samsung_clk_init(np, reg_base, NR_CLKS); - if (!ctx) - panic("%s: unable to allocate context.\n", __func__); /* Register external clocks only in non-dt cases */ if (!np) diff --git a/drivers/clk/samsung/clk-s3c2443.c b/drivers/clk/samsung/clk-s3c2443.c index 37562783b25e..5e24a17e10e6 100644 --- a/drivers/clk/samsung/clk-s3c2443.c +++ b/drivers/clk/samsung/clk-s3c2443.c @@ -400,8 +400,6 @@ void __init s3c2443_common_clk_init(struct device_node *np, unsigned long xti_f, } ctx = samsung_clk_init(np, reg_base, NR_CLKS); - if (!ctx) - panic("%s: unable to allocate context.\n", __func__); /* Register external clocks only in non-dt cases */ if (!np) diff --git a/drivers/clk/samsung/clk-s3c64xx.c b/drivers/clk/samsung/clk-s3c64xx.c index 60aa775bd374..a48bd5f17330 100644 --- a/drivers/clk/samsung/clk-s3c64xx.c +++ b/drivers/clk/samsung/clk-s3c64xx.c @@ -471,8 +471,6 @@ void __init s3c64xx_clk_init(struct device_node *np, unsigned long xtal_f, } ctx = samsung_clk_init(np, reg_base, NR_CLKS); - if (!ctx) - panic("%s: unable to allocate context.\n", __func__); /* Register external clocks. */ if (!np) diff --git a/drivers/clk/samsung/clk-s5pv210.c b/drivers/clk/samsung/clk-s5pv210.c index 52302262045d..fd2725710a6f 100644 --- a/drivers/clk/samsung/clk-s5pv210.c +++ b/drivers/clk/samsung/clk-s5pv210.c @@ -784,8 +784,6 @@ static void __init __s5pv210_clk_init(struct device_node *np, struct samsung_clk_provider *ctx; ctx = samsung_clk_init(np, reg_base, NR_CLKS); - if (!ctx) - panic("%s: unable to allocate context.\n", __func__); samsung_clk_register_mux(ctx, early_mux_clks, ARRAY_SIZE(early_mux_clks)); -- cgit v1.2.3 From d8137e035f6f36002943f32a2aa809cfde74bbc2 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Mon, 16 May 2016 10:26:47 +0200 Subject: clk: samsung: clkout: Add support for Exynos5410 Add compatible for Exynos5410 so the PMU on this SoC would provide CLKOUT. Signed-off-by: Krzysztof Kozlowski Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk-exynos-clkout.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/clk/samsung/clk-exynos-clkout.c b/drivers/clk/samsung/clk-exynos-clkout.c index 7cd02ff37a1f..96fab6cfb202 100644 --- a/drivers/clk/samsung/clk-exynos-clkout.c +++ b/drivers/clk/samsung/clk-exynos-clkout.c @@ -151,6 +151,8 @@ static void __init exynos5_clkout_init(struct device_node *node) } CLK_OF_DECLARE(exynos5250_clkout, "samsung,exynos5250-pmu", exynos5_clkout_init); +CLK_OF_DECLARE(exynos5410_clkout, "samsung,exynos5410-pmu", + exynos5_clkout_init); CLK_OF_DECLARE(exynos5420_clkout, "samsung,exynos5420-pmu", exynos5_clkout_init); CLK_OF_DECLARE(exynos5433_clkout, "samsung,exynos5433-pmu", -- cgit v1.2.3 From 9f92c0bace11a84c57cdd62d96de8113d1aba89f Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 11 May 2016 14:01:57 +0200 Subject: clk: samsung: Constify clock init data with clock arrays samsung_cmu_register_one() can accept pointer to const initialization data: struct samsung_cmu_info. The members of the latter can also be pointers to const data. Signed-off-by: Krzysztof Kozlowski Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk.c | 2 +- drivers/clk/samsung/clk.h | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/clk/samsung/clk.c b/drivers/clk/samsung/clk.c index f38a6c49f744..e4d14589cc4a 100644 --- a/drivers/clk/samsung/clk.c +++ b/drivers/clk/samsung/clk.c @@ -381,7 +381,7 @@ static void samsung_clk_sleep_init(void __iomem *reg_base, */ struct samsung_clk_provider * __init samsung_cmu_register_one( struct device_node *np, - struct samsung_cmu_info *cmu) + const struct samsung_cmu_info *cmu) { void __iomem *reg_base; struct samsung_clk_provider *ctx; diff --git a/drivers/clk/samsung/clk.h b/drivers/clk/samsung/clk.h index aa872d2c5105..61db98dd01a2 100644 --- a/drivers/clk/samsung/clk.h +++ b/drivers/clk/samsung/clk.h @@ -330,28 +330,28 @@ struct samsung_clock_reg_cache { struct samsung_cmu_info { /* list of pll clocks and respective count */ - struct samsung_pll_clock *pll_clks; + const struct samsung_pll_clock *pll_clks; unsigned int nr_pll_clks; /* list of mux clocks and respective count */ - struct samsung_mux_clock *mux_clks; + const struct samsung_mux_clock *mux_clks; unsigned int nr_mux_clks; /* list of div clocks and respective count */ - struct samsung_div_clock *div_clks; + const struct samsung_div_clock *div_clks; unsigned int nr_div_clks; /* list of gate clocks and respective count */ - struct samsung_gate_clock *gate_clks; + const struct samsung_gate_clock *gate_clks; unsigned int nr_gate_clks; /* list of fixed clocks and respective count */ - struct samsung_fixed_rate_clock *fixed_clks; + const struct samsung_fixed_rate_clock *fixed_clks; unsigned int nr_fixed_clks; /* list of fixed factor clocks and respective count */ - struct samsung_fixed_factor_clock *fixed_factor_clks; + const struct samsung_fixed_factor_clock *fixed_factor_clks; unsigned int nr_fixed_factor_clks; /* total number of clocks with IDs assigned*/ unsigned int nr_clk_ids; /* list and number of clocks registers */ - unsigned long *clk_regs; + const unsigned long *clk_regs; unsigned int nr_clk_regs; }; @@ -395,7 +395,7 @@ extern void __init samsung_clk_register_pll(struct samsung_clk_provider *ctx, extern struct samsung_clk_provider __init *samsung_cmu_register_one( struct device_node *, - struct samsung_cmu_info *); + const struct samsung_cmu_info *); extern unsigned long _get_rate(const char *clk_name); -- cgit v1.2.3 From b3a96eed8e84780d300b79b58047ea277ba358b7 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 11 May 2016 14:01:58 +0200 Subject: clk: samsung: exynos3250: Move platform driver and of_device_id to init section The platform_driver and of_device_id structs can be moved to init section because they are referenced only from subsys_initcall-level function. Signed-off-by: Krzysztof Kozlowski Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk-exynos3250.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/clk/samsung/clk-exynos3250.c b/drivers/clk/samsung/clk-exynos3250.c index 16575ee874cb..e26b04fea33b 100644 --- a/drivers/clk/samsung/clk-exynos3250.c +++ b/drivers/clk/samsung/clk-exynos3250.c @@ -1079,12 +1079,12 @@ static int __init exynos3250_cmu_isp_probe(struct platform_device *pdev) return 0; } -static const struct of_device_id exynos3250_cmu_isp_of_match[] = { +static const struct of_device_id exynos3250_cmu_isp_of_match[] __initconst = { { .compatible = "samsung,exynos3250-cmu-isp", }, { /* sentinel */ } }; -static struct platform_driver exynos3250_cmu_isp_driver = { +static struct platform_driver exynos3250_cmu_isp_driver __initdata = { .driver = { .name = "exynos3250-cmu-isp", .of_match_table = exynos3250_cmu_isp_of_match, -- cgit v1.2.3 From 0a7d82e6ee75db55b99096080ff4f12ac9a7aec3 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 11 May 2016 14:01:59 +0200 Subject: clk: samsung: exynos3250: Constify all clock initializers All of initialization data can be made const. Signed-off-by: Krzysztof Kozlowski Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk-exynos3250.c | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/drivers/clk/samsung/clk-exynos3250.c b/drivers/clk/samsung/clk-exynos3250.c index e26b04fea33b..057c3f0d0e35 100644 --- a/drivers/clk/samsung/clk-exynos3250.c +++ b/drivers/clk/samsung/clk-exynos3250.c @@ -103,7 +103,7 @@ #define PWR_CTRL1_USE_CORE1_WFI (1 << 1) #define PWR_CTRL1_USE_CORE0_WFI (1 << 0) -static unsigned long exynos3250_cmu_clk_regs[] __initdata = { +static const unsigned long exynos3250_cmu_clk_regs[] __initconst = { SRC_LEFTBUS, DIV_LEFTBUS, GATE_IP_LEFTBUS, @@ -226,7 +226,7 @@ PNAME(group_sclk_fimd0_p) = { "xxti", "xusbxti", PNAME(mout_mfc_p) = { "mout_mfc_0", "mout_mfc_1" }; PNAME(mout_g3d_p) = { "mout_g3d_0", "mout_g3d_1" }; -static struct samsung_fixed_factor_clock fixed_factor_clks[] __initdata = { +static const struct samsung_fixed_factor_clock fixed_factor_clks[] __initconst = { FFACTOR(0, "sclk_mpll_1600", "mout_mpll", 1, 1, 0), FFACTOR(0, "sclk_mpll_mif", "mout_mpll", 1, 2, 0), FFACTOR(0, "sclk_bpll", "fout_bpll", 1, 2, 0), @@ -237,7 +237,7 @@ static struct samsung_fixed_factor_clock fixed_factor_clks[] __initdata = { FFACTOR(CLK_FIN_PLL, "fin_pll", "xusbxti", 1, 1, 0), }; -static struct samsung_mux_clock mux_clks[] __initdata = { +static const struct samsung_mux_clock mux_clks[] __initconst = { /* * NOTE: Following table is sorted by register address in ascending * order and then bitfield shift in descending order, as it is done @@ -326,7 +326,7 @@ static struct samsung_mux_clock mux_clks[] __initdata = { CLK_SET_RATE_PARENT, 0), }; -static struct samsung_div_clock div_clks[] __initdata = { +static const struct samsung_div_clock div_clks[] __initconst = { /* * NOTE: Following table is sorted by register address in ascending * order and then bitfield shift in descending order, as it is done @@ -429,7 +429,7 @@ static struct samsung_div_clock div_clks[] __initdata = { DIV(CLK_DIV_COPY, "div_copy", "mout_hpm", DIV_CPU1, 0, 3), }; -static struct samsung_gate_clock gate_clks[] __initdata = { +static const struct samsung_gate_clock gate_clks[] __initconst = { /* * NOTE: Following table is sorted by register address in ascending * order and then bitfield shift in descending order, as it is done @@ -669,7 +669,7 @@ static struct samsung_gate_clock gate_clks[] __initdata = { }; /* APLL & MPLL & BPLL & UPLL */ -static struct samsung_pll_rate_table exynos3250_pll_rates[] = { +static const struct samsung_pll_rate_table exynos3250_pll_rates[] = { PLL_35XX_RATE(1200000000, 400, 4, 1), PLL_35XX_RATE(1100000000, 275, 3, 1), PLL_35XX_RATE(1066000000, 533, 6, 1), @@ -691,7 +691,7 @@ static struct samsung_pll_rate_table exynos3250_pll_rates[] = { }; /* EPLL */ -static struct samsung_pll_rate_table exynos3250_epll_rates[] = { +static const struct samsung_pll_rate_table exynos3250_epll_rates[] = { PLL_36XX_RATE(800000000, 200, 3, 1, 0), PLL_36XX_RATE(288000000, 96, 2, 2, 0), PLL_36XX_RATE(192000000, 128, 2, 3, 0), @@ -710,7 +710,7 @@ static struct samsung_pll_rate_table exynos3250_epll_rates[] = { }; /* VPLL */ -static struct samsung_pll_rate_table exynos3250_vpll_rates[] = { +static const struct samsung_pll_rate_table exynos3250_vpll_rates[] __initconst = { PLL_36XX_RATE(600000000, 100, 2, 1, 0), PLL_36XX_RATE(533000000, 266, 3, 2, 32768), PLL_36XX_RATE(519230987, 173, 2, 2, 5046), @@ -740,7 +740,7 @@ static struct samsung_pll_rate_table exynos3250_vpll_rates[] = { { /* sentinel */ } }; -static struct samsung_pll_clock exynos3250_plls[] __initdata = { +static const struct samsung_pll_clock exynos3250_plls[] __initconst = { PLL(pll_35xx, CLK_FOUT_APLL, "fout_apll", "fin_pll", APLL_LOCK, APLL_CON0, exynos3250_pll_rates), PLL(pll_35xx, CLK_FOUT_MPLL, "fout_mpll", "fin_pll", @@ -772,7 +772,7 @@ static void __init exynos3_core_down_clock(void __iomem *reg_base) __raw_writel(0x0, reg_base + PWR_CTRL2); } -static struct samsung_cmu_info cmu_info __initdata = { +static const struct samsung_cmu_info cmu_info __initconst = { .pll_clks = exynos3250_plls, .nr_pll_clks = ARRAY_SIZE(exynos3250_plls), .mux_clks = mux_clks, @@ -848,7 +848,7 @@ CLK_OF_DECLARE(exynos3250_cmu, "samsung,exynos3250-cmu", exynos3250_cmu_init); #define EPLL_CON2 0x111c #define SRC_EPLL 0x1120 -static unsigned long exynos3250_cmu_dmc_clk_regs[] __initdata = { +static const unsigned long exynos3250_cmu_dmc_clk_regs[] __initconst = { BPLL_LOCK, BPLL_CON0, BPLL_CON1, @@ -874,7 +874,7 @@ PNAME(mout_bpll_p) = { "fin_pll", "fout_bpll", }; PNAME(mout_mpll_mif_p) = { "fin_pll", "sclk_mpll_mif", }; PNAME(mout_dphy_p) = { "mout_mpll_mif", "mout_bpll", }; -static struct samsung_mux_clock dmc_mux_clks[] __initdata = { +static const struct samsung_mux_clock dmc_mux_clks[] __initconst = { /* * NOTE: Following table is sorted by register address in ascending * order and then bitfield shift in descending order, as it is done @@ -893,7 +893,7 @@ static struct samsung_mux_clock dmc_mux_clks[] __initdata = { MUX(CLK_MOUT_EPLL, "mout_epll", mout_epll_p, SRC_EPLL, 4, 1), }; -static struct samsung_div_clock dmc_div_clks[] __initdata = { +static const struct samsung_div_clock dmc_div_clks[] __initconst = { /* * NOTE: Following table is sorted by register address in ascending * order and then bitfield shift in descending order, as it is done @@ -910,14 +910,14 @@ static struct samsung_div_clock dmc_div_clks[] __initdata = { DIV(CLK_DIV_DMCD, "div_dmcd", "div_dmc", DIV_DMC1, 11, 3), }; -static struct samsung_pll_clock exynos3250_dmc_plls[] __initdata = { +static const struct samsung_pll_clock exynos3250_dmc_plls[] __initconst = { PLL(pll_35xx, CLK_FOUT_BPLL, "fout_bpll", "fin_pll", BPLL_LOCK, BPLL_CON0, exynos3250_pll_rates), PLL(pll_36xx, CLK_FOUT_EPLL, "fout_epll", "fin_pll", EPLL_LOCK, EPLL_CON0, exynos3250_epll_rates), }; -static struct samsung_cmu_info dmc_cmu_info __initdata = { +static const struct samsung_cmu_info dmc_cmu_info __initconst = { .pll_clks = exynos3250_dmc_plls, .nr_pll_clks = ARRAY_SIZE(exynos3250_dmc_plls), .mux_clks = dmc_mux_clks, @@ -947,7 +947,7 @@ CLK_OF_DECLARE(exynos3250_cmu_dmc, "samsung,exynos3250-cmu-dmc", #define GATE_IP_ISP1 0x804 #define GATE_SCLK_ISP 0x900 -static struct samsung_div_clock isp_div_clks[] __initdata = { +static const struct samsung_div_clock isp_div_clks[] __initconst = { /* * NOTE: Following table is sorted by register address in ascending * order and then bitfield shift in descending order, as it is done @@ -967,7 +967,7 @@ static struct samsung_div_clock isp_div_clks[] __initdata = { DIV(CLK_DIV_MPWM, "div_mpwm", "div_isp1", DIV_ISP1, 0, 3), }; -static struct samsung_gate_clock isp_gate_clks[] __initdata = { +static const struct samsung_gate_clock isp_gate_clks[] __initconst = { /* * NOTE: Following table is sorted by register address in ascending * order and then bitfield shift in descending order, as it is done @@ -1063,7 +1063,7 @@ static struct samsung_gate_clock isp_gate_clks[] __initdata = { GATE_SCLK_ISP, 0, CLK_IGNORE_UNUSED, 0), }; -static struct samsung_cmu_info isp_cmu_info __initdata = { +static const struct samsung_cmu_info isp_cmu_info __initconst = { .div_clks = isp_div_clks, .nr_div_clks = ARRAY_SIZE(isp_div_clks), .gate_clks = isp_gate_clks, -- cgit v1.2.3 From 8f3ac36de17ab056f43b509926ee81a09adae99b Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 11 May 2016 14:02:00 +0200 Subject: clk: samsung: exynos4: Move local function to init section The local exynos4_get_xom() function is referenced only from other init-level functions. Signed-off-by: Krzysztof Kozlowski Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk-exynos4.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c index 2f458233908b..5cac5b7892d7 100644 --- a/drivers/clk/samsung/clk-exynos4.c +++ b/drivers/clk/samsung/clk-exynos4.c @@ -1211,7 +1211,7 @@ static struct samsung_clock_alias exynos4x12_aliases[] __initdata = { * controller is first remapped and the value of XOM[0] bit is read to * determine the parent clock. */ -static unsigned long exynos4_get_xom(void) +static unsigned long __init exynos4_get_xom(void) { unsigned long xom = 0; void __iomem *chipid_base; -- cgit v1.2.3 From d0e4ca56958cea68dd9493a84c77a713e172da5c Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 11 May 2016 14:02:01 +0200 Subject: clk: samsung: exynos4: Constify all clock initializers All of initialization data can be made const. Signed-off-by: Krzysztof Kozlowski Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk-exynos4.c | 56 +++++++++++++++++++-------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c index 5cac5b7892d7..13eaf4cb0dbc 100644 --- a/drivers/clk/samsung/clk-exynos4.c +++ b/drivers/clk/samsung/clk-exynos4.c @@ -169,7 +169,7 @@ static struct samsung_clk_reg_dump *exynos4_save_pll; * list of controller registers to be saved and restored during a * suspend/resume cycle. */ -static unsigned long exynos4210_clk_save[] __initdata = { +static const unsigned long exynos4210_clk_save[] __initconst = { E4210_SRC_IMAGE, E4210_SRC_LCD1, E4210_SRC_MASK_LCD1, @@ -181,7 +181,7 @@ static unsigned long exynos4210_clk_save[] __initdata = { PWR_CTRL1, }; -static unsigned long exynos4x12_clk_save[] __initdata = { +static const unsigned long exynos4x12_clk_save[] __initconst = { E4X12_GATE_IP_IMAGE, E4X12_GATE_IP_PERIR, E4X12_SRC_CAM1, @@ -192,7 +192,7 @@ static unsigned long exynos4x12_clk_save[] __initdata = { E4X12_PWR_CTRL2, }; -static unsigned long exynos4_clk_pll_regs[] __initdata = { +static const unsigned long exynos4_clk_pll_regs[] __initconst = { EPLL_LOCK, VPLL_LOCK, EPLL_CON0, @@ -203,7 +203,7 @@ static unsigned long exynos4_clk_pll_regs[] __initdata = { VPLL_CON2, }; -static unsigned long exynos4_clk_regs[] __initdata = { +static const unsigned long exynos4_clk_regs[] __initconst = { SRC_LEFTBUS, DIV_LEFTBUS, GATE_IP_LEFTBUS, @@ -505,28 +505,28 @@ static struct samsung_fixed_rate_clock exynos4_fixed_rate_ext_clks[] __initdata }; /* fixed rate clocks generated inside the soc */ -static struct samsung_fixed_rate_clock exynos4_fixed_rate_clks[] __initdata = { +static const struct samsung_fixed_rate_clock exynos4_fixed_rate_clks[] __initconst = { FRATE(0, "sclk_hdmi24m", NULL, 0, 24000000), FRATE(CLK_SCLK_HDMIPHY, "sclk_hdmiphy", "hdmi", 0, 27000000), FRATE(0, "sclk_usbphy0", NULL, 0, 48000000), }; -static struct samsung_fixed_rate_clock exynos4210_fixed_rate_clks[] __initdata = { +static const struct samsung_fixed_rate_clock exynos4210_fixed_rate_clks[] __initconst = { FRATE(0, "sclk_usbphy1", NULL, 0, 48000000), }; -static struct samsung_fixed_factor_clock exynos4_fixed_factor_clks[] __initdata = { +static const struct samsung_fixed_factor_clock exynos4_fixed_factor_clks[] __initconst = { FFACTOR(0, "sclk_apll_div_2", "sclk_apll", 1, 2, 0), FFACTOR(0, "fout_mpll_div_2", "fout_mpll", 1, 2, 0), FFACTOR(0, "fout_apll_div_2", "fout_apll", 1, 2, 0), FFACTOR(0, "arm_clk_div_2", "div_core2", 1, 2, 0), }; -static struct samsung_fixed_factor_clock exynos4210_fixed_factor_clks[] __initdata = { +static const struct samsung_fixed_factor_clock exynos4210_fixed_factor_clks[] __initconst = { FFACTOR(0, "sclk_mpll_div_2", "sclk_mpll", 1, 2, 0), }; -static struct samsung_fixed_factor_clock exynos4x12_fixed_factor_clks[] __initdata = { +static const struct samsung_fixed_factor_clock exynos4x12_fixed_factor_clks[] __initconst = { FFACTOR(0, "sclk_mpll_user_l_div_2", "mout_mpll_user_l", 1, 2, 0), FFACTOR(0, "sclk_mpll_user_r_div_2", "mout_mpll_user_r", 1, 2, 0), FFACTOR(0, "sclk_mpll_user_t_div_2", "mout_mpll_user_t", 1, 2, 0), @@ -534,7 +534,7 @@ static struct samsung_fixed_factor_clock exynos4x12_fixed_factor_clks[] __initda }; /* list of mux clocks supported in all exynos4 soc's */ -static struct samsung_mux_clock exynos4_mux_clks[] __initdata = { +static const struct samsung_mux_clock exynos4_mux_clks[] __initconst = { MUX_FA(CLK_MOUT_APLL, "mout_apll", mout_apll_p, SRC_CPU, 0, 1, CLK_SET_RATE_PARENT | CLK_RECALC_NEW_RATES, 0, "mout_apll"), @@ -555,11 +555,11 @@ static struct samsung_mux_clock exynos4_mux_clks[] __initdata = { }; /* list of mux clocks supported in exynos4210 soc */ -static struct samsung_mux_clock exynos4210_mux_early[] __initdata = { +static const struct samsung_mux_clock exynos4210_mux_early[] __initconst = { MUX(0, "mout_vpllsrc", mout_vpllsrc_p, SRC_TOP1, 0, 1), }; -static struct samsung_mux_clock exynos4210_mux_clks[] __initdata = { +static const struct samsung_mux_clock exynos4210_mux_clks[] __initconst = { MUX(0, "mout_gdl", sclk_ampll_p4210, SRC_LEFTBUS, 0, 1), MUX(0, "mout_clkout_leftbus", clkout_left_p4210, CLKOUT_CMU_LEFTBUS, 0, 5), @@ -622,7 +622,7 @@ static struct samsung_mux_clock exynos4210_mux_clks[] __initdata = { }; /* list of mux clocks supported in exynos4x12 soc */ -static struct samsung_mux_clock exynos4x12_mux_clks[] __initdata = { +static const struct samsung_mux_clock exynos4x12_mux_clks[] __initconst = { MUX(0, "mout_mpll_user_l", mout_mpll_p, SRC_LEFTBUS, 4, 1), MUX(0, "mout_gdl", mout_gdl_p4x12, SRC_LEFTBUS, 0, 1), MUX(0, "mout_clkout_leftbus", clkout_left_p4x12, @@ -705,7 +705,7 @@ static struct samsung_mux_clock exynos4x12_mux_clks[] __initdata = { }; /* list of divider clocks supported in all exynos4 soc's */ -static struct samsung_div_clock exynos4_div_clks[] __initdata = { +static const struct samsung_div_clock exynos4_div_clks[] __initconst = { DIV(CLK_DIV_GDL, "div_gdl", "mout_gdl", DIV_LEFTBUS, 0, 3), DIV(0, "div_gpl", "div_gdl", DIV_LEFTBUS, 4, 3), DIV(0, "div_clkout_leftbus", "mout_clkout_leftbus", @@ -795,7 +795,7 @@ static struct samsung_div_clock exynos4_div_clks[] __initdata = { }; /* list of divider clocks supported in exynos4210 soc */ -static struct samsung_div_clock exynos4210_div_clks[] __initdata = { +static const struct samsung_div_clock exynos4210_div_clks[] __initconst = { DIV(CLK_ACLK200, "aclk200", "mout_aclk200", DIV_TOP, 0, 3), DIV(CLK_SCLK_FIMG2D, "sclk_fimg2d", "mout_g2d", DIV_IMAGE, 0, 4), DIV(0, "div_fimd1", "mout_fimd1", E4210_DIV_LCD1, 0, 4), @@ -806,7 +806,7 @@ static struct samsung_div_clock exynos4210_div_clks[] __initdata = { }; /* list of divider clocks supported in exynos4x12 soc */ -static struct samsung_div_clock exynos4x12_div_clks[] __initdata = { +static const struct samsung_div_clock exynos4x12_div_clks[] __initconst = { DIV(0, "div_mdnie0", "mout_mdnie0", DIV_LCD0, 4, 4), DIV(0, "div_mdnie_pwm0", "mout_mdnie_pwm0", DIV_LCD0, 8, 4), DIV(0, "div_mdnie_pwm_pre0", "div_mdnie_pwm0", DIV_LCD0, 12, 4), @@ -837,7 +837,7 @@ static struct samsung_div_clock exynos4x12_div_clks[] __initdata = { }; /* list of gate clocks supported in all exynos4 soc's */ -static struct samsung_gate_clock exynos4_gate_clks[] __initdata = { +static const struct samsung_gate_clock exynos4_gate_clks[] __initconst = { /* * After all Exynos4 based platforms are migrated to use device tree, * the device name and clock alias names specified below for some @@ -1043,7 +1043,7 @@ static struct samsung_gate_clock exynos4_gate_clks[] __initdata = { }; /* list of gate clocks supported in exynos4210 soc */ -static struct samsung_gate_clock exynos4210_gate_clks[] __initdata = { +static const struct samsung_gate_clock exynos4210_gate_clks[] __initconst = { GATE(CLK_TVENC, "tvenc", "aclk160", GATE_IP_TV, 2, 0, 0), GATE(CLK_G2D, "g2d", "aclk200", E4210_GATE_IP_IMAGE, 0, 0, 0), GATE(CLK_ROTATOR, "rotator", "aclk200", E4210_GATE_IP_IMAGE, 1, 0, 0), @@ -1090,7 +1090,7 @@ static struct samsung_gate_clock exynos4210_gate_clks[] __initdata = { }; /* list of gate clocks supported in exynos4x12 soc */ -static struct samsung_gate_clock exynos4x12_gate_clks[] __initdata = { +static const struct samsung_gate_clock exynos4x12_gate_clks[] __initconst = { GATE(CLK_AUDSS, "audss", "sclk_epll", E4X12_GATE_IP_MAUDIO, 0, 0, 0), GATE(CLK_MDNIE0, "mdnie0", "aclk160", GATE_IP_LCD0, 2, 0, 0), GATE(CLK_ROTATOR, "rotator", "aclk200", E4X12_GATE_IP_IMAGE, 1, 0, 0), @@ -1190,17 +1190,17 @@ static struct samsung_gate_clock exynos4x12_gate_clks[] __initdata = { 0), }; -static struct samsung_clock_alias exynos4_aliases[] __initdata = { +static const struct samsung_clock_alias exynos4_aliases[] __initconst = { ALIAS(CLK_MOUT_CORE, NULL, "moutcore"), ALIAS(CLK_ARM_CLK, NULL, "armclk"), ALIAS(CLK_SCLK_APLL, NULL, "mout_apll"), }; -static struct samsung_clock_alias exynos4210_aliases[] __initdata = { +static const struct samsung_clock_alias exynos4210_aliases[] __initconst = { ALIAS(CLK_SCLK_MPLL, NULL, "mout_mpll"), }; -static struct samsung_clock_alias exynos4x12_aliases[] __initdata = { +static const struct samsung_clock_alias exynos4x12_aliases[] __initconst = { ALIAS(CLK_MOUT_MPLL_USER_C, NULL, "mout_mpll"), }; @@ -1264,7 +1264,7 @@ static const struct of_device_id ext_clk_match[] __initconst = { }; /* PLLs PMS values */ -static struct samsung_pll_rate_table exynos4210_apll_rates[] __initdata = { +static const struct samsung_pll_rate_table exynos4210_apll_rates[] __initconst = { PLL_45XX_RATE(1200000000, 150, 3, 1, 28), PLL_45XX_RATE(1000000000, 250, 6, 1, 28), PLL_45XX_RATE( 800000000, 200, 6, 1, 28), @@ -1277,7 +1277,7 @@ static struct samsung_pll_rate_table exynos4210_apll_rates[] __initdata = { { /* sentinel */ } }; -static struct samsung_pll_rate_table exynos4210_epll_rates[] __initdata = { +static const struct samsung_pll_rate_table exynos4210_epll_rates[] __initconst = { PLL_4600_RATE(192000000, 48, 3, 1, 0, 0), PLL_4600_RATE(180633605, 45, 3, 1, 10381, 0), PLL_4600_RATE(180000000, 45, 3, 1, 0, 0), @@ -1288,7 +1288,7 @@ static struct samsung_pll_rate_table exynos4210_epll_rates[] __initdata = { { /* sentinel */ } }; -static struct samsung_pll_rate_table exynos4210_vpll_rates[] __initdata = { +static const struct samsung_pll_rate_table exynos4210_vpll_rates[] __initconst = { PLL_4650_RATE(360000000, 44, 3, 0, 1024, 0, 14, 0), PLL_4650_RATE(324000000, 53, 2, 1, 1024, 1, 1, 1), PLL_4650_RATE(259617187, 63, 3, 1, 1950, 0, 20, 1), @@ -1297,7 +1297,7 @@ static struct samsung_pll_rate_table exynos4210_vpll_rates[] __initdata = { { /* sentinel */ } }; -static struct samsung_pll_rate_table exynos4x12_apll_rates[] __initdata = { +static const struct samsung_pll_rate_table exynos4x12_apll_rates[] __initconst = { PLL_35XX_RATE(1500000000, 250, 4, 0), PLL_35XX_RATE(1400000000, 175, 3, 0), PLL_35XX_RATE(1300000000, 325, 6, 0), @@ -1315,7 +1315,7 @@ static struct samsung_pll_rate_table exynos4x12_apll_rates[] __initdata = { { /* sentinel */ } }; -static struct samsung_pll_rate_table exynos4x12_epll_rates[] __initdata = { +static const struct samsung_pll_rate_table exynos4x12_epll_rates[] __initconst = { PLL_36XX_RATE(192000000, 48, 3, 1, 0), PLL_36XX_RATE(180633605, 45, 3, 1, 10381), PLL_36XX_RATE(180000000, 45, 3, 1, 0), @@ -1326,7 +1326,7 @@ static struct samsung_pll_rate_table exynos4x12_epll_rates[] __initdata = { { /* sentinel */ } }; -static struct samsung_pll_rate_table exynos4x12_vpll_rates[] __initdata = { +static const struct samsung_pll_rate_table exynos4x12_vpll_rates[] __initconst = { PLL_36XX_RATE(533000000, 133, 3, 1, 16384), PLL_36XX_RATE(440000000, 110, 3, 1, 0), PLL_36XX_RATE(350000000, 175, 3, 2, 0), -- cgit v1.2.3 From ab7cc66dfa8e35e84a90ddfbb54f9bfadfbc2817 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 11 May 2016 14:02:02 +0200 Subject: clk: samsung: exynos4415: Constify all clock initializers All of initialization data can be made const. Signed-off-by: Krzysztof Kozlowski Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk-exynos4415.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/drivers/clk/samsung/clk-exynos4415.c b/drivers/clk/samsung/clk-exynos4415.c index 86ee06b226bd..1a9e9d039a3f 100644 --- a/drivers/clk/samsung/clk-exynos4415.c +++ b/drivers/clk/samsung/clk-exynos4415.c @@ -111,7 +111,7 @@ #define DIV_CPU0 0x14500 #define DIV_CPU1 0x14504 -static unsigned long exynos4415_cmu_clk_regs[] __initdata = { +static const unsigned long exynos4415_cmu_clk_regs[] __initconst = { SRC_LEFTBUS, DIV_LEFTBUS, GATE_IP_LEFTBUS, @@ -268,16 +268,16 @@ PNAME(group_aclk_isp0_300_user_p) = { "fin_pll", "mout_aclk_isp0_300" }; PNAME(group_aclk_isp1_300_user_p) = { "fin_pll", "mout_aclk_isp1_300" }; PNAME(group_mout_mpll_user_t_p) = { "mout_mpll_user_t" }; -static struct samsung_fixed_factor_clock exynos4415_fixed_factor_clks[] __initdata = { +static const struct samsung_fixed_factor_clock exynos4415_fixed_factor_clks[] __initconst = { /* HACK: fin_pll hardcoded to xusbxti until detection is implemented. */ FFACTOR(CLK_FIN_PLL, "fin_pll", "xusbxti", 1, 1, 0), }; -static struct samsung_fixed_rate_clock exynos4415_fixed_rate_clks[] __initdata = { +static const struct samsung_fixed_rate_clock exynos4415_fixed_rate_clks[] __initconst = { FRATE(CLK_SCLK_HDMIPHY, "sclk_hdmiphy", NULL, 0, 27000000), }; -static struct samsung_mux_clock exynos4415_mux_clks[] __initdata = { +static const struct samsung_mux_clock exynos4415_mux_clks[] __initconst = { /* * NOTE: Following table is sorted by register address in ascending * order and then bitfield shift in descending order, as it is done @@ -427,7 +427,7 @@ static struct samsung_mux_clock exynos4415_mux_clks[] __initdata = { group_aclk_isp1_300_user_p, SRC_TOP_ISP1, 0, 1), }; -static struct samsung_div_clock exynos4415_div_clks[] __initdata = { +static const struct samsung_div_clock exynos4415_div_clks[] __initconst = { /* * NOTE: Following table is sorted by register address in ascending * order and then bitfield shift in descending order, as it is done @@ -566,7 +566,7 @@ static struct samsung_div_clock exynos4415_div_clks[] __initdata = { DIV(CLK_DIV_COPY, "div_copy", "mout_hpm", DIV_CPU1, 0, 3), }; -static struct samsung_gate_clock exynos4415_gate_clks[] __initdata = { +static const struct samsung_gate_clock exynos4415_gate_clks[] __initconst = { /* * NOTE: Following table is sorted by register address in ascending * order and then bitfield shift in descending order, as it is done @@ -859,7 +859,7 @@ static struct samsung_gate_clock exynos4415_gate_clks[] __initdata = { /* * APLL & MPLL & BPLL & ISP_PLL & DISP_PLL & G3D_PLL */ -static struct samsung_pll_rate_table exynos4415_pll_rates[] = { +static const struct samsung_pll_rate_table exynos4415_pll_rates[] = { PLL_35XX_RATE(1600000000, 400, 3, 1), PLL_35XX_RATE(1500000000, 250, 2, 1), PLL_35XX_RATE(1400000000, 175, 3, 0), @@ -891,7 +891,7 @@ static struct samsung_pll_rate_table exynos4415_pll_rates[] = { }; /* EPLL */ -static struct samsung_pll_rate_table exynos4415_epll_rates[] = { +static const struct samsung_pll_rate_table exynos4415_epll_rates[] = { PLL_36XX_RATE(800000000, 200, 3, 1, 0), PLL_36XX_RATE(288000000, 96, 2, 2, 0), PLL_36XX_RATE(192000000, 128, 2, 3, 0), @@ -909,7 +909,7 @@ static struct samsung_pll_rate_table exynos4415_epll_rates[] = { { /* sentinel */ } }; -static struct samsung_pll_clock exynos4415_plls[] __initdata = { +static const struct samsung_pll_clock exynos4415_plls[] __initconst = { PLL(pll_35xx, CLK_FOUT_APLL, "fout_apll", "fin_pll", APLL_LOCK, APLL_CON0, exynos4415_pll_rates), PLL(pll_36xx, CLK_FOUT_EPLL, "fout_epll", "fin_pll", @@ -922,7 +922,7 @@ static struct samsung_pll_clock exynos4415_plls[] __initdata = { "fin_pll", DISP_PLL_LOCK, DISP_PLL_CON0, exynos4415_pll_rates), }; -static struct samsung_cmu_info cmu_info __initdata = { +static const struct samsung_cmu_info cmu_info __initconst = { .pll_clks = exynos4415_plls, .nr_pll_clks = ARRAY_SIZE(exynos4415_plls), .mux_clks = exynos4415_mux_clks, @@ -961,7 +961,7 @@ CLK_OF_DECLARE(exynos4415_cmu, "samsung,exynos4415-cmu", exynos4415_cmu_init); #define SRC_DMC 0x300 #define DIV_DMC1 0x504 -static unsigned long exynos4415_cmu_dmc_clk_regs[] __initdata = { +static const unsigned long exynos4415_cmu_dmc_clk_regs[] __initconst = { MPLL_LOCK, MPLL_CON0, MPLL_CON1, @@ -978,14 +978,14 @@ PNAME(mout_mpll_p) = { "fin_pll", "fout_mpll", }; PNAME(mout_bpll_p) = { "fin_pll", "fout_bpll", }; PNAME(mbpll_p) = { "mout_mpll", "mout_bpll", }; -static struct samsung_mux_clock exynos4415_dmc_mux_clks[] __initdata = { +static const struct samsung_mux_clock exynos4415_dmc_mux_clks[] __initconst = { MUX(CLK_DMC_MOUT_MPLL, "mout_mpll", mout_mpll_p, SRC_DMC, 12, 1), MUX(CLK_DMC_MOUT_BPLL, "mout_bpll", mout_bpll_p, SRC_DMC, 10, 1), MUX(CLK_DMC_MOUT_DPHY, "mout_dphy", mbpll_p, SRC_DMC, 8, 1), MUX(CLK_DMC_MOUT_DMC_BUS, "mout_dmc_bus", mbpll_p, SRC_DMC, 4, 1), }; -static struct samsung_div_clock exynos4415_dmc_div_clks[] __initdata = { +static const struct samsung_div_clock exynos4415_dmc_div_clks[] __initconst = { DIV(CLK_DMC_DIV_DMC, "div_dmc", "div_dmc_pre", DIV_DMC1, 27, 3), DIV(CLK_DMC_DIV_DPHY, "div_dphy", "mout_dphy", DIV_DMC1, 23, 3), DIV(CLK_DMC_DIV_DMC_PRE, "div_dmc_pre", "mout_dmc_bus", @@ -995,14 +995,14 @@ static struct samsung_div_clock exynos4415_dmc_div_clks[] __initdata = { DIV(CLK_DMC_DIV_MPLL_PRE, "div_mpll_pre", "mout_mpll", DIV_DMC1, 8, 2), }; -static struct samsung_pll_clock exynos4415_dmc_plls[] __initdata = { +static const struct samsung_pll_clock exynos4415_dmc_plls[] __initconst = { PLL(pll_35xx, CLK_DMC_FOUT_MPLL, "fout_mpll", "fin_pll", MPLL_LOCK, MPLL_CON0, exynos4415_pll_rates), PLL(pll_35xx, CLK_DMC_FOUT_BPLL, "fout_bpll", "fin_pll", BPLL_LOCK, BPLL_CON0, exynos4415_pll_rates), }; -static struct samsung_cmu_info cmu_dmc_info __initdata = { +static const struct samsung_cmu_info cmu_dmc_info __initconst = { .pll_clks = exynos4415_dmc_plls, .nr_pll_clks = ARRAY_SIZE(exynos4415_dmc_plls), .mux_clks = exynos4415_dmc_mux_clks, -- cgit v1.2.3 From ccd12b5cd69fbe33551922f03fe22e1053e5243c Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 11 May 2016 14:02:03 +0200 Subject: clk: samsung: exynos4415: Move PLL rates data to init section The arrays with initialization data of PLLs can be moved to initconst section because they are referenced only from other initconst-level symbols. Signed-off-by: Krzysztof Kozlowski Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk-exynos4415.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/clk/samsung/clk-exynos4415.c b/drivers/clk/samsung/clk-exynos4415.c index 1a9e9d039a3f..6c9063159717 100644 --- a/drivers/clk/samsung/clk-exynos4415.c +++ b/drivers/clk/samsung/clk-exynos4415.c @@ -859,7 +859,7 @@ static const struct samsung_gate_clock exynos4415_gate_clks[] __initconst = { /* * APLL & MPLL & BPLL & ISP_PLL & DISP_PLL & G3D_PLL */ -static const struct samsung_pll_rate_table exynos4415_pll_rates[] = { +static const struct samsung_pll_rate_table exynos4415_pll_rates[] __initconst = { PLL_35XX_RATE(1600000000, 400, 3, 1), PLL_35XX_RATE(1500000000, 250, 2, 1), PLL_35XX_RATE(1400000000, 175, 3, 0), @@ -891,7 +891,7 @@ static const struct samsung_pll_rate_table exynos4415_pll_rates[] = { }; /* EPLL */ -static const struct samsung_pll_rate_table exynos4415_epll_rates[] = { +static const struct samsung_pll_rate_table exynos4415_epll_rates[] __initconst = { PLL_36XX_RATE(800000000, 200, 3, 1, 0), PLL_36XX_RATE(288000000, 96, 2, 2, 0), PLL_36XX_RATE(192000000, 128, 2, 3, 0), -- cgit v1.2.3 From 5b37e8494d5ce1f4a8a07fb5288c3b63a533cd3c Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 11 May 2016 14:02:04 +0200 Subject: clk: samsung: exynos5250: Constify all clock initializers All of initialization data can be made const. Signed-off-by: Krzysztof Kozlowski Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk-exynos5250.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/clk/samsung/clk-exynos5250.c b/drivers/clk/samsung/clk-exynos5250.c index d8621cf31786..a6ebc068689f 100644 --- a/drivers/clk/samsung/clk-exynos5250.c +++ b/drivers/clk/samsung/clk-exynos5250.c @@ -117,7 +117,7 @@ static struct samsung_clk_reg_dump *exynos5250_save; * list of controller registers to be saved and restored during a * suspend/resume cycle. */ -static unsigned long exynos5250_clk_regs[] __initdata = { +static const unsigned long exynos5250_clk_regs[] __initconst = { SRC_CPU, DIV_CPU0, PWR_CTRL1, @@ -266,23 +266,23 @@ static struct samsung_fixed_rate_clock exynos5250_fixed_rate_ext_clks[] __initda }; /* fixed rate clocks generated inside the soc */ -static struct samsung_fixed_rate_clock exynos5250_fixed_rate_clks[] __initdata = { +static const struct samsung_fixed_rate_clock exynos5250_fixed_rate_clks[] __initconst = { FRATE(CLK_SCLK_HDMIPHY, "sclk_hdmiphy", NULL, 0, 24000000), FRATE(0, "sclk_hdmi27m", NULL, 0, 27000000), FRATE(0, "sclk_dptxphy", NULL, 0, 24000000), FRATE(0, "sclk_uhostphy", NULL, 0, 48000000), }; -static struct samsung_fixed_factor_clock exynos5250_fixed_factor_clks[] __initdata = { +static const struct samsung_fixed_factor_clock exynos5250_fixed_factor_clks[] __initconst = { FFACTOR(0, "fout_mplldiv2", "fout_mpll", 1, 2, 0), FFACTOR(0, "fout_bplldiv2", "fout_bpll", 1, 2, 0), }; -static struct samsung_mux_clock exynos5250_pll_pmux_clks[] __initdata = { +static const struct samsung_mux_clock exynos5250_pll_pmux_clks[] __initconst = { MUX(0, "mout_vpllsrc", mout_vpllsrc_p, SRC_TOP2, 0, 1), }; -static struct samsung_mux_clock exynos5250_mux_clks[] __initdata = { +static const struct samsung_mux_clock exynos5250_mux_clks[] __initconst = { /* * NOTE: Following table is sorted by (clock domain, register address, * bitfield shift) triplet in ascending order. When adding new entries, @@ -378,7 +378,7 @@ static struct samsung_mux_clock exynos5250_mux_clks[] __initdata = { MUX(0, "mout_bpll_fout", mout_bpll_fout_p, PLL_DIV2_SEL, 0, 1), }; -static struct samsung_div_clock exynos5250_div_clks[] __initdata = { +static const struct samsung_div_clock exynos5250_div_clks[] __initconst = { /* * NOTE: Following table is sorted by (clock domain, register address, * bitfield shift) triplet in ascending order. When adding new entries, @@ -470,7 +470,7 @@ static struct samsung_div_clock exynos5250_div_clks[] __initdata = { DIV(CLK_DIV_I2S2, "div_i2s2", "sclk_audio2", DIV_PERIC5, 8, 6), }; -static struct samsung_gate_clock exynos5250_gate_clks[] __initdata = { +static const struct samsung_gate_clock exynos5250_gate_clks[] __initconst = { /* * NOTE: Following table is sorted by (clock domain, register address, * bitfield shift) triplet in ascending order. When adding new entries, @@ -698,7 +698,7 @@ static struct samsung_gate_clock exynos5250_gate_clks[] __initdata = { GATE_IP_ISP1, 7, 0, 0), }; -static struct samsung_pll_rate_table vpll_24mhz_tbl[] __initdata = { +static const struct samsung_pll_rate_table vpll_24mhz_tbl[] __initconst = { /* sorted in descending order */ /* PLL_36XX_RATE(rate, m, p, s, k) */ PLL_36XX_RATE(266000000, 266, 3, 3, 0), @@ -707,7 +707,7 @@ static struct samsung_pll_rate_table vpll_24mhz_tbl[] __initdata = { { }, }; -static struct samsung_pll_rate_table epll_24mhz_tbl[] __initdata = { +static const struct samsung_pll_rate_table epll_24mhz_tbl[] __initconst = { /* sorted in descending order */ /* PLL_36XX_RATE(rate, m, p, s, k) */ PLL_36XX_RATE(192000000, 64, 2, 2, 0), @@ -721,7 +721,7 @@ static struct samsung_pll_rate_table epll_24mhz_tbl[] __initdata = { { }, }; -static struct samsung_pll_rate_table apll_24mhz_tbl[] __initdata = { +static const struct samsung_pll_rate_table apll_24mhz_tbl[] __initconst = { /* sorted in descending order */ /* PLL_35XX_RATE(rate, m, p, s) */ PLL_35XX_RATE(1700000000, 425, 6, 0), -- cgit v1.2.3 From c10d80f8e1c4eed487d845f3efd52078fdc764eb Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 11 May 2016 14:02:05 +0200 Subject: clk: samsung: exynos5260: Constify all clock initializers All of initialization data can be made const. Signed-off-by: Krzysztof Kozlowski Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk-exynos5260.c | 114 +++++++++++++++++------------------ 1 file changed, 57 insertions(+), 57 deletions(-) diff --git a/drivers/clk/samsung/clk-exynos5260.c b/drivers/clk/samsung/clk-exynos5260.c index 7a7ed075a573..a43642c36039 100644 --- a/drivers/clk/samsung/clk-exynos5260.c +++ b/drivers/clk/samsung/clk-exynos5260.c @@ -22,7 +22,7 @@ * Applicable for all 2550 Type PLLS for Exynos5260, listed below * DISP_PLL, EGL_PLL, KFC_PLL, MEM_PLL, BUS_PLL, MEDIA_PLL, G3D_PLL. */ -static struct samsung_pll_rate_table pll2550_24mhz_tbl[] __initdata = { +static const struct samsung_pll_rate_table pll2550_24mhz_tbl[] __initconst = { PLL_35XX_RATE(1700000000, 425, 6, 0), PLL_35XX_RATE(1600000000, 200, 3, 0), PLL_35XX_RATE(1500000000, 250, 4, 0), @@ -55,7 +55,7 @@ static struct samsung_pll_rate_table pll2550_24mhz_tbl[] __initdata = { /* * Applicable for 2650 Type PLL for AUD_PLL. */ -static struct samsung_pll_rate_table pll2650_24mhz_tbl[] __initdata = { +static const struct samsung_pll_rate_table pll2650_24mhz_tbl[] __initconst = { PLL_36XX_RATE(1600000000, 200, 3, 0, 0), PLL_36XX_RATE(1200000000, 100, 2, 0, 0), PLL_36XX_RATE(1000000000, 250, 3, 1, 0), @@ -78,7 +78,7 @@ static struct samsung_pll_rate_table pll2650_24mhz_tbl[] __initdata = { /* CMU_AUD */ -static unsigned long aud_clk_regs[] __initdata = { +static const unsigned long aud_clk_regs[] __initconst = { MUX_SEL_AUD, DIV_AUD0, DIV_AUD1, @@ -92,7 +92,7 @@ PNAME(mout_aud_pll_user_p) = {"fin_pll", "fout_aud_pll"}; PNAME(mout_sclk_aud_i2s_p) = {"mout_aud_pll_user", "ioclk_i2s_cdclk"}; PNAME(mout_sclk_aud_pcm_p) = {"mout_aud_pll_user", "ioclk_pcm_extclk"}; -static struct samsung_mux_clock aud_mux_clks[] __initdata = { +static const struct samsung_mux_clock aud_mux_clks[] __initconst = { MUX(AUD_MOUT_AUD_PLL_USER, "mout_aud_pll_user", mout_aud_pll_user_p, MUX_SEL_AUD, 0, 1), MUX(AUD_MOUT_SCLK_AUD_I2S, "mout_sclk_aud_i2s", mout_sclk_aud_i2s_p, @@ -101,7 +101,7 @@ static struct samsung_mux_clock aud_mux_clks[] __initdata = { MUX_SEL_AUD, 8, 1), }; -static struct samsung_div_clock aud_div_clks[] __initdata = { +static const struct samsung_div_clock aud_div_clks[] __initconst = { DIV(AUD_DOUT_ACLK_AUD_131, "dout_aclk_aud_131", "mout_aud_pll_user", DIV_AUD0, 0, 4), @@ -113,7 +113,7 @@ static struct samsung_div_clock aud_div_clks[] __initdata = { DIV_AUD1, 12, 4), }; -static struct samsung_gate_clock aud_gate_clks[] __initdata = { +static const struct samsung_gate_clock aud_gate_clks[] __initconst = { GATE(AUD_SCLK_I2S, "sclk_aud_i2s", "dout_sclk_aud_i2s", EN_SCLK_AUD, 0, CLK_SET_RATE_PARENT, 0), GATE(AUD_SCLK_PCM, "sclk_aud_pcm", "dout_sclk_aud_pcm", @@ -154,7 +154,7 @@ CLK_OF_DECLARE(exynos5260_clk_aud, "samsung,exynos5260-clock-aud", /* CMU_DISP */ -static unsigned long disp_clk_regs[] __initdata = { +static const unsigned long disp_clk_regs[] __initconst = { MUX_SEL_DISP0, MUX_SEL_DISP1, MUX_SEL_DISP2, @@ -201,7 +201,7 @@ PNAME(mout_phyclk_mipi_dphy_4lmrxclk_esc0_user_p) = {"fin_pll", PNAME(mout_sclk_hdmi_spdif_p) = {"fin_pll", "ioclk_spdif_extclk", "dout_aclk_peri_aud", "phyclk_hdmi_phy_ref_cko"}; -static struct samsung_mux_clock disp_mux_clks[] __initdata = { +static const struct samsung_mux_clock disp_mux_clks[] __initconst = { MUX(DISP_MOUT_ACLK_DISP_333_USER, "mout_aclk_disp_333_user", mout_aclk_disp_333_user_p, MUX_SEL_DISP0, 0, 1), @@ -270,7 +270,7 @@ static struct samsung_mux_clock disp_mux_clks[] __initdata = { MUX_SEL_DISP4, 4, 2), }; -static struct samsung_div_clock disp_div_clks[] __initdata = { +static const struct samsung_div_clock disp_div_clks[] __initconst = { DIV(DISP_DOUT_PCLK_DISP_111, "dout_pclk_disp_111", "mout_aclk_disp_222_user", DIV_DISP, 8, 4), @@ -283,7 +283,7 @@ static struct samsung_div_clock disp_div_clks[] __initdata = { DIV_DISP, 16, 4), }; -static struct samsung_gate_clock disp_gate_clks[] __initdata = { +static const struct samsung_gate_clock disp_gate_clks[] __initconst = { GATE(DISP_MOUT_HDMI_PHY_PIXEL_USER, "sclk_hdmi_link_i_pixel", "mout_phyclk_hdmi_phy_pixel_clko_user", EN_SCLK_DISP0, 26, CLK_SET_RATE_PARENT, 0), @@ -344,7 +344,7 @@ CLK_OF_DECLARE(exynos5260_clk_disp, "samsung,exynos5260-clock-disp", /* CMU_EGL */ -static unsigned long egl_clk_regs[] __initdata = { +static const unsigned long egl_clk_regs[] __initconst = { EGL_PLL_LOCK, EGL_PLL_CON0, EGL_PLL_CON1, @@ -361,13 +361,13 @@ static unsigned long egl_clk_regs[] __initdata = { PNAME(mout_egl_b_p) = {"mout_egl_pll", "dout_bus_pll"}; PNAME(mout_egl_pll_p) = {"fin_pll", "fout_egl_pll"}; -static struct samsung_mux_clock egl_mux_clks[] __initdata = { +static const struct samsung_mux_clock egl_mux_clks[] __initconst = { MUX(EGL_MOUT_EGL_PLL, "mout_egl_pll", mout_egl_pll_p, MUX_SEL_EGL, 4, 1), MUX(EGL_MOUT_EGL_B, "mout_egl_b", mout_egl_b_p, MUX_SEL_EGL, 16, 1), }; -static struct samsung_div_clock egl_div_clks[] __initdata = { +static const struct samsung_div_clock egl_div_clks[] __initconst = { DIV(EGL_DOUT_EGL1, "dout_egl1", "mout_egl_b", DIV_EGL, 0, 3), DIV(EGL_DOUT_EGL2, "dout_egl2", "dout_egl1", DIV_EGL, 4, 3), DIV(EGL_DOUT_ACLK_EGL, "dout_aclk_egl", "dout_egl2", DIV_EGL, 8, 3), @@ -379,7 +379,7 @@ static struct samsung_div_clock egl_div_clks[] __initdata = { DIV(EGL_DOUT_EGL_PLL, "dout_egl_pll", "mout_egl_b", DIV_EGL, 24, 3), }; -static struct samsung_pll_clock egl_pll_clks[] __initdata = { +static const struct samsung_pll_clock egl_pll_clks[] __initconst = { PLL(pll_2550xx, EGL_FOUT_EGL_PLL, "fout_egl_pll", "fin_pll", EGL_PLL_LOCK, EGL_PLL_CON0, pll2550_24mhz_tbl), @@ -408,7 +408,7 @@ CLK_OF_DECLARE(exynos5260_clk_egl, "samsung,exynos5260-clock-egl", /* CMU_FSYS */ -static unsigned long fsys_clk_regs[] __initdata = { +static const unsigned long fsys_clk_regs[] __initconst = { MUX_SEL_FSYS0, MUX_SEL_FSYS1, EN_ACLK_FSYS, @@ -431,7 +431,7 @@ PNAME(mout_phyclk_usbdrd30_pipe_pclk_user_p) = {"fin_pll", PNAME(mout_phyclk_usbdrd30_phyclock_user_p) = {"fin_pll", "phyclk_usbdrd30_udrd30_phyclock"}; -static struct samsung_mux_clock fsys_mux_clks[] __initdata = { +static const struct samsung_mux_clock fsys_mux_clks[] __initconst = { MUX(FSYS_MOUT_PHYCLK_USBDRD30_PHYCLOCK_USER, "mout_phyclk_usbdrd30_phyclock_user", mout_phyclk_usbdrd30_phyclock_user_p, @@ -454,7 +454,7 @@ static struct samsung_mux_clock fsys_mux_clks[] __initdata = { MUX_SEL_FSYS1, 16, 1), }; -static struct samsung_gate_clock fsys_gate_clks[] __initdata = { +static const struct samsung_gate_clock fsys_gate_clks[] __initconst = { GATE(FSYS_PHYCLK_USBHOST20, "phyclk_usbhost20_phyclock", "mout_phyclk_usbdrd30_phyclock_user", EN_SCLK_FSYS, 1, 0, 0), @@ -508,7 +508,7 @@ CLK_OF_DECLARE(exynos5260_clk_fsys, "samsung,exynos5260-clock-fsys", /* CMU_G2D */ -static unsigned long g2d_clk_regs[] __initdata = { +static const unsigned long g2d_clk_regs[] __initconst = { MUX_SEL_G2D, MUX_STAT_G2D, DIV_G2D, @@ -535,18 +535,18 @@ static unsigned long g2d_clk_regs[] __initdata = { PNAME(mout_aclk_g2d_333_user_p) = {"fin_pll", "dout_aclk_g2d_333"}; -static struct samsung_mux_clock g2d_mux_clks[] __initdata = { +static const struct samsung_mux_clock g2d_mux_clks[] __initconst = { MUX(G2D_MOUT_ACLK_G2D_333_USER, "mout_aclk_g2d_333_user", mout_aclk_g2d_333_user_p, MUX_SEL_G2D, 0, 1), }; -static struct samsung_div_clock g2d_div_clks[] __initdata = { +static const struct samsung_div_clock g2d_div_clks[] __initconst = { DIV(G2D_DOUT_PCLK_G2D_83, "dout_pclk_g2d_83", "mout_aclk_g2d_333_user", DIV_G2D, 0, 3), }; -static struct samsung_gate_clock g2d_gate_clks[] __initdata = { +static const struct samsung_gate_clock g2d_gate_clks[] __initconst = { GATE(G2D_CLK_G2D, "clk_g2d", "mout_aclk_g2d_333_user", EN_IP_G2D, 4, 0, 0), GATE(G2D_CLK_JPEG, "clk_jpeg", "mout_aclk_g2d_333_user", @@ -599,7 +599,7 @@ CLK_OF_DECLARE(exynos5260_clk_g2d, "samsung,exynos5260-clock-g2d", /* CMU_G3D */ -static unsigned long g3d_clk_regs[] __initdata = { +static const unsigned long g3d_clk_regs[] __initconst = { G3D_PLL_LOCK, G3D_PLL_CON0, G3D_PLL_CON1, @@ -615,23 +615,23 @@ static unsigned long g3d_clk_regs[] __initdata = { PNAME(mout_g3d_pll_p) = {"fin_pll", "fout_g3d_pll"}; -static struct samsung_mux_clock g3d_mux_clks[] __initdata = { +static const struct samsung_mux_clock g3d_mux_clks[] __initconst = { MUX(G3D_MOUT_G3D_PLL, "mout_g3d_pll", mout_g3d_pll_p, MUX_SEL_G3D, 0, 1), }; -static struct samsung_div_clock g3d_div_clks[] __initdata = { +static const struct samsung_div_clock g3d_div_clks[] __initconst = { DIV(G3D_DOUT_PCLK_G3D, "dout_pclk_g3d", "dout_aclk_g3d", DIV_G3D, 0, 3), DIV(G3D_DOUT_ACLK_G3D, "dout_aclk_g3d", "mout_g3d_pll", DIV_G3D, 4, 3), }; -static struct samsung_gate_clock g3d_gate_clks[] __initdata = { +static const struct samsung_gate_clock g3d_gate_clks[] __initconst = { GATE(G3D_CLK_G3D, "clk_g3d", "dout_aclk_g3d", EN_IP_G3D, 2, 0, 0), GATE(G3D_CLK_G3D_HPM, "clk_g3d_hpm", "dout_aclk_g3d", EN_IP_G3D, 3, 0, 0), }; -static struct samsung_pll_clock g3d_pll_clks[] __initdata = { +static const struct samsung_pll_clock g3d_pll_clks[] __initconst = { PLL(pll_2550, G3D_FOUT_G3D_PLL, "fout_g3d_pll", "fin_pll", G3D_PLL_LOCK, G3D_PLL_CON0, pll2550_24mhz_tbl), @@ -662,7 +662,7 @@ CLK_OF_DECLARE(exynos5260_clk_g3d, "samsung,exynos5260-clock-g3d", /* CMU_GSCL */ -static unsigned long gscl_clk_regs[] __initdata = { +static const unsigned long gscl_clk_regs[] __initconst = { MUX_SEL_GSCL, DIV_GSCL, EN_ACLK_GSCL, @@ -692,7 +692,7 @@ PNAME(mout_aclk_m2m_400_user_p) = {"fin_pll", "dout_aclk_gscl_400"}; PNAME(mout_aclk_gscl_fimc_user_p) = {"fin_pll", "dout_aclk_gscl_400"}; PNAME(mout_aclk_csis_p) = {"dout_aclk_csis_200", "mout_aclk_gscl_fimc_user"}; -static struct samsung_mux_clock gscl_mux_clks[] __initdata = { +static const struct samsung_mux_clock gscl_mux_clks[] __initconst = { MUX(GSCL_MOUT_ACLK_GSCL_333_USER, "mout_aclk_gscl_333_user", mout_aclk_gscl_333_user_p, MUX_SEL_GSCL, 0, 1), @@ -706,7 +706,7 @@ static struct samsung_mux_clock gscl_mux_clks[] __initdata = { MUX_SEL_GSCL, 24, 1), }; -static struct samsung_div_clock gscl_div_clks[] __initdata = { +static const struct samsung_div_clock gscl_div_clks[] __initconst = { DIV(GSCL_DOUT_PCLK_M2M_100, "dout_pclk_m2m_100", "mout_aclk_m2m_400_user", DIV_GSCL, 0, 3), @@ -715,7 +715,7 @@ static struct samsung_div_clock gscl_div_clks[] __initdata = { DIV_GSCL, 4, 3), }; -static struct samsung_gate_clock gscl_gate_clks[] __initdata = { +static const struct samsung_gate_clock gscl_gate_clks[] __initconst = { GATE(GSCL_SCLK_CSIS0_WRAP, "sclk_csis0_wrap", "dout_aclk_csis_200", EN_SCLK_GSCL_FIMC, 0, CLK_SET_RATE_PARENT, 0), GATE(GSCL_SCLK_CSIS1_WRAP, "sclk_csis1_wrap", "dout_aclk_csis_200", @@ -795,7 +795,7 @@ CLK_OF_DECLARE(exynos5260_clk_gscl, "samsung,exynos5260-clock-gscl", /* CMU_ISP */ -static unsigned long isp_clk_regs[] __initdata = { +static const unsigned long isp_clk_regs[] __initconst = { MUX_SEL_ISP0, MUX_SEL_ISP1, DIV_ISP, @@ -811,14 +811,14 @@ static unsigned long isp_clk_regs[] __initdata = { PNAME(mout_isp_400_user_p) = {"fin_pll", "dout_aclk_isp1_400"}; PNAME(mout_isp_266_user_p) = {"fin_pll", "dout_aclk_isp1_266"}; -static struct samsung_mux_clock isp_mux_clks[] __initdata = { +static const struct samsung_mux_clock isp_mux_clks[] __initconst = { MUX(ISP_MOUT_ISP_266_USER, "mout_isp_266_user", mout_isp_266_user_p, MUX_SEL_ISP0, 0, 1), MUX(ISP_MOUT_ISP_400_USER, "mout_isp_400_user", mout_isp_400_user_p, MUX_SEL_ISP0, 4, 1), }; -static struct samsung_div_clock isp_div_clks[] __initdata = { +static const struct samsung_div_clock isp_div_clks[] __initconst = { DIV(ISP_DOUT_PCLK_ISP_66, "dout_pclk_isp_66", "mout_kfc", DIV_ISP, 0, 3), DIV(ISP_DOUT_PCLK_ISP_133, "dout_pclk_isp_133", "mout_kfc", @@ -830,7 +830,7 @@ static struct samsung_div_clock isp_div_clks[] __initdata = { DIV(ISP_DOUT_SCLK_MPWM, "dout_sclk_mpwm", "mout_kfc", DIV_ISP, 20, 2), }; -static struct samsung_gate_clock isp_gate_clks[] __initdata = { +static const struct samsung_gate_clock isp_gate_clks[] __initconst = { GATE(ISP_CLK_GIC, "clk_isp_gic", "mout_aclk_isp1_266", EN_IP_ISP0, 15, 0, 0), @@ -914,7 +914,7 @@ CLK_OF_DECLARE(exynos5260_clk_isp, "samsung,exynos5260-clock-isp", /* CMU_KFC */ -static unsigned long kfc_clk_regs[] __initdata = { +static const unsigned long kfc_clk_regs[] __initconst = { KFC_PLL_LOCK, KFC_PLL_CON0, KFC_PLL_CON1, @@ -932,13 +932,13 @@ static unsigned long kfc_clk_regs[] __initdata = { PNAME(mout_kfc_pll_p) = {"fin_pll", "fout_kfc_pll"}; PNAME(mout_kfc_p) = {"mout_kfc_pll", "dout_media_pll"}; -static struct samsung_mux_clock kfc_mux_clks[] __initdata = { +static const struct samsung_mux_clock kfc_mux_clks[] __initconst = { MUX(KFC_MOUT_KFC_PLL, "mout_kfc_pll", mout_kfc_pll_p, MUX_SEL_KFC0, 0, 1), MUX(KFC_MOUT_KFC, "mout_kfc", mout_kfc_p, MUX_SEL_KFC2, 0, 1), }; -static struct samsung_div_clock kfc_div_clks[] __initdata = { +static const struct samsung_div_clock kfc_div_clks[] __initconst = { DIV(KFC_DOUT_KFC1, "dout_kfc1", "mout_kfc", DIV_KFC, 0, 3), DIV(KFC_DOUT_KFC2, "dout_kfc2", "dout_kfc1", DIV_KFC, 4, 3), DIV(KFC_DOUT_KFC_ATCLK, "dout_kfc_atclk", "dout_kfc2", DIV_KFC, 8, 3), @@ -949,7 +949,7 @@ static struct samsung_div_clock kfc_div_clks[] __initdata = { DIV(KFC_DOUT_KFC_PLL, "dout_kfc_pll", "mout_kfc", DIV_KFC, 24, 3), }; -static struct samsung_pll_clock kfc_pll_clks[] __initdata = { +static const struct samsung_pll_clock kfc_pll_clks[] __initconst = { PLL(pll_2550xx, KFC_FOUT_KFC_PLL, "fout_kfc_pll", "fin_pll", KFC_PLL_LOCK, KFC_PLL_CON0, pll2550_24mhz_tbl), @@ -978,7 +978,7 @@ CLK_OF_DECLARE(exynos5260_clk_kfc, "samsung,exynos5260-clock-kfc", /* CMU_MFC */ -static unsigned long mfc_clk_regs[] __initdata = { +static const unsigned long mfc_clk_regs[] __initconst = { MUX_SEL_MFC, DIV_MFC, EN_ACLK_MFC, @@ -991,18 +991,18 @@ static unsigned long mfc_clk_regs[] __initdata = { PNAME(mout_aclk_mfc_333_user_p) = {"fin_pll", "dout_aclk_mfc_333"}; -static struct samsung_mux_clock mfc_mux_clks[] __initdata = { +static const struct samsung_mux_clock mfc_mux_clks[] __initconst = { MUX(MFC_MOUT_ACLK_MFC_333_USER, "mout_aclk_mfc_333_user", mout_aclk_mfc_333_user_p, MUX_SEL_MFC, 0, 1), }; -static struct samsung_div_clock mfc_div_clks[] __initdata = { +static const struct samsung_div_clock mfc_div_clks[] __initconst = { DIV(MFC_DOUT_PCLK_MFC_83, "dout_pclk_mfc_83", "mout_aclk_mfc_333_user", DIV_MFC, 0, 3), }; -static struct samsung_gate_clock mfc_gate_clks[] __initdata = { +static const struct samsung_gate_clock mfc_gate_clks[] __initconst = { GATE(MFC_CLK_MFC, "clk_mfc", "mout_aclk_mfc_333_user", EN_IP_MFC, 1, 0, 0), GATE(MFC_CLK_SMMU2_MFCM0, "clk_smmu2_mfcm0", "mout_aclk_mfc_333_user", @@ -1034,7 +1034,7 @@ CLK_OF_DECLARE(exynos5260_clk_mfc, "samsung,exynos5260-clock-mfc", /* CMU_MIF */ -static unsigned long mif_clk_regs[] __initdata = { +static const unsigned long mif_clk_regs[] __initconst = { MEM_PLL_LOCK, BUS_PLL_LOCK, MEDIA_PLL_LOCK, @@ -1076,7 +1076,7 @@ PNAME(mout_mif_drex2x_p) = {"dout_mem_pll", "dout_bus_pll"}; PNAME(mout_clkm_phy_p) = {"mout_mif_drex", "dout_media_pll"}; PNAME(mout_clk2x_phy_p) = {"mout_mif_drex2x", "dout_media_pll"}; -static struct samsung_mux_clock mif_mux_clks[] __initdata = { +static const struct samsung_mux_clock mif_mux_clks[] __initconst = { MUX(MIF_MOUT_MEM_PLL, "mout_mem_pll", mout_mem_pll_p, MUX_SEL_MIF, 0, 1), MUX(MIF_MOUT_BUS_PLL, "mout_bus_pll", mout_bus_pll_p, @@ -1093,7 +1093,7 @@ static struct samsung_mux_clock mif_mux_clks[] __initdata = { MUX_SEL_MIF, 24, 1), }; -static struct samsung_div_clock mif_div_clks[] __initdata = { +static const struct samsung_div_clock mif_div_clks[] __initconst = { DIV(MIF_DOUT_MEDIA_PLL, "dout_media_pll", "mout_media_pll", DIV_MIF, 0, 3), DIV(MIF_DOUT_MEM_PLL, "dout_mem_pll", "mout_mem_pll", @@ -1112,7 +1112,7 @@ static struct samsung_div_clock mif_div_clks[] __initdata = { DIV_MIF, 28, 4), }; -static struct samsung_gate_clock mif_gate_clks[] __initdata = { +static const struct samsung_gate_clock mif_gate_clks[] __initconst = { GATE(MIF_CLK_LPDDR3PHY_WRAP0, "clk_lpddr3phy_wrap0", "dout_clk2x_phy", EN_IP_MIF, 12, CLK_IGNORE_UNUSED, 0), GATE(MIF_CLK_LPDDR3PHY_WRAP1, "clk_lpddr3phy_wrap1", "dout_clk2x_phy", @@ -1146,7 +1146,7 @@ static struct samsung_gate_clock mif_gate_clks[] __initdata = { CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0), }; -static struct samsung_pll_clock mif_pll_clks[] __initdata = { +static const struct samsung_pll_clock mif_pll_clks[] __initconst = { PLL(pll_2550xx, MIF_FOUT_MEM_PLL, "fout_mem_pll", "fin_pll", MEM_PLL_LOCK, MEM_PLL_CON0, pll2550_24mhz_tbl), @@ -1183,7 +1183,7 @@ CLK_OF_DECLARE(exynos5260_clk_mif, "samsung,exynos5260-clock-mif", /* CMU_PERI */ -static unsigned long peri_clk_regs[] __initdata = { +static const unsigned long peri_clk_regs[] __initconst = { MUX_SEL_PERI, MUX_SEL_PERI1, DIV_PERI, @@ -1219,7 +1219,7 @@ PNAME(mout_sclk_i2scod_p) = {"ioclk_i2s_cdclk", "fin_pll", "dout_aclk_peri_aud", PNAME(mout_sclk_spdif_p) = {"ioclk_spdif_extclk", "fin_pll", "dout_aclk_peri_aud", "phyclk_hdmi_phy_ref_cko"}; -static struct samsung_mux_clock peri_mux_clks[] __initdata = { +static const struct samsung_mux_clock peri_mux_clks[] __initconst = { MUX(PERI_MOUT_SCLK_PCM, "mout_sclk_pcm", mout_sclk_pcm_p, MUX_SEL_PERI1, 4, 2), MUX(PERI_MOUT_SCLK_I2SCOD, "mout_sclk_i2scod", mout_sclk_i2scod_p, @@ -1228,12 +1228,12 @@ static struct samsung_mux_clock peri_mux_clks[] __initdata = { MUX_SEL_PERI1, 20, 2), }; -static struct samsung_div_clock peri_div_clks[] __initdata = { +static const struct samsung_div_clock peri_div_clks[] __initconst = { DIV(PERI_DOUT_PCM, "dout_pcm", "mout_sclk_pcm", DIV_PERI, 0, 8), DIV(PERI_DOUT_I2S, "dout_i2s", "mout_sclk_i2scod", DIV_PERI, 8, 6), }; -static struct samsung_gate_clock peri_gate_clks[] __initdata = { +static const struct samsung_gate_clock peri_gate_clks[] __initconst = { GATE(PERI_SCLK_PCM1, "sclk_pcm1", "dout_pcm", EN_SCLK_PERI, 0, CLK_SET_RATE_PARENT, 0), GATE(PERI_SCLK_I2S, "sclk_i2s", "dout_i2s", EN_SCLK_PERI, 1, @@ -1389,7 +1389,7 @@ CLK_OF_DECLARE(exynos5260_clk_peri, "samsung,exynos5260-clock-peri", /* CMU_TOP */ -static unsigned long top_clk_regs[] __initdata = { +static const unsigned long top_clk_regs[] __initconst = { DISP_PLL_LOCK, AUD_PLL_LOCK, DISP_PLL_CON0, @@ -1430,7 +1430,7 @@ static unsigned long top_clk_regs[] __initdata = { }; /* fixed rate clocks generated inside the soc */ -static struct samsung_fixed_rate_clock fixed_rate_clks[] __initdata = { +static const struct samsung_fixed_rate_clock fixed_rate_clks[] __initconst = { FRATE(PHYCLK_DPTX_PHY_CH3_TXD_CLK, "phyclk_dptx_phy_ch3_txd_clk", NULL, 0, 270000000), FRATE(PHYCLK_DPTX_PHY_CH2_TXD_CLK, "phyclk_dptx_phy_ch2_txd_clk", NULL, @@ -1513,7 +1513,7 @@ PNAME(mout_sclk_fsys_mmc1_sdclkin_b_p) = {"mout_sclk_fsys_mmc1_sdclkin_a", PNAME(mout_sclk_fsys_mmc2_sdclkin_b_p) = {"mout_sclk_fsys_mmc2_sdclkin_a", "mout_mediatop_pll_user"}; -static struct samsung_mux_clock top_mux_clks[] __initdata = { +static const struct samsung_mux_clock top_mux_clks[] __initconst = { MUX(TOP_MOUT_MEDIATOP_PLL_USER, "mout_mediatop_pll_user", mout_mediatop_pll_user_p, MUX_SEL_TOP_PLL0, 0, 1), @@ -1673,7 +1673,7 @@ static struct samsung_mux_clock top_mux_clks[] __initdata = { MUX_SEL_TOP_GSCL, 20, 1), }; -static struct samsung_div_clock top_div_clks[] __initdata = { +static const struct samsung_div_clock top_div_clks[] __initconst = { DIV(TOP_DOUT_ACLK_G2D_333, "dout_aclk_g2d_333", "mout_aclk_g2d_333", DIV_TOP_G2D_MFC, 0, 3), DIV(TOP_DOUT_ACLK_MFC_333, "dout_aclk_mfc_333", "mout_aclk_mfc_333", @@ -1794,7 +1794,7 @@ static struct samsung_div_clock top_div_clks[] __initdata = { }; -static struct samsung_gate_clock top_gate_clks[] __initdata = { +static const struct samsung_gate_clock top_gate_clks[] __initconst = { GATE(TOP_SCLK_MMC0, "sclk_fsys_mmc0_sdclkin", "dout_sclk_fsys_mmc0_sdclkin_b", EN_SCLK_TOP, 7, CLK_SET_RATE_PARENT, 0), @@ -1809,7 +1809,7 @@ static struct samsung_gate_clock top_gate_clks[] __initdata = { CLK_SET_RATE_PARENT, 0), }; -static struct samsung_pll_clock top_pll_clks[] __initdata = { +static const struct samsung_pll_clock top_pll_clks[] __initconst = { PLL(pll_2550xx, TOP_FOUT_DISP_PLL, "fout_disp_pll", "fin_pll", DISP_PLL_LOCK, DISP_PLL_CON0, pll2550_24mhz_tbl), -- cgit v1.2.3 From 408860ba5329c547002c087cfc296851c59f6b57 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 11 May 2016 14:02:06 +0200 Subject: clk: samsung: exynos5410: Constify all clock initializers All of initialization data can be made const. Signed-off-by: Krzysztof Kozlowski Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk-exynos5410.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/clk/samsung/clk-exynos5410.c b/drivers/clk/samsung/clk-exynos5410.c index d5d5dcabc4a9..8e8c7cca8c62 100644 --- a/drivers/clk/samsung/clk-exynos5410.c +++ b/drivers/clk/samsung/clk-exynos5410.c @@ -76,7 +76,7 @@ PNAME(group2_p) = { "fin_pll", "fin_pll", "none", "none", "none", "none", "sclk_mpll_bpll", "none", "none", "sclk_cpll" }; -static struct samsung_mux_clock exynos5410_mux_clks[] __initdata = { +static const struct samsung_mux_clock exynos5410_mux_clks[] __initconst = { MUX(0, "mout_apll", apll_p, SRC_CPU, 0, 1), MUX(0, "mout_cpu", mout_cpu_p, SRC_CPU, 16, 1), @@ -105,7 +105,7 @@ static struct samsung_mux_clock exynos5410_mux_clks[] __initdata = { MUX(0, "mout_aclk400", mpll_bpll_p, SRC_TOP0, 20, 1), }; -static struct samsung_div_clock exynos5410_div_clks[] __initdata = { +static const struct samsung_div_clock exynos5410_div_clks[] __initconst = { DIV(0, "div_arm", "mout_cpu", DIV_CPU0, 0, 3), DIV(0, "div_arm2", "div_arm", DIV_CPU0, 28, 3), @@ -141,7 +141,7 @@ static struct samsung_div_clock exynos5410_div_clks[] __initdata = { DIV(0, "aclk400", "mout_aclk400", DIV_TOP0, 24, 3), }; -static struct samsung_gate_clock exynos5410_gate_clks[] __initdata = { +static const struct samsung_gate_clock exynos5410_gate_clks[] __initconst = { GATE(CLK_MCT, "mct", "aclk66", GATE_IP_PERIS, 18, 0, 0), GATE(CLK_SCLK_MMC0, "sclk_mmc0", "div_mmc_pre0", @@ -167,7 +167,7 @@ static struct samsung_gate_clock exynos5410_gate_clks[] __initdata = { SRC_MASK_PERIC0, 8, CLK_SET_RATE_PARENT, 0), }; -static struct samsung_pll_clock exynos5410_plls[nr_plls] __initdata = { +static const struct samsung_pll_clock exynos5410_plls[nr_plls] __initconst = { [apll] = PLL(pll_35xx, CLK_FOUT_APLL, "fout_apll", "fin_pll", APLL_LOCK, APLL_CON0, NULL), [cpll] = PLL(pll_35xx, CLK_FOUT_CPLL, "fout_cpll", "fin_pll", CPLL_LOCK, -- cgit v1.2.3 From ad98c64fbb792d7089118b6568ce7bc35fce1875 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 11 May 2016 14:02:07 +0200 Subject: clk: samsung: exynos5420: Constify all clock initializers All of initialization data can be made const. Signed-off-by: Krzysztof Kozlowski Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk-exynos5420.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/drivers/clk/samsung/clk-exynos5420.c b/drivers/clk/samsung/clk-exynos5420.c index 770c0f007c6b..427725c8262c 100644 --- a/drivers/clk/samsung/clk-exynos5420.c +++ b/drivers/clk/samsung/clk-exynos5420.c @@ -160,7 +160,7 @@ static struct samsung_clk_reg_dump *exynos5800_save; * list of controller registers to be saved and restored during a * suspend/resume cycle. */ -static unsigned long exynos5x_clk_regs[] __initdata = { +static const unsigned long exynos5x_clk_regs[] __initconst = { SRC_CPU, DIV_CPU0, DIV_CPU1, @@ -248,7 +248,7 @@ static unsigned long exynos5x_clk_regs[] __initdata = { DIV_KFC0, }; -static unsigned long exynos5800_clk_regs[] __initdata = { +static const unsigned long exynos5800_clk_regs[] __initconst = { SRC_TOP8, SRC_TOP9, SRC_CAM, @@ -484,7 +484,7 @@ static struct samsung_fixed_rate_clock }; /* fixed rate clocks generated inside the soc */ -static struct samsung_fixed_rate_clock exynos5x_fixed_rate_clks[] __initdata = { +static const struct samsung_fixed_rate_clock exynos5x_fixed_rate_clks[] __initconst = { FRATE(CLK_SCLK_HDMIPHY, "sclk_hdmiphy", NULL, 0, 24000000), FRATE(0, "sclk_pwi", NULL, 0, 24000000), FRATE(0, "sclk_usbh20", NULL, 0, 48000000), @@ -492,19 +492,19 @@ static struct samsung_fixed_rate_clock exynos5x_fixed_rate_clks[] __initdata = { FRATE(0, "sclk_usbh20_scan_clk", NULL, 0, 480000000), }; -static struct samsung_fixed_factor_clock - exynos5x_fixed_factor_clks[] __initdata = { +static const struct samsung_fixed_factor_clock + exynos5x_fixed_factor_clks[] __initconst = { FFACTOR(0, "ff_hsic_12m", "fin_pll", 1, 2, 0), FFACTOR(0, "ff_sw_aclk66", "mout_sw_aclk66", 1, 2, 0), }; -static struct samsung_fixed_factor_clock - exynos5800_fixed_factor_clks[] __initdata = { +static const struct samsung_fixed_factor_clock + exynos5800_fixed_factor_clks[] __initconst = { FFACTOR(0, "ff_dout_epll2", "mout_sclk_epll", 1, 2, 0), FFACTOR(0, "ff_dout_spll2", "mout_sclk_spll", 1, 2, 0), }; -static struct samsung_mux_clock exynos5800_mux_clks[] __initdata = { +static const struct samsung_mux_clock exynos5800_mux_clks[] __initconst = { MUX(0, "mout_aclk400_isp", mout_group3_5800_p, SRC_TOP0, 0, 3), MUX(0, "mout_aclk400_mscl", mout_group3_5800_p, SRC_TOP0, 4, 3), MUX(0, "mout_aclk400_wcore", mout_group2_5800_p, SRC_TOP0, 16, 3), @@ -553,7 +553,7 @@ static struct samsung_mux_clock exynos5800_mux_clks[] __initdata = { MUX(0, "mout_fimd1", mout_group2_p, SRC_DISP10, 4, 3), }; -static struct samsung_div_clock exynos5800_div_clks[] __initdata = { +static const struct samsung_div_clock exynos5800_div_clks[] __initconst = { DIV(CLK_DOUT_ACLK400_WCORE, "dout_aclk400_wcore", "mout_aclk400_wcore", DIV_TOP0, 16, 3), DIV(0, "dout_aclk550_cam", "mout_aclk550_cam", @@ -569,14 +569,14 @@ static struct samsung_div_clock exynos5800_div_clks[] __initdata = { DIV(0, "dout_sclk_sw", "sclk_spll", DIV_TOP9, 24, 6), }; -static struct samsung_gate_clock exynos5800_gate_clks[] __initdata = { +static const struct samsung_gate_clock exynos5800_gate_clks[] __initconst = { GATE(CLK_ACLK550_CAM, "aclk550_cam", "mout_user_aclk550_cam", GATE_BUS_TOP, 24, 0, 0), GATE(CLK_ACLK432_SCALER, "aclk432_scaler", "mout_user_aclk432_scaler", GATE_BUS_TOP, 27, 0, 0), }; -static struct samsung_mux_clock exynos5420_mux_clks[] __initdata = { +static const struct samsung_mux_clock exynos5420_mux_clks[] __initconst = { MUX(0, "sclk_bpll", mout_bpll_p, TOP_SPARE2, 0, 1), MUX(0, "mout_aclk400_wcore_bpll", mout_aclk400_wcore_bpll_p, TOP_SPARE2, 4, 1), @@ -606,12 +606,12 @@ static struct samsung_mux_clock exynos5420_mux_clks[] __initdata = { MUX(0, "mout_fimd1", mout_group3_p, SRC_DISP10, 4, 1), }; -static struct samsung_div_clock exynos5420_div_clks[] __initdata = { +static const struct samsung_div_clock exynos5420_div_clks[] __initconst = { DIV(CLK_DOUT_ACLK400_WCORE, "dout_aclk400_wcore", "mout_aclk400_wcore_bpll", DIV_TOP0, 16, 3), }; -static struct samsung_mux_clock exynos5x_mux_clks[] __initdata = { +static const struct samsung_mux_clock exynos5x_mux_clks[] __initconst = { MUX(0, "mout_user_pclk66_gpio", mout_user_pclk66_gpio_p, SRC_TOP7, 4, 1), MUX(0, "mout_mspll_kfc", mout_mspll_cpu_p, SRC_TOP7, 8, 2), @@ -778,7 +778,7 @@ static struct samsung_mux_clock exynos5x_mux_clks[] __initdata = { MUX(0, "mout_isp_sensor", mout_group2_p, SRC_ISP, 28, 3), }; -static struct samsung_div_clock exynos5x_div_clks[] __initdata = { +static const struct samsung_div_clock exynos5x_div_clks[] __initconst = { DIV(0, "div_arm", "mout_cpu", DIV_CPU0, 0, 3), DIV(0, "sclk_apll", "mout_apll", DIV_CPU0, 24, 3), DIV(0, "armclk2", "div_arm", DIV_CPU0, 28, 3), @@ -911,7 +911,7 @@ static struct samsung_div_clock exynos5x_div_clks[] __initdata = { CLK_SET_RATE_PARENT, 0), }; -static struct samsung_gate_clock exynos5x_gate_clks[] __initdata = { +static const struct samsung_gate_clock exynos5x_gate_clks[] __initconst = { /* G2D */ GATE(CLK_MDMA0, "mdma0", "aclk266_g2d", GATE_IP_G2D, 1, 0, 0), GATE(CLK_SSS, "sss", "aclk266_g2d", GATE_IP_G2D, 2, 0, 0), -- cgit v1.2.3 From 880c81b3b6604a004d56b5975c8bed47276e8bf6 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 11 May 2016 14:02:08 +0200 Subject: clk: samsung: exynos5440: Constify all clock initializers All of initialization data can be made const. Signed-off-by: Krzysztof Kozlowski Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk-exynos5440.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/clk/samsung/clk-exynos5440.c b/drivers/clk/samsung/clk-exynos5440.c index 22c73d4a5ee3..a57d01b99b76 100644 --- a/drivers/clk/samsung/clk-exynos5440.c +++ b/drivers/clk/samsung/clk-exynos5440.c @@ -35,7 +35,7 @@ static struct samsung_fixed_rate_clock exynos5440_fixed_rate_ext_clks[] __initda }; /* fixed rate clocks */ -static struct samsung_fixed_rate_clock exynos5440_fixed_rate_clks[] __initdata = { +static const struct samsung_fixed_rate_clock exynos5440_fixed_rate_clks[] __initconst = { FRATE(0, "ppll", NULL, 0, 1000000000), FRATE(0, "usb_phy0", NULL, 0, 60000000), FRATE(0, "usb_phy1", NULL, 0, 60000000), @@ -44,26 +44,26 @@ static struct samsung_fixed_rate_clock exynos5440_fixed_rate_clks[] __initdata = }; /* fixed factor clocks */ -static struct samsung_fixed_factor_clock exynos5440_fixed_factor_clks[] __initdata = { +static const struct samsung_fixed_factor_clock exynos5440_fixed_factor_clks[] __initconst = { FFACTOR(0, "div250", "ppll", 1, 4, 0), FFACTOR(0, "div200", "ppll", 1, 5, 0), FFACTOR(0, "div125", "div250", 1, 2, 0), }; /* mux clocks */ -static struct samsung_mux_clock exynos5440_mux_clks[] __initdata = { +static const struct samsung_mux_clock exynos5440_mux_clks[] __initconst = { MUX(0, "mout_spi", mout_spi_p, MISC_DOUT1, 5, 1), MUX_A(CLK_ARM_CLK, "arm_clk", mout_armclk_p, CPU_CLK_STATUS, 0, 1, "armclk"), }; /* divider clocks */ -static struct samsung_div_clock exynos5440_div_clks[] __initdata = { +static const struct samsung_div_clock exynos5440_div_clks[] __initconst = { DIV(CLK_SPI_BAUD, "div_spi", "mout_spi", MISC_DOUT1, 3, 2), }; /* gate clocks */ -static struct samsung_gate_clock exynos5440_gate_clks[] __initdata = { +static const struct samsung_gate_clock exynos5440_gate_clks[] __initconst = { GATE(CLK_PB0_250, "pb0_250", "div250", CLKEN_OV_VAL, 3, 0, 0), GATE(CLK_PR0_250, "pr0_250", "div250", CLKEN_OV_VAL, 4, 0, 0), GATE(CLK_PR1_250, "pr1_250", "div250", CLKEN_OV_VAL, 5, 0, 0), -- cgit v1.2.3 From a3618933c167ec6cff69ebc41a2584b0d886bc3b Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 11 May 2016 14:02:09 +0200 Subject: clk: samsung: exynos7: Constify all clock initializers All of initialization data can be made const. Signed-off-by: Krzysztof Kozlowski Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk-exynos7.c | 114 +++++++++++++++++++------------------- 1 file changed, 57 insertions(+), 57 deletions(-) diff --git a/drivers/clk/samsung/clk-exynos7.c b/drivers/clk/samsung/clk-exynos7.c index 03a82da63910..5931a4140c3d 100644 --- a/drivers/clk/samsung/clk-exynos7.c +++ b/drivers/clk/samsung/clk-exynos7.c @@ -36,7 +36,7 @@ #define ENABLE_ACLK_TOPC1 0x0804 #define ENABLE_SCLK_TOPC1 0x0A04 -static struct samsung_fixed_factor_clock topc_fixed_factor_clks[] __initdata = { +static const struct samsung_fixed_factor_clock topc_fixed_factor_clks[] __initconst = { FFACTOR(0, "ffac_topc_bus0_pll_div2", "mout_topc_bus0_pll", 1, 2, 0), FFACTOR(0, "ffac_topc_bus0_pll_div4", "ffac_topc_bus0_pll_div2", 1, 2, 0), @@ -69,7 +69,7 @@ PNAME(mout_topc_mfc_pll_half_p) = { "mout_topc_mfc_pll", PNAME(mout_topc_bus0_pll_out_p) = {"mout_topc_bus0_pll", "ffac_topc_bus0_pll_div2"}; -static unsigned long topc_clk_regs[] __initdata = { +static const unsigned long topc_clk_regs[] __initconst = { CC_PLL_LOCK, BUS0_PLL_LOCK, BUS1_DPLL_LOCK, @@ -89,7 +89,7 @@ static unsigned long topc_clk_regs[] __initdata = { DIV_TOPC3, }; -static struct samsung_mux_clock topc_mux_clks[] __initdata = { +static const struct samsung_mux_clock topc_mux_clks[] __initconst = { MUX(0, "mout_topc_bus0_pll", mout_topc_bus0_pll_ctrl_p, MUX_SEL_TOPC0, 0, 1), MUX(0, "mout_topc_bus1_pll", mout_topc_bus1_pll_ctrl_p, @@ -118,7 +118,7 @@ static struct samsung_mux_clock topc_mux_clks[] __initdata = { MUX(0, "mout_aclk_peris_66", mout_topc_group2, MUX_SEL_TOPC3, 24, 2), }; -static struct samsung_div_clock topc_div_clks[] __initdata = { +static const struct samsung_div_clock topc_div_clks[] __initconst = { DIV(DOUT_ACLK_CCORE_133, "dout_aclk_ccore_133", "mout_aclk_ccore_133", DIV_TOPC0, 4, 4), @@ -139,12 +139,12 @@ static struct samsung_div_clock topc_div_clks[] __initdata = { DIV_TOPC3, 28, 4), }; -static struct samsung_pll_rate_table pll1460x_24mhz_tbl[] __initdata = { +static const struct samsung_pll_rate_table pll1460x_24mhz_tbl[] __initconst = { PLL_36XX_RATE(491520000, 20, 1, 0, 31457), {}, }; -static struct samsung_gate_clock topc_gate_clks[] __initdata = { +static const struct samsung_gate_clock topc_gate_clks[] __initconst = { GATE(ACLK_CCORE_133, "aclk_ccore_133", "dout_aclk_ccore_133", ENABLE_ACLK_TOPC0, 4, CLK_IS_CRITICAL, 0), @@ -174,7 +174,7 @@ static struct samsung_gate_clock topc_gate_clks[] __initdata = { ENABLE_SCLK_TOPC1, 0, 0, 0), }; -static struct samsung_pll_clock topc_pll_clks[] __initdata = { +static const struct samsung_pll_clock topc_pll_clks[] __initconst = { PLL(pll_1451x, 0, "fout_bus0_pll", "fin_pll", BUS0_PLL_LOCK, BUS0_PLL_CON0, NULL), PLL(pll_1452x, 0, "fout_cc_pll", "fin_pll", CC_PLL_LOCK, @@ -187,7 +187,7 @@ static struct samsung_pll_clock topc_pll_clks[] __initdata = { AUD_PLL_CON0, pll1460x_24mhz_tbl), }; -static struct samsung_cmu_info topc_cmu_info __initdata = { +static const struct samsung_cmu_info topc_cmu_info __initconst = { .pll_clks = topc_pll_clks, .nr_pll_clks = ARRAY_SIZE(topc_pll_clks), .mux_clks = topc_mux_clks, @@ -256,7 +256,7 @@ PNAME(mout_top0_group3) = {"ioclk_audiocdclk0", PNAME(mout_top0_group4) = {"ioclk_audiocdclk1", "mout_top0_aud_pll_user", "mout_top0_bus0_pll_half", "mout_top0_bus1_pll_half"}; -static unsigned long top0_clk_regs[] __initdata = { +static const unsigned long top0_clk_regs[] __initconst = { MUX_SEL_TOP00, MUX_SEL_TOP01, MUX_SEL_TOP03, @@ -275,7 +275,7 @@ static unsigned long top0_clk_regs[] __initdata = { ENABLE_SCLK_TOP0_PERIC3, }; -static struct samsung_mux_clock top0_mux_clks[] __initdata = { +static const struct samsung_mux_clock top0_mux_clks[] __initconst = { MUX(0, "mout_top0_aud_pll_user", mout_top0_aud_pll_user_p, MUX_SEL_TOP00, 0, 1), MUX(0, "mout_top0_mfc_pll_user", mout_top0_mfc_pll_user_p, @@ -315,7 +315,7 @@ static struct samsung_mux_clock top0_mux_clks[] __initdata = { MUX(0, "mout_sclk_spi4", mout_top0_group1, MUX_SEL_TOP0_PERIC3, 20, 2), }; -static struct samsung_div_clock top0_div_clks[] __initdata = { +static const struct samsung_div_clock top0_div_clks[] __initconst = { DIV(DOUT_ACLK_PERIC1, "dout_aclk_peric1_66", "mout_aclk_peric1_66", DIV_TOP03, 12, 6), DIV(DOUT_ACLK_PERIC0, "dout_aclk_peric0_66", "mout_aclk_peric0_66", @@ -338,7 +338,7 @@ static struct samsung_div_clock top0_div_clks[] __initdata = { DIV(0, "dout_sclk_spi4", "mout_sclk_spi4", DIV_TOP0_PERIC3, 20, 12), }; -static struct samsung_gate_clock top0_gate_clks[] __initdata = { +static const struct samsung_gate_clock top0_gate_clks[] __initconst = { GATE(CLK_ACLK_PERIC0_66, "aclk_peric0_66", "dout_aclk_peric0_66", ENABLE_ACLK_TOP03, 20, CLK_SET_RATE_PARENT, 0), GATE(CLK_ACLK_PERIC1_66, "aclk_peric1_66", "dout_aclk_peric1_66", @@ -372,7 +372,7 @@ static struct samsung_gate_clock top0_gate_clks[] __initdata = { ENABLE_SCLK_TOP0_PERIC3, 20, CLK_SET_RATE_PARENT, 0), }; -static struct samsung_fixed_factor_clock top0_fixed_factor_clks[] __initdata = { +static const struct samsung_fixed_factor_clock top0_fixed_factor_clks[] __initconst = { FFACTOR(0, "ffac_top0_bus0_pll_div2", "mout_top0_bus0_pll_user", 1, 2, 0), FFACTOR(0, "ffac_top0_bus1_pll_div2", "mout_top0_bus1_pll_user", @@ -381,7 +381,7 @@ static struct samsung_fixed_factor_clock top0_fixed_factor_clks[] __initdata = { FFACTOR(0, "ffac_top0_mfc_pll_div2", "mout_top0_mfc_pll_user", 1, 2, 0), }; -static struct samsung_cmu_info top0_cmu_info __initdata = { +static const struct samsung_cmu_info top0_cmu_info __initconst = { .mux_clks = top0_mux_clks, .nr_mux_clks = ARRAY_SIZE(top0_mux_clks), .div_clks = top0_div_clks, @@ -438,7 +438,7 @@ PNAME(mout_top1_group1) = {"mout_top1_bus0_pll_half", "mout_top1_bus1_pll_half", "mout_top1_cc_pll_half", "mout_top1_mfc_pll_half"}; -static unsigned long top1_clk_regs[] __initdata = { +static const unsigned long top1_clk_regs[] __initconst = { MUX_SEL_TOP10, MUX_SEL_TOP11, MUX_SEL_TOP13, @@ -455,7 +455,7 @@ static unsigned long top1_clk_regs[] __initdata = { ENABLE_SCLK_TOP1_FSYS11, }; -static struct samsung_mux_clock top1_mux_clks[] __initdata = { +static const struct samsung_mux_clock top1_mux_clks[] __initconst = { MUX(0, "mout_top1_mfc_pll_user", mout_top1_mfc_pll_user_p, MUX_SEL_TOP10, 4, 1), MUX(0, "mout_top1_cc_pll_user", mout_top1_cc_pll_user_p, @@ -494,7 +494,7 @@ static struct samsung_mux_clock top1_mux_clks[] __initdata = { MUX_SEL_TOP1_FSYS11, 24, 2), }; -static struct samsung_div_clock top1_div_clks[] __initdata = { +static const struct samsung_div_clock top1_div_clks[] __initconst = { DIV(DOUT_ACLK_FSYS1_200, "dout_aclk_fsys1_200", "mout_aclk_fsys1_200", DIV_TOP13, 24, 4), DIV(DOUT_ACLK_FSYS0_200, "dout_aclk_fsys0_200", "mout_aclk_fsys0_200", @@ -521,7 +521,7 @@ static struct samsung_div_clock top1_div_clks[] __initdata = { "mout_sclk_phy_fsys1_26m", DIV_TOP1_FSYS11, 24, 6), }; -static struct samsung_gate_clock top1_gate_clks[] __initdata = { +static const struct samsung_gate_clock top1_gate_clks[] __initconst = { GATE(CLK_SCLK_MMC2, "sclk_mmc2", "dout_sclk_mmc2", ENABLE_SCLK_TOP1_FSYS0, 16, CLK_SET_RATE_PARENT, 0), GATE(0, "sclk_usbdrd300", "dout_sclk_usbdrd300", @@ -549,7 +549,7 @@ static struct samsung_gate_clock top1_gate_clks[] __initdata = { 24, CLK_SET_RATE_PARENT, 0), }; -static struct samsung_fixed_factor_clock top1_fixed_factor_clks[] __initdata = { +static const struct samsung_fixed_factor_clock top1_fixed_factor_clks[] __initconst = { FFACTOR(0, "ffac_top1_bus0_pll_div2", "mout_top1_bus0_pll_user", 1, 2, 0), FFACTOR(0, "ffac_top1_bus1_pll_div2", "mout_top1_bus1_pll_user", @@ -558,7 +558,7 @@ static struct samsung_fixed_factor_clock top1_fixed_factor_clks[] __initdata = { FFACTOR(0, "ffac_top1_mfc_pll_div2", "mout_top1_mfc_pll_user", 1, 2, 0), }; -static struct samsung_cmu_info top1_cmu_info __initdata = { +static const struct samsung_cmu_info top1_cmu_info __initconst = { .mux_clks = top1_mux_clks, .nr_mux_clks = ARRAY_SIZE(top1_mux_clks), .div_clks = top1_div_clks, @@ -592,22 +592,22 @@ CLK_OF_DECLARE(exynos7_clk_top1, "samsung,exynos7-clock-top1", */ PNAME(mout_aclk_ccore_133_user_p) = { "fin_pll", "aclk_ccore_133" }; -static unsigned long ccore_clk_regs[] __initdata = { +static const unsigned long ccore_clk_regs[] __initconst = { MUX_SEL_CCORE, ENABLE_PCLK_CCORE, }; -static struct samsung_mux_clock ccore_mux_clks[] __initdata = { +static const struct samsung_mux_clock ccore_mux_clks[] __initconst = { MUX(0, "mout_aclk_ccore_133_user", mout_aclk_ccore_133_user_p, MUX_SEL_CCORE, 1, 1), }; -static struct samsung_gate_clock ccore_gate_clks[] __initdata = { +static const struct samsung_gate_clock ccore_gate_clks[] __initconst = { GATE(PCLK_RTC, "pclk_rtc", "mout_aclk_ccore_133_user", ENABLE_PCLK_CCORE, 8, 0, 0), }; -static struct samsung_cmu_info ccore_cmu_info __initdata = { +static const struct samsung_cmu_info ccore_cmu_info __initconst = { .mux_clks = ccore_mux_clks, .nr_mux_clks = ARRAY_SIZE(ccore_mux_clks), .gate_clks = ccore_gate_clks, @@ -634,20 +634,20 @@ CLK_OF_DECLARE(exynos7_clk_ccore, "samsung,exynos7-clock-ccore", PNAME(mout_aclk_peric0_66_user_p) = { "fin_pll", "aclk_peric0_66" }; PNAME(mout_sclk_uart0_user_p) = { "fin_pll", "sclk_uart0" }; -static unsigned long peric0_clk_regs[] __initdata = { +static const unsigned long peric0_clk_regs[] __initconst = { MUX_SEL_PERIC0, ENABLE_PCLK_PERIC0, ENABLE_SCLK_PERIC0, }; -static struct samsung_mux_clock peric0_mux_clks[] __initdata = { +static const struct samsung_mux_clock peric0_mux_clks[] __initconst = { MUX(0, "mout_aclk_peric0_66_user", mout_aclk_peric0_66_user_p, MUX_SEL_PERIC0, 0, 1), MUX(0, "mout_sclk_uart0_user", mout_sclk_uart0_user_p, MUX_SEL_PERIC0, 16, 1), }; -static struct samsung_gate_clock peric0_gate_clks[] __initdata = { +static const struct samsung_gate_clock peric0_gate_clks[] __initconst = { GATE(PCLK_HSI2C0, "pclk_hsi2c0", "mout_aclk_peric0_66_user", ENABLE_PCLK_PERIC0, 8, 0, 0), GATE(PCLK_HSI2C1, "pclk_hsi2c1", "mout_aclk_peric0_66_user", @@ -674,7 +674,7 @@ static struct samsung_gate_clock peric0_gate_clks[] __initdata = { GATE(SCLK_PWM, "sclk_pwm", "fin_pll", ENABLE_SCLK_PERIC0, 21, 0, 0), }; -static struct samsung_cmu_info peric0_cmu_info __initdata = { +static const struct samsung_cmu_info peric0_cmu_info __initconst = { .mux_clks = peric0_mux_clks, .nr_mux_clks = ARRAY_SIZE(peric0_mux_clks), .gate_clks = peric0_gate_clks, @@ -710,7 +710,7 @@ PNAME(mout_sclk_spi2_user_p) = { "fin_pll", "sclk_spi2" }; PNAME(mout_sclk_spi3_user_p) = { "fin_pll", "sclk_spi3" }; PNAME(mout_sclk_spi4_user_p) = { "fin_pll", "sclk_spi4" }; -static unsigned long peric1_clk_regs[] __initdata = { +static const unsigned long peric1_clk_regs[] __initconst = { MUX_SEL_PERIC10, MUX_SEL_PERIC11, MUX_SEL_PERIC12, @@ -718,7 +718,7 @@ static unsigned long peric1_clk_regs[] __initdata = { ENABLE_SCLK_PERIC10, }; -static struct samsung_mux_clock peric1_mux_clks[] __initdata = { +static const struct samsung_mux_clock peric1_mux_clks[] __initconst = { MUX(0, "mout_aclk_peric1_66_user", mout_aclk_peric1_66_user_p, MUX_SEL_PERIC10, 0, 1), @@ -740,7 +740,7 @@ static struct samsung_mux_clock peric1_mux_clks[] __initdata = { MUX_SEL_PERIC11, 28, 1), }; -static struct samsung_gate_clock peric1_gate_clks[] __initdata = { +static const struct samsung_gate_clock peric1_gate_clks[] __initconst = { GATE(PCLK_HSI2C2, "pclk_hsi2c2", "mout_aclk_peric1_66_user", ENABLE_PCLK_PERIC1, 4, 0, 0), GATE(PCLK_HSI2C3, "pclk_hsi2c3", "mout_aclk_peric1_66_user", @@ -798,7 +798,7 @@ static struct samsung_gate_clock peric1_gate_clks[] __initdata = { ENABLE_SCLK_PERIC10, 19, CLK_SET_RATE_PARENT, 0), }; -static struct samsung_cmu_info peric1_cmu_info __initdata = { +static const struct samsung_cmu_info peric1_cmu_info __initconst = { .mux_clks = peric1_mux_clks, .nr_mux_clks = ARRAY_SIZE(peric1_mux_clks), .gate_clks = peric1_gate_clks, @@ -826,7 +826,7 @@ CLK_OF_DECLARE(exynos7_clk_peric1, "samsung,exynos7-clock-peric1", /* List of parent clocks for Muxes in CMU_PERIS */ PNAME(mout_aclk_peris_66_user_p) = { "fin_pll", "aclk_peris_66" }; -static unsigned long peris_clk_regs[] __initdata = { +static const unsigned long peris_clk_regs[] __initconst = { MUX_SEL_PERIS, ENABLE_PCLK_PERIS, ENABLE_PCLK_PERIS_SECURE_CHIPID, @@ -834,12 +834,12 @@ static unsigned long peris_clk_regs[] __initdata = { ENABLE_SCLK_PERIS_SECURE_CHIPID, }; -static struct samsung_mux_clock peris_mux_clks[] __initdata = { +static const struct samsung_mux_clock peris_mux_clks[] __initconst = { MUX(0, "mout_aclk_peris_66_user", mout_aclk_peris_66_user_p, MUX_SEL_PERIS, 0, 1), }; -static struct samsung_gate_clock peris_gate_clks[] __initdata = { +static const struct samsung_gate_clock peris_gate_clks[] __initconst = { GATE(PCLK_WDT, "pclk_wdt", "mout_aclk_peris_66_user", ENABLE_PCLK_PERIS, 6, 0, 0), GATE(PCLK_TMU, "pclk_tmu_apbif", "mout_aclk_peris_66_user", @@ -853,7 +853,7 @@ static struct samsung_gate_clock peris_gate_clks[] __initdata = { GATE(SCLK_TMU, "sclk_tmu", "fin_pll", ENABLE_SCLK_PERIS, 10, 0, 0), }; -static struct samsung_cmu_info peris_cmu_info __initdata = { +static const struct samsung_cmu_info peris_cmu_info __initconst = { .mux_clks = peris_mux_clks, .nr_mux_clks = ARRAY_SIZE(peris_mux_clks), .gate_clks = peris_gate_clks, @@ -894,12 +894,12 @@ PNAME(mout_phyclk_usbdrd300_udrd30_pipe_pclk_user_p) = { "fin_pll", "phyclk_usbdrd300_udrd30_pipe_pclk" }; /* fixed rate clocks used in the FSYS0 block */ -static struct samsung_fixed_rate_clock fixed_rate_clks_fsys0[] __initdata = { +static const struct samsung_fixed_rate_clock fixed_rate_clks_fsys0[] __initconst = { FRATE(0, "phyclk_usbdrd300_udrd30_phyclock", NULL, 0, 60000000), FRATE(0, "phyclk_usbdrd300_udrd30_pipe_pclk", NULL, 0, 125000000), }; -static unsigned long fsys0_clk_regs[] __initdata = { +static const unsigned long fsys0_clk_regs[] __initconst = { MUX_SEL_FSYS00, MUX_SEL_FSYS01, MUX_SEL_FSYS02, @@ -910,7 +910,7 @@ static unsigned long fsys0_clk_regs[] __initdata = { ENABLE_SCLK_FSYS04, }; -static struct samsung_mux_clock fsys0_mux_clks[] __initdata = { +static const struct samsung_mux_clock fsys0_mux_clks[] __initconst = { MUX(0, "mout_aclk_fsys0_200_user", mout_aclk_fsys0_200_user_p, MUX_SEL_FSYS00, 24, 1), @@ -927,7 +927,7 @@ static struct samsung_mux_clock fsys0_mux_clks[] __initdata = { MUX_SEL_FSYS02, 28, 1), }; -static struct samsung_gate_clock fsys0_gate_clks[] __initdata = { +static const struct samsung_gate_clock fsys0_gate_clks[] __initconst = { GATE(ACLK_PDMA1, "aclk_pdma1", "mout_aclk_fsys0_200_user", ENABLE_ACLK_FSYS00, 3, 0, 0), GATE(ACLK_PDMA0, "aclk_pdma0", "mout_aclk_fsys0_200_user", @@ -961,7 +961,7 @@ static struct samsung_gate_clock fsys0_gate_clks[] __initdata = { ENABLE_SCLK_FSYS04, 28, 0, 0), }; -static struct samsung_cmu_info fsys0_cmu_info __initdata = { +static const struct samsung_cmu_info fsys0_cmu_info __initconst = { .fixed_clks = fixed_rate_clks_fsys0, .nr_fixed_clks = ARRAY_SIZE(fixed_rate_clks_fsys0), .mux_clks = fsys0_mux_clks, @@ -1006,7 +1006,7 @@ PNAME(mout_phyclk_ufs20_rx0_user_p) = { "fin_pll", "phyclk_ufs20_rx0_symbol" }; PNAME(mout_phyclk_ufs20_rx1_user_p) = { "fin_pll", "phyclk_ufs20_rx1_symbol" }; /* fixed rate clocks used in the FSYS1 block */ -static struct samsung_fixed_rate_clock fixed_rate_clks_fsys1[] __initdata = { +static const struct samsung_fixed_rate_clock fixed_rate_clks_fsys1[] __initconst = { FRATE(PHYCLK_UFS20_TX0_SYMBOL, "phyclk_ufs20_tx0_symbol", NULL, 0, 300000000), FRATE(PHYCLK_UFS20_RX0_SYMBOL, "phyclk_ufs20_rx0_symbol", NULL, @@ -1015,7 +1015,7 @@ static struct samsung_fixed_rate_clock fixed_rate_clks_fsys1[] __initdata = { 0, 300000000), }; -static unsigned long fsys1_clk_regs[] __initdata = { +static const unsigned long fsys1_clk_regs[] __initconst = { MUX_SEL_FSYS10, MUX_SEL_FSYS11, MUX_SEL_FSYS12, @@ -1027,7 +1027,7 @@ static unsigned long fsys1_clk_regs[] __initdata = { ENABLE_SCLK_FSYS13, }; -static struct samsung_mux_clock fsys1_mux_clks[] __initdata = { +static const struct samsung_mux_clock fsys1_mux_clks[] __initconst = { MUX(MOUT_FSYS1_PHYCLK_SEL1, "mout_fsys1_phyclk_sel1", mout_fsys1_group_p, MUX_SEL_FSYS10, 16, 2), MUX(0, "mout_fsys1_phyclk_sel0", mout_fsys1_group_p, @@ -1050,12 +1050,12 @@ static struct samsung_mux_clock fsys1_mux_clks[] __initdata = { mout_phyclk_ufs20_tx0_user_p, MUX_SEL_FSYS12, 28, 1), }; -static struct samsung_div_clock fsys1_div_clks[] __initdata = { +static const struct samsung_div_clock fsys1_div_clks[] __initconst = { DIV(DOUT_PCLK_FSYS1, "dout_pclk_fsys1", "mout_aclk_fsys1_200_user", DIV_FSYS1, 0, 2), }; -static struct samsung_gate_clock fsys1_gate_clks[] __initdata = { +static const struct samsung_gate_clock fsys1_gate_clks[] __initconst = { GATE(SCLK_UFSUNIPRO20_USER, "sclk_ufsunipro20_user", "mout_sclk_ufsunipro20_user", ENABLE_SCLK_FSYS11, 20, 0, 0), @@ -1090,7 +1090,7 @@ static struct samsung_gate_clock fsys1_gate_clks[] __initdata = { ENABLE_SCLK_FSYS13, 24, CLK_IGNORE_UNUSED, 0), }; -static struct samsung_cmu_info fsys1_cmu_info __initdata = { +static const struct samsung_cmu_info fsys1_cmu_info __initconst = { .fixed_clks = fixed_rate_clks_fsys1, .nr_fixed_clks = ARRAY_SIZE(fixed_rate_clks_fsys1), .mux_clks = fsys1_mux_clks, @@ -1120,22 +1120,22 @@ CLK_OF_DECLARE(exynos7_clk_fsys1, "samsung,exynos7-clock-fsys1", /* List of parent clocks for Muxes in CMU_MSCL */ PNAME(mout_aclk_mscl_532_user_p) = { "fin_pll", "aclk_mscl_532" }; -static unsigned long mscl_clk_regs[] __initdata = { +static const unsigned long mscl_clk_regs[] __initconst = { MUX_SEL_MSCL, DIV_MSCL, ENABLE_ACLK_MSCL, ENABLE_PCLK_MSCL, }; -static struct samsung_mux_clock mscl_mux_clks[] __initdata = { +static const struct samsung_mux_clock mscl_mux_clks[] __initconst = { MUX(USERMUX_ACLK_MSCL_532, "usermux_aclk_mscl_532", mout_aclk_mscl_532_user_p, MUX_SEL_MSCL, 0, 1), }; -static struct samsung_div_clock mscl_div_clks[] __initdata = { +static const struct samsung_div_clock mscl_div_clks[] __initconst = { DIV(DOUT_PCLK_MSCL, "dout_pclk_mscl", "usermux_aclk_mscl_532", DIV_MSCL, 0, 3), }; -static struct samsung_gate_clock mscl_gate_clks[] __initdata = { +static const struct samsung_gate_clock mscl_gate_clks[] __initconst = { GATE(ACLK_MSCL_0, "aclk_mscl_0", "usermux_aclk_mscl_532", ENABLE_ACLK_MSCL, 31, 0, 0), @@ -1205,7 +1205,7 @@ static struct samsung_gate_clock mscl_gate_clks[] __initdata = { ENABLE_PCLK_MSCL, 20, 0, 0), }; -static struct samsung_cmu_info mscl_cmu_info __initdata = { +static const struct samsung_cmu_info mscl_cmu_info __initconst = { .mux_clks = mscl_mux_clks, .nr_mux_clks = ARRAY_SIZE(mscl_mux_clks), .div_clks = mscl_div_clks, @@ -1239,7 +1239,7 @@ CLK_OF_DECLARE(exynos7_clk_mscl, "samsung,exynos7-clock-mscl", PNAME(mout_aud_pll_user_p) = { "fin_pll", "fout_aud_pll" }; PNAME(mout_aud_group_p) = { "dout_aud_cdclk", "ioclk_audiocdclk0" }; -static unsigned long aud_clk_regs[] __initdata = { +static const unsigned long aud_clk_regs[] __initconst = { MUX_SEL_AUD, DIV_AUD0, DIV_AUD1, @@ -1248,13 +1248,13 @@ static unsigned long aud_clk_regs[] __initdata = { ENABLE_SCLK_AUD, }; -static struct samsung_mux_clock aud_mux_clks[] __initdata = { +static const struct samsung_mux_clock aud_mux_clks[] __initconst = { MUX(0, "mout_sclk_i2s", mout_aud_group_p, MUX_SEL_AUD, 12, 1), MUX(0, "mout_sclk_pcm", mout_aud_group_p, MUX_SEL_AUD, 16, 1), MUX(0, "mout_aud_pll_user", mout_aud_pll_user_p, MUX_SEL_AUD, 20, 1), }; -static struct samsung_div_clock aud_div_clks[] __initdata = { +static const struct samsung_div_clock aud_div_clks[] __initconst = { DIV(0, "dout_aud_ca5", "mout_aud_pll_user", DIV_AUD0, 0, 4), DIV(0, "dout_aclk_aud", "dout_aud_ca5", DIV_AUD0, 4, 4), DIV(0, "dout_aud_pclk_dbg", "dout_aud_ca5", DIV_AUD0, 8, 4), @@ -1266,7 +1266,7 @@ static struct samsung_div_clock aud_div_clks[] __initdata = { DIV(0, "dout_aud_cdclk", "mout_aud_pll_user", DIV_AUD1, 24, 4), }; -static struct samsung_gate_clock aud_gate_clks[] __initdata = { +static const struct samsung_gate_clock aud_gate_clks[] __initconst = { GATE(SCLK_PCM, "sclk_pcm", "dout_sclk_pcm", ENABLE_SCLK_AUD, 27, CLK_SET_RATE_PARENT, 0), GATE(SCLK_I2S, "sclk_i2s", "dout_sclk_i2s", @@ -1294,7 +1294,7 @@ static struct samsung_gate_clock aud_gate_clks[] __initdata = { GATE(ACLK_ADMA, "aclk_dmac", "dout_aclk_aud", ENABLE_ACLK_AUD, 31, 0, 0), }; -static struct samsung_cmu_info aud_cmu_info __initdata = { +static const struct samsung_cmu_info aud_cmu_info __initconst = { .mux_clks = aud_mux_clks, .nr_mux_clks = ARRAY_SIZE(aud_mux_clks), .div_clks = aud_div_clks, -- cgit v1.2.3 From a6cd1fbc4b9d96becf7aa884f98e8a260da5301c Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 11 May 2016 14:02:10 +0200 Subject: clk: samsung: exynos5433: Constify all clock initializers All of initialization data can be made const. Signed-off-by: Krzysztof Kozlowski Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk-exynos5433.c | 240 +++++++++++++++++------------------ 1 file changed, 120 insertions(+), 120 deletions(-) diff --git a/drivers/clk/samsung/clk-exynos5433.c b/drivers/clk/samsung/clk-exynos5433.c index 128527b8fbeb..f202a51ff99b 100644 --- a/drivers/clk/samsung/clk-exynos5433.c +++ b/drivers/clk/samsung/clk-exynos5433.c @@ -108,7 +108,7 @@ #define ENABLE_CMU_TOP 0x0c00 #define ENABLE_CMU_TOP_DIV_STAT 0x0c04 -static unsigned long top_clk_regs[] __initdata = { +static const unsigned long top_clk_regs[] __initconst = { ISP_PLL_LOCK, AUD_PLL_LOCK, ISP_PLL_CON0, @@ -218,11 +218,11 @@ PNAME(mout_sclk_audio0_p) = { "ioclk_audiocdclk0", "oscclk", PNAME(mout_sclk_hdmi_spdif_p) = { "sclk_audio1", "ioclk_spdif_extclk", }; -static struct samsung_fixed_factor_clock top_fixed_factor_clks[] __initdata = { +static const struct samsung_fixed_factor_clock top_fixed_factor_clks[] __initconst = { FFACTOR(0, "oscclk_efuse_common", "oscclk", 1, 1, 0), }; -static struct samsung_fixed_rate_clock top_fixed_clks[] __initdata = { +static const struct samsung_fixed_rate_clock top_fixed_clks[] __initconst = { /* Xi2s{0|1}CDCLK input clock for I2S/PCM */ FRATE(0, "ioclk_audiocdclk1", NULL, 0, 100000000), FRATE(0, "ioclk_audiocdclk0", NULL, 0, 100000000), @@ -238,7 +238,7 @@ static struct samsung_fixed_rate_clock top_fixed_clks[] __initdata = { FRATE(0, "ioclk_i2s1_bclk_in", NULL, 0, 12288000), }; -static struct samsung_mux_clock top_mux_clks[] __initdata = { +static const struct samsung_mux_clock top_mux_clks[] __initconst = { /* MUX_SEL_TOP0 */ MUX(CLK_MOUT_AUD_PLL, "mout_aud_pll", mout_aud_pll_p, MUX_SEL_TOP0, 4, 1), @@ -374,7 +374,7 @@ static struct samsung_mux_clock top_mux_clks[] __initdata = { mout_sclk_hdmi_spdif_p, MUX_SEL_TOP_DISP, 0, 1), }; -static struct samsung_div_clock top_div_clks[] __initdata = { +static const struct samsung_div_clock top_div_clks[] __initconst = { /* DIV_TOP0 */ DIV(CLK_DIV_ACLK_CAM1_333, "div_aclk_cam1_333", "mout_aclk_cam1_333", DIV_TOP0, 28, 3), @@ -538,7 +538,7 @@ static struct samsung_div_clock top_div_clks[] __initdata = { DIV_TOP_PERIC4, 0, 4), }; -static struct samsung_gate_clock top_gate_clks[] __initdata = { +static const struct samsung_gate_clock top_gate_clks[] __initconst = { /* ENABLE_ACLK_TOP */ GATE(CLK_ACLK_G3D_400, "aclk_g3d_400", "div_aclk_g3d_400", ENABLE_ACLK_TOP, 30, 0, 0), @@ -693,7 +693,7 @@ static struct samsung_gate_clock top_gate_clks[] __initdata = { * ATLAS_PLL & APOLLO_PLL & MEM0_PLL & MEM1_PLL & BUS_PLL & MFC_PLL * & MPHY_PLL & G3D_PLL & DISP_PLL & ISP_PLL */ -static struct samsung_pll_rate_table exynos5443_pll_rates[] = { +static const struct samsung_pll_rate_table exynos5443_pll_rates[] = { PLL_35XX_RATE(2500000000U, 625, 6, 0), PLL_35XX_RATE(2400000000U, 500, 5, 0), PLL_35XX_RATE(2300000000U, 575, 6, 0), @@ -744,7 +744,7 @@ static struct samsung_pll_rate_table exynos5443_pll_rates[] = { }; /* AUD_PLL */ -static struct samsung_pll_rate_table exynos5443_aud_pll_rates[] = { +static const struct samsung_pll_rate_table exynos5443_aud_pll_rates[] = { PLL_36XX_RATE(400000000U, 200, 3, 2, 0), PLL_36XX_RATE(393216000U, 197, 3, 2, -25690), PLL_36XX_RATE(384000000U, 128, 2, 2, 0), @@ -757,14 +757,14 @@ static struct samsung_pll_rate_table exynos5443_aud_pll_rates[] = { { /* sentinel */ } }; -static struct samsung_pll_clock top_pll_clks[] __initdata = { +static const struct samsung_pll_clock top_pll_clks[] __initconst = { PLL(pll_35xx, CLK_FOUT_ISP_PLL, "fout_isp_pll", "oscclk", ISP_PLL_LOCK, ISP_PLL_CON0, exynos5443_pll_rates), PLL(pll_36xx, CLK_FOUT_AUD_PLL, "fout_aud_pll", "oscclk", AUD_PLL_LOCK, AUD_PLL_CON0, exynos5443_aud_pll_rates), }; -static struct samsung_cmu_info top_cmu_info __initdata = { +static const struct samsung_cmu_info top_cmu_info __initconst = { .pll_clks = top_pll_clks, .nr_pll_clks = ARRAY_SIZE(top_pll_clks), .mux_clks = top_mux_clks, @@ -800,7 +800,7 @@ CLK_OF_DECLARE(exynos5433_cmu_top, "samsung,exynos5433-cmu-top", #define DIV_CPIF 0x0600 #define ENABLE_SCLK_CPIF 0x0a00 -static unsigned long cpif_clk_regs[] __initdata = { +static const unsigned long cpif_clk_regs[] __initconst = { MPHY_PLL_LOCK, MPHY_PLL_CON0, MPHY_PLL_CON1, @@ -813,24 +813,24 @@ static unsigned long cpif_clk_regs[] __initdata = { /* list of all parent clock list */ PNAME(mout_mphy_pll_p) = { "oscclk", "fout_mphy_pll", }; -static struct samsung_pll_clock cpif_pll_clks[] __initdata = { +static const struct samsung_pll_clock cpif_pll_clks[] __initconst = { PLL(pll_35xx, CLK_FOUT_MPHY_PLL, "fout_mphy_pll", "oscclk", MPHY_PLL_LOCK, MPHY_PLL_CON0, exynos5443_pll_rates), }; -static struct samsung_mux_clock cpif_mux_clks[] __initdata = { +static const struct samsung_mux_clock cpif_mux_clks[] __initconst = { /* MUX_SEL_CPIF0 */ MUX(CLK_MOUT_MPHY_PLL, "mout_mphy_pll", mout_mphy_pll_p, MUX_SEL_CPIF0, 0, 1), }; -static struct samsung_div_clock cpif_div_clks[] __initdata = { +static const struct samsung_div_clock cpif_div_clks[] __initconst = { /* DIV_CPIF */ DIV(CLK_DIV_SCLK_MPHY, "div_sclk_mphy", "mout_mphy_pll", DIV_CPIF, 0, 6), }; -static struct samsung_gate_clock cpif_gate_clks[] __initdata = { +static const struct samsung_gate_clock cpif_gate_clks[] __initconst = { /* ENABLE_SCLK_CPIF */ GATE(CLK_SCLK_MPHY_PLL, "sclk_mphy_pll", "mout_mphy_pll", ENABLE_SCLK_CPIF, 9, 0, 0), @@ -838,7 +838,7 @@ static struct samsung_gate_clock cpif_gate_clks[] __initdata = { ENABLE_SCLK_CPIF, 4, 0, 0), }; -static struct samsung_cmu_info cpif_cmu_info __initdata = { +static const struct samsung_cmu_info cpif_cmu_info __initconst = { .pll_clks = cpif_pll_clks, .nr_pll_clks = ARRAY_SIZE(cpif_pll_clks), .mux_clks = cpif_mux_clks, @@ -939,7 +939,7 @@ CLK_OF_DECLARE(exynos5433_cmu_cpif, "samsung,exynos5433-cmu-cpif", #define PAUSE 0x1008 #define DDRPHY_LOCK_CTRL 0x100c -static unsigned long mif_clk_regs[] __initdata = { +static const unsigned long mif_clk_regs[] __initconst = { MEM0_PLL_LOCK, MEM1_PLL_LOCK, BUS_PLL_LOCK, @@ -1004,7 +1004,7 @@ static unsigned long mif_clk_regs[] __initdata = { DDRPHY_LOCK_CTRL, }; -static struct samsung_pll_clock mif_pll_clks[] __initdata = { +static const struct samsung_pll_clock mif_pll_clks[] __initconst = { PLL(pll_35xx, CLK_FOUT_MEM0_PLL, "fout_mem0_pll", "oscclk", MEM0_PLL_LOCK, MEM0_PLL_CON0, exynos5443_pll_rates), PLL(pll_35xx, CLK_FOUT_MEM1_PLL, "fout_mem1_pll", "oscclk", @@ -1065,7 +1065,7 @@ PNAME(mout_sclk_decon_tv_vclk_b_p) = { "mout_sclk_decon_tv_vclk_a", PNAME(mout_sclk_dsim1_c_p) = { "mout_sclk_dsim1_b", "sclk_mphy_pll", }; PNAME(mout_sclk_dsim1_b_p) = { "mout_sclk_dsim1_a", "mout_mfc_pll_div2",}; -static struct samsung_fixed_factor_clock mif_fixed_factor_clks[] __initdata = { +static const struct samsung_fixed_factor_clock mif_fixed_factor_clks[] __initconst = { /* dout_{mfc|bus|mem1|mem0}_pll is half fixed rate from parent mux */ FFACTOR(CLK_DOUT_MFC_PLL, "dout_mfc_pll", "mout_mfc_pll", 1, 1, 0), FFACTOR(CLK_DOUT_BUS_PLL, "dout_bus_pll", "mout_bus_pll", 1, 1, 0), @@ -1073,7 +1073,7 @@ static struct samsung_fixed_factor_clock mif_fixed_factor_clks[] __initdata = { FFACTOR(CLK_DOUT_MEM0_PLL, "dout_mem0_pll", "mout_mem0_pll", 1, 1, 0), }; -static struct samsung_mux_clock mif_mux_clks[] __initdata = { +static const struct samsung_mux_clock mif_mux_clks[] __initconst = { /* MUX_SEL_MIF0 */ MUX(CLK_MOUT_MFC_PLL_DIV2, "mout_mfc_pll_div2", mout_mfc_pll_div2_p, MUX_SEL_MIF0, 28, 1), @@ -1169,7 +1169,7 @@ static struct samsung_mux_clock mif_mux_clks[] __initdata = { MUX_SEL_MIF7, 0, 1), }; -static struct samsung_div_clock mif_div_clks[] __initdata = { +static const struct samsung_div_clock mif_div_clks[] __initconst = { /* DIV_MIF1 */ DIV(CLK_DIV_SCLK_HPM_MIF, "div_sclk_hpm_mif", "div_clk2x_phy", DIV_MIF1, 16, 2), @@ -1223,7 +1223,7 @@ static struct samsung_div_clock mif_div_clks[] __initdata = { 0, 3), }; -static struct samsung_gate_clock mif_gate_clks[] __initdata = { +static const struct samsung_gate_clock mif_gate_clks[] __initconst = { /* ENABLE_ACLK_MIF0 */ GATE(CLK_CLK2X_PHY1, "clk2k_phy1", "div_clk2x_phy", ENABLE_ACLK_MIF0, 19, CLK_IGNORE_UNUSED, 0), @@ -1486,7 +1486,7 @@ static struct samsung_gate_clock mif_gate_clks[] __initdata = { ENABLE_SCLK_MIF, 0, CLK_IGNORE_UNUSED, 0), }; -static struct samsung_cmu_info mif_cmu_info __initdata = { +static const struct samsung_cmu_info mif_cmu_info __initconst = { .pll_clks = mif_pll_clks, .nr_pll_clks = ARRAY_SIZE(mif_pll_clks), .mux_clks = mif_mux_clks, @@ -1522,7 +1522,7 @@ CLK_OF_DECLARE(exynos5433_cmu_mif, "samsung,exynos5433-cmu-mif", #define ENABLE_IP_PERIC1 0x0B04 #define ENABLE_IP_PERIC2 0x0B08 -static unsigned long peric_clk_regs[] __initdata = { +static const unsigned long peric_clk_regs[] __initconst = { DIV_PERIC, ENABLE_ACLK_PERIC, ENABLE_PCLK_PERIC0, @@ -1533,13 +1533,13 @@ static unsigned long peric_clk_regs[] __initdata = { ENABLE_IP_PERIC2, }; -static struct samsung_div_clock peric_div_clks[] __initdata = { +static const struct samsung_div_clock peric_div_clks[] __initconst = { /* DIV_PERIC */ DIV(CLK_DIV_SCLK_SCI, "div_sclk_sci", "oscclk", DIV_PERIC, 4, 4), DIV(CLK_DIV_SCLK_SC_IN, "div_sclk_sc_in", "oscclk", DIV_PERIC, 0, 4), }; -static struct samsung_gate_clock peric_gate_clks[] __initdata = { +static const struct samsung_gate_clock peric_gate_clks[] __initconst = { /* ENABLE_ACLK_PERIC */ GATE(CLK_ACLK_AHB2APB_PERIC2P, "aclk_ahb2apb_peric2p", "aclk_peric_66", ENABLE_ACLK_PERIC, 3, CLK_IGNORE_UNUSED, 0), @@ -1681,7 +1681,7 @@ static struct samsung_gate_clock peric_gate_clks[] __initdata = { ENABLE_SCLK_PERIC, 0, CLK_SET_RATE_PARENT, 0), }; -static struct samsung_cmu_info peric_cmu_info __initdata = { +static const struct samsung_cmu_info peric_cmu_info __initconst = { .div_clks = peric_div_clks, .nr_div_clks = ARRAY_SIZE(peric_div_clks), .gate_clks = peric_gate_clks, @@ -1728,7 +1728,7 @@ CLK_OF_DECLARE(exynos5433_cmu_peric, "samsung,exynos5433-cmu-peric", #define ENABLE_IP_PERIS_SECURE_ANTIBRK_CNT 0x0b1c #define ENABLE_IP_PERIS_SECURE_OTP_CON 0x0b20 -static unsigned long peris_clk_regs[] __initdata = { +static const unsigned long peris_clk_regs[] __initconst = { ENABLE_ACLK_PERIS, ENABLE_PCLK_PERIS, ENABLE_PCLK_PERIS_SECURE_TZPC, @@ -1756,7 +1756,7 @@ static unsigned long peris_clk_regs[] __initdata = { ENABLE_IP_PERIS_SECURE_OTP_CON, }; -static struct samsung_gate_clock peris_gate_clks[] __initdata = { +static const struct samsung_gate_clock peris_gate_clks[] __initconst = { /* ENABLE_ACLK_PERIS */ GATE(CLK_ACLK_AHB2APB_PERIS1P, "aclk_ahb2apb_peris1p", "aclk_peris_66", ENABLE_ACLK_PERIS, 2, CLK_IGNORE_UNUSED, 0), @@ -1875,7 +1875,7 @@ static struct samsung_gate_clock peris_gate_clks[] __initdata = { ENABLE_SCLK_PERIS_SECURE_OTP_CON, 0, 0, 0), }; -static struct samsung_cmu_info peris_cmu_info __initdata = { +static const struct samsung_cmu_info peris_cmu_info __initconst = { .gate_clks = peris_gate_clks, .nr_gate_clks = ARRAY_SIZE(peris_gate_clks), .nr_clk_ids = PERIS_NR_CLK, @@ -1959,7 +1959,7 @@ PNAME(mout_sclk_mphy_p) = { "mout_sclk_ufs_mphy_user", "mout_phyclk_lli_mphy_to_ufs_user", }; -static unsigned long fsys_clk_regs[] __initdata = { +static const unsigned long fsys_clk_regs[] __initconst = { MUX_SEL_FSYS0, MUX_SEL_FSYS1, MUX_SEL_FSYS2, @@ -1980,7 +1980,7 @@ static unsigned long fsys_clk_regs[] __initdata = { ENABLE_IP_FSYS1, }; -static struct samsung_fixed_rate_clock fsys_fixed_clks[] __initdata = { +static const struct samsung_fixed_rate_clock fsys_fixed_clks[] __initconst = { /* PHY clocks from USBDRD30_PHY */ FRATE(CLK_PHYCLK_USBDRD30_UDRD30_PHYCLOCK_PHY, "phyclk_usbdrd30_udrd30_phyclock_phy", NULL, @@ -2020,7 +2020,7 @@ static struct samsung_fixed_rate_clock fsys_fixed_clks[] __initdata = { NULL, 0, 26000000), }; -static struct samsung_mux_clock fsys_mux_clks[] __initdata = { +static const struct samsung_mux_clock fsys_mux_clks[] __initconst = { /* MUX_SEL_FSYS0 */ MUX(CLK_MOUT_SCLK_UFS_MPHY_USER, "mout_sclk_ufs_mphy_user", mout_sclk_ufs_mphy_user_p, MUX_SEL_FSYS0, 4, 1), @@ -2104,7 +2104,7 @@ static struct samsung_mux_clock fsys_mux_clks[] __initdata = { MUX_SEL_FSYS4, 0, 1), }; -static struct samsung_gate_clock fsys_gate_clks[] __initdata = { +static const struct samsung_gate_clock fsys_gate_clks[] __initconst = { /* ENABLE_ACLK_FSYS0 */ GATE(CLK_ACLK_PCIE, "aclk_pcie", "mout_aclk_fsys_200_user", ENABLE_ACLK_FSYS0, 13, CLK_IGNORE_UNUSED, 0), @@ -2274,7 +2274,7 @@ static struct samsung_gate_clock fsys_gate_clks[] __initdata = { GATE(CLK_PDMA0, "pdma0", "aclk_pdma0", ENABLE_IP_FSYS0, 0, 0, 0), }; -static struct samsung_cmu_info fsys_cmu_info __initdata = { +static const struct samsung_cmu_info fsys_cmu_info __initconst = { .mux_clks = fsys_mux_clks, .nr_mux_clks = ARRAY_SIZE(fsys_mux_clks), .gate_clks = fsys_gate_clks, @@ -2310,7 +2310,7 @@ CLK_OF_DECLARE(exynos5433_cmu_fsys, "samsung,exynos5433-cmu-fsys", #define DIV_ENABLE_IP_G2D1 0x0b04 #define DIV_ENABLE_IP_G2D_SECURE_SMMU_G2D 0x0b08 -static unsigned long g2d_clk_regs[] __initdata = { +static const unsigned long g2d_clk_regs[] __initconst = { MUX_SEL_G2D0, MUX_SEL_ENABLE_G2D0, DIV_G2D, @@ -2327,7 +2327,7 @@ static unsigned long g2d_clk_regs[] __initdata = { PNAME(mout_aclk_g2d_266_user_p) = { "oscclk", "aclk_g2d_266", }; PNAME(mout_aclk_g2d_400_user_p) = { "oscclk", "aclk_g2d_400", }; -static struct samsung_mux_clock g2d_mux_clks[] __initdata = { +static const struct samsung_mux_clock g2d_mux_clks[] __initconst = { /* MUX_SEL_G2D0 */ MUX(CLK_MUX_ACLK_G2D_266_USER, "mout_aclk_g2d_266_user", mout_aclk_g2d_266_user_p, MUX_SEL_G2D0, 4, 1), @@ -2335,13 +2335,13 @@ static struct samsung_mux_clock g2d_mux_clks[] __initdata = { mout_aclk_g2d_400_user_p, MUX_SEL_G2D0, 0, 1), }; -static struct samsung_div_clock g2d_div_clks[] __initdata = { +static const struct samsung_div_clock g2d_div_clks[] __initconst = { /* DIV_G2D */ DIV(CLK_DIV_PCLK_G2D, "div_pclk_g2d", "mout_aclk_g2d_266_user", DIV_G2D, 0, 2), }; -static struct samsung_gate_clock g2d_gate_clks[] __initdata = { +static const struct samsung_gate_clock g2d_gate_clks[] __initconst = { /* DIV_ENABLE_ACLK_G2D */ GATE(CLK_ACLK_SMMU_MDMA1, "aclk_smmu_mdma1", "mout_aclk_g2d_266_user", DIV_ENABLE_ACLK_G2D, 12, 0, 0), @@ -2398,7 +2398,7 @@ static struct samsung_gate_clock g2d_gate_clks[] __initdata = { DIV_ENABLE_PCLK_G2D_SECURE_SMMU_G2D, 0, 0, 0), }; -static struct samsung_cmu_info g2d_cmu_info __initdata = { +static const struct samsung_cmu_info g2d_cmu_info __initconst = { .mux_clks = g2d_mux_clks, .nr_mux_clks = ARRAY_SIZE(g2d_mux_clks), .div_clks = g2d_div_clks, @@ -2454,7 +2454,7 @@ CLK_OF_DECLARE(exynos5433_cmu_g2d, "samsung,exynos5433-cmu-g2d", #define CLKOUT_CMU_DISP 0x0c00 #define CLKOUT_CMU_DISP_DIV_STAT 0x0c04 -static unsigned long disp_clk_regs[] __initdata = { +static const unsigned long disp_clk_regs[] __initconst = { DISP_PLL_LOCK, DISP_PLL_CON0, DISP_PLL_CON1, @@ -2527,12 +2527,12 @@ PNAME(mout_sclk_decon_tv_vclk_c_disp_p) = { PNAME(mout_sclk_decon_tv_vclk_b_disp_p) = { "mout_sclk_decon_tv_vclk_a_disp", "mout_sclk_decon_tv_vclk_user", }; -static struct samsung_pll_clock disp_pll_clks[] __initdata = { +static const struct samsung_pll_clock disp_pll_clks[] __initconst = { PLL(pll_35xx, CLK_FOUT_DISP_PLL, "fout_disp_pll", "oscclk", DISP_PLL_LOCK, DISP_PLL_CON0, exynos5443_pll_rates), }; -static struct samsung_fixed_factor_clock disp_fixed_factor_clks[] __initdata = { +static const struct samsung_fixed_factor_clock disp_fixed_factor_clks[] __initconst = { /* * sclk_rgb_{vclk|tv_vclk} is half clock of sclk_decon_{vclk|tv_vclk}. * The divider has fixed value (2) between sclk_rgb_{vclk|tv_vclk} @@ -2544,7 +2544,7 @@ static struct samsung_fixed_factor_clock disp_fixed_factor_clks[] __initdata = { 1, 2, 0), }; -static struct samsung_fixed_rate_clock disp_fixed_clks[] __initdata = { +static const struct samsung_fixed_rate_clock disp_fixed_clks[] __initconst = { /* PHY clocks from MIPI_DPHY1 */ FRATE(0, "phyclk_mipidphy1_bitclkdiv8_phy", NULL, 0, 188000000), FRATE(0, "phyclk_mipidphy1_rxclkesc0_phy", NULL, 0, 100000000), @@ -2558,7 +2558,7 @@ static struct samsung_fixed_rate_clock disp_fixed_clks[] __initdata = { NULL, 0, 166000000), }; -static struct samsung_mux_clock disp_mux_clks[] __initdata = { +static const struct samsung_mux_clock disp_mux_clks[] __initconst = { /* MUX_SEL_DISP0 */ MUX(CLK_MOUT_DISP_PLL, "mout_disp_pll", mout_disp_pll_p, MUX_SEL_DISP0, 0, 1), @@ -2633,7 +2633,7 @@ static struct samsung_mux_clock disp_mux_clks[] __initdata = { mout_sclk_decon_vclk_p, MUX_SEL_DISP4, 0, 1), }; -static struct samsung_div_clock disp_div_clks[] __initdata = { +static const struct samsung_div_clock disp_div_clks[] __initconst = { /* DIV_DISP */ DIV(CLK_DIV_SCLK_DSIM1_DISP, "div_sclk_dsim1_disp", "mout_sclk_dsim1_b_disp", DIV_DISP, 24, 3), @@ -2651,7 +2651,7 @@ static struct samsung_div_clock disp_div_clks[] __initdata = { DIV_DISP, 0, 2), }; -static struct samsung_gate_clock disp_gate_clks[] __initdata = { +static const struct samsung_gate_clock disp_gate_clks[] __initconst = { /* ENABLE_ACLK_DISP0 */ GATE(CLK_ACLK_DECON_TV, "aclk_decon_tv", "mout_aclk_disp_333_user", ENABLE_ACLK_DISP0, 2, 0, 0), @@ -2811,7 +2811,7 @@ static struct samsung_gate_clock disp_gate_clks[] __initdata = { "div_sclk_decon_eclk_disp", ENABLE_SCLK_DISP, 2, 0, 0), }; -static struct samsung_cmu_info disp_cmu_info __initdata = { +static const struct samsung_cmu_info disp_cmu_info __initconst = { .pll_clks = disp_pll_clks, .nr_pll_clks = ARRAY_SIZE(disp_pll_clks), .mux_clks = disp_mux_clks, @@ -2856,7 +2856,7 @@ CLK_OF_DECLARE(exynos5433_cmu_disp, "samsung,exynos5433-cmu-disp", #define ENABLE_IP_AUD0 0x0b00 #define ENABLE_IP_AUD1 0x0b04 -static unsigned long aud_clk_regs[] __initdata = { +static const unsigned long aud_clk_regs[] __initconst = { MUX_SEL_AUD0, MUX_SEL_AUD1, MUX_ENABLE_AUD0, @@ -2875,13 +2875,13 @@ static unsigned long aud_clk_regs[] __initdata = { PNAME(mout_aud_pll_user_aud_p) = { "oscclk", "fout_aud_pll", }; PNAME(mout_sclk_aud_pcm_p) = { "mout_aud_pll_user", "ioclk_audiocdclk0",}; -static struct samsung_fixed_rate_clock aud_fixed_clks[] __initdata = { +static const struct samsung_fixed_rate_clock aud_fixed_clks[] __initconst = { FRATE(0, "ioclk_jtag_tclk", NULL, 0, 33000000), FRATE(0, "ioclk_slimbus_clk", NULL, 0, 25000000), FRATE(0, "ioclk_i2s_bclk", NULL, 0, 50000000), }; -static struct samsung_mux_clock aud_mux_clks[] __initdata = { +static const struct samsung_mux_clock aud_mux_clks[] __initconst = { /* MUX_SEL_AUD0 */ MUX(CLK_MOUT_AUD_PLL_USER, "mout_aud_pll_user", mout_aud_pll_user_aud_p, MUX_SEL_AUD0, 0, 1), @@ -2893,7 +2893,7 @@ static struct samsung_mux_clock aud_mux_clks[] __initdata = { MUX_SEL_AUD1, 0, 1), }; -static struct samsung_div_clock aud_div_clks[] __initdata = { +static const struct samsung_div_clock aud_div_clks[] __initconst = { /* DIV_AUD0 */ DIV(CLK_DIV_ATCLK_AUD, "div_atclk_aud", "div_aud_ca5", DIV_AUD0, 12, 4), @@ -2915,7 +2915,7 @@ static struct samsung_div_clock aud_div_clks[] __initdata = { DIV_AUD1, 0, 4), }; -static struct samsung_gate_clock aud_gate_clks[] __initdata = { +static const struct samsung_gate_clock aud_gate_clks[] __initconst = { /* ENABLE_ACLK_AUD */ GATE(CLK_ACLK_INTR_CTRL, "aclk_intr_ctrl", "div_aclk_aud", ENABLE_ACLK_AUD, 12, 0, 0), @@ -2985,7 +2985,7 @@ static struct samsung_gate_clock aud_gate_clks[] __initdata = { ENABLE_SCLK_AUD1, 0, CLK_IGNORE_UNUSED, 0), }; -static struct samsung_cmu_info aud_cmu_info __initdata = { +static const struct samsung_cmu_info aud_cmu_info __initconst = { .mux_clks = aud_mux_clks, .nr_mux_clks = ARRAY_SIZE(aud_mux_clks), .div_clks = aud_div_clks, @@ -3031,24 +3031,24 @@ PNAME(mout_aclk_bus2_400_p) = { "oscclk", "aclk_bus2_400", }; ENABLE_IP_BUS0, \ ENABLE_IP_BUS1 -static unsigned long bus01_clk_regs[] __initdata = { +static const unsigned long bus01_clk_regs[] __initconst = { CMU_BUS_COMMON_CLK_REGS, }; -static unsigned long bus2_clk_regs[] __initdata = { +static const unsigned long bus2_clk_regs[] __initconst = { MUX_SEL_BUS2, MUX_ENABLE_BUS2, CMU_BUS_COMMON_CLK_REGS, }; -static struct samsung_div_clock bus0_div_clks[] __initdata = { +static const struct samsung_div_clock bus0_div_clks[] __initconst = { /* DIV_BUS0 */ DIV(CLK_DIV_PCLK_BUS_133, "div_pclk_bus0_133", "aclk_bus0_400", DIV_BUS, 0, 3), }; /* CMU_BUS0 clocks */ -static struct samsung_gate_clock bus0_gate_clks[] __initdata = { +static const struct samsung_gate_clock bus0_gate_clks[] __initconst = { /* ENABLE_ACLK_BUS0 */ GATE(CLK_ACLK_AHB2APB_BUSP, "aclk_ahb2apb_bus0p", "div_pclk_bus0_133", ENABLE_ACLK_BUS, 4, CLK_IGNORE_UNUSED, 0), @@ -3067,13 +3067,13 @@ static struct samsung_gate_clock bus0_gate_clks[] __initdata = { }; /* CMU_BUS1 clocks */ -static struct samsung_div_clock bus1_div_clks[] __initdata = { +static const struct samsung_div_clock bus1_div_clks[] __initconst = { /* DIV_BUS1 */ DIV(CLK_DIV_PCLK_BUS_133, "div_pclk_bus1_133", "aclk_bus1_400", DIV_BUS, 0, 3), }; -static struct samsung_gate_clock bus1_gate_clks[] __initdata = { +static const struct samsung_gate_clock bus1_gate_clks[] __initconst = { /* ENABLE_ACLK_BUS1 */ GATE(CLK_ACLK_AHB2APB_BUSP, "aclk_ahb2apb_bus1p", "div_pclk_bus1_133", ENABLE_ACLK_BUS, 4, CLK_IGNORE_UNUSED, 0), @@ -3092,19 +3092,19 @@ static struct samsung_gate_clock bus1_gate_clks[] __initdata = { }; /* CMU_BUS2 clocks */ -static struct samsung_mux_clock bus2_mux_clks[] __initdata = { +static const struct samsung_mux_clock bus2_mux_clks[] __initconst = { /* MUX_SEL_BUS2 */ MUX(CLK_MOUT_ACLK_BUS2_400_USER, "mout_aclk_bus2_400_user", mout_aclk_bus2_400_p, MUX_SEL_BUS2, 0, 1), }; -static struct samsung_div_clock bus2_div_clks[] __initdata = { +static const struct samsung_div_clock bus2_div_clks[] __initconst = { /* DIV_BUS2 */ DIV(CLK_DIV_PCLK_BUS_133, "div_pclk_bus2_133", "mout_aclk_bus2_400_user", DIV_BUS, 0, 3), }; -static struct samsung_gate_clock bus2_gate_clks[] __initdata = { +static const struct samsung_gate_clock bus2_gate_clks[] __initconst = { /* ENABLE_ACLK_BUS2 */ GATE(CLK_ACLK_AHB2APB_BUSP, "aclk_ahb2apb_bus2p", "div_pclk_bus2_133", ENABLE_ACLK_BUS, 3, CLK_IGNORE_UNUSED, 0), @@ -3133,19 +3133,19 @@ static struct samsung_gate_clock bus2_gate_clks[] __initdata = { .nr_gate_clks = ARRAY_SIZE(bus##id##_gate_clks), \ .nr_clk_ids = BUSx_NR_CLK -static struct samsung_cmu_info bus0_cmu_info __initdata = { +static const struct samsung_cmu_info bus0_cmu_info __initconst = { CMU_BUS_INFO_CLKS(0), .clk_regs = bus01_clk_regs, .nr_clk_regs = ARRAY_SIZE(bus01_clk_regs), }; -static struct samsung_cmu_info bus1_cmu_info __initdata = { +static const struct samsung_cmu_info bus1_cmu_info __initconst = { CMU_BUS_INFO_CLKS(1), .clk_regs = bus01_clk_regs, .nr_clk_regs = ARRAY_SIZE(bus01_clk_regs), }; -static struct samsung_cmu_info bus2_cmu_info __initdata = { +static const struct samsung_cmu_info bus2_cmu_info __initconst = { CMU_BUS_INFO_CLKS(2), .mux_clks = bus2_mux_clks, .nr_mux_clks = ARRAY_SIZE(bus2_mux_clks), @@ -3189,7 +3189,7 @@ exynos5433_cmu_bus_init(2); #define CLKOUT_CMU_G3D_DIV_STAT 0x0c04 #define CLK_STOPCTRL 0x1000 -static unsigned long g3d_clk_regs[] __initdata = { +static const unsigned long g3d_clk_regs[] __initconst = { G3D_PLL_LOCK, G3D_PLL_CON0, G3D_PLL_CON1, @@ -3212,12 +3212,12 @@ static unsigned long g3d_clk_regs[] __initdata = { PNAME(mout_aclk_g3d_400_p) = { "mout_g3d_pll", "aclk_g3d_400", }; PNAME(mout_g3d_pll_p) = { "oscclk", "fout_g3d_pll", }; -static struct samsung_pll_clock g3d_pll_clks[] __initdata = { +static const struct samsung_pll_clock g3d_pll_clks[] __initconst = { PLL(pll_35xx, CLK_FOUT_G3D_PLL, "fout_g3d_pll", "oscclk", G3D_PLL_LOCK, G3D_PLL_CON0, exynos5443_pll_rates), }; -static struct samsung_mux_clock g3d_mux_clks[] __initdata = { +static const struct samsung_mux_clock g3d_mux_clks[] __initconst = { /* MUX_SEL_G3D */ MUX_F(CLK_MOUT_ACLK_G3D_400, "mout_aclk_g3d_400", mout_aclk_g3d_400_p, MUX_SEL_G3D, 8, 1, CLK_SET_RATE_PARENT, 0), @@ -3225,7 +3225,7 @@ static struct samsung_mux_clock g3d_mux_clks[] __initdata = { MUX_SEL_G3D, 0, 1, CLK_SET_RATE_PARENT, 0), }; -static struct samsung_div_clock g3d_div_clks[] __initdata = { +static const struct samsung_div_clock g3d_div_clks[] __initconst = { /* DIV_G3D */ DIV(CLK_DIV_SCLK_HPM_G3D, "div_sclk_hpm_g3d", "mout_g3d_pll", DIV_G3D, 8, 2), @@ -3235,7 +3235,7 @@ static struct samsung_div_clock g3d_div_clks[] __initdata = { 0, 3, CLK_SET_RATE_PARENT, 0), }; -static struct samsung_gate_clock g3d_gate_clks[] __initdata = { +static const struct samsung_gate_clock g3d_gate_clks[] __initconst = { /* ENABLE_ACLK_G3D */ GATE(CLK_ACLK_BTS_G3D1, "aclk_bts_g3d1", "div_aclk_g3d", ENABLE_ACLK_G3D, 7, 0, 0), @@ -3269,7 +3269,7 @@ static struct samsung_gate_clock g3d_gate_clks[] __initdata = { ENABLE_SCLK_G3D, 0, 0, 0), }; -static struct samsung_cmu_info g3d_cmu_info __initdata = { +static const struct samsung_cmu_info g3d_cmu_info __initconst = { .pll_clks = g3d_pll_clks, .nr_pll_clks = ARRAY_SIZE(g3d_pll_clks), .mux_clks = g3d_mux_clks, @@ -3310,7 +3310,7 @@ CLK_OF_DECLARE(exynos5433_cmu_g3d, "samsung,exynos5433-cmu-g3d", #define ENABLE_IP_GSCL_SECURE_SMMU_GSCL1 0x0b0c #define ENABLE_IP_GSCL_SECURE_SMMU_GSCL2 0x0b10 -static unsigned long gscl_clk_regs[] __initdata = { +static const unsigned long gscl_clk_regs[] __initconst = { MUX_SEL_GSCL, MUX_ENABLE_GSCL, ENABLE_ACLK_GSCL, @@ -3332,7 +3332,7 @@ static unsigned long gscl_clk_regs[] __initdata = { PNAME(aclk_gscl_111_user_p) = { "oscclk", "aclk_gscl_111", }; PNAME(aclk_gscl_333_user_p) = { "oscclk", "aclk_gscl_333", }; -static struct samsung_mux_clock gscl_mux_clks[] __initdata = { +static const struct samsung_mux_clock gscl_mux_clks[] __initconst = { /* MUX_SEL_GSCL */ MUX(CLK_MOUT_ACLK_GSCL_111_USER, "mout_aclk_gscl_111_user", aclk_gscl_111_user_p, MUX_SEL_GSCL, 4, 1), @@ -3340,7 +3340,7 @@ static struct samsung_mux_clock gscl_mux_clks[] __initdata = { aclk_gscl_333_user_p, MUX_SEL_GSCL, 0, 1), }; -static struct samsung_gate_clock gscl_gate_clks[] __initdata = { +static const struct samsung_gate_clock gscl_gate_clks[] __initconst = { /* ENABLE_ACLK_GSCL */ GATE(CLK_ACLK_BTS_GSCL2, "aclk_bts_gscl2", "mout_aclk_gscl_333_user", ENABLE_ACLK_GSCL, 11, 0, 0), @@ -3412,7 +3412,7 @@ static struct samsung_gate_clock gscl_gate_clks[] __initdata = { ENABLE_PCLK_GSCL_SECURE_SMMU_GSCL2, 0, 0, 0), }; -static struct samsung_cmu_info gscl_cmu_info __initdata = { +static const struct samsung_cmu_info gscl_cmu_info __initconst = { .mux_clks = gscl_mux_clks, .nr_mux_clks = ARRAY_SIZE(gscl_mux_clks), .gate_clks = gscl_gate_clks, @@ -3465,7 +3465,7 @@ CLK_OF_DECLARE(exynos5433_cmu_gscl, "samsung,exynos5433-cmu-gscl", #define APOLLO_INTR_SPREAD_USE_STANDBYWFI 0x1084 #define APOLLO_INTR_SPREAD_BLOCKING_DURATION 0x1088 -static unsigned long apollo_clk_regs[] __initdata = { +static const unsigned long apollo_clk_regs[] __initconst = { APOLLO_PLL_LOCK, APOLLO_PLL_CON0, APOLLO_PLL_CON1, @@ -3500,12 +3500,12 @@ PNAME(mout_bus_pll_apollo_user_p) = { "oscclk", "sclk_bus_pll_apollo", }; PNAME(mout_apollo_p) = { "mout_apollo_pll", "mout_bus_pll_apollo_user", }; -static struct samsung_pll_clock apollo_pll_clks[] __initdata = { +static const struct samsung_pll_clock apollo_pll_clks[] __initconst = { PLL(pll_35xx, CLK_FOUT_APOLLO_PLL, "fout_apollo_pll", "oscclk", APOLLO_PLL_LOCK, APOLLO_PLL_CON0, exynos5443_pll_rates), }; -static struct samsung_mux_clock apollo_mux_clks[] __initdata = { +static const struct samsung_mux_clock apollo_mux_clks[] __initconst = { /* MUX_SEL_APOLLO0 */ MUX_F(CLK_MOUT_APOLLO_PLL, "mout_apollo_pll", mout_apollo_pll_p, MUX_SEL_APOLLO0, 0, 1, CLK_SET_RATE_PARENT, 0), @@ -3519,7 +3519,7 @@ static struct samsung_mux_clock apollo_mux_clks[] __initdata = { 0, 1, CLK_SET_RATE_PARENT, 0), }; -static struct samsung_div_clock apollo_div_clks[] __initdata = { +static const struct samsung_div_clock apollo_div_clks[] __initconst = { /* DIV_APOLLO0 */ DIV_F(CLK_DIV_CNTCLK_APOLLO, "div_cntclk_apollo", "div_apollo2", DIV_APOLLO0, 24, 3, CLK_GET_RATE_NOCACHE, @@ -3550,7 +3550,7 @@ static struct samsung_div_clock apollo_div_clks[] __initdata = { CLK_DIVIDER_READ_ONLY), }; -static struct samsung_gate_clock apollo_gate_clks[] __initdata = { +static const struct samsung_gate_clock apollo_gate_clks[] __initconst = { /* ENABLE_ACLK_APOLLO */ GATE(CLK_ACLK_ASATBSLV_APOLLO_3_CSSYS, "aclk_asatbslv_apollo_3_cssys", "div_atclk_apollo", ENABLE_ACLK_APOLLO, @@ -3594,7 +3594,7 @@ static struct samsung_gate_clock apollo_gate_clks[] __initdata = { CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0), }; -static struct samsung_cmu_info apollo_cmu_info __initdata = { +static const struct samsung_cmu_info apollo_cmu_info __initconst = { .pll_clks = apollo_pll_clks, .nr_pll_clks = ARRAY_SIZE(apollo_pll_clks), .mux_clks = apollo_mux_clks, @@ -3651,7 +3651,7 @@ CLK_OF_DECLARE(exynos5433_cmu_apollo, "samsung,exynos5433-cmu-apollo", #define ATLAS_INTR_SPREAD_USE_STANDBYWFI 0x1084 #define ATLAS_INTR_SPREAD_BLOCKING_DURATION 0x1088 -static unsigned long atlas_clk_regs[] __initdata = { +static const unsigned long atlas_clk_regs[] __initconst = { ATLAS_PLL_LOCK, ATLAS_PLL_CON0, ATLAS_PLL_CON1, @@ -3686,12 +3686,12 @@ PNAME(mout_bus_pll_atlas_user_p) = { "oscclk", "sclk_bus_pll_atlas", }; PNAME(mout_atlas_p) = { "mout_atlas_pll", "mout_bus_pll_atlas_user", }; -static struct samsung_pll_clock atlas_pll_clks[] __initdata = { +static const struct samsung_pll_clock atlas_pll_clks[] __initconst = { PLL(pll_35xx, CLK_FOUT_ATLAS_PLL, "fout_atlas_pll", "oscclk", ATLAS_PLL_LOCK, ATLAS_PLL_CON0, exynos5443_pll_rates), }; -static struct samsung_mux_clock atlas_mux_clks[] __initdata = { +static const struct samsung_mux_clock atlas_mux_clks[] __initconst = { /* MUX_SEL_ATLAS0 */ MUX_F(CLK_MOUT_ATLAS_PLL, "mout_atlas_pll", mout_atlas_pll_p, MUX_SEL_ATLAS0, 0, 1, CLK_SET_RATE_PARENT, 0), @@ -3705,7 +3705,7 @@ static struct samsung_mux_clock atlas_mux_clks[] __initdata = { 0, 1, CLK_SET_RATE_PARENT, 0), }; -static struct samsung_div_clock atlas_div_clks[] __initdata = { +static const struct samsung_div_clock atlas_div_clks[] __initconst = { /* DIV_ATLAS0 */ DIV_F(CLK_DIV_CNTCLK_ATLAS, "div_cntclk_atlas", "div_atlas2", DIV_ATLAS0, 24, 3, CLK_GET_RATE_NOCACHE, @@ -3736,7 +3736,7 @@ static struct samsung_div_clock atlas_div_clks[] __initdata = { CLK_DIVIDER_READ_ONLY), }; -static struct samsung_gate_clock atlas_gate_clks[] __initdata = { +static const struct samsung_gate_clock atlas_gate_clks[] __initconst = { /* ENABLE_ACLK_ATLAS */ GATE(CLK_ACLK_ATB_AUD_CSSYS, "aclk_atb_aud_cssys", "div_atclk_atlas", ENABLE_ACLK_ATLAS, @@ -3806,7 +3806,7 @@ static struct samsung_gate_clock atlas_gate_clks[] __initdata = { CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0), }; -static struct samsung_cmu_info atlas_cmu_info __initdata = { +static const struct samsung_cmu_info atlas_cmu_info __initconst = { .pll_clks = atlas_pll_clks, .nr_pll_clks = ARRAY_SIZE(atlas_pll_clks), .mux_clks = atlas_mux_clks, @@ -3853,7 +3853,7 @@ CLK_OF_DECLARE(exynos5433_cmu_atlas, "samsung,exynos5433-cmu-atlas", #define ENABLE_IP_MSCL_SECURE_SMMU_M2MSCALER1 0x0b0c #define ENABLE_IP_MSCL_SECURE_SMMU_JPEG 0x0b10 -static unsigned long mscl_clk_regs[] __initdata = { +static const unsigned long mscl_clk_regs[] __initconst = { MUX_SEL_MSCL0, MUX_SEL_MSCL1, MUX_ENABLE_MSCL0, @@ -3881,7 +3881,7 @@ PNAME(mout_aclk_mscl_400_user_p) = { "oscclk", "aclk_mscl_400", }; PNAME(mout_sclk_jpeg_p) = { "mout_sclk_jpeg_user", "mout_aclk_mscl_400_user", }; -static struct samsung_mux_clock mscl_mux_clks[] __initdata = { +static const struct samsung_mux_clock mscl_mux_clks[] __initconst = { /* MUX_SEL_MSCL0 */ MUX(CLK_MOUT_SCLK_JPEG_USER, "mout_sclk_jpeg_user", mout_sclk_jpeg_user_p, MUX_SEL_MSCL0, 4, 1), @@ -3893,13 +3893,13 @@ static struct samsung_mux_clock mscl_mux_clks[] __initdata = { MUX_SEL_MSCL1, 0, 1), }; -static struct samsung_div_clock mscl_div_clks[] __initdata = { +static const struct samsung_div_clock mscl_div_clks[] __initconst = { /* DIV_MSCL */ DIV(CLK_DIV_PCLK_MSCL, "div_pclk_mscl", "mout_aclk_mscl_400_user", DIV_MSCL, 0, 3), }; -static struct samsung_gate_clock mscl_gate_clks[] __initdata = { +static const struct samsung_gate_clock mscl_gate_clks[] __initconst = { /* ENABLE_ACLK_MSCL */ GATE(CLK_ACLK_BTS_JPEG, "aclk_bts_jpeg", "mout_aclk_mscl_400_user", ENABLE_ACLK_MSCL, 9, 0, 0), @@ -3977,7 +3977,7 @@ static struct samsung_gate_clock mscl_gate_clks[] __initdata = { CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0), }; -static struct samsung_cmu_info mscl_cmu_info __initdata = { +static const struct samsung_cmu_info mscl_cmu_info __initconst = { .mux_clks = mscl_mux_clks, .nr_mux_clks = ARRAY_SIZE(mscl_mux_clks), .div_clks = mscl_div_clks, @@ -4012,7 +4012,7 @@ CLK_OF_DECLARE(exynos5433_cmu_mscl, "samsung,exynos5433-cmu-mscl", #define ENABLE_IP_MFC1 0x0b04 #define ENABLE_IP_MFC_SECURE_SMMU_MFC 0x0b08 -static unsigned long mfc_clk_regs[] __initdata = { +static const unsigned long mfc_clk_regs[] __initconst = { MUX_SEL_MFC, MUX_ENABLE_MFC, DIV_MFC, @@ -4027,19 +4027,19 @@ static unsigned long mfc_clk_regs[] __initdata = { PNAME(mout_aclk_mfc_400_user_p) = { "oscclk", "aclk_mfc_400", }; -static struct samsung_mux_clock mfc_mux_clks[] __initdata = { +static const struct samsung_mux_clock mfc_mux_clks[] __initconst = { /* MUX_SEL_MFC */ MUX(CLK_MOUT_ACLK_MFC_400_USER, "mout_aclk_mfc_400_user", mout_aclk_mfc_400_user_p, MUX_SEL_MFC, 0, 0), }; -static struct samsung_div_clock mfc_div_clks[] __initdata = { +static const struct samsung_div_clock mfc_div_clks[] __initconst = { /* DIV_MFC */ DIV(CLK_DIV_PCLK_MFC, "div_pclk_mfc", "mout_aclk_mfc_400_user", DIV_MFC, 0, 2), }; -static struct samsung_gate_clock mfc_gate_clks[] __initdata = { +static const struct samsung_gate_clock mfc_gate_clks[] __initconst = { /* ENABLE_ACLK_MFC */ GATE(CLK_ACLK_BTS_MFC_1, "aclk_bts_mfc_1", "mout_aclk_mfc_400_user", ENABLE_ACLK_MFC, 6, 0, 0), @@ -4085,7 +4085,7 @@ static struct samsung_gate_clock mfc_gate_clks[] __initdata = { 0, CLK_IGNORE_UNUSED, 0), }; -static struct samsung_cmu_info mfc_cmu_info __initdata = { +static const struct samsung_cmu_info mfc_cmu_info __initconst = { .mux_clks = mfc_mux_clks, .nr_mux_clks = ARRAY_SIZE(mfc_mux_clks), .div_clks = mfc_div_clks, @@ -4120,7 +4120,7 @@ CLK_OF_DECLARE(exynos5433_cmu_mfc, "samsung,exynos5433-cmu-mfc", #define ENABLE_IP_HEVC1 0x0b04 #define ENABLE_IP_HEVC_SECURE_SMMU_HEVC 0x0b08 -static unsigned long hevc_clk_regs[] __initdata = { +static const unsigned long hevc_clk_regs[] __initconst = { MUX_SEL_HEVC, MUX_ENABLE_HEVC, DIV_HEVC, @@ -4135,19 +4135,19 @@ static unsigned long hevc_clk_regs[] __initdata = { PNAME(mout_aclk_hevc_400_user_p) = { "oscclk", "aclk_hevc_400", }; -static struct samsung_mux_clock hevc_mux_clks[] __initdata = { +static const struct samsung_mux_clock hevc_mux_clks[] __initconst = { /* MUX_SEL_HEVC */ MUX(CLK_MOUT_ACLK_HEVC_400_USER, "mout_aclk_hevc_400_user", mout_aclk_hevc_400_user_p, MUX_SEL_HEVC, 0, 0), }; -static struct samsung_div_clock hevc_div_clks[] __initdata = { +static const struct samsung_div_clock hevc_div_clks[] __initconst = { /* DIV_HEVC */ DIV(CLK_DIV_PCLK_HEVC, "div_pclk_hevc", "mout_aclk_hevc_400_user", DIV_HEVC, 0, 2), }; -static struct samsung_gate_clock hevc_gate_clks[] __initdata = { +static const struct samsung_gate_clock hevc_gate_clks[] __initconst = { /* ENABLE_ACLK_HEVC */ GATE(CLK_ACLK_BTS_HEVC_1, "aclk_bts_hevc_1", "mout_aclk_hevc_400_user", ENABLE_ACLK_HEVC, 6, 0, 0), @@ -4195,7 +4195,7 @@ static struct samsung_gate_clock hevc_gate_clks[] __initdata = { 0, CLK_IGNORE_UNUSED, 0), }; -static struct samsung_cmu_info hevc_cmu_info __initdata = { +static const struct samsung_cmu_info hevc_cmu_info __initconst = { .mux_clks = hevc_mux_clks, .nr_mux_clks = ARRAY_SIZE(hevc_mux_clks), .div_clks = hevc_div_clks, @@ -4232,7 +4232,7 @@ CLK_OF_DECLARE(exynos5433_cmu_hevc, "samsung,exynos5433-cmu-hevc", #define ENABLE_IP_ISP2 0x0b08 #define ENABLE_IP_ISP3 0x0b0c -static unsigned long isp_clk_regs[] __initdata = { +static const unsigned long isp_clk_regs[] __initconst = { MUX_SEL_ISP, MUX_ENABLE_ISP, DIV_ISP, @@ -4250,7 +4250,7 @@ static unsigned long isp_clk_regs[] __initdata = { PNAME(mout_aclk_isp_dis_400_user_p) = { "oscclk", "aclk_isp_dis_400", }; PNAME(mout_aclk_isp_400_user_p) = { "oscclk", "aclk_isp_400", }; -static struct samsung_mux_clock isp_mux_clks[] __initdata = { +static const struct samsung_mux_clock isp_mux_clks[] __initconst = { /* MUX_SEL_ISP */ MUX(CLK_MOUT_ACLK_ISP_DIS_400_USER, "mout_aclk_isp_dis_400_user", mout_aclk_isp_dis_400_user_p, MUX_SEL_ISP, 4, 0), @@ -4258,7 +4258,7 @@ static struct samsung_mux_clock isp_mux_clks[] __initdata = { mout_aclk_isp_400_user_p, MUX_SEL_ISP, 0, 0), }; -static struct samsung_div_clock isp_div_clks[] __initdata = { +static const struct samsung_div_clock isp_div_clks[] __initconst = { /* DIV_ISP */ DIV(CLK_DIV_PCLK_ISP_DIS, "div_pclk_isp_dis", "mout_aclk_isp_dis_400_user", DIV_ISP, 12, 3), @@ -4270,7 +4270,7 @@ static struct samsung_div_clock isp_div_clks[] __initdata = { "mout_aclk_isp_400_user", DIV_ISP, 0, 3), }; -static struct samsung_gate_clock isp_gate_clks[] __initdata = { +static const struct samsung_gate_clock isp_gate_clks[] __initconst = { /* ENABLE_ACLK_ISP0 */ GATE(CLK_ACLK_ISP_D_GLUE, "aclk_isp_d_glue", "mout_aclk_isp_400_user", ENABLE_ACLK_ISP0, 6, CLK_IGNORE_UNUSED, 0), @@ -4448,7 +4448,7 @@ static struct samsung_gate_clock isp_gate_clks[] __initdata = { 0, CLK_IGNORE_UNUSED, 0), }; -static struct samsung_cmu_info isp_cmu_info __initdata = { +static const struct samsung_cmu_info isp_cmu_info __initconst = { .mux_clks = isp_mux_clks, .nr_mux_clks = ARRAY_SIZE(isp_mux_clks), .div_clks = isp_div_clks, @@ -4504,7 +4504,7 @@ CLK_OF_DECLARE(exynos5433_cmu_isp, "samsung,exynos5433-cmu-isp", #define ENABLE_IP_CAM02 0X0b08 #define ENABLE_IP_CAM03 0X0b0C -static unsigned long cam0_clk_regs[] __initdata = { +static const unsigned long cam0_clk_regs[] __initconst = { MUX_SEL_CAM00, MUX_SEL_CAM01, MUX_SEL_CAM02, @@ -4588,14 +4588,14 @@ PNAME(mout_sclk_pixelasync_lite_c_init_a_p) = { "mout_aclk_cam0_552_user", "mout_aclk_cam0_400_user", }; -static struct samsung_fixed_rate_clock cam0_fixed_clks[] __initdata = { +static const struct samsung_fixed_rate_clock cam0_fixed_clks[] __initconst = { FRATE(CLK_PHYCLK_RXBYTEECLKHS0_S4_PHY, "phyclk_rxbyteclkhs0_s4_phy", NULL, 0, 100000000), FRATE(CLK_PHYCLK_RXBYTEECLKHS0_S2A_PHY, "phyclk_rxbyteclkhs0_s2a_phy", NULL, 0, 100000000), }; -static struct samsung_mux_clock cam0_mux_clks[] __initdata = { +static const struct samsung_mux_clock cam0_mux_clks[] __initconst = { /* MUX_SEL_CAM00 */ MUX(CLK_MOUT_ACLK_CAM0_333_USER, "mout_aclk_cam0_333_user", mout_aclk_cam0_333_user_p, MUX_SEL_CAM00, 8, 1), @@ -4669,7 +4669,7 @@ static struct samsung_mux_clock cam0_mux_clks[] __initdata = { MUX_SEL_CAM04, 0, 1), }; -static struct samsung_div_clock cam0_div_clks[] __initdata = { +static const struct samsung_div_clock cam0_div_clks[] __initconst = { /* DIV_CAM00 */ DIV(CLK_DIV_PCLK_CAM0_50, "div_pclk_cam0_50", "div_aclk_cam0_200", DIV_CAM00, 8, 2), @@ -4716,7 +4716,7 @@ static struct samsung_div_clock cam0_div_clks[] __initdata = { "mout_sclk_pixelasync_lite_c_init_b", DIV_CAM03, 0, 3), }; -static struct samsung_gate_clock cam0_gate_clks[] __initdata = { +static const struct samsung_gate_clock cam0_gate_clks[] __initconst = { /* ENABLE_ACLK_CAM00 */ GATE(CLK_ACLK_CSIS1, "aclk_csis1", "div_aclk_csis1", ENABLE_ACLK_CAM00, 6, 0, 0), @@ -4923,7 +4923,7 @@ static struct samsung_gate_clock cam0_gate_clks[] __initdata = { ENABLE_SCLK_CAM0, 0, 0, 0), }; -static struct samsung_cmu_info cam0_cmu_info __initdata = { +static const struct samsung_cmu_info cam0_cmu_info __initconst = { .mux_clks = cam0_mux_clks, .nr_mux_clks = ARRAY_SIZE(cam0_mux_clks), .div_clks = cam0_div_clks, @@ -4970,7 +4970,7 @@ CLK_OF_DECLARE(exynos5433_cmu_cam0, "samsung,exynos5433-cmu-cam0", #define ENABLE_IP_CAM11 0X0b04 #define ENABLE_IP_CAM12 0X0b08 -static unsigned long cam1_clk_regs[] __initdata = { +static const unsigned long cam1_clk_regs[] __initconst = { MUX_SEL_CAM10, MUX_SEL_CAM11, MUX_SEL_CAM12, @@ -5016,12 +5016,12 @@ PNAME(mout_aclk_lite_c_b_p) = { "mout_aclk_lite_c_a", PNAME(mout_aclk_lite_c_a_p) = { "mout_aclk_cam1_552_user", "mout_aclk_cam1_400_user", }; -static struct samsung_fixed_rate_clock cam1_fixed_clks[] __initdata = { +static const struct samsung_fixed_rate_clock cam1_fixed_clks[] __initconst = { FRATE(CLK_PHYCLK_RXBYTEECLKHS0_S2B, "phyclk_rxbyteclkhs0_s2b_phy", NULL, 0, 100000000), }; -static struct samsung_mux_clock cam1_mux_clks[] __initdata = { +static const struct samsung_mux_clock cam1_mux_clks[] __initconst = { /* MUX_SEL_CAM10 */ MUX(CLK_MOUT_SCLK_ISP_UART_USER, "mout_sclk_isp_uart_user", mout_sclk_isp_uart_user_p, MUX_SEL_CAM10, 20, 1), @@ -5057,7 +5057,7 @@ static struct samsung_mux_clock cam1_mux_clks[] __initdata = { MUX_SEL_CAM12, 0, 1), }; -static struct samsung_div_clock cam1_div_clks[] __initdata = { +static const struct samsung_div_clock cam1_div_clks[] __initconst = { /* DIV_CAM10 */ DIV(CLK_DIV_SCLK_ISP_MPWM, "div_sclk_isp_mpwm", "div_pclk_cam1_83", DIV_CAM10, 16, 2), @@ -5081,7 +5081,7 @@ static struct samsung_div_clock cam1_div_clks[] __initdata = { DIV_CAM11, 0, 3), }; -static struct samsung_gate_clock cam1_gate_clks[] __initdata = { +static const struct samsung_gate_clock cam1_gate_clks[] __initconst = { /* ENABLE_ACLK_CAM10 */ GATE(CLK_ACLK_ISP_GIC, "aclk_isp_gic", "mout_aclk_cam1_333_user", ENABLE_ACLK_CAM10, 4, 0, 0), @@ -5296,7 +5296,7 @@ static struct samsung_gate_clock cam1_gate_clks[] __initdata = { ENABLE_SCLK_CAM1, 0, 0, 0), }; -static struct samsung_cmu_info cam1_cmu_info __initdata = { +static const struct samsung_cmu_info cam1_cmu_info __initconst = { .mux_clks = cam1_mux_clks, .nr_mux_clks = ARRAY_SIZE(cam1_mux_clks), .div_clks = cam1_div_clks, -- cgit v1.2.3 From 402b7cebf286d5c06c847c175ccc8405aabdae61 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 11 May 2016 14:02:11 +0200 Subject: clk: samsung: exynos5433: Move PLL rates data to init section The arrays with initialization data of PLLs can be moved to initconst section because they are referenced only from other initconst-level symbols. Signed-off-by: Krzysztof Kozlowski Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk-exynos5433.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/clk/samsung/clk-exynos5433.c b/drivers/clk/samsung/clk-exynos5433.c index f202a51ff99b..5993bd5ac6ba 100644 --- a/drivers/clk/samsung/clk-exynos5433.c +++ b/drivers/clk/samsung/clk-exynos5433.c @@ -693,7 +693,7 @@ static const struct samsung_gate_clock top_gate_clks[] __initconst = { * ATLAS_PLL & APOLLO_PLL & MEM0_PLL & MEM1_PLL & BUS_PLL & MFC_PLL * & MPHY_PLL & G3D_PLL & DISP_PLL & ISP_PLL */ -static const struct samsung_pll_rate_table exynos5443_pll_rates[] = { +static const struct samsung_pll_rate_table exynos5443_pll_rates[] __initconst = { PLL_35XX_RATE(2500000000U, 625, 6, 0), PLL_35XX_RATE(2400000000U, 500, 5, 0), PLL_35XX_RATE(2300000000U, 575, 6, 0), @@ -744,7 +744,7 @@ static const struct samsung_pll_rate_table exynos5443_pll_rates[] = { }; /* AUD_PLL */ -static const struct samsung_pll_rate_table exynos5443_aud_pll_rates[] = { +static const struct samsung_pll_rate_table exynos5443_aud_pll_rates[] __initconst = { PLL_36XX_RATE(400000000U, 200, 3, 2, 0), PLL_36XX_RATE(393216000U, 197, 3, 2, -25690), PLL_36XX_RATE(384000000U, 128, 2, 2, 0), -- cgit v1.2.3 From ebd217e16522509c2dd371a0c51f623135cfe12c Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 11 May 2016 14:02:12 +0200 Subject: clk: samsung: exynos5420: Move sleep init function and PLL data to init section The exynos5420_clk_sleep_init() function and arrays with initialization data of PLLs can be moved to init section because they are referenced only from other init-level symbols. Signed-off-by: Krzysztof Kozlowski Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk-exynos5420.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/clk/samsung/clk-exynos5420.c b/drivers/clk/samsung/clk-exynos5420.c index 427725c8262c..95872b7c47c9 100644 --- a/drivers/clk/samsung/clk-exynos5420.c +++ b/drivers/clk/samsung/clk-exynos5420.c @@ -306,7 +306,7 @@ static struct syscore_ops exynos5420_clk_syscore_ops = { .resume = exynos5420_clk_resume, }; -static void exynos5420_clk_sleep_init(void) +static void __init exynos5420_clk_sleep_init(void) { exynos5x_save = samsung_clk_alloc_reg_dump(exynos5x_clk_regs, ARRAY_SIZE(exynos5x_clk_regs)); @@ -333,7 +333,7 @@ err_soc: return; } #else -static void exynos5420_clk_sleep_init(void) {} +static void __init exynos5420_clk_sleep_init(void) {} #endif /* list of all parent clocks */ @@ -1219,7 +1219,7 @@ static const struct samsung_gate_clock exynos5x_gate_clks[] __initconst = { GATE(CLK_G3D, "g3d", "mout_user_aclk_g3d", GATE_IP_G3D, 9, 0, 0), }; -static const struct samsung_pll_rate_table exynos5420_pll2550x_24mhz_tbl[] = { +static const struct samsung_pll_rate_table exynos5420_pll2550x_24mhz_tbl[] __initconst = { PLL_35XX_RATE(2000000000, 250, 3, 0), PLL_35XX_RATE(1900000000, 475, 6, 0), PLL_35XX_RATE(1800000000, 225, 3, 0), -- cgit v1.2.3 From 1d3f15a89e04356aa37cef8f5763cd4e2c6d11af Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 11 May 2016 14:02:13 +0200 Subject: clk: samsung: exynos5250: Move sleep init function to init section The exynos5250_clk_sleep_init() function can be moved to init section because it is referenced only from other init-level calls. Signed-off-by: Krzysztof Kozlowski Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk-exynos5250.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/clk/samsung/clk-exynos5250.c b/drivers/clk/samsung/clk-exynos5250.c index a6ebc068689f..27a227d6620c 100644 --- a/drivers/clk/samsung/clk-exynos5250.c +++ b/drivers/clk/samsung/clk-exynos5250.c @@ -190,7 +190,7 @@ static struct syscore_ops exynos5250_clk_syscore_ops = { .resume = exynos5250_clk_resume, }; -static void exynos5250_clk_sleep_init(void) +static void __init exynos5250_clk_sleep_init(void) { exynos5250_save = samsung_clk_alloc_reg_dump(exynos5250_clk_regs, ARRAY_SIZE(exynos5250_clk_regs)); @@ -203,7 +203,7 @@ static void exynos5250_clk_sleep_init(void) register_syscore_ops(&exynos5250_clk_syscore_ops); } #else -static void exynos5250_clk_sleep_init(void) {} +static void __init exynos5250_clk_sleep_init(void) {} #endif /* list of all parent clock list */ -- cgit v1.2.3 From 4dbf01b8df00864787b6c7e3d3e0890d385b0ff5 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 11 May 2016 14:02:14 +0200 Subject: clk: samsung: Fully constify mux parent names The PNAME macro defines array of strings for names of mux parents. Although the strings itself were const but pointers to them were not thus this data resided in initdata. Make this an array of const pointers to const strings and move to initconst section. Signed-off-by: Krzysztof Kozlowski Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/samsung/clk.h b/drivers/clk/samsung/clk.h index 61db98dd01a2..77d4657a95c5 100644 --- a/drivers/clk/samsung/clk.h +++ b/drivers/clk/samsung/clk.h @@ -261,7 +261,7 @@ struct samsung_gate_clock { #define GATE_DA(_id, dname, cname, pname, o, b, f, gf, a) \ __GATE(_id, dname, cname, pname, o, b, f, gf, a) -#define PNAME(x) static const char *x[] __initdata +#define PNAME(x) static const char * const x[] __initconst /** * struct samsung_clk_reg_dump: register dump of clock controller registers. -- cgit v1.2.3 From 334393366f3a68f5645b3ec9cfb7abad7e634e01 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 11 May 2016 14:12:16 +0200 Subject: clk: samsung: exynos3250: Move PLL rates data to init section The arrays with initialization data of PLLs can be moved to initconst section because they are referenced only from other initconst-level symbols. Signed-off-by: Krzysztof Kozlowski Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk-exynos3250.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/clk/samsung/clk-exynos3250.c b/drivers/clk/samsung/clk-exynos3250.c index 057c3f0d0e35..b2513959252d 100644 --- a/drivers/clk/samsung/clk-exynos3250.c +++ b/drivers/clk/samsung/clk-exynos3250.c @@ -669,7 +669,7 @@ static const struct samsung_gate_clock gate_clks[] __initconst = { }; /* APLL & MPLL & BPLL & UPLL */ -static const struct samsung_pll_rate_table exynos3250_pll_rates[] = { +static const struct samsung_pll_rate_table exynos3250_pll_rates[] __initconst = { PLL_35XX_RATE(1200000000, 400, 4, 1), PLL_35XX_RATE(1100000000, 275, 3, 1), PLL_35XX_RATE(1066000000, 533, 6, 1), @@ -691,7 +691,7 @@ static const struct samsung_pll_rate_table exynos3250_pll_rates[] = { }; /* EPLL */ -static const struct samsung_pll_rate_table exynos3250_epll_rates[] = { +static const struct samsung_pll_rate_table exynos3250_epll_rates[] __initconst = { PLL_36XX_RATE(800000000, 200, 3, 1, 0), PLL_36XX_RATE(288000000, 96, 2, 2, 0), PLL_36XX_RATE(192000000, 128, 2, 3, 0), -- cgit v1.2.3 From 1ebfb67de8f47c5f277f4a59e7f922a6806e54de Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sat, 28 May 2016 11:54:14 +0200 Subject: clk: samsung: exynos5410: Add serial3, USB and PWM clocks Just like other Exynos5 family SoCs, this one has four UARTs. Add missing UART3 clocks to the Exynos5410 clock driver. Add clocks for USB and PWM. Signed-off-by: Krzysztof Kozlowski Acked-by: Stephen Boyd Reviewed-by: Javier Martinez Canillas Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk-exynos5410.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/drivers/clk/samsung/clk-exynos5410.c b/drivers/clk/samsung/clk-exynos5410.c index 8e8c7cca8c62..8ad8d5ece7fa 100644 --- a/drivers/clk/samsung/clk-exynos5410.c +++ b/drivers/clk/samsung/clk-exynos5410.c @@ -33,9 +33,11 @@ #define SRC_CPERI1 0x4204 #define DIV_TOP0 0x10510 #define DIV_TOP1 0x10514 +#define DIV_FSYS0 0x10548 #define DIV_FSYS1 0x1054c #define DIV_FSYS2 0x10550 #define DIV_PERIC0 0x10558 +#define DIV_PERIC3 0x10564 #define SRC_TOP0 0x10210 #define SRC_TOP1 0x10214 #define SRC_TOP2 0x10218 @@ -44,6 +46,8 @@ #define SRC_MASK_FSYS 0x10340 #define SRC_MASK_PERIC0 0x10350 #define GATE_BUS_FSYS0 0x10740 +#define GATE_TOP_SCLK_FSYS 0x10840 +#define GATE_TOP_SCLK_PERIC 0x10850 #define GATE_IP_FSYS 0x10944 #define GATE_IP_PERIC 0x10950 #define GATE_IP_PERIS 0x10960 @@ -71,6 +75,7 @@ PNAME(mout_kfc_p) = { "mout_kpll", "sclk_mpll", }; PNAME(mpll_user_p) = { "fin_pll", "sclk_mpll", }; PNAME(bpll_user_p) = { "fin_pll", "sclk_bpll", }; PNAME(mpll_bpll_p) = { "sclk_mpll_muxed", "sclk_bpll_muxed", }; +PNAME(sclk_mpll_bpll_p) = { "sclk_mpll_bpll", "fin_pll", }; PNAME(group2_p) = { "fin_pll", "fin_pll", "none", "none", "none", "none", "sclk_mpll_bpll", @@ -96,10 +101,14 @@ static const struct samsung_mux_clock exynos5410_mux_clks[] __initconst = { MUX(0, "mout_mmc0", group2_p, SRC_FSYS, 0, 4), MUX(0, "mout_mmc1", group2_p, SRC_FSYS, 4, 4), MUX(0, "mout_mmc2", group2_p, SRC_FSYS, 8, 4), + MUX(0, "mout_usbd300", sclk_mpll_bpll_p, SRC_FSYS, 28, 1), + MUX(0, "mout_usbd301", sclk_mpll_bpll_p, SRC_FSYS, 29, 1), MUX(0, "mout_uart0", group2_p, SRC_PERIC0, 0, 4), MUX(0, "mout_uart1", group2_p, SRC_PERIC0, 4, 4), MUX(0, "mout_uart2", group2_p, SRC_PERIC0, 8, 4), + MUX(0, "mout_uart3", group2_p, SRC_PERIC0, 12, 4), + MUX(0, "mout_pwm", group2_p, SRC_PERIC0, 24, 4), MUX(0, "mout_aclk200", mpll_bpll_p, SRC_TOP0, 12, 1), MUX(0, "mout_aclk400", mpll_bpll_p, SRC_TOP0, 20, 1), @@ -121,6 +130,11 @@ static const struct samsung_div_clock exynos5410_div_clks[] __initconst = { DIV(0, "aclk66_pre", "sclk_mpll_muxed", DIV_TOP1, 24, 3), DIV(0, "aclk66", "aclk66_pre", DIV_TOP0, 0, 3), + DIV(0, "dout_usbphy300", "mout_usbd300", DIV_FSYS0, 16, 4), + DIV(0, "dout_usbphy301", "mout_usbd301", DIV_FSYS0, 20, 4), + DIV(0, "dout_usbd300", "mout_usbd300", DIV_FSYS0, 24, 4), + DIV(0, "dout_usbd301", "mout_usbd301", DIV_FSYS0, 28, 4), + DIV(0, "div_mmc0", "mout_mmc0", DIV_FSYS1, 0, 4), DIV(0, "div_mmc1", "mout_mmc1", DIV_FSYS1, 16, 4), DIV(0, "div_mmc2", "mout_mmc2", DIV_FSYS2, 0, 4), @@ -137,6 +151,8 @@ static const struct samsung_div_clock exynos5410_div_clks[] __initconst = { DIV(0, "div_uart2", "mout_uart2", DIV_PERIC0, 8, 4), DIV(0, "div_uart3", "mout_uart3", DIV_PERIC0, 12, 4), + DIV(0, "dout_pwm", "mout_pwm", DIV_PERIC3, 0, 4), + DIV(0, "aclk200", "mout_aclk200", DIV_TOP0, 12, 3), DIV(0, "aclk400", "mout_aclk400", DIV_TOP0, 24, 3), }; @@ -155,9 +171,23 @@ static const struct samsung_gate_clock exynos5410_gate_clks[] __initconst = { GATE(CLK_MMC1, "sdmmc1", "aclk200", GATE_BUS_FSYS0, 13, 0, 0), GATE(CLK_MMC2, "sdmmc2", "aclk200", GATE_BUS_FSYS0, 14, 0, 0), + GATE(CLK_SCLK_USBPHY301, "sclk_usbphy301", "dout_usbphy301", + GATE_TOP_SCLK_FSYS, 7, CLK_SET_RATE_PARENT, 0), + GATE(CLK_SCLK_USBPHY300, "sclk_usbphy300", "dout_usbphy300", + GATE_TOP_SCLK_FSYS, 8, CLK_SET_RATE_PARENT, 0), + GATE(CLK_SCLK_USBD300, "sclk_usbd300", "dout_usbd300", + GATE_TOP_SCLK_FSYS, 9, CLK_SET_RATE_PARENT, 0), + GATE(CLK_SCLK_USBD301, "sclk_usbd301", "dout_usbd301", + GATE_TOP_SCLK_FSYS, 10, CLK_SET_RATE_PARENT, 0), + + GATE(CLK_SCLK_PWM, "sclk_pwm", "dout_pwm", + GATE_TOP_SCLK_PERIC, 11, CLK_SET_RATE_PARENT, 0), + GATE(CLK_UART0, "uart0", "aclk66", GATE_IP_PERIC, 0, 0, 0), GATE(CLK_UART1, "uart1", "aclk66", GATE_IP_PERIC, 1, 0, 0), GATE(CLK_UART2, "uart2", "aclk66", GATE_IP_PERIC, 2, 0, 0), + GATE(CLK_UART3, "uart3", "aclk66", GATE_IP_PERIC, 3, 0, 0), + GATE(CLK_PWM, "pwm", "aclk66", GATE_IP_PERIC, 24, 0, 0), GATE(CLK_SCLK_UART0, "sclk_uart0", "div_uart0", SRC_MASK_PERIC0, 0, CLK_SET_RATE_PARENT, 0), @@ -165,6 +195,12 @@ static const struct samsung_gate_clock exynos5410_gate_clks[] __initconst = { SRC_MASK_PERIC0, 4, CLK_SET_RATE_PARENT, 0), GATE(CLK_SCLK_UART2, "sclk_uart2", "div_uart2", SRC_MASK_PERIC0, 8, CLK_SET_RATE_PARENT, 0), + GATE(CLK_SCLK_UART3, "sclk_uart3", "div_uart3", + SRC_MASK_PERIC0, 12, CLK_SET_RATE_PARENT, 0), + + GATE(CLK_USBH20, "usbh20", "aclk200_fsys", GATE_IP_FSYS, 18, 0, 0), + GATE(CLK_USBD300, "usbd300", "aclk200_fsys", GATE_IP_FSYS, 19, 0, 0), + GATE(CLK_USBD301, "usbd301", "aclk200_fsys", GATE_IP_FSYS, 20, 0, 0), }; static const struct samsung_pll_clock exynos5410_plls[nr_plls] __initconst = { -- cgit v1.2.3 From 31d3953f823291c9a6b4650ae6706d9a6974bc80 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sat, 28 May 2016 11:54:30 +0200 Subject: clk: samsung: exynos5410: Add I2C, HSI2C and RTC clocks Add clocks for I2C, USI (HSI2C) and RTC to the Exynos5410 clock driver. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Javier Martinez Canillas Acked-by: Stephen Boyd Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk-exynos5410.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/clk/samsung/clk-exynos5410.c b/drivers/clk/samsung/clk-exynos5410.c index 8ad8d5ece7fa..6a924f80cfe4 100644 --- a/drivers/clk/samsung/clk-exynos5410.c +++ b/drivers/clk/samsung/clk-exynos5410.c @@ -159,6 +159,7 @@ static const struct samsung_div_clock exynos5410_div_clks[] __initconst = { static const struct samsung_gate_clock exynos5410_gate_clks[] __initconst = { GATE(CLK_MCT, "mct", "aclk66", GATE_IP_PERIS, 18, 0, 0), + GATE(CLK_RTC, "rtc", "aclk66", GATE_IP_PERIS, 20, 0, 0), GATE(CLK_SCLK_MMC0, "sclk_mmc0", "div_mmc_pre0", SRC_MASK_FSYS, 0, CLK_SET_RATE_PARENT, 0), @@ -187,6 +188,14 @@ static const struct samsung_gate_clock exynos5410_gate_clks[] __initconst = { GATE(CLK_UART1, "uart1", "aclk66", GATE_IP_PERIC, 1, 0, 0), GATE(CLK_UART2, "uart2", "aclk66", GATE_IP_PERIC, 2, 0, 0), GATE(CLK_UART3, "uart3", "aclk66", GATE_IP_PERIC, 3, 0, 0), + GATE(CLK_I2C0, "i2c0", "aclk66", GATE_IP_PERIC, 6, 0, 0), + GATE(CLK_I2C1, "i2c1", "aclk66", GATE_IP_PERIC, 7, 0, 0), + GATE(CLK_I2C2, "i2c2", "aclk66", GATE_IP_PERIC, 8, 0, 0), + GATE(CLK_I2C3, "i2c3", "aclk66", GATE_IP_PERIC, 9, 0, 0), + GATE(CLK_USI0, "usi0", "aclk66", GATE_IP_PERIC, 10, 0, 0), + GATE(CLK_USI1, "usi1", "aclk66", GATE_IP_PERIC, 11, 0, 0), + GATE(CLK_USI2, "usi2", "aclk66", GATE_IP_PERIC, 12, 0, 0), + GATE(CLK_USI3, "usi3", "aclk66", GATE_IP_PERIC, 13, 0, 0), GATE(CLK_PWM, "pwm", "aclk66", GATE_IP_PERIC, 24, 0, 0), GATE(CLK_SCLK_UART0, "sclk_uart0", "div_uart0", -- cgit v1.2.3 From 41743a19b6ea786bc528c77868b353ab65ed5f3f Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 31 May 2016 20:39:01 +0200 Subject: clk: samsung: exynos5410: Add TMU clock Add clock for TMU to the Exynos5410 clock driver. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Javier Martinez Canillas Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk-exynos5410.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/clk/samsung/clk-exynos5410.c b/drivers/clk/samsung/clk-exynos5410.c index 6a924f80cfe4..2ddf954e0099 100644 --- a/drivers/clk/samsung/clk-exynos5410.c +++ b/drivers/clk/samsung/clk-exynos5410.c @@ -160,6 +160,7 @@ static const struct samsung_div_clock exynos5410_div_clks[] __initconst = { static const struct samsung_gate_clock exynos5410_gate_clks[] __initconst = { GATE(CLK_MCT, "mct", "aclk66", GATE_IP_PERIS, 18, 0, 0), GATE(CLK_RTC, "rtc", "aclk66", GATE_IP_PERIS, 20, 0, 0), + GATE(CLK_TMU, "tmu", "aclk66", GATE_IP_PERIS, 21, 0, 0), GATE(CLK_SCLK_MMC0, "sclk_mmc0", "div_mmc_pre0", SRC_MASK_FSYS, 0, CLK_SET_RATE_PARENT, 0), -- cgit v1.2.3 From 34cba900375ec1751a87d3655ad03b9a5b022362 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Tue, 24 May 2016 13:41:01 -0400 Subject: clk: samsung: exynos5420: Set ID for aclk333 gate clock The aclk333 clock needs to be ungated during the MFC power domain switch, so set the clock ID to allow the Exynos power domain logic to lookup this clock if is defined in the MFC PD device tree node. Signed-off-by: Javier Martinez Canillas Reviewed-by: Krzysztof Kozlowski Tested-by: Marek Szyprowski Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk-exynos5420.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/samsung/clk-exynos5420.c b/drivers/clk/samsung/clk-exynos5420.c index 95872b7c47c9..bb196ca21a77 100644 --- a/drivers/clk/samsung/clk-exynos5420.c +++ b/drivers/clk/samsung/clk-exynos5420.c @@ -946,7 +946,7 @@ static const struct samsung_gate_clock exynos5x_gate_clks[] __initconst = { GATE_BUS_TOP, 13, 0, 0), GATE(0, "aclk166", "mout_user_aclk166", GATE_BUS_TOP, 14, CLK_IGNORE_UNUSED, 0), - GATE(0, "aclk333", "mout_user_aclk333", + GATE(CLK_ACLK333, "aclk333", "mout_user_aclk333", GATE_BUS_TOP, 15, CLK_IGNORE_UNUSED, 0), GATE(0, "aclk400_isp", "mout_user_aclk400_isp", GATE_BUS_TOP, 16, 0, 0), -- cgit v1.2.3 From f4f4dd0c45676fa3fc7683046f3acc862a088fed Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 17 May 2016 09:26:14 +0200 Subject: clk: samsung: Suppress unbinding to prevent theoretical attacks Although unbinding a driver requires root privileges but it still might be used theoretically in certain attacks (by triggering NULL pointer exception or memory corruption if driver does not provide proper remove callbacks or core does not handle it). Samsung clock drivers are essential for system operation so their removal is not expected. More over, the Exynos3250 ISP clock driver does not implement remove() driver callback and it is not buildable as modules. Suppress the unbind interface for Exynos3250 ISP and S3C2410 DCLK clock drivers. Suggested-by: Marek Szyprowski Signed-off-by: Krzysztof Kozlowski Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk-exynos3250.c | 1 + drivers/clk/samsung/clk-s3c2410-dclk.c | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/clk/samsung/clk-exynos3250.c b/drivers/clk/samsung/clk-exynos3250.c index b2513959252d..1b81e283f605 100644 --- a/drivers/clk/samsung/clk-exynos3250.c +++ b/drivers/clk/samsung/clk-exynos3250.c @@ -1087,6 +1087,7 @@ static const struct of_device_id exynos3250_cmu_isp_of_match[] __initconst = { static struct platform_driver exynos3250_cmu_isp_driver __initdata = { .driver = { .name = "exynos3250-cmu-isp", + .suppress_bind_attrs = true, .of_match_table = exynos3250_cmu_isp_of_match, }, }; diff --git a/drivers/clk/samsung/clk-s3c2410-dclk.c b/drivers/clk/samsung/clk-s3c2410-dclk.c index ec6fb14d951c..ae9a595c72d0 100644 --- a/drivers/clk/samsung/clk-s3c2410-dclk.c +++ b/drivers/clk/samsung/clk-s3c2410-dclk.c @@ -428,8 +428,9 @@ MODULE_DEVICE_TABLE(platform, s3c24xx_dclk_driver_ids); static struct platform_driver s3c24xx_dclk_driver = { .driver = { - .name = "s3c24xx-dclk", - .pm = &s3c24xx_dclk_pm_ops, + .name = "s3c24xx-dclk", + .pm = &s3c24xx_dclk_pm_ops, + .suppress_bind_attrs = true, }, .probe = s3c24xx_dclk_probe, .remove = s3c24xx_dclk_remove, -- cgit v1.2.3 From 0c0cd59a4c31aa0dccb49450fca5e36d1759f1ca Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 May 2016 15:19:15 +0200 Subject: clk: samsung: exynos5433: prepare for adding CPU clocks Open-code samsung_cmu_register_one() calls for CMU_APOLLO and CMU_ATLAS setup code as a preparation for adding CPU clocks support for Exynos5433. There should be no functional change resulting from this patch. Cc: Kukjin Kim CC: Krzysztof Kozlowski Signed-off-by: Bartlomiej Zolnierkiewicz Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk-exynos5433.c | 85 +++++++++++++++++++++++------------- drivers/clk/samsung/clk.c | 12 ++--- drivers/clk/samsung/clk.h | 4 ++ 3 files changed, 65 insertions(+), 36 deletions(-) diff --git a/drivers/clk/samsung/clk-exynos5433.c b/drivers/clk/samsung/clk-exynos5433.c index 5993bd5ac6ba..70e1df6fc825 100644 --- a/drivers/clk/samsung/clk-exynos5433.c +++ b/drivers/clk/samsung/clk-exynos5433.c @@ -11,6 +11,7 @@ #include #include +#include #include @@ -3594,23 +3595,35 @@ static const struct samsung_gate_clock apollo_gate_clks[] __initconst = { CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0), }; -static const struct samsung_cmu_info apollo_cmu_info __initconst = { - .pll_clks = apollo_pll_clks, - .nr_pll_clks = ARRAY_SIZE(apollo_pll_clks), - .mux_clks = apollo_mux_clks, - .nr_mux_clks = ARRAY_SIZE(apollo_mux_clks), - .div_clks = apollo_div_clks, - .nr_div_clks = ARRAY_SIZE(apollo_div_clks), - .gate_clks = apollo_gate_clks, - .nr_gate_clks = ARRAY_SIZE(apollo_gate_clks), - .nr_clk_ids = APOLLO_NR_CLK, - .clk_regs = apollo_clk_regs, - .nr_clk_regs = ARRAY_SIZE(apollo_clk_regs), -}; - static void __init exynos5433_cmu_apollo_init(struct device_node *np) { - samsung_cmu_register_one(np, &apollo_cmu_info); + void __iomem *reg_base; + struct samsung_clk_provider *ctx; + + reg_base = of_iomap(np, 0); + if (!reg_base) { + panic("%s: failed to map registers\n", __func__); + return; + } + + ctx = samsung_clk_init(np, reg_base, APOLLO_NR_CLK); + if (!ctx) { + panic("%s: unable to allocate ctx\n", __func__); + return; + } + + samsung_clk_register_pll(ctx, apollo_pll_clks, + ARRAY_SIZE(apollo_pll_clks), reg_base); + samsung_clk_register_mux(ctx, apollo_mux_clks, + ARRAY_SIZE(apollo_mux_clks)); + samsung_clk_register_div(ctx, apollo_div_clks, + ARRAY_SIZE(apollo_div_clks)); + samsung_clk_register_gate(ctx, apollo_gate_clks, + ARRAY_SIZE(apollo_gate_clks)); + samsung_clk_sleep_init(reg_base, apollo_clk_regs, + ARRAY_SIZE(apollo_clk_regs)); + + samsung_clk_of_add_provider(np, ctx); } CLK_OF_DECLARE(exynos5433_cmu_apollo, "samsung,exynos5433-cmu-apollo", exynos5433_cmu_apollo_init); @@ -3806,23 +3819,35 @@ static const struct samsung_gate_clock atlas_gate_clks[] __initconst = { CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0), }; -static const struct samsung_cmu_info atlas_cmu_info __initconst = { - .pll_clks = atlas_pll_clks, - .nr_pll_clks = ARRAY_SIZE(atlas_pll_clks), - .mux_clks = atlas_mux_clks, - .nr_mux_clks = ARRAY_SIZE(atlas_mux_clks), - .div_clks = atlas_div_clks, - .nr_div_clks = ARRAY_SIZE(atlas_div_clks), - .gate_clks = atlas_gate_clks, - .nr_gate_clks = ARRAY_SIZE(atlas_gate_clks), - .nr_clk_ids = ATLAS_NR_CLK, - .clk_regs = atlas_clk_regs, - .nr_clk_regs = ARRAY_SIZE(atlas_clk_regs), -}; - static void __init exynos5433_cmu_atlas_init(struct device_node *np) { - samsung_cmu_register_one(np, &atlas_cmu_info); + void __iomem *reg_base; + struct samsung_clk_provider *ctx; + + reg_base = of_iomap(np, 0); + if (!reg_base) { + panic("%s: failed to map registers\n", __func__); + return; + } + + ctx = samsung_clk_init(np, reg_base, ATLAS_NR_CLK); + if (!ctx) { + panic("%s: unable to allocate ctx\n", __func__); + return; + } + + samsung_clk_register_pll(ctx, atlas_pll_clks, + ARRAY_SIZE(atlas_pll_clks), reg_base); + samsung_clk_register_mux(ctx, atlas_mux_clks, + ARRAY_SIZE(atlas_mux_clks)); + samsung_clk_register_div(ctx, atlas_div_clks, + ARRAY_SIZE(atlas_div_clks)); + samsung_clk_register_gate(ctx, atlas_gate_clks, + ARRAY_SIZE(atlas_gate_clks)); + samsung_clk_sleep_init(reg_base, atlas_clk_regs, + ARRAY_SIZE(atlas_clk_regs)); + + samsung_clk_of_add_provider(np, ctx); } CLK_OF_DECLARE(exynos5433_cmu_atlas, "samsung,exynos5433-cmu-atlas", exynos5433_cmu_atlas_init); diff --git a/drivers/clk/samsung/clk.c b/drivers/clk/samsung/clk.c index e4d14589cc4a..b7d87d6db9dc 100644 --- a/drivers/clk/samsung/clk.c +++ b/drivers/clk/samsung/clk.c @@ -346,9 +346,9 @@ static struct syscore_ops samsung_clk_syscore_ops = { .resume = samsung_clk_resume, }; -static void samsung_clk_sleep_init(void __iomem *reg_base, - const unsigned long *rdump, - unsigned long nr_rdump) +void samsung_clk_sleep_init(void __iomem *reg_base, + const unsigned long *rdump, + unsigned long nr_rdump) { struct samsung_clock_reg_cache *reg_cache; @@ -370,9 +370,9 @@ static void samsung_clk_sleep_init(void __iomem *reg_base, } #else -static void samsung_clk_sleep_init(void __iomem *reg_base, - const unsigned long *rdump, - unsigned long nr_rdump) {} +void samsung_clk_sleep_init(void __iomem *reg_base, + const unsigned long *rdump, + unsigned long nr_rdump) {} #endif /* diff --git a/drivers/clk/samsung/clk.h b/drivers/clk/samsung/clk.h index 77d4657a95c5..da3bdebabf1e 100644 --- a/drivers/clk/samsung/clk.h +++ b/drivers/clk/samsung/clk.h @@ -399,6 +399,10 @@ extern struct samsung_clk_provider __init *samsung_cmu_register_one( extern unsigned long _get_rate(const char *clk_name); +extern void samsung_clk_sleep_init(void __iomem *reg_base, + const unsigned long *rdump, + unsigned long nr_rdump); + extern void samsung_clk_save(void __iomem *base, struct samsung_clk_reg_dump *rd, unsigned int num_regs); -- cgit v1.2.3 From 53f69967dca340d79c8dda0734b8912241cb4d31 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 May 2016 15:19:16 +0200 Subject: clk: samsung: cpu: prepare for adding Exynos5433 CPU clocks Exynos5433 uses different register layout for CPU clock registers than earlier SoCs so add new code for handling this layout. Also add new CLK_CPU_HAS_E5433_REGS_LAYOUT flag to request using it. There should be no functional change resulting from this patch. Cc: Kukjin Kim CC: Krzysztof Kozlowski Signed-off-by: Bartlomiej Zolnierkiewicz Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk-cpu.c | 131 +++++++++++++++++++++++++++++++++++++++++- drivers/clk/samsung/clk-cpu.h | 4 +- 2 files changed, 133 insertions(+), 2 deletions(-) diff --git a/drivers/clk/samsung/clk-cpu.c b/drivers/clk/samsung/clk-cpu.c index 813003d6ce09..8bf7e805fd34 100644 --- a/drivers/clk/samsung/clk-cpu.c +++ b/drivers/clk/samsung/clk-cpu.c @@ -45,6 +45,13 @@ #define E4210_DIV_STAT_CPU0 0x400 #define E4210_DIV_STAT_CPU1 0x404 +#define E5433_MUX_SEL2 0x008 +#define E5433_MUX_STAT2 0x208 +#define E5433_DIV_CPU0 0x400 +#define E5433_DIV_CPU1 0x404 +#define E5433_DIV_STAT_CPU0 0x500 +#define E5433_DIV_STAT_CPU1 0x504 + #define E4210_DIV0_RATIO0_MASK 0x7 #define E4210_DIV1_HPM_MASK (0x7 << 4) #define E4210_DIV1_COPY_MASK (0x7 << 0) @@ -252,6 +259,102 @@ static int exynos_cpuclk_post_rate_change(struct clk_notifier_data *ndata, return 0; } +/* + * Helper function to set the 'safe' dividers for the CPU clock. The parameters + * div and mask contain the divider value and the register bit mask of the + * dividers to be programmed. + */ +static void exynos5433_set_safe_div(void __iomem *base, unsigned long div, + unsigned long mask) +{ + unsigned long div0; + + div0 = readl(base + E5433_DIV_CPU0); + div0 = (div0 & ~mask) | (div & mask); + writel(div0, base + E5433_DIV_CPU0); + wait_until_divider_stable(base + E5433_DIV_STAT_CPU0, mask); +} + +/* handler for pre-rate change notification from parent clock */ +static int exynos5433_cpuclk_pre_rate_change(struct clk_notifier_data *ndata, + struct exynos_cpuclk *cpuclk, void __iomem *base) +{ + const struct exynos_cpuclk_cfg_data *cfg_data = cpuclk->cfg; + unsigned long alt_prate = clk_get_rate(cpuclk->alt_parent); + unsigned long alt_div = 0, alt_div_mask = DIV_MASK; + unsigned long div0, div1 = 0, mux_reg; + unsigned long flags; + + /* find out the divider values to use for clock data */ + while ((cfg_data->prate * 1000) != ndata->new_rate) { + if (cfg_data->prate == 0) + return -EINVAL; + cfg_data++; + } + + spin_lock_irqsave(cpuclk->lock, flags); + + /* + * For the selected PLL clock frequency, get the pre-defined divider + * values. + */ + div0 = cfg_data->div0; + div1 = cfg_data->div1; + + /* + * If the old parent clock speed is less than the clock speed of + * the alternate parent, then it should be ensured that at no point + * the armclk speed is more than the old_prate until the dividers are + * set. Also workaround the issue of the dividers being set to lower + * values before the parent clock speed is set to new lower speed + * (this can result in too high speed of armclk output clocks). + */ + if (alt_prate > ndata->old_rate || ndata->old_rate > ndata->new_rate) { + unsigned long tmp_rate = min(ndata->old_rate, ndata->new_rate); + + alt_div = DIV_ROUND_UP(alt_prate, tmp_rate) - 1; + WARN_ON(alt_div >= MAX_DIV); + + exynos5433_set_safe_div(base, alt_div, alt_div_mask); + div0 |= alt_div; + } + + /* select the alternate parent */ + mux_reg = readl(base + E5433_MUX_SEL2); + writel(mux_reg | 1, base + E5433_MUX_SEL2); + wait_until_mux_stable(base + E5433_MUX_STAT2, 0, 2); + + /* alternate parent is active now. set the dividers */ + writel(div0, base + E5433_DIV_CPU0); + wait_until_divider_stable(base + E5433_DIV_STAT_CPU0, DIV_MASK_ALL); + + writel(div1, base + E5433_DIV_CPU1); + wait_until_divider_stable(base + E5433_DIV_STAT_CPU1, DIV_MASK_ALL); + + spin_unlock_irqrestore(cpuclk->lock, flags); + return 0; +} + +/* handler for post-rate change notification from parent clock */ +static int exynos5433_cpuclk_post_rate_change(struct clk_notifier_data *ndata, + struct exynos_cpuclk *cpuclk, void __iomem *base) +{ + unsigned long div = 0, div_mask = DIV_MASK; + unsigned long mux_reg; + unsigned long flags; + + spin_lock_irqsave(cpuclk->lock, flags); + + /* select apll as the alternate parent */ + mux_reg = readl(base + E5433_MUX_SEL2); + writel(mux_reg & ~1, base + E5433_MUX_SEL2); + wait_until_mux_stable(base + E5433_MUX_STAT2, 0, 1); + + exynos5433_set_safe_div(base, div, div_mask); + spin_unlock_irqrestore(cpuclk->lock, flags); + return 0; +} + /* * This notifier function is called for the pre-rate and post-rate change * notifications of the parent clock of cpuclk. @@ -275,6 +378,29 @@ static int exynos_cpuclk_notifier_cb(struct notifier_block *nb, return notifier_from_errno(err); } +/* + * This notifier function is called for the pre-rate and post-rate change + * notifications of the parent clock of cpuclk. + */ +static int exynos5433_cpuclk_notifier_cb(struct notifier_block *nb, + unsigned long event, void *data) +{ + struct clk_notifier_data *ndata = data; + struct exynos_cpuclk *cpuclk; + void __iomem *base; + int err = 0; + + cpuclk = container_of(nb, struct exynos_cpuclk, clk_nb); + base = cpuclk->ctrl_base; + + if (event == PRE_RATE_CHANGE) + err = exynos5433_cpuclk_pre_rate_change(ndata, cpuclk, base); + else if (event == POST_RATE_CHANGE) + err = exynos5433_cpuclk_post_rate_change(ndata, cpuclk, base); + + return notifier_from_errno(err); +} + /* helper function to register a CPU clock */ int __init exynos_register_cpu_clock(struct samsung_clk_provider *ctx, unsigned int lookup_id, const char *name, const char *parent, @@ -301,7 +427,10 @@ int __init exynos_register_cpu_clock(struct samsung_clk_provider *ctx, cpuclk->ctrl_base = ctx->reg_base + offset; cpuclk->lock = &ctx->lock; cpuclk->flags = flags; - cpuclk->clk_nb.notifier_call = exynos_cpuclk_notifier_cb; + if (flags & CLK_CPU_HAS_E5433_REGS_LAYOUT) + cpuclk->clk_nb.notifier_call = exynos5433_cpuclk_notifier_cb; + else + cpuclk->clk_nb.notifier_call = exynos_cpuclk_notifier_cb; cpuclk->alt_parent = __clk_lookup(alt_parent); if (!cpuclk->alt_parent) { diff --git a/drivers/clk/samsung/clk-cpu.h b/drivers/clk/samsung/clk-cpu.h index 37874d3c3165..d4b6b517fe1b 100644 --- a/drivers/clk/samsung/clk-cpu.h +++ b/drivers/clk/samsung/clk-cpu.h @@ -57,10 +57,12 @@ struct exynos_cpuclk { struct notifier_block clk_nb; unsigned long flags; -/* The CPU clock registers has DIV1 configuration register */ +/* The CPU clock registers have DIV1 configuration register */ #define CLK_CPU_HAS_DIV1 (1 << 0) /* When ALT parent is active, debug clocks need safe divider values */ #define CLK_CPU_NEEDS_DEBUG_ALT_DIV (1 << 1) +/* The CPU clock registers have Exynos5433-compatible layout */ +#define CLK_CPU_HAS_E5433_REGS_LAYOUT (1 << 2) }; extern int __init exynos_register_cpu_clock(struct samsung_clk_provider *ctx, -- cgit v1.2.3 From d7d7115d498a97a6deb782a20c689a452e77dc28 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 May 2016 15:19:17 +0200 Subject: clk: samsung: exynos5433: add CPU clocks configuration data and instantiate CPU clocks Add the CPU clocks configuration data and instantiate the CPU clocks type for Exynos5433. Cc: Kukjin Kim CC: Krzysztof Kozlowski Signed-off-by: Bartlomiej Zolnierkiewicz Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk-exynos5433.c | 72 ++++++++++++++++++++++++++++++++---- 1 file changed, 64 insertions(+), 8 deletions(-) diff --git a/drivers/clk/samsung/clk-exynos5433.c b/drivers/clk/samsung/clk-exynos5433.c index 70e1df6fc825..1d14d1cc1296 100644 --- a/drivers/clk/samsung/clk-exynos5433.c +++ b/drivers/clk/samsung/clk-exynos5433.c @@ -16,6 +16,7 @@ #include #include "clk.h" +#include "clk-cpu.h" #include "clk-pll.h" /* @@ -3509,7 +3510,8 @@ static const struct samsung_pll_clock apollo_pll_clks[] __initconst = { static const struct samsung_mux_clock apollo_mux_clks[] __initconst = { /* MUX_SEL_APOLLO0 */ MUX_F(CLK_MOUT_APOLLO_PLL, "mout_apollo_pll", mout_apollo_pll_p, - MUX_SEL_APOLLO0, 0, 1, CLK_SET_RATE_PARENT, 0), + MUX_SEL_APOLLO0, 0, 1, CLK_SET_RATE_PARENT | + CLK_RECALC_NEW_RATES, 0), /* MUX_SEL_APOLLO1 */ MUX(CLK_MOUT_BUS_PLL_APOLLO_USER, "mout_bus_pll_apollo_user", @@ -3590,9 +3592,27 @@ static const struct samsung_gate_clock apollo_gate_clks[] __initconst = { ENABLE_SCLK_APOLLO, 3, CLK_IGNORE_UNUSED, 0), GATE(CLK_SCLK_HPM_APOLLO, "sclk_hpm_apollo", "div_sclk_hpm_apollo", ENABLE_SCLK_APOLLO, 1, CLK_IGNORE_UNUSED, 0), - GATE(CLK_SCLK_APOLLO, "sclk_apollo", "div_apollo2", - ENABLE_SCLK_APOLLO, 0, - CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0), +}; + +#define E5433_APOLLO_DIV0(cntclk, pclk_dbg, atclk, pclk, aclk) \ + (((cntclk) << 24) | ((pclk_dbg) << 20) | ((atclk) << 16) | \ + ((pclk) << 12) | ((aclk) << 8)) + +#define E5433_APOLLO_DIV1(hpm, copy) \ + (((hpm) << 4) | ((copy) << 0)) + +static const struct exynos_cpuclk_cfg_data exynos5433_apolloclk_d[] __initconst = { + { 1300000, E5433_APOLLO_DIV0(3, 7, 7, 7, 2), E5433_APOLLO_DIV1(7, 1), }, + { 1200000, E5433_APOLLO_DIV0(3, 7, 7, 7, 2), E5433_APOLLO_DIV1(7, 1), }, + { 1100000, E5433_APOLLO_DIV0(3, 7, 7, 7, 2), E5433_APOLLO_DIV1(7, 1), }, + { 1000000, E5433_APOLLO_DIV0(3, 7, 7, 7, 2), E5433_APOLLO_DIV1(7, 1), }, + { 900000, E5433_APOLLO_DIV0(3, 7, 7, 7, 2), E5433_APOLLO_DIV1(7, 1), }, + { 800000, E5433_APOLLO_DIV0(3, 7, 7, 7, 2), E5433_APOLLO_DIV1(7, 1), }, + { 700000, E5433_APOLLO_DIV0(3, 7, 7, 7, 2), E5433_APOLLO_DIV1(7, 1), }, + { 600000, E5433_APOLLO_DIV0(3, 7, 7, 7, 1), E5433_APOLLO_DIV1(7, 1), }, + { 500000, E5433_APOLLO_DIV0(3, 7, 7, 7, 1), E5433_APOLLO_DIV1(7, 1), }, + { 400000, E5433_APOLLO_DIV0(3, 7, 7, 7, 1), E5433_APOLLO_DIV1(7, 1), }, + { 0 }, }; static void __init exynos5433_cmu_apollo_init(struct device_node *np) @@ -3620,6 +3640,12 @@ static void __init exynos5433_cmu_apollo_init(struct device_node *np) ARRAY_SIZE(apollo_div_clks)); samsung_clk_register_gate(ctx, apollo_gate_clks, ARRAY_SIZE(apollo_gate_clks)); + + exynos_register_cpu_clock(ctx, CLK_SCLK_APOLLO, "apolloclk", + mout_apollo_p[0], mout_apollo_p[1], 0x200, + exynos5433_apolloclk_d, ARRAY_SIZE(exynos5433_apolloclk_d), + CLK_CPU_HAS_E5433_REGS_LAYOUT); + samsung_clk_sleep_init(reg_base, apollo_clk_regs, ARRAY_SIZE(apollo_clk_regs)); @@ -3707,7 +3733,8 @@ static const struct samsung_pll_clock atlas_pll_clks[] __initconst = { static const struct samsung_mux_clock atlas_mux_clks[] __initconst = { /* MUX_SEL_ATLAS0 */ MUX_F(CLK_MOUT_ATLAS_PLL, "mout_atlas_pll", mout_atlas_pll_p, - MUX_SEL_ATLAS0, 0, 1, CLK_SET_RATE_PARENT, 0), + MUX_SEL_ATLAS0, 0, 1, CLK_SET_RATE_PARENT | + CLK_RECALC_NEW_RATES, 0), /* MUX_SEL_ATLAS1 */ MUX(CLK_MOUT_BUS_PLL_ATLAS_USER, "mout_bus_pll_atlas_user", @@ -3814,9 +3841,32 @@ static const struct samsung_gate_clock atlas_gate_clks[] __initconst = { ENABLE_SCLK_ATLAS, 2, CLK_IGNORE_UNUSED, 0), GATE(CLK_ATCLK, "atclk", "div_atclk_atlas", ENABLE_SCLK_ATLAS, 1, CLK_IGNORE_UNUSED, 0), - GATE(CLK_SCLK_ATLAS, "sclk_atlas", "div_atlas2", - ENABLE_SCLK_ATLAS, 0, - CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0), +}; + +#define E5433_ATLAS_DIV0(cntclk, pclk_dbg, atclk, pclk, aclk) \ + (((cntclk) << 24) | ((pclk_dbg) << 20) | ((atclk) << 16) | \ + ((pclk) << 12) | ((aclk) << 8)) + +#define E5433_ATLAS_DIV1(hpm, copy) \ + (((hpm) << 4) | ((copy) << 0)) + +static const struct exynos_cpuclk_cfg_data exynos5433_atlasclk_d[] __initconst = { + { 1900000, E5433_ATLAS_DIV0(7, 7, 7, 7, 4), E5433_ATLAS_DIV1(7, 1), }, + { 1800000, E5433_ATLAS_DIV0(7, 7, 7, 7, 4), E5433_ATLAS_DIV1(7, 1), }, + { 1700000, E5433_ATLAS_DIV0(7, 7, 7, 7, 4), E5433_ATLAS_DIV1(7, 1), }, + { 1600000, E5433_ATLAS_DIV0(7, 7, 7, 7, 4), E5433_ATLAS_DIV1(7, 1), }, + { 1500000, E5433_ATLAS_DIV0(7, 7, 7, 7, 3), E5433_ATLAS_DIV1(7, 1), }, + { 1400000, E5433_ATLAS_DIV0(7, 7, 7, 7, 3), E5433_ATLAS_DIV1(7, 1), }, + { 1300000, E5433_ATLAS_DIV0(7, 7, 7, 7, 3), E5433_ATLAS_DIV1(7, 1), }, + { 1200000, E5433_ATLAS_DIV0(7, 7, 7, 7, 3), E5433_ATLAS_DIV1(7, 1), }, + { 1100000, E5433_ATLAS_DIV0(7, 7, 7, 7, 3), E5433_ATLAS_DIV1(7, 1), }, + { 1000000, E5433_ATLAS_DIV0(7, 7, 7, 7, 3), E5433_ATLAS_DIV1(7, 1), }, + { 900000, E5433_ATLAS_DIV0(7, 7, 7, 7, 2), E5433_ATLAS_DIV1(7, 1), }, + { 800000, E5433_ATLAS_DIV0(7, 7, 7, 7, 2), E5433_ATLAS_DIV1(7, 1), }, + { 700000, E5433_ATLAS_DIV0(7, 7, 7, 7, 2), E5433_ATLAS_DIV1(7, 1), }, + { 600000, E5433_ATLAS_DIV0(7, 7, 7, 7, 2), E5433_ATLAS_DIV1(7, 1), }, + { 500000, E5433_ATLAS_DIV0(7, 7, 7, 7, 2), E5433_ATLAS_DIV1(7, 1), }, + { 0 }, }; static void __init exynos5433_cmu_atlas_init(struct device_node *np) @@ -3844,6 +3894,12 @@ static void __init exynos5433_cmu_atlas_init(struct device_node *np) ARRAY_SIZE(atlas_div_clks)); samsung_clk_register_gate(ctx, atlas_gate_clks, ARRAY_SIZE(atlas_gate_clks)); + + exynos_register_cpu_clock(ctx, CLK_SCLK_ATLAS, "atlasclk", + mout_atlas_p[0], mout_atlas_p[1], 0x200, + exynos5433_atlasclk_d, ARRAY_SIZE(exynos5433_atlasclk_d), + CLK_CPU_HAS_E5433_REGS_LAYOUT); + samsung_clk_sleep_init(reg_base, atlas_clk_regs, ARRAY_SIZE(atlas_clk_regs)); -- cgit v1.2.3 From 05af240fe823a6163a9081c106167f2e41d521ee Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 1 Jun 2016 11:45:50 +0200 Subject: clk: samsung: exynos5410: Add WDT, ACLK266 and SSS clocks Add clock hierarchy for Security SubSystem clock and watchdog. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Javier Martinez Canillas Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk-exynos5410.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/clk/samsung/clk-exynos5410.c b/drivers/clk/samsung/clk-exynos5410.c index 2ddf954e0099..54ec486a5e45 100644 --- a/drivers/clk/samsung/clk-exynos5410.c +++ b/drivers/clk/samsung/clk-exynos5410.c @@ -31,6 +31,7 @@ #define SRC_CPU 0x200 #define DIV_CPU0 0x500 #define SRC_CPERI1 0x4204 +#define GATE_IP_G2D 0x8800 #define DIV_TOP0 0x10510 #define DIV_TOP1 0x10514 #define DIV_FSYS0 0x10548 @@ -154,11 +155,14 @@ static const struct samsung_div_clock exynos5410_div_clks[] __initconst = { DIV(0, "dout_pwm", "mout_pwm", DIV_PERIC3, 0, 4), DIV(0, "aclk200", "mout_aclk200", DIV_TOP0, 12, 3), + DIV(0, "aclk266", "mpll_user_p", DIV_TOP0, 16, 3), DIV(0, "aclk400", "mout_aclk400", DIV_TOP0, 24, 3), }; static const struct samsung_gate_clock exynos5410_gate_clks[] __initconst = { + GATE(CLK_SSS, "sss", "aclk266", GATE_IP_G2D, 2, 0, 0), GATE(CLK_MCT, "mct", "aclk66", GATE_IP_PERIS, 18, 0, 0), + GATE(CLK_WDT, "wdt", "aclk66", GATE_IP_PERIS, 19, 0, 0), GATE(CLK_RTC, "rtc", "aclk66", GATE_IP_PERIS, 20, 0, 0), GATE(CLK_TMU, "tmu", "aclk66", GATE_IP_PERIS, 21, 0, 0), -- cgit v1.2.3 From 1faf8692bdc2da1e12c7f2ecda3a9e629ac9b05b Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 3 May 2016 09:37:08 +0200 Subject: clk: renesas: cpg-mssr: Document r8a7796 support Signed-off-by: Geert Uytterhoeven Acked-by: Rob Herring Tested-by: Simon Horman --- Documentation/devicetree/bindings/clock/renesas,cpg-mssr.txt | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/clock/renesas,cpg-mssr.txt b/Documentation/devicetree/bindings/clock/renesas,cpg-mssr.txt index fefb8023020f..394d725ac7e0 100644 --- a/Documentation/devicetree/bindings/clock/renesas,cpg-mssr.txt +++ b/Documentation/devicetree/bindings/clock/renesas,cpg-mssr.txt @@ -13,7 +13,8 @@ They provide the following functionalities: Required Properties: - compatible: Must be one of: - - "renesas,r8a7795-cpg-mssr" for the r8a7795 SoC + - "renesas,r8a7795-cpg-mssr" for the r8a7795 SoC (R-Car H3) + - "renesas,r8a7796-cpg-mssr" for the r8a7796 SoC (R-Car M3-W) - reg: Base address and length of the memory resource used by the CPG/MSSR block @@ -21,8 +22,8 @@ Required Properties: - clocks: References to external parent clocks, one entry for each entry in clock-names - clock-names: List of external parent clock names. Valid names are: - - "extal" (r8a7795) - - "extalr" (r8a7795) + - "extal" (r8a7795, r8a7796) + - "extalr" (r8a7795, r8a7796) - #clock-cells: Must be 2 - For CPG core clocks, the two clock specifier cells must be "CPG_CORE" -- cgit v1.2.3 From 972610fb23b08dd54879102a9d5be695d53b728b Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 2 May 2016 14:36:32 +0200 Subject: clk: renesas: Add r8a7796 CPG Core Clock Definitions Add all R-Car M3-W Clock Pulse Generator Core Clock Outputs, as listed in Table 8.2b ("List of Clocks [R-Car M3-W]") of the R-Car Gen3 datasheet (rev. 0.51 + Errata for Rev051 Mar 31 2016). Note that internal CPG clocks (S0, S1, S2, S3, SDSRC, and SSPSRC) are not included, as they are used as internal clock sources only, and never referenced from DT. Signed-off-by: Geert Uytterhoeven Tested-by: Simon Horman --- include/dt-bindings/clock/r8a7796-cpg-mssr.h | 69 ++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 include/dt-bindings/clock/r8a7796-cpg-mssr.h diff --git a/include/dt-bindings/clock/r8a7796-cpg-mssr.h b/include/dt-bindings/clock/r8a7796-cpg-mssr.h new file mode 100644 index 000000000000..1e5942695f0d --- /dev/null +++ b/include/dt-bindings/clock/r8a7796-cpg-mssr.h @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2016 Renesas Electronics Corp. + * + * 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. + */ +#ifndef __DT_BINDINGS_CLOCK_R8A7796_CPG_MSSR_H__ +#define __DT_BINDINGS_CLOCK_R8A7796_CPG_MSSR_H__ + +#include + +/* r8a7796 CPG Core Clocks */ +#define R8A7796_CLK_Z 0 +#define R8A7796_CLK_Z2 1 +#define R8A7796_CLK_ZR 2 +#define R8A7796_CLK_ZG 3 +#define R8A7796_CLK_ZTR 4 +#define R8A7796_CLK_ZTRD2 5 +#define R8A7796_CLK_ZT 6 +#define R8A7796_CLK_ZX 7 +#define R8A7796_CLK_S0D1 8 +#define R8A7796_CLK_S0D2 9 +#define R8A7796_CLK_S0D3 10 +#define R8A7796_CLK_S0D4 11 +#define R8A7796_CLK_S0D6 12 +#define R8A7796_CLK_S0D8 13 +#define R8A7796_CLK_S0D12 14 +#define R8A7796_CLK_S1D1 15 +#define R8A7796_CLK_S1D2 16 +#define R8A7796_CLK_S1D4 17 +#define R8A7796_CLK_S2D1 18 +#define R8A7796_CLK_S2D2 19 +#define R8A7796_CLK_S2D4 20 +#define R8A7796_CLK_S3D1 21 +#define R8A7796_CLK_S3D2 22 +#define R8A7796_CLK_S3D4 23 +#define R8A7796_CLK_LB 24 +#define R8A7796_CLK_CL 25 +#define R8A7796_CLK_ZB3 26 +#define R8A7796_CLK_ZB3D2 27 +#define R8A7796_CLK_ZB3D4 28 +#define R8A7796_CLK_CR 29 +#define R8A7796_CLK_CRD2 30 +#define R8A7796_CLK_SD0H 31 +#define R8A7796_CLK_SD0 32 +#define R8A7796_CLK_SD1H 33 +#define R8A7796_CLK_SD1 34 +#define R8A7796_CLK_SD2H 35 +#define R8A7796_CLK_SD2 36 +#define R8A7796_CLK_SD3H 37 +#define R8A7796_CLK_SD3 38 +#define R8A7796_CLK_SSP2 39 +#define R8A7796_CLK_SSP1 40 +#define R8A7796_CLK_SSPRS 41 +#define R8A7796_CLK_RPC 42 +#define R8A7796_CLK_RPCD2 43 +#define R8A7796_CLK_MSO 44 +#define R8A7796_CLK_CANFD 45 +#define R8A7796_CLK_HDMI 46 +#define R8A7796_CLK_CSI0 47 +#define R8A7796_CLK_CSIREF 48 +#define R8A7796_CLK_CP 49 +#define R8A7796_CLK_CPEX 50 +#define R8A7796_CLK_R 51 +#define R8A7796_CLK_OSC 52 + +#endif /* __DT_BINDINGS_CLOCK_R8A7796_CPG_MSSR_H__ */ -- cgit v1.2.3 From 5b1defde7054e66da5c0f6cba8b35cef29edede0 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 4 May 2016 14:32:56 +0200 Subject: clk: renesas: cpg-mssr: Extract common R-Car Gen3 support code Extract the code to support parts common to all members of the R-Car Gen3 SoC family into a separate file, to ease sharing among SoC-specific drivers. Note that while the cpg_pll_configs[] arrays and the selection of the config based on the MODE bits are identical on R-Car H3 and R-Car M3-W, they are not common, and may be different on other R-Car Gen3 SoCs. Signed-off-by: Geert Uytterhoeven Tested-by: Simon Horman --- drivers/clk/renesas/Makefile | 2 +- drivers/clk/renesas/r8a7795-cpg-mssr.c | 360 +-------------------------------- drivers/clk/renesas/rcar-gen3-cpg.c | 359 ++++++++++++++++++++++++++++++++ drivers/clk/renesas/rcar-gen3-cpg.h | 43 ++++ 4 files changed, 408 insertions(+), 356 deletions(-) create mode 100644 drivers/clk/renesas/rcar-gen3-cpg.c create mode 100644 drivers/clk/renesas/rcar-gen3-cpg.h diff --git a/drivers/clk/renesas/Makefile b/drivers/clk/renesas/Makefile index ead8bb843524..88924c95808c 100644 --- a/drivers/clk/renesas/Makefile +++ b/drivers/clk/renesas/Makefile @@ -8,7 +8,7 @@ obj-$(CONFIG_ARCH_R8A7790) += clk-rcar-gen2.o clk-div6.o obj-$(CONFIG_ARCH_R8A7791) += clk-rcar-gen2.o clk-div6.o obj-$(CONFIG_ARCH_R8A7793) += clk-rcar-gen2.o clk-div6.o obj-$(CONFIG_ARCH_R8A7794) += clk-rcar-gen2.o clk-div6.o -obj-$(CONFIG_ARCH_R8A7795) += r8a7795-cpg-mssr.o +obj-$(CONFIG_ARCH_R8A7795) += r8a7795-cpg-mssr.o rcar-gen3-cpg.o obj-$(CONFIG_ARCH_SH73A0) += clk-sh73a0.o clk-div6.o obj-$(CONFIG_CLK_RENESAS_CPG_MSSR) += renesas-cpg-mssr.o clk-div6.o diff --git a/drivers/clk/renesas/r8a7795-cpg-mssr.c b/drivers/clk/renesas/r8a7795-cpg-mssr.c index ca5519c583d4..e53aff5b23ad 100644 --- a/drivers/clk/renesas/r8a7795-cpg-mssr.c +++ b/drivers/clk/renesas/r8a7795-cpg-mssr.c @@ -12,22 +12,14 @@ * the Free Software Foundation; version 2 of the License. */ -#include -#include -#include #include -#include #include -#include #include -#include -#include #include #include "renesas-cpg-mssr.h" - -#define CPG_RCKCR 0x240 +#include "rcar-gen3-cpg.h" enum clk_ids { /* Core Clock Outputs exported to DT */ @@ -58,20 +50,6 @@ enum clk_ids { MOD_CLK_BASE }; -enum r8a7795_clk_types { - CLK_TYPE_GEN3_MAIN = CLK_TYPE_CUSTOM, - CLK_TYPE_GEN3_PLL0, - CLK_TYPE_GEN3_PLL1, - CLK_TYPE_GEN3_PLL2, - CLK_TYPE_GEN3_PLL3, - CLK_TYPE_GEN3_PLL4, - CLK_TYPE_GEN3_SD, - CLK_TYPE_GEN3_R, -}; - -#define DEF_GEN3_SD(_name, _id, _parent, _offset) \ - DEF_BASE(_name, _id, CLK_TYPE_GEN3_SD, _parent, .offset = _offset) - static const struct cpg_core_clk r8a7795_core_clks[] __initconst = { /* External Clock Inputs */ DEF_INPUT("extal", CLK_EXTAL), @@ -262,225 +240,6 @@ static const unsigned int r8a7795_crit_mod_clks[] __initconst = { MOD_CLK_ID(408), /* INTC-AP (GIC) */ }; -/* ----------------------------------------------------------------------------- - * SDn Clock - * - */ -#define CPG_SD_STP_HCK BIT(9) -#define CPG_SD_STP_CK BIT(8) - -#define CPG_SD_STP_MASK (CPG_SD_STP_HCK | CPG_SD_STP_CK) -#define CPG_SD_FC_MASK (0x7 << 2 | 0x3 << 0) - -#define CPG_SD_DIV_TABLE_DATA(stp_hck, stp_ck, sd_srcfc, sd_fc, sd_div) \ -{ \ - .val = ((stp_hck) ? CPG_SD_STP_HCK : 0) | \ - ((stp_ck) ? CPG_SD_STP_CK : 0) | \ - ((sd_srcfc) << 2) | \ - ((sd_fc) << 0), \ - .div = (sd_div), \ -} - -struct sd_div_table { - u32 val; - unsigned int div; -}; - -struct sd_clock { - struct clk_hw hw; - void __iomem *reg; - const struct sd_div_table *div_table; - unsigned int div_num; - unsigned int div_min; - unsigned int div_max; -}; - -/* SDn divider - * sd_srcfc sd_fc div - * stp_hck stp_ck (div) (div) = sd_srcfc x sd_fc - *------------------------------------------------------------------- - * 0 0 0 (1) 1 (4) 4 - * 0 0 1 (2) 1 (4) 8 - * 1 0 2 (4) 1 (4) 16 - * 1 0 3 (8) 1 (4) 32 - * 1 0 4 (16) 1 (4) 64 - * 0 0 0 (1) 0 (2) 2 - * 0 0 1 (2) 0 (2) 4 - * 1 0 2 (4) 0 (2) 8 - * 1 0 3 (8) 0 (2) 16 - * 1 0 4 (16) 0 (2) 32 - */ -static const struct sd_div_table cpg_sd_div_table[] = { -/* CPG_SD_DIV_TABLE_DATA(stp_hck, stp_ck, sd_srcfc, sd_fc, sd_div) */ - CPG_SD_DIV_TABLE_DATA(0, 0, 0, 1, 4), - CPG_SD_DIV_TABLE_DATA(0, 0, 1, 1, 8), - CPG_SD_DIV_TABLE_DATA(1, 0, 2, 1, 16), - CPG_SD_DIV_TABLE_DATA(1, 0, 3, 1, 32), - CPG_SD_DIV_TABLE_DATA(1, 0, 4, 1, 64), - CPG_SD_DIV_TABLE_DATA(0, 0, 0, 0, 2), - CPG_SD_DIV_TABLE_DATA(0, 0, 1, 0, 4), - CPG_SD_DIV_TABLE_DATA(1, 0, 2, 0, 8), - CPG_SD_DIV_TABLE_DATA(1, 0, 3, 0, 16), - CPG_SD_DIV_TABLE_DATA(1, 0, 4, 0, 32), -}; - -#define to_sd_clock(_hw) container_of(_hw, struct sd_clock, hw) - -static int cpg_sd_clock_enable(struct clk_hw *hw) -{ - struct sd_clock *clock = to_sd_clock(hw); - u32 val, sd_fc; - unsigned int i; - - val = clk_readl(clock->reg); - - sd_fc = val & CPG_SD_FC_MASK; - for (i = 0; i < clock->div_num; i++) - if (sd_fc == (clock->div_table[i].val & CPG_SD_FC_MASK)) - break; - - if (i >= clock->div_num) - return -EINVAL; - - val &= ~(CPG_SD_STP_MASK); - val |= clock->div_table[i].val & CPG_SD_STP_MASK; - - clk_writel(val, clock->reg); - - return 0; -} - -static void cpg_sd_clock_disable(struct clk_hw *hw) -{ - struct sd_clock *clock = to_sd_clock(hw); - - clk_writel(clk_readl(clock->reg) | CPG_SD_STP_MASK, clock->reg); -} - -static int cpg_sd_clock_is_enabled(struct clk_hw *hw) -{ - struct sd_clock *clock = to_sd_clock(hw); - - return !(clk_readl(clock->reg) & CPG_SD_STP_MASK); -} - -static unsigned long cpg_sd_clock_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) -{ - struct sd_clock *clock = to_sd_clock(hw); - unsigned long rate = parent_rate; - u32 val, sd_fc; - unsigned int i; - - val = clk_readl(clock->reg); - - sd_fc = val & CPG_SD_FC_MASK; - for (i = 0; i < clock->div_num; i++) - if (sd_fc == (clock->div_table[i].val & CPG_SD_FC_MASK)) - break; - - if (i >= clock->div_num) - return -EINVAL; - - return DIV_ROUND_CLOSEST(rate, clock->div_table[i].div); -} - -static unsigned int cpg_sd_clock_calc_div(struct sd_clock *clock, - unsigned long rate, - unsigned long parent_rate) -{ - unsigned int div; - - if (!rate) - rate = 1; - - div = DIV_ROUND_CLOSEST(parent_rate, rate); - - return clamp_t(unsigned int, div, clock->div_min, clock->div_max); -} - -static long cpg_sd_clock_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *parent_rate) -{ - struct sd_clock *clock = to_sd_clock(hw); - unsigned int div = cpg_sd_clock_calc_div(clock, rate, *parent_rate); - - return DIV_ROUND_CLOSEST(*parent_rate, div); -} - -static int cpg_sd_clock_set_rate(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate) -{ - struct sd_clock *clock = to_sd_clock(hw); - unsigned int div = cpg_sd_clock_calc_div(clock, rate, parent_rate); - u32 val; - unsigned int i; - - for (i = 0; i < clock->div_num; i++) - if (div == clock->div_table[i].div) - break; - - if (i >= clock->div_num) - return -EINVAL; - - val = clk_readl(clock->reg); - val &= ~(CPG_SD_STP_MASK | CPG_SD_FC_MASK); - val |= clock->div_table[i].val & (CPG_SD_STP_MASK | CPG_SD_FC_MASK); - clk_writel(val, clock->reg); - - return 0; -} - -static const struct clk_ops cpg_sd_clock_ops = { - .enable = cpg_sd_clock_enable, - .disable = cpg_sd_clock_disable, - .is_enabled = cpg_sd_clock_is_enabled, - .recalc_rate = cpg_sd_clock_recalc_rate, - .round_rate = cpg_sd_clock_round_rate, - .set_rate = cpg_sd_clock_set_rate, -}; - -static struct clk * __init cpg_sd_clk_register(const struct cpg_core_clk *core, - void __iomem *base, - const char *parent_name) -{ - struct clk_init_data init; - struct sd_clock *clock; - struct clk *clk; - unsigned int i; - - clock = kzalloc(sizeof(*clock), GFP_KERNEL); - if (!clock) - return ERR_PTR(-ENOMEM); - - init.name = core->name; - init.ops = &cpg_sd_clock_ops; - init.flags = CLK_IS_BASIC | CLK_SET_RATE_PARENT; - init.parent_names = &parent_name; - init.num_parents = 1; - - clock->reg = base + core->offset; - clock->hw.init = &init; - clock->div_table = cpg_sd_div_table; - clock->div_num = ARRAY_SIZE(cpg_sd_div_table); - - clock->div_max = clock->div_table[0].div; - clock->div_min = clock->div_max; - for (i = 1; i < clock->div_num; i++) { - clock->div_max = max(clock->div_max, clock->div_table[i].div); - clock->div_min = min(clock->div_min, clock->div_table[i].div); - } - - clk = clk_register(NULL, &clock->hw); - if (IS_ERR(clk)) - kfree(clock); - - return clk; -} - -#define CPG_PLL0CR 0x00d8 -#define CPG_PLL2CR 0x002c -#define CPG_PLL4CR 0x01f4 /* * CPG Clock Data @@ -512,13 +271,7 @@ static struct clk * __init cpg_sd_clk_register(const struct cpg_core_clk *core, (((md) & BIT(19)) >> 18) | \ (((md) & BIT(17)) >> 17)) -struct cpg_pll_config { - unsigned int extal_div; - unsigned int pll1_mult; - unsigned int pll3_mult; -}; - -static const struct cpg_pll_config cpg_pll_configs[16] __initconst = { +static const struct rcar_gen3_cpg_pll_config cpg_pll_configs[16] __initconst = { /* EXTAL div PLL1 mult PLL3 mult */ { 1, 192, 192, }, { 1, 192, 128, }, @@ -538,112 +291,9 @@ static const struct cpg_pll_config cpg_pll_configs[16] __initconst = { { 2, 192, 192, }, }; -static const struct cpg_pll_config *cpg_pll_config __initdata; - -static -struct clk * __init r8a7795_cpg_clk_register(struct device *dev, - const struct cpg_core_clk *core, - const struct cpg_mssr_info *info, - struct clk **clks, - void __iomem *base) -{ - const struct clk *parent; - unsigned int mult = 1; - unsigned int div = 1; - u32 value; - - parent = clks[core->parent]; - if (IS_ERR(parent)) - return ERR_CAST(parent); - - switch (core->type) { - case CLK_TYPE_GEN3_MAIN: - div = cpg_pll_config->extal_div; - break; - - case CLK_TYPE_GEN3_PLL0: - /* - * PLL0 is a configurable multiplier clock. Register it as a - * fixed factor clock for now as there's no generic multiplier - * clock implementation and we currently have no need to change - * the multiplier value. - */ - value = readl(base + CPG_PLL0CR); - mult = (((value >> 24) & 0x7f) + 1) * 2; - break; - - case CLK_TYPE_GEN3_PLL1: - mult = cpg_pll_config->pll1_mult; - break; - - case CLK_TYPE_GEN3_PLL2: - /* - * PLL2 is a configurable multiplier clock. Register it as a - * fixed factor clock for now as there's no generic multiplier - * clock implementation and we currently have no need to change - * the multiplier value. - */ - value = readl(base + CPG_PLL2CR); - mult = (((value >> 24) & 0x7f) + 1) * 2; - break; - - case CLK_TYPE_GEN3_PLL3: - mult = cpg_pll_config->pll3_mult; - break; - - case CLK_TYPE_GEN3_PLL4: - /* - * PLL4 is a configurable multiplier clock. Register it as a - * fixed factor clock for now as there's no generic multiplier - * clock implementation and we currently have no need to change - * the multiplier value. - */ - value = readl(base + CPG_PLL4CR); - mult = (((value >> 24) & 0x7f) + 1) * 2; - break; - - case CLK_TYPE_GEN3_SD: - return cpg_sd_clk_register(core, base, __clk_get_name(parent)); - - case CLK_TYPE_GEN3_R: - /* RINT is default. Only if EXTALR is populated, we switch to it */ - value = readl(base + CPG_RCKCR) & 0x3f; - - if (clk_get_rate(clks[CLK_EXTALR])) { - parent = clks[CLK_EXTALR]; - value |= BIT(15); - } - - writel(value, base + CPG_RCKCR); - break; - - default: - return ERR_PTR(-EINVAL); - } - - return clk_register_fixed_factor(NULL, core->name, - __clk_get_name(parent), 0, mult, div); -} - -/* - * Reset register definitions. - */ -#define MODEMR 0xe6160060 - -static u32 rcar_gen3_read_mode_pins(void) -{ - void __iomem *modemr = ioremap_nocache(MODEMR, 4); - u32 mode; - - BUG_ON(!modemr); - mode = ioread32(modemr); - iounmap(modemr); - - return mode; -} - static int __init r8a7795_cpg_mssr_init(struct device *dev) { + const struct rcar_gen3_cpg_pll_config *cpg_pll_config; u32 cpg_mode = rcar_gen3_read_mode_pins(); cpg_pll_config = &cpg_pll_configs[CPG_PLL_CONFIG_INDEX(cpg_mode)]; @@ -652,7 +302,7 @@ static int __init r8a7795_cpg_mssr_init(struct device *dev) return -EINVAL; } - return 0; + return rcar_gen3_cpg_init(cpg_pll_config, CLK_EXTALR); } const struct cpg_mssr_info r8a7795_cpg_mssr_info __initconst = { @@ -673,5 +323,5 @@ const struct cpg_mssr_info r8a7795_cpg_mssr_info __initconst = { /* Callbacks */ .init = r8a7795_cpg_mssr_init, - .cpg_clk_register = r8a7795_cpg_clk_register, + .cpg_clk_register = rcar_gen3_cpg_clk_register, }; diff --git a/drivers/clk/renesas/rcar-gen3-cpg.c b/drivers/clk/renesas/rcar-gen3-cpg.c new file mode 100644 index 000000000000..bb4f2f9a8c2f --- /dev/null +++ b/drivers/clk/renesas/rcar-gen3-cpg.c @@ -0,0 +1,359 @@ +/* + * R-Car Gen3 Clock Pulse Generator + * + * Copyright (C) 2015-2016 Glider bvba + * + * Based on clk-rcar-gen3.c + * + * Copyright (C) 2015 Renesas Electronics Corp. + * + * 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 of the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "renesas-cpg-mssr.h" +#include "rcar-gen3-cpg.h" + +#define CPG_PLL0CR 0x00d8 +#define CPG_PLL2CR 0x002c +#define CPG_PLL4CR 0x01f4 + + +/* + * SDn Clock + */ +#define CPG_SD_STP_HCK BIT(9) +#define CPG_SD_STP_CK BIT(8) + +#define CPG_SD_STP_MASK (CPG_SD_STP_HCK | CPG_SD_STP_CK) +#define CPG_SD_FC_MASK (0x7 << 2 | 0x3 << 0) + +#define CPG_SD_DIV_TABLE_DATA(stp_hck, stp_ck, sd_srcfc, sd_fc, sd_div) \ +{ \ + .val = ((stp_hck) ? CPG_SD_STP_HCK : 0) | \ + ((stp_ck) ? CPG_SD_STP_CK : 0) | \ + ((sd_srcfc) << 2) | \ + ((sd_fc) << 0), \ + .div = (sd_div), \ +} + +struct sd_div_table { + u32 val; + unsigned int div; +}; + +struct sd_clock { + struct clk_hw hw; + void __iomem *reg; + const struct sd_div_table *div_table; + unsigned int div_num; + unsigned int div_min; + unsigned int div_max; +}; + +/* SDn divider + * sd_srcfc sd_fc div + * stp_hck stp_ck (div) (div) = sd_srcfc x sd_fc + *------------------------------------------------------------------- + * 0 0 0 (1) 1 (4) 4 + * 0 0 1 (2) 1 (4) 8 + * 1 0 2 (4) 1 (4) 16 + * 1 0 3 (8) 1 (4) 32 + * 1 0 4 (16) 1 (4) 64 + * 0 0 0 (1) 0 (2) 2 + * 0 0 1 (2) 0 (2) 4 + * 1 0 2 (4) 0 (2) 8 + * 1 0 3 (8) 0 (2) 16 + * 1 0 4 (16) 0 (2) 32 + */ +static const struct sd_div_table cpg_sd_div_table[] = { +/* CPG_SD_DIV_TABLE_DATA(stp_hck, stp_ck, sd_srcfc, sd_fc, sd_div) */ + CPG_SD_DIV_TABLE_DATA(0, 0, 0, 1, 4), + CPG_SD_DIV_TABLE_DATA(0, 0, 1, 1, 8), + CPG_SD_DIV_TABLE_DATA(1, 0, 2, 1, 16), + CPG_SD_DIV_TABLE_DATA(1, 0, 3, 1, 32), + CPG_SD_DIV_TABLE_DATA(1, 0, 4, 1, 64), + CPG_SD_DIV_TABLE_DATA(0, 0, 0, 0, 2), + CPG_SD_DIV_TABLE_DATA(0, 0, 1, 0, 4), + CPG_SD_DIV_TABLE_DATA(1, 0, 2, 0, 8), + CPG_SD_DIV_TABLE_DATA(1, 0, 3, 0, 16), + CPG_SD_DIV_TABLE_DATA(1, 0, 4, 0, 32), +}; + +#define to_sd_clock(_hw) container_of(_hw, struct sd_clock, hw) + +static int cpg_sd_clock_enable(struct clk_hw *hw) +{ + struct sd_clock *clock = to_sd_clock(hw); + u32 val, sd_fc; + unsigned int i; + + val = clk_readl(clock->reg); + + sd_fc = val & CPG_SD_FC_MASK; + for (i = 0; i < clock->div_num; i++) + if (sd_fc == (clock->div_table[i].val & CPG_SD_FC_MASK)) + break; + + if (i >= clock->div_num) + return -EINVAL; + + val &= ~(CPG_SD_STP_MASK); + val |= clock->div_table[i].val & CPG_SD_STP_MASK; + + clk_writel(val, clock->reg); + + return 0; +} + +static void cpg_sd_clock_disable(struct clk_hw *hw) +{ + struct sd_clock *clock = to_sd_clock(hw); + + clk_writel(clk_readl(clock->reg) | CPG_SD_STP_MASK, clock->reg); +} + +static int cpg_sd_clock_is_enabled(struct clk_hw *hw) +{ + struct sd_clock *clock = to_sd_clock(hw); + + return !(clk_readl(clock->reg) & CPG_SD_STP_MASK); +} + +static unsigned long cpg_sd_clock_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct sd_clock *clock = to_sd_clock(hw); + unsigned long rate = parent_rate; + u32 val, sd_fc; + unsigned int i; + + val = clk_readl(clock->reg); + + sd_fc = val & CPG_SD_FC_MASK; + for (i = 0; i < clock->div_num; i++) + if (sd_fc == (clock->div_table[i].val & CPG_SD_FC_MASK)) + break; + + if (i >= clock->div_num) + return -EINVAL; + + return DIV_ROUND_CLOSEST(rate, clock->div_table[i].div); +} + +static unsigned int cpg_sd_clock_calc_div(struct sd_clock *clock, + unsigned long rate, + unsigned long parent_rate) +{ + unsigned int div; + + if (!rate) + rate = 1; + + div = DIV_ROUND_CLOSEST(parent_rate, rate); + + return clamp_t(unsigned int, div, clock->div_min, clock->div_max); +} + +static long cpg_sd_clock_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *parent_rate) +{ + struct sd_clock *clock = to_sd_clock(hw); + unsigned int div = cpg_sd_clock_calc_div(clock, rate, *parent_rate); + + return DIV_ROUND_CLOSEST(*parent_rate, div); +} + +static int cpg_sd_clock_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct sd_clock *clock = to_sd_clock(hw); + unsigned int div = cpg_sd_clock_calc_div(clock, rate, parent_rate); + u32 val; + unsigned int i; + + for (i = 0; i < clock->div_num; i++) + if (div == clock->div_table[i].div) + break; + + if (i >= clock->div_num) + return -EINVAL; + + val = clk_readl(clock->reg); + val &= ~(CPG_SD_STP_MASK | CPG_SD_FC_MASK); + val |= clock->div_table[i].val & (CPG_SD_STP_MASK | CPG_SD_FC_MASK); + clk_writel(val, clock->reg); + + return 0; +} + +static const struct clk_ops cpg_sd_clock_ops = { + .enable = cpg_sd_clock_enable, + .disable = cpg_sd_clock_disable, + .is_enabled = cpg_sd_clock_is_enabled, + .recalc_rate = cpg_sd_clock_recalc_rate, + .round_rate = cpg_sd_clock_round_rate, + .set_rate = cpg_sd_clock_set_rate, +}; + +static struct clk * __init cpg_sd_clk_register(const struct cpg_core_clk *core, + void __iomem *base, + const char *parent_name) +{ + struct clk_init_data init; + struct sd_clock *clock; + struct clk *clk; + unsigned int i; + + clock = kzalloc(sizeof(*clock), GFP_KERNEL); + if (!clock) + return ERR_PTR(-ENOMEM); + + init.name = core->name; + init.ops = &cpg_sd_clock_ops; + init.flags = CLK_IS_BASIC | CLK_SET_RATE_PARENT; + init.parent_names = &parent_name; + init.num_parents = 1; + + clock->reg = base + core->offset; + clock->hw.init = &init; + clock->div_table = cpg_sd_div_table; + clock->div_num = ARRAY_SIZE(cpg_sd_div_table); + + clock->div_max = clock->div_table[0].div; + clock->div_min = clock->div_max; + for (i = 1; i < clock->div_num; i++) { + clock->div_max = max(clock->div_max, clock->div_table[i].div); + clock->div_min = min(clock->div_min, clock->div_table[i].div); + } + + clk = clk_register(NULL, &clock->hw); + if (IS_ERR(clk)) + kfree(clock); + + return clk; +} + + +static const struct rcar_gen3_cpg_pll_config *cpg_pll_config __initdata; +static unsigned int cpg_clk_extalr __initdata; + +struct clk * __init rcar_gen3_cpg_clk_register(struct device *dev, + const struct cpg_core_clk *core, const struct cpg_mssr_info *info, + struct clk **clks, void __iomem *base) +{ + const struct clk *parent; + unsigned int mult = 1; + unsigned int div = 1; + u32 value; + + parent = clks[core->parent]; + if (IS_ERR(parent)) + return ERR_CAST(parent); + + switch (core->type) { + case CLK_TYPE_GEN3_MAIN: + div = cpg_pll_config->extal_div; + break; + + case CLK_TYPE_GEN3_PLL0: + /* + * PLL0 is a configurable multiplier clock. Register it as a + * fixed factor clock for now as there's no generic multiplier + * clock implementation and we currently have no need to change + * the multiplier value. + */ + value = readl(base + CPG_PLL0CR); + mult = (((value >> 24) & 0x7f) + 1) * 2; + break; + + case CLK_TYPE_GEN3_PLL1: + mult = cpg_pll_config->pll1_mult; + break; + + case CLK_TYPE_GEN3_PLL2: + /* + * PLL2 is a configurable multiplier clock. Register it as a + * fixed factor clock for now as there's no generic multiplier + * clock implementation and we currently have no need to change + * the multiplier value. + */ + value = readl(base + CPG_PLL2CR); + mult = (((value >> 24) & 0x7f) + 1) * 2; + break; + + case CLK_TYPE_GEN3_PLL3: + mult = cpg_pll_config->pll3_mult; + break; + + case CLK_TYPE_GEN3_PLL4: + /* + * PLL4 is a configurable multiplier clock. Register it as a + * fixed factor clock for now as there's no generic multiplier + * clock implementation and we currently have no need to change + * the multiplier value. + */ + value = readl(base + CPG_PLL4CR); + mult = (((value >> 24) & 0x7f) + 1) * 2; + break; + + case CLK_TYPE_GEN3_SD: + return cpg_sd_clk_register(core, base, __clk_get_name(parent)); + + case CLK_TYPE_GEN3_R: + /* + * RINT is default. + * Only if EXTALR is populated, we switch to it. + */ + value = readl(base + CPG_RCKCR) & 0x3f; + + if (clk_get_rate(clks[cpg_clk_extalr])) { + parent = clks[cpg_clk_extalr]; + value |= BIT(15); + } + + writel(value, base + CPG_RCKCR); + break; + + default: + return ERR_PTR(-EINVAL); + } + + return clk_register_fixed_factor(NULL, core->name, + __clk_get_name(parent), 0, mult, div); +} + +/* + * Reset register definitions. + */ +#define MODEMR 0xe6160060 + +u32 __init rcar_gen3_read_mode_pins(void) +{ + void __iomem *modemr = ioremap_nocache(MODEMR, 4); + u32 mode; + + BUG_ON(!modemr); + mode = ioread32(modemr); + iounmap(modemr); + + return mode; +} + +int __init rcar_gen3_cpg_init(const struct rcar_gen3_cpg_pll_config *config, + unsigned int clk_extalr) +{ + cpg_pll_config = config; + cpg_clk_extalr = clk_extalr; + return 0; +} diff --git a/drivers/clk/renesas/rcar-gen3-cpg.h b/drivers/clk/renesas/rcar-gen3-cpg.h new file mode 100644 index 000000000000..f699085147d1 --- /dev/null +++ b/drivers/clk/renesas/rcar-gen3-cpg.h @@ -0,0 +1,43 @@ +/* + * R-Car Gen3 Clock Pulse Generator + * + * Copyright (C) 2015-2016 Glider bvba + * + * 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 of the License. + */ + +#ifndef __CLK_RENESAS_RCAR_GEN3_CPG_H__ +#define __CLK_RENESAS_RCAR_GEN3_CPG_H__ + +enum rcar_gen3_clk_types { + CLK_TYPE_GEN3_MAIN = CLK_TYPE_CUSTOM, + CLK_TYPE_GEN3_PLL0, + CLK_TYPE_GEN3_PLL1, + CLK_TYPE_GEN3_PLL2, + CLK_TYPE_GEN3_PLL3, + CLK_TYPE_GEN3_PLL4, + CLK_TYPE_GEN3_SD, + CLK_TYPE_GEN3_R, +}; + +#define DEF_GEN3_SD(_name, _id, _parent, _offset) \ + DEF_BASE(_name, _id, CLK_TYPE_GEN3_SD, _parent, .offset = _offset) + +struct rcar_gen3_cpg_pll_config { + unsigned int extal_div; + unsigned int pll1_mult; + unsigned int pll3_mult; +}; + +#define CPG_RCKCR 0x240 + +u32 rcar_gen3_read_mode_pins(void); +struct clk *rcar_gen3_cpg_clk_register(struct device *dev, + const struct cpg_core_clk *core, const struct cpg_mssr_info *info, + struct clk **clks, void __iomem *base); +int rcar_gen3_cpg_init(const struct rcar_gen3_cpg_pll_config *config, + unsigned int clk_extalr); + +#endif -- cgit v1.2.3 From e4e2d7c388350eba8b1dbc2569441ac9b545a8c4 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 3 May 2016 11:06:15 +0200 Subject: clk: renesas: cpg-mssr: Add support for R-Car M3-W Initial support for R-Car M3-W (r8a7796), including basic core clocks, and SCIF2 (console) and INTC-AP (GIC) module clocks. Signed-off-by: Geert Uytterhoeven Tested-by: Simon Horman --- drivers/clk/renesas/Kconfig | 1 + drivers/clk/renesas/Makefile | 1 + drivers/clk/renesas/r8a7796-cpg-mssr.c | 192 +++++++++++++++++++++++++++++++++ drivers/clk/renesas/renesas-cpg-mssr.c | 6 ++ drivers/clk/renesas/renesas-cpg-mssr.h | 1 + 5 files changed, 201 insertions(+) create mode 100644 drivers/clk/renesas/r8a7796-cpg-mssr.c diff --git a/drivers/clk/renesas/Kconfig b/drivers/clk/renesas/Kconfig index 2115ce410cfb..fcad9ff090f5 100644 --- a/drivers/clk/renesas/Kconfig +++ b/drivers/clk/renesas/Kconfig @@ -1,6 +1,7 @@ config CLK_RENESAS_CPG_MSSR bool default y if ARCH_R8A7795 + default y if ARCH_R8A7796 config CLK_RENESAS_CPG_MSTP bool diff --git a/drivers/clk/renesas/Makefile b/drivers/clk/renesas/Makefile index 88924c95808c..0b8d31b4909c 100644 --- a/drivers/clk/renesas/Makefile +++ b/drivers/clk/renesas/Makefile @@ -9,6 +9,7 @@ obj-$(CONFIG_ARCH_R8A7791) += clk-rcar-gen2.o clk-div6.o obj-$(CONFIG_ARCH_R8A7793) += clk-rcar-gen2.o clk-div6.o obj-$(CONFIG_ARCH_R8A7794) += clk-rcar-gen2.o clk-div6.o obj-$(CONFIG_ARCH_R8A7795) += r8a7795-cpg-mssr.o rcar-gen3-cpg.o +obj-$(CONFIG_ARCH_R8A7796) += r8a7796-cpg-mssr.o rcar-gen3-cpg.o obj-$(CONFIG_ARCH_SH73A0) += clk-sh73a0.o clk-div6.o obj-$(CONFIG_CLK_RENESAS_CPG_MSSR) += renesas-cpg-mssr.o clk-div6.o diff --git a/drivers/clk/renesas/r8a7796-cpg-mssr.c b/drivers/clk/renesas/r8a7796-cpg-mssr.c new file mode 100644 index 000000000000..c84b549c14d2 --- /dev/null +++ b/drivers/clk/renesas/r8a7796-cpg-mssr.c @@ -0,0 +1,192 @@ +/* + * r8a7796 Clock Pulse Generator / Module Standby and Software Reset + * + * Copyright (C) 2016 Glider bvba + * + * Based on r8a7795-cpg-mssr.c + * + * Copyright (C) 2015 Glider bvba + * Copyright (C) 2015 Renesas Electronics Corp. + * + * 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 of the License. + */ + +#include +#include +#include + +#include + +#include "renesas-cpg-mssr.h" +#include "rcar-gen3-cpg.h" + +enum clk_ids { + /* Core Clock Outputs exported to DT */ + LAST_DT_CORE_CLK = R8A7796_CLK_OSC, + + /* External Input Clocks */ + CLK_EXTAL, + CLK_EXTALR, + + /* Internal Core Clocks */ + CLK_MAIN, + CLK_PLL0, + CLK_PLL1, + CLK_PLL2, + CLK_PLL3, + CLK_PLL4, + CLK_PLL1_DIV2, + CLK_PLL1_DIV4, + CLK_S0, + CLK_S1, + CLK_S2, + CLK_S3, + CLK_SDSRC, + CLK_SSPSRC, + + /* Module Clocks */ + MOD_CLK_BASE +}; + +static const struct cpg_core_clk r8a7796_core_clks[] __initconst = { + /* External Clock Inputs */ + DEF_INPUT("extal", CLK_EXTAL), + DEF_INPUT("extalr", CLK_EXTALR), + + /* Internal Core Clocks */ + DEF_BASE(".main", CLK_MAIN, CLK_TYPE_GEN3_MAIN, CLK_EXTAL), + DEF_BASE(".pll0", CLK_PLL0, CLK_TYPE_GEN3_PLL0, CLK_MAIN), + DEF_BASE(".pll1", CLK_PLL1, CLK_TYPE_GEN3_PLL1, CLK_MAIN), + DEF_BASE(".pll2", CLK_PLL2, CLK_TYPE_GEN3_PLL2, CLK_MAIN), + DEF_BASE(".pll3", CLK_PLL3, CLK_TYPE_GEN3_PLL3, CLK_MAIN), + DEF_BASE(".pll4", CLK_PLL4, CLK_TYPE_GEN3_PLL4, CLK_MAIN), + + DEF_FIXED(".pll1_div2", CLK_PLL1_DIV2, CLK_PLL1, 2, 1), + DEF_FIXED(".pll1_div4", CLK_PLL1_DIV4, CLK_PLL1_DIV2, 2, 1), + DEF_FIXED(".s0", CLK_S0, CLK_PLL1_DIV2, 2, 1), + DEF_FIXED(".s1", CLK_S1, CLK_PLL1_DIV2, 3, 1), + DEF_FIXED(".s2", CLK_S2, CLK_PLL1_DIV2, 4, 1), + DEF_FIXED(".s3", CLK_S3, CLK_PLL1_DIV2, 6, 1), + + /* Core Clock Outputs */ + DEF_FIXED("ztr", R8A7796_CLK_ZTR, CLK_PLL1_DIV2, 6, 1), + DEF_FIXED("ztrd2", R8A7796_CLK_ZTRD2, CLK_PLL1_DIV2, 12, 1), + DEF_FIXED("zt", R8A7796_CLK_ZT, CLK_PLL1_DIV2, 4, 1), + DEF_FIXED("zx", R8A7796_CLK_ZX, CLK_PLL1_DIV2, 2, 1), + DEF_FIXED("s0d1", R8A7796_CLK_S0D1, CLK_S0, 1, 1), + DEF_FIXED("s0d2", R8A7796_CLK_S0D2, CLK_S0, 2, 1), + DEF_FIXED("s0d3", R8A7796_CLK_S0D3, CLK_S0, 3, 1), + DEF_FIXED("s0d4", R8A7796_CLK_S0D4, CLK_S0, 4, 1), + DEF_FIXED("s0d6", R8A7796_CLK_S0D6, CLK_S0, 6, 1), + DEF_FIXED("s0d8", R8A7796_CLK_S0D8, CLK_S0, 8, 1), + DEF_FIXED("s0d12", R8A7796_CLK_S0D12, CLK_S0, 12, 1), + DEF_FIXED("s1d1", R8A7796_CLK_S1D1, CLK_S1, 1, 1), + DEF_FIXED("s1d2", R8A7796_CLK_S1D2, CLK_S1, 2, 1), + DEF_FIXED("s1d4", R8A7796_CLK_S1D4, CLK_S1, 4, 1), + DEF_FIXED("s2d1", R8A7796_CLK_S2D1, CLK_S2, 1, 1), + DEF_FIXED("s2d2", R8A7796_CLK_S2D2, CLK_S2, 2, 1), + DEF_FIXED("s2d4", R8A7796_CLK_S2D4, CLK_S2, 4, 1), + DEF_FIXED("s3d1", R8A7796_CLK_S3D1, CLK_S3, 1, 1), + DEF_FIXED("s3d2", R8A7796_CLK_S3D2, CLK_S3, 2, 1), + DEF_FIXED("s3d4", R8A7796_CLK_S3D4, CLK_S3, 4, 1), + + DEF_FIXED("cl", R8A7796_CLK_CL, CLK_PLL1_DIV2, 48, 1), + DEF_FIXED("cp", R8A7796_CLK_CP, CLK_EXTAL, 2, 1), +}; + +static const struct mssr_mod_clk r8a7796_mod_clks[] __initconst = { + DEF_MOD("scif2", 310, R8A7796_CLK_S3D4), + DEF_MOD("intc-ap", 408, R8A7796_CLK_S3D1), +}; + +static const unsigned int r8a7796_crit_mod_clks[] __initconst = { + MOD_CLK_ID(408), /* INTC-AP (GIC) */ +}; + + +/* + * CPG Clock Data + */ + +/* + * MD EXTAL PLL0 PLL1 PLL2 PLL3 PLL4 + * 14 13 19 17 (MHz) + *------------------------------------------------------------------- + * 0 0 0 0 16.66 x 1 x180 x192 x144 x192 x144 + * 0 0 0 1 16.66 x 1 x180 x192 x144 x128 x144 + * 0 0 1 0 Prohibited setting + * 0 0 1 1 16.66 x 1 x180 x192 x144 x192 x144 + * 0 1 0 0 20 x 1 x150 x160 x120 x160 x120 + * 0 1 0 1 20 x 1 x150 x160 x120 x106 x120 + * 0 1 1 0 Prohibited setting + * 0 1 1 1 20 x 1 x150 x160 x120 x160 x120 + * 1 0 0 0 25 x 1 x120 x128 x96 x128 x96 + * 1 0 0 1 25 x 1 x120 x128 x96 x84 x96 + * 1 0 1 0 Prohibited setting + * 1 0 1 1 25 x 1 x120 x128 x96 x128 x96 + * 1 1 0 0 33.33 / 2 x180 x192 x144 x192 x144 + * 1 1 0 1 33.33 / 2 x180 x192 x144 x128 x144 + * 1 1 1 0 Prohibited setting + * 1 1 1 1 33.33 / 2 x180 x192 x144 x192 x144 + */ +#define CPG_PLL_CONFIG_INDEX(md) ((((md) & BIT(14)) >> 11) | \ + (((md) & BIT(13)) >> 11) | \ + (((md) & BIT(19)) >> 18) | \ + (((md) & BIT(17)) >> 17)) + +static const struct rcar_gen3_cpg_pll_config cpg_pll_configs[16] __initconst = { + /* EXTAL div PLL1 mult PLL3 mult */ + { 1, 192, 192, }, + { 1, 192, 128, }, + { 0, /* Prohibited setting */ }, + { 1, 192, 192, }, + { 1, 160, 160, }, + { 1, 160, 106, }, + { 0, /* Prohibited setting */ }, + { 1, 160, 160, }, + { 1, 128, 128, }, + { 1, 128, 84, }, + { 0, /* Prohibited setting */ }, + { 1, 128, 128, }, + { 2, 192, 192, }, + { 2, 192, 128, }, + { 0, /* Prohibited setting */ }, + { 2, 192, 192, }, +}; + +static int __init r8a7796_cpg_mssr_init(struct device *dev) +{ + const struct rcar_gen3_cpg_pll_config *cpg_pll_config; + u32 cpg_mode = rcar_gen3_read_mode_pins(); + + cpg_pll_config = &cpg_pll_configs[CPG_PLL_CONFIG_INDEX(cpg_mode)]; + if (!cpg_pll_config->extal_div) { + dev_err(dev, "Prohibited setting (cpg_mode=0x%x)\n", cpg_mode); + return -EINVAL; + } + + return rcar_gen3_cpg_init(cpg_pll_config, CLK_EXTALR); +} + +const struct cpg_mssr_info r8a7796_cpg_mssr_info __initconst = { + /* Core Clocks */ + .core_clks = r8a7796_core_clks, + .num_core_clks = ARRAY_SIZE(r8a7796_core_clks), + .last_dt_core_clk = LAST_DT_CORE_CLK, + .num_total_core_clks = MOD_CLK_BASE, + + /* Module Clocks */ + .mod_clks = r8a7796_mod_clks, + .num_mod_clks = ARRAY_SIZE(r8a7796_mod_clks), + .num_hw_mod_clks = 12 * 32, + + /* Critical Module Clocks */ + .crit_mod_clks = r8a7796_crit_mod_clks, + .num_crit_mod_clks = ARRAY_SIZE(r8a7796_crit_mod_clks), + + /* Callbacks */ + .init = r8a7796_cpg_mssr_init, + .cpg_clk_register = rcar_gen3_cpg_clk_register, +}; diff --git a/drivers/clk/renesas/renesas-cpg-mssr.c b/drivers/clk/renesas/renesas-cpg-mssr.c index 210cd744a7a9..e1365e7491ae 100644 --- a/drivers/clk/renesas/renesas-cpg-mssr.c +++ b/drivers/clk/renesas/renesas-cpg-mssr.c @@ -508,6 +508,12 @@ static const struct of_device_id cpg_mssr_match[] = { .compatible = "renesas,r8a7795-cpg-mssr", .data = &r8a7795_cpg_mssr_info, }, +#endif +#ifdef CONFIG_ARCH_R8A7796 + { + .compatible = "renesas,r8a7796-cpg-mssr", + .data = &r8a7796_cpg_mssr_info, + }, #endif { /* sentinel */ } }; diff --git a/drivers/clk/renesas/renesas-cpg-mssr.h b/drivers/clk/renesas/renesas-cpg-mssr.h index 0d1e3e811e79..ee7edfaf1408 100644 --- a/drivers/clk/renesas/renesas-cpg-mssr.h +++ b/drivers/clk/renesas/renesas-cpg-mssr.h @@ -131,4 +131,5 @@ struct cpg_mssr_info { }; extern const struct cpg_mssr_info r8a7795_cpg_mssr_info; +extern const struct cpg_mssr_info r8a7796_cpg_mssr_info; #endif -- cgit v1.2.3 From 4de103397bed108212ac8e382d9285eb6b2700bd Mon Sep 17 00:00:00 2001 From: Matthew Leach Date: Wed, 8 Jun 2016 19:30:56 +0100 Subject: clk: samsung: fixup endian in pll clk Fix the clk endian access code to deal with kernels built for big endian operation. Signed-off-by: Matthew Leach Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk-pll.c | 122 +++++++++++++++++++++--------------------- 1 file changed, 61 insertions(+), 61 deletions(-) diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c index b7dd396100d8..48139bd510f1 100644 --- a/drivers/clk/samsung/clk-pll.c +++ b/drivers/clk/samsung/clk-pll.c @@ -79,7 +79,7 @@ static unsigned long samsung_pll2126_recalc_rate(struct clk_hw *hw, u32 pll_con, mdiv, pdiv, sdiv; u64 fvco = parent_rate; - pll_con = __raw_readl(pll->con_reg); + pll_con = readl_relaxed(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; @@ -112,7 +112,7 @@ static unsigned long samsung_pll3000_recalc_rate(struct clk_hw *hw, u32 pll_con, mdiv, pdiv, sdiv; u64 fvco = parent_rate; - pll_con = __raw_readl(pll->con_reg); + pll_con = readl_relaxed(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; @@ -149,7 +149,7 @@ static unsigned long samsung_pll35xx_recalc_rate(struct clk_hw *hw, u32 mdiv, pdiv, sdiv, pll_con; u64 fvco = parent_rate; - pll_con = __raw_readl(pll->con_reg); + pll_con = readl_relaxed(pll->con_reg); mdiv = (pll_con >> PLL35XX_MDIV_SHIFT) & PLL35XX_MDIV_MASK; pdiv = (pll_con >> PLL35XX_PDIV_SHIFT) & PLL35XX_PDIV_MASK; sdiv = (pll_con >> PLL35XX_SDIV_SHIFT) & PLL35XX_SDIV_MASK; @@ -186,19 +186,19 @@ static int samsung_pll35xx_set_rate(struct clk_hw *hw, unsigned long drate, return -EINVAL; } - tmp = __raw_readl(pll->con_reg); + tmp = readl_relaxed(pll->con_reg); if (!(samsung_pll35xx_mp_change(rate, tmp))) { /* If only s change, change just s value only*/ tmp &= ~(PLL35XX_SDIV_MASK << PLL35XX_SDIV_SHIFT); tmp |= rate->sdiv << PLL35XX_SDIV_SHIFT; - __raw_writel(tmp, pll->con_reg); + writel_relaxed(tmp, pll->con_reg); return 0; } /* Set PLL lock time. */ - __raw_writel(rate->pdiv * PLL35XX_LOCK_FACTOR, + writel_relaxed(rate->pdiv * PLL35XX_LOCK_FACTOR, pll->lock_reg); /* Change PLL PMS values */ @@ -208,12 +208,12 @@ static int samsung_pll35xx_set_rate(struct clk_hw *hw, unsigned long drate, tmp |= (rate->mdiv << PLL35XX_MDIV_SHIFT) | (rate->pdiv << PLL35XX_PDIV_SHIFT) | (rate->sdiv << PLL35XX_SDIV_SHIFT); - __raw_writel(tmp, pll->con_reg); + writel_relaxed(tmp, pll->con_reg); /* wait_lock_time */ do { cpu_relax(); - tmp = __raw_readl(pll->con_reg); + tmp = readl_relaxed(pll->con_reg); } while (!(tmp & (PLL35XX_LOCK_STAT_MASK << PLL35XX_LOCK_STAT_SHIFT))); return 0; @@ -253,8 +253,8 @@ static unsigned long samsung_pll36xx_recalc_rate(struct clk_hw *hw, s16 kdiv; u64 fvco = parent_rate; - pll_con0 = __raw_readl(pll->con_reg); - pll_con1 = __raw_readl(pll->con_reg + 4); + pll_con0 = readl_relaxed(pll->con_reg); + pll_con1 = readl_relaxed(pll->con_reg + 4); mdiv = (pll_con0 >> PLL36XX_MDIV_SHIFT) & PLL36XX_MDIV_MASK; pdiv = (pll_con0 >> PLL36XX_PDIV_SHIFT) & PLL36XX_PDIV_MASK; sdiv = (pll_con0 >> PLL36XX_SDIV_SHIFT) & PLL36XX_SDIV_MASK; @@ -294,20 +294,20 @@ static int samsung_pll36xx_set_rate(struct clk_hw *hw, unsigned long drate, return -EINVAL; } - pll_con0 = __raw_readl(pll->con_reg); - pll_con1 = __raw_readl(pll->con_reg + 4); + pll_con0 = readl_relaxed(pll->con_reg); + pll_con1 = readl_relaxed(pll->con_reg + 4); if (!(samsung_pll36xx_mpk_change(rate, pll_con0, pll_con1))) { /* If only s change, change just s value only*/ pll_con0 &= ~(PLL36XX_SDIV_MASK << PLL36XX_SDIV_SHIFT); pll_con0 |= (rate->sdiv << PLL36XX_SDIV_SHIFT); - __raw_writel(pll_con0, pll->con_reg); + writel_relaxed(pll_con0, pll->con_reg); return 0; } /* Set PLL lock time. */ - __raw_writel(rate->pdiv * PLL36XX_LOCK_FACTOR, pll->lock_reg); + writel_relaxed(rate->pdiv * PLL36XX_LOCK_FACTOR, pll->lock_reg); /* Change PLL PMS values */ pll_con0 &= ~((PLL36XX_MDIV_MASK << PLL36XX_MDIV_SHIFT) | @@ -316,16 +316,16 @@ static int samsung_pll36xx_set_rate(struct clk_hw *hw, unsigned long drate, pll_con0 |= (rate->mdiv << PLL36XX_MDIV_SHIFT) | (rate->pdiv << PLL36XX_PDIV_SHIFT) | (rate->sdiv << PLL36XX_SDIV_SHIFT); - __raw_writel(pll_con0, pll->con_reg); + writel_relaxed(pll_con0, pll->con_reg); pll_con1 &= ~(PLL36XX_KDIV_MASK << PLL36XX_KDIV_SHIFT); pll_con1 |= rate->kdiv << PLL36XX_KDIV_SHIFT; - __raw_writel(pll_con1, pll->con_reg + 4); + writel_relaxed(pll_con1, pll->con_reg + 4); /* wait_lock_time */ do { cpu_relax(); - tmp = __raw_readl(pll->con_reg); + tmp = readl_relaxed(pll->con_reg); } while (!(tmp & (1 << PLL36XX_LOCK_STAT_SHIFT))); return 0; @@ -366,7 +366,7 @@ static unsigned long samsung_pll45xx_recalc_rate(struct clk_hw *hw, u32 mdiv, pdiv, sdiv, pll_con; u64 fvco = parent_rate; - pll_con = __raw_readl(pll->con_reg); + pll_con = readl_relaxed(pll->con_reg); mdiv = (pll_con >> PLL45XX_MDIV_SHIFT) & PLL45XX_MDIV_MASK; pdiv = (pll_con >> PLL45XX_PDIV_SHIFT) & PLL45XX_PDIV_MASK; sdiv = (pll_con >> PLL45XX_SDIV_SHIFT) & PLL45XX_SDIV_MASK; @@ -409,14 +409,14 @@ static int samsung_pll45xx_set_rate(struct clk_hw *hw, unsigned long drate, return -EINVAL; } - con0 = __raw_readl(pll->con_reg); - con1 = __raw_readl(pll->con_reg + 0x4); + con0 = readl_relaxed(pll->con_reg); + con1 = readl_relaxed(pll->con_reg + 0x4); if (!(samsung_pll45xx_mp_change(con0, con1, rate))) { /* If only s change, change just s value only*/ con0 &= ~(PLL45XX_SDIV_MASK << PLL45XX_SDIV_SHIFT); con0 |= rate->sdiv << PLL45XX_SDIV_SHIFT; - __raw_writel(con0, pll->con_reg); + writel_relaxed(con0, pll->con_reg); return 0; } @@ -430,29 +430,29 @@ static int samsung_pll45xx_set_rate(struct clk_hw *hw, unsigned long drate, (rate->sdiv << PLL45XX_SDIV_SHIFT); /* Set PLL AFC value. */ - con1 = __raw_readl(pll->con_reg + 0x4); + con1 = readl_relaxed(pll->con_reg + 0x4); con1 &= ~(PLL45XX_AFC_MASK << PLL45XX_AFC_SHIFT); con1 |= (rate->afc << PLL45XX_AFC_SHIFT); /* Set PLL lock time. */ switch (pll->type) { case pll_4502: - __raw_writel(rate->pdiv * PLL4502_LOCK_FACTOR, pll->lock_reg); + writel_relaxed(rate->pdiv * PLL4502_LOCK_FACTOR, pll->lock_reg); break; case pll_4508: - __raw_writel(rate->pdiv * PLL4508_LOCK_FACTOR, pll->lock_reg); + writel_relaxed(rate->pdiv * PLL4508_LOCK_FACTOR, pll->lock_reg); break; default: break; } /* Set new configuration. */ - __raw_writel(con1, pll->con_reg + 0x4); - __raw_writel(con0, pll->con_reg); + writel_relaxed(con1, pll->con_reg + 0x4); + writel_relaxed(con0, pll->con_reg); /* Wait for locking. */ start = ktime_get(); - while (!(__raw_readl(pll->con_reg) & PLL45XX_LOCKED)) { + while (!(readl_relaxed(pll->con_reg) & PLL45XX_LOCKED)) { ktime_t delta = ktime_sub(ktime_get(), start); if (ktime_to_ms(delta) > PLL_TIMEOUT_MS) { @@ -513,8 +513,8 @@ static unsigned long samsung_pll46xx_recalc_rate(struct clk_hw *hw, u32 mdiv, pdiv, sdiv, kdiv, pll_con0, pll_con1, shift; u64 fvco = parent_rate; - pll_con0 = __raw_readl(pll->con_reg); - pll_con1 = __raw_readl(pll->con_reg + 4); + pll_con0 = readl_relaxed(pll->con_reg); + pll_con1 = readl_relaxed(pll->con_reg + 4); mdiv = (pll_con0 >> PLL46XX_MDIV_SHIFT) & ((pll->type == pll_1460x) ? PLL1460X_MDIV_MASK : PLL46XX_MDIV_MASK); pdiv = (pll_con0 >> PLL46XX_PDIV_SHIFT) & PLL46XX_PDIV_MASK; @@ -560,14 +560,14 @@ static int samsung_pll46xx_set_rate(struct clk_hw *hw, unsigned long drate, return -EINVAL; } - con0 = __raw_readl(pll->con_reg); - con1 = __raw_readl(pll->con_reg + 0x4); + con0 = readl_relaxed(pll->con_reg); + con1 = readl_relaxed(pll->con_reg + 0x4); if (!(samsung_pll46xx_mpk_change(con0, con1, rate))) { /* If only s change, change just s value only*/ con0 &= ~(PLL46XX_SDIV_MASK << PLL46XX_SDIV_SHIFT); con0 |= rate->sdiv << PLL46XX_SDIV_SHIFT; - __raw_writel(con0, pll->con_reg); + writel_relaxed(con0, pll->con_reg); return 0; } @@ -596,7 +596,7 @@ static int samsung_pll46xx_set_rate(struct clk_hw *hw, unsigned long drate, (rate->sdiv << PLL46XX_SDIV_SHIFT); /* Set PLL K, MFR and MRR values. */ - con1 = __raw_readl(pll->con_reg + 0x4); + con1 = readl_relaxed(pll->con_reg + 0x4); con1 &= ~((PLL46XX_KDIV_MASK << PLL46XX_KDIV_SHIFT) | (PLL46XX_MFR_MASK << PLL46XX_MFR_SHIFT) | (PLL46XX_MRR_MASK << PLL46XX_MRR_SHIFT)); @@ -605,13 +605,13 @@ static int samsung_pll46xx_set_rate(struct clk_hw *hw, unsigned long drate, (rate->mrr << PLL46XX_MRR_SHIFT); /* Write configuration to PLL */ - __raw_writel(lock, pll->lock_reg); - __raw_writel(con0, pll->con_reg); - __raw_writel(con1, pll->con_reg + 0x4); + writel_relaxed(lock, pll->lock_reg); + writel_relaxed(con0, pll->con_reg); + writel_relaxed(con1, pll->con_reg + 0x4); /* Wait for locking. */ start = ktime_get(); - while (!(__raw_readl(pll->con_reg) & PLL46XX_LOCKED)) { + while (!(readl_relaxed(pll->con_reg) & PLL46XX_LOCKED)) { ktime_t delta = ktime_sub(ktime_get(), start); if (ktime_to_ms(delta) > PLL_TIMEOUT_MS) { @@ -656,7 +656,7 @@ static unsigned long samsung_pll6552_recalc_rate(struct clk_hw *hw, u32 mdiv, pdiv, sdiv, pll_con; u64 fvco = parent_rate; - pll_con = __raw_readl(pll->con_reg); + pll_con = readl_relaxed(pll->con_reg); 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; @@ -696,8 +696,8 @@ static unsigned long samsung_pll6553_recalc_rate(struct clk_hw *hw, u32 mdiv, pdiv, sdiv, kdiv, pll_con0, pll_con1; u64 fvco = parent_rate; - pll_con0 = __raw_readl(pll->con_reg); - pll_con1 = __raw_readl(pll->con_reg + 0x4); + pll_con0 = readl_relaxed(pll->con_reg); + pll_con1 = readl_relaxed(pll->con_reg + 0x4); mdiv = (pll_con0 >> PLL6553_MDIV_SHIFT) & PLL6553_MDIV_MASK; pdiv = (pll_con0 >> PLL6553_PDIV_SHIFT) & PLL6553_PDIV_MASK; sdiv = (pll_con0 >> PLL6553_SDIV_SHIFT) & PLL6553_SDIV_MASK; @@ -734,7 +734,7 @@ static unsigned long samsung_s3c2410_pll_recalc_rate(struct clk_hw *hw, u32 pll_con, mdiv, pdiv, sdiv; u64 fvco = parent_rate; - pll_con = __raw_readl(pll->con_reg); + pll_con = readl_relaxed(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; @@ -752,7 +752,7 @@ static unsigned long samsung_s3c2440_mpll_recalc_rate(struct clk_hw *hw, u32 pll_con, mdiv, pdiv, sdiv; u64 fvco = parent_rate; - pll_con = __raw_readl(pll->con_reg); + pll_con = readl_relaxed(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; @@ -778,7 +778,7 @@ static int samsung_s3c2410_pll_set_rate(struct clk_hw *hw, unsigned long drate, return -EINVAL; } - tmp = __raw_readl(pll->con_reg); + tmp = readl_relaxed(pll->con_reg); /* Change PLL PMS values */ tmp &= ~((PLLS3C2410_MDIV_MASK << PLLS3C2410_MDIV_SHIFT) | @@ -787,7 +787,7 @@ static int samsung_s3c2410_pll_set_rate(struct clk_hw *hw, unsigned long drate, tmp |= (rate->mdiv << PLLS3C2410_MDIV_SHIFT) | (rate->pdiv << PLLS3C2410_PDIV_SHIFT) | (rate->sdiv << PLLS3C2410_SDIV_SHIFT); - __raw_writel(tmp, pll->con_reg); + writel_relaxed(tmp, pll->con_reg); /* Time to settle according to the manual */ udelay(300); @@ -798,7 +798,7 @@ static int samsung_s3c2410_pll_set_rate(struct clk_hw *hw, unsigned long drate, 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 = readl_relaxed(pll->lock_reg + PLLS3C2410_ENABLE_REG_OFFSET); u32 pll_en_orig = pll_en; if (enable) @@ -806,7 +806,7 @@ static int samsung_s3c2410_pll_enable(struct clk_hw *hw, int bit, bool enable) else pll_en |= BIT(bit); - __raw_writel(pll_en, pll->lock_reg + PLLS3C2410_ENABLE_REG_OFFSET); + writel_relaxed(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))) @@ -905,7 +905,7 @@ static unsigned long samsung_pll2550x_recalc_rate(struct clk_hw *hw, u32 r, p, m, s, pll_stat; u64 fvco = parent_rate; - pll_stat = __raw_readl(pll->reg_base + pll->offset * 3); + pll_stat = readl_relaxed(pll->reg_base + pll->offset * 3); r = (pll_stat >> PLL2550X_R_SHIFT) & PLL2550X_R_MASK; if (!r) return 0; @@ -983,7 +983,7 @@ static unsigned long samsung_pll2550xx_recalc_rate(struct clk_hw *hw, u32 mdiv, pdiv, sdiv, pll_con; u64 fvco = parent_rate; - pll_con = __raw_readl(pll->con_reg); + pll_con = readl_relaxed(pll->con_reg); mdiv = (pll_con >> PLL2550XX_M_SHIFT) & PLL2550XX_M_MASK; pdiv = (pll_con >> PLL2550XX_P_SHIFT) & PLL2550XX_P_MASK; sdiv = (pll_con >> PLL2550XX_S_SHIFT) & PLL2550XX_S_MASK; @@ -1019,19 +1019,19 @@ static int samsung_pll2550xx_set_rate(struct clk_hw *hw, unsigned long drate, return -EINVAL; } - tmp = __raw_readl(pll->con_reg); + tmp = readl_relaxed(pll->con_reg); if (!(samsung_pll2550xx_mp_change(rate->mdiv, rate->pdiv, tmp))) { /* If only s change, change just s value only*/ tmp &= ~(PLL2550XX_S_MASK << PLL2550XX_S_SHIFT); tmp |= rate->sdiv << PLL2550XX_S_SHIFT; - __raw_writel(tmp, pll->con_reg); + writel_relaxed(tmp, pll->con_reg); return 0; } /* Set PLL lock time. */ - __raw_writel(rate->pdiv * PLL2550XX_LOCK_FACTOR, pll->lock_reg); + writel_relaxed(rate->pdiv * PLL2550XX_LOCK_FACTOR, pll->lock_reg); /* Change PLL PMS values */ tmp &= ~((PLL2550XX_M_MASK << PLL2550XX_M_SHIFT) | @@ -1040,12 +1040,12 @@ static int samsung_pll2550xx_set_rate(struct clk_hw *hw, unsigned long drate, tmp |= (rate->mdiv << PLL2550XX_M_SHIFT) | (rate->pdiv << PLL2550XX_P_SHIFT) | (rate->sdiv << PLL2550XX_S_SHIFT); - __raw_writel(tmp, pll->con_reg); + writel_relaxed(tmp, pll->con_reg); /* wait_lock_time */ do { cpu_relax(); - tmp = __raw_readl(pll->con_reg); + tmp = readl_relaxed(pll->con_reg); } while (!(tmp & (PLL2550XX_LOCK_STAT_MASK << PLL2550XX_LOCK_STAT_SHIFT))); @@ -1089,8 +1089,8 @@ static unsigned long samsung_pll2650xx_recalc_rate(struct clk_hw *hw, s16 kdiv; u64 fvco = parent_rate; - pll_con0 = __raw_readl(pll->con_reg); - pll_con2 = __raw_readl(pll->con_reg + 8); + pll_con0 = readl_relaxed(pll->con_reg); + pll_con2 = readl_relaxed(pll->con_reg + 8); mdiv = (pll_con0 >> PLL2650XX_MDIV_SHIFT) & PLL2650XX_MDIV_MASK; pdiv = (pll_con0 >> PLL2650XX_PDIV_SHIFT) & PLL2650XX_PDIV_MASK; sdiv = (pll_con0 >> PLL2650XX_SDIV_SHIFT) & PLL2650XX_SDIV_MASK; @@ -1117,8 +1117,8 @@ static int samsung_pll2650xx_set_rate(struct clk_hw *hw, unsigned long drate, return -EINVAL; } - pll_con0 = __raw_readl(pll->con_reg); - pll_con2 = __raw_readl(pll->con_reg + 8); + pll_con0 = readl_relaxed(pll->con_reg); + pll_con2 = readl_relaxed(pll->con_reg + 8); /* Change PLL PMS values */ pll_con0 &= ~(PLL2650XX_MDIV_MASK << PLL2650XX_MDIV_SHIFT | @@ -1135,13 +1135,13 @@ static int samsung_pll2650xx_set_rate(struct clk_hw *hw, unsigned long drate, << PLL2650XX_KDIV_SHIFT; /* Set PLL lock time. */ - __raw_writel(PLL2650XX_LOCK_FACTOR * rate->pdiv, pll->lock_reg); + writel_relaxed(PLL2650XX_LOCK_FACTOR * rate->pdiv, pll->lock_reg); - __raw_writel(pll_con0, pll->con_reg); - __raw_writel(pll_con2, pll->con_reg + 8); + writel_relaxed(pll_con0, pll->con_reg); + writel_relaxed(pll_con2, pll->con_reg + 8); do { - tmp = __raw_readl(pll->con_reg); + tmp = readl_relaxed(pll->con_reg); } while (!(tmp & (0x1 << PLL2650XX_PLL_LOCKTIME_SHIFT))); return 0; -- cgit v1.2.3 From 21a5560b5dfc79ec03335280e68e6c2d3f1528b1 Mon Sep 17 00:00:00 2001 From: Matthew Leach Date: Wed, 8 Jun 2016 19:30:58 +0100 Subject: clk: samsung: exynos4: fixup reg access on be Use the byte-order aware big endian accessors, allowing for kernels running under big-endian. Signed-off-by: Matthew Leach Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk-exynos4.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c index 13eaf4cb0dbc..faab9b31baf5 100644 --- a/drivers/clk/samsung/clk-exynos4.c +++ b/drivers/clk/samsung/clk-exynos4.c @@ -1375,12 +1375,12 @@ static void __init exynos4x12_core_down_clock(void) if (num_possible_cpus() == 4) tmp |= PWR_CTRL1_USE_CORE3_WFE | PWR_CTRL1_USE_CORE2_WFE | PWR_CTRL1_USE_CORE3_WFI | PWR_CTRL1_USE_CORE2_WFI; - __raw_writel(tmp, reg_base + PWR_CTRL1); + writel_relaxed(tmp, reg_base + PWR_CTRL1); /* * Disable the clock up feature in case it was enabled by bootloader. */ - __raw_writel(0x0, reg_base + E4X12_PWR_CTRL2); + writel_relaxed(0x0, reg_base + E4X12_PWR_CTRL2); } #define E4210_CPU_DIV0(apll, pclk_dbg, atb, periph, corem1, corem0) \ -- cgit v1.2.3 From 7d058bc4e6bc377cbf3cbbf0c210b84c566a5825 Mon Sep 17 00:00:00 2001 From: Beomho Seo Date: Fri, 10 Jun 2016 13:56:30 +0900 Subject: clk: samsung: exynos5433: Add CLK_IGNORE_UNUSED flag for AUD UART This patch adds CLK_IGNORE_UNUSED flag for sclk_aud_uart gate clock for uart3 operation. Signed-off-by: Beomho Seo Signed-off-by: Chanwoo Choi [s.nawrocki@samsung.com: edited the patch's summary] Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk-exynos5433.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/samsung/clk-exynos5433.c b/drivers/clk/samsung/clk-exynos5433.c index 1d14d1cc1296..be3658dc9049 100644 --- a/drivers/clk/samsung/clk-exynos5433.c +++ b/drivers/clk/samsung/clk-exynos5433.c @@ -2978,7 +2978,7 @@ static const struct samsung_gate_clock aud_gate_clks[] __initconst = { GATE(CLK_SCLK_AUD_SLIMBUS, "sclk_aud_slimbus", "div_sclk_aud_slimbus", ENABLE_SCLK_AUD1, 4, 0, 0), GATE(CLK_SCLK_AUD_UART, "sclk_aud_uart", "div_sclk_aud_uart", - ENABLE_SCLK_AUD1, 3, 0, 0), + ENABLE_SCLK_AUD1, 3, CLK_IGNORE_UNUSED, 0), GATE(CLK_SCLK_AUD_PCM, "sclk_aud_pcm", "div_sclk_aud_pcm", ENABLE_SCLK_AUD1, 2, 0, 0), GATE(CLK_SCLK_I2S_BCLK, "sclk_i2s_bclk", "ioclk_i2s_bclk", -- cgit v1.2.3 From 358c9b952db6e85c861d97cb6ea8474671a025d0 Mon Sep 17 00:00:00 2001 From: Jonghwa Lee Date: Fri, 10 Jun 2016 13:56:31 +0900 Subject: clk: samsung: exynos5433: Add CLK_IGNORE_UNUSED flags to avoid hang during S2R Some clocks are required to be unmasked during suspend to RAM. Otherwise the PMU will stuck and the power down sequence will never be completed. Signed-off-by: Jonghwa Lee Signed-off-by: Chanwoo Choi [s.nawrocki@samsung.com: edited the patch's summary] Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk-exynos5433.c | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/drivers/clk/samsung/clk-exynos5433.c b/drivers/clk/samsung/clk-exynos5433.c index be3658dc9049..5d26c0f9fe0a 100644 --- a/drivers/clk/samsung/clk-exynos5433.c +++ b/drivers/clk/samsung/clk-exynos5433.c @@ -670,11 +670,14 @@ static const struct samsung_gate_clock top_gate_clks[] __initconst = { GATE(CLK_SCLK_PCM1_PERIC, "sclk_pcm1_peric", "div_sclk_pcm1", ENABLE_SCLK_TOP_PERIC, 7, CLK_SET_RATE_PARENT, 0), GATE(CLK_SCLK_UART2_PERIC, "sclk_uart2_peric", "div_sclk_uart2", - ENABLE_SCLK_TOP_PERIC, 5, CLK_SET_RATE_PARENT, 0), + ENABLE_SCLK_TOP_PERIC, 5, CLK_SET_RATE_PARENT | + CLK_IGNORE_UNUSED, 0), GATE(CLK_SCLK_UART1_PERIC, "sclk_uart1_peric", "div_sclk_uart1", - ENABLE_SCLK_TOP_PERIC, 4, CLK_SET_RATE_PARENT, 0), + ENABLE_SCLK_TOP_PERIC, 4, CLK_SET_RATE_PARENT | + CLK_IGNORE_UNUSED, 0), GATE(CLK_SCLK_UART0_PERIC, "sclk_uart0_peric", "div_sclk_uart0", - ENABLE_SCLK_TOP_PERIC, 3, CLK_SET_RATE_PARENT, 0), + ENABLE_SCLK_TOP_PERIC, 3, CLK_SET_RATE_PARENT | + CLK_IGNORE_UNUSED, 0), GATE(CLK_SCLK_SPI2_PERIC, "sclk_spi2_peric", "div_sclk_spi2_b", ENABLE_SCLK_TOP_PERIC, 2, CLK_SET_RATE_PARENT, 0), GATE(CLK_SCLK_SPI1_PERIC, "sclk_spi1_peric", "div_sclk_spi1_b", @@ -835,7 +838,7 @@ static const struct samsung_div_clock cpif_div_clks[] __initconst = { static const struct samsung_gate_clock cpif_gate_clks[] __initconst = { /* ENABLE_SCLK_CPIF */ GATE(CLK_SCLK_MPHY_PLL, "sclk_mphy_pll", "mout_mphy_pll", - ENABLE_SCLK_CPIF, 9, 0, 0), + ENABLE_SCLK_CPIF, 9, CLK_IGNORE_UNUSED, 0), GATE(CLK_SCLK_UFS_MPHY, "sclk_ufs_mphy", "div_sclk_mphy", ENABLE_SCLK_CPIF, 4, 0, 0), }; @@ -1442,11 +1445,13 @@ static const struct samsung_gate_clock mif_gate_clks[] __initconst = { /* ENABLE_PCLK_MIF_SECURE_DREX0_TZ */ GATE(CLK_PCLK_DREX0_TZ, "pclk_drex0_tz", "div_aclk_mif_133", - ENABLE_PCLK_MIF_SECURE_DREX0_TZ, 0, 0, 0), + ENABLE_PCLK_MIF_SECURE_DREX0_TZ, 0, + CLK_IGNORE_UNUSED, 0), /* ENABLE_PCLK_MIF_SECURE_DREX1_TZ */ GATE(CLK_PCLK_DREX1_TZ, "pclk_drex1_tz", "div_aclk_mif_133", - ENABLE_PCLK_MIF_SECURE_DREX1_TZ, 0, 0, 0), + ENABLE_PCLK_MIF_SECURE_DREX1_TZ, 0, + CLK_IGNORE_UNUSED, 0), /* ENABLE_PCLK_MIF_SECURE_MONOTONIC_CNT */ GATE(CLK_PCLK_MONOTONIC_CNT, "pclk_monotonic_cnt", "div_aclk_mif_133", @@ -1676,11 +1681,14 @@ static const struct samsung_gate_clock peric_gate_clks[] __initconst = { GATE(CLK_SCLK_SPI0, "sclk_spi0", "sclk_spi0_peric", ENABLE_SCLK_PERIC, 3, CLK_SET_RATE_PARENT, 0), GATE(CLK_SCLK_UART2, "sclk_uart2", "sclk_uart2_peric", - ENABLE_SCLK_PERIC, 2, CLK_SET_RATE_PARENT, 0), + ENABLE_SCLK_PERIC, 2, + CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 0), GATE(CLK_SCLK_UART1, "sclk_uart1", "sclk_uart1_peric", - ENABLE_SCLK_PERIC, 1, CLK_SET_RATE_PARENT, 0), + ENABLE_SCLK_PERIC, 1, + CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 0), GATE(CLK_SCLK_UART0, "sclk_uart0", "sclk_uart0_peric", - ENABLE_SCLK_PERIC, 0, CLK_SET_RATE_PARENT, 0), + ENABLE_SCLK_PERIC, 0, + CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 0), }; static const struct samsung_cmu_info peric_cmu_info __initconst = { @@ -2964,7 +2972,7 @@ static const struct samsung_gate_clock aud_gate_clks[] __initconst = { /* ENABLE_SCLK_AUD0 */ GATE(CLK_ATCLK_AUD, "atclk_aud", "div_atclk_aud", ENABLE_SCLK_AUD0, - 2, 0, 0), + 2, CLK_IGNORE_UNUSED, 0), GATE(CLK_PCLK_DBG_AUD, "pclk_dbg_aud", "div_pclk_dbg_aud", ENABLE_SCLK_AUD0, 1, 0, 0), GATE(CLK_SCLK_AUD_CA5, "sclk_aud_ca5", "div_aud_ca5", ENABLE_SCLK_AUD0, @@ -3358,9 +3366,11 @@ static const struct samsung_gate_clock gscl_gate_clks[] __initconst = { GATE(CLK_ACLK_GSCLNP_111, "aclk_gsclnp_111", "mout_aclk_gscl_111_user", ENABLE_ACLK_GSCL, 6, CLK_IGNORE_UNUSED, 0), GATE(CLK_ACLK_GSCLRTND_333, "aclk_gsclrtnd_333", - "mout_aclk_gscl_333_user", ENABLE_ACLK_GSCL, 5, 0, 0), + "mout_aclk_gscl_333_user", ENABLE_ACLK_GSCL, 5, + CLK_IGNORE_UNUSED, 0), GATE(CLK_ACLK_GSCLBEND_333, "aclk_gsclbend_333", - "mout_aclk_gscl_333_user", ENABLE_ACLK_GSCL, 4, 0, 0), + "mout_aclk_gscl_333_user", ENABLE_ACLK_GSCL, 4, + CLK_IGNORE_UNUSED, 0), GATE(CLK_ACLK_GSD, "aclk_gsd", "mout_aclk_gscl_333_user", ENABLE_ACLK_GSCL, 3, 0, 0), GATE(CLK_ACLK_GSCL2, "aclk_gscl2", "mout_aclk_gscl_333_user", -- cgit v1.2.3 From 0e4504470667d355b53ca3c9802fdd2120c9f946 Mon Sep 17 00:00:00 2001 From: Jaehoon Chung Date: Fri, 10 Jun 2016 13:56:32 +0900 Subject: clk: samsung: exynos5433: Add CLK_IGNORE_UNUSED flag to PCIE device This patch adds the CLK_IGNORE_UNUSED flag for PCI Express's clocks which need to remain enabled. The 'pcie' gate clock definition is also added. Signed-off-by: Jaehoon Chung Signed-off-by: Chanwoo Choi [s.nawrocki@samsung.com: edited the patch's summary] Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk-exynos5433.c | 11 ++++++----- include/dt-bindings/clock/exynos5433.h | 3 ++- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/clk/samsung/clk-exynos5433.c b/drivers/clk/samsung/clk-exynos5433.c index 5d26c0f9fe0a..4204eb828d86 100644 --- a/drivers/clk/samsung/clk-exynos5433.c +++ b/drivers/clk/samsung/clk-exynos5433.c @@ -641,7 +641,7 @@ static const struct samsung_gate_clock top_gate_clks[] __initconst = { /* ENABLE_SCLK_TOP_FSYS */ GATE(CLK_SCLK_PCIE_100_FSYS, "sclk_pcie_100_fsys", "div_sclk_pcie_100", - ENABLE_SCLK_TOP_FSYS, 7, 0, 0), + ENABLE_SCLK_TOP_FSYS, 7, CLK_IGNORE_UNUSED, 0), GATE(CLK_SCLK_MMC2_FSYS, "sclk_mmc2_fsys", "div_sclk_mmc2_b", ENABLE_SCLK_TOP_FSYS, 6, CLK_SET_RATE_PARENT, 0), GATE(CLK_SCLK_MMC1_FSYS, "sclk_mmc1_fsys", "div_sclk_mmc1_b", @@ -2148,7 +2148,7 @@ static const struct samsung_gate_clock fsys_gate_clks[] __initconst = { GATE(CLK_ACLK_SMMU_PDMA1, "aclk_smmu_pdma1", "mout_aclk_fsys_200_user", ENABLE_ACLK_FSYS1, 25, CLK_IGNORE_UNUSED, 0), GATE(CLK_ACLK_BTS_PCIE, "aclk_bts_pcie", "mout_aclk_fsys_200_user", - ENABLE_ACLK_FSYS1, 24, 0, 0), + ENABLE_ACLK_FSYS1, 24, CLK_IGNORE_UNUSED, 0), GATE(CLK_ACLK_AXIUS_PDMA1, "aclk_axius_pdma1", "mout_aclk_fsys_200_user", ENABLE_ACLK_FSYS1, 22, CLK_IGNORE_UNUSED, 0), @@ -2195,13 +2195,13 @@ static const struct samsung_gate_clock fsys_gate_clks[] __initconst = { /* ENABLE_PCLK_FSYS */ GATE(CLK_PCLK_PCIE_CTRL, "pclk_pcie_ctrl", "mout_aclk_fsys_200_user", - ENABLE_PCLK_FSYS, 17, 0, 0), + ENABLE_PCLK_FSYS, 17, CLK_IGNORE_UNUSED, 0), GATE(CLK_PCLK_SMMU_PDMA1, "pclk_smmu_pdma1", "mout_aclk_fsys_200_user", ENABLE_PCLK_FSYS, 16, CLK_IGNORE_UNUSED, 0), GATE(CLK_PCLK_PCIE_PHY, "pclk_pcie_phy", "mout_aclk_fsys_200_user", - ENABLE_PCLK_FSYS, 14, 0, 0), + ENABLE_PCLK_FSYS, 14, CLK_IGNORE_UNUSED, 0), GATE(CLK_PCLK_BTS_PCIE, "pclk_bts_pcie", "mout_aclk_fsys_200_user", - ENABLE_PCLK_FSYS, 13, 0, 0), + ENABLE_PCLK_FSYS, 13, CLK_IGNORE_UNUSED, 0), GATE(CLK_PCLK_SMMU_PDMA0, "pclk_smmu_pdma0", "mout_aclk_fsys_200_user", ENABLE_PCLK_FSYS, 8, CLK_IGNORE_UNUSED, 0), GATE(CLK_PCLK_BTS_UFS, "pclk_bts_ufs", "mout_aclk_fsys_200_user", @@ -2280,6 +2280,7 @@ static const struct samsung_gate_clock fsys_gate_clks[] __initconst = { ENABLE_SCLK_FSYS, 0, 0, 0), /* ENABLE_IP_FSYS0 */ + GATE(CLK_PCIE, "pcie", "sclk_pcie_100", ENABLE_IP_FSYS0, 17, 0, 0), GATE(CLK_PDMA1, "pdma1", "aclk_pdma1", ENABLE_IP_FSYS0, 15, 0, 0), GATE(CLK_PDMA0, "pdma0", "aclk_pdma0", ENABLE_IP_FSYS0, 0, 0, 0), }; diff --git a/include/dt-bindings/clock/exynos5433.h b/include/dt-bindings/clock/exynos5433.h index 8e024fea26e7..4fa6bb2136e3 100644 --- a/include/dt-bindings/clock/exynos5433.h +++ b/include/dt-bindings/clock/exynos5433.h @@ -622,8 +622,9 @@ #define CLK_SCLK_UFSUNIPRO 112 #define CLK_SCLK_USBHOST30 113 #define CLK_SCLK_USBDRD30 114 +#define CLK_PCIE 115 -#define FSYS_NR_CLK 115 +#define FSYS_NR_CLK 116 /* CMU_G2D */ #define CLK_MUX_ACLK_G2D_266_USER 1 -- cgit v1.2.3 From eddb65e7fdeac175cd61c54da5a217f47861ddd2 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Fri, 5 Feb 2016 17:17:32 +0100 Subject: clk: tegra: Fixup post dividers on Tegra210 Commit 86c679a52294 ("clk: tegra: pll: Fix _pll_ramp_calc_pll logic and _calc_dynamic_ramp_rate") changed the PLL divider computation logic to consistently use P-divider values from tables as real dividers rather than the hardware values. Unfortunately for some reason many of the Tegra210 clocks didn't have their tables updated (most likely an over- sight by me when applying the patches). This commit fixes them all up. Cc: Jon Hunter Cc: Rhyland Klein Acked-by: Rhyland Klein Signed-off-by: Thierry Reding --- drivers/clk/tegra/clk-tegra210.c | 94 ++++++++++++++++++++-------------------- 1 file changed, 47 insertions(+), 47 deletions(-) diff --git a/drivers/clk/tegra/clk-tegra210.c b/drivers/clk/tegra/clk-tegra210.c index 456cf586d2c2..6149573368ef 100644 --- a/drivers/clk/tegra/clk-tegra210.c +++ b/drivers/clk/tegra/clk-tegra210.c @@ -1366,9 +1366,9 @@ static u32 pll_expo_p_to_pdiv(u32 p, u32 *pdiv) static struct tegra_clk_pll_freq_table pll_x_freq_table[] = { /* 1 GHz */ - { 12000000, 1000000000, 166, 1, 1, 0 }, /* actual: 996.0 MHz */ - { 13000000, 1000000000, 153, 1, 1, 0 }, /* actual: 994.0 MHz */ - { 38400000, 1000000000, 156, 3, 1, 0 }, /* actual: 998.4 MHz */ + { 12000000, 1000000000, 166, 1, 2, 0 }, /* actual: 996.0 MHz */ + { 13000000, 1000000000, 153, 1, 2, 0 }, /* actual: 994.0 MHz */ + { 38400000, 1000000000, 156, 3, 2, 0 }, /* actual: 998.4 MHz */ { 0, 0, 0, 0, 0, 0 }, }; @@ -1417,9 +1417,9 @@ static struct div_nmp pllc_nmp = { }; static struct tegra_clk_pll_freq_table pll_cx_freq_table[] = { - { 12000000, 510000000, 85, 1, 1, 0 }, - { 13000000, 510000000, 78, 1, 1, 0 }, /* actual: 507.0 MHz */ - { 38400000, 510000000, 79, 3, 1, 0 }, /* actual: 505.6 MHz */ + { 12000000, 510000000, 85, 1, 2, 0 }, + { 13000000, 510000000, 78, 1, 2, 0 }, /* actual: 507.0 MHz */ + { 38400000, 510000000, 79, 3, 2, 0 }, /* actual: 505.6 MHz */ { 0, 0, 0, 0, 0, 0 }, }; @@ -1532,9 +1532,9 @@ static struct div_nmp pllss_nmp = { }; static struct tegra_clk_pll_freq_table pll_c4_vco_freq_table[] = { - { 12000000, 600000000, 50, 1, 0, 0 }, - { 13000000, 600000000, 46, 1, 0, 0 }, /* actual: 598.0 MHz */ - { 38400000, 600000000, 62, 4, 0, 0 }, /* actual: 595.2 MHz */ + { 12000000, 600000000, 50, 1, 1, 0 }, + { 13000000, 600000000, 46, 1, 1, 0 }, /* actual: 598.0 MHz */ + { 38400000, 600000000, 62, 4, 1, 0 }, /* actual: 595.2 MHz */ { 0, 0, 0, 0, 0, 0 }, }; @@ -1583,19 +1583,19 @@ static struct tegra_clk_pll_params pll_c4_vco_params = { }; static struct tegra_clk_pll_freq_table pll_m_freq_table[] = { - { 12000000, 800000000, 66, 1, 0, 0 }, /* actual: 792.0 MHz */ - { 13000000, 800000000, 61, 1, 0, 0 }, /* actual: 793.0 MHz */ - { 38400000, 297600000, 93, 4, 2, 0 }, - { 38400000, 400000000, 125, 4, 2, 0 }, - { 38400000, 532800000, 111, 4, 1, 0 }, - { 38400000, 665600000, 104, 3, 1, 0 }, - { 38400000, 800000000, 125, 3, 1, 0 }, - { 38400000, 931200000, 97, 4, 0, 0 }, - { 38400000, 1065600000, 111, 4, 0, 0 }, - { 38400000, 1200000000, 125, 4, 0, 0 }, - { 38400000, 1331200000, 104, 3, 0, 0 }, - { 38400000, 1459200000, 76, 2, 0, 0 }, - { 38400000, 1600000000, 125, 3, 0, 0 }, + { 12000000, 800000000, 66, 1, 1, 0 }, /* actual: 792.0 MHz */ + { 13000000, 800000000, 61, 1, 1, 0 }, /* actual: 793.0 MHz */ + { 38400000, 297600000, 93, 4, 3, 0 }, + { 38400000, 400000000, 125, 4, 3, 0 }, + { 38400000, 532800000, 111, 4, 2, 0 }, + { 38400000, 665600000, 104, 3, 2, 0 }, + { 38400000, 800000000, 125, 3, 2, 0 }, + { 38400000, 931200000, 97, 4, 1, 0 }, + { 38400000, 1065600000, 111, 4, 1, 0 }, + { 38400000, 1200000000, 125, 4, 1, 0 }, + { 38400000, 1331200000, 104, 3, 1, 0 }, + { 38400000, 1459200000, 76, 2, 1, 0 }, + { 38400000, 1600000000, 125, 3, 1, 0 }, { 0, 0, 0, 0, 0, 0 }, }; @@ -1705,9 +1705,9 @@ static struct tegra_clk_pll_params pll_e_params = { }; static struct tegra_clk_pll_freq_table pll_re_vco_freq_table[] = { - { 12000000, 672000000, 56, 1, 0, 0 }, - { 13000000, 672000000, 51, 1, 0, 0 }, /* actual: 663.0 MHz */ - { 38400000, 672000000, 70, 4, 0, 0 }, + { 12000000, 672000000, 56, 1, 1, 0 }, + { 13000000, 672000000, 51, 1, 1, 0 }, /* actual: 663.0 MHz */ + { 38400000, 672000000, 70, 4, 1, 0 }, { 0, 0, 0, 0, 0, 0 }, }; @@ -1754,8 +1754,8 @@ static struct div_nmp pllp_nmp = { }; static struct tegra_clk_pll_freq_table pll_p_freq_table[] = { - { 12000000, 408000000, 34, 1, 0, 0 }, - { 38400000, 408000000, 85, 8, 0, 0 }, /* cf = 4.8MHz, allowed exception */ + { 12000000, 408000000, 34, 1, 1, 0 }, + { 38400000, 408000000, 85, 8, 1, 0 }, /* cf = 4.8MHz, allowed exception */ { 0, 0, 0, 0, 0, 0 }, }; @@ -1820,14 +1820,14 @@ static struct div_nmp plla_nmp = { }; static struct tegra_clk_pll_freq_table pll_a_freq_table[] = { - { 12000000, 282240000, 47, 1, 1, 1, 0xf148 }, /* actual: 282240234 */ - { 12000000, 368640000, 61, 1, 1, 1, 0xfe15 }, /* actual: 368640381 */ - { 12000000, 240000000, 60, 1, 2, 1, 0 }, - { 13000000, 282240000, 43, 1, 1, 1, 0xfd7d }, /* actual: 282239807 */ - { 13000000, 368640000, 56, 1, 1, 1, 0x06d8 }, /* actual: 368640137 */ - { 13000000, 240000000, 55, 1, 2, 1, 0 }, /* actual: 238.3 MHz */ - { 38400000, 282240000, 44, 3, 1, 1, 0xf333 }, /* actual: 282239844 */ - { 38400000, 368640000, 57, 3, 1, 1, 0x0333 }, /* actual: 368639844 */ + { 12000000, 282240000, 47, 1, 2, 1, 0xf148 }, /* actual: 282240234 */ + { 12000000, 368640000, 61, 1, 2, 1, 0xfe15 }, /* actual: 368640381 */ + { 12000000, 240000000, 60, 1, 3, 1, 0 }, + { 13000000, 282240000, 43, 1, 2, 1, 0xfd7d }, /* actual: 282239807 */ + { 13000000, 368640000, 56, 1, 2, 1, 0x06d8 }, /* actual: 368640137 */ + { 13000000, 240000000, 55, 1, 3, 1, 0 }, /* actual: 238.3 MHz */ + { 38400000, 282240000, 44, 3, 2, 1, 0xf333 }, /* actual: 282239844 */ + { 38400000, 368640000, 57, 3, 2, 1, 0x0333 }, /* actual: 368639844 */ { 38400000, 240000000, 75, 3, 3, 1, 0 }, { 0, 0, 0, 0, 0, 0, 0 }, }; @@ -1873,9 +1873,9 @@ static struct div_nmp plld_nmp = { }; static struct tegra_clk_pll_freq_table pll_d_freq_table[] = { - { 12000000, 594000000, 99, 1, 1, 0, 0 }, - { 13000000, 594000000, 91, 1, 1, 0, 0xfc4f }, /* actual: 594000183 */ - { 38400000, 594000000, 30, 1, 1, 0, 0x0e00 }, + { 12000000, 594000000, 99, 1, 2, 0, 0 }, + { 13000000, 594000000, 91, 1, 2, 0, 0xfc4f }, /* actual: 594000183 */ + { 38400000, 594000000, 30, 1, 2, 0, 0x0e00 }, { 0, 0, 0, 0, 0, 0, 0 }, }; @@ -1911,9 +1911,9 @@ static struct tegra_clk_pll_params pll_d_params = { }; static struct tegra_clk_pll_freq_table tegra210_pll_d2_freq_table[] = { - { 12000000, 594000000, 99, 1, 1, 0, 0xf000 }, - { 13000000, 594000000, 91, 1, 1, 0, 0xfc4f }, /* actual: 594000183 */ - { 38400000, 594000000, 30, 1, 1, 0, 0x0e00 }, + { 12000000, 594000000, 99, 1, 2, 0, 0xf000 }, + { 13000000, 594000000, 91, 1, 2, 0, 0xfc4f }, /* actual: 594000183 */ + { 38400000, 594000000, 30, 1, 2, 0, 0x0e00 }, { 0, 0, 0, 0, 0, 0, 0 }, }; @@ -1955,9 +1955,9 @@ static struct tegra_clk_pll_params pll_d2_params = { }; static struct tegra_clk_pll_freq_table pll_dp_freq_table[] = { - { 12000000, 270000000, 90, 1, 3, 0, 0xf000 }, - { 13000000, 270000000, 83, 1, 3, 0, 0xf000 }, /* actual: 269.8 MHz */ - { 38400000, 270000000, 28, 1, 3, 0, 0xf400 }, + { 12000000, 270000000, 90, 1, 4, 0, 0xf000 }, + { 13000000, 270000000, 83, 1, 4, 0, 0xf000 }, /* actual: 269.8 MHz */ + { 38400000, 270000000, 28, 1, 4, 0, 0xf400 }, { 0, 0, 0, 0, 0, 0, 0 }, }; @@ -2007,9 +2007,9 @@ static struct div_nmp pllu_nmp = { }; static struct tegra_clk_pll_freq_table pll_u_freq_table[] = { - { 12000000, 480000000, 40, 1, 0, 0 }, - { 13000000, 480000000, 36, 1, 0, 0 }, /* actual: 468.0 MHz */ - { 38400000, 480000000, 25, 2, 0, 0 }, + { 12000000, 480000000, 40, 1, 1, 0 }, + { 13000000, 480000000, 36, 1, 1, 0 }, /* actual: 468.0 MHz */ + { 38400000, 480000000, 25, 2, 1, 0 }, { 0, 0, 0, 0, 0, 0 }, }; -- cgit v1.2.3 From ba7f4f557eb67ee21c979c8539dc1886f5d5341c Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Wed, 8 Jun 2016 22:33:31 +0800 Subject: clk: imx: correct AV PLL rate formula The audio/video PLL's rate calculation is as below in RM: Fref * (DIV_SELECT + NUM / DENOM), in origin clk-pllv3's code, below code is used: (parent_rate * div) + ((parent_rate / mfd) * mfn as it does NOT consider the float data using div, so below formula should be used as a decent method: (parent_rate * div) + ((parent_rate * mfn) / mfd) and we also need to consider parent_rate * mfd may overflow a 32 bit value, 64 bit value should be used. After updating this formula, the dram PLL's rate is 1066MHz, which is correct, while the old formula gets 1056MHz. [Aisheng: fix clk_pllv3_av_round_rate too] Signed-off-by: Anson Huang Signed-off-by: Dong Aisheng Signed-off-by: Shawn Guo --- drivers/clk/imx/clk-pllv3.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/clk/imx/clk-pllv3.c b/drivers/clk/imx/clk-pllv3.c index 4826b3c9e19e..2afc677979a3 100644 --- a/drivers/clk/imx/clk-pllv3.c +++ b/drivers/clk/imx/clk-pllv3.c @@ -218,8 +218,12 @@ static unsigned long clk_pllv3_av_recalc_rate(struct clk_hw *hw, u32 mfn = readl_relaxed(pll->base + PLL_NUM_OFFSET); u32 mfd = readl_relaxed(pll->base + PLL_DENOM_OFFSET); u32 div = readl_relaxed(pll->base) & pll->div_mask; + u64 temp64 = (u64)parent_rate; - return (parent_rate * div) + ((parent_rate / mfd) * mfn); + temp64 *= mfn; + do_div(temp64, mfd); + + return (parent_rate * div) + (u32)temp64; } static long clk_pllv3_av_round_rate(struct clk_hw *hw, unsigned long rate, @@ -243,7 +247,7 @@ static long clk_pllv3_av_round_rate(struct clk_hw *hw, unsigned long rate, do_div(temp64, parent_rate); mfn = temp64; - return parent_rate * div + parent_rate / mfd * mfn; + return parent_rate * div + parent_rate * mfn / mfd; } static int clk_pllv3_av_set_rate(struct clk_hw *hw, unsigned long rate, -- cgit v1.2.3 From 7e797d9fc8bd8cf0fb1276b1ae78b6542afe48d7 Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Wed, 8 Jun 2016 22:33:32 +0800 Subject: clk: imx7d: correct dram root clk parent select DRAM root clk should be either from pll dram main clk or dram alt root clk. Signed-off-by: Anson Huang Signed-off-by: Dong Aisheng Signed-off-by: Shawn Guo --- drivers/clk/imx/clk-imx7d.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/imx/clk-imx7d.c b/drivers/clk/imx/clk-imx7d.c index 522996800d5b..6545e07bdd38 100644 --- a/drivers/clk/imx/clk-imx7d.c +++ b/drivers/clk/imx/clk-imx7d.c @@ -65,7 +65,7 @@ static const char *dram_phym_sel[] = { "pll_dram_main_clk", "dram_phym_alt_clk", }; static const char *dram_sel[] = { "pll_dram_main_clk", - "dram_alt_clk", }; + "dram_alt_root_clk", }; static const char *dram_phym_alt_sel[] = { "osc", "pll_dram_533m_clk", "pll_sys_main_clk", "pll_enet_500m_clk", -- cgit v1.2.3 From 147947549507fbbdbb05d4a3a24f05c2e450559f Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Wed, 8 Jun 2016 22:33:33 +0800 Subject: clk: imx7d: correct dram pll type DRAM PLL is a audio/video type PLL, need to correct it to get correct ops of PLL. Signed-off-by: Anson Huang Signed-off-by: Dong Aisheng Signed-off-by: Shawn Guo --- drivers/clk/imx/clk-imx7d.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/imx/clk-imx7d.c b/drivers/clk/imx/clk-imx7d.c index 6545e07bdd38..37ef9a6ba974 100644 --- a/drivers/clk/imx/clk-imx7d.c +++ b/drivers/clk/imx/clk-imx7d.c @@ -396,7 +396,7 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node) clks[IMX7D_PLL_VIDEO_MAIN_SRC] = imx_clk_mux("pll_video_main_src", base + 0x130, 14, 2, pll_bypass_src_sel, ARRAY_SIZE(pll_bypass_src_sel)); clks[IMX7D_PLL_ARM_MAIN] = imx_clk_pllv3(IMX_PLLV3_SYS, "pll_arm_main", "pll_arm_main_src", base + 0x60, 0x7f); - clks[IMX7D_PLL_DRAM_MAIN] = imx_clk_pllv3(IMX_PLLV3_SYS, "pll_dram_main", "pll_dram_main_src", base + 0x70, 0x7f); + clks[IMX7D_PLL_DRAM_MAIN] = imx_clk_pllv3(IMX_PLLV3_AV, "pll_dram_main", "pll_dram_main_src", base + 0x70, 0x7f); clks[IMX7D_PLL_SYS_MAIN] = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll_sys_main", "pll_sys_main_src", base + 0xb0, 0x1); clks[IMX7D_PLL_ENET_MAIN] = imx_clk_pllv3(IMX_PLLV3_ENET_IMX7, "pll_enet_main", "pll_enet_main_src", base + 0xe0, 0x0); clks[IMX7D_PLL_AUDIO_MAIN] = imx_clk_pllv3(IMX_PLLV3_AV, "pll_audio_main", "pll_audio_main_src", base + 0xf0, 0x7f); -- cgit v1.2.3 From f83d31635cd65dd10eddaac1809b9e400d385d43 Mon Sep 17 00:00:00 2001 From: Dong Aisheng Date: Wed, 8 Jun 2016 22:33:36 +0800 Subject: clk: imx: fix pll clock parents pllx_bypass_src mux shouldn't be the parent of pllx clock since it's only valid when when pllx BYPASS bit is set. Thus it is actually one parent of pllx_bypass only. Instead, pllx parent should be fixed to osc according to reference manual. Other plls have the same issue. e.g. before fix, the pll tree is: osc 6 6 24000000 0 0 pll1_bypass_src 0 0 24000000 0 0 pll1 0 0 792000000 0 0 pll1_bypass 0 0 792000000 0 0 pll1_sys 0 0 792000000 0 0 After the fix, it's: osc 6 6 24000000 0 0 pll1 0 0 792000000 0 0 pll1_bypass 0 0 792000000 0 0 pll1_sys 0 0 792000000 0 0 Signed-off-by: Dong Aisheng Signed-off-by: Shawn Guo --- drivers/clk/imx/clk-imx6q.c | 14 +++++++------- drivers/clk/imx/clk-imx6sl.c | 14 +++++++------- drivers/clk/imx/clk-imx6sx.c | 14 +++++++------- drivers/clk/imx/clk-imx6ul.c | 14 +++++++------- drivers/clk/imx/clk-imx7d.c | 12 ++++++------ 5 files changed, 34 insertions(+), 34 deletions(-) diff --git a/drivers/clk/imx/clk-imx6q.c b/drivers/clk/imx/clk-imx6q.c index 2beb396fe652..ba1c1ae72ac2 100644 --- a/drivers/clk/imx/clk-imx6q.c +++ b/drivers/clk/imx/clk-imx6q.c @@ -192,13 +192,13 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node) clk[IMX6QDL_PLL7_BYPASS_SRC] = imx_clk_mux("pll7_bypass_src", base + 0x20, 14, 2, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels)); /* type name parent_name base div_mask */ - clk[IMX6QDL_CLK_PLL1] = imx_clk_pllv3(IMX_PLLV3_SYS, "pll1", "pll1_bypass_src", base + 0x00, 0x7f); - clk[IMX6QDL_CLK_PLL2] = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll2", "pll2_bypass_src", base + 0x30, 0x1); - clk[IMX6QDL_CLK_PLL3] = imx_clk_pllv3(IMX_PLLV3_USB, "pll3", "pll3_bypass_src", base + 0x10, 0x3); - clk[IMX6QDL_CLK_PLL4] = imx_clk_pllv3(IMX_PLLV3_AV, "pll4", "pll4_bypass_src", base + 0x70, 0x7f); - clk[IMX6QDL_CLK_PLL5] = imx_clk_pllv3(IMX_PLLV3_AV, "pll5", "pll5_bypass_src", base + 0xa0, 0x7f); - clk[IMX6QDL_CLK_PLL6] = imx_clk_pllv3(IMX_PLLV3_ENET, "pll6", "pll6_bypass_src", base + 0xe0, 0x3); - clk[IMX6QDL_CLK_PLL7] = imx_clk_pllv3(IMX_PLLV3_USB, "pll7", "pll7_bypass_src", base + 0x20, 0x3); + clk[IMX6QDL_CLK_PLL1] = imx_clk_pllv3(IMX_PLLV3_SYS, "pll1", "osc", base + 0x00, 0x7f); + clk[IMX6QDL_CLK_PLL2] = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll2", "osc", base + 0x30, 0x1); + clk[IMX6QDL_CLK_PLL3] = imx_clk_pllv3(IMX_PLLV3_USB, "pll3", "osc", base + 0x10, 0x3); + clk[IMX6QDL_CLK_PLL4] = imx_clk_pllv3(IMX_PLLV3_AV, "pll4", "osc", base + 0x70, 0x7f); + clk[IMX6QDL_CLK_PLL5] = imx_clk_pllv3(IMX_PLLV3_AV, "pll5", "osc", base + 0xa0, 0x7f); + clk[IMX6QDL_CLK_PLL6] = imx_clk_pllv3(IMX_PLLV3_ENET, "pll6", "osc", base + 0xe0, 0x3); + clk[IMX6QDL_CLK_PLL7] = imx_clk_pllv3(IMX_PLLV3_USB, "pll7", "osc", base + 0x20, 0x3); clk[IMX6QDL_PLL1_BYPASS] = imx_clk_mux_flags("pll1_bypass", base + 0x00, 16, 1, pll1_bypass_sels, ARRAY_SIZE(pll1_bypass_sels), CLK_SET_RATE_PARENT); clk[IMX6QDL_PLL2_BYPASS] = imx_clk_mux_flags("pll2_bypass", base + 0x30, 16, 1, pll2_bypass_sels, ARRAY_SIZE(pll2_bypass_sels), CLK_SET_RATE_PARENT); diff --git a/drivers/clk/imx/clk-imx6sl.c b/drivers/clk/imx/clk-imx6sl.c index 1be6230a07af..5fd4ddac1bf1 100644 --- a/drivers/clk/imx/clk-imx6sl.c +++ b/drivers/clk/imx/clk-imx6sl.c @@ -218,13 +218,13 @@ static void __init imx6sl_clocks_init(struct device_node *ccm_node) clks[IMX6SL_PLL7_BYPASS_SRC] = imx_clk_mux("pll7_bypass_src", base + 0x20, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels)); /* type name parent_name base div_mask */ - clks[IMX6SL_CLK_PLL1] = imx_clk_pllv3(IMX_PLLV3_SYS, "pll1", "pll1_bypass_src", base + 0x00, 0x7f); - clks[IMX6SL_CLK_PLL2] = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll2", "pll2_bypass_src", base + 0x30, 0x1); - clks[IMX6SL_CLK_PLL3] = imx_clk_pllv3(IMX_PLLV3_USB, "pll3", "pll3_bypass_src", base + 0x10, 0x3); - clks[IMX6SL_CLK_PLL4] = imx_clk_pllv3(IMX_PLLV3_AV, "pll4", "pll4_bypass_src", base + 0x70, 0x7f); - clks[IMX6SL_CLK_PLL5] = imx_clk_pllv3(IMX_PLLV3_AV, "pll5", "pll5_bypass_src", base + 0xa0, 0x7f); - clks[IMX6SL_CLK_PLL6] = imx_clk_pllv3(IMX_PLLV3_ENET, "pll6", "pll6_bypass_src", base + 0xe0, 0x3); - clks[IMX6SL_CLK_PLL7] = imx_clk_pllv3(IMX_PLLV3_USB, "pll7", "pll7_bypass_src", base + 0x20, 0x3); + clks[IMX6SL_CLK_PLL1] = imx_clk_pllv3(IMX_PLLV3_SYS, "pll1", "osc", base + 0x00, 0x7f); + clks[IMX6SL_CLK_PLL2] = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll2", "osc", base + 0x30, 0x1); + clks[IMX6SL_CLK_PLL3] = imx_clk_pllv3(IMX_PLLV3_USB, "pll3", "osc", base + 0x10, 0x3); + clks[IMX6SL_CLK_PLL4] = imx_clk_pllv3(IMX_PLLV3_AV, "pll4", "osc", base + 0x70, 0x7f); + clks[IMX6SL_CLK_PLL5] = imx_clk_pllv3(IMX_PLLV3_AV, "pll5", "osc", base + 0xa0, 0x7f); + clks[IMX6SL_CLK_PLL6] = imx_clk_pllv3(IMX_PLLV3_ENET, "pll6", "osc", base + 0xe0, 0x3); + clks[IMX6SL_CLK_PLL7] = imx_clk_pllv3(IMX_PLLV3_USB, "pll7", "osc", base + 0x20, 0x3); clks[IMX6SL_PLL1_BYPASS] = imx_clk_mux_flags("pll1_bypass", base + 0x00, 16, 1, pll1_bypass_sels, ARRAY_SIZE(pll1_bypass_sels), CLK_SET_RATE_PARENT); clks[IMX6SL_PLL2_BYPASS] = imx_clk_mux_flags("pll2_bypass", base + 0x30, 16, 1, pll2_bypass_sels, ARRAY_SIZE(pll2_bypass_sels), CLK_SET_RATE_PARENT); diff --git a/drivers/clk/imx/clk-imx6sx.c b/drivers/clk/imx/clk-imx6sx.c index 97e742a8be17..b5c96de41ccf 100644 --- a/drivers/clk/imx/clk-imx6sx.c +++ b/drivers/clk/imx/clk-imx6sx.c @@ -174,13 +174,13 @@ static void __init imx6sx_clocks_init(struct device_node *ccm_node) clks[IMX6SX_PLL7_BYPASS_SRC] = imx_clk_mux("pll7_bypass_src", base + 0x20, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels)); /* type name parent_name base div_mask */ - clks[IMX6SX_CLK_PLL1] = imx_clk_pllv3(IMX_PLLV3_SYS, "pll1", "pll1_bypass_src", base + 0x00, 0x7f); - clks[IMX6SX_CLK_PLL2] = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll2", "pll2_bypass_src", base + 0x30, 0x1); - clks[IMX6SX_CLK_PLL3] = imx_clk_pllv3(IMX_PLLV3_USB, "pll3", "pll3_bypass_src", base + 0x10, 0x3); - clks[IMX6SX_CLK_PLL4] = imx_clk_pllv3(IMX_PLLV3_AV, "pll4", "pll4_bypass_src", base + 0x70, 0x7f); - clks[IMX6SX_CLK_PLL5] = imx_clk_pllv3(IMX_PLLV3_AV, "pll5", "pll5_bypass_src", base + 0xa0, 0x7f); - clks[IMX6SX_CLK_PLL6] = imx_clk_pllv3(IMX_PLLV3_ENET, "pll6", "pll6_bypass_src", base + 0xe0, 0x3); - clks[IMX6SX_CLK_PLL7] = imx_clk_pllv3(IMX_PLLV3_USB, "pll7", "pll7_bypass_src", base + 0x20, 0x3); + clks[IMX6SX_CLK_PLL1] = imx_clk_pllv3(IMX_PLLV3_SYS, "pll1", "osc", base + 0x00, 0x7f); + clks[IMX6SX_CLK_PLL2] = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll2", "osc", base + 0x30, 0x1); + clks[IMX6SX_CLK_PLL3] = imx_clk_pllv3(IMX_PLLV3_USB, "pll3", "osc", base + 0x10, 0x3); + clks[IMX6SX_CLK_PLL4] = imx_clk_pllv3(IMX_PLLV3_AV, "pll4", "osc", base + 0x70, 0x7f); + clks[IMX6SX_CLK_PLL5] = imx_clk_pllv3(IMX_PLLV3_AV, "pll5", "osc", base + 0xa0, 0x7f); + clks[IMX6SX_CLK_PLL6] = imx_clk_pllv3(IMX_PLLV3_ENET, "pll6", "osc", base + 0xe0, 0x3); + clks[IMX6SX_CLK_PLL7] = imx_clk_pllv3(IMX_PLLV3_USB, "pll7", "osc", base + 0x20, 0x3); clks[IMX6SX_PLL1_BYPASS] = imx_clk_mux_flags("pll1_bypass", base + 0x00, 16, 1, pll1_bypass_sels, ARRAY_SIZE(pll1_bypass_sels), CLK_SET_RATE_PARENT); clks[IMX6SX_PLL2_BYPASS] = imx_clk_mux_flags("pll2_bypass", base + 0x30, 16, 1, pll2_bypass_sels, ARRAY_SIZE(pll2_bypass_sels), CLK_SET_RATE_PARENT); diff --git a/drivers/clk/imx/clk-imx6ul.c b/drivers/clk/imx/clk-imx6ul.c index 0f1f17a8f3ed..38da5a522d58 100644 --- a/drivers/clk/imx/clk-imx6ul.c +++ b/drivers/clk/imx/clk-imx6ul.c @@ -130,13 +130,13 @@ static void __init imx6ul_clocks_init(struct device_node *ccm_node) clks[IMX6UL_PLL6_BYPASS_SRC] = imx_clk_mux("pll6_bypass_src", base + 0xe0, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels)); clks[IMX6UL_PLL7_BYPASS_SRC] = imx_clk_mux("pll7_bypass_src", base + 0x20, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels)); - clks[IMX6UL_CLK_PLL1] = imx_clk_pllv3(IMX_PLLV3_SYS, "pll1", "pll1_bypass_src", base + 0x00, 0x7f); - clks[IMX6UL_CLK_PLL2] = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll2", "pll2_bypass_src", base + 0x30, 0x1); - clks[IMX6UL_CLK_PLL3] = imx_clk_pllv3(IMX_PLLV3_USB, "pll3", "pll3_bypass_src", base + 0x10, 0x3); - clks[IMX6UL_CLK_PLL4] = imx_clk_pllv3(IMX_PLLV3_AV, "pll4", "pll4_bypass_src", base + 0x70, 0x7f); - clks[IMX6UL_CLK_PLL5] = imx_clk_pllv3(IMX_PLLV3_AV, "pll5", "pll5_bypass_src", base + 0xa0, 0x7f); - clks[IMX6UL_CLK_PLL6] = imx_clk_pllv3(IMX_PLLV3_ENET, "pll6", "pll6_bypass_src", base + 0xe0, 0x3); - clks[IMX6UL_CLK_PLL7] = imx_clk_pllv3(IMX_PLLV3_USB, "pll7", "pll7_bypass_src", base + 0x20, 0x3); + clks[IMX6UL_CLK_PLL1] = imx_clk_pllv3(IMX_PLLV3_SYS, "pll1", "osc", base + 0x00, 0x7f); + clks[IMX6UL_CLK_PLL2] = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll2", "osc", base + 0x30, 0x1); + clks[IMX6UL_CLK_PLL3] = imx_clk_pllv3(IMX_PLLV3_USB, "pll3", "osc", base + 0x10, 0x3); + clks[IMX6UL_CLK_PLL4] = imx_clk_pllv3(IMX_PLLV3_AV, "pll4", "osc", base + 0x70, 0x7f); + clks[IMX6UL_CLK_PLL5] = imx_clk_pllv3(IMX_PLLV3_AV, "pll5", "osc", base + 0xa0, 0x7f); + clks[IMX6UL_CLK_PLL6] = imx_clk_pllv3(IMX_PLLV3_ENET, "pll6", "osc", base + 0xe0, 0x3); + clks[IMX6UL_CLK_PLL7] = imx_clk_pllv3(IMX_PLLV3_USB, "pll7", "osc", base + 0x20, 0x3); clks[IMX6UL_PLL1_BYPASS] = imx_clk_mux_flags("pll1_bypass", base + 0x00, 16, 1, pll1_bypass_sels, ARRAY_SIZE(pll1_bypass_sels), CLK_SET_RATE_PARENT); clks[IMX6UL_PLL2_BYPASS] = imx_clk_mux_flags("pll2_bypass", base + 0x30, 16, 1, pll2_bypass_sels, ARRAY_SIZE(pll2_bypass_sels), CLK_SET_RATE_PARENT); diff --git a/drivers/clk/imx/clk-imx7d.c b/drivers/clk/imx/clk-imx7d.c index 37ef9a6ba974..0c0003d8af5f 100644 --- a/drivers/clk/imx/clk-imx7d.c +++ b/drivers/clk/imx/clk-imx7d.c @@ -395,12 +395,12 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node) clks[IMX7D_PLL_AUDIO_MAIN_SRC] = imx_clk_mux("pll_audio_main_src", base + 0xf0, 14, 2, pll_bypass_src_sel, ARRAY_SIZE(pll_bypass_src_sel)); clks[IMX7D_PLL_VIDEO_MAIN_SRC] = imx_clk_mux("pll_video_main_src", base + 0x130, 14, 2, pll_bypass_src_sel, ARRAY_SIZE(pll_bypass_src_sel)); - clks[IMX7D_PLL_ARM_MAIN] = imx_clk_pllv3(IMX_PLLV3_SYS, "pll_arm_main", "pll_arm_main_src", base + 0x60, 0x7f); - clks[IMX7D_PLL_DRAM_MAIN] = imx_clk_pllv3(IMX_PLLV3_AV, "pll_dram_main", "pll_dram_main_src", base + 0x70, 0x7f); - clks[IMX7D_PLL_SYS_MAIN] = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll_sys_main", "pll_sys_main_src", base + 0xb0, 0x1); - clks[IMX7D_PLL_ENET_MAIN] = imx_clk_pllv3(IMX_PLLV3_ENET_IMX7, "pll_enet_main", "pll_enet_main_src", base + 0xe0, 0x0); - clks[IMX7D_PLL_AUDIO_MAIN] = imx_clk_pllv3(IMX_PLLV3_AV, "pll_audio_main", "pll_audio_main_src", base + 0xf0, 0x7f); - clks[IMX7D_PLL_VIDEO_MAIN] = imx_clk_pllv3(IMX_PLLV3_AV, "pll_video_main", "pll_video_main_src", base + 0x130, 0x7f); + clks[IMX7D_PLL_ARM_MAIN] = imx_clk_pllv3(IMX_PLLV3_SYS, "pll_arm_main", "osc", base + 0x60, 0x7f); + clks[IMX7D_PLL_DRAM_MAIN] = imx_clk_pllv3(IMX_PLLV3_AV, "pll_dram_main", "osc", base + 0x70, 0x7f); + clks[IMX7D_PLL_SYS_MAIN] = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll_sys_main", "osc", base + 0xb0, 0x1); + clks[IMX7D_PLL_ENET_MAIN] = imx_clk_pllv3(IMX_PLLV3_ENET_IMX7, "pll_enet_main", "osc", base + 0xe0, 0x0); + clks[IMX7D_PLL_AUDIO_MAIN] = imx_clk_pllv3(IMX_PLLV3_AV, "pll_audio_main", "osc", base + 0xf0, 0x7f); + clks[IMX7D_PLL_VIDEO_MAIN] = imx_clk_pllv3(IMX_PLLV3_AV, "pll_video_main", "osc", base + 0x130, 0x7f); clks[IMX7D_PLL_ARM_MAIN_BYPASS] = imx_clk_mux_flags("pll_arm_main_bypass", base + 0x60, 16, 1, pll_arm_bypass_sel, ARRAY_SIZE(pll_arm_bypass_sel), CLK_SET_RATE_PARENT); clks[IMX7D_PLL_DRAM_MAIN_BYPASS] = imx_clk_mux_flags("pll_dram_main_bypass", base + 0x70, 16, 1, pll_dram_bypass_sel, ARRAY_SIZE(pll_dram_bypass_sel), CLK_SET_RATE_PARENT); -- cgit v1.2.3 From b3e76bdc0b2190e67427d31cd740debd01c03631 Mon Sep 17 00:00:00 2001 From: Dong Aisheng Date: Wed, 8 Jun 2016 22:33:30 +0800 Subject: clk: imx: clk-pllv3: fix incorrect handle of enet powerdown bit After commit f53947456f98 ("ARM: clk: imx: update pllv3 to support imx7"), the former used BM_PLL_POWER bit is not correct anymore for IMX7 ENET. Instead, pll->powerdown holds the correct bit, so using powerdown bit in clk_pllv3_{prepare | unprepare} functions. Fixes: f53947456f98 ("ARM: clk: imx: update pllv3 to support imx7") Signed-off-by: Dong Aisheng Signed-off-by: Shawn Guo --- drivers/clk/imx/clk-pllv3.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/clk/imx/clk-pllv3.c b/drivers/clk/imx/clk-pllv3.c index 2afc677979a3..eea2b1b3791e 100644 --- a/drivers/clk/imx/clk-pllv3.c +++ b/drivers/clk/imx/clk-pllv3.c @@ -77,9 +77,9 @@ static int clk_pllv3_prepare(struct clk_hw *hw) val = readl_relaxed(pll->base); if (pll->powerup_set) - val |= BM_PLL_POWER; + val |= pll->powerdown; else - val &= ~BM_PLL_POWER; + val &= ~pll->powerdown; writel_relaxed(val, pll->base); return clk_pllv3_wait_lock(pll); @@ -92,9 +92,9 @@ static void clk_pllv3_unprepare(struct clk_hw *hw) val = readl_relaxed(pll->base); if (pll->powerup_set) - val &= ~BM_PLL_POWER; + val &= ~pll->powerdown; else - val |= BM_PLL_POWER; + val |= pll->powerdown; writel_relaxed(val, pll->base); } -- cgit v1.2.3 From 2f87a6ea1b0c4dfb71acf40d24f12b27e7680794 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Tue, 26 Apr 2016 12:43:57 -0700 Subject: clk: Add _rcuidle tracepoints to allow clk_core_disable() use from idle This commit adds an _rcuidle suffix to a pair of trace events to prevent the following splat: > =============================== > [ INFO: suspicious RCU usage. ] > 4.6.0-rc5-next-20160426+ #1114 Not tainted > ------------------------------- > include/trace/events/clk.h:59 suspicious rcu_dereference_check() usage! > > other info that might help us debug this: > > > RCU used illegally from idle CPU! > rcu_scheduler_active = 1, debug_locks = 0 > RCU used illegally from extended quiescent state! > 2 locks held by swapper/0/0: > #0: (&oh->hwmod_key#30){......}, at: [] omap_hwmod_idle+0x18/0x44 > #1: (enable_lock){......}, at: [] clk_enable_lock+0x18/0x124 > > stack backtrace: > CPU: 0 PID: 0 Comm: swapper/0 Not tainted 4.6.0-rc5-next-20160426+ #1114 > Hardware name: Generic OMAP36xx (Flattened Device Tree) > [] (unwind_backtrace) from [] (show_stack+0x10/0x14) > [] (show_stack) from [] (dump_stack+0xb0/0xe4) > [] (dump_stack) from [] (clk_core_disable+0x17c/0x348) > [] (clk_core_disable) from [] (clk_disable+0x24/0x30) > [] (clk_disable) from [] (_disable_clocks+0x18/0x7c) > [] (_disable_clocks) from [] (_idle+0x12c/0x230) > [] (_idle) from [] (omap_hwmod_idle+0x24/0x44) > [] (omap_hwmod_idle) from [] (omap_device_idle+0x3c/0x90) > [] (omap_device_idle) from [] (__rpm_callback+0x2c/0x60) > [] (__rpm_callback) from [] (rpm_callback+0x20/0x80) > [] (rpm_callback) from [] (rpm_suspend+0x100/0x768) > [] (rpm_suspend) from [] (__pm_runtime_suspend+0x64/0x84) > [] (__pm_runtime_suspend) from [] (omap2_gpio_prepare_for_idle+0x5c/0x70) > [] (omap2_gpio_prepare_for_idle) from [] (omap_sram_idle+0x140/0x244) > [] (omap_sram_idle) from [] (omap3_enter_idle_bm+0xfc/0x1ec) > [] (omap3_enter_idle_bm) from [] (cpuidle_enter_state+0x80/0x3d4) > [] (cpuidle_enter_state) from [] (cpu_startup_entry+0x198/0x3a0) > [] (cpu_startup_entry) from [] (start_kernel+0x354/0x3c8) > [] (start_kernel) from [<8000807c>] (0x8000807c) Reported-by: Tony Lindgren Signed-off-by: Paul E. McKenney Tested-by: Tony Lindgren Tested-by: Guenter Roeck Cc: Russell King Cc: Steven Rostedt Cc: Michael Turquette Cc: Stephen Boyd Cc: Cc: Cc: --- drivers/clk/clk.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index fb74dc1f7520..4fa43c02d682 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -682,12 +682,12 @@ static void clk_core_disable(struct clk_core *core) if (--core->enable_count > 0) return; - trace_clk_disable(core); + trace_clk_disable_rcuidle(core); if (core->ops->disable) core->ops->disable(core->hw); - trace_clk_disable_complete(core); + trace_clk_disable_complete_rcuidle(core); clk_core_disable(core->parent); } -- cgit v1.2.3 From f17a0dd1c2e0d05c38589c9a13a36db455b74818 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Tue, 26 Apr 2016 14:02:23 -0700 Subject: clk: Use _rcuidle suffix to allow clk_core_enable() to used from idle This commit fixes the RCU use-from-idle bug corresponding the following splat: > [ INFO: suspicious RCU usage. ] > 4.6.0-rc5-next-20160426+ #1127 Not tainted > ------------------------------- > include/trace/events/clk.h:45 suspicious rcu_dereference_check() usage! > > other info that might help us debug this: > > > RCU used illegally from idle CPU! > rcu_scheduler_active = 1, debug_locks = 0 > RCU used illegally from extended quiescent state! > 2 locks held by swapper/0/0: > #0: (&oh->hwmod_key#30){......}, at: [] omap_hwmod_enable+0x18/0x44 > #1: (enable_lock){......}, at: [] clk_enable_lock+0x18/0x124 > > stack backtrace: > CPU: 0 PID: 0 Comm: swapper/0 Not tainted 4.6.0-rc5-next-20160426+ #1127 > Hardware name: Generic OMAP36xx (Flattened Device Tree) > [] (unwind_backtrace) from [] (show_stack+0x10/0x14) > [] (show_stack) from [] (dump_stack+0xb0/0xe4) > [] (dump_stack) from [] (clk_core_enable+0x1e0/0x36c) > [] (clk_core_enable) from [] (clk_enable+0x1c/0x38) > [] (clk_enable) from [] (_enable_clocks+0x18/0x7c) > [] (_enable_clocks) from [] (_enable+0x114/0x2ec) > [] (_enable) from [] (omap_hwmod_enable+0x24/0x44) > [] (omap_hwmod_enable) from [] (omap_device_enable+0x3c/0x90) > [] (omap_device_enable) from [] (_od_runtime_resume+0x10/0x38) > [] (_od_runtime_resume) from [] (__rpm_callback+0x2c/0x60) > [] (__rpm_callback) from [] (rpm_callback+0x20/0x80) > [] (rpm_callback) from [] (rpm_resume+0x3d0/0x6f0) > [] (rpm_resume) from [] (__pm_runtime_resume+0x4c/0x64) > [] (__pm_runtime_resume) from [] (omap2_gpio_resume_after_idle+0x54/0x68) > [] (omap2_gpio_resume_after_idle) from [] (omap3_enter_idle_bm+0xfc/0x1ec) > [] (omap3_enter_idle_bm) from [] (cpuidle_enter_state+0x80/0x3d4) > [] (cpuidle_enter_state) from [] (cpu_startup_entry+0x198/0x3a0) > [] (cpu_startup_entry) from [] (start_kernel+0x354/0x3c8) > [] (start_kernel) from [<8000807c>] (0x8000807c) Reported-by: Tony Lindgren Signed-off-by: Paul E. McKenney Tested-by: Tony Lindgren Tested-by: Guenter Roeck Cc: Russell King Cc: Steven Rostedt Cc: Michael Turquette Cc: Stephen Boyd Cc: Cc: Cc: --- drivers/clk/clk.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 4fa43c02d682..ec83f404c1d2 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -735,12 +735,12 @@ static int clk_core_enable(struct clk_core *core) if (ret) return ret; - trace_clk_enable(core); + trace_clk_enable_rcuidle(core); if (core->ops->enable) ret = core->ops->enable(core->hw); - trace_clk_enable_complete(core); + trace_clk_enable_complete_rcuidle(core); if (ret) { clk_core_disable(core->parent); -- cgit v1.2.3 From c684766308abf473478cdd277839a7568111ec4b Mon Sep 17 00:00:00 2001 From: Dong Aisheng Date: Mon, 13 Jun 2016 20:24:52 +0800 Subject: clk: imx: refine the powerdown bit of clk-pllv3 The powerdown bit is a bit confused, let's change it to power_bit to relfect both powerdown and powerup case according to different plls. Signed-off-by: Dong Aisheng Signed-off-by: Shawn Guo --- drivers/clk/imx/clk-pllv3.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/clk/imx/clk-pllv3.c b/drivers/clk/imx/clk-pllv3.c index eea2b1b3791e..19f9b622981a 100644 --- a/drivers/clk/imx/clk-pllv3.c +++ b/drivers/clk/imx/clk-pllv3.c @@ -29,8 +29,8 @@ * struct clk_pllv3 - IMX PLL clock version 3 * @clk_hw: clock source * @base: base address of PLL registers - * @powerup_set: set POWER bit to power up the PLL - * @powerdown: pll powerdown offset bit + * @power_bit: pll power bit mask + * @powerup_set: set power_bit to power up the PLL * @div_mask: mask of divider bits * @div_shift: shift of divider bits * @@ -40,8 +40,8 @@ struct clk_pllv3 { struct clk_hw hw; void __iomem *base; + u32 power_bit; bool powerup_set; - u32 powerdown; u32 div_mask; u32 div_shift; unsigned long ref_clock; @@ -52,7 +52,7 @@ struct clk_pllv3 { static int clk_pllv3_wait_lock(struct clk_pllv3 *pll) { unsigned long timeout = jiffies + msecs_to_jiffies(10); - u32 val = readl_relaxed(pll->base) & pll->powerdown; + u32 val = readl_relaxed(pll->base) & pll->power_bit; /* No need to wait for lock when pll is not powered up */ if ((pll->powerup_set && !val) || (!pll->powerup_set && val)) @@ -77,9 +77,9 @@ static int clk_pllv3_prepare(struct clk_hw *hw) val = readl_relaxed(pll->base); if (pll->powerup_set) - val |= pll->powerdown; + val |= pll->power_bit; else - val &= ~pll->powerdown; + val &= ~pll->power_bit; writel_relaxed(val, pll->base); return clk_pllv3_wait_lock(pll); @@ -92,9 +92,9 @@ static void clk_pllv3_unprepare(struct clk_hw *hw) val = readl_relaxed(pll->base); if (pll->powerup_set) - val &= ~pll->powerdown; + val &= ~pll->power_bit; else - val |= pll->powerdown; + val |= pll->power_bit; writel_relaxed(val, pll->base); } @@ -316,7 +316,7 @@ struct clk *imx_clk_pllv3(enum imx_pllv3_type type, const char *name, if (!pll) return ERR_PTR(-ENOMEM); - pll->powerdown = BM_PLL_POWER; + pll->power_bit = BM_PLL_POWER; switch (type) { case IMX_PLLV3_SYS: @@ -332,7 +332,7 @@ struct clk *imx_clk_pllv3(enum imx_pllv3_type type, const char *name, ops = &clk_pllv3_av_ops; break; case IMX_PLLV3_ENET_IMX7: - pll->powerdown = IMX7_ENET_PLL_POWER; + pll->power_bit = IMX7_ENET_PLL_POWER; pll->ref_clock = 1000000000; ops = &clk_pllv3_enet_ops; break; -- cgit v1.2.3 From bfa10f7d9ae2a6d1e615bf6841887fd9adb056be Mon Sep 17 00:00:00 2001 From: Dong Aisheng Date: Mon, 13 Jun 2016 15:38:30 +0800 Subject: clk: imx6ul: fix gpt2 clock names fix gpt2 clock names Signed-off-by: Dong Aisheng Signed-off-by: Shawn Guo --- drivers/clk/imx/clk-imx6ul.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/clk/imx/clk-imx6ul.c b/drivers/clk/imx/clk-imx6ul.c index 38da5a522d58..d1d7787ce211 100644 --- a/drivers/clk/imx/clk-imx6ul.c +++ b/drivers/clk/imx/clk-imx6ul.c @@ -305,8 +305,8 @@ static void __init imx6ul_clocks_init(struct device_node *ccm_node) clks[IMX6UL_CLK_CAN1_SERIAL] = imx_clk_gate2("can1_serial", "can_podf", base + 0x68, 16); clks[IMX6UL_CLK_CAN2_IPG] = imx_clk_gate2("can2_ipg", "ipg", base + 0x68, 18); clks[IMX6UL_CLK_CAN2_SERIAL] = imx_clk_gate2("can2_serial", "can_podf", base + 0x68, 20); - clks[IMX6UL_CLK_GPT2_BUS] = imx_clk_gate2("gpt_bus", "perclk", base + 0x68, 24); - clks[IMX6UL_CLK_GPT2_SERIAL] = imx_clk_gate2("gpt_serial", "perclk", base + 0x68, 26); + clks[IMX6UL_CLK_GPT2_BUS] = imx_clk_gate2("gpt2_bus", "perclk", base + 0x68, 24); + clks[IMX6UL_CLK_GPT2_SERIAL] = imx_clk_gate2("gpt2_serial", "perclk", base + 0x68, 26); clks[IMX6UL_CLK_UART2_IPG] = imx_clk_gate2("uart2_ipg", "ipg", base + 0x68, 28); clks[IMX6UL_CLK_UART2_SERIAL] = imx_clk_gate2("uart2_serial", "uart_podf", base + 0x68, 28); clks[IMX6UL_CLK_AIPSTZ3] = imx_clk_gate2("aips_tz3", "ahb", base + 0x68, 30); -- cgit v1.2.3 From e2f716561b7eb6fd5c5962ee0bdbfc7ce2b21243 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Wed, 5 Aug 2015 16:29:40 +0200 Subject: clk: tegra: Disable spread spectrum on pll_d2 Enabling spread spectrum on pll_d2 can lead to issues with display modes. HDMI monitors, for example, would report "Signal Error" and some modes driven over DisplayPort would generate fuzzy horizontal bands. Signed-off-by: Thierry Reding --- drivers/clk/tegra/clk-tegra210.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/clk/tegra/clk-tegra210.c b/drivers/clk/tegra/clk-tegra210.c index 6149573368ef..c1fabd82aa1a 100644 --- a/drivers/clk/tegra/clk-tegra210.c +++ b/drivers/clk/tegra/clk-tegra210.c @@ -1935,8 +1935,9 @@ static struct tegra_clk_pll_params pll_d2_params = { .sdm_din_mask = PLLA_SDM_DIN_MASK, .sdm_ctrl_reg = PLLD2_MISC1, .sdm_ctrl_en_mask = PLLD2_SDM_EN_MASK, - .ssc_ctrl_reg = PLLD2_MISC1, - .ssc_ctrl_en_mask = PLLD2_SSC_EN_MASK, + /* disable spread-spectrum for pll_d2 */ + .ssc_ctrl_reg = 0, + .ssc_ctrl_en_mask = 0, .round_p_to_pdiv = pll_qlin_p_to_pdiv, .pdiv_tohw = pll_qlin_pdiv_to_hw, .div_nmp = &pllss_nmp, -- cgit v1.2.3 From c1273af4b92171731c07acabd004bbb2802d3b44 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Thu, 9 Jun 2016 17:34:51 +0200 Subject: clk: tegra: Squash sor1 safe/brick/src into a single mux The sor1 clock on Tegra210 is structured in the following way: +-------+ | pllp |---+ +-------+ | +--------------+ +-----------+ +----| | | sor_safe | +-------+ | | +-----------+ | plld |--------| | | +-------+ | | +-----------+ | sor1_src |-------| | +-------+ | | +-----------+ | plld2 |--------| | | +-------+ | | | +----| | | +-------+ | +--------------+ | | clkm |---+ +-----------+ +-------+ +--------------+ | | | sor1_brick |-------| sor1 | +--------------+ | | +-----------+ This is impractical to represent in a clock tree, though, because there is no name for the mux that has sor_safe and sor1_src as parents. It is also much more cumbersome to deal with the additional mux because users of these clocks (the display driver) would have to juggle with an extra mux for no real reason. To simply things, the above is squashed into two muxes instead, so that it looks like this: +-------+ | pllp |---+ +-------+ | +--------------+ +-----------+ +----| | | sor_safe | +-------+ | | +-----------+ | plld |--------| | | +-------+ | | +-----------+ | sor1_src |-------| sor1 | +-------+ | | +-----------+ | plld2 |--------| | | | +-------+ | | | | +----| | | | +-------+ | +--------------+ | | | clkm |---+ | | +-------+ +--------------+ | | | sor1_brick |-----------+---+ +--------------+ This still very accurately represents the hardware. Note that sor1 has sor1_brick as input twice, that's because bit 1 in the mux selects the sor1_brick irrespective of bit 0. Signed-off-by: Thierry Reding --- drivers/clk/tegra/clk-id.h | 1 - drivers/clk/tegra/clk-tegra-periph.c | 23 ++++++++++++----------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/clk/tegra/clk-id.h b/drivers/clk/tegra/clk-id.h index 36c974916d4f..5738635c5274 100644 --- a/drivers/clk/tegra/clk-id.h +++ b/drivers/clk/tegra/clk-id.h @@ -238,7 +238,6 @@ enum clk_id { tegra_clk_sor0, tegra_clk_sor0_lvds, tegra_clk_sor1, - tegra_clk_sor1_brick, tegra_clk_sor1_src, tegra_clk_spdif, tegra_clk_spdif_2x, diff --git a/drivers/clk/tegra/clk-tegra-periph.c b/drivers/clk/tegra/clk-tegra-periph.c index 29d04c663abf..af85c8aeaf5a 100644 --- a/drivers/clk/tegra/clk-tegra-periph.c +++ b/drivers/clk/tegra/clk-tegra-periph.c @@ -594,15 +594,17 @@ static u32 mux_pllp_plld_plld2_clkm_idx[] = { [0] = 0, [1] = 2, [2] = 5, [3] = 6 }; -static const char *mux_plldp_sor1_src[] = { - "pll_dp", "clk_sor1_src" -}; -#define mux_plldp_sor1_src_idx NULL - -static const char *mux_clkm_sor1_brick_sor1_src[] = { - "clk_m", "sor1_brick", "sor1_src", "sor1_brick" -}; -#define mux_clkm_sor1_brick_sor1_src_idx NULL +static const char *mux_sor_safe_sor1_brick_sor1_src[] = { + /* + * Bit 0 of the mux selects sor1_brick, irrespective of bit 1, so the + * sor1_brick parent appears twice in the list below. This is merely + * to support clk_get_parent() if firmware happened to set these bits + * to 0b11. While not an invalid setting, code should always set the + * bits to 0b01 to select sor1_brick. + */ + "sor_safe", "sor1_brick", "sor1_src", "sor1_brick" +}; +#define mux_sor_safe_sor1_brick_sor1_src_idx NULL static const char *mux_pllp_pllre_clkm[] = { "pll_p", "pll_re_out1", "clk_m" @@ -778,8 +780,7 @@ static struct tegra_periph_init_data periph_clks[] = { MUX8("nvjpg", mux_pllc2_c_c3_pllp_plla1_clkm, CLK_SOURCE_NVJPG, 195, 0, tegra_clk_nvjpg), MUX8("ape", mux_plla_pllc4_out0_pllc_pllc4_out1_pllp_pllc4_out2_clkm, CLK_SOURCE_APE, 198, TEGRA_PERIPH_ON_APB, tegra_clk_ape), MUX8_NOGATE_LOCK("sor1_src", mux_pllp_plld_plld2_clkm, CLK_SOURCE_SOR1, tegra_clk_sor1_src, &sor1_lock), - NODIV("sor1_brick", mux_plldp_sor1_src, CLK_SOURCE_SOR1, 14, MASK(1), 183, 0, tegra_clk_sor1_brick, &sor1_lock), - NODIV("sor1", mux_clkm_sor1_brick_sor1_src, CLK_SOURCE_SOR1, 15, MASK(1), 183, 0, tegra_clk_sor1, &sor1_lock), + NODIV("sor1", mux_sor_safe_sor1_brick_sor1_src, CLK_SOURCE_SOR1, 14, MASK(2), 183, 0, tegra_clk_sor1, &sor1_lock), MUX8("sdmmc_legacy", mux_pllp_out3_clkm_pllp_pllc4, CLK_SOURCE_SDMMC_LEGACY, 193, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, tegra_clk_sdmmc_legacy), MUX8("qspi", mux_pllp_pllc_pllc_out1_pllc4_out2_pllc4_out1_clkm_pllc4_out0, CLK_SOURCE_QSPI, 211, TEGRA_PERIPH_ON_APB, tegra_clk_qspi), I2C("vii2c", mux_pllp_pllc_clkm, CLK_SOURCE_VI_I2C, 208, tegra_clk_vi_i2c), -- cgit v1.2.3 From e452b818db48dc2c7edb5afd62de47ae0363aec2 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Thu, 9 Jun 2016 17:47:17 +0200 Subject: clk: tegra: Enable sor1 and sor1_src on Tegra210 Make the sor1 and sor1_src clocks available on Tegra210. They will be used by the display driver to support HDMI and DP. Signed-off-by: Thierry Reding --- drivers/clk/tegra/clk-tegra210.c | 2 ++ include/dt-bindings/clock/tegra210-car.h | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/clk/tegra/clk-tegra210.c b/drivers/clk/tegra/clk-tegra210.c index c1fabd82aa1a..aab32af77aa2 100644 --- a/drivers/clk/tegra/clk-tegra210.c +++ b/drivers/clk/tegra/clk-tegra210.c @@ -2155,6 +2155,8 @@ static struct tegra_clk tegra210_clks[tegra_clk_max] __initdata = { [tegra_clk_dpaux1] = { .dt_id = TEGRA210_CLK_DPAUX1, .present = true }, [tegra_clk_sor0] = { .dt_id = TEGRA210_CLK_SOR0, .present = true }, [tegra_clk_sor0_lvds] = { .dt_id = TEGRA210_CLK_SOR0_LVDS, .present = true }, + [tegra_clk_sor1] = { .dt_id = TEGRA210_CLK_SOR1, .present = true }, + [tegra_clk_sor1_src] = { .dt_id = TEGRA210_CLK_SOR1_SRC, .present = true }, [tegra_clk_gpu] = { .dt_id = TEGRA210_CLK_GPU, .present = true }, [tegra_clk_pll_g_ref] = { .dt_id = TEGRA210_CLK_PLL_G_REF, .present = true, }, [tegra_clk_uartb_8] = { .dt_id = TEGRA210_CLK_UARTB, .present = true }, diff --git a/include/dt-bindings/clock/tegra210-car.h b/include/dt-bindings/clock/tegra210-car.h index bd3530e56d46..35288b20f2c9 100644 --- a/include/dt-bindings/clock/tegra210-car.h +++ b/include/dt-bindings/clock/tegra210-car.h @@ -308,7 +308,7 @@ #define TEGRA210_CLK_CLK_OUT_3 279 #define TEGRA210_CLK_BLINK 280 /* 281 */ -/* 282 */ +#define TEGRA210_CLK_SOR1_SRC 282 /* 283 */ #define TEGRA210_CLK_XUSB_HOST_SRC 284 #define TEGRA210_CLK_XUSB_FALCON_SRC 285 -- cgit v1.2.3 From 25f77a3aa4cb948666bf8e7fd972533ea487c3bd Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 16 May 2016 14:47:02 +0200 Subject: clk: multiplier: Prevent the multiplier from under / over flowing In the current multiplier base clock implementation, if the CLK_SET_RATE_PARENT flag isn't set, the code will not make sure that the multiplier computed remains within the boundaries of our clock. This means that if the clock we want to reach is below the parent rate, or if the multiplier is above the maximum that we can reach, we will end up with a completely bogus one that the clock cannot achieve. Fixes: f2e0a53271a4 ("clk: Add a basic multiplier clock") Signed-off-by: Maxime Ripard Signed-off-by: Michael Turquette Link: lkml.kernel.org/r/1463402840-17062-3-git-send-email-maxime.ripard@free-electrons.com --- drivers/clk/clk-multiplier.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/drivers/clk/clk-multiplier.c b/drivers/clk/clk-multiplier.c index 9e449c7b751c..dc037c957acd 100644 --- a/drivers/clk/clk-multiplier.c +++ b/drivers/clk/clk-multiplier.c @@ -52,14 +52,28 @@ static unsigned long __bestmult(struct clk_hw *hw, unsigned long rate, unsigned long *best_parent_rate, u8 width, unsigned long flags) { + struct clk_multiplier *mult = to_clk_multiplier(hw); unsigned long orig_parent_rate = *best_parent_rate; unsigned long parent_rate, current_rate, best_rate = ~0; unsigned int i, bestmult = 0; + unsigned int maxmult = (1 << width) - 1; + + if (!(clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT)) { + bestmult = rate / orig_parent_rate; + + /* Make sure we don't end up with a 0 multiplier */ + if ((bestmult == 0) && + !(mult->flags & CLK_MULTIPLIER_ZERO_BYPASS)) + bestmult = 1; - if (!(clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT)) - return rate / *best_parent_rate; + /* Make sure we don't overflow the multiplier */ + if (bestmult > maxmult) + bestmult = maxmult; + + return bestmult; + } - for (i = 1; i < ((1 << width) - 1); i++) { + for (i = 1; i < maxmult; i++) { if (rate == orig_parent_rate * i) { /* * This is the best case for us if we have a -- cgit v1.2.3 From 14755549c7db6e26d04b208047f44538aa325802 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Tue, 7 Jun 2016 17:38:09 +0100 Subject: clk: at91: make of_sama5d2_clk_generated_setup() static The of_sama5d2_clk_generated_setup() is not exported outside of the driver, so make it static to fix the warning about it being not static: drivers/clk/at91/clk-generated.c:270:13: warning: symbol 'of_sama5d2_clk_generated_setup' was not declared. Should it be static? Signed-off-by: Ben Dooks Acked-by: Boris Brezillon Signed-off-by: Stephen Boyd --- drivers/clk/at91/clk-generated.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/at91/clk-generated.c b/drivers/clk/at91/clk-generated.c index e1aa210dd7aa..7f6bec8837ea 100644 --- a/drivers/clk/at91/clk-generated.c +++ b/drivers/clk/at91/clk-generated.c @@ -267,7 +267,7 @@ at91_clk_register_generated(struct regmap *regmap, spinlock_t *lock, const char return clk; } -void __init of_sama5d2_clk_generated_setup(struct device_node *np) +static void __init of_sama5d2_clk_generated_setup(struct device_node *np) { int num; u32 id; -- cgit v1.2.3 From c895db85f7d8d3a5a5ba38a79592c0962a72c41b Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Tue, 7 Jun 2016 17:32:30 +0100 Subject: clk: iproc: fix missing include of clk-iproc.h Fix the implicit declaration of iproc_armpll_setup() by including clk-iproc.h which defines it. Fixes the warning: drivers/clk/bcm/clk-iproc-armpll.c:242:13: warning: symbol 'iproc_armpll_setup' was not declared. Should it be static? Signed-off-by: Ben Dooks Acked-by: Ray Jui Signed-off-by: Stephen Boyd --- drivers/clk/bcm/clk-iproc-armpll.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/clk/bcm/clk-iproc-armpll.c b/drivers/clk/bcm/clk-iproc-armpll.c index a196ee28a17a..698c507921f1 100644 --- a/drivers/clk/bcm/clk-iproc-armpll.c +++ b/drivers/clk/bcm/clk-iproc-armpll.c @@ -20,6 +20,8 @@ #include #include +#include "clk-iproc.h" + #define IPROC_CLK_MAX_FREQ_POLICY 0x3 #define IPROC_CLK_POLICY_FREQ_OFFSET 0x008 #define IPROC_CLK_POLICY_FREQ_POLICY_FREQ_SHIFT 8 -- cgit v1.2.3 From b62c190f80342f76e3d1e9ebbe16f580a21cc64b Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Tue, 7 Jun 2016 14:54:08 +0100 Subject: clk: hi6220: fix missing clk.h include Fix the warning from missing "clk.h" include which defines hi6220_register_clkdiv() function. drivers/clk/hisilicon/clkdivider-hi6220.c:102:12: warning: symbol 'hi6220_register_clkdiv' was not declared. Should it be static? Signed-off-by: Ben Dooks Signed-off-by: Stephen Boyd --- drivers/clk/hisilicon/clkdivider-hi6220.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/clk/hisilicon/clkdivider-hi6220.c b/drivers/clk/hisilicon/clkdivider-hi6220.c index 113eee8ed23a..a1c1f684ad58 100644 --- a/drivers/clk/hisilicon/clkdivider-hi6220.c +++ b/drivers/clk/hisilicon/clkdivider-hi6220.c @@ -18,6 +18,8 @@ #include #include +#include "clk.h" + #define div_mask(width) ((1 << (width)) - 1) /** -- cgit v1.2.3 From 06b37e4a6ef2d392f3f35c94a9fe5d43f09f36c7 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Tue, 7 Jun 2016 13:25:02 +0100 Subject: clk: Remove unused variable Signed-off-by: Lee Jones Signed-off-by: Stephen Boyd --- drivers/clk/clk.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 874c7dd8ef66..df844a60fdf9 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -1501,7 +1501,6 @@ static int clk_core_set_rate_nolock(struct clk_core *core, { struct clk_core *top, *fail_clk; unsigned long rate = req_rate; - int ret = 0; if (!core) return 0; @@ -1532,7 +1531,7 @@ static int clk_core_set_rate_nolock(struct clk_core *core, core->req_rate = req_rate; - return ret; + return 0; } /** -- cgit v1.2.3 From 27a0becc26ba7f84babda8c66170827af1fa308d Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 8 Jun 2016 00:56:09 +0300 Subject: clk: vt8500: fix gcc-4.9 warnings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes some false positive warnings we get with older compiler versions: clk-vt8500.c: In function ‘wm8650_find_pll_bits’: clk-vt8500.c:430:12: ‘best_div2’ may be used uninitialized in this function clk-vt8500.c:429:12: ‘best_div1’ may be used uninitialized in this function clk-vt8500.c:428:14: ‘best_mul’ may be used uninitialized in this function clk-vt8500.c: In function ‘wm8750_find_pll_bits’: clk-vt8500.c:509:12: ‘best_div2’ may be used uninitialized in this function clk-vt8500.c:508:12: ‘best_div1’ may be used uninitialized in this function clk-vt8500.c:507:14: ‘best_mul’ may be used uninitialized in this function clk-vt8500.c: In function ‘wm8850_find_pll_bits’: clk-vt8500.c:560:12: ‘best_div2’ may be used uninitialized in this function clk-vt8500.c:559:12: ‘best_div1’ may be used uninitialized in this function clk-vt8500.c:558:14: ‘best_mul’ may be used uninitialized in this function As the local variables are only use for temporaries, we can just as well assign the final values directly, which also makes the code slightly shorter. Signed-off-by: Arnd Bergmann Signed-off-by: Roman Volkov Signed-off-by: Stephen Boyd --- drivers/clk/clk-vt8500.c | 34 ++++++++++------------------------ 1 file changed, 10 insertions(+), 24 deletions(-) diff --git a/drivers/clk/clk-vt8500.c b/drivers/clk/clk-vt8500.c index b0f76a84f1e9..d5a3453970d0 100644 --- a/drivers/clk/clk-vt8500.c +++ b/drivers/clk/clk-vt8500.c @@ -388,7 +388,6 @@ static int wm8650_find_pll_bits(unsigned long rate, unsigned long parent_rate, { u32 mul, div1; int div2; - u32 best_mul, best_div1, best_div2; unsigned long tclk, rate_err, best_err; best_err = (unsigned long)-1; @@ -411,9 +410,9 @@ static int wm8650_find_pll_bits(unsigned long rate, unsigned long parent_rate, if (rate_err < best_err) { best_err = rate_err; - best_mul = mul; - best_div1 = div1; - best_div2 = div2; + *multiplier = mul; + *divisor1 = div1; + *divisor2 = div2; } } @@ -425,10 +424,6 @@ static int wm8650_find_pll_bits(unsigned long rate, unsigned long parent_rate, /* if we got here, it wasn't an exact match */ pr_warn("%s: requested rate %lu, found rate %lu\n", __func__, rate, rate - best_err); - *multiplier = best_mul; - *divisor1 = best_div1; - *divisor2 = best_div2; - return 0; } @@ -464,7 +459,6 @@ static int wm8750_find_pll_bits(unsigned long rate, unsigned long parent_rate, { u32 mul; int div1, div2; - u32 best_mul, best_div1, best_div2; unsigned long tclk, rate_err, best_err; best_err = (unsigned long)-1; @@ -488,9 +482,9 @@ static int wm8750_find_pll_bits(unsigned long rate, unsigned long parent_rate, if (rate_err < best_err) { best_err = rate_err; - best_mul = mul; - best_div1 = div1; - best_div2 = div2; + *multiplier = mul; + *divisor1 = div1; + *divisor2 = div2; } } @@ -503,10 +497,7 @@ static int wm8750_find_pll_bits(unsigned long rate, unsigned long parent_rate, pr_warn("%s: requested rate %lu, found rate %lu\n", __func__, rate, rate - best_err); - *filter = wm8750_get_filter(parent_rate, best_div1); - *multiplier = best_mul; - *divisor1 = best_div1; - *divisor2 = best_div2; + *filter = wm8750_get_filter(parent_rate, *divisor1); return 0; } @@ -516,7 +507,6 @@ static int wm8850_find_pll_bits(unsigned long rate, unsigned long parent_rate, { u32 mul; int div1, div2; - u32 best_mul, best_div1, best_div2; unsigned long tclk, rate_err, best_err; best_err = (unsigned long)-1; @@ -540,9 +530,9 @@ static int wm8850_find_pll_bits(unsigned long rate, unsigned long parent_rate, if (rate_err < best_err) { best_err = rate_err; - best_mul = mul; - best_div1 = div1; - best_div2 = div2; + *multiplier = mul; + *divisor1 = div1; + *divisor2 = div2; } } @@ -555,10 +545,6 @@ static int wm8850_find_pll_bits(unsigned long rate, unsigned long parent_rate, pr_warn("%s: requested rate %lu, found rate %lu\n", __func__, rate, rate - best_err); - *multiplier = best_mul; - *divisor1 = best_div1; - *divisor2 = best_div2; - return 0; } -- cgit v1.2.3 From c03d795beee49ed6e96cf3832c083bf2ecaf1408 Mon Sep 17 00:00:00 2001 From: Roman Volkov Date: Wed, 8 Jun 2016 00:56:10 +0300 Subject: clk: vt8500: rework wm8650_find_pll_bits() PLL clock on WM8650 is calculated in the following way: M * parent [O1] => / P [O2] => / D [O3] Where O2 is 600MHz >= (M * parent) / P >= 300MHz. Current algorithm does not met this requirement, so that the function may return rates which are not supported by the hardware. This patch fixes the algorithm and simplifies the code, reducing the calculation time by ~10000 times (according to usermode app) by removing the nested loops. Signed-off-by: Roman Volkov Signed-off-by: Stephen Boyd --- drivers/clk/clk-vt8500.c | 73 +++++++++++++++++++++++++----------------------- 1 file changed, 38 insertions(+), 35 deletions(-) diff --git a/drivers/clk/clk-vt8500.c b/drivers/clk/clk-vt8500.c index d5a3453970d0..37368a399ff9 100644 --- a/drivers/clk/clk-vt8500.c +++ b/drivers/clk/clk-vt8500.c @@ -383,47 +383,50 @@ static int vt8500_find_pll_bits(unsigned long rate, unsigned long parent_rate, return 0; } -static int wm8650_find_pll_bits(unsigned long rate, unsigned long parent_rate, - u32 *multiplier, u32 *divisor1, u32 *divisor2) +/* + * M * parent [O1] => / P [O2] => / D [O3] + * Where O1 is 900MHz...3GHz; + * O2 is 600MHz >= (M * parent) / P >= 300MHz; + * M is 36...120 [25MHz parent]; D is 1 or 2 or 4 or 8. + * Possible ranges (O3): + * D = 8: 37,5MHz...75MHz + * D = 4: 75MHz...150MHz + * D = 2: 150MHz...300MHz + * D = 1: 300MHz...600MHz + */ +static int wm8650_find_pll_bits(unsigned long rate, + unsigned long parent_rate, u32 *multiplier, u32 *divisor1, + u32 *divisor2) { - u32 mul, div1; - int div2; - unsigned long tclk, rate_err, best_err; - - best_err = (unsigned long)-1; + unsigned long O1, min_err, rate_err; - /* Find the closest match (lower or equal to requested) */ - for (div1 = 5; div1 >= 3; div1--) - for (div2 = 3; div2 >= 0; div2--) - for (mul = 3; mul <= 1023; mul++) { - tclk = parent_rate * mul / (div1 * (1 << div2)); - if (tclk > rate) - continue; - /* error will always be +ve */ - rate_err = rate - tclk; - if (rate_err == 0) { - *multiplier = mul; - *divisor1 = div1; - *divisor2 = div2; - return 0; - } + if (!parent_rate || (rate < 37500000) || (rate > 600000000)) + return -EINVAL; - if (rate_err < best_err) { - best_err = rate_err; - *multiplier = mul; - *divisor1 = div1; - *divisor2 = div2; - } - } + *divisor2 = rate <= 75000000 ? 3 : rate <= 150000000 ? 2 : + rate <= 300000000 ? 1 : 0; + /* + * Divisor P cannot be calculated. Test all divisors and find where M + * will be as close as possible to the requested rate. + */ + min_err = ULONG_MAX; + for (*divisor1 = 5; *divisor1 >= 3; (*divisor1)--) { + O1 = rate * *divisor1 * (1 << (*divisor2)); + rate_err = O1 % parent_rate; + if (rate_err < min_err) { + *multiplier = O1 / parent_rate; + if (rate_err == 0) + return 0; + + min_err = rate_err; + } + } - if (best_err == (unsigned long)-1) { - pr_warn("%s: impossible rate %lu\n", __func__, rate); + if ((*multiplier < 3) || (*multiplier > 1023)) return -EINVAL; - } - /* if we got here, it wasn't an exact match */ - pr_warn("%s: requested rate %lu, found rate %lu\n", __func__, rate, - rate - best_err); + pr_warn("%s: rate error is %lu\n", __func__, min_err); + return 0; } -- cgit v1.2.3 From 2d5b520cfec56fa7fa09bd08c98d7f49a05aedd9 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Mon, 13 Jun 2016 19:34:21 +0800 Subject: clk: correct comments for __clk_determine_rate Correct comments for __clk_determine_rate. Signed-off-by: Peng Fan Cc: Michael Turquette Cc: Stephen Boyd Signed-off-by: Stephen Boyd --- drivers/clk/clk.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index df844a60fdf9..95b80aeb8c9d 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -828,9 +828,7 @@ static int clk_core_round_rate_nolock(struct clk_core *core, /** * __clk_determine_rate - get the closest rate actually supported by a clock * @hw: determine the rate of this clock - * @rate: target rate - * @min_rate: returned rate must be greater than this rate - * @max_rate: returned rate must be less than this rate + * @req: target rate request * * Useful for clk_ops such as .set_rate and .determine_rate. */ -- cgit v1.2.3 From 13445de6e71ad219f8fce8736c45f57bb3b85571 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Fri, 3 Jun 2016 23:58:03 +0300 Subject: clk: renesas: rcar-gen2: Document R8A7792 support Renesas R8A7792 SoC is a member of the R-Car gen2 family and so has CPG... Signed-off-by: Sergei Shtylyov Acked-by: Simon Horman Acked-by: Rob Herring Signed-off-by: Geert Uytterhoeven --- Documentation/devicetree/bindings/clock/renesas,rcar-gen2-cpg-clocks.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/clock/renesas,rcar-gen2-cpg-clocks.txt b/Documentation/devicetree/bindings/clock/renesas,rcar-gen2-cpg-clocks.txt index 2a9a8edc8f35..f8c05bb4116e 100644 --- a/Documentation/devicetree/bindings/clock/renesas,rcar-gen2-cpg-clocks.txt +++ b/Documentation/devicetree/bindings/clock/renesas,rcar-gen2-cpg-clocks.txt @@ -10,6 +10,7 @@ Required Properties: - compatible: Must be one of - "renesas,r8a7790-cpg-clocks" for the r8a7790 CPG - "renesas,r8a7791-cpg-clocks" for the r8a7791 CPG + - "renesas,r8a7792-cpg-clocks" for the r8a7792 CPG - "renesas,r8a7793-cpg-clocks" for the r8a7793 CPG - "renesas,r8a7794-cpg-clocks" for the r8a7794 CPG and "renesas,rcar-gen2-cpg-clocks" as a fallback. -- cgit v1.2.3 From ef71b1eaa0e09a082027f15f9e040a6f636ce874 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Fri, 3 Jun 2016 23:59:07 +0300 Subject: clk: renesas: mstp: Document R8A7792 support Renesas R8A7792 SoC also has the CPG MSTP clocks... Signed-off-by: Sergei Shtylyov Acked-by: Simon Horman Acked-by: Rob Herring Signed-off-by: Geert Uytterhoeven --- Documentation/devicetree/bindings/clock/renesas,cpg-mstp-clocks.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/clock/renesas,cpg-mstp-clocks.txt b/Documentation/devicetree/bindings/clock/renesas,cpg-mstp-clocks.txt index 16ed18155160..da578ebdda28 100644 --- a/Documentation/devicetree/bindings/clock/renesas,cpg-mstp-clocks.txt +++ b/Documentation/devicetree/bindings/clock/renesas,cpg-mstp-clocks.txt @@ -17,6 +17,7 @@ Required Properties: - "renesas,r8a7779-mstp-clocks" for R8A7779 (R-Car H1) MSTP gate clocks - "renesas,r8a7790-mstp-clocks" for R8A7790 (R-Car H2) MSTP gate clocks - "renesas,r8a7791-mstp-clocks" for R8A7791 (R-Car M2-W) MSTP gate clocks + - "renesas,r8a7792-mstp-clocks" for R8A7792 (R-Car V2H) MSTP gate clocks - "renesas,r8a7793-mstp-clocks" for R8A7793 (R-Car M2-N) MSTP gate clocks - "renesas,r8a7794-mstp-clocks" for R8A7794 (R-Car E2) MSTP gate clocks - "renesas,sh73a0-mstp-clocks" for SH73A0 (SH-MobileAG5) MSTP gate clocks -- cgit v1.2.3 From a233bffb6b5ad90a7e01a9c9b14b036d156eb0dd Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Thu, 26 May 2016 00:40:44 +0300 Subject: clk: renesas: Add R8A7792 support Renesas R-Car V2H (R8A7792) clocks are handled by R-Car gen2 clock driver. Signed-off-by: Sergei Shtylyov Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/Kconfig | 1 + drivers/clk/renesas/Makefile | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/clk/renesas/Kconfig b/drivers/clk/renesas/Kconfig index fcad9ff090f5..41a12d376799 100644 --- a/drivers/clk/renesas/Kconfig +++ b/drivers/clk/renesas/Kconfig @@ -12,6 +12,7 @@ config CLK_RENESAS_CPG_MSTP default y if ARCH_R8A7779 default y if ARCH_R8A7790 default y if ARCH_R8A7791 + default y if ARCH_R8A7792 default y if ARCH_R8A7793 default y if ARCH_R8A7794 default y if ARCH_SH73A0 diff --git a/drivers/clk/renesas/Makefile b/drivers/clk/renesas/Makefile index 0b8d31b4909c..90dd0db7d9c6 100644 --- a/drivers/clk/renesas/Makefile +++ b/drivers/clk/renesas/Makefile @@ -6,6 +6,7 @@ obj-$(CONFIG_ARCH_R8A7778) += clk-r8a7778.o obj-$(CONFIG_ARCH_R8A7779) += clk-r8a7779.o obj-$(CONFIG_ARCH_R8A7790) += clk-rcar-gen2.o clk-div6.o obj-$(CONFIG_ARCH_R8A7791) += clk-rcar-gen2.o clk-div6.o +obj-$(CONFIG_ARCH_R8A7792) += clk-rcar-gen2.o clk-div6.o obj-$(CONFIG_ARCH_R8A7793) += clk-rcar-gen2.o clk-div6.o obj-$(CONFIG_ARCH_R8A7794) += clk-rcar-gen2.o clk-div6.o obj-$(CONFIG_ARCH_R8A7795) += r8a7795-cpg-mssr.o rcar-gen3-cpg.o -- cgit v1.2.3 From a20956804220951196671ed5455d085927d6a754 Mon Sep 17 00:00:00 2001 From: Kieran Bingham Date: Thu, 9 Jun 2016 17:12:26 +0100 Subject: clk: renesas: r8a7795: Provide FDP1 clocks Reviewed-by: Laurent Pinchart Signed-off-by: Kieran Bingham Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/r8a7795-cpg-mssr.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/clk/renesas/r8a7795-cpg-mssr.c b/drivers/clk/renesas/r8a7795-cpg-mssr.c index e53aff5b23ad..8f76af6f454d 100644 --- a/drivers/clk/renesas/r8a7795-cpg-mssr.c +++ b/drivers/clk/renesas/r8a7795-cpg-mssr.c @@ -107,6 +107,9 @@ static const struct cpg_core_clk r8a7795_core_clks[] __initconst = { }; static const struct mssr_mod_clk r8a7795_mod_clks[] __initconst = { + DEF_MOD("fdp1-2", 117, R8A7795_CLK_S2D1), + DEF_MOD("fdp1-1", 118, R8A7795_CLK_S2D1), + DEF_MOD("fdp1-0", 119, R8A7795_CLK_S2D1), DEF_MOD("scif5", 202, R8A7795_CLK_S3D4), DEF_MOD("scif4", 203, R8A7795_CLK_S3D4), DEF_MOD("scif3", 204, R8A7795_CLK_S3D4), -- cgit v1.2.3 From f7bb887fb898307dd575179303b710d933f242ea Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 10 Jun 2016 09:36:44 +0200 Subject: clk: renesas: r8a7795: Correct lvds clock parent According to the latest information, the parent clock of the LVDS module clock is the S0D4 clock, not the S2D1 clock. Note that this change has no influence on actual operation, as the rcar-du LVDS encoder driver doesn't use the parent clock's rate. Signed-off-by: Geert Uytterhoeven Reviewed-by: Laurent Pinchart --- drivers/clk/renesas/r8a7795-cpg-mssr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/renesas/r8a7795-cpg-mssr.c b/drivers/clk/renesas/r8a7795-cpg-mssr.c index 8f76af6f454d..ad01b0b1bc5f 100644 --- a/drivers/clk/renesas/r8a7795-cpg-mssr.c +++ b/drivers/clk/renesas/r8a7795-cpg-mssr.c @@ -180,7 +180,7 @@ static const struct mssr_mod_clk r8a7795_mod_clks[] __initconst = { DEF_MOD("du2", 722, R8A7795_CLK_S2D1), DEF_MOD("du1", 723, R8A7795_CLK_S2D1), DEF_MOD("du0", 724, R8A7795_CLK_S2D1), - DEF_MOD("lvds", 727, R8A7795_CLK_S2D1), + DEF_MOD("lvds", 727, R8A7795_CLK_S0D4), DEF_MOD("hdmi1", 728, R8A7795_CLK_HDMI), DEF_MOD("hdmi0", 729, R8A7795_CLK_HDMI), DEF_MOD("vin7", 804, R8A7795_CLK_S2D1), -- cgit v1.2.3 From 7d6cc0cddbc2f1953b2ff6f5930a065e40b94507 Mon Sep 17 00:00:00 2001 From: Ramesh Shanmugasundaram Date: Fri, 17 Jun 2016 13:25:14 +0100 Subject: clk: renesas: r8a7795: Add DRIF clock This patch adds DRIF module clocks for r8a7795 SoC. Signed-off-by: Ramesh Shanmugasundaram Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/r8a7795-cpg-mssr.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/clk/renesas/r8a7795-cpg-mssr.c b/drivers/clk/renesas/r8a7795-cpg-mssr.c index ad01b0b1bc5f..b9485ab891a0 100644 --- a/drivers/clk/renesas/r8a7795-cpg-mssr.c +++ b/drivers/clk/renesas/r8a7795-cpg-mssr.c @@ -138,6 +138,14 @@ static const struct mssr_mod_clk r8a7795_mod_clks[] __initconst = { DEF_MOD("intc-ap", 408, R8A7795_CLK_S3D1), DEF_MOD("audmac0", 502, R8A7795_CLK_S3D4), DEF_MOD("audmac1", 501, R8A7795_CLK_S3D4), + DEF_MOD("drif7", 508, R8A7795_CLK_S3D2), + DEF_MOD("drif6", 509, R8A7795_CLK_S3D2), + DEF_MOD("drif5", 510, R8A7795_CLK_S3D2), + DEF_MOD("drif4", 511, R8A7795_CLK_S3D2), + DEF_MOD("drif3", 512, R8A7795_CLK_S3D2), + DEF_MOD("drif2", 513, R8A7795_CLK_S3D2), + DEF_MOD("drif1", 514, R8A7795_CLK_S3D2), + DEF_MOD("drif0", 515, R8A7795_CLK_S3D2), DEF_MOD("hscif4", 516, R8A7795_CLK_S3D1), DEF_MOD("hscif3", 517, R8A7795_CLK_S3D1), DEF_MOD("hscif2", 518, R8A7795_CLK_S3D1), -- cgit v1.2.3 From e4c82863fd17bacb60080481c11eb0303d3f83d0 Mon Sep 17 00:00:00 2001 From: Khiem Nguyen Date: Sun, 19 Jun 2016 09:34:18 +0700 Subject: clk: renesas: r8a7795: Add THS/TSC clock Signed-off-by: Khiem Nguyen Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/r8a7795-cpg-mssr.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/clk/renesas/r8a7795-cpg-mssr.c b/drivers/clk/renesas/r8a7795-cpg-mssr.c index b9485ab891a0..d359c92e13a6 100644 --- a/drivers/clk/renesas/r8a7795-cpg-mssr.c +++ b/drivers/clk/renesas/r8a7795-cpg-mssr.c @@ -151,6 +151,7 @@ static const struct mssr_mod_clk r8a7795_mod_clks[] __initconst = { DEF_MOD("hscif2", 518, R8A7795_CLK_S3D1), DEF_MOD("hscif1", 519, R8A7795_CLK_S3D1), DEF_MOD("hscif0", 520, R8A7795_CLK_S3D1), + DEF_MOD("thermal", 522, R8A7795_CLK_CP), DEF_MOD("pwm", 523, R8A7795_CLK_S3D4), DEF_MOD("fcpvd3", 600, R8A7795_CLK_S2D1), DEF_MOD("fcpvd2", 601, R8A7795_CLK_S2D1), -- cgit v1.2.3 From 5f6d71044f4d766c3636b9fd2c43e7c9d71d31af Mon Sep 17 00:00:00 2001 From: Xing Zheng Date: Tue, 21 Jun 2016 12:53:29 +0800 Subject: clk: rockchip: add clock-ids for rk3228 audio clocks This patch exports related i2s/spdif clocks for dts reference. Signed-off-by: Xing Zheng Signed-off-by: Heiko Stuebner --- include/dt-bindings/clock/rk3228-cru.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/dt-bindings/clock/rk3228-cru.h b/include/dt-bindings/clock/rk3228-cru.h index 5d43ed9b05ad..c992f3e50e25 100644 --- a/include/dt-bindings/clock/rk3228-cru.h +++ b/include/dt-bindings/clock/rk3228-cru.h @@ -84,6 +84,10 @@ #define PCLK_HDMI_PHY 365 /* hclk gates */ +#define HCLK_I2S0_8CH 442 +#define HCLK_I2S1_8CH 443 +#define HCLK_I2S2_2CH 444 +#define HCLK_SPDIF_8CH 445 #define HCLK_VOP 452 #define HCLK_NANDC 453 #define HCLK_SDMMC 456 -- cgit v1.2.3 From 9ff59360b863706b50cbcd7ffad9287d67254063 Mon Sep 17 00:00:00 2001 From: Xing Zheng Date: Tue, 21 Jun 2016 12:59:47 +0800 Subject: clk: rockchip: add clock-ids for rk3228 MAC clocks This patch exports related MAC clocks for dts reference. Signed-off-by: Xing Zheng Signed-off-by: Heiko Stuebner --- include/dt-bindings/clock/rk3228-cru.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/include/dt-bindings/clock/rk3228-cru.h b/include/dt-bindings/clock/rk3228-cru.h index c992f3e50e25..b27e2b1a65e3 100644 --- a/include/dt-bindings/clock/rk3228-cru.h +++ b/include/dt-bindings/clock/rk3228-cru.h @@ -52,6 +52,15 @@ #define SCLK_EMMC_SAMPLE 121 #define SCLK_VOP 122 #define SCLK_HDMI_HDCP 123 +#define SCLK_MAC_SRC 124 +#define SCLK_MAC_EXTCLK 125 +#define SCLK_MAC 126 +#define SCLK_MAC_REFOUT 127 +#define SCLK_MAC_REF 128 +#define SCLK_MAC_RX 129 +#define SCLK_MAC_TX 130 +#define SCLK_MAC_PHY 131 +#define SCLK_MAC_OUT 132 /* dclk gates */ #define DCLK_VOP 190 @@ -61,6 +70,7 @@ #define ACLK_DMAC 194 #define ACLK_PERI 210 #define ACLK_VOP 211 +#define ACLK_GMAC 212 /* pclk gates */ #define PCLK_GPIO0 320 @@ -82,6 +92,7 @@ #define PCLK_PERI 363 #define PCLK_HDMI_CTRL 364 #define PCLK_HDMI_PHY 365 +#define PCLK_GMAC 367 /* hclk gates */ #define HCLK_I2S0_8CH 442 -- cgit v1.2.3 From 67de7901c441f7516d3ca967fa64533556cae4e7 Mon Sep 17 00:00:00 2001 From: Xing Zheng Date: Tue, 21 Jun 2016 12:53:27 +0800 Subject: clk: rockchip: fix incorrect rk3228 clock registers Due to copy and paste carelessly, RK3288_CLKxxx references are incorrect, we need to fix them. Signed-off-by: Xing Zheng Signed-off-by: Heiko Stuebner --- drivers/clk/rockchip/clk-rk3228.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/clk/rockchip/clk-rk3228.c b/drivers/clk/rockchip/clk-rk3228.c index 016bdb0b793a..62c68346f3d7 100644 --- a/drivers/clk/rockchip/clk-rk3228.c +++ b/drivers/clk/rockchip/clk-rk3228.c @@ -335,7 +335,7 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = { RK2928_CLKGATE_CON(2), 6, GFLAGS), GATE(0, "sclk_hsadc", "ext_hsadc", 0, - RK3288_CLKGATE_CON(10), 12, GFLAGS), + RK2928_CLKGATE_CON(10), 12, GFLAGS), COMPOSITE(0, "sclk_wifi", mux_pll_src_cpll_gpll_usb480m_p, 0, RK2928_CLKSEL_CON(23), 5, 2, MFLAGS, 0, 6, DFLAGS, @@ -380,8 +380,8 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = { RK2928_CLKSEL_CON(9), 15, 1, MFLAGS, 0, 7, DFLAGS, RK2928_CLKGATE_CON(0), 3, GFLAGS), COMPOSITE_FRAC(0, "i2s0_frac", "i2s0_src", CLK_SET_RATE_PARENT, - RK3288_CLKSEL_CON(8), 0, - RK3288_CLKGATE_CON(0), 4, GFLAGS), + RK2928_CLKSEL_CON(8), 0, + RK2928_CLKGATE_CON(0), 4, GFLAGS), COMPOSITE_NODIV(SCLK_I2S0, "sclk_i2s0", mux_i2s0_p, 0, RK2928_CLKSEL_CON(9), 8, 2, MFLAGS, RK2928_CLKGATE_CON(0), 5, GFLAGS), @@ -390,8 +390,8 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = { RK2928_CLKSEL_CON(3), 15, 1, MFLAGS, 0, 7, DFLAGS, RK2928_CLKGATE_CON(0), 10, GFLAGS), COMPOSITE_FRAC(0, "i2s1_frac", "i2s1_src", CLK_SET_RATE_PARENT, - RK3288_CLKSEL_CON(7), 0, - RK3288_CLKGATE_CON(0), 11, GFLAGS), + RK2928_CLKSEL_CON(7), 0, + RK2928_CLKGATE_CON(0), 11, GFLAGS), MUX(0, "i2s1_pre", mux_i2s1_pre_p, 0, RK2928_CLKSEL_CON(3), 8, 2, MFLAGS), GATE(SCLK_I2S1, "sclk_i2s1", "i2s1_pre", 0, @@ -404,8 +404,8 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = { RK2928_CLKSEL_CON(16), 15, 1, MFLAGS, 0, 7, DFLAGS, RK2928_CLKGATE_CON(0), 7, GFLAGS), COMPOSITE_FRAC(0, "i2s2_frac", "i2s2_src", CLK_SET_RATE_PARENT, - RK3288_CLKSEL_CON(30), 0, - RK3288_CLKGATE_CON(0), 8, GFLAGS), + RK2928_CLKSEL_CON(30), 0, + RK2928_CLKGATE_CON(0), 8, GFLAGS), COMPOSITE_NODIV(SCLK_I2S2, "sclk_i2s2", mux_i2s2_p, 0, RK2928_CLKSEL_CON(16), 8, 2, MFLAGS, RK2928_CLKGATE_CON(0), 9, GFLAGS), @@ -414,8 +414,8 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = { RK2928_CLKSEL_CON(6), 15, 1, MFLAGS, 0, 7, DFLAGS, RK2928_CLKGATE_CON(2), 10, GFLAGS), COMPOSITE_FRAC(0, "spdif_frac", "sclk_spdif_src", CLK_SET_RATE_PARENT, - RK3288_CLKSEL_CON(20), 0, - RK3288_CLKGATE_CON(2), 12, GFLAGS), + RK2928_CLKSEL_CON(20), 0, + RK2928_CLKGATE_CON(2), 12, GFLAGS), MUX(SCLK_SPDIF, "sclk_spdif", mux_sclk_spdif_p, 0, RK2928_CLKSEL_CON(6), 8, 2, MFLAGS), -- cgit v1.2.3 From 2858038696b9672ef50cd38904fec510bc814584 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Tue, 21 Jun 2016 17:30:35 +0200 Subject: clk: tegra: Mark timer clock as critical The timer clock feeds the timer block, which, among other things, is used to drive the SOR lane sequencer. Since the Tegra timer driver is not enabled on 64-bit ARM, nothing currently claims that clock and it gets disabled by the common clock framework at late_init time. Given the non-obvious dependencies, the timer clock can be considered a critical part of the SoC infrastructure, requiring its clock source to be always on. Acked-by: Rhyland Klein Acked-by: Peter De Schrijver Signed-off-by: Thierry Reding --- drivers/clk/tegra/clk-tegra-periph.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/tegra/clk-tegra-periph.c b/drivers/clk/tegra/clk-tegra-periph.c index af85c8aeaf5a..4ce4e7fb1124 100644 --- a/drivers/clk/tegra/clk-tegra-periph.c +++ b/drivers/clk/tegra/clk-tegra-periph.c @@ -792,7 +792,7 @@ static struct tegra_periph_init_data periph_clks[] = { static struct tegra_periph_init_data gate_clks[] = { GATE("rtc", "clk_32k", 4, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, tegra_clk_rtc, 0), - GATE("timer", "clk_m", 5, 0, tegra_clk_timer, 0), + GATE("timer", "clk_m", 5, 0, tegra_clk_timer, CLK_IS_CRITICAL), GATE("isp", "clk_m", 23, 0, tegra_clk_isp, 0), GATE("vcp", "clk_m", 29, 0, tegra_clk_vcp, 0), GATE("apbdma", "clk_m", 34, 0, tegra_clk_apbdma, 0), -- cgit v1.2.3 From 89ef4b6217566f3429a577b84fc67b3a6463e26c Mon Sep 17 00:00:00 2001 From: Michael Turquette Date: Thu, 28 Apr 2016 17:18:52 -0700 Subject: clk: meson8b: rectify reg offsets with datasheet The register offsets in the data sheet are confusing. Document them more thoroughly. Tested-by: Kevin Hilman Signed-off-by: Michael Turquette --- drivers/clk/meson/meson8b-clkc.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/drivers/clk/meson/meson8b-clkc.c b/drivers/clk/meson/meson8b-clkc.c index 4d057b3e21b2..444ef9414797 100644 --- a/drivers/clk/meson/meson8b-clkc.c +++ b/drivers/clk/meson/meson8b-clkc.c @@ -24,10 +24,19 @@ #include "clkc.h" +/* + * Clock controller register offsets + * + * Register offsets from the HardKernel[0] data sheet are listed in comment + * blocks below. Those offsets must be multiplied by 4 before adding them to + * the base address to get the right value + * + * [0] http://dn.odroid.com/S805/Datasheet/S805_Datasheet%20V0.8%2020150126.pdf + */ #define MESON8B_REG_CTL0_ADDR 0x0000 -#define MESON8B_REG_SYS_CPU_CNTL1 0x015c -#define MESON8B_REG_HHI_MPEG 0x0174 -#define MESON8B_REG_MALI 0x01b0 +#define MESON8B_REG_SYS_CPU_CNTL1 0x015c /* 0x57 offset in data sheet */ +#define MESON8B_REG_HHI_MPEG 0x0174 /* 0x5d offset in data sheet */ +#define MESON8B_REG_MALI 0x01b0 /* 0x6c offset in data sheet */ #define MESON8B_REG_PLL_FIXED 0x0280 #define MESON8B_REG_PLL_SYS 0x0300 #define MESON8B_REG_PLL_VID 0x0320 -- cgit v1.2.3 From e92f7cca446ec503251b58ad9a8b5592a2d927de Mon Sep 17 00:00:00 2001 From: Michael Turquette Date: Thu, 28 Apr 2016 12:00:52 -0700 Subject: clk: meson8b: clean up fixed rate clocks Remove the fixed_rate registration function and helpers from clkc.[ch]. Replace unnecessary configuration struct with static initialization of the desired clock type. While we're here, begin the transition to a proper platform_driver and call of_clk_add_hw_provider with a shiny new struct clk_hw_onecell_data. Tested-by: Kevin Hilman Signed-off-by: Michael Turquette --- drivers/clk/meson/clkc.c | 34 -------------------- drivers/clk/meson/clkc.h | 26 --------------- drivers/clk/meson/meson8b-clkc.c | 69 +++++++++++++++++++++++++++++++--------- 3 files changed, 54 insertions(+), 75 deletions(-) diff --git a/drivers/clk/meson/clkc.c b/drivers/clk/meson/clkc.c index d920d410b51d..c6802fd23994 100644 --- a/drivers/clk/meson/clkc.c +++ b/drivers/clk/meson/clkc.c @@ -167,36 +167,6 @@ meson_clk_register_fixed_factor(const struct clk_conf *clk_conf, return clk; } -static struct clk * __init -meson_clk_register_fixed_rate(const struct clk_conf *clk_conf, - void __iomem *clk_base) -{ - struct clk *clk; - const struct fixed_rate_conf *fixed_rate_conf; - const struct parm *r; - unsigned long rate; - u32 reg; - - fixed_rate_conf = &clk_conf->conf.fixed_rate; - rate = fixed_rate_conf->rate; - - if (!rate) { - r = &fixed_rate_conf->rate_parm; - reg = readl(clk_base + clk_conf->reg_off + r->reg_off); - rate = PARM_GET(r->width, r->shift, reg); - } - - rate *= 1000000; - - clk = clk_register_fixed_rate(NULL, - clk_conf->clk_name, - clk_conf->num_parents - ? clk_conf->clks_parent[0] : NULL, - clk_conf->flags, rate); - - return clk; -} - void __init meson_clk_register_clks(const struct clk_conf *clk_confs, unsigned int nr_confs, void __iomem *clk_base) @@ -208,10 +178,6 @@ void __init meson_clk_register_clks(const struct clk_conf *clk_confs, const struct clk_conf *clk_conf = &clk_confs[i]; switch (clk_conf->clk_type) { - case CLK_FIXED_RATE: - clk = meson_clk_register_fixed_rate(clk_conf, - clk_base); - break; case CLK_FIXED_FACTOR: clk = meson_clk_register_fixed_factor(clk_conf, clk_base); diff --git a/drivers/clk/meson/clkc.h b/drivers/clk/meson/clkc.h index 609ae92cc13f..b23b057d86e1 100644 --- a/drivers/clk/meson/clkc.h +++ b/drivers/clk/meson/clkc.h @@ -69,11 +69,6 @@ struct fixed_fact_conf { struct parm mult_parm; }; -struct fixed_rate_conf { - unsigned long rate; - struct parm rate_parm; -}; - struct composite_conf { struct parm mux_parm; struct parm div_parm; @@ -89,7 +84,6 @@ struct composite_conf { enum clk_type { CLK_FIXED_FACTOR, - CLK_FIXED_RATE, CLK_COMPOSITE, CLK_CPU, CLK_PLL, @@ -105,32 +99,12 @@ struct clk_conf { unsigned long flags; union { struct fixed_fact_conf fixed_fact; - struct fixed_rate_conf fixed_rate; const struct composite_conf *composite; struct pll_conf *pll; const struct clk_div_table *div_table; } conf; }; -#define FIXED_RATE_P(_ro, _ci, _cn, _f, _c) \ - { \ - .reg_off = (_ro), \ - .clk_type = CLK_FIXED_RATE, \ - .clk_id = (_ci), \ - .clk_name = (_cn), \ - .flags = (_f), \ - .conf.fixed_rate.rate_parm = _c, \ - } \ - -#define FIXED_RATE(_ci, _cn, _f, _r) \ - { \ - .clk_type = CLK_FIXED_RATE, \ - .clk_id = (_ci), \ - .clk_name = (_cn), \ - .flags = (_f), \ - .conf.fixed_rate.rate = (_r), \ - } \ - #define PLL(_ro, _ci, _cn, _cp, _f, _c) \ { \ .reg_off = (_ro), \ diff --git a/drivers/clk/meson/meson8b-clkc.c b/drivers/clk/meson/meson8b-clkc.c index 444ef9414797..9afd4808b9c1 100644 --- a/drivers/clk/meson/meson8b-clkc.c +++ b/drivers/clk/meson/meson8b-clkc.c @@ -33,7 +33,6 @@ * * [0] http://dn.odroid.com/S805/Datasheet/S805_Datasheet%20V0.8%2020150126.pdf */ -#define MESON8B_REG_CTL0_ADDR 0x0000 #define MESON8B_REG_SYS_CPU_CNTL1 0x015c /* 0x57 offset in data sheet */ #define MESON8B_REG_HHI_MPEG 0x0174 /* 0x5d offset in data sheet */ #define MESON8B_REG_MALI 0x01b0 /* 0x6c offset in data sheet */ @@ -149,12 +148,25 @@ static const struct composite_conf mali_conf __initconst = { .gate_parm = PARM(0x00, 8, 1), }; -static const struct clk_conf meson8b_xtal_conf __initconst = - FIXED_RATE_P(MESON8B_REG_CTL0_ADDR, CLKID_XTAL, "xtal", 0, - PARM(0x00, 4, 7)); +static struct clk_fixed_rate meson8b_xtal = { + .fixed_rate = 24000000, + .hw.init = &(struct clk_init_data){ + .name = "xtal", + .num_parents = 0, + .ops = &clk_fixed_rate_ops, + }, +}; + +static struct clk_fixed_rate meson8b_zero = { + .fixed_rate = 0, + .hw.init = &(struct clk_init_data){ + .name = "zero", + .num_parents = 0, + .ops = &clk_fixed_rate_ops, + }, +}; static const struct clk_conf meson8b_clk_confs[] __initconst = { - FIXED_RATE(CLKID_ZERO, "zero", 0, 0), PLL(MESON8B_REG_PLL_FIXED, CLKID_PLL_FIXED, "fixed_pll", p_xtal, 0, &pll_confs), PLL(MESON8B_REG_PLL_VID, CLKID_PLL_VID, "vid_pll", @@ -174,23 +186,29 @@ static const struct clk_conf meson8b_clk_confs[] __initconst = { CLK_IGNORE_UNUSED, &mali_conf), }; +/* + * FIXME we cannot register two providers w/o breaking things. Luckily only + * clk81 is actually used by any drivers. Convert clk81 to use + * clk_hw_onecell_data last and flip the switch to call of_clk_add_hw_provider + * instead of of_clk_add_provider in the clk81 conversion patch to keep from + * breaking bisect. Then delete this comment ;-) + */ +static struct clk_hw_onecell_data meson8b_hw_onecell_data = { + .hws = { + [CLKID_XTAL] = &meson8b_xtal.hw, + [CLKID_ZERO] = &meson8b_zero.hw, + }, + .num = CLK_NR_CLKS, +}; + static void __init meson8b_clkc_init(struct device_node *np) { void __iomem *clk_base; + int ret, clkid; if (!meson_clk_init(np, CLK_NR_CLKS)) return; - /* XTAL */ - clk_base = of_iomap(np, 0); - if (!clk_base) { - pr_err("%s: Unable to map xtal base\n", __func__); - return; - } - - meson_clk_register_clks(&meson8b_xtal_conf, 1, clk_base); - iounmap(clk_base); - /* Generic clocks and PLLs */ clk_base = of_iomap(np, 1); if (!clk_base) { @@ -198,8 +216,29 @@ static void __init meson8b_clkc_init(struct device_node *np) return; } + /* + * register all clks + * CLKID_UNUSED = 0, so skip it and start with CLKID_XTAL = 1 + */ + for (clkid = CLKID_XTAL; clkid < CLK_NR_CLKS; clkid++) { + /* array might be sparse */ + if (!meson8b_hw_onecell_data.hws[clkid]) + continue; + + /* FIXME convert to devm_clk_register */ + ret = clk_hw_register(NULL, meson8b_hw_onecell_data.hws[clkid]); + if (ret) + goto unregister; + } + meson_clk_register_clks(meson8b_clk_confs, ARRAY_SIZE(meson8b_clk_confs), clk_base); + return; + +/* FIXME remove after converting to platform_driver/devm_clk_register */ +unregister: + for (clkid = CLK_NR_CLKS - 1; clkid >= 0; clkid--) + clk_hw_unregister(meson8b_hw_onecell_data.hws[clkid]); } CLK_OF_DECLARE(meson8b_clock, "amlogic,meson8b-clkc", meson8b_clkc_init); -- cgit v1.2.3 From ec623f2a43ebe482abc925f8785f462c0fe3c08a Mon Sep 17 00:00:00 2001 From: Michael Turquette Date: Thu, 28 Apr 2016 12:01:42 -0700 Subject: clk: meson8b: clean up pll clocks Remove the pll registration function and helpers. Replace unnecessary configuration struct with static initialization of the desired clock type. Tested-by: Kevin Hilman Signed-off-by: Michael Turquette --- drivers/clk/meson/clk-pll.c | 72 ++++-------------------- drivers/clk/meson/clkc.c | 6 +- drivers/clk/meson/clkc.h | 52 +++++++++--------- drivers/clk/meson/meson8b-clkc.c | 115 ++++++++++++++++++++++++++++++++------- 4 files changed, 131 insertions(+), 114 deletions(-) diff --git a/drivers/clk/meson/clk-pll.c b/drivers/clk/meson/clk-pll.c index 664edf0708ea..60c6b94fe9b1 100644 --- a/drivers/clk/meson/clk-pll.c +++ b/drivers/clk/meson/clk-pll.c @@ -44,13 +44,6 @@ #define MESON_PLL_RESET BIT(29) #define MESON_PLL_LOCK BIT(31) -struct meson_clk_pll { - struct clk_hw hw; - void __iomem *base; - struct pll_conf *conf; - unsigned int rate_count; - spinlock_t *lock; -}; #define to_meson_clk_pll(_hw) container_of(_hw, struct meson_clk_pll, hw) static unsigned long meson_clk_pll_recalc_rate(struct clk_hw *hw, @@ -63,15 +56,15 @@ static unsigned long meson_clk_pll_recalc_rate(struct clk_hw *hw, u16 n, m, od; u32 reg; - p = &pll->conf->n; + p = &pll->n; reg = readl(pll->base + p->reg_off); n = PARM_GET(p->width, p->shift, reg); - p = &pll->conf->m; + p = &pll->m; reg = readl(pll->base + p->reg_off); m = PARM_GET(p->width, p->shift, reg); - p = &pll->conf->od; + p = &pll->od; reg = readl(pll->base + p->reg_off); od = PARM_GET(p->width, p->shift, reg); @@ -84,7 +77,7 @@ static long meson_clk_pll_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *parent_rate) { struct meson_clk_pll *pll = to_meson_clk_pll(hw); - const struct pll_rate_table *rate_table = pll->conf->rate_table; + const struct pll_rate_table *rate_table = pll->rate_table; int i; for (i = 0; i < pll->rate_count; i++) { @@ -99,7 +92,7 @@ static long meson_clk_pll_round_rate(struct clk_hw *hw, unsigned long rate, static const struct pll_rate_table *meson_clk_get_pll_settings(struct meson_clk_pll *pll, unsigned long rate) { - const struct pll_rate_table *rate_table = pll->conf->rate_table; + const struct pll_rate_table *rate_table = pll->rate_table; int i; for (i = 0; i < pll->rate_count; i++) { @@ -145,24 +138,24 @@ static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate, return -EINVAL; /* PLL reset */ - p = &pll->conf->n; + p = &pll->n; reg = readl(pll->base + p->reg_off); writel(reg | MESON_PLL_RESET, pll->base + p->reg_off); reg = PARM_SET(p->width, p->shift, reg, rate_set->n); writel(reg, pll->base + p->reg_off); - p = &pll->conf->m; + p = &pll->m; reg = readl(pll->base + p->reg_off); reg = PARM_SET(p->width, p->shift, reg, rate_set->m); writel(reg, pll->base + p->reg_off); - p = &pll->conf->od; + p = &pll->od; reg = readl(pll->base + p->reg_off); reg = PARM_SET(p->width, p->shift, reg, rate_set->od); writel(reg, pll->base + p->reg_off); - p = &pll->conf->n; + p = &pll->n; ret = meson_clk_pll_wait_lock(pll, p); if (ret) { pr_warn("%s: pll did not lock, trying to restore old rate %lu\n", @@ -173,55 +166,12 @@ static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate, return ret; } -static const struct clk_ops meson_clk_pll_ops = { +const struct clk_ops meson_clk_pll_ops = { .recalc_rate = meson_clk_pll_recalc_rate, .round_rate = meson_clk_pll_round_rate, .set_rate = meson_clk_pll_set_rate, }; -static const struct clk_ops meson_clk_pll_ro_ops = { +const struct clk_ops meson_clk_pll_ro_ops = { .recalc_rate = meson_clk_pll_recalc_rate, }; - -struct clk *meson_clk_register_pll(const struct clk_conf *clk_conf, - void __iomem *reg_base, - spinlock_t *lock) -{ - struct clk *clk; - struct meson_clk_pll *clk_pll; - struct clk_init_data init; - - clk_pll = kzalloc(sizeof(*clk_pll), GFP_KERNEL); - if (!clk_pll) - return ERR_PTR(-ENOMEM); - - clk_pll->base = reg_base + clk_conf->reg_off; - clk_pll->lock = lock; - clk_pll->conf = clk_conf->conf.pll; - - init.name = clk_conf->clk_name; - init.flags = clk_conf->flags | CLK_GET_RATE_NOCACHE; - - init.parent_names = &clk_conf->clks_parent[0]; - init.num_parents = 1; - init.ops = &meson_clk_pll_ro_ops; - - /* If no rate_table is specified we assume the PLL is read-only */ - if (clk_pll->conf->rate_table) { - int len; - - for (len = 0; clk_pll->conf->rate_table[len].rate != 0; ) - len++; - - clk_pll->rate_count = len; - init.ops = &meson_clk_pll_ops; - } - - clk_pll->hw.init = &init; - - clk = clk_register(NULL, &clk_pll->hw); - if (IS_ERR(clk)) - kfree(clk_pll); - - return clk; -} diff --git a/drivers/clk/meson/clkc.c b/drivers/clk/meson/clkc.c index c6802fd23994..2161ea38272e 100644 --- a/drivers/clk/meson/clkc.c +++ b/drivers/clk/meson/clkc.c @@ -21,7 +21,7 @@ #include "clkc.h" -static DEFINE_SPINLOCK(clk_lock); +DEFINE_SPINLOCK(clk_lock); static struct clk **clks; static struct clk_onecell_data clk_data; @@ -190,10 +190,6 @@ void __init meson_clk_register_clks(const struct clk_conf *clk_confs, clk = meson_clk_register_cpu(clk_conf, clk_base, &clk_lock); break; - case CLK_PLL: - clk = meson_clk_register_pll(clk_conf, clk_base, - &clk_lock); - break; default: clk = NULL; } diff --git a/drivers/clk/meson/clkc.h b/drivers/clk/meson/clkc.h index b23b057d86e1..0bb4fb88a1a9 100644 --- a/drivers/clk/meson/clkc.h +++ b/drivers/clk/meson/clkc.h @@ -34,12 +34,13 @@ struct parm { u8 shift; u8 width; }; -#define PARM(_r, _s, _w) \ - { \ - .reg_off = (_r), \ - .shift = (_s), \ - .width = (_w), \ - } \ + +#define PARM(_r, _s, _w) \ +{ \ + .reg_off = (_r), \ + .shift = (_s), \ + .width = (_w), \ +} \ struct pll_rate_table { unsigned long rate; @@ -55,13 +56,19 @@ struct pll_rate_table { .od = (_od), \ } \ -struct pll_conf { - const struct pll_rate_table *rate_table; - struct parm m; - struct parm n; - struct parm od; +struct meson_clk_pll { + struct clk_hw hw; + void __iomem *base; + struct parm m; + struct parm n; + struct parm od; + const struct pll_rate_table *rate_table; + unsigned int rate_count; + spinlock_t *lock; }; +#define to_meson_clk_pll(_hw) container_of(_hw, struct meson_clk_pll, hw) + struct fixed_fact_conf { unsigned int div; unsigned int mult; @@ -86,7 +93,6 @@ enum clk_type { CLK_FIXED_FACTOR, CLK_COMPOSITE, CLK_CPU, - CLK_PLL, }; struct clk_conf { @@ -100,23 +106,10 @@ struct clk_conf { union { struct fixed_fact_conf fixed_fact; const struct composite_conf *composite; - struct pll_conf *pll; const struct clk_div_table *div_table; } conf; }; -#define PLL(_ro, _ci, _cn, _cp, _f, _c) \ - { \ - .reg_off = (_ro), \ - .clk_type = CLK_PLL, \ - .clk_id = (_ci), \ - .clk_name = (_cn), \ - .clks_parent = (_cp), \ - .num_parents = ARRAY_SIZE(_cp), \ - .flags = (_f), \ - .conf.pll = (_c), \ - } \ - #define FIXED_FACTOR_DIV(_ci, _cn, _cp, _f, _d) \ { \ .clk_type = CLK_FIXED_FACTOR, \ @@ -155,7 +148,12 @@ void meson_clk_register_clks(const struct clk_conf *clk_confs, unsigned int nr_confs, void __iomem *clk_base); struct clk *meson_clk_register_cpu(const struct clk_conf *clk_conf, void __iomem *reg_base, spinlock_t *lock); -struct clk *meson_clk_register_pll(const struct clk_conf *clk_conf, - void __iomem *reg_base, spinlock_t *lock); + +/* shared data */ +extern spinlock_t clk_lock; + +/* clk_ops */ +extern const struct clk_ops meson_clk_pll_ro_ops; +extern const struct clk_ops meson_clk_pll_ops; #endif /* __CLKC_H */ diff --git a/drivers/clk/meson/meson8b-clkc.c b/drivers/clk/meson/meson8b-clkc.c index 9afd4808b9c1..a3d8e6618043 100644 --- a/drivers/clk/meson/meson8b-clkc.c +++ b/drivers/clk/meson/meson8b-clkc.c @@ -110,7 +110,6 @@ static const struct clk_div_table cpu_div_table[] = { { /* sentinel */ }, }; -PNAME(p_xtal) = { "xtal" }; PNAME(p_fclk_div) = { "fixed_pll" }; PNAME(p_cpu_clk) = { "sys_pll" }; PNAME(p_clk81) = { "fclk_div3", "fclk_div4", "fclk_div5" }; @@ -120,19 +119,6 @@ PNAME(p_mali) = { "fclk_div3", "fclk_div4", "fclk_div5", static u32 mux_table_clk81[] = { 6, 5, 7 }; static u32 mux_table_mali[] = { 6, 5, 7, 4, 0 }; -static struct pll_conf pll_confs = { - .m = PARM(0x00, 0, 9), - .n = PARM(0x00, 9, 5), - .od = PARM(0x00, 16, 2), -}; - -static struct pll_conf sys_pll_conf = { - .m = PARM(0x00, 0, 9), - .n = PARM(0x00, 9, 5), - .od = PARM(0x00, 16, 2), - .rate_table = sys_pll_rate_table, -}; - static const struct composite_conf clk81_conf __initconst = { .mux_table = mux_table_clk81, .mux_flags = CLK_MUX_READ_ONLY, @@ -166,13 +152,87 @@ static struct clk_fixed_rate meson8b_zero = { }, }; +static struct meson_clk_pll meson8b_fixed_pll = { + .m = { + .reg_off = MESON8B_REG_PLL_FIXED, + .shift = 0, + .width = 9, + }, + .n = { + .reg_off = MESON8B_REG_PLL_FIXED, + .shift = 9, + .width = 5, + }, + .od = { + .reg_off = MESON8B_REG_PLL_FIXED, + .shift = 16, + .width = 2, + }, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "fixed_pll", + .ops = &meson_clk_pll_ro_ops, + .parent_names = (const char *[]){ "xtal" }, + .num_parents = 1, + .flags = CLK_GET_RATE_NOCACHE, + }, +}; + +static struct meson_clk_pll meson8b_vid_pll = { + .m = { + .reg_off = MESON8B_REG_PLL_VID, + .shift = 0, + .width = 9, + }, + .n = { + .reg_off = MESON8B_REG_PLL_VID, + .shift = 9, + .width = 5, + }, + .od = { + .reg_off = MESON8B_REG_PLL_VID, + .shift = 16, + .width = 2, + }, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "vid_pll", + .ops = &meson_clk_pll_ro_ops, + .parent_names = (const char *[]){ "xtal" }, + .num_parents = 1, + .flags = CLK_GET_RATE_NOCACHE, + }, +}; + +static struct meson_clk_pll meson8b_sys_pll = { + .m = { + .reg_off = MESON8B_REG_PLL_SYS, + .shift = 0, + .width = 9, + }, + .n = { + .reg_off = MESON8B_REG_PLL_SYS, + .shift = 9, + .width = 5, + }, + .od = { + .reg_off = MESON8B_REG_PLL_SYS, + .shift = 16, + .width = 2, + }, + .rate_table = sys_pll_rate_table, + .rate_count = ARRAY_SIZE(sys_pll_rate_table), + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "sys_pll", + .ops = &meson_clk_pll_ops, + .parent_names = (const char *[]){ "xtal" }, + .num_parents = 1, + .flags = CLK_GET_RATE_NOCACHE, + }, +}; + static const struct clk_conf meson8b_clk_confs[] __initconst = { - PLL(MESON8B_REG_PLL_FIXED, CLKID_PLL_FIXED, "fixed_pll", - p_xtal, 0, &pll_confs), - PLL(MESON8B_REG_PLL_VID, CLKID_PLL_VID, "vid_pll", - p_xtal, 0, &pll_confs), - PLL(MESON8B_REG_PLL_SYS, CLKID_PLL_SYS, "sys_pll", - p_xtal, 0, &sys_pll_conf), FIXED_FACTOR_DIV(CLKID_FCLK_DIV2, "fclk_div2", p_fclk_div, 0, 2), FIXED_FACTOR_DIV(CLKID_FCLK_DIV3, "fclk_div3", p_fclk_div, 0, 3), FIXED_FACTOR_DIV(CLKID_FCLK_DIV4, "fclk_div4", p_fclk_div, 0, 4), @@ -197,14 +257,23 @@ static struct clk_hw_onecell_data meson8b_hw_onecell_data = { .hws = { [CLKID_XTAL] = &meson8b_xtal.hw, [CLKID_ZERO] = &meson8b_zero.hw, + [CLKID_PLL_FIXED] = &meson8b_fixed_pll.hw, + [CLKID_PLL_VID] = &meson8b_vid_pll.hw, + [CLKID_PLL_SYS] = &meson8b_sys_pll.hw, }, .num = CLK_NR_CLKS, }; +static struct meson_clk_pll *const meson8b_clk_plls[] = { + &meson8b_fixed_pll, + &meson8b_vid_pll, + &meson8b_sys_pll, +}; + static void __init meson8b_clkc_init(struct device_node *np) { void __iomem *clk_base; - int ret, clkid; + int ret, clkid, i; if (!meson_clk_init(np, CLK_NR_CLKS)) return; @@ -216,6 +285,10 @@ static void __init meson8b_clkc_init(struct device_node *np) return; } + /* Populate base address for PLLs */ + for (i = 0; i < ARRAY_SIZE(meson8b_clk_plls); i++) + meson8b_clk_plls[i]->base = clk_base; + /* * register all clks * CLKID_UNUSED = 0, so skip it and start with CLKID_XTAL = 1 -- cgit v1.2.3 From 6282a2da098b07763ac5d8a710b759f17d63d1b3 Mon Sep 17 00:00:00 2001 From: Michael Turquette Date: Thu, 28 Apr 2016 12:01:58 -0700 Subject: clk: meson8b: clean up fixed factor clocks Remove the fixed factor registration function and helpers. Replace unnecessary configuration struct with static initialization of the desired clock type. Tested-by: Kevin Hilman Signed-off-by: Michael Turquette --- drivers/clk/meson/clkc.c | 46 ---------------------------- drivers/clk/meson/clkc.h | 19 ------------ drivers/clk/meson/meson8b-clkc.c | 66 ++++++++++++++++++++++++++++++++++++---- 3 files changed, 60 insertions(+), 71 deletions(-) diff --git a/drivers/clk/meson/clkc.c b/drivers/clk/meson/clkc.c index 2161ea38272e..275da2790063 100644 --- a/drivers/clk/meson/clkc.c +++ b/drivers/clk/meson/clkc.c @@ -125,48 +125,6 @@ error: return clk; } -static struct clk * __init -meson_clk_register_fixed_factor(const struct clk_conf *clk_conf, - void __iomem *clk_base) -{ - struct clk *clk; - const struct fixed_fact_conf *fixed_fact_conf; - const struct parm *p; - unsigned int mult, div; - u32 reg; - - fixed_fact_conf = &clk_conf->conf.fixed_fact; - - mult = clk_conf->conf.fixed_fact.mult; - div = clk_conf->conf.fixed_fact.div; - - if (!mult) { - mult = 1; - p = &fixed_fact_conf->mult_parm; - if (MESON_PARM_APPLICABLE(p)) { - reg = readl(clk_base + clk_conf->reg_off + p->reg_off); - mult = PARM_GET(p->width, p->shift, reg); - } - } - - if (!div) { - div = 1; - p = &fixed_fact_conf->div_parm; - if (MESON_PARM_APPLICABLE(p)) { - reg = readl(clk_base + clk_conf->reg_off + p->reg_off); - mult = PARM_GET(p->width, p->shift, reg); - } - } - - clk = clk_register_fixed_factor(NULL, - clk_conf->clk_name, - clk_conf->clks_parent[0], - clk_conf->flags, - mult, div); - - return clk; -} - void __init meson_clk_register_clks(const struct clk_conf *clk_confs, unsigned int nr_confs, void __iomem *clk_base) @@ -178,10 +136,6 @@ void __init meson_clk_register_clks(const struct clk_conf *clk_confs, const struct clk_conf *clk_conf = &clk_confs[i]; switch (clk_conf->clk_type) { - case CLK_FIXED_FACTOR: - clk = meson_clk_register_fixed_factor(clk_conf, - clk_base); - break; case CLK_COMPOSITE: clk = meson_clk_register_composite(clk_conf, clk_base); diff --git a/drivers/clk/meson/clkc.h b/drivers/clk/meson/clkc.h index 0bb4fb88a1a9..97dd4d719a84 100644 --- a/drivers/clk/meson/clkc.h +++ b/drivers/clk/meson/clkc.h @@ -69,13 +69,6 @@ struct meson_clk_pll { #define to_meson_clk_pll(_hw) container_of(_hw, struct meson_clk_pll, hw) -struct fixed_fact_conf { - unsigned int div; - unsigned int mult; - struct parm div_parm; - struct parm mult_parm; -}; - struct composite_conf { struct parm mux_parm; struct parm div_parm; @@ -90,7 +83,6 @@ struct composite_conf { #define PNAME(x) static const char *x[] enum clk_type { - CLK_FIXED_FACTOR, CLK_COMPOSITE, CLK_CPU, }; @@ -104,22 +96,11 @@ struct clk_conf { int num_parents; unsigned long flags; union { - struct fixed_fact_conf fixed_fact; const struct composite_conf *composite; const struct clk_div_table *div_table; } conf; }; -#define FIXED_FACTOR_DIV(_ci, _cn, _cp, _f, _d) \ - { \ - .clk_type = CLK_FIXED_FACTOR, \ - .clk_id = (_ci), \ - .clk_name = (_cn), \ - .clks_parent = (_cp), \ - .num_parents = ARRAY_SIZE(_cp), \ - .conf.fixed_fact.div = (_d), \ - } \ - #define CPU(_ro, _ci, _cn, _cp, _dt) \ { \ .reg_off = (_ro), \ diff --git a/drivers/clk/meson/meson8b-clkc.c b/drivers/clk/meson/meson8b-clkc.c index a3d8e6618043..6571e66ecc4e 100644 --- a/drivers/clk/meson/meson8b-clkc.c +++ b/drivers/clk/meson/meson8b-clkc.c @@ -110,7 +110,6 @@ static const struct clk_div_table cpu_div_table[] = { { /* sentinel */ }, }; -PNAME(p_fclk_div) = { "fixed_pll" }; PNAME(p_cpu_clk) = { "sys_pll" }; PNAME(p_clk81) = { "fclk_div3", "fclk_div4", "fclk_div5" }; PNAME(p_mali) = { "fclk_div3", "fclk_div4", "fclk_div5", @@ -232,12 +231,62 @@ static struct meson_clk_pll meson8b_sys_pll = { }, }; +static struct clk_fixed_factor meson8b_fclk_div2 = { + .mult = 1, + .div = 2, + .hw.init = &(struct clk_init_data){ + .name = "fclk_div2", + .ops = &clk_fixed_factor_ops, + .parent_names = (const char *[]){ "fixed_pll" }, + .num_parents = 1, + }, +}; + +static struct clk_fixed_factor meson8b_fclk_div3 = { + .mult = 1, + .div = 3, + .hw.init = &(struct clk_init_data){ + .name = "fclk_div3", + .ops = &clk_fixed_factor_ops, + .parent_names = (const char *[]){ "fixed_pll" }, + .num_parents = 1, + }, +}; + +static struct clk_fixed_factor meson8b_fclk_div4 = { + .mult = 1, + .div = 4, + .hw.init = &(struct clk_init_data){ + .name = "fclk_div4", + .ops = &clk_fixed_factor_ops, + .parent_names = (const char *[]){ "fixed_pll" }, + .num_parents = 1, + }, +}; + +static struct clk_fixed_factor meson8b_fclk_div5 = { + .mult = 1, + .div = 5, + .hw.init = &(struct clk_init_data){ + .name = "fclk_div5", + .ops = &clk_fixed_factor_ops, + .parent_names = (const char *[]){ "fixed_pll" }, + .num_parents = 1, + }, +}; + +static struct clk_fixed_factor meson8b_fclk_div7 = { + .mult = 1, + .div = 7, + .hw.init = &(struct clk_init_data){ + .name = "fclk_div7", + .ops = &clk_fixed_factor_ops, + .parent_names = (const char *[]){ "fixed_pll" }, + .num_parents = 1, + }, +}; + static const struct clk_conf meson8b_clk_confs[] __initconst = { - FIXED_FACTOR_DIV(CLKID_FCLK_DIV2, "fclk_div2", p_fclk_div, 0, 2), - FIXED_FACTOR_DIV(CLKID_FCLK_DIV3, "fclk_div3", p_fclk_div, 0, 3), - FIXED_FACTOR_DIV(CLKID_FCLK_DIV4, "fclk_div4", p_fclk_div, 0, 4), - FIXED_FACTOR_DIV(CLKID_FCLK_DIV5, "fclk_div5", p_fclk_div, 0, 5), - FIXED_FACTOR_DIV(CLKID_FCLK_DIV7, "fclk_div7", p_fclk_div, 0, 7), CPU(MESON8B_REG_SYS_CPU_CNTL1, CLKID_CPUCLK, "a5_clk", p_cpu_clk, cpu_div_table), COMPOSITE(MESON8B_REG_HHI_MPEG, CLKID_CLK81, "clk81", p_clk81, @@ -260,6 +309,11 @@ static struct clk_hw_onecell_data meson8b_hw_onecell_data = { [CLKID_PLL_FIXED] = &meson8b_fixed_pll.hw, [CLKID_PLL_VID] = &meson8b_vid_pll.hw, [CLKID_PLL_SYS] = &meson8b_sys_pll.hw, + [CLKID_FCLK_DIV2] = &meson8b_fclk_div2.hw, + [CLKID_FCLK_DIV3] = &meson8b_fclk_div3.hw, + [CLKID_FCLK_DIV4] = &meson8b_fclk_div4.hw, + [CLKID_FCLK_DIV5] = &meson8b_fclk_div5.hw, + [CLKID_FCLK_DIV7] = &meson8b_fclk_div7.hw, }, .num = CLK_NR_CLKS, }; -- cgit v1.2.3 From 55d42c40dd8aa7384aa5c5295ef9037db2b00226 Mon Sep 17 00:00:00 2001 From: Michael Turquette Date: Sat, 30 Apr 2016 12:47:36 -0700 Subject: clk: meson8b: clean up cpu clocks Remove the cpu clock registration function and helpers. Replace unnecessary configuration struct with static initialization of the desired clock type. Ninja rename a5_clk to cpu_clk to better align with cpufreq convention. Tested-by: Kevin Hilman Signed-off-by: Michael Turquette --- drivers/clk/meson/clk-cpu.c | 73 +++------------------------------------- drivers/clk/meson/clkc.c | 4 --- drivers/clk/meson/clkc.h | 25 ++++++-------- drivers/clk/meson/meson8b-clkc.c | 47 ++++++++++++++++++++++++-- 4 files changed, 59 insertions(+), 90 deletions(-) diff --git a/drivers/clk/meson/clk-cpu.c b/drivers/clk/meson/clk-cpu.c index f7c30ea54ca8..f8b2b7efd016 100644 --- a/drivers/clk/meson/clk-cpu.c +++ b/drivers/clk/meson/clk-cpu.c @@ -51,13 +51,6 @@ #include "clkc.h" -struct meson_clk_cpu { - struct notifier_block clk_nb; - const struct clk_div_table *div_table; - struct clk_hw hw; - void __iomem *base; - u16 reg_off; -}; #define to_meson_clk_cpu_hw(_hw) container_of(_hw, struct meson_clk_cpu, hw) #define to_meson_clk_cpu_nb(_nb) container_of(_nb, struct meson_clk_cpu, clk_nb) @@ -119,6 +112,7 @@ static unsigned long meson_clk_cpu_recalc_rate(struct clk_hw *hw, return parent_rate / div; } +/* FIXME MUX1 & MUX2 should be struct clk_hw objects */ static int meson_clk_cpu_pre_rate_change(struct meson_clk_cpu *clk_cpu, struct clk_notifier_data *ndata) { @@ -140,6 +134,7 @@ static int meson_clk_cpu_pre_rate_change(struct meson_clk_cpu *clk_cpu, return 0; } +/* FIXME MUX1 & MUX2 should be struct clk_hw objects */ static int meson_clk_cpu_post_rate_change(struct meson_clk_cpu *clk_cpu, struct clk_notifier_data *ndata) { @@ -161,7 +156,7 @@ static int meson_clk_cpu_post_rate_change(struct meson_clk_cpu *clk_cpu, * PLL clock is to be changed. We use the xtal input as temporary parent * while the PLL frequency is stabilized. */ -static int meson_clk_cpu_notifier_cb(struct notifier_block *nb, +int meson_clk_cpu_notifier_cb(struct notifier_block *nb, unsigned long event, void *data) { struct clk_notifier_data *ndata = data; @@ -176,68 +171,8 @@ static int meson_clk_cpu_notifier_cb(struct notifier_block *nb, return notifier_from_errno(ret); } -static const struct clk_ops meson_clk_cpu_ops = { +const struct clk_ops meson_clk_cpu_ops = { .recalc_rate = meson_clk_cpu_recalc_rate, .round_rate = meson_clk_cpu_round_rate, .set_rate = meson_clk_cpu_set_rate, }; - -struct clk *meson_clk_register_cpu(const struct clk_conf *clk_conf, - void __iomem *reg_base, - spinlock_t *lock) -{ - struct clk *clk; - struct clk *pclk; - struct meson_clk_cpu *clk_cpu; - struct clk_init_data init; - int ret; - - clk_cpu = kzalloc(sizeof(*clk_cpu), GFP_KERNEL); - if (!clk_cpu) - return ERR_PTR(-ENOMEM); - - clk_cpu->base = reg_base; - clk_cpu->reg_off = clk_conf->reg_off; - clk_cpu->div_table = clk_conf->conf.div_table; - clk_cpu->clk_nb.notifier_call = meson_clk_cpu_notifier_cb; - - init.name = clk_conf->clk_name; - init.ops = &meson_clk_cpu_ops; - init.flags = clk_conf->flags | CLK_GET_RATE_NOCACHE; - init.flags |= CLK_SET_RATE_PARENT; - init.parent_names = clk_conf->clks_parent; - init.num_parents = 1; - - clk_cpu->hw.init = &init; - - pclk = __clk_lookup(clk_conf->clks_parent[0]); - if (!pclk) { - pr_err("%s: could not lookup parent clock %s\n", - __func__, clk_conf->clks_parent[0]); - ret = -EINVAL; - goto free_clk; - } - - ret = clk_notifier_register(pclk, &clk_cpu->clk_nb); - if (ret) { - pr_err("%s: failed to register clock notifier for %s\n", - __func__, clk_conf->clk_name); - goto free_clk; - } - - clk = clk_register(NULL, &clk_cpu->hw); - if (IS_ERR(clk)) { - ret = PTR_ERR(clk); - goto unregister_clk_nb; - } - - return clk; - -unregister_clk_nb: - clk_notifier_unregister(pclk, &clk_cpu->clk_nb); -free_clk: - kfree(clk_cpu); - - return ERR_PTR(ret); -} - diff --git a/drivers/clk/meson/clkc.c b/drivers/clk/meson/clkc.c index 275da2790063..0f965537b37f 100644 --- a/drivers/clk/meson/clkc.c +++ b/drivers/clk/meson/clkc.c @@ -140,10 +140,6 @@ void __init meson_clk_register_clks(const struct clk_conf *clk_confs, clk = meson_clk_register_composite(clk_conf, clk_base); break; - case CLK_CPU: - clk = meson_clk_register_cpu(clk_conf, clk_base, - &clk_lock); - break; default: clk = NULL; } diff --git a/drivers/clk/meson/clkc.h b/drivers/clk/meson/clkc.h index 97dd4d719a84..bfa5ae24930a 100644 --- a/drivers/clk/meson/clkc.h +++ b/drivers/clk/meson/clkc.h @@ -69,6 +69,14 @@ struct meson_clk_pll { #define to_meson_clk_pll(_hw) container_of(_hw, struct meson_clk_pll, hw) +struct meson_clk_cpu { + struct clk_hw hw; + void __iomem *base; + u16 reg_off; + struct notifier_block clk_nb; + const struct clk_div_table *div_table; +}; + struct composite_conf { struct parm mux_parm; struct parm div_parm; @@ -84,7 +92,6 @@ struct composite_conf { enum clk_type { CLK_COMPOSITE, - CLK_CPU, }; struct clk_conf { @@ -101,17 +108,6 @@ struct clk_conf { } conf; }; -#define CPU(_ro, _ci, _cn, _cp, _dt) \ - { \ - .reg_off = (_ro), \ - .clk_type = CLK_CPU, \ - .clk_id = (_ci), \ - .clk_name = (_cn), \ - .clks_parent = (_cp), \ - .num_parents = ARRAY_SIZE(_cp), \ - .conf.div_table = (_dt), \ - } \ - #define COMPOSITE(_ro, _ci, _cn, _cp, _f, _c) \ { \ .reg_off = (_ro), \ @@ -127,8 +123,8 @@ struct clk_conf { struct clk **meson_clk_init(struct device_node *np, unsigned long nr_clks); void meson_clk_register_clks(const struct clk_conf *clk_confs, unsigned int nr_confs, void __iomem *clk_base); -struct clk *meson_clk_register_cpu(const struct clk_conf *clk_conf, - void __iomem *reg_base, spinlock_t *lock); +int meson_clk_cpu_notifier_cb(struct notifier_block *nb, unsigned long event, + void *data); /* shared data */ extern spinlock_t clk_lock; @@ -136,5 +132,6 @@ extern spinlock_t clk_lock; /* clk_ops */ extern const struct clk_ops meson_clk_pll_ro_ops; extern const struct clk_ops meson_clk_pll_ops; +extern const struct clk_ops meson_clk_cpu_ops; #endif /* __CLKC_H */ diff --git a/drivers/clk/meson/meson8b-clkc.c b/drivers/clk/meson/meson8b-clkc.c index 6571e66ecc4e..94512b6ada25 100644 --- a/drivers/clk/meson/meson8b-clkc.c +++ b/drivers/clk/meson/meson8b-clkc.c @@ -15,6 +15,7 @@ * this program. If not, see . */ +#include #include #include #include @@ -110,7 +111,6 @@ static const struct clk_div_table cpu_div_table[] = { { /* sentinel */ }, }; -PNAME(p_cpu_clk) = { "sys_pll" }; PNAME(p_clk81) = { "fclk_div3", "fclk_div4", "fclk_div5" }; PNAME(p_mali) = { "fclk_div3", "fclk_div4", "fclk_div5", "fclk_div7", "zero" }; @@ -286,9 +286,19 @@ static struct clk_fixed_factor meson8b_fclk_div7 = { }, }; +static struct meson_clk_cpu meson8b_cpu_clk = { + .reg_off = MESON8B_REG_SYS_CPU_CNTL1, + .div_table = cpu_div_table, + .clk_nb.notifier_call = meson_clk_cpu_notifier_cb, + .hw.init = &(struct clk_init_data){ + .name = "cpu_clk", + .ops = &meson_clk_cpu_ops, + .parent_names = (const char *[]){ "sys_pll" }, + .num_parents = 1, + }, +}; + static const struct clk_conf meson8b_clk_confs[] __initconst = { - CPU(MESON8B_REG_SYS_CPU_CNTL1, CLKID_CPUCLK, "a5_clk", p_cpu_clk, - cpu_div_table), COMPOSITE(MESON8B_REG_HHI_MPEG, CLKID_CLK81, "clk81", p_clk81, CLK_SET_RATE_NO_REPARENT | CLK_IGNORE_UNUSED, &clk81_conf), COMPOSITE(MESON8B_REG_MALI, CLKID_MALI, "mali", p_mali, @@ -314,6 +324,7 @@ static struct clk_hw_onecell_data meson8b_hw_onecell_data = { [CLKID_FCLK_DIV4] = &meson8b_fclk_div4.hw, [CLKID_FCLK_DIV5] = &meson8b_fclk_div5.hw, [CLKID_FCLK_DIV7] = &meson8b_fclk_div7.hw, + [CLKID_CPUCLK] = &meson8b_cpu_clk.hw, }, .num = CLK_NR_CLKS, }; @@ -328,6 +339,8 @@ static void __init meson8b_clkc_init(struct device_node *np) { void __iomem *clk_base; int ret, clkid, i; + struct clk_hw *parent_hw; + struct clk *parent_clk; if (!meson_clk_init(np, CLK_NR_CLKS)) return; @@ -343,6 +356,9 @@ static void __init meson8b_clkc_init(struct device_node *np) for (i = 0; i < ARRAY_SIZE(meson8b_clk_plls); i++) meson8b_clk_plls[i]->base = clk_base; + /* Populate the base address for CPU clk */ + meson8b_cpu_clk.base = clk_base; + /* * register all clks * CLKID_UNUSED = 0, so skip it and start with CLKID_XTAL = 1 @@ -358,12 +374,37 @@ static void __init meson8b_clkc_init(struct device_node *np) goto unregister; } + /* + * Register CPU clk notifier + * + * FIXME this is wrong for a lot of reasons. First, the muxes should be + * struct clk_hw objects. Second, we shouldn't program the muxes in + * notifier handlers. The tricky programming sequence will be handled + * by the forthcoming coordinated clock rates mechanism once that + * feature is released. + * + * Furthermore, looking up the parent this way is terrible. At some + * point we will stop allocating a default struct clk when registering + * a new clk_hw, and this hack will no longer work. Releasing the ccr + * feature before that time solves the problem :-) + */ + parent_hw = clk_hw_get_parent(&meson8b_cpu_clk.hw); + parent_clk = parent_hw->clk; + ret = clk_notifier_register(parent_clk, &meson8b_cpu_clk.clk_nb); + if (ret) { + pr_err("%s: failed to register clock notifier for cpu_clk\n", + __func__); + goto unregister_clk_nb; + } + meson_clk_register_clks(meson8b_clk_confs, ARRAY_SIZE(meson8b_clk_confs), clk_base); return; /* FIXME remove after converting to platform_driver/devm_clk_register */ +unregister_clk_nb: + clk_notifier_unregister(parent_clk, &meson8b_a5_clk.clk_nb); unregister: for (clkid = CLK_NR_CLKS - 1; clkid >= 0; clkid--) clk_hw_unregister(meson8b_hw_onecell_data.hws[clkid]); -- cgit v1.2.3 From ab95d6e8ccd3a7514114d08f8b8e5ca0c303c412 Mon Sep 17 00:00:00 2001 From: Michael Turquette Date: Thu, 5 May 2016 07:56:42 -0700 Subject: clk: meson8b: remove mali clk This clock is undocumented and always orphaned. Get rid of it until we have more complete clock tree documentation. Tested-by: Kevin Hilman Signed-off-by: Michael Turquette --- drivers/clk/meson/meson8b-clkc.c | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/drivers/clk/meson/meson8b-clkc.c b/drivers/clk/meson/meson8b-clkc.c index 94512b6ada25..dcd8f030782d 100644 --- a/drivers/clk/meson/meson8b-clkc.c +++ b/drivers/clk/meson/meson8b-clkc.c @@ -112,11 +112,8 @@ static const struct clk_div_table cpu_div_table[] = { }; PNAME(p_clk81) = { "fclk_div3", "fclk_div4", "fclk_div5" }; -PNAME(p_mali) = { "fclk_div3", "fclk_div4", "fclk_div5", - "fclk_div7", "zero" }; static u32 mux_table_clk81[] = { 6, 5, 7 }; -static u32 mux_table_mali[] = { 6, 5, 7, 4, 0 }; static const struct composite_conf clk81_conf __initconst = { .mux_table = mux_table_clk81, @@ -126,13 +123,6 @@ static const struct composite_conf clk81_conf __initconst = { .gate_parm = PARM(0x00, 7, 1), }; -static const struct composite_conf mali_conf __initconst = { - .mux_table = mux_table_mali, - .mux_parm = PARM(0x00, 9, 3), - .div_parm = PARM(0x00, 0, 7), - .gate_parm = PARM(0x00, 8, 1), -}; - static struct clk_fixed_rate meson8b_xtal = { .fixed_rate = 24000000, .hw.init = &(struct clk_init_data){ @@ -142,15 +132,6 @@ static struct clk_fixed_rate meson8b_xtal = { }, }; -static struct clk_fixed_rate meson8b_zero = { - .fixed_rate = 0, - .hw.init = &(struct clk_init_data){ - .name = "zero", - .num_parents = 0, - .ops = &clk_fixed_rate_ops, - }, -}; - static struct meson_clk_pll meson8b_fixed_pll = { .m = { .reg_off = MESON8B_REG_PLL_FIXED, @@ -301,8 +282,6 @@ static struct meson_clk_cpu meson8b_cpu_clk = { static const struct clk_conf meson8b_clk_confs[] __initconst = { COMPOSITE(MESON8B_REG_HHI_MPEG, CLKID_CLK81, "clk81", p_clk81, CLK_SET_RATE_NO_REPARENT | CLK_IGNORE_UNUSED, &clk81_conf), - COMPOSITE(MESON8B_REG_MALI, CLKID_MALI, "mali", p_mali, - CLK_IGNORE_UNUSED, &mali_conf), }; /* @@ -315,7 +294,6 @@ static const struct clk_conf meson8b_clk_confs[] __initconst = { static struct clk_hw_onecell_data meson8b_hw_onecell_data = { .hws = { [CLKID_XTAL] = &meson8b_xtal.hw, - [CLKID_ZERO] = &meson8b_zero.hw, [CLKID_PLL_FIXED] = &meson8b_fixed_pll.hw, [CLKID_PLL_VID] = &meson8b_vid_pll.hw, [CLKID_PLL_SYS] = &meson8b_sys_pll.hw, -- cgit v1.2.3 From c0daa3e6f5b0b707f5c4b408bc8ef541c9a7742a Mon Sep 17 00:00:00 2001 From: Michael Turquette Date: Thu, 28 Apr 2016 12:01:51 -0700 Subject: clk: meson8b: clean up composite clocks Remove the composite clock registration function and helpers. Replace unnecessary configuration struct with static initialization of the desired clock type. To preserve git bisect this patch also flips the switch and starts using of_clk_add_hw_provider instead of the deprecated meson_clk_register_clks method. As a byproduct clk.c can be deleted. Tested-by: Kevin Hilman Signed-off-by: Michael Turquette --- drivers/clk/meson/Makefile | 2 +- drivers/clk/meson/clkc.c | 161 ------------------------------- drivers/clk/meson/clkc.h | 56 ----------- drivers/clk/meson/meson8b-clkc.c | 93 ++++++++++++------ include/dt-bindings/clock/meson8b-clkc.h | 4 +- 5 files changed, 69 insertions(+), 247 deletions(-) delete mode 100644 drivers/clk/meson/clkc.c diff --git a/drivers/clk/meson/Makefile b/drivers/clk/meson/Makefile index 6d45531df9ab..901b5d435812 100644 --- a/drivers/clk/meson/Makefile +++ b/drivers/clk/meson/Makefile @@ -2,5 +2,5 @@ # Makefile for Meson specific clk # -obj-y += clkc.o clk-pll.o clk-cpu.o +obj-y += clk-pll.o clk-cpu.o obj-y += meson8b-clkc.o diff --git a/drivers/clk/meson/clkc.c b/drivers/clk/meson/clkc.c deleted file mode 100644 index 0f965537b37f..000000000000 --- a/drivers/clk/meson/clkc.c +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright (c) 2015 Endless Mobile, Inc. - * Author: Carlo Caione - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program. If not, see . - */ - -#include -#include -#include - -#include "clkc.h" - -DEFINE_SPINLOCK(clk_lock); - -static struct clk **clks; -static struct clk_onecell_data clk_data; - -struct clk ** __init meson_clk_init(struct device_node *np, - unsigned long nr_clks) -{ - clks = kcalloc(nr_clks, sizeof(*clks), GFP_KERNEL); - if (!clks) - return ERR_PTR(-ENOMEM); - - clk_data.clks = clks; - clk_data.clk_num = nr_clks; - of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); - - return clks; -} - -static void meson_clk_add_lookup(struct clk *clk, unsigned int id) -{ - if (clks && id) - clks[id] = clk; -} - -static struct clk * __init -meson_clk_register_composite(const struct clk_conf *clk_conf, - void __iomem *clk_base) -{ - struct clk *clk; - struct clk_mux *mux = NULL; - struct clk_divider *div = NULL; - struct clk_gate *gate = NULL; - const struct clk_ops *mux_ops = NULL; - const struct composite_conf *composite_conf; - - composite_conf = clk_conf->conf.composite; - - if (clk_conf->num_parents > 1) { - mux = kzalloc(sizeof(*mux), GFP_KERNEL); - if (!mux) - return ERR_PTR(-ENOMEM); - - mux->reg = clk_base + clk_conf->reg_off - + composite_conf->mux_parm.reg_off; - mux->shift = composite_conf->mux_parm.shift; - mux->mask = BIT(composite_conf->mux_parm.width) - 1; - mux->flags = composite_conf->mux_flags; - mux->lock = &clk_lock; - mux->table = composite_conf->mux_table; - mux_ops = (composite_conf->mux_flags & CLK_MUX_READ_ONLY) ? - &clk_mux_ro_ops : &clk_mux_ops; - } - - if (MESON_PARM_APPLICABLE(&composite_conf->div_parm)) { - div = kzalloc(sizeof(*div), GFP_KERNEL); - if (!div) { - clk = ERR_PTR(-ENOMEM); - goto error; - } - - div->reg = clk_base + clk_conf->reg_off - + composite_conf->div_parm.reg_off; - div->shift = composite_conf->div_parm.shift; - div->width = composite_conf->div_parm.width; - div->lock = &clk_lock; - div->flags = composite_conf->div_flags; - div->table = composite_conf->div_table; - } - - if (MESON_PARM_APPLICABLE(&composite_conf->gate_parm)) { - gate = kzalloc(sizeof(*gate), GFP_KERNEL); - if (!gate) { - clk = ERR_PTR(-ENOMEM); - goto error; - } - - gate->reg = clk_base + clk_conf->reg_off - + composite_conf->div_parm.reg_off; - gate->bit_idx = composite_conf->gate_parm.shift; - gate->flags = composite_conf->gate_flags; - gate->lock = &clk_lock; - } - - clk = clk_register_composite(NULL, clk_conf->clk_name, - clk_conf->clks_parent, - clk_conf->num_parents, - mux ? &mux->hw : NULL, mux_ops, - div ? &div->hw : NULL, &clk_divider_ops, - gate ? &gate->hw : NULL, &clk_gate_ops, - clk_conf->flags); - if (IS_ERR(clk)) - goto error; - - return clk; - -error: - kfree(gate); - kfree(div); - kfree(mux); - - return clk; -} - -void __init meson_clk_register_clks(const struct clk_conf *clk_confs, - unsigned int nr_confs, - void __iomem *clk_base) -{ - unsigned int i; - struct clk *clk = NULL; - - for (i = 0; i < nr_confs; i++) { - const struct clk_conf *clk_conf = &clk_confs[i]; - - switch (clk_conf->clk_type) { - case CLK_COMPOSITE: - clk = meson_clk_register_composite(clk_conf, - clk_base); - break; - default: - clk = NULL; - } - - if (!clk) { - pr_err("%s: unknown clock type %d\n", __func__, - clk_conf->clk_type); - continue; - } - - if (IS_ERR(clk)) { - pr_warn("%s: Unable to create %s clock\n", __func__, - clk_conf->clk_name); - continue; - } - - meson_clk_add_lookup(clk, clk_conf->clk_id); - } -} diff --git a/drivers/clk/meson/clkc.h b/drivers/clk/meson/clkc.h index bfa5ae24930a..f3f396168ba4 100644 --- a/drivers/clk/meson/clkc.h +++ b/drivers/clk/meson/clkc.h @@ -35,13 +35,6 @@ struct parm { u8 width; }; -#define PARM(_r, _s, _w) \ -{ \ - .reg_off = (_r), \ - .shift = (_s), \ - .width = (_w), \ -} \ - struct pll_rate_table { unsigned long rate; u16 m; @@ -77,58 +70,9 @@ struct meson_clk_cpu { const struct clk_div_table *div_table; }; -struct composite_conf { - struct parm mux_parm; - struct parm div_parm; - struct parm gate_parm; - struct clk_div_table *div_table; - u32 *mux_table; - u8 mux_flags; - u8 div_flags; - u8 gate_flags; -}; - -#define PNAME(x) static const char *x[] - -enum clk_type { - CLK_COMPOSITE, -}; - -struct clk_conf { - u16 reg_off; - enum clk_type clk_type; - unsigned int clk_id; - const char *clk_name; - const char **clks_parent; - int num_parents; - unsigned long flags; - union { - const struct composite_conf *composite; - const struct clk_div_table *div_table; - } conf; -}; - -#define COMPOSITE(_ro, _ci, _cn, _cp, _f, _c) \ - { \ - .reg_off = (_ro), \ - .clk_type = CLK_COMPOSITE, \ - .clk_id = (_ci), \ - .clk_name = (_cn), \ - .clks_parent = (_cp), \ - .num_parents = ARRAY_SIZE(_cp), \ - .flags = (_f), \ - .conf.composite = (_c), \ - } \ - -struct clk **meson_clk_init(struct device_node *np, unsigned long nr_clks); -void meson_clk_register_clks(const struct clk_conf *clk_confs, - unsigned int nr_confs, void __iomem *clk_base); int meson_clk_cpu_notifier_cb(struct notifier_block *nb, unsigned long event, void *data); -/* shared data */ -extern spinlock_t clk_lock; - /* clk_ops */ extern const struct clk_ops meson_clk_pll_ro_ops; extern const struct clk_ops meson_clk_pll_ops; diff --git a/drivers/clk/meson/meson8b-clkc.c b/drivers/clk/meson/meson8b-clkc.c index dcd8f030782d..57dea03e64b2 100644 --- a/drivers/clk/meson/meson8b-clkc.c +++ b/drivers/clk/meson/meson8b-clkc.c @@ -41,6 +41,8 @@ #define MESON8B_REG_PLL_SYS 0x0300 #define MESON8B_REG_PLL_VID 0x0320 +static DEFINE_SPINLOCK(clk_lock); + static const struct pll_rate_table sys_pll_rate_table[] = { PLL_RATE(312000000, 52, 1, 2), PLL_RATE(336000000, 56, 1, 2), @@ -111,18 +113,6 @@ static const struct clk_div_table cpu_div_table[] = { { /* sentinel */ }, }; -PNAME(p_clk81) = { "fclk_div3", "fclk_div4", "fclk_div5" }; - -static u32 mux_table_clk81[] = { 6, 5, 7 }; - -static const struct composite_conf clk81_conf __initconst = { - .mux_table = mux_table_clk81, - .mux_flags = CLK_MUX_READ_ONLY, - .mux_parm = PARM(0x00, 12, 3), - .div_parm = PARM(0x00, 0, 7), - .gate_parm = PARM(0x00, 7, 1), -}; - static struct clk_fixed_rate meson8b_xtal = { .fixed_rate = 24000000, .hw.init = &(struct clk_init_data){ @@ -267,6 +257,11 @@ static struct clk_fixed_factor meson8b_fclk_div7 = { }, }; +/* + * FIXME cpu clocks and the legacy composite clocks (e.g. clk81) are both PLL + * post-dividers and should be modeled with their respective PLLs via the + * forthcoming coordinated clock rates feature + */ static struct meson_clk_cpu meson8b_cpu_clk = { .reg_off = MESON8B_REG_SYS_CPU_CNTL1, .div_table = cpu_div_table, @@ -279,18 +274,57 @@ static struct meson_clk_cpu meson8b_cpu_clk = { }, }; -static const struct clk_conf meson8b_clk_confs[] __initconst = { - COMPOSITE(MESON8B_REG_HHI_MPEG, CLKID_CLK81, "clk81", p_clk81, - CLK_SET_RATE_NO_REPARENT | CLK_IGNORE_UNUSED, &clk81_conf), +static u32 mux_table_clk81[] = { 6, 5, 7 }; + +struct clk_mux meson8b_mpeg_clk_sel = { + .reg = (void *)MESON8B_REG_HHI_MPEG, + .mask = 0x7, + .shift = 12, + .flags = CLK_MUX_READ_ONLY, + .table = mux_table_clk81, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "mpeg_clk_sel", + .ops = &clk_mux_ro_ops, + /* + * FIXME bits 14:12 selects from 8 possible parents: + * xtal, 1'b0 (wtf), fclk_div7, mpll_clkout1, mpll_clkout2, + * fclk_div4, fclk_div3, fclk_div5 + */ + .parent_names = (const char *[]){ "fclk_div3", "fclk_div4", + "fclk_div5" }, + .num_parents = 3, + .flags = (CLK_SET_RATE_NO_REPARENT | CLK_IGNORE_UNUSED), + }, +}; + +struct clk_divider meson8b_mpeg_clk_div = { + .reg = (void *)MESON8B_REG_HHI_MPEG, + .shift = 0, + .width = 7, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "mpeg_clk_div", + .ops = &clk_divider_ops, + .parent_names = (const char *[]){ "mpeg_clk_sel" }, + .num_parents = 1, + .flags = (CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED), + }, +}; + +struct clk_gate meson8b_clk81 = { + .reg = (void *)MESON8B_REG_HHI_MPEG, + .bit_idx = 7, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "clk81", + .ops = &clk_gate_ops, + .parent_names = (const char *[]){ "mpeg_clk_div" }, + .num_parents = 1, + .flags = (CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED), + }, }; -/* - * FIXME we cannot register two providers w/o breaking things. Luckily only - * clk81 is actually used by any drivers. Convert clk81 to use - * clk_hw_onecell_data last and flip the switch to call of_clk_add_hw_provider - * instead of of_clk_add_provider in the clk81 conversion patch to keep from - * breaking bisect. Then delete this comment ;-) - */ static struct clk_hw_onecell_data meson8b_hw_onecell_data = { .hws = { [CLKID_XTAL] = &meson8b_xtal.hw, @@ -303,6 +337,9 @@ static struct clk_hw_onecell_data meson8b_hw_onecell_data = { [CLKID_FCLK_DIV5] = &meson8b_fclk_div5.hw, [CLKID_FCLK_DIV7] = &meson8b_fclk_div7.hw, [CLKID_CPUCLK] = &meson8b_cpu_clk.hw, + [CLKID_MPEG_SEL] = &meson8b_mpeg_clk_sel.hw, + [CLKID_MPEG_DIV] = &meson8b_mpeg_clk_div.hw, + [CLKID_CLK81] = &meson8b_clk81.hw, }, .num = CLK_NR_CLKS, }; @@ -320,9 +357,6 @@ static void __init meson8b_clkc_init(struct device_node *np) struct clk_hw *parent_hw; struct clk *parent_clk; - if (!meson_clk_init(np, CLK_NR_CLKS)) - return; - /* Generic clocks and PLLs */ clk_base = of_iomap(np, 1); if (!clk_base) { @@ -337,6 +371,11 @@ static void __init meson8b_clkc_init(struct device_node *np) /* Populate the base address for CPU clk */ meson8b_cpu_clk.base = clk_base; + /* Populate the base address for the MPEG clks */ + meson8b_mpeg_clk_sel.reg = clk_base + (u32)meson8b_mpeg_clk_sel.reg; + meson8b_mpeg_clk_div.reg = clk_base + (u32)meson8b_mpeg_clk_div.reg; + meson8b_clk81.reg = clk_base + (u32)meson8b_clk81.reg; + /* * register all clks * CLKID_UNUSED = 0, so skip it and start with CLKID_XTAL = 1 @@ -375,9 +414,7 @@ static void __init meson8b_clkc_init(struct device_node *np) goto unregister_clk_nb; } - meson_clk_register_clks(meson8b_clk_confs, - ARRAY_SIZE(meson8b_clk_confs), - clk_base); + of_clk_add_hw_provider(np, of_clk_hw_onecell_get, &meson8b_hw_onecell_data); return; /* FIXME remove after converting to platform_driver/devm_clk_register */ diff --git a/include/dt-bindings/clock/meson8b-clkc.h b/include/dt-bindings/clock/meson8b-clkc.h index bd2720d58e0c..595a58d0969a 100644 --- a/include/dt-bindings/clock/meson8b-clkc.h +++ b/include/dt-bindings/clock/meson8b-clkc.h @@ -19,7 +19,9 @@ #define CLKID_MALI 11 #define CLKID_CPUCLK 12 #define CLKID_ZERO 13 +#define CLKID_MPEG_SEL 14 +#define CLKID_MPEG_DIV 15 -#define CLK_NR_CLKS (CLKID_ZERO + 1) +#define CLK_NR_CLKS (CLKID_MPEG_DIV + 1) #endif /* __MESON8B_CLKC_H */ -- cgit v1.2.3 From 796b9aa85d3f8dc61a34c2a4161fc09f7977d0bd Mon Sep 17 00:00:00 2001 From: Michael Turquette Date: Wed, 11 May 2016 11:11:18 -0700 Subject: clk: meson8b: convert to platform_driver This patch creates a proper platform_driver for the meson8b clock controller. Use of CLK_OF_DECLARE is removed, and can be added back in later if very early registration of some clocks is required. Tested-by: Kevin Hilman Signed-off-by: Michael Turquette --- drivers/clk/meson/meson8b-clkc.c | 67 +++++++++++++++++++++++++++++----------- 1 file changed, 49 insertions(+), 18 deletions(-) diff --git a/drivers/clk/meson/meson8b-clkc.c b/drivers/clk/meson/meson8b-clkc.c index 57dea03e64b2..b1902e91213d 100644 --- a/drivers/clk/meson/meson8b-clkc.c +++ b/drivers/clk/meson/meson8b-clkc.c @@ -2,6 +2,9 @@ * Copyright (c) 2015 Endless Mobile, Inc. * Author: Carlo Caione * + * Copyright (c) 2016 BayLibre, Inc. + * Michael Turquette + * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, * version 2, as published by the Free Software Foundation. @@ -17,11 +20,10 @@ #include #include -#include -#include #include -#include #include +#include +#include #include "clkc.h" @@ -350,18 +352,19 @@ static struct meson_clk_pll *const meson8b_clk_plls[] = { &meson8b_sys_pll, }; -static void __init meson8b_clkc_init(struct device_node *np) +static int meson8b_clkc_probe(struct platform_device *pdev) { void __iomem *clk_base; int ret, clkid, i; struct clk_hw *parent_hw; struct clk *parent_clk; + struct device *dev = &pdev->dev; /* Generic clocks and PLLs */ - clk_base = of_iomap(np, 1); + clk_base = of_iomap(dev->of_node, 1); if (!clk_base) { pr_err("%s: Unable to map clk base\n", __func__); - return; + return -ENXIO; } /* Populate base address for PLLs */ @@ -386,9 +389,9 @@ static void __init meson8b_clkc_init(struct device_node *np) continue; /* FIXME convert to devm_clk_register */ - ret = clk_hw_register(NULL, meson8b_hw_onecell_data.hws[clkid]); + ret = devm_clk_hw_register(dev, meson8b_hw_onecell_data.hws[clkid]); if (ret) - goto unregister; + goto iounmap; } /* @@ -411,17 +414,45 @@ static void __init meson8b_clkc_init(struct device_node *np) if (ret) { pr_err("%s: failed to register clock notifier for cpu_clk\n", __func__); - goto unregister_clk_nb; + goto iounmap; } - of_clk_add_hw_provider(np, of_clk_hw_onecell_get, &meson8b_hw_onecell_data); - return; + return of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get, + &meson8b_hw_onecell_data); -/* FIXME remove after converting to platform_driver/devm_clk_register */ -unregister_clk_nb: - clk_notifier_unregister(parent_clk, &meson8b_a5_clk.clk_nb); -unregister: - for (clkid = CLK_NR_CLKS - 1; clkid >= 0; clkid--) - clk_hw_unregister(meson8b_hw_onecell_data.hws[clkid]); +iounmap: + iounmap(clk_base); + return ret; } -CLK_OF_DECLARE(meson8b_clock, "amlogic,meson8b-clkc", meson8b_clkc_init); + +static const struct of_device_id meson8b_clkc_match_table[] = { + { .compatible = "amlogic,meson8b-clkc" }, + { } +}; +MODULE_DEVICE_TABLE(of, meson8b_match_table); + +static struct platform_driver meson8b_driver = { + .probe = meson8b_clkc_probe, + .driver = { + .name = "meson8b-clkc", + .of_match_table = meson8b_clkc_match_table, + }, +}; + +static int __init meson8b_clkc_init(void) +{ + return platform_driver_register(&meson8b_driver); +} +module_init(meson8b_clkc_init); + +static void __exit meson8b_clkc_exit(void) +{ + platform_driver_unregister(&meson8b_driver); +} +module_exit(meson8b_clkc_exit); + +MODULE_DESCRIPTION("AmLogic S805 / Meson8b Clock Controller Driver"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:meson8b-clkc"); +MODULE_AUTHOR("Michael Turquette "); +MODULE_AUTHOR("Carlo Caione "); -- cgit v1.2.3 From cb7c47d7066ca9fda053f5cb327ea49e14f42409 Mon Sep 17 00:00:00 2001 From: Michael Turquette Date: Mon, 23 May 2016 14:29:13 -0700 Subject: clk: meson: only build selected platforms Break the AmLogic clock code up so that only the necessary parts are compiled and linked. The core code is selected by both arm and arm64 builds with COMMON_CLK_AMLOGIC. The individual drivers have their own config options as well. Tested-by: Kevin Hilman Signed-off-by: Michael Turquette --- drivers/clk/Kconfig | 1 + drivers/clk/Makefile | 2 +- drivers/clk/meson/Kconfig | 12 ++++++++++++ drivers/clk/meson/Makefile | 4 ++-- 4 files changed, 16 insertions(+), 3 deletions(-) create mode 100644 drivers/clk/meson/Kconfig diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index 53ddba26578c..30feb6b40305 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -208,6 +208,7 @@ config COMMON_CLK_OXNAS source "drivers/clk/bcm/Kconfig" source "drivers/clk/hisilicon/Kconfig" +source "drivers/clk/meson/Kconfig" source "drivers/clk/mvebu/Kconfig" source "drivers/clk/qcom/Kconfig" source "drivers/clk/renesas/Kconfig" diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index dcc5e698ff6d..af03eb2f6c05 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -65,7 +65,7 @@ ifeq ($(CONFIG_COMMON_CLK), y) obj-$(CONFIG_ARCH_MMP) += mmp/ endif obj-y += mvebu/ -obj-$(CONFIG_ARCH_MESON) += meson/ +obj-$(CONFIG_COMMON_CLK_AMLOGIC) += meson/ obj-$(CONFIG_ARCH_MXS) += mxs/ obj-$(CONFIG_MACH_PISTACHIO) += pistachio/ obj-$(CONFIG_COMMON_CLK_NXP) += nxp/ diff --git a/drivers/clk/meson/Kconfig b/drivers/clk/meson/Kconfig new file mode 100644 index 000000000000..7bb19ad7369e --- /dev/null +++ b/drivers/clk/meson/Kconfig @@ -0,0 +1,12 @@ +config COMMON_CLK_AMLOGIC + bool + depends on OF + depends on ARCH_MESON || COMPILE_TEST + +config COMMON_CLK_MESON8B + bool + depends on COMMON_CLK_AMLOGIC + help + Support for the clock controller on AmLogic S805 devices, aka + meson8b. Say Y if you want peripherals and CPU frequency scaling to + work. diff --git a/drivers/clk/meson/Makefile b/drivers/clk/meson/Makefile index 901b5d435812..b3d60fecd846 100644 --- a/drivers/clk/meson/Makefile +++ b/drivers/clk/meson/Makefile @@ -2,5 +2,5 @@ # Makefile for Meson specific clk # -obj-y += clk-pll.o clk-cpu.o -obj-y += meson8b-clkc.o +obj-$(CONFIG_COMMON_CLK_AMLOGIC) += clk-pll.o clk-cpu.o +obj-$(CONFIG_COMMON_CLK_MESON8B) += meson8b-clkc.o -- cgit v1.2.3 From 73de5c8bcf4924faf5d57c3d626b01a04ed1ee41 Mon Sep 17 00:00:00 2001 From: Michael Turquette Date: Tue, 7 Jun 2016 16:00:55 -0700 Subject: clk: meson: add peripheral gate macro There are a series of peripheral and system gate clocks that fan out from the clk81 signal. Add a helper macro to statically initialize these gate clocks. Tested-by: Kevin Hilman Signed-off-by: Michael Turquette --- drivers/clk/meson/clkc.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/clk/meson/clkc.h b/drivers/clk/meson/clkc.h index f3f396168ba4..9436932880c0 100644 --- a/drivers/clk/meson/clkc.h +++ b/drivers/clk/meson/clkc.h @@ -73,6 +73,20 @@ struct meson_clk_cpu { int meson_clk_cpu_notifier_cb(struct notifier_block *nb, unsigned long event, void *data); +#define MESON_GATE(_name, _reg, _bit) \ +struct clk_gate gxbb_##_name = { \ + .reg = (void __iomem *) _reg, \ + .bit_idx = (_bit), \ + .lock = &clk_lock, \ + .hw.init = &(struct clk_init_data) { \ + .name = #_name, \ + .ops = &clk_gate_ops, \ + .parent_names = (const char *[]){ "clk81" }, \ + .num_parents = 1, \ + .flags = (CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED), \ + }, \ +}; + /* clk_ops */ extern const struct clk_ops meson_clk_pll_ro_ops; extern const struct clk_ops meson_clk_pll_ops; -- cgit v1.2.3 From 1c50da4f27cbfb588b59684b55eb7a087bb26ed1 Mon Sep 17 00:00:00 2001 From: Michael Turquette Date: Mon, 6 Jun 2016 23:16:17 -0700 Subject: clk: meson: add mpll support MPLLs are adjustable rate clocks derived from PLLs. On both Meson8b and GXBB they appear to be only derived from fixed_pll. Add support for these clock types so that they can be added to their respective drivers. Tested-by: Kevin Hilman Signed-off-by: Michael Turquette --- drivers/clk/meson/Makefile | 2 +- drivers/clk/meson/clk-mpll.c | 94 ++++++++++++++++++++++++++++++++++++++++++++ drivers/clk/meson/clkc.h | 10 +++++ 3 files changed, 105 insertions(+), 1 deletion(-) create mode 100644 drivers/clk/meson/clk-mpll.c diff --git a/drivers/clk/meson/Makefile b/drivers/clk/meson/Makefile index b3d60fecd846..7667218b5e46 100644 --- a/drivers/clk/meson/Makefile +++ b/drivers/clk/meson/Makefile @@ -2,5 +2,5 @@ # Makefile for Meson specific clk # -obj-$(CONFIG_COMMON_CLK_AMLOGIC) += clk-pll.o clk-cpu.o +obj-$(CONFIG_COMMON_CLK_AMLOGIC) += clk-pll.o clk-cpu.o clk-mpll.o obj-$(CONFIG_COMMON_CLK_MESON8B) += meson8b-clkc.o diff --git a/drivers/clk/meson/clk-mpll.c b/drivers/clk/meson/clk-mpll.c new file mode 100644 index 000000000000..03af79005ddb --- /dev/null +++ b/drivers/clk/meson/clk-mpll.c @@ -0,0 +1,94 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright (c) 2016 AmLogic, Inc. + * Author: Michael Turquette + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License 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. + * + * 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., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called COPYING + * + * BSD LICENSE + * + * Copyright (c) 2016 AmLogic, Inc. + * Author: Michael Turquette + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * MultiPhase Locked Loops are outputs from a PLL with additional frequency + * scaling capabilities. MPLL rates are calculated as: + * + * f(N2_integer, SDM_IN ) = 2.0G/(N2_integer + SDM_IN/16384) + */ + +#include +#include "clkc.h" + +#define SDM_MAX 16384 + +#define to_meson_clk_mpll(_hw) container_of(_hw, struct meson_clk_mpll, hw) + +static unsigned long mpll_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct meson_clk_mpll *mpll = to_meson_clk_mpll(hw); + struct parm *p; + unsigned long rate = 0; + unsigned long reg, sdm, n2; + + p = &mpll->sdm; + reg = readl(mpll->base + p->reg_off); + sdm = PARM_GET(p->width, p->shift, reg); + + p = &mpll->n2; + reg = readl(mpll->base + p->reg_off); + n2 = PARM_GET(p->width, p->shift, reg); + + rate = (parent_rate * SDM_MAX) / ((SDM_MAX * n2) + sdm); + + return rate; +} + +const struct clk_ops meson_clk_mpll_ro_ops = { + .recalc_rate = mpll_recalc_rate, +}; diff --git a/drivers/clk/meson/clkc.h b/drivers/clk/meson/clkc.h index 9436932880c0..73f014691240 100644 --- a/drivers/clk/meson/clkc.h +++ b/drivers/clk/meson/clkc.h @@ -73,6 +73,15 @@ struct meson_clk_cpu { int meson_clk_cpu_notifier_cb(struct notifier_block *nb, unsigned long event, void *data); +struct meson_clk_mpll { + struct clk_hw hw; + void __iomem *base; + struct parm sdm; + struct parm n2; + /* FIXME ssen gate control? */ + spinlock_t *lock; +}; + #define MESON_GATE(_name, _reg, _bit) \ struct clk_gate gxbb_##_name = { \ .reg = (void __iomem *) _reg, \ @@ -91,5 +100,6 @@ struct clk_gate gxbb_##_name = { \ extern const struct clk_ops meson_clk_pll_ro_ops; extern const struct clk_ops meson_clk_pll_ops; extern const struct clk_ops meson_clk_cpu_ops; +extern const struct clk_ops meson_clk_mpll_ro_ops; #endif /* __CLKC_H */ -- cgit v1.2.3 From 4a47295144ddbcf802fcddb3d7c0736d9a1f2e40 Mon Sep 17 00:00:00 2001 From: Michael Turquette Date: Mon, 6 Jun 2016 18:08:15 -0700 Subject: clk: meson: fractional pll support Fractional MPLLs are a superset of the existing AmLogic MPLLs. They add in a couple of new bitfields for further dividing the clock rate to achieve rates with fractional hertz. Tested-by: Kevin Hilman Signed-off-by: Michael Turquette --- drivers/clk/meson/clk-pll.c | 32 ++++++++++++++++++++++++++++++-- drivers/clk/meson/clkc.h | 15 +++++++++++++++ 2 files changed, 45 insertions(+), 2 deletions(-) diff --git a/drivers/clk/meson/clk-pll.c b/drivers/clk/meson/clk-pll.c index 60c6b94fe9b1..4adc1e89212c 100644 --- a/drivers/clk/meson/clk-pll.c +++ b/drivers/clk/meson/clk-pll.c @@ -53,7 +53,7 @@ static unsigned long meson_clk_pll_recalc_rate(struct clk_hw *hw, struct parm *p; unsigned long parent_rate_mhz = parent_rate / 1000000; unsigned long rate_mhz; - u16 n, m, od; + u16 n, m, frac = 0, od, od2 = 0; u32 reg; p = &pll->n; @@ -68,7 +68,21 @@ static unsigned long meson_clk_pll_recalc_rate(struct clk_hw *hw, reg = readl(pll->base + p->reg_off); od = PARM_GET(p->width, p->shift, reg); - rate_mhz = (parent_rate_mhz * m / n) >> od; + p = &pll->od2; + if (p->width) { + reg = readl(pll->base + p->reg_off); + od2 = PARM_GET(p->width, p->shift, reg); + } + + p = &pll->frac; + if (p->width) { + reg = readl(pll->base + p->reg_off); + frac = PARM_GET(p->width, p->shift, reg); + rate_mhz = (parent_rate_mhz * m + \ + (parent_rate_mhz * frac >> 12)) * 2 / n; + rate_mhz = rate_mhz >> od >> od2; + } else + rate_mhz = (parent_rate_mhz * m / n) >> od >> od2; return rate_mhz * 1000000; } @@ -155,6 +169,20 @@ static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate, reg = PARM_SET(p->width, p->shift, reg, rate_set->od); writel(reg, pll->base + p->reg_off); + p = &pll->od2; + if (p->width) { + reg = readl(pll->base + p->reg_off); + reg = PARM_SET(p->width, p->shift, reg, rate_set->od2); + writel(reg, pll->base + p->reg_off); + } + + p = &pll->frac; + if (p->width) { + reg = readl(pll->base + p->reg_off); + reg = PARM_SET(p->width, p->shift, reg, rate_set->frac); + writel(reg, pll->base + p->reg_off); + } + p = &pll->n; ret = meson_clk_pll_wait_lock(pll, p); if (ret) { diff --git a/drivers/clk/meson/clkc.h b/drivers/clk/meson/clkc.h index 73f014691240..53326c32e853 100644 --- a/drivers/clk/meson/clkc.h +++ b/drivers/clk/meson/clkc.h @@ -40,7 +40,10 @@ struct pll_rate_table { u16 m; u16 n; u16 od; + u16 od2; + u16 frac; }; + #define PLL_RATE(_r, _m, _n, _od) \ { \ .rate = (_r), \ @@ -49,12 +52,24 @@ struct pll_rate_table { .od = (_od), \ } \ +#define PLL_FRAC_RATE(_r, _m, _n, _od, _od2, _frac) \ + { \ + .rate = (_r), \ + .m = (_m), \ + .n = (_n), \ + .od = (_od), \ + .od2 = (_od2), \ + .frac = (_frac), \ + } \ + struct meson_clk_pll { struct clk_hw hw; void __iomem *base; struct parm m; struct parm n; + struct parm frac; struct parm od; + struct parm od2; const struct pll_rate_table *rate_table; unsigned int rate_count; spinlock_t *lock; -- cgit v1.2.3 From 2cc9e7ec219819db10474160d65837c6c260522a Mon Sep 17 00:00:00 2001 From: Michael Turquette Date: Thu, 9 Jun 2016 16:20:47 -0700 Subject: clk: gxbb: Document bindings for the GXBB clock controller Add documentations for the clock controller. Tested-by: Kevin Hilman Signed-off-by: Michael Turquette --- .../bindings/clock/amlogic,gxbb-clkc.txt | 36 ++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/amlogic,gxbb-clkc.txt diff --git a/Documentation/devicetree/bindings/clock/amlogic,gxbb-clkc.txt b/Documentation/devicetree/bindings/clock/amlogic,gxbb-clkc.txt new file mode 100644 index 000000000000..ce06435d28ed --- /dev/null +++ b/Documentation/devicetree/bindings/clock/amlogic,gxbb-clkc.txt @@ -0,0 +1,36 @@ +* Amlogic GXBB Clock and Reset Unit + +The Amlogic GXBB clock controller generates and supplies clock to various +controllers within the SoC. + +Required Properties: + +- compatible: should be "amlogic,gxbb-clkc" +- reg: physical base address of the clock 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. All available clocks are defined as +preprocessor macros in the dt-bindings/clock/gxbb-clkc.h header and can be +used in device tree sources. + +Example: Clock controller node: + + clkc: clock-controller@c883c000 { + #clock-cells = <1>; + compatible = "amlogic,gxbb-clkc"; + reg = <0x0 0xc883c000 0x0 0x3db>; + }; + +Example: UART controller node that consumes the clock generated by the clock + controller: + + uart_AO: serial@c81004c0 { + compatible = "amlogic,meson-uart"; + reg = <0xc81004c0 0x14>; + interrupts = <0 90 1>; + clocks = <&clkc CLKID_CLK81>; + status = "disabled"; + }; -- cgit v1.2.3 From 738f66d3211d7ae0cd0012ba6457dac9a03bfd6b Mon Sep 17 00:00:00 2001 From: Michael Turquette Date: Mon, 23 May 2016 15:44:26 -0700 Subject: clk: gxbb: add AmLogic GXBB clk controller driver The gxbb clock controller is the primary clock generation unit for the AmLogic GXBB SoC. It is clocked by a fixed 24MHz xtal, contains several PLLs and the usual post-dividers, muxes, dividers and leaf gates that are fed into various IP blocks in the SoC. Tested-by: Kevin Hilman Signed-off-by: Michael Turquette --- drivers/clk/meson/Kconfig | 7 + drivers/clk/meson/Makefile | 1 + drivers/clk/meson/gxbb.c | 954 ++++++++++++++++++++++++++++++++++ drivers/clk/meson/gxbb.h | 271 ++++++++++ include/dt-bindings/clock/gxbb-clkc.h | 12 + 5 files changed, 1245 insertions(+) create mode 100644 drivers/clk/meson/gxbb.c create mode 100644 drivers/clk/meson/gxbb.h create mode 100644 include/dt-bindings/clock/gxbb-clkc.h diff --git a/drivers/clk/meson/Kconfig b/drivers/clk/meson/Kconfig index 7bb19ad7369e..19480bcc7046 100644 --- a/drivers/clk/meson/Kconfig +++ b/drivers/clk/meson/Kconfig @@ -10,3 +10,10 @@ config COMMON_CLK_MESON8B Support for the clock controller on AmLogic S805 devices, aka meson8b. Say Y if you want peripherals and CPU frequency scaling to work. + +config COMMON_CLK_GXBB + bool + depends on COMMON_CLK_AMLOGIC + help + Support for the clock controller on AmLogic S905 devices, aka gxbb. + Say Y if you want peripherals and CPU frequency scaling to work. diff --git a/drivers/clk/meson/Makefile b/drivers/clk/meson/Makefile index 7667218b5e46..197e40175166 100644 --- a/drivers/clk/meson/Makefile +++ b/drivers/clk/meson/Makefile @@ -4,3 +4,4 @@ obj-$(CONFIG_COMMON_CLK_AMLOGIC) += clk-pll.o clk-cpu.o clk-mpll.o obj-$(CONFIG_COMMON_CLK_MESON8B) += meson8b-clkc.o +obj-$(CONFIG_COMMON_CLK_GXBB) += gxbb.o diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c new file mode 100644 index 000000000000..007b7157cf4b --- /dev/null +++ b/drivers/clk/meson/gxbb.c @@ -0,0 +1,954 @@ +/* + * Copyright (c) 2016 AmLogic, Inc. + * Michael Turquette + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + +#include +#include +#include +#include +#include + +#include "clkc.h" +#include "gxbb.h" + +static DEFINE_SPINLOCK(clk_lock); + +static const struct pll_rate_table sys_pll_rate_table[] = { + PLL_RATE(24000000, 56, 1, 2), + PLL_RATE(48000000, 64, 1, 2), + PLL_RATE(72000000, 72, 1, 2), + PLL_RATE(96000000, 64, 1, 2), + PLL_RATE(120000000, 80, 1, 2), + PLL_RATE(144000000, 96, 1, 2), + PLL_RATE(168000000, 56, 1, 1), + PLL_RATE(192000000, 64, 1, 1), + PLL_RATE(216000000, 72, 1, 1), + PLL_RATE(240000000, 80, 1, 1), + PLL_RATE(264000000, 88, 1, 1), + PLL_RATE(288000000, 96, 1, 1), + PLL_RATE(312000000, 52, 1, 2), + PLL_RATE(336000000, 56, 1, 2), + PLL_RATE(360000000, 60, 1, 2), + PLL_RATE(384000000, 64, 1, 2), + PLL_RATE(408000000, 68, 1, 2), + PLL_RATE(432000000, 72, 1, 2), + PLL_RATE(456000000, 76, 1, 2), + PLL_RATE(480000000, 80, 1, 2), + PLL_RATE(504000000, 84, 1, 2), + PLL_RATE(528000000, 88, 1, 2), + PLL_RATE(552000000, 92, 1, 2), + PLL_RATE(576000000, 96, 1, 2), + PLL_RATE(600000000, 50, 1, 1), + PLL_RATE(624000000, 52, 1, 1), + PLL_RATE(648000000, 54, 1, 1), + PLL_RATE(672000000, 56, 1, 1), + PLL_RATE(696000000, 58, 1, 1), + PLL_RATE(720000000, 60, 1, 1), + PLL_RATE(744000000, 62, 1, 1), + PLL_RATE(768000000, 64, 1, 1), + PLL_RATE(792000000, 66, 1, 1), + PLL_RATE(816000000, 68, 1, 1), + PLL_RATE(840000000, 70, 1, 1), + PLL_RATE(864000000, 72, 1, 1), + PLL_RATE(888000000, 74, 1, 1), + PLL_RATE(912000000, 76, 1, 1), + PLL_RATE(936000000, 78, 1, 1), + PLL_RATE(960000000, 80, 1, 1), + PLL_RATE(984000000, 82, 1, 1), + PLL_RATE(1008000000, 84, 1, 1), + PLL_RATE(1032000000, 86, 1, 1), + PLL_RATE(1056000000, 88, 1, 1), + PLL_RATE(1080000000, 90, 1, 1), + PLL_RATE(1104000000, 92, 1, 1), + PLL_RATE(1128000000, 94, 1, 1), + PLL_RATE(1152000000, 96, 1, 1), + PLL_RATE(1176000000, 98, 1, 1), + PLL_RATE(1200000000, 50, 1, 0), + PLL_RATE(1224000000, 51, 1, 0), + PLL_RATE(1248000000, 52, 1, 0), + PLL_RATE(1272000000, 53, 1, 0), + PLL_RATE(1296000000, 54, 1, 0), + PLL_RATE(1320000000, 55, 1, 0), + PLL_RATE(1344000000, 56, 1, 0), + PLL_RATE(1368000000, 57, 1, 0), + PLL_RATE(1392000000, 58, 1, 0), + PLL_RATE(1416000000, 59, 1, 0), + PLL_RATE(1440000000, 60, 1, 0), + PLL_RATE(1464000000, 61, 1, 0), + PLL_RATE(1488000000, 62, 1, 0), + PLL_RATE(1512000000, 63, 1, 0), + PLL_RATE(1536000000, 64, 1, 0), + PLL_RATE(1560000000, 65, 1, 0), + PLL_RATE(1584000000, 66, 1, 0), + PLL_RATE(1608000000, 67, 1, 0), + PLL_RATE(1632000000, 68, 1, 0), + PLL_RATE(1656000000, 68, 1, 0), + PLL_RATE(1680000000, 68, 1, 0), + PLL_RATE(1704000000, 68, 1, 0), + PLL_RATE(1728000000, 69, 1, 0), + PLL_RATE(1752000000, 69, 1, 0), + PLL_RATE(1776000000, 69, 1, 0), + PLL_RATE(1800000000, 69, 1, 0), + PLL_RATE(1824000000, 70, 1, 0), + PLL_RATE(1848000000, 70, 1, 0), + PLL_RATE(1872000000, 70, 1, 0), + PLL_RATE(1896000000, 70, 1, 0), + PLL_RATE(1920000000, 71, 1, 0), + PLL_RATE(1944000000, 71, 1, 0), + PLL_RATE(1968000000, 71, 1, 0), + PLL_RATE(1992000000, 71, 1, 0), + PLL_RATE(2016000000, 72, 1, 0), + PLL_RATE(2040000000, 72, 1, 0), + PLL_RATE(2064000000, 72, 1, 0), + PLL_RATE(2088000000, 72, 1, 0), + PLL_RATE(2112000000, 73, 1, 0), + { /* sentinel */ }, +}; + +static const struct pll_rate_table gp0_pll_rate_table[] = { + PLL_RATE(96000000, 32, 1, 3), + PLL_RATE(99000000, 33, 1, 3), + PLL_RATE(102000000, 34, 1, 3), + PLL_RATE(105000000, 35, 1, 3), + PLL_RATE(108000000, 36, 1, 3), + PLL_RATE(111000000, 37, 1, 3), + PLL_RATE(114000000, 38, 1, 3), + PLL_RATE(117000000, 39, 1, 3), + PLL_RATE(120000000, 40, 1, 3), + PLL_RATE(123000000, 41, 1, 3), + PLL_RATE(126000000, 42, 1, 3), + PLL_RATE(129000000, 43, 1, 3), + PLL_RATE(132000000, 44, 1, 3), + PLL_RATE(135000000, 45, 1, 3), + PLL_RATE(138000000, 46, 1, 3), + PLL_RATE(141000000, 47, 1, 3), + PLL_RATE(144000000, 48, 1, 3), + PLL_RATE(147000000, 49, 1, 3), + PLL_RATE(150000000, 50, 1, 3), + PLL_RATE(153000000, 51, 1, 3), + PLL_RATE(156000000, 52, 1, 3), + PLL_RATE(159000000, 53, 1, 3), + PLL_RATE(162000000, 54, 1, 3), + PLL_RATE(165000000, 55, 1, 3), + PLL_RATE(168000000, 56, 1, 3), + PLL_RATE(171000000, 57, 1, 3), + PLL_RATE(174000000, 58, 1, 3), + PLL_RATE(177000000, 59, 1, 3), + PLL_RATE(180000000, 60, 1, 3), + PLL_RATE(183000000, 61, 1, 3), + PLL_RATE(186000000, 62, 1, 3), + PLL_RATE(192000000, 32, 1, 2), + PLL_RATE(198000000, 33, 1, 2), + PLL_RATE(204000000, 34, 1, 2), + PLL_RATE(210000000, 35, 1, 2), + PLL_RATE(216000000, 36, 1, 2), + PLL_RATE(222000000, 37, 1, 2), + PLL_RATE(228000000, 38, 1, 2), + PLL_RATE(234000000, 39, 1, 2), + PLL_RATE(240000000, 40, 1, 2), + PLL_RATE(246000000, 41, 1, 2), + PLL_RATE(252000000, 42, 1, 2), + PLL_RATE(258000000, 43, 1, 2), + PLL_RATE(264000000, 44, 1, 2), + PLL_RATE(270000000, 45, 1, 2), + PLL_RATE(276000000, 46, 1, 2), + PLL_RATE(282000000, 47, 1, 2), + PLL_RATE(288000000, 48, 1, 2), + PLL_RATE(294000000, 49, 1, 2), + PLL_RATE(300000000, 50, 1, 2), + PLL_RATE(306000000, 51, 1, 2), + PLL_RATE(312000000, 52, 1, 2), + PLL_RATE(318000000, 53, 1, 2), + PLL_RATE(324000000, 54, 1, 2), + PLL_RATE(330000000, 55, 1, 2), + PLL_RATE(336000000, 56, 1, 2), + PLL_RATE(342000000, 57, 1, 2), + PLL_RATE(348000000, 58, 1, 2), + PLL_RATE(354000000, 59, 1, 2), + PLL_RATE(360000000, 60, 1, 2), + PLL_RATE(366000000, 61, 1, 2), + PLL_RATE(372000000, 62, 1, 2), + PLL_RATE(384000000, 32, 1, 1), + PLL_RATE(396000000, 33, 1, 1), + PLL_RATE(408000000, 34, 1, 1), + PLL_RATE(420000000, 35, 1, 1), + PLL_RATE(432000000, 36, 1, 1), + PLL_RATE(444000000, 37, 1, 1), + PLL_RATE(456000000, 38, 1, 1), + PLL_RATE(468000000, 39, 1, 1), + PLL_RATE(480000000, 40, 1, 1), + PLL_RATE(492000000, 41, 1, 1), + PLL_RATE(504000000, 42, 1, 1), + PLL_RATE(516000000, 43, 1, 1), + PLL_RATE(528000000, 44, 1, 1), + PLL_RATE(540000000, 45, 1, 1), + PLL_RATE(552000000, 46, 1, 1), + PLL_RATE(564000000, 47, 1, 1), + PLL_RATE(576000000, 48, 1, 1), + PLL_RATE(588000000, 49, 1, 1), + PLL_RATE(600000000, 50, 1, 1), + PLL_RATE(612000000, 51, 1, 1), + PLL_RATE(624000000, 52, 1, 1), + PLL_RATE(636000000, 53, 1, 1), + PLL_RATE(648000000, 54, 1, 1), + PLL_RATE(660000000, 55, 1, 1), + PLL_RATE(672000000, 56, 1, 1), + PLL_RATE(684000000, 57, 1, 1), + PLL_RATE(696000000, 58, 1, 1), + PLL_RATE(708000000, 59, 1, 1), + PLL_RATE(720000000, 60, 1, 1), + PLL_RATE(732000000, 61, 1, 1), + PLL_RATE(744000000, 62, 1, 1), + PLL_RATE(768000000, 32, 1, 0), + PLL_RATE(792000000, 33, 1, 0), + PLL_RATE(816000000, 34, 1, 0), + PLL_RATE(840000000, 35, 1, 0), + PLL_RATE(864000000, 36, 1, 0), + PLL_RATE(888000000, 37, 1, 0), + PLL_RATE(912000000, 38, 1, 0), + PLL_RATE(936000000, 39, 1, 0), + PLL_RATE(960000000, 40, 1, 0), + PLL_RATE(984000000, 41, 1, 0), + PLL_RATE(1008000000, 42, 1, 0), + PLL_RATE(1032000000, 43, 1, 0), + PLL_RATE(1056000000, 44, 1, 0), + PLL_RATE(1080000000, 45, 1, 0), + PLL_RATE(1104000000, 46, 1, 0), + PLL_RATE(1128000000, 47, 1, 0), + PLL_RATE(1152000000, 48, 1, 0), + PLL_RATE(1176000000, 49, 1, 0), + PLL_RATE(1200000000, 50, 1, 0), + PLL_RATE(1224000000, 51, 1, 0), + PLL_RATE(1248000000, 52, 1, 0), + PLL_RATE(1272000000, 53, 1, 0), + PLL_RATE(1296000000, 54, 1, 0), + PLL_RATE(1320000000, 55, 1, 0), + PLL_RATE(1344000000, 56, 1, 0), + PLL_RATE(1368000000, 57, 1, 0), + PLL_RATE(1392000000, 58, 1, 0), + PLL_RATE(1416000000, 59, 1, 0), + PLL_RATE(1440000000, 60, 1, 0), + PLL_RATE(1464000000, 61, 1, 0), + PLL_RATE(1488000000, 62, 1, 0), + { /* sentinel */ }, +}; + +static const struct clk_div_table cpu_div_table[] = { + { .val = 1, .div = 1 }, + { .val = 2, .div = 2 }, + { .val = 3, .div = 3 }, + { .val = 2, .div = 4 }, + { .val = 3, .div = 6 }, + { .val = 4, .div = 8 }, + { .val = 5, .div = 10 }, + { .val = 6, .div = 12 }, + { .val = 7, .div = 14 }, + { .val = 8, .div = 16 }, + { /* sentinel */ }, +}; + +static struct meson_clk_pll gxbb_fixed_pll = { + .m = { + .reg_off = HHI_MPLL_CNTL, + .shift = 0, + .width = 9, + }, + .n = { + .reg_off = HHI_MPLL_CNTL, + .shift = 9, + .width = 5, + }, + .od = { + .reg_off = HHI_MPLL_CNTL, + .shift = 16, + .width = 2, + }, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "fixed_pll", + .ops = &meson_clk_pll_ro_ops, + .parent_names = (const char *[]){ "xtal" }, + .num_parents = 1, + .flags = CLK_GET_RATE_NOCACHE, + }, +}; + +static struct meson_clk_pll gxbb_hdmi_pll = { + .m = { + .reg_off = HHI_HDMI_PLL_CNTL, + .shift = 0, + .width = 9, + }, + .n = { + .reg_off = HHI_HDMI_PLL_CNTL, + .shift = 9, + .width = 5, + }, + .frac = { + .reg_off = HHI_HDMI_PLL_CNTL2, + .shift = 0, + .width = 12, + }, + .od = { + .reg_off = HHI_HDMI_PLL_CNTL2, + .shift = 16, + .width = 2, + }, + .od2 = { + .reg_off = HHI_HDMI_PLL_CNTL2, + .shift = 22, + .width = 2, + }, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "hdmi_pll", + .ops = &meson_clk_pll_ro_ops, + .parent_names = (const char *[]){ "xtal" }, + .num_parents = 1, + .flags = CLK_GET_RATE_NOCACHE, + }, +}; + +static struct meson_clk_pll gxbb_sys_pll = { + .m = { + .reg_off = HHI_SYS_PLL_CNTL, + .shift = 0, + .width = 9, + }, + .n = { + .reg_off = HHI_SYS_PLL_CNTL, + .shift = 9, + .width = 5, + }, + .od = { + .reg_off = HHI_SYS_PLL_CNTL, + .shift = 10, + .width = 2, + }, + .rate_table = sys_pll_rate_table, + .rate_count = ARRAY_SIZE(sys_pll_rate_table), + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "sys_pll", + .ops = &meson_clk_pll_ro_ops, + .parent_names = (const char *[]){ "xtal" }, + .num_parents = 1, + .flags = CLK_GET_RATE_NOCACHE, + }, +}; + +static struct meson_clk_pll gxbb_gp0_pll = { + .m = { + .reg_off = HHI_GP0_PLL_CNTL, + .shift = 0, + .width = 9, + }, + .n = { + .reg_off = HHI_GP0_PLL_CNTL, + .shift = 9, + .width = 5, + }, + .od = { + .reg_off = HHI_GP0_PLL_CNTL, + .shift = 16, + .width = 2, + }, + .rate_table = gp0_pll_rate_table, + .rate_count = ARRAY_SIZE(gp0_pll_rate_table), + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "gp0_pll", + .ops = &meson_clk_pll_ops, + .parent_names = (const char *[]){ "xtal" }, + .num_parents = 1, + .flags = CLK_GET_RATE_NOCACHE, + }, +}; + +static struct clk_fixed_factor gxbb_fclk_div2 = { + .mult = 1, + .div = 2, + .hw.init = &(struct clk_init_data){ + .name = "fclk_div2", + .ops = &clk_fixed_factor_ops, + .parent_names = (const char *[]){ "fixed_pll" }, + .num_parents = 1, + }, +}; + +static struct clk_fixed_factor gxbb_fclk_div3 = { + .mult = 1, + .div = 3, + .hw.init = &(struct clk_init_data){ + .name = "fclk_div3", + .ops = &clk_fixed_factor_ops, + .parent_names = (const char *[]){ "fixed_pll" }, + .num_parents = 1, + }, +}; + +static struct clk_fixed_factor gxbb_fclk_div4 = { + .mult = 1, + .div = 4, + .hw.init = &(struct clk_init_data){ + .name = "fclk_div4", + .ops = &clk_fixed_factor_ops, + .parent_names = (const char *[]){ "fixed_pll" }, + .num_parents = 1, + }, +}; + +static struct clk_fixed_factor gxbb_fclk_div5 = { + .mult = 1, + .div = 5, + .hw.init = &(struct clk_init_data){ + .name = "fclk_div5", + .ops = &clk_fixed_factor_ops, + .parent_names = (const char *[]){ "fixed_pll" }, + .num_parents = 1, + }, +}; + +static struct clk_fixed_factor gxbb_fclk_div7 = { + .mult = 1, + .div = 7, + .hw.init = &(struct clk_init_data){ + .name = "fclk_div7", + .ops = &clk_fixed_factor_ops, + .parent_names = (const char *[]){ "fixed_pll" }, + .num_parents = 1, + }, +}; + +static struct meson_clk_mpll gxbb_mpll0 = { + .sdm = { + .reg_off = HHI_MPLL_CNTL7, + .shift = 0, + .width = 14, + }, + .n2 = { + .reg_off = HHI_MPLL_CNTL7, + .shift = 16, + .width = 9, + }, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "mpll0", + .ops = &meson_clk_mpll_ro_ops, + .parent_names = (const char *[]){ "fixed_pll" }, + .num_parents = 1, + }, +}; + +static struct meson_clk_mpll gxbb_mpll1 = { + .sdm = { + .reg_off = HHI_MPLL_CNTL8, + .shift = 0, + .width = 14, + }, + .n2 = { + .reg_off = HHI_MPLL_CNTL8, + .shift = 16, + .width = 9, + }, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "mpll1", + .ops = &meson_clk_mpll_ro_ops, + .parent_names = (const char *[]){ "fixed_pll" }, + .num_parents = 1, + }, +}; + +static struct meson_clk_mpll gxbb_mpll2 = { + .sdm = { + .reg_off = HHI_MPLL_CNTL9, + .shift = 0, + .width = 14, + }, + .n2 = { + .reg_off = HHI_MPLL_CNTL9, + .shift = 16, + .width = 9, + }, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "mpll2", + .ops = &meson_clk_mpll_ro_ops, + .parent_names = (const char *[]){ "fixed_pll" }, + .num_parents = 1, + }, +}; + +/* + * FIXME cpu clocks and the legacy composite clocks (e.g. clk81) are both PLL + * post-dividers and should be modeled with their respective PLLs via the + * forthcoming coordinated clock rates feature + */ +static struct meson_clk_cpu gxbb_cpu_clk = { + .reg_off = HHI_SYS_CPU_CLK_CNTL1, + .div_table = cpu_div_table, + .clk_nb.notifier_call = meson_clk_cpu_notifier_cb, + .hw.init = &(struct clk_init_data){ + .name = "cpu_clk", + .ops = &meson_clk_cpu_ops, + .parent_names = (const char *[]){ "sys_pll" }, + .num_parents = 1, + }, +}; + +static u32 mux_table_clk81[] = { 6, 5, 7 }; + +static struct clk_mux gxbb_mpeg_clk_sel = { + .reg = (void *)HHI_MPEG_CLK_CNTL, + .mask = 0x7, + .shift = 12, + .flags = CLK_MUX_READ_ONLY, + .table = mux_table_clk81, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "mpeg_clk_sel", + .ops = &clk_mux_ro_ops, + /* + * FIXME bits 14:12 selects from 8 possible parents: + * xtal, 1'b0 (wtf), fclk_div7, mpll_clkout1, mpll_clkout2, + * fclk_div4, fclk_div3, fclk_div5 + */ + .parent_names = (const char *[]){ "fclk_div3", "fclk_div4", + "fclk_div5" }, + .num_parents = 3, + .flags = (CLK_SET_RATE_NO_REPARENT | CLK_IGNORE_UNUSED), + }, +}; + +static struct clk_divider gxbb_mpeg_clk_div = { + .reg = (void *)HHI_MPEG_CLK_CNTL, + .shift = 0, + .width = 7, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "mpeg_clk_div", + .ops = &clk_divider_ops, + .parent_names = (const char *[]){ "mpeg_clk_sel" }, + .num_parents = 1, + .flags = (CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED), + }, +}; + +/* the mother of dragons^W gates */ +static struct clk_gate gxbb_clk81 = { + .reg = (void *)HHI_MPEG_CLK_CNTL, + .bit_idx = 7, + .lock = &clk_lock, + .hw.init = &(struct clk_init_data){ + .name = "clk81", + .ops = &clk_gate_ops, + .parent_names = (const char *[]){ "mpeg_clk_div" }, + .num_parents = 1, + .flags = (CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED | CLK_IS_CRITICAL), + }, +}; + +/* Everything Else (EE) domain gates */ +static MESON_GATE(ddr, HHI_GCLK_MPEG0, 0); +static MESON_GATE(dos, HHI_GCLK_MPEG0, 1); +static MESON_GATE(isa, HHI_GCLK_MPEG0, 5); +static MESON_GATE(pl301, HHI_GCLK_MPEG0, 6); +static MESON_GATE(periphs, HHI_GCLK_MPEG0, 7); +static MESON_GATE(spicc, HHI_GCLK_MPEG0, 8); +static MESON_GATE(i2c, HHI_GCLK_MPEG0, 9); +static MESON_GATE(sar_adc, HHI_GCLK_MPEG0, 10); +static MESON_GATE(smart_card, HHI_GCLK_MPEG0, 11); +static MESON_GATE(rng0, HHI_GCLK_MPEG0, 12); +static MESON_GATE(uart0, HHI_GCLK_MPEG0, 13); +static MESON_GATE(sdhc, HHI_GCLK_MPEG0, 14); +static MESON_GATE(stream, HHI_GCLK_MPEG0, 15); +static MESON_GATE(async_fifo, HHI_GCLK_MPEG0, 16); +static MESON_GATE(sdio, HHI_GCLK_MPEG0, 17); +static MESON_GATE(abuf, HHI_GCLK_MPEG0, 18); +static MESON_GATE(hiu_iface, HHI_GCLK_MPEG0, 19); +static MESON_GATE(assist_misc, HHI_GCLK_MPEG0, 23); +static MESON_GATE(spi, HHI_GCLK_MPEG0, 30); + +static MESON_GATE(i2s_spdif, HHI_GCLK_MPEG1, 2); +static MESON_GATE(eth, HHI_GCLK_MPEG1, 3); +static MESON_GATE(demux, HHI_GCLK_MPEG1, 4); +static MESON_GATE(aiu_glue, HHI_GCLK_MPEG1, 6); +static MESON_GATE(iec958, HHI_GCLK_MPEG1, 7); +static MESON_GATE(i2s_out, HHI_GCLK_MPEG1, 8); +static MESON_GATE(amclk, HHI_GCLK_MPEG1, 9); +static MESON_GATE(aififo2, HHI_GCLK_MPEG1, 10); +static MESON_GATE(mixer, HHI_GCLK_MPEG1, 11); +static MESON_GATE(mixer_iface, HHI_GCLK_MPEG1, 12); +static MESON_GATE(adc, HHI_GCLK_MPEG1, 13); +static MESON_GATE(blkmv, HHI_GCLK_MPEG1, 14); +static MESON_GATE(aiu, HHI_GCLK_MPEG1, 15); +static MESON_GATE(uart1, HHI_GCLK_MPEG1, 16); +static MESON_GATE(g2d, HHI_GCLK_MPEG1, 20); +static MESON_GATE(usb0, HHI_GCLK_MPEG1, 21); +static MESON_GATE(usb1, HHI_GCLK_MPEG1, 22); +static MESON_GATE(reset, HHI_GCLK_MPEG1, 23); +static MESON_GATE(nand, HHI_GCLK_MPEG1, 24); +static MESON_GATE(dos_parser, HHI_GCLK_MPEG1, 25); +static MESON_GATE(usb, HHI_GCLK_MPEG1, 26); +static MESON_GATE(vdin1, HHI_GCLK_MPEG1, 28); +static MESON_GATE(ahb_arb0, HHI_GCLK_MPEG1, 29); +static MESON_GATE(efuse, HHI_GCLK_MPEG1, 30); +static MESON_GATE(boot_rom, HHI_GCLK_MPEG1, 31); + +static MESON_GATE(ahb_data_bus, HHI_GCLK_MPEG2, 1); +static MESON_GATE(ahb_ctrl_bus, HHI_GCLK_MPEG2, 2); +static MESON_GATE(hdmi_intr_sync, HHI_GCLK_MPEG2, 3); +static MESON_GATE(hdmi_pclk, HHI_GCLK_MPEG2, 4); +static MESON_GATE(usb1_ddr_bridge, HHI_GCLK_MPEG2, 8); +static MESON_GATE(usb0_ddr_bridge, HHI_GCLK_MPEG2, 9); +static MESON_GATE(mmc_pclk, HHI_GCLK_MPEG2, 11); +static MESON_GATE(dvin, HHI_GCLK_MPEG2, 12); +static MESON_GATE(uart2, HHI_GCLK_MPEG2, 15); +static MESON_GATE(sana, HHI_GCLK_MPEG2, 22); +static MESON_GATE(vpu_intr, HHI_GCLK_MPEG2, 25); +static MESON_GATE(sec_ahb_ahb3_bridge, HHI_GCLK_MPEG2, 26); +static MESON_GATE(clk81_a53, HHI_GCLK_MPEG2, 29); + +static MESON_GATE(vclk2_venci0, HHI_GCLK_OTHER, 1); +static MESON_GATE(vclk2_venci1, HHI_GCLK_OTHER, 2); +static MESON_GATE(vclk2_vencp0, HHI_GCLK_OTHER, 3); +static MESON_GATE(vclk2_vencp1, HHI_GCLK_OTHER, 4); +static MESON_GATE(gclk_venci_int0, HHI_GCLK_OTHER, 8); +static MESON_GATE(gclk_vencp_int, HHI_GCLK_OTHER, 9); +static MESON_GATE(dac_clk, HHI_GCLK_OTHER, 10); +static MESON_GATE(aoclk_gate, HHI_GCLK_OTHER, 14); +static MESON_GATE(iec958_gate, HHI_GCLK_OTHER, 16); +static MESON_GATE(enc480p, HHI_GCLK_OTHER, 20); +static MESON_GATE(rng1, HHI_GCLK_OTHER, 21); +static MESON_GATE(gclk_venci_int1, HHI_GCLK_OTHER, 22); +static MESON_GATE(vclk2_venclmcc, HHI_GCLK_OTHER, 24); +static MESON_GATE(vclk2_vencl, HHI_GCLK_OTHER, 25); +static MESON_GATE(vclk_other, HHI_GCLK_OTHER, 26); +static MESON_GATE(edp, HHI_GCLK_OTHER, 31); + +/* Always On (AO) domain gates */ + +static MESON_GATE(ao_media_cpu, HHI_GCLK_AO, 0); +static MESON_GATE(ao_ahb_sram, HHI_GCLK_AO, 1); +static MESON_GATE(ao_ahb_bus, HHI_GCLK_AO, 2); +static MESON_GATE(ao_iface, HHI_GCLK_AO, 3); +static MESON_GATE(ao_i2c, HHI_GCLK_AO, 4); + +/* Array of all clocks provided by this provider */ + +static struct clk_hw_onecell_data gxbb_hw_onecell_data = { + .hws = { + [CLKID_SYS_PLL] = &gxbb_sys_pll.hw, + [CLKID_CPUCLK] = &gxbb_cpu_clk.hw, + [CLKID_HDMI_PLL] = &gxbb_hdmi_pll.hw, + [CLKID_FIXED_PLL] = &gxbb_fixed_pll.hw, + [CLKID_FCLK_DIV2] = &gxbb_fclk_div2.hw, + [CLKID_FCLK_DIV3] = &gxbb_fclk_div3.hw, + [CLKID_FCLK_DIV4] = &gxbb_fclk_div4.hw, + [CLKID_FCLK_DIV5] = &gxbb_fclk_div5.hw, + [CLKID_FCLK_DIV7] = &gxbb_fclk_div7.hw, + [CLKID_GP0_PLL] = &gxbb_gp0_pll.hw, + [CLKID_MPEG_SEL] = &gxbb_mpeg_clk_sel.hw, + [CLKID_MPEG_DIV] = &gxbb_mpeg_clk_div.hw, + [CLKID_CLK81] = &gxbb_clk81.hw, + [CLKID_MPLL0] = &gxbb_mpll0.hw, + [CLKID_MPLL1] = &gxbb_mpll1.hw, + [CLKID_MPLL2] = &gxbb_mpll2.hw, + [CLKID_DDR] = &gxbb_ddr.hw, + [CLKID_DOS] = &gxbb_dos.hw, + [CLKID_ISA] = &gxbb_isa.hw, + [CLKID_PL301] = &gxbb_pl301.hw, + [CLKID_PERIPHS] = &gxbb_periphs.hw, + [CLKID_SPICC] = &gxbb_spicc.hw, + [CLKID_I2C] = &gxbb_i2c.hw, + [CLKID_SAR_ADC] = &gxbb_sar_adc.hw, + [CLKID_SMART_CARD] = &gxbb_smart_card.hw, + [CLKID_RNG0] = &gxbb_rng0.hw, + [CLKID_UART0] = &gxbb_uart0.hw, + [CLKID_SDHC] = &gxbb_sdhc.hw, + [CLKID_STREAM] = &gxbb_stream.hw, + [CLKID_ASYNC_FIFO] = &gxbb_async_fifo.hw, + [CLKID_SDIO] = &gxbb_sdio.hw, + [CLKID_ABUF] = &gxbb_abuf.hw, + [CLKID_HIU_IFACE] = &gxbb_hiu_iface.hw, + [CLKID_ASSIST_MISC] = &gxbb_assist_misc.hw, + [CLKID_SPI] = &gxbb_spi.hw, + [CLKID_I2S_SPDIF] = &gxbb_i2s_spdif.hw, + [CLKID_ETH] = &gxbb_eth.hw, + [CLKID_DEMUX] = &gxbb_demux.hw, + [CLKID_AIU_GLUE] = &gxbb_aiu_glue.hw, + [CLKID_IEC958] = &gxbb_iec958.hw, + [CLKID_I2S_OUT] = &gxbb_i2s_out.hw, + [CLKID_AMCLK] = &gxbb_amclk.hw, + [CLKID_AIFIFO2] = &gxbb_aififo2.hw, + [CLKID_MIXER] = &gxbb_mixer.hw, + [CLKID_MIXER_IFACE] = &gxbb_mixer_iface.hw, + [CLKID_ADC] = &gxbb_adc.hw, + [CLKID_BLKMV] = &gxbb_blkmv.hw, + [CLKID_AIU] = &gxbb_aiu.hw, + [CLKID_UART1] = &gxbb_uart1.hw, + [CLKID_G2D] = &gxbb_g2d.hw, + [CLKID_USB0] = &gxbb_usb0.hw, + [CLKID_USB1] = &gxbb_usb1.hw, + [CLKID_RESET] = &gxbb_reset.hw, + [CLKID_NAND] = &gxbb_nand.hw, + [CLKID_DOS_PARSER] = &gxbb_dos_parser.hw, + [CLKID_USB] = &gxbb_usb.hw, + [CLKID_VDIN1] = &gxbb_vdin1.hw, + [CLKID_AHB_ARB0] = &gxbb_ahb_arb0.hw, + [CLKID_EFUSE] = &gxbb_efuse.hw, + [CLKID_BOOT_ROM] = &gxbb_boot_rom.hw, + [CLKID_AHB_DATA_BUS] = &gxbb_ahb_data_bus.hw, + [CLKID_AHB_CTRL_BUS] = &gxbb_ahb_ctrl_bus.hw, + [CLKID_HDMI_INTR_SYNC] = &gxbb_hdmi_intr_sync.hw, + [CLKID_HDMI_PCLK] = &gxbb_hdmi_pclk.hw, + [CLKID_USB1_DDR_BRIDGE] = &gxbb_usb1_ddr_bridge.hw, + [CLKID_USB0_DDR_BRIDGE] = &gxbb_usb0_ddr_bridge.hw, + [CLKID_MMC_PCLK] = &gxbb_mmc_pclk.hw, + [CLKID_DVIN] = &gxbb_dvin.hw, + [CLKID_UART2] = &gxbb_uart2.hw, + [CLKID_SANA] = &gxbb_sana.hw, + [CLKID_VPU_INTR] = &gxbb_vpu_intr.hw, + [CLKID_SEC_AHB_AHB3_BRIDGE] = &gxbb_sec_ahb_ahb3_bridge.hw, + [CLKID_CLK81_A53] = &gxbb_clk81_a53.hw, + [CLKID_VCLK2_VENCI0] = &gxbb_vclk2_venci0.hw, + [CLKID_VCLK2_VENCI1] = &gxbb_vclk2_venci1.hw, + [CLKID_VCLK2_VENCP0] = &gxbb_vclk2_vencp0.hw, + [CLKID_VCLK2_VENCP1] = &gxbb_vclk2_vencp1.hw, + [CLKID_GCLK_VENCI_INT0] = &gxbb_gclk_venci_int0.hw, + [CLKID_GCLK_VENCI_INT] = &gxbb_gclk_vencp_int.hw, + [CLKID_DAC_CLK] = &gxbb_dac_clk.hw, + [CLKID_AOCLK_GATE] = &gxbb_aoclk_gate.hw, + [CLKID_IEC958_GATE] = &gxbb_iec958_gate.hw, + [CLKID_ENC480P] = &gxbb_enc480p.hw, + [CLKID_RNG1] = &gxbb_rng1.hw, + [CLKID_GCLK_VENCI_INT1] = &gxbb_gclk_venci_int1.hw, + [CLKID_VCLK2_VENCLMCC] = &gxbb_vclk2_venclmcc.hw, + [CLKID_VCLK2_VENCL] = &gxbb_vclk2_vencl.hw, + [CLKID_VCLK_OTHER] = &gxbb_vclk_other.hw, + [CLKID_EDP] = &gxbb_edp.hw, + [CLKID_AO_MEDIA_CPU] = &gxbb_ao_media_cpu.hw, + [CLKID_AO_AHB_SRAM] = &gxbb_ao_ahb_sram.hw, + [CLKID_AO_AHB_BUS] = &gxbb_ao_ahb_bus.hw, + [CLKID_AO_IFACE] = &gxbb_ao_iface.hw, + [CLKID_AO_I2C] = &gxbb_ao_i2c.hw, + }, + .num = NR_CLKS, +}; + +/* Convenience tables to populate base addresses in .probe */ + +static struct meson_clk_pll *const gxbb_clk_plls[] = { + &gxbb_fixed_pll, + &gxbb_hdmi_pll, + &gxbb_sys_pll, + &gxbb_gp0_pll, +}; + +static struct meson_clk_mpll *const gxbb_clk_mplls[] = { + &gxbb_mpll0, + &gxbb_mpll1, + &gxbb_mpll2, +}; + +static struct clk_gate *gxbb_clk_gates[] = { + &gxbb_clk81, + &gxbb_ddr, + &gxbb_dos, + &gxbb_isa, + &gxbb_pl301, + &gxbb_periphs, + &gxbb_spicc, + &gxbb_i2c, + &gxbb_sar_adc, + &gxbb_smart_card, + &gxbb_rng0, + &gxbb_uart0, + &gxbb_sdhc, + &gxbb_stream, + &gxbb_async_fifo, + &gxbb_sdio, + &gxbb_abuf, + &gxbb_hiu_iface, + &gxbb_assist_misc, + &gxbb_spi, + &gxbb_i2s_spdif, + &gxbb_eth, + &gxbb_demux, + &gxbb_aiu_glue, + &gxbb_iec958, + &gxbb_i2s_out, + &gxbb_amclk, + &gxbb_aififo2, + &gxbb_mixer, + &gxbb_mixer_iface, + &gxbb_adc, + &gxbb_blkmv, + &gxbb_aiu, + &gxbb_uart1, + &gxbb_g2d, + &gxbb_usb0, + &gxbb_usb1, + &gxbb_reset, + &gxbb_nand, + &gxbb_dos_parser, + &gxbb_usb, + &gxbb_vdin1, + &gxbb_ahb_arb0, + &gxbb_efuse, + &gxbb_boot_rom, + &gxbb_ahb_data_bus, + &gxbb_ahb_ctrl_bus, + &gxbb_hdmi_intr_sync, + &gxbb_hdmi_pclk, + &gxbb_usb1_ddr_bridge, + &gxbb_usb0_ddr_bridge, + &gxbb_mmc_pclk, + &gxbb_dvin, + &gxbb_uart2, + &gxbb_sana, + &gxbb_vpu_intr, + &gxbb_sec_ahb_ahb3_bridge, + &gxbb_clk81_a53, + &gxbb_vclk2_venci0, + &gxbb_vclk2_venci1, + &gxbb_vclk2_vencp0, + &gxbb_vclk2_vencp1, + &gxbb_gclk_venci_int0, + &gxbb_gclk_vencp_int, + &gxbb_dac_clk, + &gxbb_aoclk_gate, + &gxbb_iec958_gate, + &gxbb_enc480p, + &gxbb_rng1, + &gxbb_gclk_venci_int1, + &gxbb_vclk2_venclmcc, + &gxbb_vclk2_vencl, + &gxbb_vclk_other, + &gxbb_edp, + &gxbb_ao_media_cpu, + &gxbb_ao_ahb_sram, + &gxbb_ao_ahb_bus, + &gxbb_ao_iface, + &gxbb_ao_i2c, +}; + +static int gxbb_clkc_probe(struct platform_device *pdev) +{ + void __iomem *clk_base; + int ret, clkid, i; + struct clk_hw *parent_hw; + struct clk *parent_clk; + struct device *dev = &pdev->dev; + + /* Generic clocks and PLLs */ + clk_base = of_iomap(dev->of_node, 0); + if (!clk_base) { + pr_err("%s: Unable to map clk base\n", __func__); + return -ENXIO; + } + + /* Populate base address for PLLs */ + for (i = 0; i < ARRAY_SIZE(gxbb_clk_plls); i++) + gxbb_clk_plls[i]->base = clk_base; + + /* Populate base address for MPLLs */ + for (i = 0; i < ARRAY_SIZE(gxbb_clk_mplls); i++) + gxbb_clk_mplls[i]->base = clk_base; + + /* Populate the base address for CPU clk */ + gxbb_cpu_clk.base = clk_base; + + /* Populate the base address for the MPEG clks */ + gxbb_mpeg_clk_sel.reg = clk_base + (u64)gxbb_mpeg_clk_sel.reg; + gxbb_mpeg_clk_div.reg = clk_base + (u64)gxbb_mpeg_clk_div.reg; + + /* Populate base address for gates */ + for (i = 0; i < ARRAY_SIZE(gxbb_clk_gates); i++) + gxbb_clk_gates[i]->reg = clk_base + + (u64)gxbb_clk_gates[i]->reg; + + /* + * register all clks + */ + for (clkid = 0; clkid < NR_CLKS; clkid++) { + ret = devm_clk_hw_register(dev, gxbb_hw_onecell_data.hws[clkid]); + if (ret) + goto iounmap; + } + + /* + * Register CPU clk notifier + * + * FIXME this is wrong for a lot of reasons. First, the muxes should be + * struct clk_hw objects. Second, we shouldn't program the muxes in + * notifier handlers. The tricky programming sequence will be handled + * by the forthcoming coordinated clock rates mechanism once that + * feature is released. + * + * Furthermore, looking up the parent this way is terrible. At some + * point we will stop allocating a default struct clk when registering + * a new clk_hw, and this hack will no longer work. Releasing the ccr + * feature before that time solves the problem :-) + */ + parent_hw = clk_hw_get_parent(&gxbb_cpu_clk.hw); + parent_clk = parent_hw->clk; + ret = clk_notifier_register(parent_clk, &gxbb_cpu_clk.clk_nb); + if (ret) { + pr_err("%s: failed to register clock notifier for cpu_clk\n", + __func__); + goto iounmap; + } + + return of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get, + &gxbb_hw_onecell_data); + +iounmap: + iounmap(clk_base); + return ret; +} + +static const struct of_device_id gxbb_clkc_match_table[] = { + { .compatible = "amlogic,gxbb-clkc" }, + { } +}; +MODULE_DEVICE_TABLE(of, gxbb_match_table); + +static struct platform_driver gxbb_driver = { + .probe = gxbb_clkc_probe, + .driver = { + .name = "gxbb-clkc", + .of_match_table = gxbb_clkc_match_table, + }, +}; + +static int __init gxbb_clkc_init(void) +{ + return platform_driver_register(&gxbb_driver); +} +module_init(gxbb_clkc_init); + +static void __exit gxbb_clkc_exit(void) +{ + platform_driver_unregister(&gxbb_driver); +} +module_exit(gxbb_clkc_exit); + +MODULE_DESCRIPTION("AmLogic S905 / GXBB Clock Controller Driver"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:gxbb-clkc"); +MODULE_AUTHOR("Michael Turquette "); diff --git a/drivers/clk/meson/gxbb.h b/drivers/clk/meson/gxbb.h new file mode 100644 index 000000000000..a2adf3448b59 --- /dev/null +++ b/drivers/clk/meson/gxbb.h @@ -0,0 +1,271 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright (c) 2016 AmLogic, Inc. + * Author: Michael Turquette + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License 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. + * + * 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., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called COPYING + * + * BSD LICENSE + * + * Copyright (c) 2016 BayLibre, Inc. + * Author: Michael Turquette + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __GXBB_H +#define __GXBB_H + +/* + * Clock controller register offsets + * + * Register offsets from the data sheet are listed in comment blocks below. + * Those offsets must be multiplied by 4 before adding them to the base address + * to get the right value + */ +#define SCR 0x2C /* 0x0b offset in data sheet */ +#define TIMEOUT_VALUE 0x3c /* 0x0f offset in data sheet */ + +#define HHI_GP0_PLL_CNTL 0x40 /* 0x10 offset in data sheet */ +#define HHI_GP0_PLL_CNTL2 0x44 /* 0x11 offset in data sheet */ +#define HHI_GP0_PLL_CNTL3 0x48 /* 0x12 offset in data sheet */ +#define HHI_GP0_PLL_CNTL4 0x4c /* 0x13 offset in data sheet */ + +#define HHI_XTAL_DIVN_CNTL 0xbc /* 0x2f offset in data sheet */ +#define HHI_TIMER90K 0xec /* 0x3b offset in data sheet */ + +#define HHI_MEM_PD_REG0 0x100 /* 0x40 offset in data sheet */ +#define HHI_MEM_PD_REG1 0x104 /* 0x41 offset in data sheet */ +#define HHI_VPU_MEM_PD_REG1 0x108 /* 0x42 offset in data sheet */ +#define HHI_VIID_CLK_DIV 0x128 /* 0x4a offset in data sheet */ +#define HHI_VIID_CLK_CNTL 0x12c /* 0x4b offset in data sheet */ + +#define HHI_GCLK_MPEG0 0x140 /* 0x50 offset in data sheet */ +#define HHI_GCLK_MPEG1 0x144 /* 0x51 offset in data sheet */ +#define HHI_GCLK_MPEG2 0x148 /* 0x52 offset in data sheet */ +#define HHI_GCLK_OTHER 0x150 /* 0x54 offset in data sheet */ +#define HHI_GCLK_AO 0x154 /* 0x55 offset in data sheet */ +#define HHI_SYS_OSCIN_CNTL 0x158 /* 0x56 offset in data sheet */ +#define HHI_SYS_CPU_CLK_CNTL1 0x15c /* 0x57 offset in data sheet */ +#define HHI_SYS_CPU_RESET_CNTL 0x160 /* 0x58 offset in data sheet */ +#define HHI_VID_CLK_DIV 0x164 /* 0x59 offset in data sheet */ + +#define HHI_MPEG_CLK_CNTL 0x174 /* 0x5d offset in data sheet */ +#define HHI_AUD_CLK_CNTL 0x178 /* 0x5e offset in data sheet */ +#define HHI_VID_CLK_CNTL 0x17c /* 0x5f offset in data sheet */ +#define HHI_AUD_CLK_CNTL2 0x190 /* 0x64 offset in data sheet */ +#define HHI_VID_CLK_CNTL2 0x194 /* 0x65 offset in data sheet */ +#define HHI_SYS_CPU_CLK_CNTL0 0x19c /* 0x67 offset in data sheet */ +#define HHI_VID_PLL_CLK_DIV 0x1a0 /* 0x68 offset in data sheet */ +#define HHI_AUD_CLK_CNTL3 0x1a4 /* 0x69 offset in data sheet */ +#define HHI_MALI_CLK_CNTL 0x1b0 /* 0x6c offset in data sheet */ +#define HHI_VPU_CLK_CNTL 0x1bC /* 0x6f offset in data sheet */ + +#define HHI_HDMI_CLK_CNTL 0x1CC /* 0x73 offset in data sheet */ +#define HHI_VDEC_CLK_CNTL 0x1E0 /* 0x78 offset in data sheet */ +#define HHI_VDEC2_CLK_CNTL 0x1E4 /* 0x79 offset in data sheet */ +#define HHI_VDEC3_CLK_CNTL 0x1E8 /* 0x7a offset in data sheet */ +#define HHI_VDEC4_CLK_CNTL 0x1EC /* 0x7b offset in data sheet */ +#define HHI_HDCP22_CLK_CNTL 0x1F0 /* 0x7c offset in data sheet */ +#define HHI_VAPBCLK_CNTL 0x1F4 /* 0x7d offset in data sheet */ + +#define HHI_VPU_CLKB_CNTL 0x20C /* 0x83 offset in data sheet */ +#define HHI_USB_CLK_CNTL 0x220 /* 0x88 offset in data sheet */ +#define HHI_32K_CLK_CNTL 0x224 /* 0x89 offset in data sheet */ +#define HHI_GEN_CLK_CNTL 0x228 /* 0x8a offset in data sheet */ +#define HHI_GEN_CLK_CNTL 0x228 /* 0x8a offset in data sheet */ + +#define HHI_PCM_CLK_CNTL 0x258 /* 0x96 offset in data sheet */ +#define HHI_NAND_CLK_CNTL 0x25C /* 0x97 offset in data sheet */ +#define HHI_SD_EMMC_CLK_CNTL 0x264 /* 0x99 offset in data sheet */ + +#define HHI_MPLL_CNTL 0x280 /* 0xa0 offset in data sheet */ +#define HHI_MPLL_CNTL2 0x284 /* 0xa1 offset in data sheet */ +#define HHI_MPLL_CNTL3 0x288 /* 0xa2 offset in data sheet */ +#define HHI_MPLL_CNTL4 0x28C /* 0xa3 offset in data sheet */ +#define HHI_MPLL_CNTL5 0x290 /* 0xa4 offset in data sheet */ +#define HHI_MPLL_CNTL6 0x294 /* 0xa5 offset in data sheet */ +#define HHI_MPLL_CNTL7 0x298 /* MP0, 0xa6 offset in data sheet */ +#define HHI_MPLL_CNTL8 0x29C /* MP1, 0xa7 offset in data sheet */ +#define HHI_MPLL_CNTL9 0x2A0 /* MP2, 0xa8 offset in data sheet */ +#define HHI_MPLL_CNTL10 0x2A4 /* MP2, 0xa9 offset in data sheet */ + +#define HHI_MPLL3_CNTL0 0x2E0 /* 0xb8 offset in data sheet */ +#define HHI_MPLL3_CNTL1 0x2E4 /* 0xb9 offset in data sheet */ +#define HHI_VDAC_CNTL0 0x2F4 /* 0xbd offset in data sheet */ +#define HHI_VDAC_CNTL1 0x2F8 /* 0xbe offset in data sheet */ + +#define HHI_SYS_PLL_CNTL 0x300 /* 0xc0 offset in data sheet */ +#define HHI_SYS_PLL_CNTL2 0x304 /* 0xc1 offset in data sheet */ +#define HHI_SYS_PLL_CNTL3 0x308 /* 0xc2 offset in data sheet */ +#define HHI_SYS_PLL_CNTL4 0x30c /* 0xc3 offset in data sheet */ +#define HHI_SYS_PLL_CNTL5 0x310 /* 0xc4 offset in data sheet */ +#define HHI_DPLL_TOP_I 0x318 /* 0xc6 offset in data sheet */ +#define HHI_DPLL_TOP2_I 0x31C /* 0xc7 offset in data sheet */ +#define HHI_HDMI_PLL_CNTL 0x320 /* 0xc8 offset in data sheet */ +#define HHI_HDMI_PLL_CNTL2 0x324 /* 0xc9 offset in data sheet */ +#define HHI_HDMI_PLL_CNTL3 0x328 /* 0xca offset in data sheet */ +#define HHI_HDMI_PLL_CNTL4 0x32C /* 0xcb offset in data sheet */ +#define HHI_HDMI_PLL_CNTL5 0x330 /* 0xcc offset in data sheet */ +#define HHI_HDMI_PLL_CNTL6 0x334 /* 0xcd offset in data sheet */ +#define HHI_HDMI_PLL_CNTL_I 0x338 /* 0xce offset in data sheet */ +#define HHI_HDMI_PLL_CNTL7 0x33C /* 0xcf offset in data sheet */ + +#define HHI_HDMI_PHY_CNTL0 0x3A0 /* 0xe8 offset in data sheet */ +#define HHI_HDMI_PHY_CNTL1 0x3A4 /* 0xe9 offset in data sheet */ +#define HHI_HDMI_PHY_CNTL2 0x3A8 /* 0xea offset in data sheet */ +#define HHI_HDMI_PHY_CNTL3 0x3AC /* 0xeb offset in data sheet */ + +#define HHI_VID_LOCK_CLK_CNTL 0x3C8 /* 0xf2 offset in data sheet */ +#define HHI_BT656_CLK_CNTL 0x3D4 /* 0xf5 offset in data sheet */ +#define HHI_SAR_CLK_CNTL 0x3D8 /* 0xf6 offset in data sheet */ + +/* + * CLKID index values + * + * These indices are entirely contrived and do not map onto the hardware. + * Migrate them out of this header and into the DT header file when they need + * to be exposed to client nodes in DT: include/dt-bindings/clock/gxbb-clkc.h + */ +#define CLKID_SYS_PLL 0 +/* CLKID_CPUCLK */ +#define CLKID_HDMI_PLL 2 +#define CLKID_FIXED_PLL 3 +#define CLKID_FCLK_DIV2 4 +#define CLKID_FCLK_DIV3 5 +#define CLKID_FCLK_DIV4 6 +#define CLKID_FCLK_DIV5 7 +#define CLKID_FCLK_DIV7 8 +#define CLKID_GP0_PLL 9 +#define CLKID_MPEG_SEL 10 +#define CLKID_MPEG_DIV 11 +/* CLKID_CLK81 */ +#define CLKID_MPLL0 13 +#define CLKID_MPLL1 14 +#define CLKID_MPLL2 15 +#define CLKID_DDR 16 +#define CLKID_DOS 17 +#define CLKID_ISA 18 +#define CLKID_PL301 19 +#define CLKID_PERIPHS 20 +#define CLKID_SPICC 21 +#define CLKID_I2C 22 +#define CLKID_SAR_ADC 23 +#define CLKID_SMART_CARD 24 +#define CLKID_RNG0 25 +#define CLKID_UART0 26 +#define CLKID_SDHC 27 +#define CLKID_STREAM 28 +#define CLKID_ASYNC_FIFO 29 +#define CLKID_SDIO 30 +#define CLKID_ABUF 31 +#define CLKID_HIU_IFACE 32 +#define CLKID_ASSIST_MISC 33 +#define CLKID_SPI 34 +#define CLKID_I2S_SPDIF 35 +#define CLKID_ETH 36 +#define CLKID_DEMUX 37 +#define CLKID_AIU_GLUE 38 +#define CLKID_IEC958 39 +#define CLKID_I2S_OUT 40 +#define CLKID_AMCLK 41 +#define CLKID_AIFIFO2 42 +#define CLKID_MIXER 43 +#define CLKID_MIXER_IFACE 44 +#define CLKID_ADC 45 +#define CLKID_BLKMV 46 +#define CLKID_AIU 47 +#define CLKID_UART1 48 +#define CLKID_G2D 49 +#define CLKID_USB0 50 +#define CLKID_USB1 51 +#define CLKID_RESET 52 +#define CLKID_NAND 53 +#define CLKID_DOS_PARSER 54 +#define CLKID_USB 55 +#define CLKID_VDIN1 56 +#define CLKID_AHB_ARB0 57 +#define CLKID_EFUSE 58 +#define CLKID_BOOT_ROM 59 +#define CLKID_AHB_DATA_BUS 60 +#define CLKID_AHB_CTRL_BUS 61 +#define CLKID_HDMI_INTR_SYNC 62 +#define CLKID_HDMI_PCLK 63 +#define CLKID_USB1_DDR_BRIDGE 64 +#define CLKID_USB0_DDR_BRIDGE 65 +#define CLKID_MMC_PCLK 66 +#define CLKID_DVIN 67 +#define CLKID_UART2 68 +#define CLKID_SANA 69 +#define CLKID_VPU_INTR 70 +#define CLKID_SEC_AHB_AHB3_BRIDGE 71 +#define CLKID_CLK81_A53 72 +#define CLKID_VCLK2_VENCI0 73 +#define CLKID_VCLK2_VENCI1 74 +#define CLKID_VCLK2_VENCP0 75 +#define CLKID_VCLK2_VENCP1 76 +#define CLKID_GCLK_VENCI_INT0 77 +#define CLKID_GCLK_VENCI_INT 78 +#define CLKID_DAC_CLK 79 +#define CLKID_AOCLK_GATE 80 +#define CLKID_IEC958_GATE 81 +#define CLKID_ENC480P 82 +#define CLKID_RNG1 83 +#define CLKID_GCLK_VENCI_INT1 84 +#define CLKID_VCLK2_VENCLMCC 85 +#define CLKID_VCLK2_VENCL 86 +#define CLKID_VCLK_OTHER 87 +#define CLKID_EDP 88 +#define CLKID_AO_MEDIA_CPU 89 +#define CLKID_AO_AHB_SRAM 90 +#define CLKID_AO_AHB_BUS 91 +#define CLKID_AO_IFACE 92 +#define CLKID_AO_I2C 93 + +#define NR_CLKS 94 + +/* include the CLKIDs that have been made part of the stable DT binding */ +#include + +#endif /* __GXBB_H */ diff --git a/include/dt-bindings/clock/gxbb-clkc.h b/include/dt-bindings/clock/gxbb-clkc.h new file mode 100644 index 000000000000..f889d80246cb --- /dev/null +++ b/include/dt-bindings/clock/gxbb-clkc.h @@ -0,0 +1,12 @@ +/* + * GXBB clock tree IDs + */ + +#ifndef __GXBB_CLKC_H +#define __GXBB_CLKC_H + +#define CLKID_CPUCLK 1 +#define CLKID_CLK81 12 +#define CLKID_ETH 36 + +#endif /* __GXBB_CLKC_H */ -- cgit v1.2.3 From 2e34c2ac16ee6574743c73caa3d796e307f028a6 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Thu, 23 Jun 2016 12:52:30 +0200 Subject: clk: tegra: Make sor_safe the parent of dpaux and dpaux1 It turns out that sor_safe, rather than pll_p, is the parent of the dpaux and dpaux1 clocks. Acked-by: Jon Hunter Tested-by: Jon Hunter Acked-by: Rhyland Klein Signed-off-by: Thierry Reding --- drivers/clk/tegra/clk-tegra210.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/clk/tegra/clk-tegra210.c b/drivers/clk/tegra/clk-tegra210.c index aab32af77aa2..fe295b4102ca 100644 --- a/drivers/clk/tegra/clk-tegra210.c +++ b/drivers/clk/tegra/clk-tegra210.c @@ -2466,11 +2466,11 @@ static __init void tegra210_periph_clk_init(void __iomem *clk_base, 1, 2); clks[TEGRA210_CLK_XUSB_SS_DIV2] = clk; - clk = tegra_clk_register_periph_fixed("dpaux", "pll_p", 0, clk_base, + clk = tegra_clk_register_periph_fixed("dpaux", "sor_safe", 0, clk_base, 1, 17, 181); clks[TEGRA210_CLK_DPAUX] = clk; - clk = tegra_clk_register_periph_fixed("dpaux1", "pll_p", 0, clk_base, + clk = tegra_clk_register_periph_fixed("dpaux1", "sor_safe", 0, clk_base, 1, 17, 207); clks[TEGRA210_CLK_DPAUX1] = clk; -- cgit v1.2.3 From 74d3ba0b6f1b22ed02ae16031c741822c9928793 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Thu, 23 Jun 2016 12:52:31 +0200 Subject: clk: tegra: Micro-optimize Tegra210 clock setup sor_safe being the parent of the dpaux and dpaux1 clocks, it's not only natural, but also slightly more efficient, to initialize it before its children. This avoids orphaning the dpaux and dpaux1 clocks only to get them reparented when the sor_safe clock is registered. Acked-by: Jon Hunter Tested-by: Jon Hunter Acked-by: Rhyland Klein Signed-off-by: Thierry Reding --- drivers/clk/tegra/clk-tegra210.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/clk/tegra/clk-tegra210.c b/drivers/clk/tegra/clk-tegra210.c index fe295b4102ca..b4df5c46642f 100644 --- a/drivers/clk/tegra/clk-tegra210.c +++ b/drivers/clk/tegra/clk-tegra210.c @@ -2466,6 +2466,10 @@ static __init void tegra210_periph_clk_init(void __iomem *clk_base, 1, 2); clks[TEGRA210_CLK_XUSB_SS_DIV2] = clk; + clk = tegra_clk_register_periph_fixed("sor_safe", "pll_p", 0, clk_base, + 1, 17, 222); + clks[TEGRA210_CLK_SOR_SAFE] = clk; + clk = tegra_clk_register_periph_fixed("dpaux", "sor_safe", 0, clk_base, 1, 17, 181); clks[TEGRA210_CLK_DPAUX] = clk; @@ -2474,10 +2478,6 @@ static __init void tegra210_periph_clk_init(void __iomem *clk_base, 1, 17, 207); clks[TEGRA210_CLK_DPAUX1] = clk; - clk = tegra_clk_register_periph_fixed("sor_safe", "pll_p", 0, clk_base, - 1, 17, 222); - clks[TEGRA210_CLK_SOR_SAFE] = clk; - /* pll_d_dsi_out */ clk = clk_register_gate(NULL, "pll_d_dsi_out", "pll_d_out0", 0, clk_base + PLLD_MISC0, 21, 0, &pll_d_lock); -- cgit v1.2.3 From 9e60de1cf2705b78d91eab1353cf778a7b7c348f Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Tue, 21 Jun 2016 15:53:14 -0700 Subject: clk: qcom: Remove gcc_aggre1_pnoc_ahb_clk from msm8996 This clk is critical to operation of the SoC and should never be turned off. Furthermore, there are no consumers of this clk so let's just delete it so things like eMMC work. Reported-by: Srinivas Kandagatla Fixes: b1e010c0730a ("clk: qcom: Add MSM8996 Global Clock Control (GCC) driver") Signed-off-by: Stephen Boyd --- drivers/clk/qcom/gcc-msm8996.c | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/drivers/clk/qcom/gcc-msm8996.c b/drivers/clk/qcom/gcc-msm8996.c index c9b96f318d9c..bbf732bbc3fd 100644 --- a/drivers/clk/qcom/gcc-msm8996.c +++ b/drivers/clk/qcom/gcc-msm8996.c @@ -2891,21 +2891,6 @@ static struct clk_branch gcc_smmu_aggre0_ahb_clk = { }, }; -static struct clk_branch gcc_aggre1_pnoc_ahb_clk = { - .halt_reg = 0x82014, - .clkr = { - .enable_reg = 0x82014, - .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data){ - .name = "gcc_aggre1_pnoc_ahb_clk", - .parent_names = (const char *[]){ "periph_noc_clk_src" }, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, - .ops = &clk_branch2_ops, - }, - }, -}; - static struct clk_branch gcc_aggre2_ufs_axi_clk = { .halt_reg = 0x83014, .clkr = { @@ -3308,7 +3293,6 @@ static struct clk_regmap *gcc_msm8996_clocks[] = { [GCC_AGGRE0_CNOC_AHB_CLK] = &gcc_aggre0_cnoc_ahb_clk.clkr, [GCC_SMMU_AGGRE0_AXI_CLK] = &gcc_smmu_aggre0_axi_clk.clkr, [GCC_SMMU_AGGRE0_AHB_CLK] = &gcc_smmu_aggre0_ahb_clk.clkr, - [GCC_AGGRE1_PNOC_AHB_CLK] = &gcc_aggre1_pnoc_ahb_clk.clkr, [GCC_AGGRE2_UFS_AXI_CLK] = &gcc_aggre2_ufs_axi_clk.clkr, [GCC_AGGRE2_USB3_AXI_CLK] = &gcc_aggre2_usb3_axi_clk.clkr, [GCC_QSPI_AHB_CLK] = &gcc_qspi_ahb_clk.clkr, -- cgit v1.2.3 From e81b87d22a8fed6bac24197972c9c394a2b92b5d Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 28 Jun 2016 13:25:04 +0200 Subject: clk: Provide notifier stubs when !COMMON_CLK The clk notifier symbols are hidden by COMMON_CLK. However on some platforms HAVE_CLK might be set while COMMON_CLK not which leads to compile test build errors like: $ make.cross ARCH=sh drivers/devfreq/tegra-devfreq.c: In function 'tegra_actmon_rate_notify_cb': >> drivers/devfreq/tegra-devfreq.c:391:16: error: 'POST_RATE_CHANGE' undeclared (first use in this function) if (action != POST_RATE_CHANGE) ^ drivers/devfreq/tegra-devfreq.c: In function 'tegra_devfreq_probe': >> drivers/devfreq/tegra-devfreq.c:654:8: error: implicit declaration of function 'clk_notifier_register' [-Werror=implicit-function-declaration] err = clk_notifier_register(tegra->emc_clock, &tegra->rate_change_nb); ^ Export the macros and data type declarations outside of COMMON_CLK ifdef and provide stubs to fix the compile testing. Reported-by: kbuild test robot Signed-off-by: Krzysztof Kozlowski Tested-by: Bartlomiej Zolnierkiewicz Signed-off-by: Stephen Boyd --- include/linux/clk.h | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/include/linux/clk.h b/include/linux/clk.h index 0df4a51e1a78..a89ba4e7af7a 100644 --- a/include/linux/clk.h +++ b/include/linux/clk.h @@ -20,8 +20,6 @@ struct device; struct clk; -#ifdef CONFIG_COMMON_CLK - /** * DOC: clk notifier callback types * @@ -78,6 +76,8 @@ struct clk_notifier_data { unsigned long new_rate; }; +#ifdef CONFIG_COMMON_CLK + /** * clk_notifier_register: register a clock rate-change notifier callback * @clk: clock whose rate we are interested in @@ -140,6 +140,18 @@ bool clk_is_match(const struct clk *p, const struct clk *q); #else +static inline int clk_notifier_register(struct clk *clk, + struct notifier_block *nb) +{ + return -ENOTSUPP; +} + +static inline int clk_notifier_unregister(struct clk *clk, + struct notifier_block *nb) +{ + return -ENOTSUPP; +} + static inline long clk_get_accuracy(struct clk *clk) { return -ENOTSUPP; -- cgit v1.2.3 From 15d68e8c2e95e8b62465c7cb3bc642784365ee1b Mon Sep 17 00:00:00 2001 From: Andrew Bresticker Date: Thu, 26 May 2016 12:41:31 -0400 Subject: clk: tegra: Initialize UTMI PLL when enabling PLLU Move the UTMI PLL initialization code form clk-tegra.c files into clk-pll.c. UTMI PLL was being configured and set in HW control right after registration. However, when the clock init_table is processed and child clks of PLLU are enabled, it will call in and enable PLLU as well, and initiate SW enabling sequence even though PLLU is already in HW control. This leads to getting UTMIPLL stuck with a SEQ_BUSY status. Doing the initialization once during pllu_enable means we configure it properly into HW control. A side effect of the commonization/localization of the UTMI PLL init code, is that it corrects some errors that were present for earlier generations. For instance, in clk-tegra124.c, it used to have: #define UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(x) (((x) & 0x1f) << 6) when the correct shift to use is present in the new version: #define UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(x) (((x) & 0x1f) << 27) which matches the Tegra124 TRM register definition. Signed-off-by: Andrew Bresticker [rklein: Merged in some later fixes for potential deadlocks] Signed-off-by: Rhyland Klein [treding: coding style bike-shedding, remove unused variable] Signed-off-by: Thierry Reding --- drivers/clk/tegra/clk-pll.c | 505 +++++++++++++++++++++++++++++++++++++++ drivers/clk/tegra/clk-tegra114.c | 156 +----------- drivers/clk/tegra/clk-tegra124.c | 156 +----------- drivers/clk/tegra/clk-tegra210.c | 182 +------------- drivers/clk/tegra/clk-tegra30.c | 113 +-------- drivers/clk/tegra/clk.h | 17 ++ 6 files changed, 531 insertions(+), 598 deletions(-) diff --git a/drivers/clk/tegra/clk-pll.c b/drivers/clk/tegra/clk-pll.c index 4e194ecc8d5e..b3855360d6bc 100644 --- a/drivers/clk/tegra/clk-pll.c +++ b/drivers/clk/tegra/clk-pll.c @@ -191,6 +191,53 @@ #define PLLSS_REF_SRC_SEL_SHIFT 25 #define PLLSS_REF_SRC_SEL_MASK (3 << PLLSS_REF_SRC_SEL_SHIFT) +#define UTMIP_PLL_CFG1 0x484 +#define UTMIP_PLL_CFG1_XTAL_FREQ_COUNT(x) (((x) & 0xfff) << 0) +#define UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(x) (((x) & 0x1f) << 27) +#define UTMIP_PLL_CFG1_FORCE_PLL_ACTIVE_POWERDOWN BIT(12) +#define UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN BIT(14) +#define UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERUP BIT(15) +#define UTMIP_PLL_CFG1_FORCE_PLLU_POWERDOWN BIT(16) +#define UTMIP_PLL_CFG1_FORCE_PLLU_POWERUP BIT(17) + +#define UTMIP_PLL_CFG2 0x488 +#define UTMIP_PLL_CFG2_STABLE_COUNT(x) (((x) & 0xfff) << 6) +#define UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(x) (((x) & 0x3f) << 18) +#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_A_POWERDOWN BIT(0) +#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_A_POWERUP BIT(1) +#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_B_POWERDOWN BIT(2) +#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_B_POWERUP BIT(3) +#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_C_POWERDOWN BIT(4) +#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_C_POWERUP BIT(5) +#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_D_POWERDOWN BIT(24) +#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_D_POWERUP BIT(25) +#define UTMIP_PLL_CFG2_PHY_XTAL_CLOCKEN BIT(30) + +#define UTMIPLL_HW_PWRDN_CFG0 0x52c +#define UTMIPLL_HW_PWRDN_CFG0_IDDQ_SWCTL BIT(0) +#define UTMIPLL_HW_PWRDN_CFG0_IDDQ_OVERRIDE BIT(1) +#define UTMIPLL_HW_PWRDN_CFG0_CLK_ENABLE_SWCTL BIT(2) +#define UTMIPLL_HW_PWRDN_CFG0_SEQ_IN_SWCTL BIT(4) +#define UTMIPLL_HW_PWRDN_CFG0_SEQ_RESET_INPUT_VALUE BIT(5) +#define UTMIPLL_HW_PWRDN_CFG0_USE_LOCKDET BIT(6) +#define UTMIPLL_HW_PWRDN_CFG0_SEQ_ENABLE BIT(24) +#define UTMIPLL_HW_PWRDN_CFG0_SEQ_START_STATE BIT(25) + +#define PLLU_HW_PWRDN_CFG0 0x530 +#define PLLU_HW_PWRDN_CFG0_CLK_SWITCH_SWCTL BIT(0) +#define PLLU_HW_PWRDN_CFG0_CLK_ENABLE_SWCTL BIT(2) +#define PLLU_HW_PWRDN_CFG0_USE_LOCKDET BIT(6) +#define PLLU_HW_PWRDN_CFG0_USE_SWITCH_DETECT BIT(7) +#define PLLU_HW_PWRDN_CFG0_SEQ_ENABLE BIT(24) +#define PLLU_HW_PWRDN_CFG0_IDDQ_PD_INCLUDE BIT(28) + +#define XUSB_PLL_CFG0 0x534 +#define XUSB_PLL_CFG0_UTMIPLL_LOCK_DLY 0x3ff +#define XUSB_PLL_CFG0_PLLU_LOCK_DLY (0x3ff << 14) + +#define PLLU_BASE_CLKENABLE_USB BIT(21) +#define PLLU_BASE_OVERRIDE BIT(24) + #define pll_readl(offset, p) readl_relaxed(p->clk_base + offset) #define pll_readl_base(p) pll_readl(p->params->base_reg, p) #define pll_readl_misc(p) pll_readl(p->params->misc_reg, p) @@ -973,6 +1020,133 @@ const struct clk_ops tegra_clk_plle_ops = { .enable = clk_plle_enable, }; +/* + * Structure defining the fields for USB UTMI clocks Parameters. + */ +struct utmi_clk_param { + /* Oscillator Frequency in Hz */ + u32 osc_frequency; + /* UTMIP PLL Enable Delay Count */ + u8 enable_delay_count; + /* UTMIP PLL Stable count */ + u8 stable_count; + /* UTMIP PLL Active delay count */ + u8 active_delay_count; + /* UTMIP PLL Xtal frequency count */ + u8 xtal_freq_count; +}; + +static const struct utmi_clk_param utmi_parameters[] = { + { + .osc_frequency = 13000000, .enable_delay_count = 0x02, + .stable_count = 0x33, .active_delay_count = 0x05, + .xtal_freq_count = 0x7f + }, { + .osc_frequency = 19200000, .enable_delay_count = 0x03, + .stable_count = 0x4b, .active_delay_count = 0x06, + .xtal_freq_count = 0xbb + }, { + .osc_frequency = 12000000, .enable_delay_count = 0x02, + .stable_count = 0x2f, .active_delay_count = 0x04, + .xtal_freq_count = 0x76 + }, { + .osc_frequency = 26000000, .enable_delay_count = 0x04, + .stable_count = 0x66, .active_delay_count = 0x09, + .xtal_freq_count = 0xfe + }, { + .osc_frequency = 16800000, .enable_delay_count = 0x03, + .stable_count = 0x41, .active_delay_count = 0x0a, + .xtal_freq_count = 0xa4 + }, { + .osc_frequency = 38400000, .enable_delay_count = 0x0, + .stable_count = 0x0, .active_delay_count = 0x6, + .xtal_freq_count = 0x80 + }, +}; + +static int clk_pllu_enable(struct clk_hw *hw) +{ + struct tegra_clk_pll *pll = to_clk_pll(hw); + struct clk_hw *pll_ref = clk_hw_get_parent(hw); + struct clk_hw *osc = clk_hw_get_parent(pll_ref); + const struct utmi_clk_param *params = NULL; + unsigned long flags = 0, input_rate; + unsigned int i; + int ret = 0; + u32 value; + + if (!osc) { + pr_err("%s: failed to get OSC clock\n", __func__); + return -EINVAL; + } + + input_rate = clk_hw_get_rate(osc); + + if (pll->lock) + spin_lock_irqsave(pll->lock, flags); + + _clk_pll_enable(hw); + + ret = clk_pll_wait_for_lock(pll); + if (ret < 0) + goto out; + + for (i = 0; i < ARRAY_SIZE(utmi_parameters); i++) { + if (input_rate == utmi_parameters[i].osc_frequency) { + params = &utmi_parameters[i]; + break; + } + } + + if (!params) { + pr_err("%s: unexpected input rate %lu Hz\n", __func__, + input_rate); + ret = -EINVAL; + goto out; + } + + value = pll_readl_base(pll); + value &= ~PLLU_BASE_OVERRIDE; + pll_writel_base(value, pll); + + value = readl_relaxed(pll->clk_base + UTMIP_PLL_CFG2); + /* Program UTMIP PLL stable and active counts */ + value &= ~UTMIP_PLL_CFG2_STABLE_COUNT(~0); + value |= UTMIP_PLL_CFG2_STABLE_COUNT(params->stable_count); + value &= ~UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(~0); + value |= UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(params->active_delay_count); + /* Remove power downs from UTMIP PLL control bits */ + value &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_A_POWERDOWN; + value &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_B_POWERDOWN; + value &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_C_POWERDOWN; + writel_relaxed(value, pll->clk_base + UTMIP_PLL_CFG2); + + value = readl_relaxed(pll->clk_base + UTMIP_PLL_CFG1); + /* Program UTMIP PLL delay and oscillator frequency counts */ + value &= ~UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(~0); + value |= UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(params->enable_delay_count); + value &= ~UTMIP_PLL_CFG1_XTAL_FREQ_COUNT(~0); + value |= UTMIP_PLL_CFG1_XTAL_FREQ_COUNT(params->xtal_freq_count); + /* Remove power downs from UTMIP PLL control bits */ + value &= ~UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN; + value &= ~UTMIP_PLL_CFG1_FORCE_PLL_ACTIVE_POWERDOWN; + value &= ~UTMIP_PLL_CFG1_FORCE_PLLU_POWERDOWN; + writel_relaxed(value, pll->clk_base + UTMIP_PLL_CFG1); + +out: + if (pll->lock) + spin_unlock_irqrestore(pll->lock, flags); + + return ret; +} + +static const struct clk_ops tegra_clk_pllu_ops = { + .is_enabled = clk_pll_is_enabled, + .enable = clk_pllu_enable, + .disable = clk_pll_disable, + .recalc_rate = clk_pll_recalc_rate, +}; + static int _pll_fixed_mdiv(struct tegra_clk_pll_params *pll_params, unsigned long parent_rate) { @@ -1505,6 +1679,112 @@ static void clk_plle_tegra114_disable(struct clk_hw *hw) if (pll->lock) spin_unlock_irqrestore(pll->lock, flags); } + +static int clk_pllu_tegra114_enable(struct clk_hw *hw) +{ + struct tegra_clk_pll *pll = to_clk_pll(hw); + const struct utmi_clk_param *params = NULL; + struct clk *osc = __clk_lookup("osc"); + unsigned long flags = 0, input_rate; + unsigned int i; + int ret = 0; + u32 value; + + if (!osc) { + pr_err("%s: failed to get OSC clock\n", __func__); + return -EINVAL; + } + + input_rate = clk_hw_get_rate(__clk_get_hw(osc)); + + if (pll->lock) + spin_lock_irqsave(pll->lock, flags); + + _clk_pll_enable(hw); + + ret = clk_pll_wait_for_lock(pll); + if (ret < 0) + goto out; + + for (i = 0; i < ARRAY_SIZE(utmi_parameters); i++) { + if (input_rate == utmi_parameters[i].osc_frequency) { + params = &utmi_parameters[i]; + break; + } + } + + if (!params) { + pr_err("%s: unexpected input rate %lu Hz\n", __func__, + input_rate); + ret = -EINVAL; + goto out; + } + + value = pll_readl_base(pll); + value &= ~PLLU_BASE_OVERRIDE; + pll_writel_base(value, pll); + + value = readl_relaxed(pll->clk_base + UTMIP_PLL_CFG2); + /* Program UTMIP PLL stable and active counts */ + value &= ~UTMIP_PLL_CFG2_STABLE_COUNT(~0); + value |= UTMIP_PLL_CFG2_STABLE_COUNT(params->stable_count); + value &= ~UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(~0); + value |= UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(params->active_delay_count); + /* Remove power downs from UTMIP PLL control bits */ + value &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_A_POWERDOWN; + value &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_B_POWERDOWN; + value &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_C_POWERDOWN; + writel_relaxed(value, pll->clk_base + UTMIP_PLL_CFG2); + + value = readl_relaxed(pll->clk_base + UTMIP_PLL_CFG1); + /* Program UTMIP PLL delay and oscillator frequency counts */ + value &= ~UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(~0); + value |= UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(params->enable_delay_count); + value &= ~UTMIP_PLL_CFG1_XTAL_FREQ_COUNT(~0); + value |= UTMIP_PLL_CFG1_XTAL_FREQ_COUNT(params->xtal_freq_count); + /* Remove power downs from UTMIP PLL control bits */ + value &= ~UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN; + value &= ~UTMIP_PLL_CFG1_FORCE_PLL_ACTIVE_POWERDOWN; + value &= ~UTMIP_PLL_CFG1_FORCE_PLLU_POWERUP; + value &= ~UTMIP_PLL_CFG1_FORCE_PLLU_POWERDOWN; + writel_relaxed(value, pll->clk_base + UTMIP_PLL_CFG1); + + /* Setup HW control of UTMIPLL */ + value = readl_relaxed(pll->clk_base + UTMIPLL_HW_PWRDN_CFG0); + value |= UTMIPLL_HW_PWRDN_CFG0_USE_LOCKDET; + value &= ~UTMIPLL_HW_PWRDN_CFG0_CLK_ENABLE_SWCTL; + value |= UTMIPLL_HW_PWRDN_CFG0_SEQ_START_STATE; + writel_relaxed(value, pll->clk_base + UTMIPLL_HW_PWRDN_CFG0); + + value = readl_relaxed(pll->clk_base + UTMIP_PLL_CFG1); + value &= ~UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERUP; + value &= ~UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN; + writel_relaxed(value, pll->clk_base + UTMIP_PLL_CFG1); + + udelay(1); + + /* + * Setup SW override of UTMIPLL assuming USB2.0 ports are assigned + * to USB2 + */ + value = readl_relaxed(pll->clk_base + UTMIPLL_HW_PWRDN_CFG0); + value |= UTMIPLL_HW_PWRDN_CFG0_IDDQ_SWCTL; + value &= ~UTMIPLL_HW_PWRDN_CFG0_IDDQ_OVERRIDE; + writel_relaxed(value, pll->clk_base + UTMIPLL_HW_PWRDN_CFG0); + + udelay(1); + + /* Enable HW control of UTMIPLL */ + value = readl_relaxed(pll->clk_base + UTMIPLL_HW_PWRDN_CFG0); + value |= UTMIPLL_HW_PWRDN_CFG0_SEQ_ENABLE; + writel_relaxed(value, pll->clk_base + UTMIPLL_HW_PWRDN_CFG0); + +out: + if (pll->lock) + spin_unlock_irqrestore(pll->lock, flags); + + return ret; +} #endif static struct tegra_clk_pll *_tegra_init_pll(void __iomem *clk_base, @@ -1614,6 +1894,27 @@ struct clk *tegra_clk_register_plle(const char *name, const char *parent_name, return clk; } +struct clk *tegra_clk_register_pllu(const char *name, const char *parent_name, + void __iomem *clk_base, unsigned long flags, + struct tegra_clk_pll_params *pll_params, spinlock_t *lock) +{ + struct tegra_clk_pll *pll; + struct clk *clk; + + pll_params->flags |= TEGRA_PLLU; + + pll = _tegra_init_pll(clk_base, NULL, pll_params, lock); + if (IS_ERR(pll)) + return ERR_CAST(pll); + + clk = _tegra_clk_register_pll(pll, name, parent_name, flags, + &tegra_clk_pllu_ops); + if (IS_ERR(clk)) + kfree(pll); + + return clk; +} + #if defined(CONFIG_ARCH_TEGRA_114_SOC) || \ defined(CONFIG_ARCH_TEGRA_124_SOC) || \ defined(CONFIG_ARCH_TEGRA_132_SOC) || \ @@ -1652,6 +1953,12 @@ static const struct clk_ops tegra_clk_plle_tegra114_ops = { .recalc_rate = clk_pll_recalc_rate, }; +static const struct clk_ops tegra_clk_pllu_tegra114_ops = { + .is_enabled = clk_pll_is_enabled, + .enable = clk_pllu_tegra114_enable, + .disable = clk_pll_disable, + .recalc_rate = clk_pll_recalc_rate, +}; struct clk *tegra_clk_register_pllxc(const char *name, const char *parent_name, void __iomem *clk_base, void __iomem *pmc, @@ -1919,6 +2226,29 @@ struct clk *tegra_clk_register_plle_tegra114(const char *name, return clk; } + +struct clk * +tegra_clk_register_pllu_tegra114(const char *name, const char *parent_name, + void __iomem *clk_base, unsigned long flags, + struct tegra_clk_pll_params *pll_params, + spinlock_t *lock) +{ + struct tegra_clk_pll *pll; + struct clk *clk; + + pll_params->flags |= TEGRA_PLLU; + + pll = _tegra_init_pll(clk_base, NULL, pll_params, lock); + if (IS_ERR(pll)) + return ERR_CAST(pll); + + clk = _tegra_clk_register_pll(pll, name, parent_name, flags, + &tegra_clk_pllu_tegra114_ops); + if (IS_ERR(clk)) + kfree(pll); + + return clk; +} #endif #if defined(CONFIG_ARCH_TEGRA_124_SOC) || defined(CONFIG_ARCH_TEGRA_132_SOC) @@ -2187,6 +2517,152 @@ static int clk_plle_tegra210_is_enabled(struct clk_hw *hw) return val & PLLE_BASE_ENABLE ? 1 : 0; } +static int clk_pllu_tegra210_enable(struct clk_hw *hw) +{ + struct tegra_clk_pll *pll = to_clk_pll(hw); + struct clk_hw *pll_ref = clk_hw_get_parent(hw); + struct clk_hw *osc = clk_hw_get_parent(pll_ref); + const struct utmi_clk_param *params = NULL; + unsigned long flags = 0, input_rate; + unsigned int i; + int ret = 0; + u32 value; + + if (!osc) { + pr_err("%s: failed to get OSC clock\n", __func__); + return -EINVAL; + } + + input_rate = clk_hw_get_rate(osc); + + if (pll->lock) + spin_lock_irqsave(pll->lock, flags); + + _clk_pll_enable(hw); + + ret = clk_pll_wait_for_lock(pll); + if (ret < 0) + goto out; + + for (i = 0; i < ARRAY_SIZE(utmi_parameters); i++) { + if (input_rate == utmi_parameters[i].osc_frequency) { + params = &utmi_parameters[i]; + break; + } + } + + if (!params) { + pr_err("%s: unexpected input rate %lu Hz\n", __func__, + input_rate); + ret = -EINVAL; + goto out; + } + + value = pll_readl_base(pll); + value &= ~PLLU_BASE_OVERRIDE; + pll_writel_base(value, pll); + + /* Put PLLU under HW control */ + value = readl_relaxed(pll->clk_base + PLLU_HW_PWRDN_CFG0); + value |= PLLU_HW_PWRDN_CFG0_IDDQ_PD_INCLUDE | + PLLU_HW_PWRDN_CFG0_USE_SWITCH_DETECT | + PLLU_HW_PWRDN_CFG0_USE_LOCKDET; + value &= ~(PLLU_HW_PWRDN_CFG0_CLK_ENABLE_SWCTL | + PLLU_HW_PWRDN_CFG0_CLK_SWITCH_SWCTL); + writel_relaxed(value, pll->clk_base + PLLU_HW_PWRDN_CFG0); + + value = readl_relaxed(pll->clk_base + XUSB_PLL_CFG0); + value &= ~XUSB_PLL_CFG0_PLLU_LOCK_DLY; + writel_relaxed(value, pll->clk_base + XUSB_PLL_CFG0); + + udelay(1); + + value = readl_relaxed(pll->clk_base + PLLU_HW_PWRDN_CFG0); + value |= PLLU_HW_PWRDN_CFG0_SEQ_ENABLE; + writel_relaxed(value, pll->clk_base + PLLU_HW_PWRDN_CFG0); + + udelay(1); + + /* Disable PLLU clock branch to UTMIPLL since it uses OSC */ + value = pll_readl_base(pll); + value &= ~PLLU_BASE_CLKENABLE_USB; + pll_writel_base(value, pll); + + value = readl_relaxed(pll->clk_base + UTMIPLL_HW_PWRDN_CFG0); + if (value & UTMIPLL_HW_PWRDN_CFG0_SEQ_ENABLE) { + pr_debug("UTMIPLL already enabled\n"); + goto out; + } + + value &= ~UTMIPLL_HW_PWRDN_CFG0_IDDQ_OVERRIDE; + writel_relaxed(value, pll->clk_base + UTMIPLL_HW_PWRDN_CFG0); + + /* Program UTMIP PLL stable and active counts */ + value = readl_relaxed(pll->clk_base + UTMIP_PLL_CFG2); + value &= ~UTMIP_PLL_CFG2_STABLE_COUNT(~0); + value |= UTMIP_PLL_CFG2_STABLE_COUNT(params->stable_count); + value &= ~UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(~0); + value |= UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(params->active_delay_count); + value |= UTMIP_PLL_CFG2_PHY_XTAL_CLOCKEN; + writel_relaxed(value, pll->clk_base + UTMIP_PLL_CFG2); + + /* Program UTMIP PLL delay and oscillator frequency counts */ + value = readl_relaxed(pll->clk_base + UTMIP_PLL_CFG1); + value &= ~UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(~0); + value |= UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(params->enable_delay_count); + value &= ~UTMIP_PLL_CFG1_XTAL_FREQ_COUNT(~0); + value |= UTMIP_PLL_CFG1_XTAL_FREQ_COUNT(params->xtal_freq_count); + writel_relaxed(value, pll->clk_base + UTMIP_PLL_CFG1); + + /* Remove power downs from UTMIP PLL control bits */ + value = readl_relaxed(pll->clk_base + UTMIP_PLL_CFG1); + value &= ~UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN; + value |= UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERUP; + writel(value, pll->clk_base + UTMIP_PLL_CFG1); + + udelay(1); + + /* Enable samplers for SNPS, XUSB_HOST, XUSB_DEV */ + value = readl_relaxed(pll->clk_base + UTMIP_PLL_CFG2); + value |= UTMIP_PLL_CFG2_FORCE_PD_SAMP_A_POWERUP; + value |= UTMIP_PLL_CFG2_FORCE_PD_SAMP_B_POWERUP; + value |= UTMIP_PLL_CFG2_FORCE_PD_SAMP_D_POWERUP; + value &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_A_POWERDOWN; + value &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_B_POWERDOWN; + value &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_D_POWERDOWN; + writel_relaxed(value, pll->clk_base + UTMIP_PLL_CFG2); + + /* Setup HW control of UTMIPLL */ + value = readl_relaxed(pll->clk_base + UTMIP_PLL_CFG1); + value &= ~UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERUP; + value &= ~UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN; + writel_relaxed(value, pll->clk_base + UTMIP_PLL_CFG1); + + value = readl_relaxed(pll->clk_base + UTMIPLL_HW_PWRDN_CFG0); + value |= UTMIPLL_HW_PWRDN_CFG0_USE_LOCKDET; + value &= ~UTMIPLL_HW_PWRDN_CFG0_CLK_ENABLE_SWCTL; + writel_relaxed(value, pll->clk_base + UTMIPLL_HW_PWRDN_CFG0); + + udelay(1); + + value = readl_relaxed(pll->clk_base + XUSB_PLL_CFG0); + value &= ~XUSB_PLL_CFG0_UTMIPLL_LOCK_DLY; + writel_relaxed(value, pll->clk_base + XUSB_PLL_CFG0); + + udelay(1); + + /* Enable HW control of UTMIPLL */ + value = readl_relaxed(pll->clk_base + UTMIPLL_HW_PWRDN_CFG0); + value |= UTMIPLL_HW_PWRDN_CFG0_SEQ_ENABLE; + writel_relaxed(value, pll->clk_base + UTMIPLL_HW_PWRDN_CFG0); + +out: + if (pll->lock) + spin_unlock_irqrestore(pll->lock, flags); + + return ret; +} + static const struct clk_ops tegra_clk_plle_tegra210_ops = { .is_enabled = clk_plle_tegra210_is_enabled, .enable = clk_plle_tegra210_enable, @@ -2194,6 +2670,13 @@ static const struct clk_ops tegra_clk_plle_tegra210_ops = { .recalc_rate = clk_pll_recalc_rate, }; +static const struct clk_ops tegra_clk_pllu_tegra210_ops = { + .is_enabled = clk_pll_is_enabled, + .enable = clk_pllu_tegra210_enable, + .disable = clk_pll_disable, + .recalc_rate = clk_pllre_recalc_rate, +}; + struct clk *tegra_clk_register_plle_tegra210(const char *name, const char *parent_name, void __iomem *clk_base, unsigned long flags, @@ -2434,4 +2917,26 @@ struct clk *tegra_clk_register_pllmb(const char *name, const char *parent_name, return clk; } + +struct clk *tegra_clk_register_pllu_tegra210(const char *name, + const char *parent_name, void __iomem *clk_base, + unsigned long flags, struct tegra_clk_pll_params *pll_params, + spinlock_t *lock) +{ + struct tegra_clk_pll *pll; + struct clk *clk; + + pll_params->flags |= TEGRA_PLLU; + + pll = _tegra_init_pll(clk_base, NULL, pll_params, lock); + if (IS_ERR(pll)) + return ERR_CAST(pll); + + clk = _tegra_clk_register_pll(pll, name, parent_name, flags, + &tegra_clk_pllu_tegra210_ops); + if (IS_ERR(clk)) + kfree(pll); + + return clk; +} #endif diff --git a/drivers/clk/tegra/clk-tegra114.c b/drivers/clk/tegra/clk-tegra114.c index b78054fac0a8..64da7b79a6e4 100644 --- a/drivers/clk/tegra/clk-tegra114.c +++ b/drivers/clk/tegra/clk-tegra114.c @@ -113,32 +113,6 @@ #define CCLKG_BURST_POLICY 0x368 -#define UTMIP_PLL_CFG2 0x488 -#define UTMIP_PLL_CFG2_STABLE_COUNT(x) (((x) & 0xffff) << 6) -#define UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(x) (((x) & 0x3f) << 18) -#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_A_POWERDOWN BIT(0) -#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_B_POWERDOWN BIT(2) -#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_C_POWERDOWN BIT(4) - -#define UTMIP_PLL_CFG1 0x484 -#define UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(x) (((x) & 0x1f) << 6) -#define UTMIP_PLL_CFG1_XTAL_FREQ_COUNT(x) (((x) & 0xfff) << 0) -#define UTMIP_PLL_CFG1_FORCE_PLLU_POWERUP BIT(17) -#define UTMIP_PLL_CFG1_FORCE_PLLU_POWERDOWN BIT(16) -#define UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERUP BIT(15) -#define UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN BIT(14) -#define UTMIP_PLL_CFG1_FORCE_PLL_ACTIVE_POWERDOWN BIT(12) - -#define UTMIPLL_HW_PWRDN_CFG0 0x52c -#define UTMIPLL_HW_PWRDN_CFG0_SEQ_START_STATE BIT(25) -#define UTMIPLL_HW_PWRDN_CFG0_SEQ_ENABLE BIT(24) -#define UTMIPLL_HW_PWRDN_CFG0_USE_LOCKDET BIT(6) -#define UTMIPLL_HW_PWRDN_CFG0_SEQ_RESET_INPUT_VALUE BIT(5) -#define UTMIPLL_HW_PWRDN_CFG0_SEQ_IN_SWCTL BIT(4) -#define UTMIPLL_HW_PWRDN_CFG0_CLK_ENABLE_SWCTL BIT(2) -#define UTMIPLL_HW_PWRDN_CFG0_IDDQ_OVERRIDE BIT(1) -#define UTMIPLL_HW_PWRDN_CFG0_IDDQ_SWCTL BIT(0) - #define CLK_SOURCE_CSITE 0x1d4 #define CLK_SOURCE_EMC 0x19c @@ -649,43 +623,6 @@ static unsigned long tegra114_input_freq[] = { #define MASK(x) (BIT(x) - 1) -struct utmi_clk_param { - /* Oscillator Frequency in KHz */ - u32 osc_frequency; - /* UTMIP PLL Enable Delay Count */ - u8 enable_delay_count; - /* UTMIP PLL Stable count */ - u8 stable_count; - /* UTMIP PLL Active delay count */ - u8 active_delay_count; - /* UTMIP PLL Xtal frequency count */ - u8 xtal_freq_count; -}; - -static const struct utmi_clk_param utmi_parameters[] = { - { - .osc_frequency = 13000000, .enable_delay_count = 0x02, - .stable_count = 0x33, .active_delay_count = 0x05, - .xtal_freq_count = 0x7f - }, { - .osc_frequency = 19200000, .enable_delay_count = 0x03, - .stable_count = 0x4b, .active_delay_count = 0x06, - .xtal_freq_count = 0xbb - }, { - .osc_frequency = 12000000, .enable_delay_count = 0x02, - .stable_count = 0x2f, .active_delay_count = 0x04, - .xtal_freq_count = 0x76 - }, { - .osc_frequency = 26000000, .enable_delay_count = 0x04, - .stable_count = 0x66, .active_delay_count = 0x09, - .xtal_freq_count = 0xfe - }, { - .osc_frequency = 16800000, .enable_delay_count = 0x03, - .stable_count = 0x41, .active_delay_count = 0x0a, - .xtal_freq_count = 0xa4 - }, -}; - /* peripheral mux definitions */ static const char *mux_plld_out0_plld2_out0[] = { @@ -986,92 +923,9 @@ static void __init tegra114_fixed_clk_init(void __iomem *clk_base) } -static __init void tegra114_utmi_param_configure(void __iomem *clk_base) -{ - unsigned int i; - u32 reg; - - for (i = 0; i < ARRAY_SIZE(utmi_parameters); i++) { - if (osc_freq == utmi_parameters[i].osc_frequency) - break; - } - - if (i >= ARRAY_SIZE(utmi_parameters)) { - pr_err("%s: Unexpected oscillator freq %lu\n", __func__, - osc_freq); - return; - } - - reg = readl_relaxed(clk_base + UTMIP_PLL_CFG2); - - /* Program UTMIP PLL stable and active counts */ - /* [FIXME] arclk_rst.h says WRONG! This should be 1ms -> 0x50 Check! */ - reg &= ~UTMIP_PLL_CFG2_STABLE_COUNT(~0); - reg |= UTMIP_PLL_CFG2_STABLE_COUNT(utmi_parameters[i].stable_count); - - reg &= ~UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(~0); - - reg |= UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(utmi_parameters[i]. - active_delay_count); - - /* Remove power downs from UTMIP PLL control bits */ - reg &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_A_POWERDOWN; - reg &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_B_POWERDOWN; - reg &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_C_POWERDOWN; - - writel_relaxed(reg, clk_base + UTMIP_PLL_CFG2); - - /* Program UTMIP PLL delay and oscillator frequency counts */ - reg = readl_relaxed(clk_base + UTMIP_PLL_CFG1); - reg &= ~UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(~0); - - reg |= UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(utmi_parameters[i]. - enable_delay_count); - - reg &= ~UTMIP_PLL_CFG1_XTAL_FREQ_COUNT(~0); - reg |= UTMIP_PLL_CFG1_XTAL_FREQ_COUNT(utmi_parameters[i]. - xtal_freq_count); - - /* Remove power downs from UTMIP PLL control bits */ - reg &= ~UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN; - reg &= ~UTMIP_PLL_CFG1_FORCE_PLL_ACTIVE_POWERDOWN; - reg &= ~UTMIP_PLL_CFG1_FORCE_PLLU_POWERUP; - reg &= ~UTMIP_PLL_CFG1_FORCE_PLLU_POWERDOWN; - writel_relaxed(reg, clk_base + UTMIP_PLL_CFG1); - - /* Setup HW control of UTMIPLL */ - reg = readl_relaxed(clk_base + UTMIPLL_HW_PWRDN_CFG0); - reg |= UTMIPLL_HW_PWRDN_CFG0_USE_LOCKDET; - reg &= ~UTMIPLL_HW_PWRDN_CFG0_CLK_ENABLE_SWCTL; - reg |= UTMIPLL_HW_PWRDN_CFG0_SEQ_START_STATE; - writel_relaxed(reg, clk_base + UTMIPLL_HW_PWRDN_CFG0); - - reg = readl_relaxed(clk_base + UTMIP_PLL_CFG1); - reg &= ~UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERUP; - reg &= ~UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN; - writel_relaxed(reg, clk_base + UTMIP_PLL_CFG1); - - udelay(1); - - /* Setup SW override of UTMIPLL assuming USB2.0 - ports are assigned to USB2 */ - reg = readl_relaxed(clk_base + UTMIPLL_HW_PWRDN_CFG0); - reg |= UTMIPLL_HW_PWRDN_CFG0_IDDQ_SWCTL; - reg &= ~UTMIPLL_HW_PWRDN_CFG0_IDDQ_OVERRIDE; - writel_relaxed(reg, clk_base + UTMIPLL_HW_PWRDN_CFG0); - - udelay(1); - - /* Enable HW control UTMIPLL */ - reg = readl_relaxed(clk_base + UTMIPLL_HW_PWRDN_CFG0); - reg |= UTMIPLL_HW_PWRDN_CFG0_SEQ_ENABLE; - writel_relaxed(reg, clk_base + UTMIPLL_HW_PWRDN_CFG0); -} - static void __init tegra114_pll_init(void __iomem *clk_base, void __iomem *pmc) { - u32 val; struct clk *clk; /* PLLC */ @@ -1118,16 +972,10 @@ static void __init tegra114_pll_init(void __iomem *clk_base, CLK_SET_RATE_PARENT, 1, 1); /* PLLU */ - val = readl(clk_base + pll_u_params.base_reg); - val &= ~BIT(24); /* disable PLLU_OVERRIDE */ - writel(val, clk_base + pll_u_params.base_reg); - - clk = tegra_clk_register_pll("pll_u", "pll_ref", clk_base, pmc, 0, - &pll_u_params, &pll_u_lock); + clk = tegra_clk_register_pllu_tegra114("pll_u", "pll_ref", clk_base, 0, + &pll_u_params, &pll_u_lock); clks[TEGRA114_CLK_PLL_U] = clk; - tegra114_utmi_param_configure(clk_base); - /* PLLU_480M */ clk = clk_register_gate(NULL, "pll_u_480M", "pll_u", CLK_SET_RATE_PARENT, clk_base + PLLU_BASE, diff --git a/drivers/clk/tegra/clk-tegra124.c b/drivers/clk/tegra/clk-tegra124.c index f4fbbf16a056..a112d3d2bff1 100644 --- a/drivers/clk/tegra/clk-tegra124.c +++ b/drivers/clk/tegra/clk-tegra124.c @@ -99,32 +99,6 @@ #define CCLKG_BURST_POLICY 0x368 -#define UTMIP_PLL_CFG2 0x488 -#define UTMIP_PLL_CFG2_STABLE_COUNT(x) (((x) & 0xffff) << 6) -#define UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(x) (((x) & 0x3f) << 18) -#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_A_POWERDOWN BIT(0) -#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_B_POWERDOWN BIT(2) -#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_C_POWERDOWN BIT(4) - -#define UTMIP_PLL_CFG1 0x484 -#define UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(x) (((x) & 0x1f) << 6) -#define UTMIP_PLL_CFG1_XTAL_FREQ_COUNT(x) (((x) & 0xfff) << 0) -#define UTMIP_PLL_CFG1_FORCE_PLLU_POWERUP BIT(17) -#define UTMIP_PLL_CFG1_FORCE_PLLU_POWERDOWN BIT(16) -#define UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERUP BIT(15) -#define UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN BIT(14) -#define UTMIP_PLL_CFG1_FORCE_PLL_ACTIVE_POWERDOWN BIT(12) - -#define UTMIPLL_HW_PWRDN_CFG0 0x52c -#define UTMIPLL_HW_PWRDN_CFG0_SEQ_START_STATE BIT(25) -#define UTMIPLL_HW_PWRDN_CFG0_SEQ_ENABLE BIT(24) -#define UTMIPLL_HW_PWRDN_CFG0_USE_LOCKDET BIT(6) -#define UTMIPLL_HW_PWRDN_CFG0_SEQ_RESET_INPUT_VALUE BIT(5) -#define UTMIPLL_HW_PWRDN_CFG0_SEQ_IN_SWCTL BIT(4) -#define UTMIPLL_HW_PWRDN_CFG0_CLK_ENABLE_SWCTL BIT(2) -#define UTMIPLL_HW_PWRDN_CFG0_IDDQ_OVERRIDE BIT(1) -#define UTMIPLL_HW_PWRDN_CFG0_IDDQ_SWCTL BIT(0) - /* Tegra CPU clock and reset control regs */ #define CLK_RST_CONTROLLER_CPU_CMPLX_STATUS 0x470 @@ -764,43 +738,6 @@ static struct tegra_clk_pll_params pll_u_params = { TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE, }; -struct utmi_clk_param { - /* Oscillator Frequency in KHz */ - u32 osc_frequency; - /* UTMIP PLL Enable Delay Count */ - u8 enable_delay_count; - /* UTMIP PLL Stable count */ - u8 stable_count; - /* UTMIP PLL Active delay count */ - u8 active_delay_count; - /* UTMIP PLL Xtal frequency count */ - u8 xtal_freq_count; -}; - -static const struct utmi_clk_param utmi_parameters[] = { - { - .osc_frequency = 13000000, .enable_delay_count = 0x02, - .stable_count = 0x33, .active_delay_count = 0x05, - .xtal_freq_count = 0x7f - }, { - .osc_frequency = 19200000, .enable_delay_count = 0x03, - .stable_count = 0x4b, .active_delay_count = 0x06, - .xtal_freq_count = 0xbb - }, { - .osc_frequency = 12000000, .enable_delay_count = 0x02, - .stable_count = 0x2f, .active_delay_count = 0x04, - .xtal_freq_count = 0x76 - }, { - .osc_frequency = 26000000, .enable_delay_count = 0x04, - .stable_count = 0x66, .active_delay_count = 0x09, - .xtal_freq_count = 0xfe - }, { - .osc_frequency = 16800000, .enable_delay_count = 0x03, - .stable_count = 0x41, .active_delay_count = 0x0a, - .xtal_freq_count = 0xa4 - }, -}; - static struct tegra_clk tegra124_clks[tegra_clk_max] __initdata = { [tegra_clk_ispb] = { .dt_id = TEGRA124_CLK_ISPB, .present = true }, [tegra_clk_rtc] = { .dt_id = TEGRA124_CLK_RTC, .present = true }, @@ -1063,88 +1000,6 @@ static struct tegra_devclk devclks[] __initdata = { static struct clk **clks; -static void tegra124_utmi_param_configure(void __iomem *clk_base) -{ - unsigned int i; - u32 reg; - - for (i = 0; i < ARRAY_SIZE(utmi_parameters); i++) { - if (osc_freq == utmi_parameters[i].osc_frequency) - break; - } - - if (i >= ARRAY_SIZE(utmi_parameters)) { - pr_err("%s: Unexpected oscillator freq %lu\n", __func__, - osc_freq); - return; - } - - reg = readl_relaxed(clk_base + UTMIP_PLL_CFG2); - - /* Program UTMIP PLL stable and active counts */ - /* [FIXME] arclk_rst.h says WRONG! This should be 1ms -> 0x50 Check! */ - reg &= ~UTMIP_PLL_CFG2_STABLE_COUNT(~0); - reg |= UTMIP_PLL_CFG2_STABLE_COUNT(utmi_parameters[i].stable_count); - - reg &= ~UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(~0); - - reg |= UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(utmi_parameters[i]. - active_delay_count); - - /* Remove power downs from UTMIP PLL control bits */ - reg &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_A_POWERDOWN; - reg &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_B_POWERDOWN; - reg &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_C_POWERDOWN; - - writel_relaxed(reg, clk_base + UTMIP_PLL_CFG2); - - /* Program UTMIP PLL delay and oscillator frequency counts */ - reg = readl_relaxed(clk_base + UTMIP_PLL_CFG1); - reg &= ~UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(~0); - - reg |= UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(utmi_parameters[i]. - enable_delay_count); - - reg &= ~UTMIP_PLL_CFG1_XTAL_FREQ_COUNT(~0); - reg |= UTMIP_PLL_CFG1_XTAL_FREQ_COUNT(utmi_parameters[i]. - xtal_freq_count); - - /* Remove power downs from UTMIP PLL control bits */ - reg &= ~UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN; - reg &= ~UTMIP_PLL_CFG1_FORCE_PLL_ACTIVE_POWERDOWN; - reg &= ~UTMIP_PLL_CFG1_FORCE_PLLU_POWERUP; - reg &= ~UTMIP_PLL_CFG1_FORCE_PLLU_POWERDOWN; - writel_relaxed(reg, clk_base + UTMIP_PLL_CFG1); - - /* Setup HW control of UTMIPLL */ - reg = readl_relaxed(clk_base + UTMIPLL_HW_PWRDN_CFG0); - reg |= UTMIPLL_HW_PWRDN_CFG0_USE_LOCKDET; - reg &= ~UTMIPLL_HW_PWRDN_CFG0_CLK_ENABLE_SWCTL; - reg |= UTMIPLL_HW_PWRDN_CFG0_SEQ_START_STATE; - writel_relaxed(reg, clk_base + UTMIPLL_HW_PWRDN_CFG0); - - reg = readl_relaxed(clk_base + UTMIP_PLL_CFG1); - reg &= ~UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERUP; - reg &= ~UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN; - writel_relaxed(reg, clk_base + UTMIP_PLL_CFG1); - - udelay(1); - - /* Setup SW override of UTMIPLL assuming USB2.0 - ports are assigned to USB2 */ - reg = readl_relaxed(clk_base + UTMIPLL_HW_PWRDN_CFG0); - reg |= UTMIPLL_HW_PWRDN_CFG0_IDDQ_SWCTL; - reg &= ~UTMIPLL_HW_PWRDN_CFG0_IDDQ_OVERRIDE; - writel_relaxed(reg, clk_base + UTMIPLL_HW_PWRDN_CFG0); - - udelay(1); - - /* Enable HW control UTMIPLL */ - reg = readl_relaxed(clk_base + UTMIPLL_HW_PWRDN_CFG0); - reg |= UTMIPLL_HW_PWRDN_CFG0_SEQ_ENABLE; - writel_relaxed(reg, clk_base + UTMIPLL_HW_PWRDN_CFG0); -} - static __init void tegra124_periph_clk_init(void __iomem *clk_base, void __iomem *pmc_base) { @@ -1195,7 +1050,6 @@ static __init void tegra124_periph_clk_init(void __iomem *clk_base, static void __init tegra124_pll_init(void __iomem *clk_base, void __iomem *pmc) { - u32 val; struct clk *clk; /* PLLC */ @@ -1256,17 +1110,11 @@ static void __init tegra124_pll_init(void __iomem *clk_base, clks[TEGRA124_CLK_PLL_M_UD] = clk; /* PLLU */ - val = readl(clk_base + pll_u_params.base_reg); - val &= ~BIT(24); /* disable PLLU_OVERRIDE */ - writel(val, clk_base + pll_u_params.base_reg); - - clk = tegra_clk_register_pll("pll_u", "pll_ref", clk_base, pmc, 0, - &pll_u_params, &pll_u_lock); + clk = tegra_clk_register_pllu_tegra114("pll_u", "pll_ref", clk_base, 0, + &pll_u_params, &pll_u_lock); clk_register_clkdev(clk, "pll_u", NULL); clks[TEGRA124_CLK_PLL_U] = clk; - tegra124_utmi_param_configure(clk_base); - /* PLLU_480M */ clk = clk_register_gate(NULL, "pll_u_480M", "pll_u", CLK_SET_RATE_PARENT, clk_base + PLLU_BASE, diff --git a/drivers/clk/tegra/clk-tegra210.c b/drivers/clk/tegra/clk-tegra210.c index b4df5c46642f..2896d2e783ce 100644 --- a/drivers/clk/tegra/clk-tegra210.c +++ b/drivers/clk/tegra/clk-tegra210.c @@ -155,27 +155,6 @@ #define PMC_PLLM_WB0_OVERRIDE 0x1dc #define PMC_PLLM_WB0_OVERRIDE_2 0x2b0 -#define UTMIP_PLL_CFG2 0x488 -#define UTMIP_PLL_CFG2_STABLE_COUNT(x) (((x) & 0xfff) << 6) -#define UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(x) (((x) & 0x3f) << 18) -#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_A_POWERDOWN BIT(0) -#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_A_POWERUP BIT(1) -#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_B_POWERDOWN BIT(2) -#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_B_POWERUP BIT(3) -#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_C_POWERDOWN BIT(4) -#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_C_POWERUP BIT(5) -#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_D_POWERDOWN BIT(24) -#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_D_POWERUP BIT(25) - -#define UTMIP_PLL_CFG1 0x484 -#define UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(x) (((x) & 0x1f) << 27) -#define UTMIP_PLL_CFG1_XTAL_FREQ_COUNT(x) (((x) & 0xfff) << 0) -#define UTMIP_PLL_CFG1_FORCE_PLLU_POWERUP BIT(17) -#define UTMIP_PLL_CFG1_FORCE_PLLU_POWERDOWN BIT(16) -#define UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERUP BIT(15) -#define UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN BIT(14) -#define UTMIP_PLL_CFG1_FORCE_PLL_ACTIVE_POWERDOWN BIT(12) - #define SATA_PLL_CFG0 0x490 #define SATA_PLL_CFG0_PADPLL_RESET_SWCTL BIT(0) #define SATA_PLL_CFG0_PADPLL_USE_LOCKDET BIT(2) @@ -2038,47 +2017,6 @@ static struct tegra_clk_pll_params pll_u_vco_params = { .calc_rate = tegra210_pll_fixed_mdiv_cfg, }; -struct utmi_clk_param { - /* Oscillator Frequency in KHz */ - u32 osc_frequency; - /* UTMIP PLL Enable Delay Count */ - u8 enable_delay_count; - /* UTMIP PLL Stable count */ - u16 stable_count; - /* UTMIP PLL Active delay count */ - u8 active_delay_count; - /* UTMIP PLL Xtal frequency count */ - u16 xtal_freq_count; -}; - -static const struct utmi_clk_param utmi_parameters[] = { - { - .osc_frequency = 38400000, .enable_delay_count = 0x0, - .stable_count = 0x0, .active_delay_count = 0x6, - .xtal_freq_count = 0x80 - }, { - .osc_frequency = 13000000, .enable_delay_count = 0x02, - .stable_count = 0x33, .active_delay_count = 0x05, - .xtal_freq_count = 0x7f - }, { - .osc_frequency = 19200000, .enable_delay_count = 0x03, - .stable_count = 0x4b, .active_delay_count = 0x06, - .xtal_freq_count = 0xbb - }, { - .osc_frequency = 12000000, .enable_delay_count = 0x02, - .stable_count = 0x2f, .active_delay_count = 0x08, - .xtal_freq_count = 0x76 - }, { - .osc_frequency = 26000000, .enable_delay_count = 0x04, - .stable_count = 0x66, .active_delay_count = 0x09, - .xtal_freq_count = 0xfe - }, { - .osc_frequency = 16800000, .enable_delay_count = 0x03, - .stable_count = 0x41, .active_delay_count = 0x0a, - .xtal_freq_count = 0xa4 - }, -}; - static struct tegra_clk tegra210_clks[tegra_clk_max] __initdata = { [tegra_clk_ispb] = { .dt_id = TEGRA210_CLK_ISPB, .present = true }, [tegra_clk_rtc] = { .dt_id = TEGRA210_CLK_RTC, .present = true }, @@ -2348,114 +2286,6 @@ static struct tegra_audio_clk_info tegra210_audio_plls[] = { static struct clk **clks; -static void tegra210_utmi_param_configure(void __iomem *clk_base) -{ - u32 reg; - int i; - - for (i = 0; i < ARRAY_SIZE(utmi_parameters); i++) { - if (osc_freq == utmi_parameters[i].osc_frequency) - break; - } - - if (i >= ARRAY_SIZE(utmi_parameters)) { - pr_err("%s: Unexpected oscillator freq %lu\n", __func__, - osc_freq); - return; - } - - reg = readl_relaxed(clk_base + PLLU_HW_PWRDN_CFG0); - reg |= PLLU_HW_PWRDN_CFG0_IDDQ_PD_INCLUDE | - PLLU_HW_PWRDN_CFG0_USE_SWITCH_DETECT | - PLLU_HW_PWRDN_CFG0_USE_LOCKDET; - reg &= ~(PLLU_HW_PWRDN_CFG0_CLK_ENABLE_SWCTL | - PLLU_HW_PWRDN_CFG0_CLK_SWITCH_SWCTL); - writel_relaxed(reg, clk_base + PLLU_HW_PWRDN_CFG0); - - reg = readl_relaxed(clk_base + PLLU_HW_PWRDN_CFG0); - reg |= PLLU_HW_PWRDN_CFG0_SEQ_ENABLE; - writel_relaxed(reg, clk_base + PLLU_HW_PWRDN_CFG0); - udelay(1); - - reg = readl_relaxed(clk_base + PLLU_BASE); - reg &= ~PLLU_BASE_CLKENABLE_USB; - writel_relaxed(reg, clk_base + PLLU_BASE); - - reg = readl_relaxed(clk_base + UTMIPLL_HW_PWRDN_CFG0); - reg &= ~UTMIPLL_HW_PWRDN_CFG0_IDDQ_OVERRIDE; - writel_relaxed(reg, clk_base + UTMIPLL_HW_PWRDN_CFG0); - - udelay(10); - - reg = readl_relaxed(clk_base + UTMIP_PLL_CFG2); - - /* Program UTMIP PLL stable and active counts */ - /* [FIXME] arclk_rst.h says WRONG! This should be 1ms -> 0x50 Check! */ - reg &= ~UTMIP_PLL_CFG2_STABLE_COUNT(~0); - reg |= UTMIP_PLL_CFG2_STABLE_COUNT(utmi_parameters[i].stable_count); - - reg &= ~UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(~0); - - reg |= UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(utmi_parameters[i]. - active_delay_count); - writel_relaxed(reg, clk_base + UTMIP_PLL_CFG2); - - /* Program UTMIP PLL delay and oscillator frequency counts */ - reg = readl_relaxed(clk_base + UTMIP_PLL_CFG1); - reg &= ~UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(~0); - - reg |= UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(utmi_parameters[i]. - enable_delay_count); - - reg &= ~UTMIP_PLL_CFG1_XTAL_FREQ_COUNT(~0); - reg |= UTMIP_PLL_CFG1_XTAL_FREQ_COUNT(utmi_parameters[i]. - xtal_freq_count); - - reg |= UTMIP_PLL_CFG1_FORCE_PLLU_POWERDOWN; - writel_relaxed(reg, clk_base + UTMIP_PLL_CFG1); - - /* Remove power downs from UTMIP PLL control bits */ - reg = readl_relaxed(clk_base + UTMIP_PLL_CFG1); - reg &= ~UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN; - reg |= UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERUP; - writel_relaxed(reg, clk_base + UTMIP_PLL_CFG1); - udelay(1); - - /* Enable samplers for SNPS, XUSB_HOST, XUSB_DEV */ - reg = readl_relaxed(clk_base + UTMIP_PLL_CFG2); - reg |= UTMIP_PLL_CFG2_FORCE_PD_SAMP_A_POWERUP; - reg |= UTMIP_PLL_CFG2_FORCE_PD_SAMP_B_POWERUP; - reg |= UTMIP_PLL_CFG2_FORCE_PD_SAMP_D_POWERUP; - reg &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_A_POWERDOWN; - reg &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_B_POWERDOWN; - reg &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_D_POWERDOWN; - writel_relaxed(reg, clk_base + UTMIP_PLL_CFG2); - - /* Setup HW control of UTMIPLL */ - reg = readl_relaxed(clk_base + UTMIP_PLL_CFG1); - reg &= ~UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN; - reg &= ~UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERUP; - writel_relaxed(reg, clk_base + UTMIP_PLL_CFG1); - - reg = readl_relaxed(clk_base + UTMIPLL_HW_PWRDN_CFG0); - reg |= UTMIPLL_HW_PWRDN_CFG0_USE_LOCKDET; - reg &= ~UTMIPLL_HW_PWRDN_CFG0_CLK_ENABLE_SWCTL; - writel_relaxed(reg, clk_base + UTMIPLL_HW_PWRDN_CFG0); - - udelay(1); - - reg = readl_relaxed(clk_base + XUSB_PLL_CFG0); - reg &= ~XUSB_PLL_CFG0_UTMIPLL_LOCK_DLY; - writel_relaxed(reg, clk_base + XUSB_PLL_CFG0); - - udelay(1); - - /* Enable HW control UTMIPLL */ - reg = readl_relaxed(clk_base + UTMIPLL_HW_PWRDN_CFG0); - reg |= UTMIPLL_HW_PWRDN_CFG0_SEQ_ENABLE; - writel_relaxed(reg, clk_base + UTMIPLL_HW_PWRDN_CFG0); -} - static __init void tegra210_periph_clk_init(void __iomem *clk_base, void __iomem *pmc_base) { @@ -2523,7 +2353,6 @@ static __init void tegra210_periph_clk_init(void __iomem *clk_base, static void __init tegra210_pll_init(void __iomem *clk_base, void __iomem *pmc) { - u32 val; struct clk *clk; /* PLLC */ @@ -2583,12 +2412,9 @@ static void __init tegra210_pll_init(void __iomem *clk_base, clks[TEGRA210_CLK_PLL_M_UD] = clk; /* PLLU_VCO */ - val = readl(clk_base + pll_u_vco_params.base_reg); - val &= ~PLLU_BASE_OVERRIDE; /* disable PLLU_OVERRIDE */ - writel(val, clk_base + pll_u_vco_params.base_reg); - - clk = tegra_clk_register_pllre("pll_u_vco", "pll_ref", clk_base, pmc, - 0, &pll_u_vco_params, &pll_u_lock, pll_ref_freq); + clk = tegra_clk_register_pllu_tegra210("pll_u_vco", "pll_ref", + clk_base, 0, &pll_u_vco_params, + &pll_u_lock); clk_register_clkdev(clk, "pll_u_vco", NULL); clks[TEGRA210_CLK_PLL_U] = clk; @@ -2621,8 +2447,6 @@ static void __init tegra210_pll_init(void __iomem *clk_base, clk_register_clkdev(clk, "pll_u_out2", NULL); clks[TEGRA210_CLK_PLL_U_OUT2] = clk; - tegra210_utmi_param_configure(clk_base); - /* PLLU_480M */ clk = clk_register_gate(NULL, "pll_u_480M", "pll_u_vco", CLK_SET_RATE_PARENT, clk_base + PLLU_BASE, diff --git a/drivers/clk/tegra/clk-tegra30.c b/drivers/clk/tegra/clk-tegra30.c index 9396f4930da7..8e2db5ead8da 100644 --- a/drivers/clk/tegra/clk-tegra30.c +++ b/drivers/clk/tegra/clk-tegra30.c @@ -118,20 +118,6 @@ #define AUDIO_SYNC_DOUBLER 0x49c -#define UTMIP_PLL_CFG2 0x488 -#define UTMIP_PLL_CFG2_STABLE_COUNT(x) (((x) & 0xffff) << 6) -#define UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(x) (((x) & 0x3f) << 18) -#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_A_POWERDOWN BIT(0) -#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_B_POWERDOWN BIT(2) -#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_C_POWERDOWN BIT(4) - -#define UTMIP_PLL_CFG1 0x484 -#define UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(x) (((x) & 0x1f) << 6) -#define UTMIP_PLL_CFG1_XTAL_FREQ_COUNT(x) (((x) & 0xfff) << 0) -#define UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN BIT(14) -#define UTMIP_PLL_CFG1_FORCE_PLL_ACTIVE_POWERDOWN BIT(12) -#define UTMIP_PLL_CFG1_FORCE_PLLU_POWERDOWN BIT(16) - /* Tegra CPU clock and reset control regs */ #define TEGRA_CLK_RST_CONTROLLER_CLK_CPU_CMPLX 0x4c #define TEGRA_CLK_RST_CONTROLLER_RST_CPU_CMPLX_SET 0x340 @@ -207,46 +193,6 @@ static DEFINE_SPINLOCK(emc_lock); static struct clk **clks; -/* - * Structure defining the fields for USB UTMI clocks Parameters. - */ -struct utmi_clk_param { - /* Oscillator Frequency in KHz */ - u32 osc_frequency; - /* UTMIP PLL Enable Delay Count */ - u8 enable_delay_count; - /* UTMIP PLL Stable count */ - u8 stable_count; - /* UTMIP PLL Active delay count */ - u8 active_delay_count; - /* UTMIP PLL Xtal frequency count */ - u8 xtal_freq_count; -}; - -static const struct utmi_clk_param utmi_parameters[] = { - { - .osc_frequency = 13000000, .enable_delay_count = 0x02, - .stable_count = 0x33, .active_delay_count = 0x05, - .xtal_freq_count = 0x7f - }, { - .osc_frequency = 19200000, .enable_delay_count = 0x03, - .stable_count = 0x4b, .active_delay_count = 0x06, - .xtal_freq_count = 0xbb - }, { - .osc_frequency = 12000000, .enable_delay_count = 0x02, - .stable_count = 0x2f, .active_delay_count = 0x04, - .xtal_freq_count = 0x76 - }, { - .osc_frequency = 26000000, .enable_delay_count = 0x04, - .stable_count = 0x66, .active_delay_count = 0x09, - .xtal_freq_count = 0xfe - }, { - .osc_frequency = 16800000, .enable_delay_count = 0x03, - .stable_count = 0x41, .active_delay_count = 0x0a, - .xtal_freq_count = 0xa4 - }, -}; - static struct tegra_clk_pll_freq_table pll_c_freq_table[] = { { 12000000, 1040000000, 520, 6, 1, 8 }, { 13000000, 1040000000, 480, 6, 1, 8 }, @@ -873,59 +819,6 @@ static struct tegra_clk tegra30_clks[tegra_clk_max] __initdata = { [tegra_clk_pll_a_out0] = { .dt_id = TEGRA30_CLK_PLL_A_OUT0, .present = true }, }; -static void tegra30_utmi_param_configure(void) -{ - unsigned int i; - u32 reg; - - for (i = 0; i < ARRAY_SIZE(utmi_parameters); i++) { - if (input_freq == utmi_parameters[i].osc_frequency) - break; - } - - if (i >= ARRAY_SIZE(utmi_parameters)) { - pr_err("%s: Unexpected input rate %lu\n", __func__, input_freq); - return; - } - - reg = readl_relaxed(clk_base + UTMIP_PLL_CFG2); - - /* Program UTMIP PLL stable and active counts */ - reg &= ~UTMIP_PLL_CFG2_STABLE_COUNT(~0); - reg |= UTMIP_PLL_CFG2_STABLE_COUNT( - utmi_parameters[i].stable_count); - - reg &= ~UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(~0); - - reg |= UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT( - utmi_parameters[i].active_delay_count); - - /* Remove power downs from UTMIP PLL control bits */ - reg &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_A_POWERDOWN; - reg &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_B_POWERDOWN; - reg &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_C_POWERDOWN; - - writel_relaxed(reg, clk_base + UTMIP_PLL_CFG2); - - /* Program UTMIP PLL delay and oscillator frequency counts */ - reg = readl_relaxed(clk_base + UTMIP_PLL_CFG1); - reg &= ~UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(~0); - - reg |= UTMIP_PLL_CFG1_ENABLE_DLY_COUNT( - utmi_parameters[i].enable_delay_count); - - reg &= ~UTMIP_PLL_CFG1_XTAL_FREQ_COUNT(~0); - reg |= UTMIP_PLL_CFG1_XTAL_FREQ_COUNT( - utmi_parameters[i].xtal_freq_count); - - /* Remove power downs from UTMIP PLL control bits */ - reg &= ~UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN; - reg &= ~UTMIP_PLL_CFG1_FORCE_PLL_ACTIVE_POWERDOWN; - reg &= ~UTMIP_PLL_CFG1_FORCE_PLLU_POWERDOWN; - - writel_relaxed(reg, clk_base + UTMIP_PLL_CFG1); -} - static const char *pll_e_parents[] = { "pll_ref", "pll_p" }; static void __init tegra30_pll_init(void) @@ -972,12 +865,10 @@ static void __init tegra30_pll_init(void) clks[TEGRA30_CLK_PLL_X_OUT0] = clk; /* PLLU */ - clk = tegra_clk_register_pll("pll_u", "pll_ref", clk_base, pmc_base, 0, - &pll_u_params, NULL); + clk = tegra_clk_register_pllu("pll_u", "pll_ref", clk_base, 0, + &pll_u_params, NULL); clks[TEGRA30_CLK_PLL_U] = clk; - tegra30_utmi_param_configure(); - /* PLLD */ clk = tegra_clk_register_pll("pll_d", "pll_ref", clk_base, pmc_base, 0, &pll_d_params, &pll_d_lock); diff --git a/drivers/clk/tegra/clk.h b/drivers/clk/tegra/clk.h index 9421f0310999..6ba82ecffd4d 100644 --- a/drivers/clk/tegra/clk.h +++ b/drivers/clk/tegra/clk.h @@ -427,6 +427,23 @@ struct clk *tegra_clk_register_pllmb(const char *name, const char *parent_name, struct tegra_clk_pll_params *pll_params, spinlock_t *lock); +struct clk *tegra_clk_register_pllu(const char *name, const char *parent_name, + void __iomem *clk_base, unsigned long flags, + struct tegra_clk_pll_params *pll_params, + spinlock_t *lock); + +struct clk *tegra_clk_register_pllu_tegra114(const char *name, + const char *parent_name, + void __iomem *clk_base, unsigned long flags, + struct tegra_clk_pll_params *pll_params, + spinlock_t *lock); + +struct clk *tegra_clk_register_pllu_tegra210(const char *name, + const char *parent_name, + void __iomem *clk_base, unsigned long flags, + struct tegra_clk_pll_params *pll_params, + spinlock_t *lock); + /** * struct tegra_clk_pll_out - PLL divider down clock * -- cgit v1.2.3 From 6fb924dc9c482557ebd41f6c6a5fde34210a2e08 Mon Sep 17 00:00:00 2001 From: Zhangfei Gao Date: Wed, 29 Jun 2016 17:48:44 -0700 Subject: clk: hi6220: Add RTC clock for pl031 Adds clk support for the pl031 RTC on hi6220 Cc: Michael Turquette Cc: Stephen Boyd Cc: Rob Herring Cc: Pawel Moll Cc: Wei Xu Cc: Guodong Xu Signed-off-by: Zhangfei Gao [jstultz: Forward ported, tweaked commit description] Signed-off-by: John Stultz Signed-off-by: Stephen Boyd --- drivers/clk/hisilicon/clk-hi6220.c | 2 ++ include/dt-bindings/clock/hi6220-clock.h | 5 +++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/clk/hisilicon/clk-hi6220.c b/drivers/clk/hisilicon/clk-hi6220.c index f02cb41d40a4..76de9a762a86 100644 --- a/drivers/clk/hisilicon/clk-hi6220.c +++ b/drivers/clk/hisilicon/clk-hi6220.c @@ -68,6 +68,8 @@ static struct hisi_gate_clock hi6220_separated_gate_clks_ao[] __initdata = { { HI6220_TIMER7_PCLK, "timer7_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 22, 0, }, { HI6220_TIMER8_PCLK, "timer8_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 23, 0, }, { HI6220_UART0_PCLK, "uart0_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 24, 0, }, + { HI6220_RTC0_PCLK, "rtc0_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 25, 0, }, + { HI6220_RTC1_PCLK, "rtc1_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 26, 0, }, }; static void __init hi6220_clk_ao_init(struct device_node *np) diff --git a/include/dt-bindings/clock/hi6220-clock.h b/include/dt-bindings/clock/hi6220-clock.h index 70ee3833a7a0..6b03c84f4278 100644 --- a/include/dt-bindings/clock/hi6220-clock.h +++ b/include/dt-bindings/clock/hi6220-clock.h @@ -55,8 +55,9 @@ #define HI6220_TIMER7_PCLK 34 #define HI6220_TIMER8_PCLK 35 #define HI6220_UART0_PCLK 36 - -#define HI6220_AO_NR_CLKS 37 +#define HI6220_RTC0_PCLK 37 +#define HI6220_RTC1_PCLK 38 +#define HI6220_AO_NR_CLKS 39 /* clk in Hi6220 systrl */ /* gate clock */ -- cgit v1.2.3 From fa6415affe2020606799fd4e9e89f37a01fb2ae9 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Tue, 7 Jun 2016 12:19:25 +0100 Subject: clk: st: clk-flexgen: Detect critical clocks Utilise the new Critical Clock infrastructure to mark clocks which much not be disabled as CRITICAL. While we're at it, reduce the coverage of the flex_flags variable, since it's only really used in a single for() loop. Signed-off-by: Lee Jones Signed-off-by: Stephen Boyd --- drivers/clk/st/clk-flexgen.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/clk/st/clk-flexgen.c b/drivers/clk/st/clk-flexgen.c index 627267c7ec5c..546bd79c8e3a 100644 --- a/drivers/clk/st/clk-flexgen.c +++ b/drivers/clk/st/clk-flexgen.c @@ -267,7 +267,6 @@ static void __init st_of_flexgen_setup(struct device_node *np) const char **parents; int num_parents, i; spinlock_t *rlock = NULL; - unsigned long flex_flags = 0; int ret; pnode = of_get_parent(np); @@ -308,12 +307,15 @@ static void __init st_of_flexgen_setup(struct device_node *np) for (i = 0; i < clk_data->clk_num; i++) { struct clk *clk; const char *clk_name; + unsigned long flex_flags = 0; if (of_property_read_string_index(np, "clock-output-names", i, &clk_name)) { break; } + of_clk_detect_critical(np, i, &flex_flags); + /* * If we read an empty clock name then the output is unused */ -- cgit v1.2.3 From a3a2d78bd1860472903929f7f2385278204d9164 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Tue, 7 Jun 2016 12:19:26 +0100 Subject: clk: st: clkgen-fsyn: Detect critical clocks Utilise the new Critical Clock infrastructure to mark clocks which much not be disabled as CRITICAL. Clocks are marked as CRITICAL using clk flags. This patch also ensures flags are peculated through the framework in the correct manner. Signed-off-by: Lee Jones Signed-off-by: Stephen Boyd --- drivers/clk/st/clkgen-fsyn.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/clk/st/clkgen-fsyn.c b/drivers/clk/st/clkgen-fsyn.c index dec4eaaecc00..09afeb85109c 100644 --- a/drivers/clk/st/clkgen-fsyn.c +++ b/drivers/clk/st/clkgen-fsyn.c @@ -1027,7 +1027,7 @@ static const struct clk_ops st_quadfs_ops = { static struct clk * __init st_clk_register_quadfs_fsynth( const char *name, const char *parent_name, struct clkgen_quadfs_data *quadfs, void __iomem *reg, u32 chan, - spinlock_t *lock) + unsigned long flags, spinlock_t *lock) { struct st_clk_quadfs_fsynth *fs; struct clk *clk; @@ -1045,7 +1045,7 @@ static struct clk * __init st_clk_register_quadfs_fsynth( init.name = name; init.ops = &st_quadfs_ops; - init.flags = CLK_GET_RATE_NOCACHE | CLK_IS_BASIC; + init.flags = flags | CLK_GET_RATE_NOCACHE | CLK_IS_BASIC; init.parent_names = &parent_name; init.num_parents = 1; @@ -1115,6 +1115,7 @@ static void __init st_of_create_quadfs_fsynths( for (fschan = 0; fschan < QUADFS_MAX_CHAN; fschan++) { struct clk *clk; const char *clk_name; + unsigned long flags = 0; if (of_property_read_string_index(np, "clock-output-names", fschan, &clk_name)) { @@ -1127,8 +1128,11 @@ static void __init st_of_create_quadfs_fsynths( if (*clk_name == '\0') continue; + of_clk_detect_critical(np, fschan, &flags); + clk = st_clk_register_quadfs_fsynth(clk_name, pll_name, - quadfs, reg, fschan, lock); + quadfs, reg, fschan, + flags, lock); /* * If there was an error registering this clock output, clean -- cgit v1.2.3 From 6ca59e6e1fc3a8d7ccbf85ff036bd6ff40847c1a Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Tue, 7 Jun 2016 12:19:27 +0100 Subject: clk: st: clkgen-pll: Detect critical clocks Utilise the new Critical Clock infrastructure to mark clocks which much not be disabled as CRITICAL. Clocks are marked as CRITICAL using clk flags. This patch also ensures flags are peculated through the framework in the correct manner. Signed-off-by: Lee Jones Signed-off-by: Stephen Boyd --- drivers/clk/st/clkgen-pll.c | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/drivers/clk/st/clkgen-pll.c b/drivers/clk/st/clkgen-pll.c index 38f6f3a9098e..0b5990e82e0d 100644 --- a/drivers/clk/st/clkgen-pll.c +++ b/drivers/clk/st/clkgen-pll.c @@ -840,7 +840,7 @@ static const struct clk_ops stm_pll4600c28_ops = { static struct clk * __init clkgen_pll_register(const char *parent_name, struct clkgen_pll_data *pll_data, - void __iomem *reg, + void __iomem *reg, unsigned long pll_flags, const char *clk_name, spinlock_t *lock) { struct clkgen_pll *pll; @@ -854,7 +854,7 @@ static struct clk * __init clkgen_pll_register(const char *parent_name, init.name = clk_name; init.ops = pll_data->ops; - init.flags = CLK_IS_BASIC | CLK_GET_RATE_NOCACHE; + init.flags = pll_flags | CLK_IS_BASIC | CLK_GET_RATE_NOCACHE; init.parent_names = &parent_name; init.num_parents = 1; @@ -948,7 +948,7 @@ static void __init clkgena_c65_pll_setup(struct device_node *np) */ clk_data->clks[0] = clkgen_pll_register(parent_name, (struct clkgen_pll_data *) &st_pll1600c65_ax, - reg + CLKGENAx_PLL0_OFFSET, clk_name, NULL); + reg + CLKGENAx_PLL0_OFFSET, 0, clk_name, NULL); if (IS_ERR(clk_data->clks[0])) goto err; @@ -977,7 +977,7 @@ static void __init clkgena_c65_pll_setup(struct device_node *np) */ clk_data->clks[2] = clkgen_pll_register(parent_name, (struct clkgen_pll_data *) &st_pll800c65_ax, - reg + CLKGENAx_PLL1_OFFSET, clk_name, NULL); + reg + CLKGENAx_PLL1_OFFSET, 0, clk_name, NULL); if (IS_ERR(clk_data->clks[2])) goto err; @@ -995,7 +995,7 @@ CLK_OF_DECLARE(clkgena_c65_plls, static struct clk * __init clkgen_odf_register(const char *parent_name, void __iomem *reg, struct clkgen_pll_data *pll_data, - int odf, + unsigned long pll_flags, int odf, spinlock_t *odf_lock, const char *odf_name) { @@ -1004,7 +1004,7 @@ static struct clk * __init clkgen_odf_register(const char *parent_name, struct clk_gate *gate; struct clk_divider *div; - flags = CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT; + flags = pll_flags | CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT; gate = kzalloc(sizeof(*gate), GFP_KERNEL); if (!gate) @@ -1099,6 +1099,7 @@ static void __init clkgen_c32_pll_setup(struct device_node *np) int num_odfs, odf; struct clk_onecell_data *clk_data; struct clkgen_pll_data *data; + unsigned long pll_flags = 0; match = of_match_node(c32_pll_of_match, np); if (!match) { @@ -1116,8 +1117,10 @@ static void __init clkgen_c32_pll_setup(struct device_node *np) if (!pll_base) return; - clk = clkgen_pll_register(parent_name, data, pll_base, np->name, - data->lock); + of_clk_detect_critical(np, 0, &pll_flags); + + clk = clkgen_pll_register(parent_name, data, pll_base, pll_flags, + np->name, data->lock); if (IS_ERR(clk)) return; @@ -1139,12 +1142,15 @@ static void __init clkgen_c32_pll_setup(struct device_node *np) for (odf = 0; odf < num_odfs; odf++) { struct clk *clk; const char *clk_name; + unsigned long odf_flags = 0; if (of_property_read_string_index(np, "clock-output-names", odf, &clk_name)) return; - clk = clkgen_odf_register(pll_name, pll_base, data, + of_clk_detect_critical(np, odf, &odf_flags); + + clk = clkgen_odf_register(pll_name, pll_base, data, odf_flags, odf, &clkgena_c32_odf_lock, clk_name); if (IS_ERR(clk)) goto err; @@ -1206,7 +1212,8 @@ static void __init clkgengpu_c32_pll_setup(struct device_node *np) /* * PLL 1200MHz output */ - clk = clkgen_pll_register(parent_name, data, reg, clk_name, data->lock); + clk = clkgen_pll_register(parent_name, data, reg, + 0, clk_name, data->lock); if (!IS_ERR(clk)) of_clk_add_provider(np, of_clk_src_simple_get, clk); -- cgit v1.2.3 From 8e66cc05820a188f16551d1648d33c9ec3de366d Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Wed, 1 Jun 2016 16:15:02 -0700 Subject: clk: highbank: Migrate to clk_hw based registration and OF APIs Now that we have clk_hw based provider APIs to register clks, we can get rid of struct clk pointers in this driver, allowing us to move closer to a clear split of consumer and provider clk APIs. Signed-off-by: Stephen Boyd Acked-by: Rob Herring Signed-off-by: Stephen Boyd --- drivers/clk/clk-highbank.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/clk/clk-highbank.c b/drivers/clk/clk-highbank.c index be3a21abb185..727ed8e1bb72 100644 --- a/drivers/clk/clk-highbank.c +++ b/drivers/clk/clk-highbank.c @@ -275,7 +275,6 @@ static const struct clk_ops periclk_ops = { static __init struct clk *hb_clk_init(struct device_node *node, const struct clk_ops *ops) { u32 reg; - struct clk *clk; struct hb_clk *hb_clk; const char *clk_name = node->name; const char *parent_name; @@ -308,13 +307,13 @@ static __init struct clk *hb_clk_init(struct device_node *node, const struct clk hb_clk->hw.init = &init; - clk = clk_register(NULL, &hb_clk->hw); - if (WARN_ON(IS_ERR(clk))) { + rc = clk_hw_register(NULL, &hb_clk->hw); + if (WARN_ON(rc)) { kfree(hb_clk); return NULL; } - rc = of_clk_add_provider(node, of_clk_src_simple_get, clk); - return clk; + rc = of_clk_add_hw_provider(node, of_clk_hw_simple_get, &hb_clk->hw); + return hb_clk->hw.clk; } static void __init hb_pll_init(struct device_node *node) -- cgit v1.2.3 From 7b38d1b222b42cfed197290332a8e426fb77e8fe Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Wed, 1 Jun 2016 16:15:19 -0700 Subject: clk: nomadik: Migrate to clk_hw based OF and registration APIs Now that we have clk_hw based provider APIs to register clks, we can get rid of struct clk pointers while registering clks in these drivers, allowing us to move closer to a clear split of consumer and provider clk APIs. Signed-off-by: Stephen Boyd Acked-by: Linus Walleij Signed-off-by: Stephen Boyd --- drivers/clk/clk-nomadik.c | 48 +++++++++++++++++++++++++---------------------- 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/drivers/clk/clk-nomadik.c b/drivers/clk/clk-nomadik.c index e4d8a991c58f..71677eb12565 100644 --- a/drivers/clk/clk-nomadik.c +++ b/drivers/clk/clk-nomadik.c @@ -253,11 +253,11 @@ static const struct clk_ops pll_clk_ops = { .recalc_rate = pll_clk_recalc_rate, }; -static struct clk * __init +static struct clk_hw * __init pll_clk_register(struct device *dev, const char *name, const char *parent_name, u32 id) { - struct clk *clk; + int ret; struct clk_pll *pll; struct clk_init_data init; @@ -281,11 +281,13 @@ pll_clk_register(struct device *dev, const char *name, pr_debug("register PLL1 clock \"%s\"\n", name); - clk = clk_register(dev, &pll->hw); - if (IS_ERR(clk)) + ret = clk_hw_register(dev, &pll->hw); + if (ret) { kfree(pll); + return ERR_PTR(ret); + } - return clk; + return &pll->hw; } /* @@ -345,11 +347,11 @@ static const struct clk_ops src_clk_ops = { .recalc_rate = src_clk_recalc_rate, }; -static struct clk * __init +static struct clk_hw * __init src_clk_register(struct device *dev, const char *name, const char *parent_name, u8 id) { - struct clk *clk; + int ret; struct clk_src *sclk; struct clk_init_data init; @@ -376,11 +378,13 @@ src_clk_register(struct device *dev, const char *name, pr_debug("register clock \"%s\" ID: %d group: %d bits: %08x\n", name, id, sclk->group1, sclk->clkbit); - clk = clk_register(dev, &sclk->hw); - if (IS_ERR(clk)) + ret = clk_hw_register(dev, &sclk->hw); + if (ret) { kfree(sclk); + return ERR_PTR(ret); + } - return clk; + return &sclk->hw; } #ifdef CONFIG_DEBUG_FS @@ -508,7 +512,7 @@ device_initcall(nomadik_src_clk_init_debugfs); static void __init of_nomadik_pll_setup(struct device_node *np) { - struct clk *clk = ERR_PTR(-EINVAL); + struct clk_hw *hw; const char *clk_name = np->name; const char *parent_name; u32 pll_id; @@ -522,16 +526,16 @@ static void __init of_nomadik_pll_setup(struct device_node *np) return; } parent_name = of_clk_get_parent_name(np, 0); - clk = pll_clk_register(NULL, clk_name, parent_name, pll_id); - if (!IS_ERR(clk)) - of_clk_add_provider(np, of_clk_src_simple_get, clk); + hw = pll_clk_register(NULL, clk_name, parent_name, pll_id); + if (!IS_ERR(hw)) + of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw); } CLK_OF_DECLARE(nomadik_pll_clk, "st,nomadik-pll-clock", of_nomadik_pll_setup); static void __init of_nomadik_hclk_setup(struct device_node *np) { - struct clk *clk = ERR_PTR(-EINVAL); + struct clk_hw *hw; const char *clk_name = np->name; const char *parent_name; @@ -542,20 +546,20 @@ static void __init of_nomadik_hclk_setup(struct device_node *np) /* * The HCLK divides PLL1 with 1 (passthru), 2, 3 or 4. */ - clk = clk_register_divider(NULL, clk_name, parent_name, + hw = clk_hw_register_divider(NULL, clk_name, parent_name, 0, src_base + SRC_CR, 13, 2, CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO, &src_lock); - if (!IS_ERR(clk)) - of_clk_add_provider(np, of_clk_src_simple_get, clk); + if (!IS_ERR(hw)) + of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw); } CLK_OF_DECLARE(nomadik_hclk_clk, "st,nomadik-hclk-clock", of_nomadik_hclk_setup); static void __init of_nomadik_src_clk_setup(struct device_node *np) { - struct clk *clk = ERR_PTR(-EINVAL); + struct clk_hw *hw; const char *clk_name = np->name; const char *parent_name; u32 clk_id; @@ -569,9 +573,9 @@ static void __init of_nomadik_src_clk_setup(struct device_node *np) return; } parent_name = of_clk_get_parent_name(np, 0); - clk = src_clk_register(NULL, clk_name, parent_name, clk_id); - if (!IS_ERR(clk)) - of_clk_add_provider(np, of_clk_src_simple_get, clk); + hw = src_clk_register(NULL, clk_name, parent_name, clk_id); + if (!IS_ERR(hw)) + of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw); } CLK_OF_DECLARE(nomadik_src_clk, "st,nomadik-src-clock", of_nomadik_src_clk_setup); -- cgit v1.2.3 From fb2cd7d07ae0146db95b68c4c31b2d96cd0e9575 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Wed, 1 Jun 2016 16:15:31 -0700 Subject: clk: u300: Migrate to clk_hw based registration APIs Now that we have clk_hw based provider APIs to register clks, we can get rid of struct clk pointers while registering clks in these drivers, allowing us to move closer to a clear split of consumer and provider clk APIs. Signed-off-by: Stephen Boyd Acked-by: Linus Walleij Signed-off-by: Stephen Boyd --- drivers/clk/clk-u300.c | 59 ++++++++++++++++++++++++++++---------------------- 1 file changed, 33 insertions(+), 26 deletions(-) diff --git a/drivers/clk/clk-u300.c b/drivers/clk/clk-u300.c index 95d1742dac30..ec8aafda6e24 100644 --- a/drivers/clk/clk-u300.c +++ b/drivers/clk/clk-u300.c @@ -689,7 +689,7 @@ static const struct clk_ops syscon_clk_ops = { .set_rate = syscon_clk_set_rate, }; -static struct clk * __init +static struct clk_hw * __init syscon_clk_register(struct device *dev, const char *name, const char *parent_name, unsigned long flags, bool hw_ctrld, @@ -697,9 +697,10 @@ syscon_clk_register(struct device *dev, const char *name, void __iomem *en_reg, u8 en_bit, u16 clk_val) { - struct clk *clk; + struct clk_hw *hw; struct clk_syscon *sclk; struct clk_init_data init; + int ret; sclk = kzalloc(sizeof(struct clk_syscon), GFP_KERNEL); if (!sclk) { @@ -722,11 +723,14 @@ syscon_clk_register(struct device *dev, const char *name, sclk->en_bit = en_bit; sclk->clk_val = clk_val; - clk = clk_register(dev, &sclk->hw); - if (IS_ERR(clk)) + hw = &sclk->hw; + ret = clk_hw_register(dev, hw); + if (ret) { kfree(sclk); + hw = ERR_PTR(ret); + } - return clk; + return hw; } #define U300_CLK_TYPE_SLOW 0 @@ -868,7 +872,7 @@ static struct u300_clock const u300_clk_lookup[] __initconst = { static void __init of_u300_syscon_clk_init(struct device_node *np) { - struct clk *clk = ERR_PTR(-EINVAL); + struct clk_hw *hw = ERR_PTR(-EINVAL); const char *clk_name = np->name; const char *parent_name; void __iomem *res_reg; @@ -911,16 +915,15 @@ static void __init of_u300_syscon_clk_init(struct device_node *np) const struct u300_clock *u3clk = &u300_clk_lookup[i]; if (u3clk->type == clk_type && u3clk->id == clk_id) - clk = syscon_clk_register(NULL, - clk_name, parent_name, - 0, u3clk->hw_ctrld, - res_reg, u3clk->id, - en_reg, u3clk->id, - u3clk->clk_val); + hw = syscon_clk_register(NULL, clk_name, parent_name, + 0, u3clk->hw_ctrld, + res_reg, u3clk->id, + en_reg, u3clk->id, + u3clk->clk_val); } - if (!IS_ERR(clk)) { - of_clk_add_provider(np, of_clk_src_simple_get, clk); + if (!IS_ERR(hw)) { + of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw); /* * Some few system clocks - device tree does not @@ -928,11 +931,11 @@ static void __init of_u300_syscon_clk_init(struct device_node *np) * for now we add these three clocks here. */ if (clk_type == U300_CLK_TYPE_REST && clk_id == 5) - clk_register_clkdev(clk, NULL, "pl172"); + clk_hw_register_clkdev(hw, NULL, "pl172"); if (clk_type == U300_CLK_TYPE_REST && clk_id == 9) - clk_register_clkdev(clk, NULL, "semi"); + clk_hw_register_clkdev(hw, NULL, "semi"); if (clk_type == U300_CLK_TYPE_REST && clk_id == 12) - clk_register_clkdev(clk, NULL, "intcon"); + clk_hw_register_clkdev(hw, NULL, "intcon"); } } @@ -1111,13 +1114,14 @@ static const struct clk_ops mclk_ops = { .set_rate = mclk_clk_set_rate, }; -static struct clk * __init +static struct clk_hw * __init mclk_clk_register(struct device *dev, const char *name, const char *parent_name, bool is_mspro) { - struct clk *clk; + struct clk_hw *hw; struct clk_mclk *mclk; struct clk_init_data init; + int ret; mclk = kzalloc(sizeof(struct clk_mclk), GFP_KERNEL); if (!mclk) { @@ -1133,23 +1137,26 @@ mclk_clk_register(struct device *dev, const char *name, mclk->hw.init = &init; mclk->is_mspro = is_mspro; - clk = clk_register(dev, &mclk->hw); - if (IS_ERR(clk)) + hw = &mclk->hw; + ret = clk_hw_register(dev, hw); + if (ret) { kfree(mclk); + hw = ERR_PTR(ret); + } - return clk; + return hw; } static void __init of_u300_syscon_mclk_init(struct device_node *np) { - struct clk *clk = ERR_PTR(-EINVAL); + struct clk_hw *hw; const char *clk_name = np->name; const char *parent_name; parent_name = of_clk_get_parent_name(np, 0); - clk = mclk_clk_register(NULL, clk_name, parent_name, false); - if (!IS_ERR(clk)) - of_clk_add_provider(np, of_clk_src_simple_get, clk); + hw = mclk_clk_register(NULL, clk_name, parent_name, false); + if (!IS_ERR(hw)) + of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw); } static const struct of_device_id u300_clk_match[] __initconst = { -- cgit v1.2.3 From ff02c6c0a4693c858db8918a6215fee85369cd9c Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Wed, 1 Jun 2016 16:15:04 -0700 Subject: clk: bcm: iproc: Migrate to clk_hw based registration and OF APIs Now that we have clk_hw based provider APIs to register clks, we can get rid of struct clk pointers while registering clks in these drivers, allowing us to move closer to a clear split of consumer and provider clk APIs. Cc: Jon Mason Cc: Simran Rai Signed-off-by: Stephen Boyd Tested-by: Ray Jui Signed-off-by: Stephen Boyd --- drivers/clk/bcm/clk-iproc-armpll.c | 9 ++++----- drivers/clk/bcm/clk-iproc-asiu.c | 27 +++++++++++++-------------- drivers/clk/bcm/clk-iproc-pll.c | 32 ++++++++++++++++---------------- 3 files changed, 33 insertions(+), 35 deletions(-) diff --git a/drivers/clk/bcm/clk-iproc-armpll.c b/drivers/clk/bcm/clk-iproc-armpll.c index 698c507921f1..d7d628214b85 100644 --- a/drivers/clk/bcm/clk-iproc-armpll.c +++ b/drivers/clk/bcm/clk-iproc-armpll.c @@ -244,7 +244,6 @@ static const struct clk_ops iproc_arm_pll_ops = { void __init iproc_armpll_setup(struct device_node *node) { int ret; - struct clk *clk; struct iproc_arm_pll *pll; struct clk_init_data init; const char *parent_name; @@ -265,18 +264,18 @@ void __init iproc_armpll_setup(struct device_node *node) init.num_parents = (parent_name ? 1 : 0); pll->hw.init = &init; - clk = clk_register(NULL, &pll->hw); - if (WARN_ON(IS_ERR(clk))) + ret = clk_hw_register(NULL, &pll->hw); + if (WARN_ON(ret)) goto err_iounmap; - ret = of_clk_add_provider(node, of_clk_src_simple_get, clk); + ret = of_clk_add_hw_provider(node, of_clk_hw_simple_get, &pll->hw); if (WARN_ON(ret)) goto err_clk_unregister; return; err_clk_unregister: - clk_unregister(clk); + clk_hw_unregister(&pll->hw); err_iounmap: iounmap(pll->base); err_free_pll: diff --git a/drivers/clk/bcm/clk-iproc-asiu.c b/drivers/clk/bcm/clk-iproc-asiu.c index f630e1bbdcfe..4360e481368b 100644 --- a/drivers/clk/bcm/clk-iproc-asiu.c +++ b/drivers/clk/bcm/clk-iproc-asiu.c @@ -37,7 +37,7 @@ struct iproc_asiu { void __iomem *div_base; void __iomem *gate_base; - struct clk_onecell_data clk_data; + struct clk_hw_onecell_data *clk_data; struct iproc_asiu_clk *clks; }; @@ -197,11 +197,11 @@ void __init iproc_asiu_setup(struct device_node *node, if (WARN_ON(!asiu)) return; - asiu->clk_data.clk_num = num_clks; - asiu->clk_data.clks = kcalloc(num_clks, sizeof(*asiu->clk_data.clks), - GFP_KERNEL); - if (WARN_ON(!asiu->clk_data.clks)) + asiu->clk_data = kzalloc(sizeof(*asiu->clk_data->hws) * num_clks + + sizeof(*asiu->clk_data), GFP_KERNEL); + if (WARN_ON(!asiu->clk_data)) goto err_clks; + asiu->clk_data->num = num_clks; asiu->clks = kcalloc(num_clks, sizeof(*asiu->clks), GFP_KERNEL); if (WARN_ON(!asiu->clks)) @@ -217,7 +217,6 @@ void __init iproc_asiu_setup(struct device_node *node, for (i = 0; i < num_clks; i++) { struct clk_init_data init; - struct clk *clk; const char *parent_name; struct iproc_asiu_clk *asiu_clk; const char *clk_name; @@ -240,22 +239,22 @@ void __init iproc_asiu_setup(struct device_node *node, init.num_parents = (parent_name ? 1 : 0); asiu_clk->hw.init = &init; - clk = clk_register(NULL, &asiu_clk->hw); - if (WARN_ON(IS_ERR(clk))) + ret = clk_hw_register(NULL, &asiu_clk->hw); + if (WARN_ON(ret)) goto err_clk_register; - asiu->clk_data.clks[i] = clk; + asiu->clk_data->hws[i] = &asiu_clk->hw; } - ret = of_clk_add_provider(node, of_clk_src_onecell_get, - &asiu->clk_data); + ret = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, + asiu->clk_data); if (WARN_ON(ret)) goto err_clk_register; return; err_clk_register: - for (i = 0; i < num_clks; i++) - clk_unregister(asiu->clk_data.clks[i]); + while (--i >= 0) + clk_hw_unregister(asiu->clk_data->hws[i]); iounmap(asiu->gate_base); err_iomap_gate: @@ -265,7 +264,7 @@ err_iomap_div: kfree(asiu->clks); err_asiu_clks: - kfree(asiu->clk_data.clks); + kfree(asiu->clk_data); err_clks: kfree(asiu); diff --git a/drivers/clk/bcm/clk-iproc-pll.c b/drivers/clk/bcm/clk-iproc-pll.c index fd492a5dad12..e04634c46395 100644 --- a/drivers/clk/bcm/clk-iproc-pll.c +++ b/drivers/clk/bcm/clk-iproc-pll.c @@ -89,7 +89,7 @@ struct iproc_pll { const struct iproc_pll_vco_param *vco_param; unsigned int num_vco_entries; - struct clk_onecell_data clk_data; + struct clk_hw_onecell_data *clk_data; struct iproc_clk *clks; }; @@ -625,7 +625,6 @@ void __init iproc_pll_clk_setup(struct device_node *node, unsigned int num_clks) { int i, ret; - struct clk *clk; struct iproc_pll *pll; struct iproc_clk *iclk; struct clk_init_data init; @@ -638,11 +637,11 @@ void __init iproc_pll_clk_setup(struct device_node *node, if (WARN_ON(!pll)) return; - pll->clk_data.clk_num = num_clks; - pll->clk_data.clks = kcalloc(num_clks, sizeof(*pll->clk_data.clks), - GFP_KERNEL); - if (WARN_ON(!pll->clk_data.clks)) + pll->clk_data = kzalloc(sizeof(*pll->clk_data->hws) * num_clks + + sizeof(*pll->clk_data), GFP_KERNEL); + if (WARN_ON(!pll->clk_data)) goto err_clk_data; + pll->clk_data->num = num_clks; pll->clks = kcalloc(num_clks, sizeof(*pll->clks), GFP_KERNEL); if (WARN_ON(!pll->clks)) @@ -694,11 +693,11 @@ void __init iproc_pll_clk_setup(struct device_node *node, iproc_pll_sw_cfg(pll); - clk = clk_register(NULL, &iclk->hw); - if (WARN_ON(IS_ERR(clk))) + ret = clk_hw_register(NULL, &iclk->hw); + if (WARN_ON(ret)) goto err_pll_register; - pll->clk_data.clks[0] = clk; + pll->clk_data->hws[0] = &iclk->hw; /* now initialize and register all leaf clocks */ for (i = 1; i < num_clks; i++) { @@ -724,22 +723,23 @@ void __init iproc_pll_clk_setup(struct device_node *node, init.num_parents = (parent_name ? 1 : 0); iclk->hw.init = &init; - clk = clk_register(NULL, &iclk->hw); - if (WARN_ON(IS_ERR(clk))) + ret = clk_hw_register(NULL, &iclk->hw); + if (WARN_ON(ret)) goto err_clk_register; - pll->clk_data.clks[i] = clk; + pll->clk_data->hws[i] = &iclk->hw; } - ret = of_clk_add_provider(node, of_clk_src_onecell_get, &pll->clk_data); + ret = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, + pll->clk_data); if (WARN_ON(ret)) goto err_clk_register; return; err_clk_register: - for (i = 0; i < num_clks; i++) - clk_unregister(pll->clk_data.clks[i]); + while (--i >= 0) + clk_hw_unregister(pll->clk_data->hws[i]); err_pll_register: if (pll->status_base != pll->control_base) @@ -759,7 +759,7 @@ err_pll_iomap: kfree(pll->clks); err_clks: - kfree(pll->clk_data.clks); + kfree(pll->clk_data); err_clk_data: kfree(pll); -- cgit v1.2.3 From 4e950d1ef1c61c5a14bec967a317ee9a3bb5893b Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Wed, 1 Jun 2016 16:15:29 -0700 Subject: clk: stm32f4: Migrate to clk_hw based OF and registration APIs Now that we have clk_hw based provider APIs to register clks, we can get rid of struct clk pointers while registering clks in these drivers, allowing us to move closer to a clear split of consumer and provider clk APIs. Cc: Daniel Thompson Signed-off-by: Stephen Boyd Signed-off-by: Stephen Boyd --- drivers/clk/clk-stm32f4.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/clk/clk-stm32f4.c b/drivers/clk/clk-stm32f4.c index fd89e771107e..b6ca33f0c935 100644 --- a/drivers/clk/clk-stm32f4.c +++ b/drivers/clk/clk-stm32f4.c @@ -136,7 +136,7 @@ static const u64 stm32f42xx_gate_map[] = { 0x000000f17ef417ffull, 0x0000000000000001ull, 0x04777f33f6fec9ffull }; -static struct clk *clks[MAX_CLKS]; +static struct clk_hw *clks[MAX_CLKS]; static DEFINE_SPINLOCK(stm32f4_clk_lock); static void __iomem *base; @@ -281,7 +281,7 @@ static int stm32f4_rcc_lookup_clk_idx(u8 primary, u8 secondary) (BIT_ULL_WORD(secondary) >= 2 ? hweight64(table[2]) : 0); } -static struct clk * +static struct clk_hw * stm32f4_rcc_lookup_clk(struct of_phandle_args *clkspec, void *data) { int i = stm32f4_rcc_lookup_clk_idx(clkspec->args[0], clkspec->args[1]); @@ -346,9 +346,9 @@ static void __init stm32f4_rcc_init(struct device_node *np) clk_register_apb_mul(NULL, "apb2_mul", "apb2_div", CLK_SET_RATE_PARENT, 15); - clks[SYSTICK] = clk_register_fixed_factor(NULL, "systick", "ahb_div", + clks[SYSTICK] = clk_hw_register_fixed_factor(NULL, "systick", "ahb_div", 0, 1, 8); - clks[FCLK] = clk_register_fixed_factor(NULL, "fclk", "ahb_div", + clks[FCLK] = clk_hw_register_fixed_factor(NULL, "fclk", "ahb_div", 0, 1, 1); for (n = 0; n < ARRAY_SIZE(stm32f4_gates); n++) { @@ -360,7 +360,7 @@ static void __init stm32f4_rcc_init(struct device_node *np) if (idx < 0) goto fail; - clks[idx] = clk_register_gate( + clks[idx] = clk_hw_register_gate( NULL, gd->name, gd->parent_name, gd->flags, base + gd->offset, gd->bit_idx, 0, &stm32f4_clk_lock); @@ -371,7 +371,7 @@ static void __init stm32f4_rcc_init(struct device_node *np) } } - of_clk_add_provider(np, stm32f4_rcc_lookup_clk, NULL); + of_clk_add_hw_provider(np, stm32f4_rcc_lookup_clk, NULL); return; fail: iounmap(base); -- cgit v1.2.3 From b228fad50c009182ae012de35ee05cad9818d8b5 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Wed, 1 Jun 2016 16:15:24 -0700 Subject: clk: s2mps11: Migrate to clk_hw based OF and registration APIs Now that we have clk_hw based provider APIs to register clks, we can get rid of struct clk pointers while registering clks in these drivers, allowing us to move closer to a clear split of consumer and provider clk APIs. Signed-off-by: Stephen Boyd Acked-by: Andi Shyti Reviewed-by: Krzysztof Kozlowski Signed-off-by: Stephen Boyd --- drivers/clk/clk-s2mps11.c | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/drivers/clk/clk-s2mps11.c b/drivers/clk/clk-s2mps11.c index f8c83977c7fa..fbaa84a33c46 100644 --- a/drivers/clk/clk-s2mps11.c +++ b/drivers/clk/clk-s2mps11.c @@ -137,7 +137,7 @@ static int s2mps11_clk_probe(struct platform_device *pdev) { struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent); struct s2mps11_clk *s2mps11_clks; - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; unsigned int s2mps11_reg; int i, ret = 0; enum sec_device_type hwid = platform_get_device_id(pdev)->driver_data; @@ -147,15 +147,12 @@ static int s2mps11_clk_probe(struct platform_device *pdev) if (!s2mps11_clks) return -ENOMEM; - clk_data = devm_kzalloc(&pdev->dev, sizeof(*clk_data), GFP_KERNEL); + clk_data = devm_kzalloc(&pdev->dev, sizeof(*clk_data) + + sizeof(*clk_data->hws) * S2MPS11_CLKS_NUM, + GFP_KERNEL); if (!clk_data) return -ENOMEM; - clk_data->clks = devm_kcalloc(&pdev->dev, S2MPS11_CLKS_NUM, - sizeof(struct clk *), GFP_KERNEL); - if (!clk_data->clks) - return -ENOMEM; - switch (hwid) { case S2MPS11X: s2mps11_reg = S2MPS11_REG_RTC_CTRL; @@ -196,18 +193,18 @@ static int s2mps11_clk_probe(struct platform_device *pdev) goto err_reg; } - s2mps11_clks[i].lookup = clkdev_create(s2mps11_clks[i].clk, + s2mps11_clks[i].lookup = clkdev_hw_create(&s2mps11_clks[i].hw, s2mps11_clks_init[i].name, NULL); if (!s2mps11_clks[i].lookup) { ret = -ENOMEM; goto err_reg; } - clk_data->clks[i] = s2mps11_clks[i].clk; + clk_data->hws[i] = &s2mps11_clks[i].hw; } - clk_data->clk_num = S2MPS11_CLKS_NUM; - of_clk_add_provider(s2mps11_clks->clk_np, of_clk_src_onecell_get, - clk_data); + clk_data->num = S2MPS11_CLKS_NUM; + of_clk_add_hw_provider(s2mps11_clks->clk_np, of_clk_hw_onecell_get, + clk_data); platform_set_drvdata(pdev, s2mps11_clks); -- cgit v1.2.3 From 97b7129cd2afb478c4812781470f06d65f458825 Mon Sep 17 00:00:00 2001 From: Jiancheng Xue Date: Wed, 15 Jun 2016 14:26:34 +0800 Subject: reset: hisilicon: change the definition of hisi_reset_init Change the input arguments type to struct platform_device pointer. Signed-off-by: Jiancheng Xue Signed-off-by: Stephen Boyd --- drivers/clk/hisilicon/clk-hi3519.c | 2 +- drivers/clk/hisilicon/reset.c | 19 +++++++++---------- drivers/clk/hisilicon/reset.h | 5 +++-- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/drivers/clk/hisilicon/clk-hi3519.c b/drivers/clk/hisilicon/clk-hi3519.c index 715c7301a66a..8d12700d0cff 100644 --- a/drivers/clk/hisilicon/clk-hi3519.c +++ b/drivers/clk/hisilicon/clk-hi3519.c @@ -86,7 +86,7 @@ static int hi3519_clk_probe(struct platform_device *pdev) struct hisi_clock_data *clk_data; struct hisi_reset_controller *rstc; - rstc = hisi_reset_init(np); + rstc = hisi_reset_init(pdev); if (!rstc) return -ENOMEM; diff --git a/drivers/clk/hisilicon/reset.c b/drivers/clk/hisilicon/reset.c index 6aa49c2204d0..2a5015c736ce 100644 --- a/drivers/clk/hisilicon/reset.c +++ b/drivers/clk/hisilicon/reset.c @@ -19,6 +19,7 @@ #include #include +#include #include #include #include @@ -98,25 +99,25 @@ static const struct reset_control_ops hisi_reset_ops = { .deassert = hisi_reset_deassert, }; -struct hisi_reset_controller *hisi_reset_init(struct device_node *np) +struct hisi_reset_controller *hisi_reset_init(struct platform_device *pdev) { struct hisi_reset_controller *rstc; + struct resource *res; - rstc = kzalloc(sizeof(*rstc), GFP_KERNEL); + rstc = devm_kmalloc(&pdev->dev, sizeof(*rstc), GFP_KERNEL); if (!rstc) return NULL; - rstc->membase = of_iomap(np, 0); - if (!rstc->membase) { - kfree(rstc); + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + rstc->membase = devm_ioremap(&pdev->dev, + res->start, resource_size(res)); + if (!rstc->membase) return NULL; - } spin_lock_init(&rstc->lock); - rstc->rcdev.owner = THIS_MODULE; rstc->rcdev.ops = &hisi_reset_ops; - rstc->rcdev.of_node = np; + rstc->rcdev.of_node = pdev->dev.of_node; rstc->rcdev.of_reset_n_cells = 2; rstc->rcdev.of_xlate = hisi_reset_of_xlate; reset_controller_register(&rstc->rcdev); @@ -128,7 +129,5 @@ EXPORT_SYMBOL_GPL(hisi_reset_init); void hisi_reset_exit(struct hisi_reset_controller *rstc) { reset_controller_unregister(&rstc->rcdev); - iounmap(rstc->membase); - kfree(rstc); } EXPORT_SYMBOL_GPL(hisi_reset_exit); diff --git a/drivers/clk/hisilicon/reset.h b/drivers/clk/hisilicon/reset.h index 677d773ed27c..9a69374a0b32 100644 --- a/drivers/clk/hisilicon/reset.h +++ b/drivers/clk/hisilicon/reset.h @@ -22,10 +22,11 @@ struct device_node; struct hisi_reset_controller; #ifdef CONFIG_RESET_CONTROLLER -struct hisi_reset_controller *hisi_reset_init(struct device_node *np); +struct hisi_reset_controller *hisi_reset_init(struct platform_device *pdev); void hisi_reset_exit(struct hisi_reset_controller *rstc); #else -static inline hisi_reset_controller *hisi_reset_init(struct device_node *np) +static inline +struct hisi_reset_controller *hisi_reset_init(struct platform_device *pdev) { return 0; } -- cgit v1.2.3 From 322269163a36ac73be403120e046d90d6a1d38f1 Mon Sep 17 00:00:00 2001 From: Jiancheng Xue Date: Wed, 15 Jun 2016 14:26:35 +0800 Subject: clk: hisilicon: add hisi_clk_alloc function. Before, there was an ordering issue that the clock provider had been published in hisi_clk_init before it could provide valid clocks to consumers. hisi_clk_alloc is just used to allocate memory space for struct hisi_clock_data. It makes it possible to publish the provider after the clocks are ready. Signed-off-by: Jiancheng Xue Signed-off-by: Stephen Boyd --- drivers/clk/hisilicon/clk.c | 29 +++++++++++++++++++++++++++++ drivers/clk/hisilicon/clk.h | 3 +++ 2 files changed, 32 insertions(+) diff --git a/drivers/clk/hisilicon/clk.c b/drivers/clk/hisilicon/clk.c index 9b15adbfc30c..78675d172a65 100644 --- a/drivers/clk/hisilicon/clk.c +++ b/drivers/clk/hisilicon/clk.c @@ -37,6 +37,35 @@ static DEFINE_SPINLOCK(hisi_clk_lock); +struct hisi_clock_data *hisi_clk_alloc(struct platform_device *pdev, + int nr_clks) +{ + struct hisi_clock_data *clk_data; + struct resource *res; + struct clk **clk_table; + + clk_data = devm_kmalloc(&pdev->dev, sizeof(*clk_data), GFP_KERNEL); + if (!clk_data) + return NULL; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + clk_data->base = devm_ioremap(&pdev->dev, + res->start, resource_size(res)); + if (!clk_data->base) + return NULL; + + clk_table = devm_kmalloc(&pdev->dev, sizeof(struct clk *) * nr_clks, + GFP_KERNEL); + if (!clk_table) + return NULL; + + clk_data->clk_data.clks = clk_table; + clk_data->clk_data.clk_num = nr_clks; + + return clk_data; +} +EXPORT_SYMBOL_GPL(hisi_clk_alloc); + struct hisi_clock_data *hisi_clk_init(struct device_node *np, int nr_clks) { diff --git a/drivers/clk/hisilicon/clk.h b/drivers/clk/hisilicon/clk.h index 20d64afe4ad8..5fc644f4799f 100644 --- a/drivers/clk/hisilicon/clk.h +++ b/drivers/clk/hisilicon/clk.h @@ -30,6 +30,8 @@ #include #include +struct platform_device; + struct hisi_clock_data { struct clk_onecell_data clk_data; void __iomem *base; @@ -110,6 +112,7 @@ struct clk *hi6220_register_clkdiv(struct device *dev, const char *name, const char *parent_name, unsigned long flags, void __iomem *reg, u8 shift, u8 width, u32 mask_bit, spinlock_t *lock); +struct hisi_clock_data *hisi_clk_alloc(struct platform_device *, int); struct hisi_clock_data *hisi_clk_init(struct device_node *, int); void hisi_clk_register_fixed_rate(const struct hisi_fixed_rate_clock *, int, struct hisi_clock_data *); -- cgit v1.2.3 From 5497f668c8ca42717529a340abb1674df60bbe1c Mon Sep 17 00:00:00 2001 From: Jiancheng Xue Date: Wed, 15 Jun 2016 14:26:36 +0800 Subject: clk: hisilicon: add error processing for hisi_clk_register_* functions Add error processing for hisi_clk_register_* functions. Signed-off-by: Jiancheng Xue Signed-off-by: Stephen Boyd --- drivers/clk/hisilicon/clk.c | 60 +++++++++++++++++++++++++++++++++++++-------- drivers/clk/hisilicon/clk.h | 10 ++++---- 2 files changed, 55 insertions(+), 15 deletions(-) diff --git a/drivers/clk/hisilicon/clk.c b/drivers/clk/hisilicon/clk.c index 78675d172a65..9ba2d91f4d3a 100644 --- a/drivers/clk/hisilicon/clk.c +++ b/drivers/clk/hisilicon/clk.c @@ -102,7 +102,7 @@ err: } EXPORT_SYMBOL_GPL(hisi_clk_init); -void hisi_clk_register_fixed_rate(const struct hisi_fixed_rate_clock *clks, +int hisi_clk_register_fixed_rate(const struct hisi_fixed_rate_clock *clks, int nums, struct hisi_clock_data *data) { struct clk *clk; @@ -116,14 +116,22 @@ void hisi_clk_register_fixed_rate(const struct hisi_fixed_rate_clock *clks, if (IS_ERR(clk)) { pr_err("%s: failed to register clock %s\n", __func__, clks[i].name); - continue; + goto err; } data->clk_data.clks[clks[i].id] = clk; } + + return 0; + +err: + while (i--) + clk_unregister_fixed_rate(data->clk_data.clks[clks[i].id]); + + return PTR_ERR(clk); } EXPORT_SYMBOL_GPL(hisi_clk_register_fixed_rate); -void hisi_clk_register_fixed_factor(const struct hisi_fixed_factor_clock *clks, +int hisi_clk_register_fixed_factor(const struct hisi_fixed_factor_clock *clks, int nums, struct hisi_clock_data *data) { @@ -138,14 +146,22 @@ void hisi_clk_register_fixed_factor(const struct hisi_fixed_factor_clock *clks, if (IS_ERR(clk)) { pr_err("%s: failed to register clock %s\n", __func__, clks[i].name); - continue; + goto err; } data->clk_data.clks[clks[i].id] = clk; } + + return 0; + +err: + while (i--) + clk_unregister_fixed_factor(data->clk_data.clks[clks[i].id]); + + return PTR_ERR(clk); } EXPORT_SYMBOL_GPL(hisi_clk_register_fixed_factor); -void hisi_clk_register_mux(const struct hisi_mux_clock *clks, +int hisi_clk_register_mux(const struct hisi_mux_clock *clks, int nums, struct hisi_clock_data *data) { struct clk *clk; @@ -164,7 +180,7 @@ void hisi_clk_register_mux(const struct hisi_mux_clock *clks, if (IS_ERR(clk)) { pr_err("%s: failed to register clock %s\n", __func__, clks[i].name); - continue; + goto err; } if (clks[i].alias) @@ -172,10 +188,18 @@ void hisi_clk_register_mux(const struct hisi_mux_clock *clks, data->clk_data.clks[clks[i].id] = clk; } + + return 0; + +err: + while (i--) + clk_unregister_mux(data->clk_data.clks[clks[i].id]); + + return PTR_ERR(clk); } EXPORT_SYMBOL_GPL(hisi_clk_register_mux); -void hisi_clk_register_divider(const struct hisi_divider_clock *clks, +int hisi_clk_register_divider(const struct hisi_divider_clock *clks, int nums, struct hisi_clock_data *data) { struct clk *clk; @@ -194,7 +218,7 @@ void hisi_clk_register_divider(const struct hisi_divider_clock *clks, if (IS_ERR(clk)) { pr_err("%s: failed to register clock %s\n", __func__, clks[i].name); - continue; + goto err; } if (clks[i].alias) @@ -202,10 +226,18 @@ void hisi_clk_register_divider(const struct hisi_divider_clock *clks, data->clk_data.clks[clks[i].id] = clk; } + + return 0; + +err: + while (i--) + clk_unregister_divider(data->clk_data.clks[clks[i].id]); + + return PTR_ERR(clk); } EXPORT_SYMBOL_GPL(hisi_clk_register_divider); -void hisi_clk_register_gate(const struct hisi_gate_clock *clks, +int hisi_clk_register_gate(const struct hisi_gate_clock *clks, int nums, struct hisi_clock_data *data) { struct clk *clk; @@ -223,7 +255,7 @@ void hisi_clk_register_gate(const struct hisi_gate_clock *clks, if (IS_ERR(clk)) { pr_err("%s: failed to register clock %s\n", __func__, clks[i].name); - continue; + goto err; } if (clks[i].alias) @@ -231,6 +263,14 @@ void hisi_clk_register_gate(const struct hisi_gate_clock *clks, data->clk_data.clks[clks[i].id] = clk; } + + return 0; + +err: + while (i--) + clk_unregister_gate(data->clk_data.clks[clks[i].id]); + + return PTR_ERR(clk); } EXPORT_SYMBOL_GPL(hisi_clk_register_gate); diff --git a/drivers/clk/hisilicon/clk.h b/drivers/clk/hisilicon/clk.h index 5fc644f4799f..257532945c58 100644 --- a/drivers/clk/hisilicon/clk.h +++ b/drivers/clk/hisilicon/clk.h @@ -114,15 +114,15 @@ struct clk *hi6220_register_clkdiv(struct device *dev, const char *name, struct hisi_clock_data *hisi_clk_alloc(struct platform_device *, int); struct hisi_clock_data *hisi_clk_init(struct device_node *, int); -void hisi_clk_register_fixed_rate(const struct hisi_fixed_rate_clock *, +int hisi_clk_register_fixed_rate(const struct hisi_fixed_rate_clock *, int, struct hisi_clock_data *); -void hisi_clk_register_fixed_factor(const struct hisi_fixed_factor_clock *, +int hisi_clk_register_fixed_factor(const struct hisi_fixed_factor_clock *, int, struct hisi_clock_data *); -void hisi_clk_register_mux(const struct hisi_mux_clock *, int, +int hisi_clk_register_mux(const struct hisi_mux_clock *, int, struct hisi_clock_data *); -void hisi_clk_register_divider(const struct hisi_divider_clock *, +int hisi_clk_register_divider(const struct hisi_divider_clock *, int, struct hisi_clock_data *); -void hisi_clk_register_gate(const struct hisi_gate_clock *, +int hisi_clk_register_gate(const struct hisi_gate_clock *, int, struct hisi_clock_data *); void hisi_clk_register_gate_sep(const struct hisi_gate_clock *, int, struct hisi_clock_data *); -- cgit v1.2.3 From fbf0410ed5f96ae63fcb221ab785e746871a4e62 Mon Sep 17 00:00:00 2001 From: Jiancheng Xue Date: Wed, 15 Jun 2016 14:26:37 +0800 Subject: clk: hisilicon: add hisi_clk_unregister_* functions Add hisi_clk_unregister_* functions. Signed-off-by: Jiancheng Xue Signed-off-by: Stephen Boyd --- drivers/clk/hisilicon/clk.h | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/drivers/clk/hisilicon/clk.h b/drivers/clk/hisilicon/clk.h index 257532945c58..4e1d1affc6f5 100644 --- a/drivers/clk/hisilicon/clk.h +++ b/drivers/clk/hisilicon/clk.h @@ -128,4 +128,25 @@ void hisi_clk_register_gate_sep(const struct hisi_gate_clock *, int, struct hisi_clock_data *); void hi6220_clk_register_divider(const struct hi6220_divider_clock *, int, struct hisi_clock_data *); + +#define hisi_clk_unregister(type) \ +static inline \ +void hisi_clk_unregister_##type(const struct hisi_##type##_clock *clks, \ + int nums, struct hisi_clock_data *data) \ +{ \ + struct clk **clocks = data->clk_data.clks; \ + int i; \ + for (i = 0; i < nums; i++) { \ + int id = clks[i].id; \ + if (clocks[id]) \ + clk_unregister_##type(clocks[id]); \ + } \ +} + +hisi_clk_unregister(fixed_rate) +hisi_clk_unregister(fixed_factor) +hisi_clk_unregister(mux) +hisi_clk_unregister(divider) +hisi_clk_unregister(gate) + #endif /* __HISI_CLK_H */ -- cgit v1.2.3 From 224b3b262c52ef3b13ec62cd879b48d2611c2c10 Mon Sep 17 00:00:00 2001 From: Jiancheng Xue Date: Wed, 15 Jun 2016 14:26:38 +0800 Subject: clk: hisilicon: hi3519: add driver remove path and fix some issues 1. Add driver remove path. 2. Fix some issues. -Fix the ordering issue about clock provider being published. -Add error checking upon registering clocks. Signed-off-by: Jiancheng Xue Signed-off-by: Stephen Boyd --- drivers/clk/hisilicon/clk-hi3519.c | 116 ++++++++++++++++++++++++++++++++----- 1 file changed, 100 insertions(+), 16 deletions(-) diff --git a/drivers/clk/hisilicon/clk-hi3519.c b/drivers/clk/hisilicon/clk-hi3519.c index 8d12700d0cff..51b173ef1dda 100644 --- a/drivers/clk/hisilicon/clk-hi3519.c +++ b/drivers/clk/hisilicon/clk-hi3519.c @@ -38,6 +38,11 @@ #define HI3519_NR_CLKS 128 +struct hi3519_crg_data { + struct hisi_clock_data *clk_data; + struct hisi_reset_controller *rstc; +}; + static const struct hisi_fixed_rate_clock hi3519_fixed_rate_clks[] = { { HI3519_FIXED_24M, "24m", NULL, 0, 24000000, }, { HI3519_FIXED_50M, "50m", NULL, 0, 50000000, }, @@ -80,33 +85,105 @@ static const struct hisi_gate_clock hi3519_gate_clks[] = { CLK_SET_RATE_PARENT, 0xe4, 18, 0, }, }; -static int hi3519_clk_probe(struct platform_device *pdev) +static struct hisi_clock_data *hi3519_clk_register(struct platform_device *pdev) { - struct device_node *np = pdev->dev.of_node; struct hisi_clock_data *clk_data; - struct hisi_reset_controller *rstc; + int ret; - rstc = hisi_reset_init(pdev); - if (!rstc) + clk_data = hisi_clk_alloc(pdev, HI3519_NR_CLKS); + if (!clk_data) + return ERR_PTR(-ENOMEM); + + ret = hisi_clk_register_fixed_rate(hi3519_fixed_rate_clks, + ARRAY_SIZE(hi3519_fixed_rate_clks), + clk_data); + if (ret) + return ERR_PTR(ret); + + ret = hisi_clk_register_mux(hi3519_mux_clks, + ARRAY_SIZE(hi3519_mux_clks), + clk_data); + if (ret) + goto unregister_fixed_rate; + + ret = hisi_clk_register_gate(hi3519_gate_clks, + ARRAY_SIZE(hi3519_gate_clks), + clk_data); + if (ret) + goto unregister_mux; + + ret = of_clk_add_provider(pdev->dev.of_node, + of_clk_src_onecell_get, &clk_data->clk_data); + if (ret) + goto unregister_gate; + + return clk_data; + +unregister_fixed_rate: + hisi_clk_unregister_fixed_rate(hi3519_fixed_rate_clks, + ARRAY_SIZE(hi3519_fixed_rate_clks), + clk_data); + +unregister_mux: + hisi_clk_unregister_mux(hi3519_mux_clks, + ARRAY_SIZE(hi3519_mux_clks), + clk_data); +unregister_gate: + hisi_clk_unregister_gate(hi3519_gate_clks, + ARRAY_SIZE(hi3519_gate_clks), + clk_data); + return ERR_PTR(ret); +} + +static void hi3519_clk_unregister(struct platform_device *pdev) +{ + struct hi3519_crg_data *crg = platform_get_drvdata(pdev); + + of_clk_del_provider(pdev->dev.of_node); + + hisi_clk_unregister_gate(hi3519_gate_clks, + ARRAY_SIZE(hi3519_mux_clks), + crg->clk_data); + hisi_clk_unregister_mux(hi3519_mux_clks, + ARRAY_SIZE(hi3519_mux_clks), + crg->clk_data); + hisi_clk_unregister_fixed_rate(hi3519_fixed_rate_clks, + ARRAY_SIZE(hi3519_fixed_rate_clks), + crg->clk_data); +} + +static int hi3519_clk_probe(struct platform_device *pdev) +{ + struct hi3519_crg_data *crg; + + crg = devm_kmalloc(&pdev->dev, sizeof(*crg), GFP_KERNEL); + if (!crg) + return -ENOMEM; + + crg->rstc = hisi_reset_init(pdev); + if (!crg->rstc) return -ENOMEM; - clk_data = hisi_clk_init(np, HI3519_NR_CLKS); - if (!clk_data) { - hisi_reset_exit(rstc); - return -ENODEV; + crg->clk_data = hi3519_clk_register(pdev); + if (IS_ERR(crg->clk_data)) { + hisi_reset_exit(crg->rstc); + return PTR_ERR(crg->clk_data); } - hisi_clk_register_fixed_rate(hi3519_fixed_rate_clks, - ARRAY_SIZE(hi3519_fixed_rate_clks), - clk_data); - hisi_clk_register_mux(hi3519_mux_clks, ARRAY_SIZE(hi3519_mux_clks), - clk_data); - hisi_clk_register_gate(hi3519_gate_clks, - ARRAY_SIZE(hi3519_gate_clks), clk_data); + platform_set_drvdata(pdev, crg); + return 0; +} + +static int hi3519_clk_remove(struct platform_device *pdev) +{ + struct hi3519_crg_data *crg = platform_get_drvdata(pdev); + hisi_reset_exit(crg->rstc); + hi3519_clk_unregister(pdev); return 0; } + static const struct of_device_id hi3519_clk_match_table[] = { { .compatible = "hisilicon,hi3519-crg" }, { } @@ -115,6 +192,7 @@ MODULE_DEVICE_TABLE(of, hi3519_clk_match_table); static struct platform_driver hi3519_clk_driver = { .probe = hi3519_clk_probe, + .remove = hi3519_clk_remove, .driver = { .name = "hi3519-clk", .of_match_table = hi3519_clk_match_table, @@ -127,5 +205,11 @@ static int __init hi3519_clk_init(void) } core_initcall(hi3519_clk_init); +static void __exit hi3519_clk_exit(void) +{ + platform_driver_unregister(&hi3519_clk_driver); +} +module_exit(hi3519_clk_exit); + MODULE_LICENSE("GPL v2"); MODULE_DESCRIPTION("HiSilicon Hi3519 Clock Driver"); -- cgit v1.2.3 From 52445637371e5a30c0320eae75970c28f982d914 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sun, 22 May 2016 14:33:35 +0900 Subject: clk: fixed-rate: add clk_hw_unregister_fixed_rate() This will be used to migrate to the clk_hw APIs. Signed-off-by: Masahiro Yamada Signed-off-by: Stephen Boyd --- drivers/clk/clk-fixed-rate.c | 11 +++++++++++ include/linux/clk-provider.h | 1 + 2 files changed, 12 insertions(+) diff --git a/drivers/clk/clk-fixed-rate.c b/drivers/clk/clk-fixed-rate.c index 8e4453eb54e8..2edb39342a02 100644 --- a/drivers/clk/clk-fixed-rate.c +++ b/drivers/clk/clk-fixed-rate.c @@ -145,6 +145,17 @@ void clk_unregister_fixed_rate(struct clk *clk) } EXPORT_SYMBOL_GPL(clk_unregister_fixed_rate); +void clk_hw_unregister_fixed_rate(struct clk_hw *hw) +{ + struct clk_fixed_rate *fixed; + + fixed = to_clk_fixed_rate(hw); + + clk_hw_unregister(hw); + kfree(fixed); +} +EXPORT_SYMBOL_GPL(clk_hw_unregister_fixed_rate); + #ifdef CONFIG_OF /** * of_fixed_clk_setup() - Setup function for simple fixed rate clock diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index 0c72204c75fc..94e00fe976f5 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -293,6 +293,7 @@ void clk_unregister_fixed_rate(struct clk *clk); struct clk_hw *clk_hw_register_fixed_rate_with_accuracy(struct device *dev, const char *name, const char *parent_name, unsigned long flags, unsigned long fixed_rate, unsigned long fixed_accuracy); +void clk_hw_unregister_fixed_rate(struct clk_hw *hw); void of_fixed_clk_setup(struct device_node *np); -- cgit v1.2.3 From cb87df58bca917c6c11cd273e61544c9b8b60189 Mon Sep 17 00:00:00 2001 From: Xing Zheng Date: Tue, 21 Jun 2016 12:53:28 +0800 Subject: clk: rockchip: include rk3228 downstream muxes into fractional dividers During the initial conversion to the newly introduced combined fractional dividers+muxes the rk3228 clocks were left out, so convert them now. Signed-off-by: Xing Zheng Signed-off-by: Heiko Stuebner --- drivers/clk/rockchip/clk-rk3228.c | 81 +++++++++++++++++++++++++-------------- 1 file changed, 52 insertions(+), 29 deletions(-) diff --git a/drivers/clk/rockchip/clk-rk3228.c b/drivers/clk/rockchip/clk-rk3228.c index 62c68346f3d7..72bcdbacecfd 100644 --- a/drivers/clk/rockchip/clk-rk3228.c +++ b/drivers/clk/rockchip/clk-rk3228.c @@ -170,6 +170,34 @@ static struct rockchip_pll_clock rk3228_pll_clks[] __initdata = { #define DFLAGS CLK_DIVIDER_HIWORD_MASK #define GFLAGS (CLK_GATE_HIWORD_MASK | CLK_GATE_SET_TO_DISABLE) +static struct rockchip_clk_branch rk3228_i2s0_fracmux __initdata = + MUX(0, "i2s0_pre", mux_i2s0_p, CLK_SET_RATE_PARENT, + RK2928_CLKSEL_CON(9), 8, 2, MFLAGS); + +static struct rockchip_clk_branch rk3228_i2s1_fracmux __initdata = + MUX(0, "i2s1_pre", mux_i2s1_pre_p, CLK_SET_RATE_PARENT, + RK2928_CLKSEL_CON(3), 8, 2, MFLAGS); + +static struct rockchip_clk_branch rk3228_i2s2_fracmux __initdata = + MUX(0, "i2s2_pre", mux_i2s2_p, CLK_SET_RATE_PARENT, + RK2928_CLKSEL_CON(16), 8, 2, MFLAGS); + +static struct rockchip_clk_branch rk3228_spdif_fracmux __initdata = + MUX(SCLK_SPDIF, "sclk_spdif", mux_sclk_spdif_p, CLK_SET_RATE_PARENT, + RK2928_CLKSEL_CON(6), 8, 2, MFLAGS); + +static struct rockchip_clk_branch rk3228_uart0_fracmux __initdata = + MUX(SCLK_UART0, "sclk_uart0", mux_uart0_p, CLK_SET_RATE_PARENT, + RK2928_CLKSEL_CON(13), 8, 2, MFLAGS); + +static struct rockchip_clk_branch rk3228_uart1_fracmux __initdata = + MUX(SCLK_UART1, "sclk_uart1", mux_uart1_p, CLK_SET_RATE_PARENT, + RK2928_CLKSEL_CON(14), 8, 2, MFLAGS); + +static struct rockchip_clk_branch rk3228_uart2_fracmux __initdata = + MUX(SCLK_UART2, "sclk_uart2", mux_uart2_p, CLK_SET_RATE_PARENT, + RK2928_CLKSEL_CON(15), 8, 2, MFLAGS); + static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = { /* * Clock-Architecture Diagram 1 @@ -379,22 +407,21 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = { COMPOSITE(0, "i2s0_src", mux_pll_src_2plls_p, 0, RK2928_CLKSEL_CON(9), 15, 1, MFLAGS, 0, 7, DFLAGS, RK2928_CLKGATE_CON(0), 3, GFLAGS), - COMPOSITE_FRAC(0, "i2s0_frac", "i2s0_src", CLK_SET_RATE_PARENT, + COMPOSITE_FRACMUX(0, "i2s0_frac", "i2s0_src", CLK_SET_RATE_PARENT, RK2928_CLKSEL_CON(8), 0, - RK2928_CLKGATE_CON(0), 4, GFLAGS), - COMPOSITE_NODIV(SCLK_I2S0, "sclk_i2s0", mux_i2s0_p, 0, - RK2928_CLKSEL_CON(9), 8, 2, MFLAGS, + RK2928_CLKGATE_CON(0), 4, GFLAGS, + &rk3228_i2s0_fracmux), + GATE(SCLK_I2S0, "sclk_i2s0", "i2s0_pre", CLK_SET_RATE_PARENT, RK2928_CLKGATE_CON(0), 5, GFLAGS), COMPOSITE(0, "i2s1_src", mux_pll_src_2plls_p, 0, RK2928_CLKSEL_CON(3), 15, 1, MFLAGS, 0, 7, DFLAGS, RK2928_CLKGATE_CON(0), 10, GFLAGS), - COMPOSITE_FRAC(0, "i2s1_frac", "i2s1_src", CLK_SET_RATE_PARENT, + COMPOSITE_FRACMUX(0, "i2s1_frac", "i2s1_src", CLK_SET_RATE_PARENT, RK2928_CLKSEL_CON(7), 0, - RK2928_CLKGATE_CON(0), 11, GFLAGS), - MUX(0, "i2s1_pre", mux_i2s1_pre_p, 0, - RK2928_CLKSEL_CON(3), 8, 2, MFLAGS), - GATE(SCLK_I2S1, "sclk_i2s1", "i2s1_pre", 0, + RK2928_CLKGATE_CON(0), 11, GFLAGS, + &rk3228_i2s1_fracmux), + GATE(SCLK_I2S1, "sclk_i2s1", "i2s1_pre", CLK_SET_RATE_PARENT, RK2928_CLKGATE_CON(0), 14, GFLAGS), COMPOSITE_NODIV(SCLK_I2S_OUT, "i2s_out", mux_i2s_out_p, 0, RK2928_CLKSEL_CON(3), 12, 1, MFLAGS, @@ -403,21 +430,20 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = { COMPOSITE(0, "i2s2_src", mux_pll_src_2plls_p, 0, RK2928_CLKSEL_CON(16), 15, 1, MFLAGS, 0, 7, DFLAGS, RK2928_CLKGATE_CON(0), 7, GFLAGS), - COMPOSITE_FRAC(0, "i2s2_frac", "i2s2_src", CLK_SET_RATE_PARENT, + COMPOSITE_FRACMUX(0, "i2s2_frac", "i2s2_src", CLK_SET_RATE_PARENT, RK2928_CLKSEL_CON(30), 0, - RK2928_CLKGATE_CON(0), 8, GFLAGS), - COMPOSITE_NODIV(SCLK_I2S2, "sclk_i2s2", mux_i2s2_p, 0, - RK2928_CLKSEL_CON(16), 8, 2, MFLAGS, + RK2928_CLKGATE_CON(0), 8, GFLAGS, + &rk3228_i2s2_fracmux), + GATE(SCLK_I2S2, "sclk_i2s2", "i2s2_pre", CLK_SET_RATE_PARENT, RK2928_CLKGATE_CON(0), 9, GFLAGS), COMPOSITE(0, "sclk_spdif_src", mux_pll_src_2plls_p, 0, RK2928_CLKSEL_CON(6), 15, 1, MFLAGS, 0, 7, DFLAGS, RK2928_CLKGATE_CON(2), 10, GFLAGS), - COMPOSITE_FRAC(0, "spdif_frac", "sclk_spdif_src", CLK_SET_RATE_PARENT, + COMPOSITE_FRACMUX(0, "spdif_frac", "sclk_spdif_src", CLK_SET_RATE_PARENT, RK2928_CLKSEL_CON(20), 0, - RK2928_CLKGATE_CON(2), 12, GFLAGS), - MUX(SCLK_SPDIF, "sclk_spdif", mux_sclk_spdif_p, 0, - RK2928_CLKSEL_CON(6), 8, 2, MFLAGS), + RK2928_CLKGATE_CON(2), 12, GFLAGS, + &rk3228_spdif_fracmux), GATE(0, "jtag", "ext_jtag", 0, RK2928_CLKGATE_CON(1), 3, GFLAGS), @@ -456,21 +482,18 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = { COMPOSITE(0, "uart2_src", mux_pll_src_cpll_gpll_usb480m_p, 0, RK2928_CLKSEL_CON(15), 12, 2, MFLAGS, 0, 7, DFLAGS, RK2928_CLKGATE_CON(1), 12, GFLAGS), - COMPOSITE_FRAC(0, "uart0_frac", "uart0_src", CLK_SET_RATE_PARENT, + COMPOSITE_FRACMUX(0, "uart0_frac", "uart0_src", CLK_SET_RATE_PARENT, RK2928_CLKSEL_CON(17), 0, - RK2928_CLKGATE_CON(1), 9, GFLAGS), - COMPOSITE_FRAC(0, "uart1_frac", "uart1_src", CLK_SET_RATE_PARENT, + RK2928_CLKGATE_CON(1), 9, GFLAGS, + &rk3228_uart0_fracmux), + COMPOSITE_FRACMUX(0, "uart1_frac", "uart1_src", CLK_SET_RATE_PARENT, RK2928_CLKSEL_CON(18), 0, - RK2928_CLKGATE_CON(1), 11, GFLAGS), - COMPOSITE_FRAC(0, "uart2_frac", "uart2_src", CLK_SET_RATE_PARENT, + RK2928_CLKGATE_CON(1), 11, GFLAGS, + &rk3228_uart1_fracmux), + COMPOSITE_FRACMUX(0, "uart2_frac", "uart2_src", CLK_SET_RATE_PARENT, RK2928_CLKSEL_CON(19), 0, - RK2928_CLKGATE_CON(1), 13, GFLAGS), - MUX(SCLK_UART0, "sclk_uart0", mux_uart0_p, CLK_SET_RATE_PARENT, - RK2928_CLKSEL_CON(13), 8, 2, MFLAGS), - MUX(SCLK_UART1, "sclk_uart1", mux_uart1_p, CLK_SET_RATE_PARENT, - RK2928_CLKSEL_CON(14), 8, 2, MFLAGS), - MUX(SCLK_UART2, "sclk_uart2", mux_uart2_p, CLK_SET_RATE_PARENT, - RK2928_CLKSEL_CON(15), 8, 2, MFLAGS), + RK2928_CLKGATE_CON(1), 13, GFLAGS, + &rk3228_uart2_fracmux), COMPOSITE(SCLK_NANDC, "sclk_nandc", mux_pll_src_2plls_p, 0, RK2928_CLKSEL_CON(2), 14, 1, MFLAGS, 8, 5, DFLAGS, -- cgit v1.2.3 From a45c072bb408a9c6ee2f77c209339625f70607ff Mon Sep 17 00:00:00 2001 From: Xing Zheng Date: Tue, 21 Jun 2016 12:53:29 +0800 Subject: clk: rockchip: export rk3228 audio clocks This patch exports related i2s/spdif clocks for dts reference. Signed-off-by: Xing Zheng Signed-off-by: Heiko Stuebner --- drivers/clk/rockchip/clk-rk3228.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/clk/rockchip/clk-rk3228.c b/drivers/clk/rockchip/clk-rk3228.c index 72bcdbacecfd..79a3db18b712 100644 --- a/drivers/clk/rockchip/clk-rk3228.c +++ b/drivers/clk/rockchip/clk-rk3228.c @@ -581,10 +581,10 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = { GATE(0, "aclk_bus_noc", "aclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(10), 1, GFLAGS), GATE(0, "hclk_rom", "hclk_cpu", 0, RK2928_CLKGATE_CON(8), 3, GFLAGS), - GATE(0, "hclk_i2s0_8ch", "hclk_cpu", 0, RK2928_CLKGATE_CON(8), 7, GFLAGS), - GATE(0, "hclk_i2s1_8ch", "hclk_cpu", 0, RK2928_CLKGATE_CON(8), 8, GFLAGS), - GATE(0, "hclk_i2s2_2ch", "hclk_cpu", 0, RK2928_CLKGATE_CON(8), 9, GFLAGS), - GATE(0, "hclk_spdif_8ch", "hclk_cpu", 0, RK2928_CLKGATE_CON(8), 10, GFLAGS), + GATE(HCLK_I2S0_8CH, "hclk_i2s0_8ch", "hclk_cpu", 0, RK2928_CLKGATE_CON(8), 7, GFLAGS), + GATE(HCLK_I2S1_8CH, "hclk_i2s1_8ch", "hclk_cpu", 0, RK2928_CLKGATE_CON(8), 8, GFLAGS), + GATE(HCLK_I2S2_2CH, "hclk_i2s2_2ch", "hclk_cpu", 0, RK2928_CLKGATE_CON(8), 9, GFLAGS), + GATE(HCLK_SPDIF_8CH, "hclk_spdif_8ch", "hclk_cpu", 0, RK2928_CLKGATE_CON(8), 10, GFLAGS), GATE(0, "hclk_tsp", "hclk_cpu", 0, RK2928_CLKGATE_CON(10), 11, GFLAGS), GATE(0, "hclk_crypto_mst", "hclk_cpu", 0, RK2928_CLKGATE_CON(8), 11, GFLAGS), GATE(0, "hclk_crypto_slv", "hclk_cpu", 0, RK2928_CLKGATE_CON(8), 12, GFLAGS), -- cgit v1.2.3 From 09f684226db2d4ee8bce5dd5086c965096766864 Mon Sep 17 00:00:00 2001 From: Xing Zheng Date: Tue, 21 Jun 2016 12:53:30 +0800 Subject: clk: rockchip: rename rk3228 sclk_macphy_50m to sclk_mac_extclk The sclk_macphy_50m is confusing, the sclk_mac_extclk describes a external clock clearly. Signed-off-by: Xing Zheng Signed-off-by: Heiko Stuebner --- drivers/clk/rockchip/clk-rk3228.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/clk/rockchip/clk-rk3228.c b/drivers/clk/rockchip/clk-rk3228.c index 79a3db18b712..980d0da69972 100644 --- a/drivers/clk/rockchip/clk-rk3228.c +++ b/drivers/clk/rockchip/clk-rk3228.c @@ -151,8 +151,8 @@ PNAME(mux_uart0_p) = { "uart0_src", "uart0_frac", "xin24m" }; PNAME(mux_uart1_p) = { "uart1_src", "uart1_frac", "xin24m" }; PNAME(mux_uart2_p) = { "uart2_src", "uart2_frac", "xin24m" }; -PNAME(mux_sclk_macphy_50m_p) = { "ext_gmac", "phy_50m_out" }; -PNAME(mux_sclk_gmac_pre_p) = { "sclk_gmac_src", "sclk_macphy_50m" }; +PNAME(mux_sclk_mac_extclk_p) = { "ext_gmac", "phy_50m_out" }; +PNAME(mux_sclk_gmac_pre_p) = { "sclk_gmac_src", "sclk_mac_extclk" }; PNAME(mux_sclk_macphy_p) = { "sclk_gmac_src", "ext_gmac" }; static struct rockchip_pll_clock rk3228_pll_clks[] __initdata = { @@ -502,7 +502,7 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = { COMPOSITE(0, "sclk_gmac_src", mux_pll_src_2plls_p, 0, RK2928_CLKSEL_CON(5), 7, 1, MFLAGS, 0, 5, DFLAGS, RK2928_CLKGATE_CON(1), 7, GFLAGS), - MUX(0, "sclk_macphy_50m", mux_sclk_macphy_50m_p, 0, + MUX(0, "sclk_mac_extclk", mux_sclk_mac_extclk_p, 0, RK2928_CLKSEL_CON(29), 10, 1, MFLAGS), MUX(0, "sclk_gmac_pre", mux_sclk_gmac_pre_p, 0, RK2928_CLKSEL_CON(5), 5, 1, MFLAGS), -- cgit v1.2.3 From 6e3732a2bebc3f08a59d2eafc2aa613b92055e3f Mon Sep 17 00:00:00 2001 From: Xing Zheng Date: Tue, 21 Jun 2016 12:59:47 +0800 Subject: clk: rockchip: export rk3228 MAC clocks This patch exports related MAC clocks for dts reference. Signed-off-by: Xing Zheng Signed-off-by: Heiko Stuebner --- drivers/clk/rockchip/clk-rk3228.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/clk/rockchip/clk-rk3228.c b/drivers/clk/rockchip/clk-rk3228.c index 980d0da69972..db6e5a9e6de6 100644 --- a/drivers/clk/rockchip/clk-rk3228.c +++ b/drivers/clk/rockchip/clk-rk3228.c @@ -499,25 +499,25 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = { RK2928_CLKSEL_CON(2), 14, 1, MFLAGS, 8, 5, DFLAGS, RK2928_CLKGATE_CON(1), 0, GFLAGS), - COMPOSITE(0, "sclk_gmac_src", mux_pll_src_2plls_p, 0, + COMPOSITE(SCLK_MAC_SRC, "sclk_gmac_src", mux_pll_src_2plls_p, 0, RK2928_CLKSEL_CON(5), 7, 1, MFLAGS, 0, 5, DFLAGS, RK2928_CLKGATE_CON(1), 7, GFLAGS), - MUX(0, "sclk_mac_extclk", mux_sclk_mac_extclk_p, 0, + MUX(SCLK_MAC_EXTCLK, "sclk_mac_extclk", mux_sclk_mac_extclk_p, 0, RK2928_CLKSEL_CON(29), 10, 1, MFLAGS), - MUX(0, "sclk_gmac_pre", mux_sclk_gmac_pre_p, 0, + MUX(SCLK_MAC, "sclk_gmac_pre", mux_sclk_gmac_pre_p, 0, RK2928_CLKSEL_CON(5), 5, 1, MFLAGS), - GATE(0, "sclk_mac_refout", "sclk_gmac_pre", 0, + GATE(SCLK_MAC_REFOUT, "sclk_mac_refout", "sclk_gmac_pre", 0, RK2928_CLKGATE_CON(5), 4, GFLAGS), - GATE(0, "sclk_mac_ref", "sclk_gmac_pre", 0, + GATE(SCLK_MAC_REF, "sclk_mac_ref", "sclk_gmac_pre", 0, RK2928_CLKGATE_CON(5), 3, GFLAGS), - GATE(0, "sclk_mac_rx", "sclk_gmac_pre", 0, + GATE(SCLK_MAC_RX, "sclk_mac_rx", "sclk_gmac_pre", 0, RK2928_CLKGATE_CON(5), 5, GFLAGS), - GATE(0, "sclk_mac_tx", "sclk_gmac_pre", 0, + GATE(SCLK_MAC_TX, "sclk_mac_tx", "sclk_gmac_pre", 0, RK2928_CLKGATE_CON(5), 6, GFLAGS), - COMPOSITE(0, "sclk_macphy", mux_sclk_macphy_p, 0, + COMPOSITE(SCLK_MAC_PHY, "sclk_macphy", mux_sclk_macphy_p, 0, RK2928_CLKSEL_CON(29), 12, 1, MFLAGS, 8, 2, DFLAGS, RK2928_CLKGATE_CON(5), 7, GFLAGS), - COMPOSITE(0, "sclk_gmac_out", mux_pll_src_2plls_p, 0, + COMPOSITE(SCLK_MAC_OUT, "sclk_gmac_out", mux_pll_src_2plls_p, 0, RK2928_CLKSEL_CON(5), 15, 1, MFLAGS, 8, 5, DFLAGS, RK2928_CLKGATE_CON(2), 2, GFLAGS), @@ -551,7 +551,7 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = { /* PD_PERI */ GATE(0, "aclk_peri_noc", "aclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(12), 0, GFLAGS), - GATE(0, "aclk_gmac", "aclk_peri", 0, RK2928_CLKGATE_CON(11), 4, GFLAGS), + GATE(ACLK_GMAC, "aclk_gmac", "aclk_peri", 0, RK2928_CLKGATE_CON(11), 4, GFLAGS), GATE(HCLK_SDMMC, "hclk_sdmmc", "hclk_peri", 0, RK2928_CLKGATE_CON(11), 0, GFLAGS), GATE(HCLK_SDIO, "hclk_sdio", "hclk_peri", 0, RK2928_CLKGATE_CON(11), 1, GFLAGS), @@ -567,7 +567,7 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = { GATE(0, "hclk_host2_arb", "hclk_peri", 0, RK2928_CLKGATE_CON(11), 14, GFLAGS), GATE(0, "hclk_peri_noc", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(12), 1, GFLAGS), - GATE(0, "pclk_gmac", "pclk_peri", 0, RK2928_CLKGATE_CON(11), 5, GFLAGS), + GATE(PCLK_GMAC, "pclk_gmac", "pclk_peri", 0, RK2928_CLKGATE_CON(11), 5, GFLAGS), GATE(0, "pclk_peri_noc", "pclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(12), 2, GFLAGS), /* PD_GPU */ -- cgit v1.2.3 From 3770821fa360525e6c726cd562a2438a0aa5d566 Mon Sep 17 00:00:00 2001 From: Xing Zheng Date: Thu, 30 Jun 2016 10:18:59 +0800 Subject: clk: rockchip: fix incorrect rk3399 spdif-DPTX divider bits The CLKSEL_CON32 bit_0 is controlled for spdif_8ch, not spdif_rec_dptx, it should be bit_8, let's fix it. Fixes: 115510053e5e ("clk: rockchip: add clock controller for the RK3399") Reported-by: Chris Zhong Tested-by: Chris Zhong Signed-off-by: Xing Zheng Cc: stable@vger.kernel.org Signed-off-by: Heiko Stuebner --- drivers/clk/rockchip/clk-rk3399.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/rockchip/clk-rk3399.c b/drivers/clk/rockchip/clk-rk3399.c index b6742fad3f8d..78e51cb255fb 100644 --- a/drivers/clk/rockchip/clk-rk3399.c +++ b/drivers/clk/rockchip/clk-rk3399.c @@ -586,7 +586,7 @@ static struct rockchip_clk_branch rk3399_clk_branches[] __initdata = { RK3399_CLKGATE_CON(8), 15, GFLAGS), COMPOSITE(SCLK_SPDIF_REC_DPTX, "clk_spdif_rec_dptx", mux_pll_src_cpll_gpll_p, 0, - RK3399_CLKSEL_CON(32), 15, 1, MFLAGS, 0, 5, DFLAGS, + RK3399_CLKSEL_CON(32), 15, 1, MFLAGS, 8, 5, DFLAGS, RK3399_CLKGATE_CON(10), 6, GFLAGS), /* i2s */ COMPOSITE(0, "clk_i2s0_div", mux_pll_src_cpll_gpll_p, 0, -- cgit v1.2.3 From e6cbf9984ee7340a6d428217ca30d353b4ccf1c5 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Wed, 22 Jun 2016 11:15:54 +0200 Subject: clk: fixed-factor: Allow for a few clocks to change the parent rate The only way for a fixed factor clock to change its rate would be to change its parent rate. Since passing blindly CLK_SET_RATE_PARENT might break a lot of platforms that were relying on the fact that the parent rate wouldn't change, introduce a compatible-based whitelist that will allow clocks to opt-in that flag. Signed-off-by: Maxime Ripard Acked-by: Rob Herring Signed-off-by: Stephen Boyd --- .../devicetree/bindings/clock/fixed-factor-clock.txt | 4 ++++ drivers/clk/clk-fixed-factor.c | 11 ++++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/clock/fixed-factor-clock.txt b/Documentation/devicetree/bindings/clock/fixed-factor-clock.txt index 1bae8527eb9b..189467a7188a 100644 --- a/Documentation/devicetree/bindings/clock/fixed-factor-clock.txt +++ b/Documentation/devicetree/bindings/clock/fixed-factor-clock.txt @@ -14,6 +14,10 @@ Required properties: Optional properties: - clock-output-names : From common clock binding. +Some clocks that require special treatments are also handled by that +driver, with the compatibles: + - allwinner,sun4i-a10-pll3-2x-clk + Example: clock { compatible = "fixed-factor-clock"; diff --git a/drivers/clk/clk-fixed-factor.c b/drivers/clk/clk-fixed-factor.c index 75cd6c792cb8..4db3be214077 100644 --- a/drivers/clk/clk-fixed-factor.c +++ b/drivers/clk/clk-fixed-factor.c @@ -142,6 +142,11 @@ void clk_hw_unregister_fixed_factor(struct clk_hw *hw) EXPORT_SYMBOL_GPL(clk_hw_unregister_fixed_factor); #ifdef CONFIG_OF +static const struct of_device_id set_rate_parent_matches[] = { + { .compatible = "allwinner,sun4i-a10-pll3-2x-clk" }, + { /* Sentinel */ }, +}; + /** * of_fixed_factor_clk_setup() - Setup function for simple fixed factor clock */ @@ -150,6 +155,7 @@ void __init of_fixed_factor_clk_setup(struct device_node *node) struct clk *clk; const char *clk_name = node->name; const char *parent_name; + unsigned long flags = 0; u32 div, mult; if (of_property_read_u32(node, "clock-div", &div)) { @@ -167,7 +173,10 @@ void __init of_fixed_factor_clk_setup(struct device_node *node) of_property_read_string(node, "clock-output-names", &clk_name); parent_name = of_clk_get_parent_name(node, 0); - clk = clk_register_fixed_factor(NULL, clk_name, parent_name, 0, + if (of_match_node(set_rate_parent_matches, node)) + flags |= CLK_SET_RATE_PARENT; + + clk = clk_register_fixed_factor(NULL, clk_name, parent_name, flags, mult, div); if (!IS_ERR(clk)) of_clk_add_provider(node, of_clk_src_simple_get, clk); -- cgit v1.2.3 From a6adc30ba7bef8da62a32c884609eb9cace04fbc Mon Sep 17 00:00:00 2001 From: Dong Aisheng Date: Thu, 30 Jun 2016 17:31:11 +0800 Subject: clk: introduce clk_core_enable_lock and clk_core_disable_lock functions This can be useful when clock core wants to enable/disable clocks. Then we don't have to convert the struct clk_core to struct clk to call clk_enable/clk_disable which is a bit un-align with exist using. And after introduce clk_core_{enable|disable}_lock, we can refine clk_enable and clk_disable a bit. As well as clk_core_{enable|disable}_lock, we also added clk_core_{prepare|unprepare}_lock and clk_core_prepare_enable/ clk_core_unprepare_disable for clock core to easily use. Cc: Michael Turquette Cc: Stephen Boyd Cc: Shawn Guo Signed-off-by: Dong Aisheng Signed-off-by: Stephen Boyd --- drivers/clk/clk.c | 85 +++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 63 insertions(+), 22 deletions(-) diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 95b80aeb8c9d..55e62bac0fb4 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -591,6 +591,13 @@ static void clk_core_unprepare(struct clk_core *core) clk_core_unprepare(core->parent); } +static void clk_core_unprepare_lock(struct clk_core *core) +{ + clk_prepare_lock(); + clk_core_unprepare(core); + clk_prepare_unlock(); +} + /** * clk_unprepare - undo preparation of a clock source * @clk: the clk being unprepared @@ -607,9 +614,7 @@ void clk_unprepare(struct clk *clk) if (IS_ERR_OR_NULL(clk)) return; - clk_prepare_lock(); - clk_core_unprepare(clk->core); - clk_prepare_unlock(); + clk_core_unprepare_lock(clk->core); } EXPORT_SYMBOL_GPL(clk_unprepare); @@ -645,6 +650,17 @@ static int clk_core_prepare(struct clk_core *core) return 0; } +static int clk_core_prepare_lock(struct clk_core *core) +{ + int ret; + + clk_prepare_lock(); + ret = clk_core_prepare(core); + clk_prepare_unlock(); + + return ret; +} + /** * clk_prepare - prepare a clock source * @clk: the clk being prepared @@ -659,16 +675,10 @@ static int clk_core_prepare(struct clk_core *core) */ int clk_prepare(struct clk *clk) { - int ret; - if (!clk) return 0; - clk_prepare_lock(); - ret = clk_core_prepare(clk->core); - clk_prepare_unlock(); - - return ret; + return clk_core_prepare_lock(clk->core); } EXPORT_SYMBOL_GPL(clk_prepare); @@ -698,6 +708,15 @@ static void clk_core_disable(struct clk_core *core) clk_core_disable(core->parent); } +static void clk_core_disable_lock(struct clk_core *core) +{ + unsigned long flags; + + flags = clk_enable_lock(); + clk_core_disable(core); + clk_enable_unlock(flags); +} + /** * clk_disable - gate a clock * @clk: the clk being gated @@ -712,14 +731,10 @@ static void clk_core_disable(struct clk_core *core) */ void clk_disable(struct clk *clk) { - unsigned long flags; - if (IS_ERR_OR_NULL(clk)) return; - flags = clk_enable_lock(); - clk_core_disable(clk->core); - clk_enable_unlock(flags); + clk_core_disable_lock(clk->core); } EXPORT_SYMBOL_GPL(clk_disable); @@ -758,6 +773,18 @@ static int clk_core_enable(struct clk_core *core) return 0; } +static int clk_core_enable_lock(struct clk_core *core) +{ + unsigned long flags; + int ret; + + flags = clk_enable_lock(); + ret = clk_core_enable(core); + clk_enable_unlock(flags); + + return ret; +} + /** * clk_enable - ungate a clock * @clk: the clk being ungated @@ -773,19 +800,33 @@ static int clk_core_enable(struct clk_core *core) */ int clk_enable(struct clk *clk) { - unsigned long flags; - int ret; - if (!clk) return 0; - flags = clk_enable_lock(); - ret = clk_core_enable(clk->core); - clk_enable_unlock(flags); + return clk_core_enable_lock(clk->core); +} +EXPORT_SYMBOL_GPL(clk_enable); + +static int clk_core_prepare_enable(struct clk_core *core) +{ + int ret; + + ret = clk_core_prepare_lock(core); + if (ret) + return ret; + + ret = clk_core_enable_lock(core); + if (ret) + clk_core_unprepare_lock(core); return ret; } -EXPORT_SYMBOL_GPL(clk_enable); + +static void clk_core_disable_unprepare(struct clk_core *core) +{ + clk_core_disable_lock(core); + clk_core_unprepare_lock(core); +} static int clk_core_round_rate_nolock(struct clk_core *core, struct clk_rate_request *req) -- cgit v1.2.3 From 7ec986efed0208ca5fdfc26f9fc19c1604d3d502 Mon Sep 17 00:00:00 2001 From: Dong Aisheng Date: Thu, 30 Jun 2016 17:31:12 +0800 Subject: clk: move clk_disable_unused after clk_core_disable_unprepare function No function level change, just moving code place. clk_disable_unused function will need to call clk_core_prepare_enable/ clk_core_disable_unprepare when adding CLK_OPS_PARENT_ENABLE features. So move it after clk_core_disable_unprepare to avoid adding forward declared functions later. Cc: Michael Turquette Cc: Stephen Boyd Cc: Shawn Guo Signed-off-by: Dong Aisheng Signed-off-by: Stephen Boyd --- drivers/clk/clk.c | 196 +++++++++++++++++++++++++++--------------------------- 1 file changed, 98 insertions(+), 98 deletions(-) diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 55e62bac0fb4..e2e8f0c9f20a 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -172,104 +172,6 @@ static bool clk_core_is_enabled(struct clk_core *core) return core->ops->is_enabled(core->hw); } -static void clk_unprepare_unused_subtree(struct clk_core *core) -{ - struct clk_core *child; - - lockdep_assert_held(&prepare_lock); - - hlist_for_each_entry(child, &core->children, child_node) - clk_unprepare_unused_subtree(child); - - if (core->prepare_count) - return; - - if (core->flags & CLK_IGNORE_UNUSED) - return; - - if (clk_core_is_prepared(core)) { - trace_clk_unprepare(core); - if (core->ops->unprepare_unused) - core->ops->unprepare_unused(core->hw); - else if (core->ops->unprepare) - core->ops->unprepare(core->hw); - trace_clk_unprepare_complete(core); - } -} - -static void clk_disable_unused_subtree(struct clk_core *core) -{ - struct clk_core *child; - unsigned long flags; - - lockdep_assert_held(&prepare_lock); - - hlist_for_each_entry(child, &core->children, child_node) - clk_disable_unused_subtree(child); - - flags = clk_enable_lock(); - - if (core->enable_count) - goto unlock_out; - - if (core->flags & CLK_IGNORE_UNUSED) - goto unlock_out; - - /* - * some gate clocks have special needs during the disable-unused - * sequence. call .disable_unused if available, otherwise fall - * back to .disable - */ - if (clk_core_is_enabled(core)) { - trace_clk_disable(core); - if (core->ops->disable_unused) - core->ops->disable_unused(core->hw); - else if (core->ops->disable) - core->ops->disable(core->hw); - trace_clk_disable_complete(core); - } - -unlock_out: - clk_enable_unlock(flags); -} - -static bool clk_ignore_unused; -static int __init clk_ignore_unused_setup(char *__unused) -{ - clk_ignore_unused = true; - return 1; -} -__setup("clk_ignore_unused", clk_ignore_unused_setup); - -static int clk_disable_unused(void) -{ - struct clk_core *core; - - if (clk_ignore_unused) { - pr_warn("clk: Not disabling unused clocks\n"); - return 0; - } - - clk_prepare_lock(); - - hlist_for_each_entry(core, &clk_root_list, child_node) - clk_disable_unused_subtree(core); - - hlist_for_each_entry(core, &clk_orphan_list, child_node) - clk_disable_unused_subtree(core); - - hlist_for_each_entry(core, &clk_root_list, child_node) - clk_unprepare_unused_subtree(core); - - hlist_for_each_entry(core, &clk_orphan_list, child_node) - clk_unprepare_unused_subtree(core); - - clk_prepare_unlock(); - - return 0; -} -late_initcall_sync(clk_disable_unused); - /*** helper functions ***/ const char *__clk_get_name(const struct clk *clk) @@ -828,6 +730,104 @@ static void clk_core_disable_unprepare(struct clk_core *core) clk_core_unprepare_lock(core); } +static void clk_unprepare_unused_subtree(struct clk_core *core) +{ + struct clk_core *child; + + lockdep_assert_held(&prepare_lock); + + hlist_for_each_entry(child, &core->children, child_node) + clk_unprepare_unused_subtree(child); + + if (core->prepare_count) + return; + + if (core->flags & CLK_IGNORE_UNUSED) + return; + + if (clk_core_is_prepared(core)) { + trace_clk_unprepare(core); + if (core->ops->unprepare_unused) + core->ops->unprepare_unused(core->hw); + else if (core->ops->unprepare) + core->ops->unprepare(core->hw); + trace_clk_unprepare_complete(core); + } +} + +static void clk_disable_unused_subtree(struct clk_core *core) +{ + struct clk_core *child; + unsigned long flags; + + lockdep_assert_held(&prepare_lock); + + hlist_for_each_entry(child, &core->children, child_node) + clk_disable_unused_subtree(child); + + flags = clk_enable_lock(); + + if (core->enable_count) + goto unlock_out; + + if (core->flags & CLK_IGNORE_UNUSED) + goto unlock_out; + + /* + * some gate clocks have special needs during the disable-unused + * sequence. call .disable_unused if available, otherwise fall + * back to .disable + */ + if (clk_core_is_enabled(core)) { + trace_clk_disable(core); + if (core->ops->disable_unused) + core->ops->disable_unused(core->hw); + else if (core->ops->disable) + core->ops->disable(core->hw); + trace_clk_disable_complete(core); + } + +unlock_out: + clk_enable_unlock(flags); +} + +static bool clk_ignore_unused; +static int __init clk_ignore_unused_setup(char *__unused) +{ + clk_ignore_unused = true; + return 1; +} +__setup("clk_ignore_unused", clk_ignore_unused_setup); + +static int clk_disable_unused(void) +{ + struct clk_core *core; + + if (clk_ignore_unused) { + pr_warn("clk: Not disabling unused clocks\n"); + return 0; + } + + clk_prepare_lock(); + + hlist_for_each_entry(core, &clk_root_list, child_node) + clk_disable_unused_subtree(core); + + hlist_for_each_entry(core, &clk_orphan_list, child_node) + clk_disable_unused_subtree(core); + + hlist_for_each_entry(core, &clk_root_list, child_node) + clk_unprepare_unused_subtree(core); + + hlist_for_each_entry(core, &clk_orphan_list, child_node) + clk_unprepare_unused_subtree(core); + + clk_prepare_unlock(); + + return 0; +} +late_initcall_sync(clk_disable_unused); + static int clk_core_round_rate_nolock(struct clk_core *core, struct clk_rate_request *req) { -- cgit v1.2.3 From a4b3518d146f150d633f7dc815bb8ee2fbc162e9 Mon Sep 17 00:00:00 2001 From: Dong Aisheng Date: Thu, 30 Jun 2016 17:31:13 +0800 Subject: clk: core: support clocks which requires parents enable (part 1) On Freescale i.MX7D platform, all clocks operations, including enable/disable, rate change and re-parent, requires its parent clock enable. Current clock core can not support it well. This patch introduce a new flag CLK_OPS_PARENT_ENABLE to handle this special case in clock core that enable its parent clock firstly for each operation and disable it later after operation complete. The patch part 1 fixes the possible disabling clocks while its parent is off during kernel booting phase in clk_disable_unused_subtree(). Before the completion of kernel booting, clock tree is still not built completely, there may be a case that the child clock is on but its parent is off which could be caused by either HW initial reset state or bootloader initialization. Taking bootloader as an example, we may enable all clocks in HW by default. And during kernel booting time, the parent clock could be disabled in its driver probe due to calling clk_prepare_enable and clk_disable_unprepare. Because it's child clock is only enabled in HW while its SW usecount in clock tree is still 0, so clk_disable of parent clock will gate the parent clock in both HW and SW usecount ultimately. Then there will be a child clock is still on in HW but its parent is already off. Later in clk_disable_unused(), this clock disable accessing while its parent off will cause system hang due to the limitation of HW which must require its parent on. This patch simply enables the parent clock first before disabling if flag CLK_OPS_PARENT_ENABLE is set in clk_disable_unused_subtree(). This is a simple solution and only affects booting time. After kernel booting up the clock tree is already created, there will be no case that child is off but its parent is off. So no need do this checking for normal clk_disable() later. Cc: Michael Turquette Cc: Stephen Boyd Cc: Shawn Guo Signed-off-by: Dong Aisheng Signed-off-by: Stephen Boyd --- drivers/clk/clk.c | 5 +++++ include/linux/clk-provider.h | 2 ++ 2 files changed, 7 insertions(+) diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index e2e8f0c9f20a..e3bd28c9ef28 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -765,6 +765,9 @@ static void clk_disable_unused_subtree(struct clk_core *core) hlist_for_each_entry(child, &core->children, child_node) clk_disable_unused_subtree(child); + if (core->flags & CLK_OPS_PARENT_ENABLE) + clk_core_prepare_enable(core->parent); + flags = clk_enable_lock(); if (core->enable_count) @@ -789,6 +792,8 @@ static void clk_disable_unused_subtree(struct clk_core *core) unlock_out: clk_enable_unlock(flags); + if (core->flags & CLK_OPS_PARENT_ENABLE) + clk_core_disable_unprepare(core->parent); } static bool clk_ignore_unused; diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index eeb2e69ee727..a39c0c530778 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -33,6 +33,8 @@ #define CLK_RECALC_NEW_RATES BIT(9) /* recalc rates after notifications */ #define CLK_SET_RATE_UNGATE BIT(10) /* clock needs to run to set rate */ #define CLK_IS_CRITICAL BIT(11) /* do not gate, ever */ +/* parents need enable during gate/ungate, set rate and re-parent */ +#define CLK_OPS_PARENT_ENABLE BIT(12) struct clk; struct clk_hw; -- cgit v1.2.3 From fc8726a2c021b5525151ff6482f8f9a863c56d8d Mon Sep 17 00:00:00 2001 From: Dong Aisheng Date: Thu, 30 Jun 2016 17:31:14 +0800 Subject: clk: core: support clocks which requires parents enable (part 2) On Freescale i.MX7D platform, all clocks operations, including enable/disable, rate change and re-parent, requires its parent clock on. Current clock core can not support it well. This patch adding flag CLK_OPS_PARENT_ENABLE to handle this special case in clock core that enable its parent clock firstly for each operation and disable it later after operation complete. The patch part 2 fixes set clock rate and set parent while its parent is off. The most special case is for set_parent() operation which requires all parents including both old and new one to be enabled at the same time during the operation. Cc: Michael Turquette Cc: Stephen Boyd Cc: Shawn Guo Signed-off-by: Dong Aisheng [sboyd@codeaurora.org: Move set_rate tracepoint after prepare_enable] Signed-off-by: Stephen Boyd --- drivers/clk/clk.c | 48 +++++++++++++++++++++++++++++++++--------------- 1 file changed, 33 insertions(+), 15 deletions(-) diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index e3bd28c9ef28..820a939fb6bb 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -1172,7 +1172,9 @@ static struct clk_core *__clk_set_parent_before(struct clk_core *core, struct clk_core *old_parent = core->parent; /* - * Migrate prepare state between parents and prevent race with + * 1. enable parents for CLK_OPS_PARENT_ENABLE clock + * + * 2. Migrate prepare state between parents and prevent race with * clk_enable(). * * If the clock is not prepared, then a race with @@ -1188,12 +1190,17 @@ static struct clk_core *__clk_set_parent_before(struct clk_core *core, * * See also: Comment for clk_set_parent() below. */ + + /* enable old_parent & parent if CLK_OPS_PARENT_ENABLE is set */ + if (core->flags & CLK_OPS_PARENT_ENABLE) { + clk_core_prepare_enable(old_parent); + clk_core_prepare_enable(parent); + } + + /* migrate prepare count if > 0 */ if (core->prepare_count) { - clk_core_prepare(parent); - flags = clk_enable_lock(); - clk_core_enable(parent); - clk_core_enable(core); - clk_enable_unlock(flags); + clk_core_prepare_enable(parent); + clk_core_enable_lock(core); } /* update the clk tree topology */ @@ -1208,18 +1215,19 @@ static void __clk_set_parent_after(struct clk_core *core, struct clk_core *parent, struct clk_core *old_parent) { - unsigned long flags; - /* * Finish the migration of prepare state and undo the changes done * for preventing a race with clk_enable(). */ if (core->prepare_count) { - flags = clk_enable_lock(); - clk_core_disable(core); - clk_core_disable(old_parent); - clk_enable_unlock(flags); - clk_core_unprepare(old_parent); + clk_core_disable_lock(core); + clk_core_disable_unprepare(old_parent); + } + + /* re-balance ref counting if CLK_OPS_PARENT_ENABLE is set */ + if (core->flags & CLK_OPS_PARENT_ENABLE) { + clk_core_disable_unprepare(parent); + clk_core_disable_unprepare(old_parent); } } @@ -1466,13 +1474,17 @@ static void clk_change_rate(struct clk_core *core) unsigned long best_parent_rate = 0; bool skip_set_rate = false; struct clk_core *old_parent; + struct clk_core *parent = NULL; old_rate = core->rate; - if (core->new_parent) + if (core->new_parent) { + parent = core->new_parent; best_parent_rate = core->new_parent->rate; - else if (core->parent) + } else if (core->parent) { + parent = core->parent; best_parent_rate = core->parent->rate; + } if (core->flags & CLK_SET_RATE_UNGATE) { unsigned long flags; @@ -1500,6 +1512,9 @@ static void clk_change_rate(struct clk_core *core) __clk_set_parent_after(core, core->new_parent, old_parent); } + if (core->flags & CLK_OPS_PARENT_ENABLE) + clk_core_prepare_enable(parent); + trace_clk_set_rate(core, core->new_rate); if (!skip_set_rate && core->ops->set_rate) @@ -1518,6 +1533,9 @@ static void clk_change_rate(struct clk_core *core) clk_core_unprepare(core); } + if (core->flags & CLK_OPS_PARENT_ENABLE) + clk_core_disable_unprepare(parent); + if (core->notifier_count && old_rate != core->rate) __clk_notify(core, POST_RATE_CHANGE, old_rate, core->rate); -- cgit v1.2.3 From 5afc99417fc37f9eaee10b132511051b41e434bf Mon Sep 17 00:00:00 2001 From: Dong Aisheng Date: Thu, 30 Jun 2016 17:31:15 +0800 Subject: clk: imx: re-order and concentrate the same type of clk api Re-order and concentrate the same type of clk api for better code maintenance. Cc: Shawn Guo Signed-off-by: Dong Aisheng Signed-off-by: Stephen Boyd --- drivers/clk/imx/clk.h | 58 +++++++++++++++++++++++++-------------------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/drivers/clk/imx/clk.h b/drivers/clk/imx/clk.h index 508d0fad84cf..936e235f7c04 100644 --- a/drivers/clk/imx/clk.h +++ b/drivers/clk/imx/clk.h @@ -51,28 +51,6 @@ struct clk * imx_obtain_fixed_clock( struct clk *imx_clk_gate_exclusive(const char *name, const char *parent, void __iomem *reg, u8 shift, u32 exclusive_mask); -static inline struct clk *imx_clk_gate2(const char *name, const char *parent, - void __iomem *reg, u8 shift) -{ - return clk_register_gate2(NULL, name, parent, CLK_SET_RATE_PARENT, reg, - shift, 0x3, 0, &imx_ccm_lock, NULL); -} - -static inline struct clk *imx_clk_gate2_shared(const char *name, - const char *parent, void __iomem *reg, u8 shift, - unsigned int *share_count) -{ - return clk_register_gate2(NULL, name, parent, CLK_SET_RATE_PARENT, reg, - shift, 0x3, 0, &imx_ccm_lock, share_count); -} - -static inline struct clk *imx_clk_gate2_cgr(const char *name, const char *parent, - void __iomem *reg, u8 shift, u8 cgr_val) -{ - return clk_register_gate2(NULL, name, parent, CLK_SET_RATE_PARENT, reg, - shift, cgr_val, 0, &imx_ccm_lock, NULL); -} - struct clk *imx_clk_pfd(const char *name, const char *parent_name, void __iomem *reg, u8 idx); @@ -97,6 +75,13 @@ static inline struct clk *imx_clk_fixed(const char *name, int rate) return clk_register_fixed_rate(NULL, name, NULL, 0, rate); } +static inline struct clk *imx_clk_fixed_factor(const char *name, + const char *parent, unsigned int mult, unsigned int div) +{ + return clk_register_fixed_factor(NULL, name, parent, + CLK_SET_RATE_PARENT, mult, div); +} + static inline struct clk *imx_clk_divider(const char *name, const char *parent, void __iomem *reg, u8 shift, u8 width) { @@ -126,6 +111,28 @@ static inline struct clk *imx_clk_gate_dis(const char *name, const char *parent, shift, CLK_GATE_SET_TO_DISABLE, &imx_ccm_lock); } +static inline struct clk *imx_clk_gate2(const char *name, const char *parent, + void __iomem *reg, u8 shift) +{ + return clk_register_gate2(NULL, name, parent, CLK_SET_RATE_PARENT, reg, + shift, 0x3, 0, &imx_ccm_lock, NULL); +} + +static inline struct clk *imx_clk_gate2_shared(const char *name, + const char *parent, void __iomem *reg, u8 shift, + unsigned int *share_count) +{ + return clk_register_gate2(NULL, name, parent, CLK_SET_RATE_PARENT, reg, + shift, 0x3, 0, &imx_ccm_lock, share_count); +} + +static inline struct clk *imx_clk_gate2_cgr(const char *name, + const char *parent, void __iomem *reg, u8 shift, u8 cgr_val) +{ + return clk_register_gate2(NULL, name, parent, CLK_SET_RATE_PARENT, reg, + shift, cgr_val, 0, &imx_ccm_lock, NULL); +} + static inline struct clk *imx_clk_mux(const char *name, void __iomem *reg, u8 shift, u8 width, const char **parents, int num_parents) { @@ -143,13 +150,6 @@ static inline struct clk *imx_clk_mux_flags(const char *name, &imx_ccm_lock); } -static inline struct clk *imx_clk_fixed_factor(const char *name, - const char *parent, unsigned int mult, unsigned int div) -{ - return clk_register_fixed_factor(NULL, name, parent, - CLK_SET_RATE_PARENT, mult, div); -} - struct clk *imx_clk_cpu(const char *name, const char *parent_name, struct clk *div, struct clk *mux, struct clk *pll, struct clk *step); -- cgit v1.2.3 From 39c29498ce7fbf9c28962775ed3e798a4ff68b78 Mon Sep 17 00:00:00 2001 From: Dong Aisheng Date: Thu, 30 Jun 2016 17:31:16 +0800 Subject: clk: imx: add clk api for supporting CLK_OPS_PARENT_ENABLE clocks IMX SoCs like i.MX7D requires using CLK_OPS_PARENT_ENABLE flags, adding the corresponding clock APIs variants for easily to use. Cc: Michael Turquette Cc: Stephen Boyd Cc: Shawn Guo Signed-off-by: Dong Aisheng Signed-off-by: Stephen Boyd --- drivers/clk/imx/clk.h | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/drivers/clk/imx/clk.h b/drivers/clk/imx/clk.h index 936e235f7c04..a81c0385ed64 100644 --- a/drivers/clk/imx/clk.h +++ b/drivers/clk/imx/clk.h @@ -97,6 +97,14 @@ static inline struct clk *imx_clk_divider_flags(const char *name, reg, shift, width, 0, &imx_ccm_lock); } +static inline struct clk *imx_clk_divider2(const char *name, const char *parent, + void __iomem *reg, u8 shift, u8 width) +{ + return clk_register_divider(NULL, name, parent, + CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE, + reg, shift, width, 0, &imx_ccm_lock); +} + static inline struct clk *imx_clk_gate(const char *name, const char *parent, void __iomem *reg, u8 shift) { @@ -133,6 +141,22 @@ static inline struct clk *imx_clk_gate2_cgr(const char *name, shift, cgr_val, 0, &imx_ccm_lock, NULL); } +static inline struct clk *imx_clk_gate3(const char *name, const char *parent, + void __iomem *reg, u8 shift) +{ + return clk_register_gate(NULL, name, parent, + CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE, + reg, shift, 0, &imx_ccm_lock); +} + +static inline struct clk *imx_clk_gate4(const char *name, const char *parent, + void __iomem *reg, u8 shift) +{ + return clk_register_gate2(NULL, name, parent, + CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE, + reg, shift, 0x3, 0, &imx_ccm_lock, NULL); +} + static inline struct clk *imx_clk_mux(const char *name, void __iomem *reg, u8 shift, u8 width, const char **parents, int num_parents) { @@ -141,6 +165,14 @@ static inline struct clk *imx_clk_mux(const char *name, void __iomem *reg, width, 0, &imx_ccm_lock); } +static inline struct clk *imx_clk_mux2(const char *name, void __iomem *reg, + u8 shift, u8 width, const char **parents, int num_parents) +{ + return clk_register_mux(NULL, name, parents, num_parents, + CLK_SET_RATE_NO_REPARENT | CLK_OPS_PARENT_ENABLE, + reg, shift, width, 0, &imx_ccm_lock); +} + static inline struct clk *imx_clk_mux_flags(const char *name, void __iomem *reg, u8 shift, u8 width, const char **parents, int num_parents, unsigned long flags) -- cgit v1.2.3 From cbeac74a5883e4d3caa1e3ad2efdd39a9c52ee73 Mon Sep 17 00:00:00 2001 From: Dong Aisheng Date: Thu, 30 Jun 2016 17:31:17 +0800 Subject: clk: imx7d: using api with flag CLK_OPS_PARENT_ENABLE i.MX7D requires all clocks operations including enable/disable, rate change and re-parent with its parent clock on. Changing to the correct APIs to tell clk core such requirement. Cc: Michael Turquette Cc: Stephen Boyd Cc: Shawn Guo Signed-off-by: Dong Aisheng Signed-off-by: Stephen Boyd --- drivers/clk/imx/clk-imx7d.c | 714 ++++++++++++++++++++++---------------------- 1 file changed, 357 insertions(+), 357 deletions(-) diff --git a/drivers/clk/imx/clk-imx7d.c b/drivers/clk/imx/clk-imx7d.c index 0c0003d8af5f..62e25c37c6d6 100644 --- a/drivers/clk/imx/clk-imx7d.c +++ b/drivers/clk/imx/clk-imx7d.c @@ -474,363 +474,363 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node) base = of_iomap(np, 0); WARN_ON(!base); - clks[IMX7D_ARM_A7_ROOT_SRC] = imx_clk_mux("arm_a7_src", base + 0x8000, 24, 3, arm_a7_sel, ARRAY_SIZE(arm_a7_sel)); - clks[IMX7D_ARM_M4_ROOT_SRC] = imx_clk_mux("arm_m4_src", base + 0x8080, 24, 3, arm_m4_sel, ARRAY_SIZE(arm_m4_sel)); - clks[IMX7D_ARM_M0_ROOT_SRC] = imx_clk_mux("arm_m0_src", base + 0x8100, 24, 3, arm_m0_sel, ARRAY_SIZE(arm_m0_sel)); - clks[IMX7D_MAIN_AXI_ROOT_SRC] = imx_clk_mux("axi_src", base + 0x8800, 24, 3, axi_sel, ARRAY_SIZE(axi_sel)); - clks[IMX7D_DISP_AXI_ROOT_SRC] = imx_clk_mux("disp_axi_src", base + 0x8880, 24, 3, disp_axi_sel, ARRAY_SIZE(disp_axi_sel)); - clks[IMX7D_ENET_AXI_ROOT_SRC] = imx_clk_mux("enet_axi_src", base + 0x8900, 24, 3, enet_axi_sel, ARRAY_SIZE(enet_axi_sel)); - clks[IMX7D_NAND_USDHC_BUS_ROOT_SRC] = imx_clk_mux("nand_usdhc_src", base + 0x8980, 24, 3, nand_usdhc_bus_sel, ARRAY_SIZE(nand_usdhc_bus_sel)); - clks[IMX7D_AHB_CHANNEL_ROOT_SRC] = imx_clk_mux("ahb_src", base + 0x9000, 24, 3, ahb_channel_sel, ARRAY_SIZE(ahb_channel_sel)); - clks[IMX7D_DRAM_PHYM_ROOT_SRC] = imx_clk_mux("dram_phym_src", base + 0x9800, 24, 1, dram_phym_sel, ARRAY_SIZE(dram_phym_sel)); - clks[IMX7D_DRAM_ROOT_SRC] = imx_clk_mux("dram_src", base + 0x9880, 24, 1, dram_sel, ARRAY_SIZE(dram_sel)); - clks[IMX7D_DRAM_PHYM_ALT_ROOT_SRC] = imx_clk_mux("dram_phym_alt_src", base + 0xa000, 24, 3, dram_phym_alt_sel, ARRAY_SIZE(dram_phym_alt_sel)); - clks[IMX7D_DRAM_ALT_ROOT_SRC] = imx_clk_mux("dram_alt_src", base + 0xa080, 24, 3, dram_alt_sel, ARRAY_SIZE(dram_alt_sel)); - clks[IMX7D_USB_HSIC_ROOT_SRC] = imx_clk_mux("usb_hsic_src", base + 0xa100, 24, 3, usb_hsic_sel, ARRAY_SIZE(usb_hsic_sel)); - clks[IMX7D_PCIE_CTRL_ROOT_SRC] = imx_clk_mux("pcie_ctrl_src", base + 0xa180, 24, 3, pcie_ctrl_sel, ARRAY_SIZE(pcie_ctrl_sel)); - clks[IMX7D_PCIE_PHY_ROOT_SRC] = imx_clk_mux("pcie_phy_src", base + 0xa200, 24, 3, pcie_phy_sel, ARRAY_SIZE(pcie_phy_sel)); - clks[IMX7D_EPDC_PIXEL_ROOT_SRC] = imx_clk_mux("epdc_pixel_src", base + 0xa280, 24, 3, epdc_pixel_sel, ARRAY_SIZE(epdc_pixel_sel)); - clks[IMX7D_LCDIF_PIXEL_ROOT_SRC] = imx_clk_mux("lcdif_pixel_src", base + 0xa300, 24, 3, lcdif_pixel_sel, ARRAY_SIZE(lcdif_pixel_sel)); - clks[IMX7D_MIPI_DSI_ROOT_SRC] = imx_clk_mux("mipi_dsi_src", base + 0xa380, 24, 3, mipi_dsi_sel, ARRAY_SIZE(mipi_dsi_sel)); - clks[IMX7D_MIPI_CSI_ROOT_SRC] = imx_clk_mux("mipi_csi_src", base + 0xa400, 24, 3, mipi_csi_sel, ARRAY_SIZE(mipi_csi_sel)); - clks[IMX7D_MIPI_DPHY_ROOT_SRC] = imx_clk_mux("mipi_dphy_src", base + 0xa480, 24, 3, mipi_dphy_sel, ARRAY_SIZE(mipi_dphy_sel)); - clks[IMX7D_SAI1_ROOT_SRC] = imx_clk_mux("sai1_src", base + 0xa500, 24, 3, sai1_sel, ARRAY_SIZE(sai1_sel)); - clks[IMX7D_SAI2_ROOT_SRC] = imx_clk_mux("sai2_src", base + 0xa580, 24, 3, sai2_sel, ARRAY_SIZE(sai2_sel)); - clks[IMX7D_SAI3_ROOT_SRC] = imx_clk_mux("sai3_src", base + 0xa600, 24, 3, sai3_sel, ARRAY_SIZE(sai3_sel)); - clks[IMX7D_SPDIF_ROOT_SRC] = imx_clk_mux("spdif_src", base + 0xa680, 24, 3, spdif_sel, ARRAY_SIZE(spdif_sel)); - clks[IMX7D_ENET1_REF_ROOT_SRC] = imx_clk_mux("enet1_ref_src", base + 0xa700, 24, 3, enet1_ref_sel, ARRAY_SIZE(enet1_ref_sel)); - clks[IMX7D_ENET1_TIME_ROOT_SRC] = imx_clk_mux("enet1_time_src", base + 0xa780, 24, 3, enet1_time_sel, ARRAY_SIZE(enet1_time_sel)); - clks[IMX7D_ENET2_REF_ROOT_SRC] = imx_clk_mux("enet2_ref_src", base + 0xa800, 24, 3, enet2_ref_sel, ARRAY_SIZE(enet2_ref_sel)); - clks[IMX7D_ENET2_TIME_ROOT_SRC] = imx_clk_mux("enet2_time_src", base + 0xa880, 24, 3, enet2_time_sel, ARRAY_SIZE(enet2_time_sel)); - clks[IMX7D_ENET_PHY_REF_ROOT_SRC] = imx_clk_mux("enet_phy_ref_src", base + 0xa900, 24, 3, enet_phy_ref_sel, ARRAY_SIZE(enet_phy_ref_sel)); - clks[IMX7D_EIM_ROOT_SRC] = imx_clk_mux("eim_src", base + 0xa980, 24, 3, eim_sel, ARRAY_SIZE(eim_sel)); - clks[IMX7D_NAND_ROOT_SRC] = imx_clk_mux("nand_src", base + 0xaa00, 24, 3, nand_sel, ARRAY_SIZE(nand_sel)); - clks[IMX7D_QSPI_ROOT_SRC] = imx_clk_mux("qspi_src", base + 0xaa80, 24, 3, qspi_sel, ARRAY_SIZE(qspi_sel)); - clks[IMX7D_USDHC1_ROOT_SRC] = imx_clk_mux("usdhc1_src", base + 0xab00, 24, 3, usdhc1_sel, ARRAY_SIZE(usdhc1_sel)); - clks[IMX7D_USDHC2_ROOT_SRC] = imx_clk_mux("usdhc2_src", base + 0xab80, 24, 3, usdhc2_sel, ARRAY_SIZE(usdhc2_sel)); - clks[IMX7D_USDHC3_ROOT_SRC] = imx_clk_mux("usdhc3_src", base + 0xac00, 24, 3, usdhc3_sel, ARRAY_SIZE(usdhc3_sel)); - clks[IMX7D_CAN1_ROOT_SRC] = imx_clk_mux("can1_src", base + 0xac80, 24, 3, can1_sel, ARRAY_SIZE(can1_sel)); - clks[IMX7D_CAN2_ROOT_SRC] = imx_clk_mux("can2_src", base + 0xad00, 24, 3, can2_sel, ARRAY_SIZE(can2_sel)); - clks[IMX7D_I2C1_ROOT_SRC] = imx_clk_mux("i2c1_src", base + 0xad80, 24, 3, i2c1_sel, ARRAY_SIZE(i2c1_sel)); - clks[IMX7D_I2C2_ROOT_SRC] = imx_clk_mux("i2c2_src", base + 0xae00, 24, 3, i2c2_sel, ARRAY_SIZE(i2c2_sel)); - clks[IMX7D_I2C3_ROOT_SRC] = imx_clk_mux("i2c3_src", base + 0xae80, 24, 3, i2c3_sel, ARRAY_SIZE(i2c3_sel)); - clks[IMX7D_I2C4_ROOT_SRC] = imx_clk_mux("i2c4_src", base + 0xaf00, 24, 3, i2c4_sel, ARRAY_SIZE(i2c4_sel)); - clks[IMX7D_UART1_ROOT_SRC] = imx_clk_mux("uart1_src", base + 0xaf80, 24, 3, uart1_sel, ARRAY_SIZE(uart1_sel)); - clks[IMX7D_UART2_ROOT_SRC] = imx_clk_mux("uart2_src", base + 0xb000, 24, 3, uart2_sel, ARRAY_SIZE(uart2_sel)); - clks[IMX7D_UART3_ROOT_SRC] = imx_clk_mux("uart3_src", base + 0xb080, 24, 3, uart3_sel, ARRAY_SIZE(uart3_sel)); - clks[IMX7D_UART4_ROOT_SRC] = imx_clk_mux("uart4_src", base + 0xb100, 24, 3, uart4_sel, ARRAY_SIZE(uart4_sel)); - clks[IMX7D_UART5_ROOT_SRC] = imx_clk_mux("uart5_src", base + 0xb180, 24, 3, uart5_sel, ARRAY_SIZE(uart5_sel)); - clks[IMX7D_UART6_ROOT_SRC] = imx_clk_mux("uart6_src", base + 0xb200, 24, 3, uart6_sel, ARRAY_SIZE(uart6_sel)); - clks[IMX7D_UART7_ROOT_SRC] = imx_clk_mux("uart7_src", base + 0xb280, 24, 3, uart7_sel, ARRAY_SIZE(uart7_sel)); - clks[IMX7D_ECSPI1_ROOT_SRC] = imx_clk_mux("ecspi1_src", base + 0xb300, 24, 3, ecspi1_sel, ARRAY_SIZE(ecspi1_sel)); - clks[IMX7D_ECSPI2_ROOT_SRC] = imx_clk_mux("ecspi2_src", base + 0xb380, 24, 3, ecspi2_sel, ARRAY_SIZE(ecspi2_sel)); - clks[IMX7D_ECSPI3_ROOT_SRC] = imx_clk_mux("ecspi3_src", base + 0xb400, 24, 3, ecspi3_sel, ARRAY_SIZE(ecspi3_sel)); - clks[IMX7D_ECSPI4_ROOT_SRC] = imx_clk_mux("ecspi4_src", base + 0xb480, 24, 3, ecspi4_sel, ARRAY_SIZE(ecspi4_sel)); - clks[IMX7D_PWM1_ROOT_SRC] = imx_clk_mux("pwm1_src", base + 0xb500, 24, 3, pwm1_sel, ARRAY_SIZE(pwm1_sel)); - clks[IMX7D_PWM2_ROOT_SRC] = imx_clk_mux("pwm2_src", base + 0xb580, 24, 3, pwm2_sel, ARRAY_SIZE(pwm2_sel)); - clks[IMX7D_PWM3_ROOT_SRC] = imx_clk_mux("pwm3_src", base + 0xb600, 24, 3, pwm3_sel, ARRAY_SIZE(pwm3_sel)); - clks[IMX7D_PWM4_ROOT_SRC] = imx_clk_mux("pwm4_src", base + 0xb680, 24, 3, pwm4_sel, ARRAY_SIZE(pwm4_sel)); - clks[IMX7D_FLEXTIMER1_ROOT_SRC] = imx_clk_mux("flextimer1_src", base + 0xb700, 24, 3, flextimer1_sel, ARRAY_SIZE(flextimer1_sel)); - clks[IMX7D_FLEXTIMER2_ROOT_SRC] = imx_clk_mux("flextimer2_src", base + 0xb780, 24, 3, flextimer2_sel, ARRAY_SIZE(flextimer2_sel)); - clks[IMX7D_SIM1_ROOT_SRC] = imx_clk_mux("sim1_src", base + 0xb800, 24, 3, sim1_sel, ARRAY_SIZE(sim1_sel)); - clks[IMX7D_SIM2_ROOT_SRC] = imx_clk_mux("sim2_src", base + 0xb880, 24, 3, sim2_sel, ARRAY_SIZE(sim2_sel)); - clks[IMX7D_GPT1_ROOT_SRC] = imx_clk_mux("gpt1_src", base + 0xb900, 24, 3, gpt1_sel, ARRAY_SIZE(gpt1_sel)); - clks[IMX7D_GPT2_ROOT_SRC] = imx_clk_mux("gpt2_src", base + 0xb980, 24, 3, gpt2_sel, ARRAY_SIZE(gpt2_sel)); - clks[IMX7D_GPT3_ROOT_SRC] = imx_clk_mux("gpt3_src", base + 0xba00, 24, 3, gpt3_sel, ARRAY_SIZE(gpt3_sel)); - clks[IMX7D_GPT4_ROOT_SRC] = imx_clk_mux("gpt4_src", base + 0xba80, 24, 3, gpt4_sel, ARRAY_SIZE(gpt4_sel)); - clks[IMX7D_TRACE_ROOT_SRC] = imx_clk_mux("trace_src", base + 0xbb00, 24, 3, trace_sel, ARRAY_SIZE(trace_sel)); - clks[IMX7D_WDOG_ROOT_SRC] = imx_clk_mux("wdog_src", base + 0xbb80, 24, 3, wdog_sel, ARRAY_SIZE(wdog_sel)); - clks[IMX7D_CSI_MCLK_ROOT_SRC] = imx_clk_mux("csi_mclk_src", base + 0xbc00, 24, 3, csi_mclk_sel, ARRAY_SIZE(csi_mclk_sel)); - clks[IMX7D_AUDIO_MCLK_ROOT_SRC] = imx_clk_mux("audio_mclk_src", base + 0xbc80, 24, 3, audio_mclk_sel, ARRAY_SIZE(audio_mclk_sel)); - clks[IMX7D_WRCLK_ROOT_SRC] = imx_clk_mux("wrclk_src", base + 0xbd00, 24, 3, wrclk_sel, ARRAY_SIZE(wrclk_sel)); - clks[IMX7D_CLKO1_ROOT_SRC] = imx_clk_mux("clko1_src", base + 0xbd80, 24, 3, clko1_sel, ARRAY_SIZE(clko1_sel)); - clks[IMX7D_CLKO2_ROOT_SRC] = imx_clk_mux("clko2_src", base + 0xbe00, 24, 3, clko2_sel, ARRAY_SIZE(clko2_sel)); - - clks[IMX7D_ARM_A7_ROOT_CG] = imx_clk_gate("arm_a7_cg", "arm_a7_src", base + 0x8000, 28); - clks[IMX7D_ARM_M4_ROOT_CG] = imx_clk_gate("arm_m4_cg", "arm_m4_src", base + 0x8080, 28); - clks[IMX7D_ARM_M0_ROOT_CG] = imx_clk_gate("arm_m0_cg", "arm_m0_src", base + 0x8100, 28); - clks[IMX7D_MAIN_AXI_ROOT_CG] = imx_clk_gate("axi_cg", "axi_src", base + 0x8800, 28); - clks[IMX7D_DISP_AXI_ROOT_CG] = imx_clk_gate("disp_axi_cg", "disp_axi_src", base + 0x8880, 28); - clks[IMX7D_ENET_AXI_ROOT_CG] = imx_clk_gate("enet_axi_cg", "enet_axi_src", base + 0x8900, 28); - clks[IMX7D_NAND_USDHC_BUS_ROOT_CG] = imx_clk_gate("nand_usdhc_cg", "nand_usdhc_src", base + 0x8980, 28); - clks[IMX7D_AHB_CHANNEL_ROOT_CG] = imx_clk_gate("ahb_cg", "ahb_src", base + 0x9000, 28); - clks[IMX7D_DRAM_PHYM_ROOT_CG] = imx_clk_gate("dram_phym_cg", "dram_phym_src", base + 0x9800, 28); - clks[IMX7D_DRAM_ROOT_CG] = imx_clk_gate("dram_cg", "dram_src", base + 0x9880, 28); - clks[IMX7D_DRAM_PHYM_ALT_ROOT_CG] = imx_clk_gate("dram_phym_alt_cg", "dram_phym_alt_src", base + 0xa000, 28); - clks[IMX7D_DRAM_ALT_ROOT_CG] = imx_clk_gate("dram_alt_cg", "dram_alt_src", base + 0xa080, 28); - clks[IMX7D_USB_HSIC_ROOT_CG] = imx_clk_gate("usb_hsic_cg", "usb_hsic_src", base + 0xa100, 28); - clks[IMX7D_PCIE_CTRL_ROOT_CG] = imx_clk_gate("pcie_ctrl_cg", "pcie_ctrl_src", base + 0xa180, 28); - clks[IMX7D_PCIE_PHY_ROOT_CG] = imx_clk_gate("pcie_phy_cg", "pcie_phy_src", base + 0xa200, 28); - clks[IMX7D_EPDC_PIXEL_ROOT_CG] = imx_clk_gate("epdc_pixel_cg", "epdc_pixel_src", base + 0xa280, 28); - clks[IMX7D_LCDIF_PIXEL_ROOT_CG] = imx_clk_gate("lcdif_pixel_cg", "lcdif_pixel_src", base + 0xa300, 28); - clks[IMX7D_MIPI_DSI_ROOT_CG] = imx_clk_gate("mipi_dsi_cg", "mipi_dsi_src", base + 0xa380, 28); - clks[IMX7D_MIPI_CSI_ROOT_CG] = imx_clk_gate("mipi_csi_cg", "mipi_csi_src", base + 0xa400, 28); - clks[IMX7D_MIPI_DPHY_ROOT_CG] = imx_clk_gate("mipi_dphy_cg", "mipi_dphy_src", base + 0xa480, 28); - clks[IMX7D_SAI1_ROOT_CG] = imx_clk_gate("sai1_cg", "sai1_src", base + 0xa500, 28); - clks[IMX7D_SAI2_ROOT_CG] = imx_clk_gate("sai2_cg", "sai2_src", base + 0xa580, 28); - clks[IMX7D_SAI3_ROOT_CG] = imx_clk_gate("sai3_cg", "sai3_src", base + 0xa600, 28); - clks[IMX7D_SPDIF_ROOT_CG] = imx_clk_gate("spdif_cg", "spdif_src", base + 0xa680, 28); - clks[IMX7D_ENET1_REF_ROOT_CG] = imx_clk_gate("enet1_ref_cg", "enet1_ref_src", base + 0xa700, 28); - clks[IMX7D_ENET1_TIME_ROOT_CG] = imx_clk_gate("enet1_time_cg", "enet1_time_src", base + 0xa780, 28); - clks[IMX7D_ENET2_REF_ROOT_CG] = imx_clk_gate("enet2_ref_cg", "enet2_ref_src", base + 0xa800, 28); - clks[IMX7D_ENET2_TIME_ROOT_CG] = imx_clk_gate("enet2_time_cg", "enet2_time_src", base + 0xa880, 28); - clks[IMX7D_ENET_PHY_REF_ROOT_CG] = imx_clk_gate("enet_phy_ref_cg", "enet_phy_ref_src", base + 0xa900, 28); - clks[IMX7D_EIM_ROOT_CG] = imx_clk_gate("eim_cg", "eim_src", base + 0xa980, 28); - clks[IMX7D_NAND_ROOT_CG] = imx_clk_gate("nand_cg", "nand_src", base + 0xaa00, 28); - clks[IMX7D_QSPI_ROOT_CG] = imx_clk_gate("qspi_cg", "qspi_src", base + 0xaa80, 28); - clks[IMX7D_USDHC1_ROOT_CG] = imx_clk_gate("usdhc1_cg", "usdhc1_src", base + 0xab00, 28); - clks[IMX7D_USDHC2_ROOT_CG] = imx_clk_gate("usdhc2_cg", "usdhc2_src", base + 0xab80, 28); - clks[IMX7D_USDHC3_ROOT_CG] = imx_clk_gate("usdhc3_cg", "usdhc3_src", base + 0xac00, 28); - clks[IMX7D_CAN1_ROOT_CG] = imx_clk_gate("can1_cg", "can1_src", base + 0xac80, 28); - clks[IMX7D_CAN2_ROOT_CG] = imx_clk_gate("can2_cg", "can2_src", base + 0xad00, 28); - clks[IMX7D_I2C1_ROOT_CG] = imx_clk_gate("i2c1_cg", "i2c1_src", base + 0xad80, 28); - clks[IMX7D_I2C2_ROOT_CG] = imx_clk_gate("i2c2_cg", "i2c2_src", base + 0xae00, 28); - clks[IMX7D_I2C3_ROOT_CG] = imx_clk_gate("i2c3_cg", "i2c3_src", base + 0xae80, 28); - clks[IMX7D_I2C4_ROOT_CG] = imx_clk_gate("i2c4_cg", "i2c4_src", base + 0xaf00, 28); - clks[IMX7D_UART1_ROOT_CG] = imx_clk_gate("uart1_cg", "uart1_src", base + 0xaf80, 28); - clks[IMX7D_UART2_ROOT_CG] = imx_clk_gate("uart2_cg", "uart2_src", base + 0xb000, 28); - clks[IMX7D_UART3_ROOT_CG] = imx_clk_gate("uart3_cg", "uart3_src", base + 0xb080, 28); - clks[IMX7D_UART4_ROOT_CG] = imx_clk_gate("uart4_cg", "uart4_src", base + 0xb100, 28); - clks[IMX7D_UART5_ROOT_CG] = imx_clk_gate("uart5_cg", "uart5_src", base + 0xb180, 28); - clks[IMX7D_UART6_ROOT_CG] = imx_clk_gate("uart6_cg", "uart6_src", base + 0xb200, 28); - clks[IMX7D_UART7_ROOT_CG] = imx_clk_gate("uart7_cg", "uart7_src", base + 0xb280, 28); - clks[IMX7D_ECSPI1_ROOT_CG] = imx_clk_gate("ecspi1_cg", "ecspi1_src", base + 0xb300, 28); - clks[IMX7D_ECSPI2_ROOT_CG] = imx_clk_gate("ecspi2_cg", "ecspi2_src", base + 0xb380, 28); - clks[IMX7D_ECSPI3_ROOT_CG] = imx_clk_gate("ecspi3_cg", "ecspi3_src", base + 0xb400, 28); - clks[IMX7D_ECSPI4_ROOT_CG] = imx_clk_gate("ecspi4_cg", "ecspi4_src", base + 0xb480, 28); - clks[IMX7D_PWM1_ROOT_CG] = imx_clk_gate("pwm1_cg", "pwm1_src", base + 0xb500, 28); - clks[IMX7D_PWM2_ROOT_CG] = imx_clk_gate("pwm2_cg", "pwm2_src", base + 0xb580, 28); - clks[IMX7D_PWM3_ROOT_CG] = imx_clk_gate("pwm3_cg", "pwm3_src", base + 0xb600, 28); - clks[IMX7D_PWM4_ROOT_CG] = imx_clk_gate("pwm4_cg", "pwm4_src", base + 0xb680, 28); - clks[IMX7D_FLEXTIMER1_ROOT_CG] = imx_clk_gate("flextimer1_cg", "flextimer1_src", base + 0xb700, 28); - clks[IMX7D_FLEXTIMER2_ROOT_CG] = imx_clk_gate("flextimer2_cg", "flextimer2_src", base + 0xb780, 28); - clks[IMX7D_SIM1_ROOT_CG] = imx_clk_gate("sim1_cg", "sim1_src", base + 0xb800, 28); - clks[IMX7D_SIM2_ROOT_CG] = imx_clk_gate("sim2_cg", "sim2_src", base + 0xb880, 28); - clks[IMX7D_GPT1_ROOT_CG] = imx_clk_gate("gpt1_cg", "gpt1_src", base + 0xb900, 28); - clks[IMX7D_GPT2_ROOT_CG] = imx_clk_gate("gpt2_cg", "gpt2_src", base + 0xb980, 28); - clks[IMX7D_GPT3_ROOT_CG] = imx_clk_gate("gpt3_cg", "gpt3_src", base + 0xbA00, 28); - clks[IMX7D_GPT4_ROOT_CG] = imx_clk_gate("gpt4_cg", "gpt4_src", base + 0xbA80, 28); - clks[IMX7D_TRACE_ROOT_CG] = imx_clk_gate("trace_cg", "trace_src", base + 0xbb00, 28); - clks[IMX7D_WDOG_ROOT_CG] = imx_clk_gate("wdog_cg", "wdog_src", base + 0xbb80, 28); - clks[IMX7D_CSI_MCLK_ROOT_CG] = imx_clk_gate("csi_mclk_cg", "csi_mclk_src", base + 0xbc00, 28); - clks[IMX7D_AUDIO_MCLK_ROOT_CG] = imx_clk_gate("audio_mclk_cg", "audio_mclk_src", base + 0xbc80, 28); - clks[IMX7D_WRCLK_ROOT_CG] = imx_clk_gate("wrclk_cg", "wrclk_src", base + 0xbd00, 28); - clks[IMX7D_CLKO1_ROOT_CG] = imx_clk_gate("clko1_cg", "clko1_src", base + 0xbd80, 28); - clks[IMX7D_CLKO2_ROOT_CG] = imx_clk_gate("clko2_cg", "clko2_src", base + 0xbe00, 28); - - clks[IMX7D_MAIN_AXI_ROOT_PRE_DIV] = imx_clk_divider("axi_pre_div", "axi_cg", base + 0x8800, 16, 3); - clks[IMX7D_DISP_AXI_ROOT_PRE_DIV] = imx_clk_divider("disp_axi_pre_div", "disp_axi_cg", base + 0x8880, 16, 3); - clks[IMX7D_ENET_AXI_ROOT_PRE_DIV] = imx_clk_divider("enet_axi_pre_div", "enet_axi_cg", base + 0x8900, 16, 3); - clks[IMX7D_NAND_USDHC_BUS_ROOT_PRE_DIV] = imx_clk_divider("nand_usdhc_pre_div", "nand_usdhc_cg", base + 0x8980, 16, 3); - clks[IMX7D_AHB_CHANNEL_ROOT_PRE_DIV] = imx_clk_divider("ahb_pre_div", "ahb_cg", base + 0x9000, 16, 3); - clks[IMX7D_DRAM_PHYM_ALT_ROOT_PRE_DIV] = imx_clk_divider("dram_phym_alt_pre_div", "dram_phym_alt_cg", base + 0xa000, 16, 3); - clks[IMX7D_DRAM_ALT_ROOT_PRE_DIV] = imx_clk_divider("dram_alt_pre_div", "dram_alt_cg", base + 0xa080, 16, 3); - clks[IMX7D_USB_HSIC_ROOT_PRE_DIV] = imx_clk_divider("usb_hsic_pre_div", "usb_hsic_cg", base + 0xa100, 16, 3); - clks[IMX7D_PCIE_CTRL_ROOT_PRE_DIV] = imx_clk_divider("pcie_ctrl_pre_div", "pcie_ctrl_cg", base + 0xa180, 16, 3); - clks[IMX7D_PCIE_PHY_ROOT_PRE_DIV] = imx_clk_divider("pcie_phy_pre_div", "pcie_phy_cg", base + 0xa200, 16, 3); - clks[IMX7D_EPDC_PIXEL_ROOT_PRE_DIV] = imx_clk_divider("epdc_pixel_pre_div", "epdc_pixel_cg", base + 0xa280, 16, 3); - clks[IMX7D_LCDIF_PIXEL_ROOT_PRE_DIV] = imx_clk_divider("lcdif_pixel_pre_div", "lcdif_pixel_cg", base + 0xa300, 16, 3); - clks[IMX7D_MIPI_DSI_ROOT_PRE_DIV] = imx_clk_divider("mipi_dsi_pre_div", "mipi_dsi_cg", base + 0xa380, 16, 3); - clks[IMX7D_MIPI_CSI_ROOT_PRE_DIV] = imx_clk_divider("mipi_csi_pre_div", "mipi_csi_cg", base + 0xa400, 16, 3); - clks[IMX7D_MIPI_DPHY_ROOT_PRE_DIV] = imx_clk_divider("mipi_dphy_pre_div", "mipi_dphy_cg", base + 0xa480, 16, 3); - clks[IMX7D_SAI1_ROOT_PRE_DIV] = imx_clk_divider("sai1_pre_div", "sai1_cg", base + 0xa500, 16, 3); - clks[IMX7D_SAI2_ROOT_PRE_DIV] = imx_clk_divider("sai2_pre_div", "sai2_cg", base + 0xa580, 16, 3); - clks[IMX7D_SAI3_ROOT_PRE_DIV] = imx_clk_divider("sai3_pre_div", "sai3_cg", base + 0xa600, 16, 3); - clks[IMX7D_SPDIF_ROOT_PRE_DIV] = imx_clk_divider("spdif_pre_div", "spdif_cg", base + 0xa680, 16, 3); - clks[IMX7D_ENET1_REF_ROOT_PRE_DIV] = imx_clk_divider("enet1_ref_pre_div", "enet1_ref_cg", base + 0xa700, 16, 3); - clks[IMX7D_ENET1_TIME_ROOT_PRE_DIV] = imx_clk_divider("enet1_time_pre_div", "enet1_time_cg", base + 0xa780, 16, 3); - clks[IMX7D_ENET2_REF_ROOT_PRE_DIV] = imx_clk_divider("enet2_ref_pre_div", "enet2_ref_cg", base + 0xa800, 16, 3); - clks[IMX7D_ENET2_TIME_ROOT_PRE_DIV] = imx_clk_divider("enet2_time_pre_div", "enet2_time_cg", base + 0xa880, 16, 3); - clks[IMX7D_ENET_PHY_REF_ROOT_PRE_DIV] = imx_clk_divider("enet_phy_ref_pre_div", "enet_phy_ref_cg", base + 0xa900, 16, 3); - clks[IMX7D_EIM_ROOT_PRE_DIV] = imx_clk_divider("eim_pre_div", "eim_cg", base + 0xa980, 16, 3); - clks[IMX7D_NAND_ROOT_PRE_DIV] = imx_clk_divider("nand_pre_div", "nand_cg", base + 0xaa00, 16, 3); - clks[IMX7D_QSPI_ROOT_PRE_DIV] = imx_clk_divider("qspi_pre_div", "qspi_cg", base + 0xaa80, 16, 3); - clks[IMX7D_USDHC1_ROOT_PRE_DIV] = imx_clk_divider("usdhc1_pre_div", "usdhc1_cg", base + 0xab00, 16, 3); - clks[IMX7D_USDHC2_ROOT_PRE_DIV] = imx_clk_divider("usdhc2_pre_div", "usdhc2_cg", base + 0xab80, 16, 3); - clks[IMX7D_USDHC3_ROOT_PRE_DIV] = imx_clk_divider("usdhc3_pre_div", "usdhc3_cg", base + 0xac00, 16, 3); - clks[IMX7D_CAN1_ROOT_PRE_DIV] = imx_clk_divider("can1_pre_div", "can1_cg", base + 0xac80, 16, 3); - clks[IMX7D_CAN2_ROOT_PRE_DIV] = imx_clk_divider("can2_pre_div", "can2_cg", base + 0xad00, 16, 3); - clks[IMX7D_I2C1_ROOT_PRE_DIV] = imx_clk_divider("i2c1_pre_div", "i2c1_cg", base + 0xad80, 16, 3); - clks[IMX7D_I2C2_ROOT_PRE_DIV] = imx_clk_divider("i2c2_pre_div", "i2c2_cg", base + 0xae00, 16, 3); - clks[IMX7D_I2C3_ROOT_PRE_DIV] = imx_clk_divider("i2c3_pre_div", "i2c3_cg", base + 0xae80, 16, 3); - clks[IMX7D_I2C4_ROOT_PRE_DIV] = imx_clk_divider("i2c4_pre_div", "i2c4_cg", base + 0xaf00, 16, 3); - clks[IMX7D_UART1_ROOT_PRE_DIV] = imx_clk_divider("uart1_pre_div", "uart1_cg", base + 0xaf80, 16, 3); - clks[IMX7D_UART2_ROOT_PRE_DIV] = imx_clk_divider("uart2_pre_div", "uart2_cg", base + 0xb000, 16, 3); - clks[IMX7D_UART3_ROOT_PRE_DIV] = imx_clk_divider("uart3_pre_div", "uart3_cg", base + 0xb080, 16, 3); - clks[IMX7D_UART4_ROOT_PRE_DIV] = imx_clk_divider("uart4_pre_div", "uart4_cg", base + 0xb100, 16, 3); - clks[IMX7D_UART5_ROOT_PRE_DIV] = imx_clk_divider("uart5_pre_div", "uart5_cg", base + 0xb180, 16, 3); - clks[IMX7D_UART6_ROOT_PRE_DIV] = imx_clk_divider("uart6_pre_div", "uart6_cg", base + 0xb200, 16, 3); - clks[IMX7D_UART7_ROOT_PRE_DIV] = imx_clk_divider("uart7_pre_div", "uart7_cg", base + 0xb280, 16, 3); - clks[IMX7D_ECSPI1_ROOT_PRE_DIV] = imx_clk_divider("ecspi1_pre_div", "ecspi1_cg", base + 0xb300, 16, 3); - clks[IMX7D_ECSPI2_ROOT_PRE_DIV] = imx_clk_divider("ecspi2_pre_div", "ecspi2_cg", base + 0xb380, 16, 3); - clks[IMX7D_ECSPI3_ROOT_PRE_DIV] = imx_clk_divider("ecspi3_pre_div", "ecspi3_cg", base + 0xb400, 16, 3); - clks[IMX7D_ECSPI4_ROOT_PRE_DIV] = imx_clk_divider("ecspi4_pre_div", "ecspi4_cg", base + 0xb480, 16, 3); - clks[IMX7D_PWM1_ROOT_PRE_DIV] = imx_clk_divider("pwm1_pre_div", "pwm1_cg", base + 0xb500, 16, 3); - clks[IMX7D_PWM2_ROOT_PRE_DIV] = imx_clk_divider("pwm2_pre_div", "pwm2_cg", base + 0xb580, 16, 3); - clks[IMX7D_PWM3_ROOT_PRE_DIV] = imx_clk_divider("pwm3_pre_div", "pwm3_cg", base + 0xb600, 16, 3); - clks[IMX7D_PWM4_ROOT_PRE_DIV] = imx_clk_divider("pwm4_pre_div", "pwm4_cg", base + 0xb680, 16, 3); - clks[IMX7D_FLEXTIMER1_ROOT_PRE_DIV] = imx_clk_divider("flextimer1_pre_div", "flextimer1_cg", base + 0xb700, 16, 3); - clks[IMX7D_FLEXTIMER2_ROOT_PRE_DIV] = imx_clk_divider("flextimer2_pre_div", "flextimer2_cg", base + 0xb780, 16, 3); - clks[IMX7D_SIM1_ROOT_PRE_DIV] = imx_clk_divider("sim1_pre_div", "sim1_cg", base + 0xb800, 16, 3); - clks[IMX7D_SIM2_ROOT_PRE_DIV] = imx_clk_divider("sim2_pre_div", "sim2_cg", base + 0xb880, 16, 3); - clks[IMX7D_GPT1_ROOT_PRE_DIV] = imx_clk_divider("gpt1_pre_div", "gpt1_cg", base + 0xb900, 16, 3); - clks[IMX7D_GPT2_ROOT_PRE_DIV] = imx_clk_divider("gpt2_pre_div", "gpt2_cg", base + 0xb980, 16, 3); - clks[IMX7D_GPT3_ROOT_PRE_DIV] = imx_clk_divider("gpt3_pre_div", "gpt3_cg", base + 0xba00, 16, 3); - clks[IMX7D_GPT4_ROOT_PRE_DIV] = imx_clk_divider("gpt4_pre_div", "gpt4_cg", base + 0xba80, 16, 3); - clks[IMX7D_TRACE_ROOT_PRE_DIV] = imx_clk_divider("trace_pre_div", "trace_cg", base + 0xbb00, 16, 3); - clks[IMX7D_WDOG_ROOT_PRE_DIV] = imx_clk_divider("wdog_pre_div", "wdog_cg", base + 0xbb80, 16, 3); - clks[IMX7D_CSI_MCLK_ROOT_PRE_DIV] = imx_clk_divider("csi_mclk_pre_div", "csi_mclk_cg", base + 0xbc00, 16, 3); - clks[IMX7D_AUDIO_MCLK_ROOT_PRE_DIV] = imx_clk_divider("audio_mclk_pre_div", "audio_mclk_cg", base + 0xbc80, 16, 3); - clks[IMX7D_WRCLK_ROOT_PRE_DIV] = imx_clk_divider("wrclk_pre_div", "wrclk_cg", base + 0xbd00, 16, 3); - clks[IMX7D_CLKO1_ROOT_PRE_DIV] = imx_clk_divider("clko1_pre_div", "clko1_cg", base + 0xbd80, 16, 3); - clks[IMX7D_CLKO2_ROOT_PRE_DIV] = imx_clk_divider("clko2_pre_div", "clko2_cg", base + 0xbe00, 16, 3); - - clks[IMX7D_ARM_A7_ROOT_DIV] = imx_clk_divider("arm_a7_div", "arm_a7_cg", base + 0x8000, 0, 3); - clks[IMX7D_ARM_M4_ROOT_DIV] = imx_clk_divider("arm_m4_div", "arm_m4_cg", base + 0x8080, 0, 3); - clks[IMX7D_ARM_M0_ROOT_DIV] = imx_clk_divider("arm_m0_div", "arm_m0_cg", base + 0x8100, 0, 3); - clks[IMX7D_MAIN_AXI_ROOT_DIV] = imx_clk_divider("axi_post_div", "axi_pre_div", base + 0x8800, 0, 6); - clks[IMX7D_DISP_AXI_ROOT_DIV] = imx_clk_divider("disp_axi_post_div", "disp_axi_pre_div", base + 0x8880, 0, 6); - clks[IMX7D_ENET_AXI_ROOT_DIV] = imx_clk_divider("enet_axi_post_div", "enet_axi_pre_div", base + 0x8900, 0, 6); - clks[IMX7D_NAND_USDHC_BUS_ROOT_DIV] = imx_clk_divider("nand_usdhc_post_div", "nand_usdhc_pre_div", base + 0x8980, 0, 6); - clks[IMX7D_AHB_CHANNEL_ROOT_DIV] = imx_clk_divider("ahb_post_div", "ahb_pre_div", base + 0x9000, 0, 6); - clks[IMX7D_DRAM_ROOT_DIV] = imx_clk_divider("dram_post_div", "dram_cg", base + 0x9880, 0, 3); - clks[IMX7D_DRAM_PHYM_ALT_ROOT_DIV] = imx_clk_divider("dram_phym_alt_post_div", "dram_phym_alt_pre_div", base + 0xa000, 0, 3); - clks[IMX7D_DRAM_ALT_ROOT_DIV] = imx_clk_divider("dram_alt_post_div", "dram_alt_pre_div", base + 0xa080, 0, 3); - clks[IMX7D_USB_HSIC_ROOT_DIV] = imx_clk_divider("usb_hsic_post_div", "usb_hsic_pre_div", base + 0xa100, 0, 6); - clks[IMX7D_PCIE_CTRL_ROOT_DIV] = imx_clk_divider("pcie_ctrl_post_div", "pcie_ctrl_pre_div", base + 0xa180, 0, 6); - clks[IMX7D_PCIE_PHY_ROOT_DIV] = imx_clk_divider("pcie_phy_post_div", "pcie_phy_pre_div", base + 0xa200, 0, 6); - clks[IMX7D_EPDC_PIXEL_ROOT_DIV] = imx_clk_divider("epdc_pixel_post_div", "epdc_pixel_pre_div", base + 0xa280, 0, 6); - clks[IMX7D_LCDIF_PIXEL_ROOT_DIV] = imx_clk_divider("lcdif_pixel_post_div", "lcdif_pixel_pre_div", base + 0xa300, 0, 6); - clks[IMX7D_MIPI_DSI_ROOT_DIV] = imx_clk_divider("mipi_dsi_post_div", "mipi_dsi_pre_div", base + 0xa380, 0, 6); - clks[IMX7D_MIPI_CSI_ROOT_DIV] = imx_clk_divider("mipi_csi_post_div", "mipi_csi_pre_div", base + 0xa400, 0, 6); - clks[IMX7D_MIPI_DPHY_ROOT_DIV] = imx_clk_divider("mipi_dphy_post_div", "mipi_csi_dphy_div", base + 0xa480, 0, 6); - clks[IMX7D_SAI1_ROOT_DIV] = imx_clk_divider("sai1_post_div", "sai1_pre_div", base + 0xa500, 0, 6); - clks[IMX7D_SAI2_ROOT_DIV] = imx_clk_divider("sai2_post_div", "sai2_pre_div", base + 0xa580, 0, 6); - clks[IMX7D_SAI3_ROOT_DIV] = imx_clk_divider("sai3_post_div", "sai3_pre_div", base + 0xa600, 0, 6); - clks[IMX7D_SPDIF_ROOT_DIV] = imx_clk_divider("spdif_post_div", "spdif_pre_div", base + 0xa680, 0, 6); - clks[IMX7D_ENET1_REF_ROOT_DIV] = imx_clk_divider("enet1_ref_post_div", "enet1_ref_pre_div", base + 0xa700, 0, 6); - clks[IMX7D_ENET1_TIME_ROOT_DIV] = imx_clk_divider("enet1_time_post_div", "enet1_time_pre_div", base + 0xa780, 0, 6); - clks[IMX7D_ENET2_REF_ROOT_DIV] = imx_clk_divider("enet2_ref_post_div", "enet2_ref_pre_div", base + 0xa800, 0, 6); - clks[IMX7D_ENET2_TIME_ROOT_DIV] = imx_clk_divider("enet2_time_post_div", "enet2_time_pre_div", base + 0xa880, 0, 6); - clks[IMX7D_ENET_PHY_REF_ROOT_DIV] = imx_clk_divider("enet_phy_ref_post_div", "enet_phy_ref_pre_div", base + 0xa900, 0, 6); - clks[IMX7D_EIM_ROOT_DIV] = imx_clk_divider("eim_post_div", "eim_pre_div", base + 0xa980, 0, 6); - clks[IMX7D_NAND_ROOT_DIV] = imx_clk_divider("nand_post_div", "nand_pre_div", base + 0xaa00, 0, 6); - clks[IMX7D_QSPI_ROOT_DIV] = imx_clk_divider("qspi_post_div", "qspi_pre_div", base + 0xaa80, 0, 6); - clks[IMX7D_USDHC1_ROOT_DIV] = imx_clk_divider("usdhc1_post_div", "usdhc1_pre_div", base + 0xab00, 0, 6); - clks[IMX7D_USDHC2_ROOT_DIV] = imx_clk_divider("usdhc2_post_div", "usdhc2_pre_div", base + 0xab80, 0, 6); - clks[IMX7D_USDHC3_ROOT_DIV] = imx_clk_divider("usdhc3_post_div", "usdhc3_pre_div", base + 0xac00, 0, 6); - clks[IMX7D_CAN1_ROOT_DIV] = imx_clk_divider("can1_post_div", "can1_pre_div", base + 0xac80, 0, 6); - clks[IMX7D_CAN2_ROOT_DIV] = imx_clk_divider("can2_post_div", "can2_pre_div", base + 0xad00, 0, 6); - clks[IMX7D_I2C1_ROOT_DIV] = imx_clk_divider("i2c1_post_div", "i2c1_pre_div", base + 0xad80, 0, 6); - clks[IMX7D_I2C2_ROOT_DIV] = imx_clk_divider("i2c2_post_div", "i2c2_pre_div", base + 0xae00, 0, 6); - clks[IMX7D_I2C3_ROOT_DIV] = imx_clk_divider("i2c3_post_div", "i2c3_pre_div", base + 0xae80, 0, 6); - clks[IMX7D_I2C4_ROOT_DIV] = imx_clk_divider("i2c4_post_div", "i2c4_pre_div", base + 0xaf00, 0, 6); - clks[IMX7D_UART1_ROOT_DIV] = imx_clk_divider("uart1_post_div", "uart1_pre_div", base + 0xaf80, 0, 6); - clks[IMX7D_UART2_ROOT_DIV] = imx_clk_divider("uart2_post_div", "uart2_pre_div", base + 0xb000, 0, 6); - clks[IMX7D_UART3_ROOT_DIV] = imx_clk_divider("uart3_post_div", "uart3_pre_div", base + 0xb080, 0, 6); - clks[IMX7D_UART4_ROOT_DIV] = imx_clk_divider("uart4_post_div", "uart4_pre_div", base + 0xb100, 0, 6); - clks[IMX7D_UART5_ROOT_DIV] = imx_clk_divider("uart5_post_div", "uart5_pre_div", base + 0xb180, 0, 6); - clks[IMX7D_UART6_ROOT_DIV] = imx_clk_divider("uart6_post_div", "uart6_pre_div", base + 0xb200, 0, 6); - clks[IMX7D_UART7_ROOT_DIV] = imx_clk_divider("uart7_post_div", "uart7_pre_div", base + 0xb280, 0, 6); - clks[IMX7D_ECSPI1_ROOT_DIV] = imx_clk_divider("ecspi1_post_div", "ecspi1_pre_div", base + 0xb300, 0, 6); - clks[IMX7D_ECSPI2_ROOT_DIV] = imx_clk_divider("ecspi2_post_div", "ecspi2_pre_div", base + 0xb380, 0, 6); - clks[IMX7D_ECSPI3_ROOT_DIV] = imx_clk_divider("ecspi3_post_div", "ecspi3_pre_div", base + 0xb400, 0, 6); - clks[IMX7D_ECSPI4_ROOT_DIV] = imx_clk_divider("ecspi4_post_div", "ecspi4_pre_div", base + 0xb480, 0, 6); - clks[IMX7D_PWM1_ROOT_DIV] = imx_clk_divider("pwm1_post_div", "pwm1_pre_div", base + 0xb500, 0, 6); - clks[IMX7D_PWM2_ROOT_DIV] = imx_clk_divider("pwm2_post_div", "pwm2_pre_div", base + 0xb580, 0, 6); - clks[IMX7D_PWM3_ROOT_DIV] = imx_clk_divider("pwm3_post_div", "pwm3_pre_div", base + 0xb600, 0, 6); - clks[IMX7D_PWM4_ROOT_DIV] = imx_clk_divider("pwm4_post_div", "pwm4_pre_div", base + 0xb680, 0, 6); - clks[IMX7D_FLEXTIMER1_ROOT_DIV] = imx_clk_divider("flextimer1_post_div", "flextimer1_pre_div", base + 0xb700, 0, 6); - clks[IMX7D_FLEXTIMER2_ROOT_DIV] = imx_clk_divider("flextimer2_post_div", "flextimer2_pre_div", base + 0xb780, 0, 6); - clks[IMX7D_SIM1_ROOT_DIV] = imx_clk_divider("sim1_post_div", "sim1_pre_div", base + 0xb800, 0, 6); - clks[IMX7D_SIM2_ROOT_DIV] = imx_clk_divider("sim2_post_div", "sim2_pre_div", base + 0xb880, 0, 6); - clks[IMX7D_GPT1_ROOT_DIV] = imx_clk_divider("gpt1_post_div", "gpt1_pre_div", base + 0xb900, 0, 6); - clks[IMX7D_GPT2_ROOT_DIV] = imx_clk_divider("gpt2_post_div", "gpt2_pre_div", base + 0xb980, 0, 6); - clks[IMX7D_GPT3_ROOT_DIV] = imx_clk_divider("gpt3_post_div", "gpt3_pre_div", base + 0xba00, 0, 6); - clks[IMX7D_GPT4_ROOT_DIV] = imx_clk_divider("gpt4_post_div", "gpt4_pre_div", base + 0xba80, 0, 6); - clks[IMX7D_TRACE_ROOT_DIV] = imx_clk_divider("trace_post_div", "trace_pre_div", base + 0xbb00, 0, 6); - clks[IMX7D_WDOG_ROOT_DIV] = imx_clk_divider("wdog_post_div", "wdog_pre_div", base + 0xbb80, 0, 6); - clks[IMX7D_CSI_MCLK_ROOT_DIV] = imx_clk_divider("csi_mclk_post_div", "csi_mclk_pre_div", base + 0xbc00, 0, 6); - clks[IMX7D_AUDIO_MCLK_ROOT_DIV] = imx_clk_divider("audio_mclk_post_div", "audio_mclk_pre_div", base + 0xbc80, 0, 6); - clks[IMX7D_WRCLK_ROOT_DIV] = imx_clk_divider("wrclk_post_div", "wrclk_pre_div", base + 0xbd00, 0, 6); - clks[IMX7D_CLKO1_ROOT_DIV] = imx_clk_divider("clko1_post_div", "clko1_pre_div", base + 0xbd80, 0, 6); - clks[IMX7D_CLKO2_ROOT_DIV] = imx_clk_divider("clko2_post_div", "clko2_pre_div", base + 0xbe00, 0, 6); - - clks[IMX7D_ARM_A7_ROOT_CLK] = imx_clk_gate2("arm_a7_root_clk", "arm_a7_div", base + 0x4000, 0); - clks[IMX7D_ARM_M4_ROOT_CLK] = imx_clk_gate2("arm_m4_root_clk", "arm_m4_div", base + 0x4010, 0); - clks[IMX7D_ARM_M0_ROOT_CLK] = imx_clk_gate2("arm_m0_root_clk", "arm_m0_div", base + 0x4020, 0); - clks[IMX7D_MAIN_AXI_ROOT_CLK] = imx_clk_gate2("main_axi_root_clk", "axi_post_div", base + 0x4040, 0); - clks[IMX7D_DISP_AXI_ROOT_CLK] = imx_clk_gate2("disp_axi_root_clk", "disp_axi_post_div", base + 0x4050, 0); - clks[IMX7D_ENET_AXI_ROOT_CLK] = imx_clk_gate2("enet_axi_root_clk", "enet_axi_post_div", base + 0x4060, 0); - clks[IMX7D_OCRAM_CLK] = imx_clk_gate2("ocram_clk", "axi_post_div", base + 0x4110, 0); - clks[IMX7D_OCRAM_S_CLK] = imx_clk_gate2("ocram_s_clk", "ahb_post_div", base + 0x4120, 0); - clks[IMX7D_NAND_USDHC_BUS_ROOT_CLK] = imx_clk_gate2("nand_usdhc_root_clk", "nand_usdhc_post_div", base + 0x4130, 0); - clks[IMX7D_AHB_CHANNEL_ROOT_CLK] = imx_clk_gate2("ahb_root_clk", "ahb_post_div", base + 0x4200, 0); - clks[IMX7D_DRAM_ROOT_CLK] = imx_clk_gate2("dram_root_clk", "dram_post_div", base + 0x4130, 0); - clks[IMX7D_DRAM_PHYM_ROOT_CLK] = imx_clk_gate2("dram_phym_root_clk", "dram_phym_cg", base + 0x4130, 0); - clks[IMX7D_DRAM_PHYM_ALT_ROOT_CLK] = imx_clk_gate2("dram_phym_alt_root_clk", "dram_phym_alt_post_div", base + 0x4130, 0); - clks[IMX7D_DRAM_ALT_ROOT_CLK] = imx_clk_gate2("dram_alt_root_clk", "dram_alt_post_div", base + 0x4130, 0); - clks[IMX7D_USB_HSIC_ROOT_CLK] = imx_clk_gate2("usb_hsic_root_clk", "usb_hsic_post_div", base + 0x4420, 0); - clks[IMX7D_PCIE_CTRL_ROOT_CLK] = imx_clk_gate2("pcie_ctrl_root_clk", "pcie_ctrl_post_div", base + 0x4600, 0); - clks[IMX7D_PCIE_PHY_ROOT_CLK] = imx_clk_gate2("pcie_phy_root_clk", "pcie_phy_post_div", base + 0x4600, 0); - clks[IMX7D_EPDC_PIXEL_ROOT_CLK] = imx_clk_gate2("epdc_pixel_root_clk", "epdc_pixel_post_div", base + 0x44a0, 0); - clks[IMX7D_LCDIF_PIXEL_ROOT_CLK] = imx_clk_gate2("lcdif_pixel_root_clk", "lcdif_pixel_post_div", base + 0x44b0, 0); - clks[IMX7D_MIPI_DSI_ROOT_CLK] = imx_clk_gate2("mipi_dsi_root_clk", "mipi_dsi_post_div", base + 0x4650, 0); - clks[IMX7D_MIPI_CSI_ROOT_CLK] = imx_clk_gate2("mipi_csi_root_clk", "mipi_csi_post_div", base + 0x4640, 0); - clks[IMX7D_MIPI_DPHY_ROOT_CLK] = imx_clk_gate2("mipi_dphy_root_clk", "mipi_dphy_post_div", base + 0x4660, 0); - clks[IMX7D_SAI1_ROOT_CLK] = imx_clk_gate2("sai1_root_clk", "sai1_post_div", base + 0x48c0, 0); - clks[IMX7D_SAI2_ROOT_CLK] = imx_clk_gate2("sai2_root_clk", "sai2_post_div", base + 0x48d0, 0); - clks[IMX7D_SAI3_ROOT_CLK] = imx_clk_gate2("sai3_root_clk", "sai3_post_div", base + 0x48e0, 0); - clks[IMX7D_SPDIF_ROOT_CLK] = imx_clk_gate2("spdif_root_clk", "spdif_post_div", base + 0x44d0, 0); - clks[IMX7D_ENET1_REF_ROOT_CLK] = imx_clk_gate2("enet1_ref_root_clk", "enet1_ref_post_div", base + 0x44e0, 0); - clks[IMX7D_ENET1_TIME_ROOT_CLK] = imx_clk_gate2("enet1_time_root_clk", "enet1_time_post_div", base + 0x44f0, 0); - clks[IMX7D_ENET2_REF_ROOT_CLK] = imx_clk_gate2("enet2_ref_root_clk", "enet2_ref_post_div", base + 0x4500, 0); - clks[IMX7D_ENET2_TIME_ROOT_CLK] = imx_clk_gate2("enet2_time_root_clk", "enet2_time_post_div", base + 0x4510, 0); - clks[IMX7D_ENET_PHY_REF_ROOT_CLK] = imx_clk_gate2("enet_phy_ref_root_clk", "enet_phy_ref_post_div", base + 0x4520, 0); - clks[IMX7D_EIM_ROOT_CLK] = imx_clk_gate2("eim_root_clk", "eim_post_div", base + 0x4160, 0); - clks[IMX7D_NAND_ROOT_CLK] = imx_clk_gate2("nand_root_clk", "nand_post_div", base + 0x4140, 0); - clks[IMX7D_QSPI_ROOT_CLK] = imx_clk_gate2("qspi_root_clk", "qspi_post_div", base + 0x4150, 0); - clks[IMX7D_USDHC1_ROOT_CLK] = imx_clk_gate2("usdhc1_root_clk", "usdhc1_post_div", base + 0x46c0, 0); - clks[IMX7D_USDHC2_ROOT_CLK] = imx_clk_gate2("usdhc2_root_clk", "usdhc2_post_div", base + 0x46d0, 0); - clks[IMX7D_USDHC3_ROOT_CLK] = imx_clk_gate2("usdhc3_root_clk", "usdhc3_post_div", base + 0x46e0, 0); - clks[IMX7D_CAN1_ROOT_CLK] = imx_clk_gate2("can1_root_clk", "can1_post_div", base + 0x4740, 0); - clks[IMX7D_CAN2_ROOT_CLK] = imx_clk_gate2("can2_root_clk", "can2_post_div", base + 0x4750, 0); - clks[IMX7D_I2C1_ROOT_CLK] = imx_clk_gate2("i2c1_root_clk", "i2c1_post_div", base + 0x4880, 0); - clks[IMX7D_I2C2_ROOT_CLK] = imx_clk_gate2("i2c2_root_clk", "i2c2_post_div", base + 0x4890, 0); - clks[IMX7D_I2C3_ROOT_CLK] = imx_clk_gate2("i2c3_root_clk", "i2c3_post_div", base + 0x48a0, 0); - clks[IMX7D_I2C4_ROOT_CLK] = imx_clk_gate2("i2c4_root_clk", "i2c4_post_div", base + 0x48b0, 0); - clks[IMX7D_UART1_ROOT_CLK] = imx_clk_gate2("uart1_root_clk", "uart1_post_div", base + 0x4940, 0); - clks[IMX7D_UART2_ROOT_CLK] = imx_clk_gate2("uart2_root_clk", "uart2_post_div", base + 0x4950, 0); - clks[IMX7D_UART3_ROOT_CLK] = imx_clk_gate2("uart3_root_clk", "uart3_post_div", base + 0x4960, 0); - clks[IMX7D_UART4_ROOT_CLK] = imx_clk_gate2("uart4_root_clk", "uart4_post_div", base + 0x4970, 0); - clks[IMX7D_UART5_ROOT_CLK] = imx_clk_gate2("uart5_root_clk", "uart5_post_div", base + 0x4980, 0); - clks[IMX7D_UART6_ROOT_CLK] = imx_clk_gate2("uart6_root_clk", "uart6_post_div", base + 0x4990, 0); - clks[IMX7D_UART7_ROOT_CLK] = imx_clk_gate2("uart7_root_clk", "uart7_post_div", base + 0x49a0, 0); - clks[IMX7D_ECSPI1_ROOT_CLK] = imx_clk_gate2("ecspi1_root_clk", "ecspi1_post_div", base + 0x4780, 0); - clks[IMX7D_ECSPI2_ROOT_CLK] = imx_clk_gate2("ecspi2_root_clk", "ecspi2_post_div", base + 0x4790, 0); - clks[IMX7D_ECSPI3_ROOT_CLK] = imx_clk_gate2("ecspi3_root_clk", "ecspi3_post_div", base + 0x47a0, 0); - clks[IMX7D_ECSPI4_ROOT_CLK] = imx_clk_gate2("ecspi4_root_clk", "ecspi4_post_div", base + 0x47b0, 0); - clks[IMX7D_PWM1_ROOT_CLK] = imx_clk_gate2("pwm1_root_clk", "pwm1_post_div", base + 0x4840, 0); - clks[IMX7D_PWM2_ROOT_CLK] = imx_clk_gate2("pwm2_root_clk", "pwm2_post_div", base + 0x4850, 0); - clks[IMX7D_PWM3_ROOT_CLK] = imx_clk_gate2("pwm3_root_clk", "pwm3_post_div", base + 0x4860, 0); - clks[IMX7D_PWM4_ROOT_CLK] = imx_clk_gate2("pwm4_root_clk", "pwm4_post_div", base + 0x4870, 0); - clks[IMX7D_FLEXTIMER1_ROOT_CLK] = imx_clk_gate2("flextimer1_root_clk", "flextimer1_post_div", base + 0x4800, 0); - clks[IMX7D_FLEXTIMER2_ROOT_CLK] = imx_clk_gate2("flextimer2_root_clk", "flextimer2_post_div", base + 0x4810, 0); - clks[IMX7D_SIM1_ROOT_CLK] = imx_clk_gate2("sim1_root_clk", "sim1_post_div", base + 0x4900, 0); - clks[IMX7D_SIM2_ROOT_CLK] = imx_clk_gate2("sim2_root_clk", "sim2_post_div", base + 0x4910, 0); - clks[IMX7D_GPT1_ROOT_CLK] = imx_clk_gate2("gpt1_root_clk", "gpt1_post_div", base + 0x47c0, 0); - clks[IMX7D_GPT2_ROOT_CLK] = imx_clk_gate2("gpt2_root_clk", "gpt2_post_div", base + 0x47d0, 0); - clks[IMX7D_GPT3_ROOT_CLK] = imx_clk_gate2("gpt3_root_clk", "gpt3_post_div", base + 0x47e0, 0); - clks[IMX7D_GPT4_ROOT_CLK] = imx_clk_gate2("gpt4_root_clk", "gpt4_post_div", base + 0x47f0, 0); - clks[IMX7D_TRACE_ROOT_CLK] = imx_clk_gate2("trace_root_clk", "trace_post_div", base + 0x4300, 0); - clks[IMX7D_WDOG1_ROOT_CLK] = imx_clk_gate2("wdog1_root_clk", "wdog_post_div", base + 0x49c0, 0); - clks[IMX7D_WDOG2_ROOT_CLK] = imx_clk_gate2("wdog2_root_clk", "wdog_post_div", base + 0x49d0, 0); - clks[IMX7D_WDOG3_ROOT_CLK] = imx_clk_gate2("wdog3_root_clk", "wdog_post_div", base + 0x49e0, 0); - clks[IMX7D_WDOG4_ROOT_CLK] = imx_clk_gate2("wdog4_root_clk", "wdog_post_div", base + 0x49f0, 0); - clks[IMX7D_CSI_MCLK_ROOT_CLK] = imx_clk_gate2("csi_mclk_root_clk", "csi_mclk_post_div", base + 0x4490, 0); - clks[IMX7D_AUDIO_MCLK_ROOT_CLK] = imx_clk_gate2("audio_mclk_root_clk", "audio_mclk_post_div", base + 0x4790, 0); - clks[IMX7D_WRCLK_ROOT_CLK] = imx_clk_gate2("wrclk_root_clk", "wrclk_post_div", base + 0x47a0, 0); - clks[IMX7D_ADC_ROOT_CLK] = imx_clk_gate2("adc_root_clk", "ipg_root_clk", base + 0x4200, 0); + clks[IMX7D_ARM_A7_ROOT_SRC] = imx_clk_mux2("arm_a7_src", base + 0x8000, 24, 3, arm_a7_sel, ARRAY_SIZE(arm_a7_sel)); + clks[IMX7D_ARM_M4_ROOT_SRC] = imx_clk_mux2("arm_m4_src", base + 0x8080, 24, 3, arm_m4_sel, ARRAY_SIZE(arm_m4_sel)); + clks[IMX7D_ARM_M0_ROOT_SRC] = imx_clk_mux2("arm_m0_src", base + 0x8100, 24, 3, arm_m0_sel, ARRAY_SIZE(arm_m0_sel)); + clks[IMX7D_MAIN_AXI_ROOT_SRC] = imx_clk_mux2("axi_src", base + 0x8800, 24, 3, axi_sel, ARRAY_SIZE(axi_sel)); + clks[IMX7D_DISP_AXI_ROOT_SRC] = imx_clk_mux2("disp_axi_src", base + 0x8880, 24, 3, disp_axi_sel, ARRAY_SIZE(disp_axi_sel)); + clks[IMX7D_ENET_AXI_ROOT_SRC] = imx_clk_mux2("enet_axi_src", base + 0x8900, 24, 3, enet_axi_sel, ARRAY_SIZE(enet_axi_sel)); + clks[IMX7D_NAND_USDHC_BUS_ROOT_SRC] = imx_clk_mux2("nand_usdhc_src", base + 0x8980, 24, 3, nand_usdhc_bus_sel, ARRAY_SIZE(nand_usdhc_bus_sel)); + clks[IMX7D_AHB_CHANNEL_ROOT_SRC] = imx_clk_mux2("ahb_src", base + 0x9000, 24, 3, ahb_channel_sel, ARRAY_SIZE(ahb_channel_sel)); + clks[IMX7D_DRAM_PHYM_ROOT_SRC] = imx_clk_mux2("dram_phym_src", base + 0x9800, 24, 1, dram_phym_sel, ARRAY_SIZE(dram_phym_sel)); + clks[IMX7D_DRAM_ROOT_SRC] = imx_clk_mux2("dram_src", base + 0x9880, 24, 1, dram_sel, ARRAY_SIZE(dram_sel)); + clks[IMX7D_DRAM_PHYM_ALT_ROOT_SRC] = imx_clk_mux2("dram_phym_alt_src", base + 0xa000, 24, 3, dram_phym_alt_sel, ARRAY_SIZE(dram_phym_alt_sel)); + clks[IMX7D_DRAM_ALT_ROOT_SRC] = imx_clk_mux2("dram_alt_src", base + 0xa080, 24, 3, dram_alt_sel, ARRAY_SIZE(dram_alt_sel)); + clks[IMX7D_USB_HSIC_ROOT_SRC] = imx_clk_mux2("usb_hsic_src", base + 0xa100, 24, 3, usb_hsic_sel, ARRAY_SIZE(usb_hsic_sel)); + clks[IMX7D_PCIE_CTRL_ROOT_SRC] = imx_clk_mux2("pcie_ctrl_src", base + 0xa180, 24, 3, pcie_ctrl_sel, ARRAY_SIZE(pcie_ctrl_sel)); + clks[IMX7D_PCIE_PHY_ROOT_SRC] = imx_clk_mux2("pcie_phy_src", base + 0xa200, 24, 3, pcie_phy_sel, ARRAY_SIZE(pcie_phy_sel)); + clks[IMX7D_EPDC_PIXEL_ROOT_SRC] = imx_clk_mux2("epdc_pixel_src", base + 0xa280, 24, 3, epdc_pixel_sel, ARRAY_SIZE(epdc_pixel_sel)); + clks[IMX7D_LCDIF_PIXEL_ROOT_SRC] = imx_clk_mux2("lcdif_pixel_src", base + 0xa300, 24, 3, lcdif_pixel_sel, ARRAY_SIZE(lcdif_pixel_sel)); + clks[IMX7D_MIPI_DSI_ROOT_SRC] = imx_clk_mux2("mipi_dsi_src", base + 0xa380, 24, 3, mipi_dsi_sel, ARRAY_SIZE(mipi_dsi_sel)); + clks[IMX7D_MIPI_CSI_ROOT_SRC] = imx_clk_mux2("mipi_csi_src", base + 0xa400, 24, 3, mipi_csi_sel, ARRAY_SIZE(mipi_csi_sel)); + clks[IMX7D_MIPI_DPHY_ROOT_SRC] = imx_clk_mux2("mipi_dphy_src", base + 0xa480, 24, 3, mipi_dphy_sel, ARRAY_SIZE(mipi_dphy_sel)); + clks[IMX7D_SAI1_ROOT_SRC] = imx_clk_mux2("sai1_src", base + 0xa500, 24, 3, sai1_sel, ARRAY_SIZE(sai1_sel)); + clks[IMX7D_SAI2_ROOT_SRC] = imx_clk_mux2("sai2_src", base + 0xa580, 24, 3, sai2_sel, ARRAY_SIZE(sai2_sel)); + clks[IMX7D_SAI3_ROOT_SRC] = imx_clk_mux2("sai3_src", base + 0xa600, 24, 3, sai3_sel, ARRAY_SIZE(sai3_sel)); + clks[IMX7D_SPDIF_ROOT_SRC] = imx_clk_mux2("spdif_src", base + 0xa680, 24, 3, spdif_sel, ARRAY_SIZE(spdif_sel)); + clks[IMX7D_ENET1_REF_ROOT_SRC] = imx_clk_mux2("enet1_ref_src", base + 0xa700, 24, 3, enet1_ref_sel, ARRAY_SIZE(enet1_ref_sel)); + clks[IMX7D_ENET1_TIME_ROOT_SRC] = imx_clk_mux2("enet1_time_src", base + 0xa780, 24, 3, enet1_time_sel, ARRAY_SIZE(enet1_time_sel)); + clks[IMX7D_ENET2_REF_ROOT_SRC] = imx_clk_mux2("enet2_ref_src", base + 0xa800, 24, 3, enet2_ref_sel, ARRAY_SIZE(enet2_ref_sel)); + clks[IMX7D_ENET2_TIME_ROOT_SRC] = imx_clk_mux2("enet2_time_src", base + 0xa880, 24, 3, enet2_time_sel, ARRAY_SIZE(enet2_time_sel)); + clks[IMX7D_ENET_PHY_REF_ROOT_SRC] = imx_clk_mux2("enet_phy_ref_src", base + 0xa900, 24, 3, enet_phy_ref_sel, ARRAY_SIZE(enet_phy_ref_sel)); + clks[IMX7D_EIM_ROOT_SRC] = imx_clk_mux2("eim_src", base + 0xa980, 24, 3, eim_sel, ARRAY_SIZE(eim_sel)); + clks[IMX7D_NAND_ROOT_SRC] = imx_clk_mux2("nand_src", base + 0xaa00, 24, 3, nand_sel, ARRAY_SIZE(nand_sel)); + clks[IMX7D_QSPI_ROOT_SRC] = imx_clk_mux2("qspi_src", base + 0xaa80, 24, 3, qspi_sel, ARRAY_SIZE(qspi_sel)); + clks[IMX7D_USDHC1_ROOT_SRC] = imx_clk_mux2("usdhc1_src", base + 0xab00, 24, 3, usdhc1_sel, ARRAY_SIZE(usdhc1_sel)); + clks[IMX7D_USDHC2_ROOT_SRC] = imx_clk_mux2("usdhc2_src", base + 0xab80, 24, 3, usdhc2_sel, ARRAY_SIZE(usdhc2_sel)); + clks[IMX7D_USDHC3_ROOT_SRC] = imx_clk_mux2("usdhc3_src", base + 0xac00, 24, 3, usdhc3_sel, ARRAY_SIZE(usdhc3_sel)); + clks[IMX7D_CAN1_ROOT_SRC] = imx_clk_mux2("can1_src", base + 0xac80, 24, 3, can1_sel, ARRAY_SIZE(can1_sel)); + clks[IMX7D_CAN2_ROOT_SRC] = imx_clk_mux2("can2_src", base + 0xad00, 24, 3, can2_sel, ARRAY_SIZE(can2_sel)); + clks[IMX7D_I2C1_ROOT_SRC] = imx_clk_mux2("i2c1_src", base + 0xad80, 24, 3, i2c1_sel, ARRAY_SIZE(i2c1_sel)); + clks[IMX7D_I2C2_ROOT_SRC] = imx_clk_mux2("i2c2_src", base + 0xae00, 24, 3, i2c2_sel, ARRAY_SIZE(i2c2_sel)); + clks[IMX7D_I2C3_ROOT_SRC] = imx_clk_mux2("i2c3_src", base + 0xae80, 24, 3, i2c3_sel, ARRAY_SIZE(i2c3_sel)); + clks[IMX7D_I2C4_ROOT_SRC] = imx_clk_mux2("i2c4_src", base + 0xaf00, 24, 3, i2c4_sel, ARRAY_SIZE(i2c4_sel)); + clks[IMX7D_UART1_ROOT_SRC] = imx_clk_mux2("uart1_src", base + 0xaf80, 24, 3, uart1_sel, ARRAY_SIZE(uart1_sel)); + clks[IMX7D_UART2_ROOT_SRC] = imx_clk_mux2("uart2_src", base + 0xb000, 24, 3, uart2_sel, ARRAY_SIZE(uart2_sel)); + clks[IMX7D_UART3_ROOT_SRC] = imx_clk_mux2("uart3_src", base + 0xb080, 24, 3, uart3_sel, ARRAY_SIZE(uart3_sel)); + clks[IMX7D_UART4_ROOT_SRC] = imx_clk_mux2("uart4_src", base + 0xb100, 24, 3, uart4_sel, ARRAY_SIZE(uart4_sel)); + clks[IMX7D_UART5_ROOT_SRC] = imx_clk_mux2("uart5_src", base + 0xb180, 24, 3, uart5_sel, ARRAY_SIZE(uart5_sel)); + clks[IMX7D_UART6_ROOT_SRC] = imx_clk_mux2("uart6_src", base + 0xb200, 24, 3, uart6_sel, ARRAY_SIZE(uart6_sel)); + clks[IMX7D_UART7_ROOT_SRC] = imx_clk_mux2("uart7_src", base + 0xb280, 24, 3, uart7_sel, ARRAY_SIZE(uart7_sel)); + clks[IMX7D_ECSPI1_ROOT_SRC] = imx_clk_mux2("ecspi1_src", base + 0xb300, 24, 3, ecspi1_sel, ARRAY_SIZE(ecspi1_sel)); + clks[IMX7D_ECSPI2_ROOT_SRC] = imx_clk_mux2("ecspi2_src", base + 0xb380, 24, 3, ecspi2_sel, ARRAY_SIZE(ecspi2_sel)); + clks[IMX7D_ECSPI3_ROOT_SRC] = imx_clk_mux2("ecspi3_src", base + 0xb400, 24, 3, ecspi3_sel, ARRAY_SIZE(ecspi3_sel)); + clks[IMX7D_ECSPI4_ROOT_SRC] = imx_clk_mux2("ecspi4_src", base + 0xb480, 24, 3, ecspi4_sel, ARRAY_SIZE(ecspi4_sel)); + clks[IMX7D_PWM1_ROOT_SRC] = imx_clk_mux2("pwm1_src", base + 0xb500, 24, 3, pwm1_sel, ARRAY_SIZE(pwm1_sel)); + clks[IMX7D_PWM2_ROOT_SRC] = imx_clk_mux2("pwm2_src", base + 0xb580, 24, 3, pwm2_sel, ARRAY_SIZE(pwm2_sel)); + clks[IMX7D_PWM3_ROOT_SRC] = imx_clk_mux2("pwm3_src", base + 0xb600, 24, 3, pwm3_sel, ARRAY_SIZE(pwm3_sel)); + clks[IMX7D_PWM4_ROOT_SRC] = imx_clk_mux2("pwm4_src", base + 0xb680, 24, 3, pwm4_sel, ARRAY_SIZE(pwm4_sel)); + clks[IMX7D_FLEXTIMER1_ROOT_SRC] = imx_clk_mux2("flextimer1_src", base + 0xb700, 24, 3, flextimer1_sel, ARRAY_SIZE(flextimer1_sel)); + clks[IMX7D_FLEXTIMER2_ROOT_SRC] = imx_clk_mux2("flextimer2_src", base + 0xb780, 24, 3, flextimer2_sel, ARRAY_SIZE(flextimer2_sel)); + clks[IMX7D_SIM1_ROOT_SRC] = imx_clk_mux2("sim1_src", base + 0xb800, 24, 3, sim1_sel, ARRAY_SIZE(sim1_sel)); + clks[IMX7D_SIM2_ROOT_SRC] = imx_clk_mux2("sim2_src", base + 0xb880, 24, 3, sim2_sel, ARRAY_SIZE(sim2_sel)); + clks[IMX7D_GPT1_ROOT_SRC] = imx_clk_mux2("gpt1_src", base + 0xb900, 24, 3, gpt1_sel, ARRAY_SIZE(gpt1_sel)); + clks[IMX7D_GPT2_ROOT_SRC] = imx_clk_mux2("gpt2_src", base + 0xb980, 24, 3, gpt2_sel, ARRAY_SIZE(gpt2_sel)); + clks[IMX7D_GPT3_ROOT_SRC] = imx_clk_mux2("gpt3_src", base + 0xba00, 24, 3, gpt3_sel, ARRAY_SIZE(gpt3_sel)); + clks[IMX7D_GPT4_ROOT_SRC] = imx_clk_mux2("gpt4_src", base + 0xba80, 24, 3, gpt4_sel, ARRAY_SIZE(gpt4_sel)); + clks[IMX7D_TRACE_ROOT_SRC] = imx_clk_mux2("trace_src", base + 0xbb00, 24, 3, trace_sel, ARRAY_SIZE(trace_sel)); + clks[IMX7D_WDOG_ROOT_SRC] = imx_clk_mux2("wdog_src", base + 0xbb80, 24, 3, wdog_sel, ARRAY_SIZE(wdog_sel)); + clks[IMX7D_CSI_MCLK_ROOT_SRC] = imx_clk_mux2("csi_mclk_src", base + 0xbc00, 24, 3, csi_mclk_sel, ARRAY_SIZE(csi_mclk_sel)); + clks[IMX7D_AUDIO_MCLK_ROOT_SRC] = imx_clk_mux2("audio_mclk_src", base + 0xbc80, 24, 3, audio_mclk_sel, ARRAY_SIZE(audio_mclk_sel)); + clks[IMX7D_WRCLK_ROOT_SRC] = imx_clk_mux2("wrclk_src", base + 0xbd00, 24, 3, wrclk_sel, ARRAY_SIZE(wrclk_sel)); + clks[IMX7D_CLKO1_ROOT_SRC] = imx_clk_mux2("clko1_src", base + 0xbd80, 24, 3, clko1_sel, ARRAY_SIZE(clko1_sel)); + clks[IMX7D_CLKO2_ROOT_SRC] = imx_clk_mux2("clko2_src", base + 0xbe00, 24, 3, clko2_sel, ARRAY_SIZE(clko2_sel)); + + clks[IMX7D_ARM_A7_ROOT_CG] = imx_clk_gate3("arm_a7_cg", "arm_a7_src", base + 0x8000, 28); + clks[IMX7D_ARM_M4_ROOT_CG] = imx_clk_gate3("arm_m4_cg", "arm_m4_src", base + 0x8080, 28); + clks[IMX7D_ARM_M0_ROOT_CG] = imx_clk_gate3("arm_m0_cg", "arm_m0_src", base + 0x8100, 28); + clks[IMX7D_MAIN_AXI_ROOT_CG] = imx_clk_gate3("axi_cg", "axi_src", base + 0x8800, 28); + clks[IMX7D_DISP_AXI_ROOT_CG] = imx_clk_gate3("disp_axi_cg", "disp_axi_src", base + 0x8880, 28); + clks[IMX7D_ENET_AXI_ROOT_CG] = imx_clk_gate3("enet_axi_cg", "enet_axi_src", base + 0x8900, 28); + clks[IMX7D_NAND_USDHC_BUS_ROOT_CG] = imx_clk_gate3("nand_usdhc_cg", "nand_usdhc_src", base + 0x8980, 28); + clks[IMX7D_AHB_CHANNEL_ROOT_CG] = imx_clk_gate3("ahb_cg", "ahb_src", base + 0x9000, 28); + clks[IMX7D_DRAM_PHYM_ROOT_CG] = imx_clk_gate3("dram_phym_cg", "dram_phym_src", base + 0x9800, 28); + clks[IMX7D_DRAM_ROOT_CG] = imx_clk_gate3("dram_cg", "dram_src", base + 0x9880, 28); + clks[IMX7D_DRAM_PHYM_ALT_ROOT_CG] = imx_clk_gate3("dram_phym_alt_cg", "dram_phym_alt_src", base + 0xa000, 28); + clks[IMX7D_DRAM_ALT_ROOT_CG] = imx_clk_gate3("dram_alt_cg", "dram_alt_src", base + 0xa080, 28); + clks[IMX7D_USB_HSIC_ROOT_CG] = imx_clk_gate3("usb_hsic_cg", "usb_hsic_src", base + 0xa100, 28); + clks[IMX7D_PCIE_CTRL_ROOT_CG] = imx_clk_gate3("pcie_ctrl_cg", "pcie_ctrl_src", base + 0xa180, 28); + clks[IMX7D_PCIE_PHY_ROOT_CG] = imx_clk_gate3("pcie_phy_cg", "pcie_phy_src", base + 0xa200, 28); + clks[IMX7D_EPDC_PIXEL_ROOT_CG] = imx_clk_gate3("epdc_pixel_cg", "epdc_pixel_src", base + 0xa280, 28); + clks[IMX7D_LCDIF_PIXEL_ROOT_CG] = imx_clk_gate3("lcdif_pixel_cg", "lcdif_pixel_src", base + 0xa300, 28); + clks[IMX7D_MIPI_DSI_ROOT_CG] = imx_clk_gate3("mipi_dsi_cg", "mipi_dsi_src", base + 0xa380, 28); + clks[IMX7D_MIPI_CSI_ROOT_CG] = imx_clk_gate3("mipi_csi_cg", "mipi_csi_src", base + 0xa400, 28); + clks[IMX7D_MIPI_DPHY_ROOT_CG] = imx_clk_gate3("mipi_dphy_cg", "mipi_dphy_src", base + 0xa480, 28); + clks[IMX7D_SAI1_ROOT_CG] = imx_clk_gate3("sai1_cg", "sai1_src", base + 0xa500, 28); + clks[IMX7D_SAI2_ROOT_CG] = imx_clk_gate3("sai2_cg", "sai2_src", base + 0xa580, 28); + clks[IMX7D_SAI3_ROOT_CG] = imx_clk_gate3("sai3_cg", "sai3_src", base + 0xa600, 28); + clks[IMX7D_SPDIF_ROOT_CG] = imx_clk_gate3("spdif_cg", "spdif_src", base + 0xa680, 28); + clks[IMX7D_ENET1_REF_ROOT_CG] = imx_clk_gate3("enet1_ref_cg", "enet1_ref_src", base + 0xa700, 28); + clks[IMX7D_ENET1_TIME_ROOT_CG] = imx_clk_gate3("enet1_time_cg", "enet1_time_src", base + 0xa780, 28); + clks[IMX7D_ENET2_REF_ROOT_CG] = imx_clk_gate3("enet2_ref_cg", "enet2_ref_src", base + 0xa800, 28); + clks[IMX7D_ENET2_TIME_ROOT_CG] = imx_clk_gate3("enet2_time_cg", "enet2_time_src", base + 0xa880, 28); + clks[IMX7D_ENET_PHY_REF_ROOT_CG] = imx_clk_gate3("enet_phy_ref_cg", "enet_phy_ref_src", base + 0xa900, 28); + clks[IMX7D_EIM_ROOT_CG] = imx_clk_gate3("eim_cg", "eim_src", base + 0xa980, 28); + clks[IMX7D_NAND_ROOT_CG] = imx_clk_gate3("nand_cg", "nand_src", base + 0xaa00, 28); + clks[IMX7D_QSPI_ROOT_CG] = imx_clk_gate3("qspi_cg", "qspi_src", base + 0xaa80, 28); + clks[IMX7D_USDHC1_ROOT_CG] = imx_clk_gate3("usdhc1_cg", "usdhc1_src", base + 0xab00, 28); + clks[IMX7D_USDHC2_ROOT_CG] = imx_clk_gate3("usdhc2_cg", "usdhc2_src", base + 0xab80, 28); + clks[IMX7D_USDHC3_ROOT_CG] = imx_clk_gate3("usdhc3_cg", "usdhc3_src", base + 0xac00, 28); + clks[IMX7D_CAN1_ROOT_CG] = imx_clk_gate3("can1_cg", "can1_src", base + 0xac80, 28); + clks[IMX7D_CAN2_ROOT_CG] = imx_clk_gate3("can2_cg", "can2_src", base + 0xad00, 28); + clks[IMX7D_I2C1_ROOT_CG] = imx_clk_gate3("i2c1_cg", "i2c1_src", base + 0xad80, 28); + clks[IMX7D_I2C2_ROOT_CG] = imx_clk_gate3("i2c2_cg", "i2c2_src", base + 0xae00, 28); + clks[IMX7D_I2C3_ROOT_CG] = imx_clk_gate3("i2c3_cg", "i2c3_src", base + 0xae80, 28); + clks[IMX7D_I2C4_ROOT_CG] = imx_clk_gate3("i2c4_cg", "i2c4_src", base + 0xaf00, 28); + clks[IMX7D_UART1_ROOT_CG] = imx_clk_gate3("uart1_cg", "uart1_src", base + 0xaf80, 28); + clks[IMX7D_UART2_ROOT_CG] = imx_clk_gate3("uart2_cg", "uart2_src", base + 0xb000, 28); + clks[IMX7D_UART3_ROOT_CG] = imx_clk_gate3("uart3_cg", "uart3_src", base + 0xb080, 28); + clks[IMX7D_UART4_ROOT_CG] = imx_clk_gate3("uart4_cg", "uart4_src", base + 0xb100, 28); + clks[IMX7D_UART5_ROOT_CG] = imx_clk_gate3("uart5_cg", "uart5_src", base + 0xb180, 28); + clks[IMX7D_UART6_ROOT_CG] = imx_clk_gate3("uart6_cg", "uart6_src", base + 0xb200, 28); + clks[IMX7D_UART7_ROOT_CG] = imx_clk_gate3("uart7_cg", "uart7_src", base + 0xb280, 28); + clks[IMX7D_ECSPI1_ROOT_CG] = imx_clk_gate3("ecspi1_cg", "ecspi1_src", base + 0xb300, 28); + clks[IMX7D_ECSPI2_ROOT_CG] = imx_clk_gate3("ecspi2_cg", "ecspi2_src", base + 0xb380, 28); + clks[IMX7D_ECSPI3_ROOT_CG] = imx_clk_gate3("ecspi3_cg", "ecspi3_src", base + 0xb400, 28); + clks[IMX7D_ECSPI4_ROOT_CG] = imx_clk_gate3("ecspi4_cg", "ecspi4_src", base + 0xb480, 28); + clks[IMX7D_PWM1_ROOT_CG] = imx_clk_gate3("pwm1_cg", "pwm1_src", base + 0xb500, 28); + clks[IMX7D_PWM2_ROOT_CG] = imx_clk_gate3("pwm2_cg", "pwm2_src", base + 0xb580, 28); + clks[IMX7D_PWM3_ROOT_CG] = imx_clk_gate3("pwm3_cg", "pwm3_src", base + 0xb600, 28); + clks[IMX7D_PWM4_ROOT_CG] = imx_clk_gate3("pwm4_cg", "pwm4_src", base + 0xb680, 28); + clks[IMX7D_FLEXTIMER1_ROOT_CG] = imx_clk_gate3("flextimer1_cg", "flextimer1_src", base + 0xb700, 28); + clks[IMX7D_FLEXTIMER2_ROOT_CG] = imx_clk_gate3("flextimer2_cg", "flextimer2_src", base + 0xb780, 28); + clks[IMX7D_SIM1_ROOT_CG] = imx_clk_gate3("sim1_cg", "sim1_src", base + 0xb800, 28); + clks[IMX7D_SIM2_ROOT_CG] = imx_clk_gate3("sim2_cg", "sim2_src", base + 0xb880, 28); + clks[IMX7D_GPT1_ROOT_CG] = imx_clk_gate3("gpt1_cg", "gpt1_src", base + 0xb900, 28); + clks[IMX7D_GPT2_ROOT_CG] = imx_clk_gate3("gpt2_cg", "gpt2_src", base + 0xb980, 28); + clks[IMX7D_GPT3_ROOT_CG] = imx_clk_gate3("gpt3_cg", "gpt3_src", base + 0xbA00, 28); + clks[IMX7D_GPT4_ROOT_CG] = imx_clk_gate3("gpt4_cg", "gpt4_src", base + 0xbA80, 28); + clks[IMX7D_TRACE_ROOT_CG] = imx_clk_gate3("trace_cg", "trace_src", base + 0xbb00, 28); + clks[IMX7D_WDOG_ROOT_CG] = imx_clk_gate3("wdog_cg", "wdog_src", base + 0xbb80, 28); + clks[IMX7D_CSI_MCLK_ROOT_CG] = imx_clk_gate3("csi_mclk_cg", "csi_mclk_src", base + 0xbc00, 28); + clks[IMX7D_AUDIO_MCLK_ROOT_CG] = imx_clk_gate3("audio_mclk_cg", "audio_mclk_src", base + 0xbc80, 28); + clks[IMX7D_WRCLK_ROOT_CG] = imx_clk_gate3("wrclk_cg", "wrclk_src", base + 0xbd00, 28); + clks[IMX7D_CLKO1_ROOT_CG] = imx_clk_gate3("clko1_cg", "clko1_src", base + 0xbd80, 28); + clks[IMX7D_CLKO2_ROOT_CG] = imx_clk_gate3("clko2_cg", "clko2_src", base + 0xbe00, 28); + + clks[IMX7D_MAIN_AXI_ROOT_PRE_DIV] = imx_clk_divider2("axi_pre_div", "axi_cg", base + 0x8800, 16, 3); + clks[IMX7D_DISP_AXI_ROOT_PRE_DIV] = imx_clk_divider2("disp_axi_pre_div", "disp_axi_cg", base + 0x8880, 16, 3); + clks[IMX7D_ENET_AXI_ROOT_PRE_DIV] = imx_clk_divider2("enet_axi_pre_div", "enet_axi_cg", base + 0x8900, 16, 3); + clks[IMX7D_NAND_USDHC_BUS_ROOT_PRE_DIV] = imx_clk_divider2("nand_usdhc_pre_div", "nand_usdhc_cg", base + 0x8980, 16, 3); + clks[IMX7D_AHB_CHANNEL_ROOT_PRE_DIV] = imx_clk_divider2("ahb_pre_div", "ahb_cg", base + 0x9000, 16, 3); + clks[IMX7D_DRAM_PHYM_ALT_ROOT_PRE_DIV] = imx_clk_divider2("dram_phym_alt_pre_div", "dram_phym_alt_cg", base + 0xa000, 16, 3); + clks[IMX7D_DRAM_ALT_ROOT_PRE_DIV] = imx_clk_divider2("dram_alt_pre_div", "dram_alt_cg", base + 0xa080, 16, 3); + clks[IMX7D_USB_HSIC_ROOT_PRE_DIV] = imx_clk_divider2("usb_hsic_pre_div", "usb_hsic_cg", base + 0xa100, 16, 3); + clks[IMX7D_PCIE_CTRL_ROOT_PRE_DIV] = imx_clk_divider2("pcie_ctrl_pre_div", "pcie_ctrl_cg", base + 0xa180, 16, 3); + clks[IMX7D_PCIE_PHY_ROOT_PRE_DIV] = imx_clk_divider2("pcie_phy_pre_div", "pcie_phy_cg", base + 0xa200, 16, 3); + clks[IMX7D_EPDC_PIXEL_ROOT_PRE_DIV] = imx_clk_divider2("epdc_pixel_pre_div", "epdc_pixel_cg", base + 0xa280, 16, 3); + clks[IMX7D_LCDIF_PIXEL_ROOT_PRE_DIV] = imx_clk_divider2("lcdif_pixel_pre_div", "lcdif_pixel_cg", base + 0xa300, 16, 3); + clks[IMX7D_MIPI_DSI_ROOT_PRE_DIV] = imx_clk_divider2("mipi_dsi_pre_div", "mipi_dsi_cg", base + 0xa380, 16, 3); + clks[IMX7D_MIPI_CSI_ROOT_PRE_DIV] = imx_clk_divider2("mipi_csi_pre_div", "mipi_csi_cg", base + 0xa400, 16, 3); + clks[IMX7D_MIPI_DPHY_ROOT_PRE_DIV] = imx_clk_divider2("mipi_dphy_pre_div", "mipi_dphy_cg", base + 0xa480, 16, 3); + clks[IMX7D_SAI1_ROOT_PRE_DIV] = imx_clk_divider2("sai1_pre_div", "sai1_cg", base + 0xa500, 16, 3); + clks[IMX7D_SAI2_ROOT_PRE_DIV] = imx_clk_divider2("sai2_pre_div", "sai2_cg", base + 0xa580, 16, 3); + clks[IMX7D_SAI3_ROOT_PRE_DIV] = imx_clk_divider2("sai3_pre_div", "sai3_cg", base + 0xa600, 16, 3); + clks[IMX7D_SPDIF_ROOT_PRE_DIV] = imx_clk_divider2("spdif_pre_div", "spdif_cg", base + 0xa680, 16, 3); + clks[IMX7D_ENET1_REF_ROOT_PRE_DIV] = imx_clk_divider2("enet1_ref_pre_div", "enet1_ref_cg", base + 0xa700, 16, 3); + clks[IMX7D_ENET1_TIME_ROOT_PRE_DIV] = imx_clk_divider2("enet1_time_pre_div", "enet1_time_cg", base + 0xa780, 16, 3); + clks[IMX7D_ENET2_REF_ROOT_PRE_DIV] = imx_clk_divider2("enet2_ref_pre_div", "enet2_ref_cg", base + 0xa800, 16, 3); + clks[IMX7D_ENET2_TIME_ROOT_PRE_DIV] = imx_clk_divider2("enet2_time_pre_div", "enet2_time_cg", base + 0xa880, 16, 3); + clks[IMX7D_ENET_PHY_REF_ROOT_PRE_DIV] = imx_clk_divider2("enet_phy_ref_pre_div", "enet_phy_ref_cg", base + 0xa900, 16, 3); + clks[IMX7D_EIM_ROOT_PRE_DIV] = imx_clk_divider2("eim_pre_div", "eim_cg", base + 0xa980, 16, 3); + clks[IMX7D_NAND_ROOT_PRE_DIV] = imx_clk_divider2("nand_pre_div", "nand_cg", base + 0xaa00, 16, 3); + clks[IMX7D_QSPI_ROOT_PRE_DIV] = imx_clk_divider2("qspi_pre_div", "qspi_cg", base + 0xaa80, 16, 3); + clks[IMX7D_USDHC1_ROOT_PRE_DIV] = imx_clk_divider2("usdhc1_pre_div", "usdhc1_cg", base + 0xab00, 16, 3); + clks[IMX7D_USDHC2_ROOT_PRE_DIV] = imx_clk_divider2("usdhc2_pre_div", "usdhc2_cg", base + 0xab80, 16, 3); + clks[IMX7D_USDHC3_ROOT_PRE_DIV] = imx_clk_divider2("usdhc3_pre_div", "usdhc3_cg", base + 0xac00, 16, 3); + clks[IMX7D_CAN1_ROOT_PRE_DIV] = imx_clk_divider2("can1_pre_div", "can1_cg", base + 0xac80, 16, 3); + clks[IMX7D_CAN2_ROOT_PRE_DIV] = imx_clk_divider2("can2_pre_div", "can2_cg", base + 0xad00, 16, 3); + clks[IMX7D_I2C1_ROOT_PRE_DIV] = imx_clk_divider2("i2c1_pre_div", "i2c1_cg", base + 0xad80, 16, 3); + clks[IMX7D_I2C2_ROOT_PRE_DIV] = imx_clk_divider2("i2c2_pre_div", "i2c2_cg", base + 0xae00, 16, 3); + clks[IMX7D_I2C3_ROOT_PRE_DIV] = imx_clk_divider2("i2c3_pre_div", "i2c3_cg", base + 0xae80, 16, 3); + clks[IMX7D_I2C4_ROOT_PRE_DIV] = imx_clk_divider2("i2c4_pre_div", "i2c4_cg", base + 0xaf00, 16, 3); + clks[IMX7D_UART1_ROOT_PRE_DIV] = imx_clk_divider2("uart1_pre_div", "uart1_cg", base + 0xaf80, 16, 3); + clks[IMX7D_UART2_ROOT_PRE_DIV] = imx_clk_divider2("uart2_pre_div", "uart2_cg", base + 0xb000, 16, 3); + clks[IMX7D_UART3_ROOT_PRE_DIV] = imx_clk_divider2("uart3_pre_div", "uart3_cg", base + 0xb080, 16, 3); + clks[IMX7D_UART4_ROOT_PRE_DIV] = imx_clk_divider2("uart4_pre_div", "uart4_cg", base + 0xb100, 16, 3); + clks[IMX7D_UART5_ROOT_PRE_DIV] = imx_clk_divider2("uart5_pre_div", "uart5_cg", base + 0xb180, 16, 3); + clks[IMX7D_UART6_ROOT_PRE_DIV] = imx_clk_divider2("uart6_pre_div", "uart6_cg", base + 0xb200, 16, 3); + clks[IMX7D_UART7_ROOT_PRE_DIV] = imx_clk_divider2("uart7_pre_div", "uart7_cg", base + 0xb280, 16, 3); + clks[IMX7D_ECSPI1_ROOT_PRE_DIV] = imx_clk_divider2("ecspi1_pre_div", "ecspi1_cg", base + 0xb300, 16, 3); + clks[IMX7D_ECSPI2_ROOT_PRE_DIV] = imx_clk_divider2("ecspi2_pre_div", "ecspi2_cg", base + 0xb380, 16, 3); + clks[IMX7D_ECSPI3_ROOT_PRE_DIV] = imx_clk_divider2("ecspi3_pre_div", "ecspi3_cg", base + 0xb400, 16, 3); + clks[IMX7D_ECSPI4_ROOT_PRE_DIV] = imx_clk_divider2("ecspi4_pre_div", "ecspi4_cg", base + 0xb480, 16, 3); + clks[IMX7D_PWM1_ROOT_PRE_DIV] = imx_clk_divider2("pwm1_pre_div", "pwm1_cg", base + 0xb500, 16, 3); + clks[IMX7D_PWM2_ROOT_PRE_DIV] = imx_clk_divider2("pwm2_pre_div", "pwm2_cg", base + 0xb580, 16, 3); + clks[IMX7D_PWM3_ROOT_PRE_DIV] = imx_clk_divider2("pwm3_pre_div", "pwm3_cg", base + 0xb600, 16, 3); + clks[IMX7D_PWM4_ROOT_PRE_DIV] = imx_clk_divider2("pwm4_pre_div", "pwm4_cg", base + 0xb680, 16, 3); + clks[IMX7D_FLEXTIMER1_ROOT_PRE_DIV] = imx_clk_divider2("flextimer1_pre_div", "flextimer1_cg", base + 0xb700, 16, 3); + clks[IMX7D_FLEXTIMER2_ROOT_PRE_DIV] = imx_clk_divider2("flextimer2_pre_div", "flextimer2_cg", base + 0xb780, 16, 3); + clks[IMX7D_SIM1_ROOT_PRE_DIV] = imx_clk_divider2("sim1_pre_div", "sim1_cg", base + 0xb800, 16, 3); + clks[IMX7D_SIM2_ROOT_PRE_DIV] = imx_clk_divider2("sim2_pre_div", "sim2_cg", base + 0xb880, 16, 3); + clks[IMX7D_GPT1_ROOT_PRE_DIV] = imx_clk_divider2("gpt1_pre_div", "gpt1_cg", base + 0xb900, 16, 3); + clks[IMX7D_GPT2_ROOT_PRE_DIV] = imx_clk_divider2("gpt2_pre_div", "gpt2_cg", base + 0xb980, 16, 3); + clks[IMX7D_GPT3_ROOT_PRE_DIV] = imx_clk_divider2("gpt3_pre_div", "gpt3_cg", base + 0xba00, 16, 3); + clks[IMX7D_GPT4_ROOT_PRE_DIV] = imx_clk_divider2("gpt4_pre_div", "gpt4_cg", base + 0xba80, 16, 3); + clks[IMX7D_TRACE_ROOT_PRE_DIV] = imx_clk_divider2("trace_pre_div", "trace_cg", base + 0xbb00, 16, 3); + clks[IMX7D_WDOG_ROOT_PRE_DIV] = imx_clk_divider2("wdog_pre_div", "wdog_cg", base + 0xbb80, 16, 3); + clks[IMX7D_CSI_MCLK_ROOT_PRE_DIV] = imx_clk_divider2("csi_mclk_pre_div", "csi_mclk_cg", base + 0xbc00, 16, 3); + clks[IMX7D_AUDIO_MCLK_ROOT_PRE_DIV] = imx_clk_divider2("audio_mclk_pre_div", "audio_mclk_cg", base + 0xbc80, 16, 3); + clks[IMX7D_WRCLK_ROOT_PRE_DIV] = imx_clk_divider2("wrclk_pre_div", "wrclk_cg", base + 0xbd00, 16, 3); + clks[IMX7D_CLKO1_ROOT_PRE_DIV] = imx_clk_divider2("clko1_pre_div", "clko1_cg", base + 0xbd80, 16, 3); + clks[IMX7D_CLKO2_ROOT_PRE_DIV] = imx_clk_divider2("clko2_pre_div", "clko2_cg", base + 0xbe00, 16, 3); + + clks[IMX7D_ARM_A7_ROOT_DIV] = imx_clk_divider2("arm_a7_div", "arm_a7_cg", base + 0x8000, 0, 3); + clks[IMX7D_ARM_M4_ROOT_DIV] = imx_clk_divider2("arm_m4_div", "arm_m4_cg", base + 0x8080, 0, 3); + clks[IMX7D_ARM_M0_ROOT_DIV] = imx_clk_divider2("arm_m0_div", "arm_m0_cg", base + 0x8100, 0, 3); + clks[IMX7D_MAIN_AXI_ROOT_DIV] = imx_clk_divider2("axi_post_div", "axi_pre_div", base + 0x8800, 0, 6); + clks[IMX7D_DISP_AXI_ROOT_DIV] = imx_clk_divider2("disp_axi_post_div", "disp_axi_pre_div", base + 0x8880, 0, 6); + clks[IMX7D_ENET_AXI_ROOT_DIV] = imx_clk_divider2("enet_axi_post_div", "enet_axi_pre_div", base + 0x8900, 0, 6); + clks[IMX7D_NAND_USDHC_BUS_ROOT_DIV] = imx_clk_divider2("nand_usdhc_post_div", "nand_usdhc_pre_div", base + 0x8980, 0, 6); + clks[IMX7D_AHB_CHANNEL_ROOT_DIV] = imx_clk_divider2("ahb_post_div", "ahb_pre_div", base + 0x9000, 0, 6); + clks[IMX7D_DRAM_ROOT_DIV] = imx_clk_divider2("dram_post_div", "dram_cg", base + 0x9880, 0, 3); + clks[IMX7D_DRAM_PHYM_ALT_ROOT_DIV] = imx_clk_divider2("dram_phym_alt_post_div", "dram_phym_alt_pre_div", base + 0xa000, 0, 3); + clks[IMX7D_DRAM_ALT_ROOT_DIV] = imx_clk_divider2("dram_alt_post_div", "dram_alt_pre_div", base + 0xa080, 0, 3); + clks[IMX7D_USB_HSIC_ROOT_DIV] = imx_clk_divider2("usb_hsic_post_div", "usb_hsic_pre_div", base + 0xa100, 0, 6); + clks[IMX7D_PCIE_CTRL_ROOT_DIV] = imx_clk_divider2("pcie_ctrl_post_div", "pcie_ctrl_pre_div", base + 0xa180, 0, 6); + clks[IMX7D_PCIE_PHY_ROOT_DIV] = imx_clk_divider2("pcie_phy_post_div", "pcie_phy_pre_div", base + 0xa200, 0, 6); + clks[IMX7D_EPDC_PIXEL_ROOT_DIV] = imx_clk_divider2("epdc_pixel_post_div", "epdc_pixel_pre_div", base + 0xa280, 0, 6); + clks[IMX7D_LCDIF_PIXEL_ROOT_DIV] = imx_clk_divider2("lcdif_pixel_post_div", "lcdif_pixel_pre_div", base + 0xa300, 0, 6); + clks[IMX7D_MIPI_DSI_ROOT_DIV] = imx_clk_divider2("mipi_dsi_post_div", "mipi_dsi_pre_div", base + 0xa380, 0, 6); + clks[IMX7D_MIPI_CSI_ROOT_DIV] = imx_clk_divider2("mipi_csi_post_div", "mipi_csi_pre_div", base + 0xa400, 0, 6); + clks[IMX7D_MIPI_DPHY_ROOT_DIV] = imx_clk_divider2("mipi_dphy_post_div", "mipi_csi_dphy_div", base + 0xa480, 0, 6); + clks[IMX7D_SAI1_ROOT_DIV] = imx_clk_divider2("sai1_post_div", "sai1_pre_div", base + 0xa500, 0, 6); + clks[IMX7D_SAI2_ROOT_DIV] = imx_clk_divider2("sai2_post_div", "sai2_pre_div", base + 0xa580, 0, 6); + clks[IMX7D_SAI3_ROOT_DIV] = imx_clk_divider2("sai3_post_div", "sai3_pre_div", base + 0xa600, 0, 6); + clks[IMX7D_SPDIF_ROOT_DIV] = imx_clk_divider2("spdif_post_div", "spdif_pre_div", base + 0xa680, 0, 6); + clks[IMX7D_ENET1_REF_ROOT_DIV] = imx_clk_divider2("enet1_ref_post_div", "enet1_ref_pre_div", base + 0xa700, 0, 6); + clks[IMX7D_ENET1_TIME_ROOT_DIV] = imx_clk_divider2("enet1_time_post_div", "enet1_time_pre_div", base + 0xa780, 0, 6); + clks[IMX7D_ENET2_REF_ROOT_DIV] = imx_clk_divider2("enet2_ref_post_div", "enet2_ref_pre_div", base + 0xa800, 0, 6); + clks[IMX7D_ENET2_TIME_ROOT_DIV] = imx_clk_divider2("enet2_time_post_div", "enet2_time_pre_div", base + 0xa880, 0, 6); + clks[IMX7D_ENET_PHY_REF_ROOT_DIV] = imx_clk_divider2("enet_phy_ref_post_div", "enet_phy_ref_pre_div", base + 0xa900, 0, 6); + clks[IMX7D_EIM_ROOT_DIV] = imx_clk_divider2("eim_post_div", "eim_pre_div", base + 0xa980, 0, 6); + clks[IMX7D_NAND_ROOT_DIV] = imx_clk_divider2("nand_post_div", "nand_pre_div", base + 0xaa00, 0, 6); + clks[IMX7D_QSPI_ROOT_DIV] = imx_clk_divider2("qspi_post_div", "qspi_pre_div", base + 0xaa80, 0, 6); + clks[IMX7D_USDHC1_ROOT_DIV] = imx_clk_divider2("usdhc1_post_div", "usdhc1_pre_div", base + 0xab00, 0, 6); + clks[IMX7D_USDHC2_ROOT_DIV] = imx_clk_divider2("usdhc2_post_div", "usdhc2_pre_div", base + 0xab80, 0, 6); + clks[IMX7D_USDHC3_ROOT_DIV] = imx_clk_divider2("usdhc3_post_div", "usdhc3_pre_div", base + 0xac00, 0, 6); + clks[IMX7D_CAN1_ROOT_DIV] = imx_clk_divider2("can1_post_div", "can1_pre_div", base + 0xac80, 0, 6); + clks[IMX7D_CAN2_ROOT_DIV] = imx_clk_divider2("can2_post_div", "can2_pre_div", base + 0xad00, 0, 6); + clks[IMX7D_I2C1_ROOT_DIV] = imx_clk_divider2("i2c1_post_div", "i2c1_pre_div", base + 0xad80, 0, 6); + clks[IMX7D_I2C2_ROOT_DIV] = imx_clk_divider2("i2c2_post_div", "i2c2_pre_div", base + 0xae00, 0, 6); + clks[IMX7D_I2C3_ROOT_DIV] = imx_clk_divider2("i2c3_post_div", "i2c3_pre_div", base + 0xae80, 0, 6); + clks[IMX7D_I2C4_ROOT_DIV] = imx_clk_divider2("i2c4_post_div", "i2c4_pre_div", base + 0xaf00, 0, 6); + clks[IMX7D_UART1_ROOT_DIV] = imx_clk_divider2("uart1_post_div", "uart1_pre_div", base + 0xaf80, 0, 6); + clks[IMX7D_UART2_ROOT_DIV] = imx_clk_divider2("uart2_post_div", "uart2_pre_div", base + 0xb000, 0, 6); + clks[IMX7D_UART3_ROOT_DIV] = imx_clk_divider2("uart3_post_div", "uart3_pre_div", base + 0xb080, 0, 6); + clks[IMX7D_UART4_ROOT_DIV] = imx_clk_divider2("uart4_post_div", "uart4_pre_div", base + 0xb100, 0, 6); + clks[IMX7D_UART5_ROOT_DIV] = imx_clk_divider2("uart5_post_div", "uart5_pre_div", base + 0xb180, 0, 6); + clks[IMX7D_UART6_ROOT_DIV] = imx_clk_divider2("uart6_post_div", "uart6_pre_div", base + 0xb200, 0, 6); + clks[IMX7D_UART7_ROOT_DIV] = imx_clk_divider2("uart7_post_div", "uart7_pre_div", base + 0xb280, 0, 6); + clks[IMX7D_ECSPI1_ROOT_DIV] = imx_clk_divider2("ecspi1_post_div", "ecspi1_pre_div", base + 0xb300, 0, 6); + clks[IMX7D_ECSPI2_ROOT_DIV] = imx_clk_divider2("ecspi2_post_div", "ecspi2_pre_div", base + 0xb380, 0, 6); + clks[IMX7D_ECSPI3_ROOT_DIV] = imx_clk_divider2("ecspi3_post_div", "ecspi3_pre_div", base + 0xb400, 0, 6); + clks[IMX7D_ECSPI4_ROOT_DIV] = imx_clk_divider2("ecspi4_post_div", "ecspi4_pre_div", base + 0xb480, 0, 6); + clks[IMX7D_PWM1_ROOT_DIV] = imx_clk_divider2("pwm1_post_div", "pwm1_pre_div", base + 0xb500, 0, 6); + clks[IMX7D_PWM2_ROOT_DIV] = imx_clk_divider2("pwm2_post_div", "pwm2_pre_div", base + 0xb580, 0, 6); + clks[IMX7D_PWM3_ROOT_DIV] = imx_clk_divider2("pwm3_post_div", "pwm3_pre_div", base + 0xb600, 0, 6); + clks[IMX7D_PWM4_ROOT_DIV] = imx_clk_divider2("pwm4_post_div", "pwm4_pre_div", base + 0xb680, 0, 6); + clks[IMX7D_FLEXTIMER1_ROOT_DIV] = imx_clk_divider2("flextimer1_post_div", "flextimer1_pre_div", base + 0xb700, 0, 6); + clks[IMX7D_FLEXTIMER2_ROOT_DIV] = imx_clk_divider2("flextimer2_post_div", "flextimer2_pre_div", base + 0xb780, 0, 6); + clks[IMX7D_SIM1_ROOT_DIV] = imx_clk_divider2("sim1_post_div", "sim1_pre_div", base + 0xb800, 0, 6); + clks[IMX7D_SIM2_ROOT_DIV] = imx_clk_divider2("sim2_post_div", "sim2_pre_div", base + 0xb880, 0, 6); + clks[IMX7D_GPT1_ROOT_DIV] = imx_clk_divider2("gpt1_post_div", "gpt1_pre_div", base + 0xb900, 0, 6); + clks[IMX7D_GPT2_ROOT_DIV] = imx_clk_divider2("gpt2_post_div", "gpt2_pre_div", base + 0xb980, 0, 6); + clks[IMX7D_GPT3_ROOT_DIV] = imx_clk_divider2("gpt3_post_div", "gpt3_pre_div", base + 0xba00, 0, 6); + clks[IMX7D_GPT4_ROOT_DIV] = imx_clk_divider2("gpt4_post_div", "gpt4_pre_div", base + 0xba80, 0, 6); + clks[IMX7D_TRACE_ROOT_DIV] = imx_clk_divider2("trace_post_div", "trace_pre_div", base + 0xbb00, 0, 6); + clks[IMX7D_WDOG_ROOT_DIV] = imx_clk_divider2("wdog_post_div", "wdog_pre_div", base + 0xbb80, 0, 6); + clks[IMX7D_CSI_MCLK_ROOT_DIV] = imx_clk_divider2("csi_mclk_post_div", "csi_mclk_pre_div", base + 0xbc00, 0, 6); + clks[IMX7D_AUDIO_MCLK_ROOT_DIV] = imx_clk_divider2("audio_mclk_post_div", "audio_mclk_pre_div", base + 0xbc80, 0, 6); + clks[IMX7D_WRCLK_ROOT_DIV] = imx_clk_divider2("wrclk_post_div", "wrclk_pre_div", base + 0xbd00, 0, 6); + clks[IMX7D_CLKO1_ROOT_DIV] = imx_clk_divider2("clko1_post_div", "clko1_pre_div", base + 0xbd80, 0, 6); + clks[IMX7D_CLKO2_ROOT_DIV] = imx_clk_divider2("clko2_post_div", "clko2_pre_div", base + 0xbe00, 0, 6); + + clks[IMX7D_ARM_A7_ROOT_CLK] = imx_clk_gate4("arm_a7_root_clk", "arm_a7_div", base + 0x4000, 0); + clks[IMX7D_ARM_M4_ROOT_CLK] = imx_clk_gate4("arm_m4_root_clk", "arm_m4_div", base + 0x4010, 0); + clks[IMX7D_ARM_M0_ROOT_CLK] = imx_clk_gate4("arm_m0_root_clk", "arm_m0_div", base + 0x4020, 0); + clks[IMX7D_MAIN_AXI_ROOT_CLK] = imx_clk_gate4("main_axi_root_clk", "axi_post_div", base + 0x4040, 0); + clks[IMX7D_DISP_AXI_ROOT_CLK] = imx_clk_gate4("disp_axi_root_clk", "disp_axi_post_div", base + 0x4050, 0); + clks[IMX7D_ENET_AXI_ROOT_CLK] = imx_clk_gate4("enet_axi_root_clk", "enet_axi_post_div", base + 0x4060, 0); + clks[IMX7D_OCRAM_CLK] = imx_clk_gate4("ocram_clk", "axi_post_div", base + 0x4110, 0); + clks[IMX7D_OCRAM_S_CLK] = imx_clk_gate4("ocram_s_clk", "ahb_post_div", base + 0x4120, 0); + clks[IMX7D_NAND_USDHC_BUS_ROOT_CLK] = imx_clk_gate4("nand_usdhc_root_clk", "nand_usdhc_post_div", base + 0x4130, 0); + clks[IMX7D_AHB_CHANNEL_ROOT_CLK] = imx_clk_gate4("ahb_root_clk", "ahb_post_div", base + 0x4200, 0); + clks[IMX7D_DRAM_ROOT_CLK] = imx_clk_gate4("dram_root_clk", "dram_post_div", base + 0x4130, 0); + clks[IMX7D_DRAM_PHYM_ROOT_CLK] = imx_clk_gate4("dram_phym_root_clk", "dram_phym_cg", base + 0x4130, 0); + clks[IMX7D_DRAM_PHYM_ALT_ROOT_CLK] = imx_clk_gate4("dram_phym_alt_root_clk", "dram_phym_alt_post_div", base + 0x4130, 0); + clks[IMX7D_DRAM_ALT_ROOT_CLK] = imx_clk_gate4("dram_alt_root_clk", "dram_alt_post_div", base + 0x4130, 0); + clks[IMX7D_USB_HSIC_ROOT_CLK] = imx_clk_gate4("usb_hsic_root_clk", "usb_hsic_post_div", base + 0x4420, 0); + clks[IMX7D_PCIE_CTRL_ROOT_CLK] = imx_clk_gate4("pcie_ctrl_root_clk", "pcie_ctrl_post_div", base + 0x4600, 0); + clks[IMX7D_PCIE_PHY_ROOT_CLK] = imx_clk_gate4("pcie_phy_root_clk", "pcie_phy_post_div", base + 0x4600, 0); + clks[IMX7D_EPDC_PIXEL_ROOT_CLK] = imx_clk_gate4("epdc_pixel_root_clk", "epdc_pixel_post_div", base + 0x44a0, 0); + clks[IMX7D_LCDIF_PIXEL_ROOT_CLK] = imx_clk_gate4("lcdif_pixel_root_clk", "lcdif_pixel_post_div", base + 0x44b0, 0); + clks[IMX7D_MIPI_DSI_ROOT_CLK] = imx_clk_gate4("mipi_dsi_root_clk", "mipi_dsi_post_div", base + 0x4650, 0); + clks[IMX7D_MIPI_CSI_ROOT_CLK] = imx_clk_gate4("mipi_csi_root_clk", "mipi_csi_post_div", base + 0x4640, 0); + clks[IMX7D_MIPI_DPHY_ROOT_CLK] = imx_clk_gate4("mipi_dphy_root_clk", "mipi_dphy_post_div", base + 0x4660, 0); + clks[IMX7D_SAI1_ROOT_CLK] = imx_clk_gate4("sai1_root_clk", "sai1_post_div", base + 0x48c0, 0); + clks[IMX7D_SAI2_ROOT_CLK] = imx_clk_gate4("sai2_root_clk", "sai2_post_div", base + 0x48d0, 0); + clks[IMX7D_SAI3_ROOT_CLK] = imx_clk_gate4("sai3_root_clk", "sai3_post_div", base + 0x48e0, 0); + clks[IMX7D_SPDIF_ROOT_CLK] = imx_clk_gate4("spdif_root_clk", "spdif_post_div", base + 0x44d0, 0); + clks[IMX7D_ENET1_REF_ROOT_CLK] = imx_clk_gate4("enet1_ref_root_clk", "enet1_ref_post_div", base + 0x44e0, 0); + clks[IMX7D_ENET1_TIME_ROOT_CLK] = imx_clk_gate4("enet1_time_root_clk", "enet1_time_post_div", base + 0x44f0, 0); + clks[IMX7D_ENET2_REF_ROOT_CLK] = imx_clk_gate4("enet2_ref_root_clk", "enet2_ref_post_div", base + 0x4500, 0); + clks[IMX7D_ENET2_TIME_ROOT_CLK] = imx_clk_gate4("enet2_time_root_clk", "enet2_time_post_div", base + 0x4510, 0); + clks[IMX7D_ENET_PHY_REF_ROOT_CLK] = imx_clk_gate4("enet_phy_ref_root_clk", "enet_phy_ref_post_div", base + 0x4520, 0); + clks[IMX7D_EIM_ROOT_CLK] = imx_clk_gate4("eim_root_clk", "eim_post_div", base + 0x4160, 0); + clks[IMX7D_NAND_ROOT_CLK] = imx_clk_gate4("nand_root_clk", "nand_post_div", base + 0x4140, 0); + clks[IMX7D_QSPI_ROOT_CLK] = imx_clk_gate4("qspi_root_clk", "qspi_post_div", base + 0x4150, 0); + clks[IMX7D_USDHC1_ROOT_CLK] = imx_clk_gate4("usdhc1_root_clk", "usdhc1_post_div", base + 0x46c0, 0); + clks[IMX7D_USDHC2_ROOT_CLK] = imx_clk_gate4("usdhc2_root_clk", "usdhc2_post_div", base + 0x46d0, 0); + clks[IMX7D_USDHC3_ROOT_CLK] = imx_clk_gate4("usdhc3_root_clk", "usdhc3_post_div", base + 0x46e0, 0); + clks[IMX7D_CAN1_ROOT_CLK] = imx_clk_gate4("can1_root_clk", "can1_post_div", base + 0x4740, 0); + clks[IMX7D_CAN2_ROOT_CLK] = imx_clk_gate4("can2_root_clk", "can2_post_div", base + 0x4750, 0); + clks[IMX7D_I2C1_ROOT_CLK] = imx_clk_gate4("i2c1_root_clk", "i2c1_post_div", base + 0x4880, 0); + clks[IMX7D_I2C2_ROOT_CLK] = imx_clk_gate4("i2c2_root_clk", "i2c2_post_div", base + 0x4890, 0); + clks[IMX7D_I2C3_ROOT_CLK] = imx_clk_gate4("i2c3_root_clk", "i2c3_post_div", base + 0x48a0, 0); + clks[IMX7D_I2C4_ROOT_CLK] = imx_clk_gate4("i2c4_root_clk", "i2c4_post_div", base + 0x48b0, 0); + clks[IMX7D_UART1_ROOT_CLK] = imx_clk_gate4("uart1_root_clk", "uart1_post_div", base + 0x4940, 0); + clks[IMX7D_UART2_ROOT_CLK] = imx_clk_gate4("uart2_root_clk", "uart2_post_div", base + 0x4950, 0); + clks[IMX7D_UART3_ROOT_CLK] = imx_clk_gate4("uart3_root_clk", "uart3_post_div", base + 0x4960, 0); + clks[IMX7D_UART4_ROOT_CLK] = imx_clk_gate4("uart4_root_clk", "uart4_post_div", base + 0x4970, 0); + clks[IMX7D_UART5_ROOT_CLK] = imx_clk_gate4("uart5_root_clk", "uart5_post_div", base + 0x4980, 0); + clks[IMX7D_UART6_ROOT_CLK] = imx_clk_gate4("uart6_root_clk", "uart6_post_div", base + 0x4990, 0); + clks[IMX7D_UART7_ROOT_CLK] = imx_clk_gate4("uart7_root_clk", "uart7_post_div", base + 0x49a0, 0); + clks[IMX7D_ECSPI1_ROOT_CLK] = imx_clk_gate4("ecspi1_root_clk", "ecspi1_post_div", base + 0x4780, 0); + clks[IMX7D_ECSPI2_ROOT_CLK] = imx_clk_gate4("ecspi2_root_clk", "ecspi2_post_div", base + 0x4790, 0); + clks[IMX7D_ECSPI3_ROOT_CLK] = imx_clk_gate4("ecspi3_root_clk", "ecspi3_post_div", base + 0x47a0, 0); + clks[IMX7D_ECSPI4_ROOT_CLK] = imx_clk_gate4("ecspi4_root_clk", "ecspi4_post_div", base + 0x47b0, 0); + clks[IMX7D_PWM1_ROOT_CLK] = imx_clk_gate4("pwm1_root_clk", "pwm1_post_div", base + 0x4840, 0); + clks[IMX7D_PWM2_ROOT_CLK] = imx_clk_gate4("pwm2_root_clk", "pwm2_post_div", base + 0x4850, 0); + clks[IMX7D_PWM3_ROOT_CLK] = imx_clk_gate4("pwm3_root_clk", "pwm3_post_div", base + 0x4860, 0); + clks[IMX7D_PWM4_ROOT_CLK] = imx_clk_gate4("pwm4_root_clk", "pwm4_post_div", base + 0x4870, 0); + clks[IMX7D_FLEXTIMER1_ROOT_CLK] = imx_clk_gate4("flextimer1_root_clk", "flextimer1_post_div", base + 0x4800, 0); + clks[IMX7D_FLEXTIMER2_ROOT_CLK] = imx_clk_gate4("flextimer2_root_clk", "flextimer2_post_div", base + 0x4810, 0); + clks[IMX7D_SIM1_ROOT_CLK] = imx_clk_gate4("sim1_root_clk", "sim1_post_div", base + 0x4900, 0); + clks[IMX7D_SIM2_ROOT_CLK] = imx_clk_gate4("sim2_root_clk", "sim2_post_div", base + 0x4910, 0); + clks[IMX7D_GPT1_ROOT_CLK] = imx_clk_gate4("gpt1_root_clk", "gpt1_post_div", base + 0x47c0, 0); + clks[IMX7D_GPT2_ROOT_CLK] = imx_clk_gate4("gpt2_root_clk", "gpt2_post_div", base + 0x47d0, 0); + clks[IMX7D_GPT3_ROOT_CLK] = imx_clk_gate4("gpt3_root_clk", "gpt3_post_div", base + 0x47e0, 0); + clks[IMX7D_GPT4_ROOT_CLK] = imx_clk_gate4("gpt4_root_clk", "gpt4_post_div", base + 0x47f0, 0); + clks[IMX7D_TRACE_ROOT_CLK] = imx_clk_gate4("trace_root_clk", "trace_post_div", base + 0x4300, 0); + clks[IMX7D_WDOG1_ROOT_CLK] = imx_clk_gate4("wdog1_root_clk", "wdog_post_div", base + 0x49c0, 0); + clks[IMX7D_WDOG2_ROOT_CLK] = imx_clk_gate4("wdog2_root_clk", "wdog_post_div", base + 0x49d0, 0); + clks[IMX7D_WDOG3_ROOT_CLK] = imx_clk_gate4("wdog3_root_clk", "wdog_post_div", base + 0x49e0, 0); + clks[IMX7D_WDOG4_ROOT_CLK] = imx_clk_gate4("wdog4_root_clk", "wdog_post_div", base + 0x49f0, 0); + clks[IMX7D_CSI_MCLK_ROOT_CLK] = imx_clk_gate4("csi_mclk_root_clk", "csi_mclk_post_div", base + 0x4490, 0); + clks[IMX7D_AUDIO_MCLK_ROOT_CLK] = imx_clk_gate4("audio_mclk_root_clk", "audio_mclk_post_div", base + 0x4790, 0); + clks[IMX7D_WRCLK_ROOT_CLK] = imx_clk_gate4("wrclk_root_clk", "wrclk_post_div", base + 0x47a0, 0); + clks[IMX7D_ADC_ROOT_CLK] = imx_clk_gate4("adc_root_clk", "ipg_root_clk", base + 0x4200, 0); clks[IMX7D_GPT_3M_CLK] = imx_clk_fixed_factor("gpt_3m", "osc", 1, 8); -- cgit v1.2.3 From e8e628fb3f47ec7a45f9a026561e88ec8884776c Mon Sep 17 00:00:00 2001 From: Dong Aisheng Date: Thu, 30 Jun 2016 17:31:18 +0800 Subject: clk: imx7d: only enable minimum required clocks Formerly clk core does not support imx7d clock type well that all its clock operations requires the parent clock on. Therefore we enabled all clocks by default in clock driver initialization for other module clocks operate well. After patch 'clk: imx7d: using api with flag CLK_OPS_PARENT_ENABLE', clk core can handle such clock type well, so we don't have to enable them all by default anymore. Instead, we only enable a minimum required set of clocks. Cc: Michael Turquette Cc: Stephen Boyd Cc: Shawn Guo Signed-off-by: Dong Aisheng Signed-off-by: Stephen Boyd --- drivers/clk/imx/clk-imx7d.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/drivers/clk/imx/clk-imx7d.c b/drivers/clk/imx/clk-imx7d.c index 62e25c37c6d6..79293edeb380 100644 --- a/drivers/clk/imx/clk-imx7d.c +++ b/drivers/clk/imx/clk-imx7d.c @@ -361,6 +361,14 @@ static const char *pll_enet_bypass_sel[] = { "pll_enet_main", "pll_enet_main_src static const char *pll_audio_bypass_sel[] = { "pll_audio_main", "pll_audio_main_src", }; static const char *pll_video_bypass_sel[] = { "pll_video_main", "pll_video_main_src", }; +static int const clks_init_on[] __initconst = { + IMX7D_ARM_A7_ROOT_CLK, IMX7D_MAIN_AXI_ROOT_CLK, + IMX7D_PLL_SYS_MAIN_480M_CLK, IMX7D_NAND_USDHC_BUS_ROOT_CLK, + IMX7D_DRAM_PHYM_ROOT_CLK, IMX7D_DRAM_ROOT_CLK, + IMX7D_DRAM_PHYM_ALT_ROOT_CLK, IMX7D_DRAM_ALT_ROOT_CLK, + IMX7D_AHB_CHANNEL_ROOT_CLK, +}; + static struct clk_onecell_data clk_data; static struct clk ** const uart_clks[] __initconst = { @@ -846,14 +854,8 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node) clk_data.clk_num = ARRAY_SIZE(clks); of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); - /* TO BE FIXED LATER - * Enable all clock to bring up imx7, otherwise system will be halt and block - * the other part upstream Because imx7d clock design changed, clock framework - * need do a little modify. - * Dong Aisheng is working on this. After that, this part need be changed. - */ - for (i = 0; i < IMX7D_CLK_END; i++) - clk_prepare_enable(clks[i]); + for (i = 0; i < ARRAY_SIZE(clks_init_on); i++) + clk_prepare_enable(clks[clks_init_on[i]]); /* use old gpt clk setting, gpt1 root clk must be twice as gpt counter freq */ clk_set_parent(clks[IMX7D_GPT1_ROOT_SRC], clks[IMX7D_OSC_24M_CLK]); -- cgit v1.2.3 From cdbf85c1cedac57f0f6e46d6f3d97c5a332d6908 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 1 Jul 2016 17:54:01 +0200 Subject: clk: qcom: add EBI2 clocks to the MSM8660 GCC This adds the EBI2 2X and EBI2 clocks to the MSM8660/APQ8060 GCC. This is necessary to enable clocking of the external bus interface so that peripherals on it can be mounted. These two clocks are simple gated branch clocks. In the vendor tree clock-8x60, these clocks have some kind of dependency, the EBI2 clock has .depends = &ebi2_2x_clk.c, what this means is undocumented, it doesn't seem like there is a parent/child relationship, so the solution I chose was to just have the EBI2 driver get and enable both clocks. Cc: Stephen Boyd Cc: Bjorn Andersson Signed-off-by: Linus Walleij Signed-off-by: Stephen Boyd --- drivers/clk/qcom/gcc-msm8660.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/drivers/clk/qcom/gcc-msm8660.c b/drivers/clk/qcom/gcc-msm8660.c index 6dc55864979c..c347a0d44bc8 100644 --- a/drivers/clk/qcom/gcc-msm8660.c +++ b/drivers/clk/qcom/gcc-msm8660.c @@ -2290,6 +2290,32 @@ static struct clk_branch sdc5_h_clk = { }, }; +static struct clk_branch ebi2_2x_clk = { + .halt_reg = 0x2fcc, + .halt_bit = 18, + .clkr = { + .enable_reg = 0x2660, + .enable_mask = BIT(4), + .hw.init = &(struct clk_init_data){ + .name = "ebi2_2x_clk", + .ops = &clk_branch_ops, + }, + }, +}; + +static struct clk_branch ebi2_clk = { + .halt_reg = 0x2fcc, + .halt_bit = 19, + .clkr = { + .enable_reg = 0x2664, + .enable_mask = BIT(4), + .hw.init = &(struct clk_init_data){ + .name = "ebi2_clk", + .ops = &clk_branch_ops, + }, + }, +}; + static struct clk_branch adm0_clk = { .halt_reg = 0x2fdc, .halt_check = BRANCH_HALT_VOTED, @@ -2533,6 +2559,8 @@ static struct clk_regmap *gcc_msm8660_clks[] = { [SDC3_H_CLK] = &sdc3_h_clk.clkr, [SDC4_H_CLK] = &sdc4_h_clk.clkr, [SDC5_H_CLK] = &sdc5_h_clk.clkr, + [EBI2_2X_CLK] = &ebi2_2x_clk.clkr, + [EBI2_CLK] = &ebi2_clk.clkr, [ADM0_CLK] = &adm0_clk.clkr, [ADM0_PBUS_CLK] = &adm0_pbus_clk.clkr, [ADM1_CLK] = &adm1_clk.clkr, -- cgit v1.2.3 From a718ce38d4cdcd1377d5b2e40b10acd80e63af29 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Mon, 4 Jul 2016 17:12:11 -0400 Subject: clk: meson8b: make it explicitly non-modular The Kconfig currently controlling compilation of this code is: drivers/clk/meson/Kconfig:config COMMON_CLK_MESON8B drivers/clk/meson/Kconfig: bool ...meaning that it currently is not being built as a module by anyone. However a recent commit added a bunch of modular boilerplate to this driver. Lets remove the modular code that is essentially orphaned, so that when reading the driver there is no doubt it is builtin-only. Since module_init translates to device_initcall in the non-modular case, the init ordering remains unchanged with this commit. Also note that MODULE DEVICE_TABLE/ALIAS are no-op when non-modular. We also delete the MODULE_LICENSE tag etc. since all that information was (or is now) contained at the top of the file in the comments. Cc: Stephen Boyd Cc: Carlo Caione Cc: Kevin Hilman Cc: linux-clk@vger.kernel.org Cc: linux-amlogic@lists.infradead.org Signed-off-by: Paul Gortmaker Signed-off-by: Michael Turquette Link: lkml.kernel.org/r/20160704211220.5685-2-paul.gortmaker@windriver.com --- drivers/clk/meson/meson8b-clkc.c | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/drivers/clk/meson/meson8b-clkc.c b/drivers/clk/meson/meson8b-clkc.c index b1902e91213d..4c9413cdf373 100644 --- a/drivers/clk/meson/meson8b-clkc.c +++ b/drivers/clk/meson/meson8b-clkc.c @@ -1,4 +1,6 @@ /* + * AmLogic S805 / Meson8b Clock Controller Driver + * * Copyright (c) 2015 Endless Mobile, Inc. * Author: Carlo Caione * @@ -23,7 +25,7 @@ #include #include #include -#include +#include #include "clkc.h" @@ -429,7 +431,6 @@ static const struct of_device_id meson8b_clkc_match_table[] = { { .compatible = "amlogic,meson8b-clkc" }, { } }; -MODULE_DEVICE_TABLE(of, meson8b_match_table); static struct platform_driver meson8b_driver = { .probe = meson8b_clkc_probe, @@ -443,16 +444,4 @@ static int __init meson8b_clkc_init(void) { return platform_driver_register(&meson8b_driver); } -module_init(meson8b_clkc_init); - -static void __exit meson8b_clkc_exit(void) -{ - platform_driver_unregister(&meson8b_driver); -} -module_exit(meson8b_clkc_exit); - -MODULE_DESCRIPTION("AmLogic S805 / Meson8b Clock Controller Driver"); -MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("platform:meson8b-clkc"); -MODULE_AUTHOR("Michael Turquette "); -MODULE_AUTHOR("Carlo Caione "); +device_initcall(meson8b_clkc_init); -- cgit v1.2.3 From 1f501d632ed2f719d36c62ba1f8a68de0200391a Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Mon, 4 Jul 2016 17:12:12 -0400 Subject: clk: meson: make gxbb explicitly non-modular The Kconfig currently controlling compilation of this code is: drivers/clk/meson/Kconfig:config COMMON_CLK_GXBB drivers/clk/meson/Kconfig: bool ...meaning that it currently is not being built as a module by anyone. Lets remove the modular code that is essentially orphaned, so that when reading the driver there is no doubt it is builtin-only. Since module_init translates to device_initcall in the non-modular case, the init ordering remains unchanged with this commit. Also note that MODULE_DEVICE_TABLE and ALIAS are no-op for non-modules. We also delete the MODULE_LICENSE tag etc. since all that information was (or is now) contained at the top of the file in the comments. Cc: Stephen Boyd Cc: Carlo Caione Cc: Kevin Hilman Cc: linux-clk@vger.kernel.org Cc: linux-amlogic@lists.infradead.org Signed-off-by: Paul Gortmaker Signed-off-by: Michael Turquette Link: lkml.kernel.org/r/20160704211220.5685-3-paul.gortmaker@windriver.com --- drivers/clk/meson/gxbb.c | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c index 007b7157cf4b..a4c6684b3019 100644 --- a/drivers/clk/meson/gxbb.c +++ b/drivers/clk/meson/gxbb.c @@ -1,4 +1,6 @@ /* + * AmLogic S905 / GXBB Clock Controller Driver + * * Copyright (c) 2016 AmLogic, Inc. * Michael Turquette * @@ -19,7 +21,7 @@ #include #include #include -#include +#include #include "clkc.h" #include "gxbb.h" @@ -926,7 +928,6 @@ static const struct of_device_id gxbb_clkc_match_table[] = { { .compatible = "amlogic,gxbb-clkc" }, { } }; -MODULE_DEVICE_TABLE(of, gxbb_match_table); static struct platform_driver gxbb_driver = { .probe = gxbb_clkc_probe, @@ -940,15 +941,4 @@ static int __init gxbb_clkc_init(void) { return platform_driver_register(&gxbb_driver); } -module_init(gxbb_clkc_init); - -static void __exit gxbb_clkc_exit(void) -{ - platform_driver_unregister(&gxbb_driver); -} -module_exit(gxbb_clkc_exit); - -MODULE_DESCRIPTION("AmLogic S905 / GXBB Clock Controller Driver"); -MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("platform:gxbb-clkc"); -MODULE_AUTHOR("Michael Turquette "); +device_initcall(gxbb_clkc_init); -- cgit v1.2.3 From c6e80ace83a90a410d09de0727ff9b151de6291a Mon Sep 17 00:00:00 2001 From: Xinliang Liu Date: Wed, 29 Jun 2016 16:45:54 +0800 Subject: clk: hi6220: Change syspll and media_syspll clk to 1.19GHz In the bootloader of HiKey/96boards, syspll and media_syspll clk was initialized to 1.19GHz. So, here changes it in kernel accordingly. 1.19GHz was chosen over 1.2GHz because at 1.19GHz we get more precise HDMI pixel clock (1.19G/16 = 74.4MHz) for 1280x720p@60Hz HDMI (74.25MHz required by standards). Closer pixel clock means better compatibility to HDMI monitors. Signed-off-by: Guodong Xu Signed-off-by: Xinliang Liu Signed-off-by: Michael Turquette Link: lkml.kernel.org/r/1467189955-21694-1-git-send-email-guodong.xu@linaro.org --- drivers/clk/hisilicon/clk-hi6220.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/clk/hisilicon/clk-hi6220.c b/drivers/clk/hisilicon/clk-hi6220.c index 76de9a762a86..fe364e63f8de 100644 --- a/drivers/clk/hisilicon/clk-hi6220.c +++ b/drivers/clk/hisilicon/clk-hi6220.c @@ -34,8 +34,8 @@ static struct hisi_fixed_rate_clock hi6220_fixed_rate_clks[] __initdata = { { HI6220_PLL_BBP, "bbppll0", NULL, 0, 245760000, }, { HI6220_PLL_GPU, "gpupll", NULL, 0, 1000000000,}, { HI6220_PLL1_DDR, "ddrpll1", NULL, 0, 1066000000,}, - { HI6220_PLL_SYS, "syspll", NULL, 0, 1200000000,}, - { HI6220_PLL_SYS_MEDIA, "media_syspll", NULL, 0, 1200000000,}, + { HI6220_PLL_SYS, "syspll", NULL, 0, 1190400000,}, + { HI6220_PLL_SYS_MEDIA, "media_syspll", NULL, 0, 1190400000,}, { HI6220_DDR_SRC, "ddr_sel_src", NULL, 0, 1200000000,}, { HI6220_PLL_MEDIA, "media_pll", NULL, 0, 1440000000,}, { HI6220_PLL_DDR, "ddrpll0", NULL, 0, 1600000000,}, -- cgit v1.2.3 From cb98fd5d4da192cf2bf3fceddcc3bc9e59a22598 Mon Sep 17 00:00:00 2001 From: Wadim Egorov Date: Thu, 2 Jun 2016 08:50:27 +0200 Subject: clk: Kconfig: Name RK818 in Kconfig for COMMON_CLK_RK808 The RK808 and RK818 PMICs are using a similar register map. We can reuse the clk driver for the RK818 PMIC. So let's add the RK818 in the Kconfig description. Signed-off-by: Wadim Egorov Acked-by: Stephen Boyd Signed-off-by: Michael Turquette Link: lkml.kernel.org/r/1464850228-17244-4-git-send-email-w.egorov@phytec.de --- drivers/clk/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index bfaad3d72233..7cef0503429a 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -49,10 +49,10 @@ config COMMON_CLK_MAX77802 This driver supports Maxim 77802 crystal oscillator clock. config COMMON_CLK_RK808 - tristate "Clock driver for RK808" + tristate "Clock driver for RK808/RK818" depends on MFD_RK808 ---help--- - This driver supports RK808 crystal oscillator clock. These + This driver supports RK808 and RK818 crystal oscillator clock. These multi-function devices have two fixed-rate oscillators, clocked at 32KHz each. Clkout1 is always on, Clkout2 can off by control register. -- cgit v1.2.3 From 80c6397c37d56f4cf8e175a541b1ebbf5f7d186a Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Mon, 4 Jul 2016 17:12:15 -0400 Subject: clk: oxnas: make it explicitly non-modular The Kconfig currently controlling compilation of this code is: drivers/clk/Kconfig:config COMMON_CLK_OXNAS drivers/clk/Kconfig: bool "Clock driver for the OXNAS SoC Family" ...meaning that it currently is not being built as a module by anyone. Lets remove the modular code that is essentially orphaned, so that when reading the driver there is no doubt it is builtin-only. We explicitly disallow a driver unbind, since that doesn't have a sensible use case anyway, and it allows us to drop the ".remove" code for non-modular drivers. Since module_platform_driver() uses the same init level priority as builtin_platform_driver() the init ordering remains unchanged with this commit. Also note that MODULE_DEVICE_TABLE is a no-op for non-modular code. Cc: Stephen Boyd Acked-by: Neil Armstrong Cc: linux-clk@vger.kernel.org Signed-off-by: Paul Gortmaker Signed-off-by: Michael Turquette Link: lkml.kernel.org/r/20160704211220.5685-6-paul.gortmaker@windriver.com --- drivers/clk/clk-oxnas.c | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/drivers/clk/clk-oxnas.c b/drivers/clk/clk-oxnas.c index 79bcb2e42060..47649ac5d399 100644 --- a/drivers/clk/clk-oxnas.c +++ b/drivers/clk/clk-oxnas.c @@ -18,7 +18,7 @@ #include #include -#include +#include #include #include #include @@ -170,26 +170,17 @@ static int oxnas_stdclk_probe(struct platform_device *pdev) clk_oxnas->onecell_data); } -static int oxnas_stdclk_remove(struct platform_device *pdev) -{ - of_clk_del_provider(pdev->dev.of_node); - - return 0; -} - static const struct of_device_id oxnas_stdclk_dt_ids[] = { { .compatible = "oxsemi,ox810se-stdclk" }, { } }; -MODULE_DEVICE_TABLE(of, oxnas_stdclk_dt_ids); static struct platform_driver oxnas_stdclk_driver = { .probe = oxnas_stdclk_probe, - .remove = oxnas_stdclk_remove, .driver = { .name = "oxnas-stdclk", + .suppress_bind_attrs = true, .of_match_table = oxnas_stdclk_dt_ids, }, }; - -module_platform_driver(oxnas_stdclk_driver); +builtin_platform_driver(oxnas_stdclk_driver); -- cgit v1.2.3 From 439a36d7d9318c2709066d853720bd77f201033a Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Mon, 4 Jul 2016 17:12:18 -0400 Subject: clk: sunxi: make clk-* explicitly non-modular MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We have the following file --> Kconfig mapping: sunxi/clk-factors.c obj-y sunxi/clk-sun6i-apb0-gates.c CONFIG_MFD_SUN6I_PRCM (bool) sunxi/clk-sun6i-apb0.c CONFIG_MFD_SUN6I_PRCM sunxi/clk-sun6i-ar100.c CONFIG_MFD_SUN6I_PRCM sunxi/clk-sun8i-apb0.c CONFIG_MFD_SUN6I_PRCM sunxi/clk-sun9i-mmc.c obj-y Hence none of these are being built as a module by anyone. Lets remove the modular code that is essentially orphaned, so that when reading the drivers there is no doubt they are builtin-only. All drivers get mostly the same changes, so they are handled in batch. Changes are (1) convert to builtin_platform_register, (2) use the init.h header, (3) delete the MODULE_LICENCE/MODULE_AUTHOR and associated tags, and (4) delete any ".remove" functions. There was a stray module.h in a file not using any init.h or module.h stuff, so we simply removed that one. In two cases, we explicitly disallow a driver unbind, since that doesn't have a sensible use case anyway, and it allows us to drop the ".remove" code for non-modular drivers. Since module_platform_driver() uses the same init level priority as builtin_platform_driver() the init ordering remains unchanged with this commit. We delete the MODULE_LICENSE etc. tags since all that information is already contained at the top of each file in the comments. Acked-by: Boris Brezillon Cc: Chen-Yu Tsai Cc: "Emilio López" Cc: Stephen Boyd Acked-by: Maxime Ripard Cc: linux-clk@vger.kernel.org Signed-off-by: Paul Gortmaker Signed-off-by: Michael Turquette Link: lkml.kernel.org/r/20160704211220.5685-9-paul.gortmaker@windriver.com --- drivers/clk/sunxi/clk-factors.c | 1 - drivers/clk/sunxi/clk-sun6i-apb0-gates.c | 9 ++------- drivers/clk/sunxi/clk-sun6i-apb0.c | 9 ++------- drivers/clk/sunxi/clk-sun6i-ar100.c | 21 +++------------------ drivers/clk/sunxi/clk-sun8i-apb0.c | 9 ++------- drivers/clk/sunxi/clk-sun9i-mmc.c | 28 +++------------------------- 6 files changed, 12 insertions(+), 65 deletions(-) diff --git a/drivers/clk/sunxi/clk-factors.c b/drivers/clk/sunxi/clk-factors.c index ddefe9668863..dfe5e3e32d28 100644 --- a/drivers/clk/sunxi/clk-factors.c +++ b/drivers/clk/sunxi/clk-factors.c @@ -12,7 +12,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/clk/sunxi/clk-sun6i-apb0-gates.c b/drivers/clk/sunxi/clk-sun6i-apb0-gates.c index 68021fa5ecd9..09cdb9874636 100644 --- a/drivers/clk/sunxi/clk-sun6i-apb0-gates.c +++ b/drivers/clk/sunxi/clk-sun6i-apb0-gates.c @@ -9,7 +9,7 @@ */ #include -#include +#include #include #include #include @@ -33,7 +33,6 @@ static const struct of_device_id sun6i_a31_apb0_gates_clk_dt_ids[] = { { .compatible = "allwinner,sun8i-a23-apb0-gates-clk", .data = &sun8i_a23_apb0_gates }, { /* sentinel */ } }; -MODULE_DEVICE_TABLE(of, sun6i_a31_apb0_gates_clk_dt_ids); static int sun6i_a31_apb0_gates_clk_probe(struct platform_device *pdev) { @@ -102,8 +101,4 @@ static struct platform_driver sun6i_a31_apb0_gates_clk_driver = { }, .probe = sun6i_a31_apb0_gates_clk_probe, }; -module_platform_driver(sun6i_a31_apb0_gates_clk_driver); - -MODULE_AUTHOR("Boris BREZILLON "); -MODULE_DESCRIPTION("Allwinner A31 APB0 gate clocks driver"); -MODULE_LICENSE("GPL v2"); +builtin_platform_driver(sun6i_a31_apb0_gates_clk_driver); diff --git a/drivers/clk/sunxi/clk-sun6i-apb0.c b/drivers/clk/sunxi/clk-sun6i-apb0.c index e703e1895b76..b9c8d359288c 100644 --- a/drivers/clk/sunxi/clk-sun6i-apb0.c +++ b/drivers/clk/sunxi/clk-sun6i-apb0.c @@ -9,7 +9,7 @@ */ #include -#include +#include #include #include @@ -61,7 +61,6 @@ static const struct of_device_id sun6i_a31_apb0_clk_dt_ids[] = { { .compatible = "allwinner,sun6i-a31-apb0-clk" }, { /* sentinel */ } }; -MODULE_DEVICE_TABLE(of, sun6i_a31_apb0_clk_dt_ids); static struct platform_driver sun6i_a31_apb0_clk_driver = { .driver = { @@ -70,8 +69,4 @@ static struct platform_driver sun6i_a31_apb0_clk_driver = { }, .probe = sun6i_a31_apb0_clk_probe, }; -module_platform_driver(sun6i_a31_apb0_clk_driver); - -MODULE_AUTHOR("Boris BREZILLON "); -MODULE_DESCRIPTION("Allwinner A31 APB0 clock Driver"); -MODULE_LICENSE("GPL v2"); +builtin_platform_driver(sun6i_a31_apb0_clk_driver); diff --git a/drivers/clk/sunxi/clk-sun6i-ar100.c b/drivers/clk/sunxi/clk-sun6i-ar100.c index 84a187e55360..64ca3e9e38e6 100644 --- a/drivers/clk/sunxi/clk-sun6i-ar100.c +++ b/drivers/clk/sunxi/clk-sun6i-ar100.c @@ -10,7 +10,7 @@ #include #include -#include +#include #include #include #include @@ -91,32 +91,17 @@ static int sun6i_a31_ar100_clk_probe(struct platform_device *pdev) return 0; } -static int sun6i_a31_ar100_clk_remove(struct platform_device *pdev) -{ - struct device_node *np = pdev->dev.of_node; - struct clk *clk = platform_get_drvdata(pdev); - - sunxi_factors_unregister(np, clk); - - return 0; -} - static const struct of_device_id sun6i_a31_ar100_clk_dt_ids[] = { { .compatible = "allwinner,sun6i-a31-ar100-clk" }, { /* sentinel */ } }; -MODULE_DEVICE_TABLE(of, sun6i_a31_ar100_clk_dt_ids); static struct platform_driver sun6i_a31_ar100_clk_driver = { .driver = { .name = "sun6i-a31-ar100-clk", .of_match_table = sun6i_a31_ar100_clk_dt_ids, + .suppress_bind_attrs = true, }, .probe = sun6i_a31_ar100_clk_probe, - .remove = sun6i_a31_ar100_clk_remove, }; -module_platform_driver(sun6i_a31_ar100_clk_driver); - -MODULE_AUTHOR("Boris BREZILLON "); -MODULE_DESCRIPTION("Allwinner A31 AR100 clock Driver"); -MODULE_LICENSE("GPL v2"); +builtin_platform_driver(sun6i_a31_ar100_clk_driver); diff --git a/drivers/clk/sunxi/clk-sun8i-apb0.c b/drivers/clk/sunxi/clk-sun8i-apb0.c index 2ea61debffc1..a5666e1d0ce7 100644 --- a/drivers/clk/sunxi/clk-sun8i-apb0.c +++ b/drivers/clk/sunxi/clk-sun8i-apb0.c @@ -15,7 +15,7 @@ */ #include -#include +#include #include #include #include @@ -108,7 +108,6 @@ static const struct of_device_id sun8i_a23_apb0_clk_dt_ids[] = { { .compatible = "allwinner,sun8i-a23-apb0-clk" }, { /* sentinel */ } }; -MODULE_DEVICE_TABLE(of, sun8i_a23_apb0_clk_dt_ids); static struct platform_driver sun8i_a23_apb0_clk_driver = { .driver = { @@ -117,8 +116,4 @@ static struct platform_driver sun8i_a23_apb0_clk_driver = { }, .probe = sun8i_a23_apb0_clk_probe, }; -module_platform_driver(sun8i_a23_apb0_clk_driver); - -MODULE_AUTHOR("Chen-Yu Tsai "); -MODULE_DESCRIPTION("Allwinner A23 APB0 clock Driver"); -MODULE_LICENSE("GPL v2"); +builtin_platform_driver(sun8i_a23_apb0_clk_driver); diff --git a/drivers/clk/sunxi/clk-sun9i-mmc.c b/drivers/clk/sunxi/clk-sun9i-mmc.c index 716737388b7d..6041bdba2e97 100644 --- a/drivers/clk/sunxi/clk-sun9i-mmc.c +++ b/drivers/clk/sunxi/clk-sun9i-mmc.c @@ -16,7 +16,7 @@ #include #include -#include +#include #include #include #include @@ -183,39 +183,17 @@ err_clk_register: return ret; } -static int sun9i_a80_mmc_config_clk_remove(struct platform_device *pdev) -{ - struct device_node *np = pdev->dev.of_node; - struct sun9i_mmc_clk_data *data = platform_get_drvdata(pdev); - struct clk_onecell_data *clk_data = &data->clk_data; - int i; - - reset_controller_unregister(&data->rcdev); - of_clk_del_provider(np); - for (i = 0; i < clk_data->clk_num; i++) - clk_unregister(clk_data->clks[i]); - - reset_control_assert(data->reset); - - return 0; -} - static const struct of_device_id sun9i_a80_mmc_config_clk_dt_ids[] = { { .compatible = "allwinner,sun9i-a80-mmc-config-clk" }, { /* sentinel */ } }; -MODULE_DEVICE_TABLE(of, sun9i_a80_mmc_config_clk_dt_ids); static struct platform_driver sun9i_a80_mmc_config_clk_driver = { .driver = { .name = "sun9i-a80-mmc-config-clk", + .suppress_bind_attrs = true, .of_match_table = sun9i_a80_mmc_config_clk_dt_ids, }, .probe = sun9i_a80_mmc_config_clk_probe, - .remove = sun9i_a80_mmc_config_clk_remove, }; -module_platform_driver(sun9i_a80_mmc_config_clk_driver); - -MODULE_AUTHOR("Chen-Yu Tsai "); -MODULE_DESCRIPTION("Allwinner A80 MMC clock/reset Driver"); -MODULE_LICENSE("GPL v2"); +builtin_platform_driver(sun9i_a80_mmc_config_clk_driver); -- cgit v1.2.3 From 054e2730088a9c9340b5bc6927000f5c14a8b6d7 Mon Sep 17 00:00:00 2001 From: Sylvain Lemieux Date: Fri, 3 Jun 2016 15:34:35 -0400 Subject: clk: lpc32xx: allow peripheral clock selection in device tree This patch add the support to select the peripheral clock (PERIPH) as a parent clock source using the "assigned-clock-parents" parameter in the device tree. Signed-off-by: Sylvain Lemieux Acked-by: Vladimir Zapolskiy Signed-off-by: Michael Turquette Link: lkml.kernel.org/r/1464982475-24738-1-git-send-email-slemieux.tyco@gmail.com --- drivers/clk/nxp/clk-lpc32xx.c | 3 +-- include/dt-bindings/clock/lpc32xx-clock.h | 1 + 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/clk/nxp/clk-lpc32xx.c b/drivers/clk/nxp/clk-lpc32xx.c index 481b2646b496..90d740a2fc0d 100644 --- a/drivers/clk/nxp/clk-lpc32xx.c +++ b/drivers/clk/nxp/clk-lpc32xx.c @@ -87,7 +87,7 @@ enum { enum { /* Start from the last defined clock in dt bindings */ - LPC32XX_CLK_ADC_DIV = LPC32XX_CLK_HCLK_PLL + 1, + LPC32XX_CLK_ADC_DIV = LPC32XX_CLK_PERIPH + 1, LPC32XX_CLK_ADC_RTC, LPC32XX_CLK_TEST1, LPC32XX_CLK_TEST2, @@ -99,7 +99,6 @@ enum { LPC32XX_CLK_HCLK_DIV_PERIPH, LPC32XX_CLK_HCLK_DIV, LPC32XX_CLK_HCLK, - LPC32XX_CLK_PERIPH, LPC32XX_CLK_ARM, LPC32XX_CLK_ARM_VFP, diff --git a/include/dt-bindings/clock/lpc32xx-clock.h b/include/dt-bindings/clock/lpc32xx-clock.h index d41b6fea1450..e624d3a52798 100644 --- a/include/dt-bindings/clock/lpc32xx-clock.h +++ b/include/dt-bindings/clock/lpc32xx-clock.h @@ -48,6 +48,7 @@ #define LPC32XX_CLK_PWM2 33 #define LPC32XX_CLK_ADC 34 #define LPC32XX_CLK_HCLK_PLL 35 +#define LPC32XX_CLK_PERIPH 36 /* LPC32XX USB clocks */ #define LPC32XX_USB_CLK_I2C 1 -- cgit v1.2.3 From 334e125b4e136739c4a22818eac6e3b50a48f767 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Sun, 3 Jul 2016 08:06:43 +0200 Subject: clk: stm32f4: fix error handling This is likely that checking 'clks[idx]' instead of 'clks[n]' is expected here. Signed-off-by: Christophe JAILLET Signed-off-by: Michael Turquette Link: lkml.kernel.org/r/1467526003-13318-1-git-send-email-christophe.jaillet@wanadoo.fr --- drivers/clk/clk-stm32f4.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/clk-stm32f4.c b/drivers/clk/clk-stm32f4.c index b6ca33f0c935..02d681008401 100644 --- a/drivers/clk/clk-stm32f4.c +++ b/drivers/clk/clk-stm32f4.c @@ -364,7 +364,7 @@ static void __init stm32f4_rcc_init(struct device_node *np) NULL, gd->name, gd->parent_name, gd->flags, base + gd->offset, gd->bit_idx, 0, &stm32f4_clk_lock); - if (IS_ERR(clks[n])) { + if (IS_ERR(clks[idx])) { pr_err("%s: Unable to register leaf clock %s\n", np->full_name, gd->name); goto fail; -- cgit v1.2.3 From e16fb2e6355c1c1b41623af9e01ada196e2af098 Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Wed, 6 Jul 2016 20:38:37 -0700 Subject: clk: gxbb: expose CLKID_MMC_PCLK The MMC_PCLK is needed for the SD/eMMC driver, expose to DT (and comment out in clk driver) Signed-off-by: Kevin Hilman Signed-off-by: Michael Turquette Link: lkml.kernel.org/r/20160707033837.20029-1-khilman@baylibre.com --- drivers/clk/meson/gxbb.h | 2 +- include/dt-bindings/clock/gxbb-clkc.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/clk/meson/gxbb.h b/drivers/clk/meson/gxbb.h index a2adf3448b59..8355ecd27b81 100644 --- a/drivers/clk/meson/gxbb.h +++ b/drivers/clk/meson/gxbb.h @@ -234,7 +234,7 @@ #define CLKID_HDMI_PCLK 63 #define CLKID_USB1_DDR_BRIDGE 64 #define CLKID_USB0_DDR_BRIDGE 65 -#define CLKID_MMC_PCLK 66 +/* CLKID_MMC_PCLK */ #define CLKID_DVIN 67 #define CLKID_UART2 68 #define CLKID_SANA 69 diff --git a/include/dt-bindings/clock/gxbb-clkc.h b/include/dt-bindings/clock/gxbb-clkc.h index f889d80246cb..5eb69ec74f6b 100644 --- a/include/dt-bindings/clock/gxbb-clkc.h +++ b/include/dt-bindings/clock/gxbb-clkc.h @@ -8,5 +8,6 @@ #define CLKID_CPUCLK 1 #define CLKID_CLK81 12 #define CLKID_ETH 36 +#define CLKID_MMC_PCLK 66 #endif /* __GXBB_CLKC_H */ -- cgit v1.2.3 From c200c39b2d3906dfd5c7d6b3918befda5b5d7ea2 Mon Sep 17 00:00:00 2001 From: Tomeu Vizoso Date: Fri, 8 Jul 2016 09:14:38 +0200 Subject: clk: clk-conf: Fix error message when clock isn't found When failing to lookup the assigned clock for setting its parents, we were previously printing a misleading error message that lead to think that it was the parent clock what couldn't be found. Change error message to make clear that it's the assigned clock what couldn't be found in this case. Signed-off-by: Tomeu Vizoso Signed-off-by: Michael Turquette Link: lkml.kernel.org/r/1467962078-30405-1-git-send-email-tomeu.vizoso@collabora.com --- drivers/clk/clk-conf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/clk-conf.c b/drivers/clk/clk-conf.c index 43a218f35b19..674785d968a3 100644 --- a/drivers/clk/clk-conf.c +++ b/drivers/clk/clk-conf.c @@ -55,7 +55,7 @@ static int __set_clk_parents(struct device_node *node, bool clk_supplier) } clk = of_clk_get_from_provider(&clkspec); if (IS_ERR(clk)) { - pr_warn("clk: couldn't get parent clock %d for %s\n", + pr_warn("clk: couldn't get assigned clock %d for %s\n", index, node->full_name); rc = PTR_ERR(clk); goto err; -- cgit v1.2.3 From a06498297d233fd5074da14f25e72c2f104561d3 Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Tue, 28 Jun 2016 11:02:28 +0530 Subject: clk: imx: vf610: Disable automatic clock gating for lpuart in LPSTOP mode In order to allow wake support in STOP sleep mode, clocks are needed. Use imx_clk_gate2_cgr to disable automatic clock gating in low power mode STOP. This allows to enable wake by UART using: echo enabled > /sys/class/tty/ttyLP0/power/wakeup However, if wake is not enabled, the driver should disable the clocks explicitly to save power. Signed-off-by: Stefan Agner Signed-off-by: Bhuvanchandra DV Signed-off-by: Michael Turquette Link: lkml.kernel.org/r/20160628053235.5114-3-bhuvanchandra.dv@toradex.com --- drivers/clk/imx/clk-vf610.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/clk/imx/clk-vf610.c b/drivers/clk/imx/clk-vf610.c index 3a1f24475ee4..0476353ab423 100644 --- a/drivers/clk/imx/clk-vf610.c +++ b/drivers/clk/imx/clk-vf610.c @@ -315,12 +315,12 @@ static void __init vf610_clocks_init(struct device_node *ccm_node) clk[VF610_CLK_PIT] = imx_clk_gate2("pit", "ipg_bus", CCM_CCGR1, CCM_CCGRx_CGn(7)); - clk[VF610_CLK_UART0] = imx_clk_gate2("uart0", "ipg_bus", CCM_CCGR0, CCM_CCGRx_CGn(7)); - clk[VF610_CLK_UART1] = imx_clk_gate2("uart1", "ipg_bus", CCM_CCGR0, CCM_CCGRx_CGn(8)); - clk[VF610_CLK_UART2] = imx_clk_gate2("uart2", "ipg_bus", CCM_CCGR0, CCM_CCGRx_CGn(9)); - clk[VF610_CLK_UART3] = imx_clk_gate2("uart3", "ipg_bus", CCM_CCGR0, CCM_CCGRx_CGn(10)); - clk[VF610_CLK_UART4] = imx_clk_gate2("uart4", "ipg_bus", CCM_CCGR6, CCM_CCGRx_CGn(9)); - clk[VF610_CLK_UART5] = imx_clk_gate2("uart5", "ipg_bus", CCM_CCGR6, CCM_CCGRx_CGn(10)); + clk[VF610_CLK_UART0] = imx_clk_gate2_cgr("uart0", "ipg_bus", CCM_CCGR0, CCM_CCGRx_CGn(7), 0x2); + clk[VF610_CLK_UART1] = imx_clk_gate2_cgr("uart1", "ipg_bus", CCM_CCGR0, CCM_CCGRx_CGn(8), 0x2); + clk[VF610_CLK_UART2] = imx_clk_gate2_cgr("uart2", "ipg_bus", CCM_CCGR0, CCM_CCGRx_CGn(9), 0x2); + clk[VF610_CLK_UART3] = imx_clk_gate2_cgr("uart3", "ipg_bus", CCM_CCGR0, CCM_CCGRx_CGn(10), 0x2); + clk[VF610_CLK_UART4] = imx_clk_gate2_cgr("uart4", "ipg_bus", CCM_CCGR6, CCM_CCGRx_CGn(9), 0x2); + clk[VF610_CLK_UART5] = imx_clk_gate2_cgr("uart5", "ipg_bus", CCM_CCGR6, CCM_CCGRx_CGn(10), 0x2); clk[VF610_CLK_I2C0] = imx_clk_gate2("i2c0", "ipg_bus", CCM_CCGR4, CCM_CCGRx_CGn(6)); clk[VF610_CLK_I2C1] = imx_clk_gate2("i2c1", "ipg_bus", CCM_CCGR4, CCM_CCGRx_CGn(7)); -- cgit v1.2.3 From c0692d68a88a108fd0a34f0a9bc9c3781b49d6d6 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Wed, 29 Jun 2016 21:05:22 +0200 Subject: dt-bindings: sunxi: Add CCU binding documentation Introduce a new binding with its documentation for the brand new clock sub-framework. Signed-off-by: Maxime Ripard Acked-by: Rob Herring Signed-off-by: Michael Turquette Link: lkml.kernel.org/r/20160629190535.11855-2-maxime.ripard@free-electrons.com --- .../devicetree/bindings/clock/sunxi-ccu.txt | 24 ++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/sunxi-ccu.txt diff --git a/Documentation/devicetree/bindings/clock/sunxi-ccu.txt b/Documentation/devicetree/bindings/clock/sunxi-ccu.txt new file mode 100644 index 000000000000..cb91507ffb1e --- /dev/null +++ b/Documentation/devicetree/bindings/clock/sunxi-ccu.txt @@ -0,0 +1,24 @@ +Allwinner Clock Control Unit Binding +------------------------------------ + +Required properties : +- compatible: must contain one of the following compatible: + - "allwinner,sun8i-h3-ccu" + +- reg: Must contain the registers base address and length +- clocks: phandle to the oscillators feeding the CCU. Two are needed: + - "hosc": the high frequency oscillator (usually at 24MHz) + - "losc": the low frequency oscillator (usually at 32kHz) +- clock-names: Must contain the clock names described just above +- #clock-cells : must contain 1 +- #reset-cells : must contain 1 + +Example: +ccu: clock@01c20000 { + compatible = "allwinner,sun8i-h3-ccu"; + reg = <0x01c20000 0x400>; + clocks = <&osc24M>, <&osc32k>; + clock-names = "hosc", "losc"; + #clock-cells = <1>; + #reset-cells = <1>; +}; -- cgit v1.2.3 From 1d80c14248d6082c91a8a9e3d70cc94c3cc18ecb Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Wed, 29 Jun 2016 21:05:23 +0200 Subject: clk: sunxi-ng: Add common infrastructure Start our new clock infrastructure by adding the registration code, common structure and common code. Signed-off-by: Maxime Ripard Signed-off-by: Michael Turquette Link: lkml.kernel.org/r/20160629190535.11855-3-maxime.ripard@free-electrons.com --- drivers/clk/Kconfig | 1 + drivers/clk/Makefile | 1 + drivers/clk/sunxi-ng/Kconfig | 3 ++ drivers/clk/sunxi-ng/Makefile | 3 ++ drivers/clk/sunxi-ng/ccu_common.c | 90 +++++++++++++++++++++++++++++++++++++++ drivers/clk/sunxi-ng/ccu_common.h | 85 ++++++++++++++++++++++++++++++++++++ drivers/clk/sunxi-ng/ccu_mult.h | 15 +++++++ drivers/clk/sunxi-ng/ccu_reset.c | 55 ++++++++++++++++++++++++ drivers/clk/sunxi-ng/ccu_reset.h | 40 +++++++++++++++++ 9 files changed, 293 insertions(+) create mode 100644 drivers/clk/sunxi-ng/Kconfig create mode 100644 drivers/clk/sunxi-ng/Makefile create mode 100644 drivers/clk/sunxi-ng/ccu_common.c create mode 100644 drivers/clk/sunxi-ng/ccu_common.h create mode 100644 drivers/clk/sunxi-ng/ccu_mult.h create mode 100644 drivers/clk/sunxi-ng/ccu_reset.c create mode 100644 drivers/clk/sunxi-ng/ccu_reset.h diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index 53ddba26578c..8216f47ac37d 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -212,6 +212,7 @@ source "drivers/clk/mvebu/Kconfig" source "drivers/clk/qcom/Kconfig" source "drivers/clk/renesas/Kconfig" source "drivers/clk/samsung/Kconfig" +source "drivers/clk/sunxi-ng/Kconfig" source "drivers/clk/tegra/Kconfig" source "drivers/clk/ti/Kconfig" diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index dcc5e698ff6d..7a44a1526d60 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -79,6 +79,7 @@ obj-$(CONFIG_ARCH_SOCFPGA) += socfpga/ obj-$(CONFIG_PLAT_SPEAR) += spear/ obj-$(CONFIG_ARCH_STI) += st/ obj-$(CONFIG_ARCH_SUNXI) += sunxi/ +obj-$(CONFIG_ARCH_SUNXI) += sunxi-ng/ obj-$(CONFIG_ARCH_TEGRA) += tegra/ obj-y += ti/ obj-$(CONFIG_ARCH_U8500) += ux500/ diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-ng/Kconfig new file mode 100644 index 000000000000..df5b2768d8b4 --- /dev/null +++ b/drivers/clk/sunxi-ng/Kconfig @@ -0,0 +1,3 @@ +config SUNXI_CCU + bool "Clock support for Allwinner SoCs" + default ARCH_SUNXI diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile new file mode 100644 index 000000000000..886d0786ca51 --- /dev/null +++ b/drivers/clk/sunxi-ng/Makefile @@ -0,0 +1,3 @@ +# Common objects +obj-$(CONFIG_SUNXI_CCU) += ccu_common.o +obj-$(CONFIG_SUNXI_CCU) += ccu_reset.o diff --git a/drivers/clk/sunxi-ng/ccu_common.c b/drivers/clk/sunxi-ng/ccu_common.c new file mode 100644 index 000000000000..fc17b5295e16 --- /dev/null +++ b/drivers/clk/sunxi-ng/ccu_common.c @@ -0,0 +1,90 @@ +/* + * Copyright 2016 Maxime Ripard + * + * Maxime Ripard + * + * 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 "ccu_common.h" +#include "ccu_reset.h" + +static DEFINE_SPINLOCK(ccu_lock); + +void ccu_helper_wait_for_lock(struct ccu_common *common, u32 lock) +{ + u32 reg; + + if (!lock) + return; + + WARN_ON(readl_relaxed_poll_timeout(common->base + common->reg, reg, + !(reg & lock), 100, 70000)); +} + +int sunxi_ccu_probe(struct device_node *node, void __iomem *reg, + const struct sunxi_ccu_desc *desc) +{ + struct ccu_reset *reset; + int i, ret; + + for (i = 0; i < desc->num_ccu_clks; i++) { + struct ccu_common *cclk = desc->ccu_clks[i]; + + if (!cclk) + continue; + + cclk->base = reg; + cclk->lock = &ccu_lock; + } + + for (i = 0; i < desc->hw_clks->num ; i++) { + struct clk_hw *hw = desc->hw_clks->hws[i]; + + if (!hw) + continue; + + ret = clk_hw_register(NULL, hw); + if (ret) { + pr_err("Couldn't register clock %s\n", + clk_hw_get_name(hw)); + goto err_clk_unreg; + } + } + + ret = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, + desc->hw_clks); + if (ret) + goto err_clk_unreg; + + reset = kzalloc(sizeof(*reset), GFP_KERNEL); + reset->rcdev.of_node = node; + reset->rcdev.ops = &ccu_reset_ops; + reset->rcdev.owner = THIS_MODULE; + reset->rcdev.nr_resets = desc->num_resets; + reset->base = reg; + reset->lock = &ccu_lock; + reset->reset_map = desc->resets; + + ret = reset_controller_register(&reset->rcdev); + if (ret) + goto err_of_clk_unreg; + + return 0; + +err_of_clk_unreg: +err_clk_unreg: + return ret; +} diff --git a/drivers/clk/sunxi-ng/ccu_common.h b/drivers/clk/sunxi-ng/ccu_common.h new file mode 100644 index 000000000000..b3d9abfbd721 --- /dev/null +++ b/drivers/clk/sunxi-ng/ccu_common.h @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2016 Maxime Ripard. All rights reserved. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + */ + +#ifndef _COMMON_H_ +#define _COMMON_H_ + +#include +#include + +#define CCU_FEATURE_FRACTIONAL BIT(0) +#define CCU_FEATURE_VARIABLE_PREDIV BIT(1) +#define CCU_FEATURE_FIXED_PREDIV BIT(2) +#define CCU_FEATURE_FIXED_POSTDIV BIT(3) + +struct device_node; + +#define CLK_HW_INIT(_name, _parent, _ops, _flags) \ + &(struct clk_init_data) { \ + .flags = _flags, \ + .name = _name, \ + .parent_names = (const char *[]) { _parent }, \ + .num_parents = 1, \ + .ops = _ops, \ + } + +#define CLK_HW_INIT_PARENTS(_name, _parents, _ops, _flags) \ + &(struct clk_init_data) { \ + .flags = _flags, \ + .name = _name, \ + .parent_names = _parents, \ + .num_parents = ARRAY_SIZE(_parents), \ + .ops = _ops, \ + } + +#define CLK_FIXED_FACTOR(_struct, _name, _parent, \ + _div, _mult, _flags) \ + struct clk_fixed_factor _struct = { \ + .div = _div, \ + .mult = _mult, \ + .hw.init = CLK_HW_INIT(_name, \ + _parent, \ + &clk_fixed_factor_ops, \ + _flags), \ + } + +struct ccu_common { + void __iomem *base; + u16 reg; + + unsigned long features; + spinlock_t *lock; + struct clk_hw hw; +}; + +static inline struct ccu_common *hw_to_ccu_common(struct clk_hw *hw) +{ + return container_of(hw, struct ccu_common, hw); +} + +struct sunxi_ccu_desc { + struct ccu_common **ccu_clks; + unsigned long num_ccu_clks; + + struct clk_hw_onecell_data *hw_clks; + + struct ccu_reset_map *resets; + unsigned long num_resets; +}; + +void ccu_helper_wait_for_lock(struct ccu_common *common, u32 lock); + +int sunxi_ccu_probe(struct device_node *node, void __iomem *reg, + const struct sunxi_ccu_desc *desc); + +#endif /* _COMMON_H_ */ diff --git a/drivers/clk/sunxi-ng/ccu_mult.h b/drivers/clk/sunxi-ng/ccu_mult.h new file mode 100644 index 000000000000..609db6610880 --- /dev/null +++ b/drivers/clk/sunxi-ng/ccu_mult.h @@ -0,0 +1,15 @@ +#ifndef _CCU_MULT_H_ +#define _CCU_MULT_H_ + +struct _ccu_mult { + u8 shift; + u8 width; +}; + +#define _SUNXI_CCU_MULT(_shift, _width) \ + { \ + .shift = _shift, \ + .width = _width, \ + } + +#endif /* _CCU_MULT_H_ */ diff --git a/drivers/clk/sunxi-ng/ccu_reset.c b/drivers/clk/sunxi-ng/ccu_reset.c new file mode 100644 index 000000000000..6c31d48783a7 --- /dev/null +++ b/drivers/clk/sunxi-ng/ccu_reset.c @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2016 Maxime Ripard + * Maxime Ripard + * + * 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 "ccu_reset.h" + +static int ccu_reset_assert(struct reset_controller_dev *rcdev, + unsigned long id) +{ + struct ccu_reset *ccu = rcdev_to_ccu_reset(rcdev); + const struct ccu_reset_map *map = &ccu->reset_map[id]; + unsigned long flags; + u32 reg; + + spin_lock_irqsave(ccu->lock, flags); + + reg = readl(ccu->base + map->reg); + writel(reg & ~map->bit, ccu->base + map->reg); + + spin_unlock_irqrestore(ccu->lock, flags); + + return 0; +} + +static int ccu_reset_deassert(struct reset_controller_dev *rcdev, + unsigned long id) +{ + struct ccu_reset *ccu = rcdev_to_ccu_reset(rcdev); + const struct ccu_reset_map *map = &ccu->reset_map[id]; + unsigned long flags; + u32 reg; + + spin_lock_irqsave(ccu->lock, flags); + + reg = readl(ccu->base + map->reg); + writel(reg | map->bit, ccu->base + map->reg); + + spin_unlock_irqrestore(ccu->lock, flags); + + return 0; +} + +const struct reset_control_ops ccu_reset_ops = { + .assert = ccu_reset_assert, + .deassert = ccu_reset_deassert, +}; diff --git a/drivers/clk/sunxi-ng/ccu_reset.h b/drivers/clk/sunxi-ng/ccu_reset.h new file mode 100644 index 000000000000..36a4679210bd --- /dev/null +++ b/drivers/clk/sunxi-ng/ccu_reset.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2016 Maxime Ripard. All rights reserved. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + */ + +#ifndef _CCU_RESET_H_ +#define _CCU_RESET_H_ + +#include + +struct ccu_reset_map { + u16 reg; + u32 bit; +}; + + +struct ccu_reset { + void __iomem *base; + struct ccu_reset_map *reset_map; + spinlock_t *lock; + + struct reset_controller_dev rcdev; +}; + +static inline struct ccu_reset *rcdev_to_ccu_reset(struct reset_controller_dev *rcdev) +{ + return container_of(rcdev, struct ccu_reset, rcdev); +} + +extern const struct reset_control_ops ccu_reset_ops; + +#endif /* _CCU_RESET_H_ */ -- cgit v1.2.3 From 89a3dfb787072438f72de95ff3fe7b58213e08c1 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Wed, 29 Jun 2016 21:05:24 +0200 Subject: clk: sunxi-ng: Add fractional lib Some clocks can be switched to a mode called fractional that have two fixed output rate you can choose from. Add a small library to deal with those clocks. Signed-off-by: Maxime Ripard Signed-off-by: Michael Turquette Link: lkml.kernel.org/r/20160629190535.11855-4-maxime.ripard@free-electrons.com --- drivers/clk/sunxi-ng/Kconfig | 9 ++++ drivers/clk/sunxi-ng/Makefile | 3 ++ drivers/clk/sunxi-ng/ccu_frac.c | 110 ++++++++++++++++++++++++++++++++++++++++ drivers/clk/sunxi-ng/ccu_frac.h | 53 +++++++++++++++++++ 4 files changed, 175 insertions(+) create mode 100644 drivers/clk/sunxi-ng/ccu_frac.c create mode 100644 drivers/clk/sunxi-ng/ccu_frac.h diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-ng/Kconfig index df5b2768d8b4..3d117d7a3621 100644 --- a/drivers/clk/sunxi-ng/Kconfig +++ b/drivers/clk/sunxi-ng/Kconfig @@ -1,3 +1,12 @@ config SUNXI_CCU bool "Clock support for Allwinner SoCs" default ARCH_SUNXI + +if SUNXI_CCU + +# Base clock types + +config SUNXI_CCU_FRAC + bool + +endif diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile index 886d0786ca51..46f417cb682a 100644 --- a/drivers/clk/sunxi-ng/Makefile +++ b/drivers/clk/sunxi-ng/Makefile @@ -1,3 +1,6 @@ # Common objects obj-$(CONFIG_SUNXI_CCU) += ccu_common.o obj-$(CONFIG_SUNXI_CCU) += ccu_reset.o + +# Base clock types +obj-$(CONFIG_SUNXI_CCU_FRAC) += ccu_frac.o diff --git a/drivers/clk/sunxi-ng/ccu_frac.c b/drivers/clk/sunxi-ng/ccu_frac.c new file mode 100644 index 000000000000..5c4b10cd15b5 --- /dev/null +++ b/drivers/clk/sunxi-ng/ccu_frac.c @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2016 Maxime Ripard + * Maxime Ripard + * + * 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 "ccu_frac.h" + +bool ccu_frac_helper_is_enabled(struct ccu_common *common, + struct _ccu_frac *cf) +{ + if (!(common->features & CCU_FEATURE_FRACTIONAL)) + return false; + + return !(readl(common->base + common->reg) & cf->enable); +} + +void ccu_frac_helper_enable(struct ccu_common *common, + struct _ccu_frac *cf) +{ + unsigned long flags; + u32 reg; + + if (!(common->features & CCU_FEATURE_FRACTIONAL)) + return; + + spin_lock_irqsave(common->lock, flags); + reg = readl(common->base + common->reg); + writel(reg & ~cf->enable, common->base + common->reg); + spin_unlock_irqrestore(common->lock, flags); +} + +void ccu_frac_helper_disable(struct ccu_common *common, + struct _ccu_frac *cf) +{ + unsigned long flags; + u32 reg; + + if (!(common->features & CCU_FEATURE_FRACTIONAL)) + return; + + spin_lock_irqsave(common->lock, flags); + reg = readl(common->base + common->reg); + writel(reg | cf->enable, common->base + common->reg); + spin_unlock_irqrestore(common->lock, flags); +} + +bool ccu_frac_helper_has_rate(struct ccu_common *common, + struct _ccu_frac *cf, + unsigned long rate) +{ + if (!(common->features & CCU_FEATURE_FRACTIONAL)) + return false; + + return (cf->rates[0] == rate) || (cf->rates[1] == rate); +} + +unsigned long ccu_frac_helper_read_rate(struct ccu_common *common, + struct _ccu_frac *cf) +{ + u32 reg; + + printk("%s: Read fractional\n", clk_hw_get_name(&common->hw)); + + if (!(common->features & CCU_FEATURE_FRACTIONAL)) + return 0; + + printk("%s: clock is fractional (rates %lu and %lu)\n", + clk_hw_get_name(&common->hw), cf->rates[0], cf->rates[1]); + + reg = readl(common->base + common->reg); + + printk("%s: clock reg is 0x%x (select is 0x%x)\n", + clk_hw_get_name(&common->hw), reg, cf->select); + + return (reg & cf->select) ? cf->rates[1] : cf->rates[0]; +} + +int ccu_frac_helper_set_rate(struct ccu_common *common, + struct _ccu_frac *cf, + unsigned long rate) +{ + unsigned long flags; + u32 reg, sel; + + if (!(common->features & CCU_FEATURE_FRACTIONAL)) + return -EINVAL; + + if (cf->rates[0] == rate) + sel = 0; + else if (cf->rates[1] == rate) + sel = cf->select; + else + return -EINVAL; + + spin_lock_irqsave(common->lock, flags); + reg = readl(common->base + common->reg); + reg &= ~cf->select; + writel(reg | sel, common->base + common->reg); + spin_unlock_irqrestore(common->lock, flags); + + return 0; +} diff --git a/drivers/clk/sunxi-ng/ccu_frac.h b/drivers/clk/sunxi-ng/ccu_frac.h new file mode 100644 index 000000000000..e4c670b1cdfe --- /dev/null +++ b/drivers/clk/sunxi-ng/ccu_frac.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2016 Maxime Ripard. All rights reserved. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + */ + +#ifndef _CCU_FRAC_H_ +#define _CCU_FRAC_H_ + +#include + +#include "ccu_common.h" + +struct _ccu_frac { + u32 enable; + u32 select; + + unsigned long rates[2]; +}; + +#define _SUNXI_CCU_FRAC(_enable, _select, _rate1, _rate2) \ + { \ + .enable = _enable, \ + .select = _select, \ + .rates = { _rate1, _rate2 }, \ + } + +bool ccu_frac_helper_is_enabled(struct ccu_common *common, + struct _ccu_frac *cf); +void ccu_frac_helper_enable(struct ccu_common *common, + struct _ccu_frac *cf); +void ccu_frac_helper_disable(struct ccu_common *common, + struct _ccu_frac *cf); + +bool ccu_frac_helper_has_rate(struct ccu_common *common, + struct _ccu_frac *cf, + unsigned long rate); + +unsigned long ccu_frac_helper_read_rate(struct ccu_common *common, + struct _ccu_frac *cf); + +int ccu_frac_helper_set_rate(struct ccu_common *common, + struct _ccu_frac *cf, + unsigned long rate); + +#endif /* _CCU_FRAC_H_ */ -- cgit v1.2.3 From 1a7e7c388df10b2636e4ba18cc29ef740fbea6cc Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Wed, 29 Jun 2016 21:05:25 +0200 Subject: clk: sunxi-ng: Add gate clock support Some clocks in the Allwinner SoCs clocks unit are just simple gates. Add support for those clocks. Since it's a feature that can also be found in more complex clocks, provide a bunch of helpers that can be reused later on. Signed-off-by: Maxime Ripard Signed-off-by: Michael Turquette Link: lkml.kernel.org/r/20160629190535.11855-5-maxime.ripard@free-electrons.com --- drivers/clk/sunxi-ng/Kconfig | 3 ++ drivers/clk/sunxi-ng/Makefile | 1 + drivers/clk/sunxi-ng/ccu_gate.c | 82 +++++++++++++++++++++++++++++++++++++++++ drivers/clk/sunxi-ng/ccu_gate.h | 52 ++++++++++++++++++++++++++ 4 files changed, 138 insertions(+) create mode 100644 drivers/clk/sunxi-ng/ccu_gate.c create mode 100644 drivers/clk/sunxi-ng/ccu_gate.h diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-ng/Kconfig index 3d117d7a3621..2f135c8a61b6 100644 --- a/drivers/clk/sunxi-ng/Kconfig +++ b/drivers/clk/sunxi-ng/Kconfig @@ -9,4 +9,7 @@ if SUNXI_CCU config SUNXI_CCU_FRAC bool +config SUNXI_CCU_GATE + bool + endif diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile index 46f417cb682a..48b885f2d8ff 100644 --- a/drivers/clk/sunxi-ng/Makefile +++ b/drivers/clk/sunxi-ng/Makefile @@ -4,3 +4,4 @@ obj-$(CONFIG_SUNXI_CCU) += ccu_reset.o # Base clock types obj-$(CONFIG_SUNXI_CCU_FRAC) += ccu_frac.o +obj-$(CONFIG_SUNXI_CCU_GATE) += ccu_gate.o diff --git a/drivers/clk/sunxi-ng/ccu_gate.c b/drivers/clk/sunxi-ng/ccu_gate.c new file mode 100644 index 000000000000..8a81f9d4a89f --- /dev/null +++ b/drivers/clk/sunxi-ng/ccu_gate.c @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2016 Maxime Ripard + * Maxime Ripard + * + * 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 "ccu_gate.h" + +void ccu_gate_helper_disable(struct ccu_common *common, u32 gate) +{ + unsigned long flags; + u32 reg; + + if (!gate) + return; + + spin_lock_irqsave(common->lock, flags); + + reg = readl(common->base + common->reg); + writel(reg & ~gate, common->base + common->reg); + + spin_unlock_irqrestore(common->lock, flags); +} + +static void ccu_gate_disable(struct clk_hw *hw) +{ + struct ccu_gate *cg = hw_to_ccu_gate(hw); + + return ccu_gate_helper_disable(&cg->common, cg->enable); +} + +int ccu_gate_helper_enable(struct ccu_common *common, u32 gate) +{ + unsigned long flags; + u32 reg; + + if (!gate) + return 0; + + spin_lock_irqsave(common->lock, flags); + + reg = readl(common->base + common->reg); + writel(reg | gate, common->base + common->reg); + + spin_unlock_irqrestore(common->lock, flags); + + return 0; +} + +static int ccu_gate_enable(struct clk_hw *hw) +{ + struct ccu_gate *cg = hw_to_ccu_gate(hw); + + return ccu_gate_helper_enable(&cg->common, cg->enable); +} + +int ccu_gate_helper_is_enabled(struct ccu_common *common, u32 gate) +{ + if (!gate) + return 1; + + return readl(common->base + common->reg) & gate; +} + +static int ccu_gate_is_enabled(struct clk_hw *hw) +{ + struct ccu_gate *cg = hw_to_ccu_gate(hw); + + return ccu_gate_helper_is_enabled(&cg->common, cg->enable); +} + +const struct clk_ops ccu_gate_ops = { + .disable = ccu_gate_disable, + .enable = ccu_gate_enable, + .is_enabled = ccu_gate_is_enabled, +}; diff --git a/drivers/clk/sunxi-ng/ccu_gate.h b/drivers/clk/sunxi-ng/ccu_gate.h new file mode 100644 index 000000000000..4466169bd2d7 --- /dev/null +++ b/drivers/clk/sunxi-ng/ccu_gate.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2016 Maxime Ripard. All rights reserved. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + */ + +#ifndef _CCU_GATE_H_ +#define _CCU_GATE_H_ + +#include + +#include "ccu_common.h" + +struct ccu_gate { + u32 enable; + + struct ccu_common common; +}; + +#define SUNXI_CCU_GATE(_struct, _name, _parent, _reg, _gate, _flags) \ + struct ccu_gate _struct = { \ + .enable = _gate, \ + .common = { \ + .reg = _reg, \ + .hw.init = CLK_HW_INIT(_name, \ + _parent, \ + &ccu_gate_ops, \ + _flags), \ + } \ + } + +static inline struct ccu_gate *hw_to_ccu_gate(struct clk_hw *hw) +{ + struct ccu_common *common = hw_to_ccu_common(hw); + + return container_of(common, struct ccu_gate, common); +} + +void ccu_gate_helper_disable(struct ccu_common *common, u32 gate); +int ccu_gate_helper_enable(struct ccu_common *common, u32 gate); +int ccu_gate_helper_is_enabled(struct ccu_common *common, u32 gate); + +extern const struct clk_ops ccu_gate_ops; + +#endif /* _CCU_GATE_H_ */ -- cgit v1.2.3 From 2a65ed42dca8721fb7aa397cc3c7321fbb3b7dba Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Wed, 29 Jun 2016 21:05:26 +0200 Subject: clk: sunxi-ng: Add mux clock support Some clocks in the Allwinner SoCs clocks unit are just muxes. However, those muxes might also be found in some other complicated clocks that would benefit from the code in there to deal with "advanced" features, like pre-dividers. Introduce a set of helpers to reduce the code duplication in such cases. Signed-off-by: Maxime Ripard Signed-off-by: Michael Turquette Link: lkml.kernel.org/r/20160629190535.11855-6-maxime.ripard@free-electrons.com --- drivers/clk/sunxi-ng/Kconfig | 3 + drivers/clk/sunxi-ng/Makefile | 1 + drivers/clk/sunxi-ng/ccu_mux.c | 187 +++++++++++++++++++++++++++++++++++++++++ drivers/clk/sunxi-ng/ccu_mux.h | 91 ++++++++++++++++++++ 4 files changed, 282 insertions(+) create mode 100644 drivers/clk/sunxi-ng/ccu_mux.c create mode 100644 drivers/clk/sunxi-ng/ccu_mux.h diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-ng/Kconfig index 2f135c8a61b6..4699a602e0c1 100644 --- a/drivers/clk/sunxi-ng/Kconfig +++ b/drivers/clk/sunxi-ng/Kconfig @@ -12,4 +12,7 @@ config SUNXI_CCU_FRAC config SUNXI_CCU_GATE bool +config SUNXI_CCU_MUX + bool + endif diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile index 48b885f2d8ff..eaa833721245 100644 --- a/drivers/clk/sunxi-ng/Makefile +++ b/drivers/clk/sunxi-ng/Makefile @@ -5,3 +5,4 @@ obj-$(CONFIG_SUNXI_CCU) += ccu_reset.o # Base clock types obj-$(CONFIG_SUNXI_CCU_FRAC) += ccu_frac.o obj-$(CONFIG_SUNXI_CCU_GATE) += ccu_gate.o +obj-$(CONFIG_SUNXI_CCU_MUX) += ccu_mux.o diff --git a/drivers/clk/sunxi-ng/ccu_mux.c b/drivers/clk/sunxi-ng/ccu_mux.c new file mode 100644 index 000000000000..58fc36e7dcce --- /dev/null +++ b/drivers/clk/sunxi-ng/ccu_mux.c @@ -0,0 +1,187 @@ +/* + * Copyright (C) 2016 Maxime Ripard + * Maxime Ripard + * + * 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 "ccu_gate.h" +#include "ccu_mux.h" + +void ccu_mux_helper_adjust_parent_for_prediv(struct ccu_common *common, + struct ccu_mux_internal *cm, + int parent_index, + unsigned long *parent_rate) +{ + u8 prediv = 1; + u32 reg; + + if (!((common->features & CCU_FEATURE_FIXED_PREDIV) || + (common->features & CCU_FEATURE_VARIABLE_PREDIV))) + return; + + reg = readl(common->base + common->reg); + if (parent_index < 0) { + parent_index = reg >> cm->shift; + parent_index &= (1 << cm->width) - 1; + } + + if (common->features & CCU_FEATURE_FIXED_PREDIV) + if (parent_index == cm->fixed_prediv.index) + prediv = cm->fixed_prediv.div; + + if (common->features & CCU_FEATURE_VARIABLE_PREDIV) + if (parent_index == cm->variable_prediv.index) { + u8 div; + + div = reg >> cm->variable_prediv.shift; + div &= (1 << cm->variable_prediv.width) - 1; + prediv = div + 1; + } + + *parent_rate = *parent_rate / prediv; +} + +int ccu_mux_helper_determine_rate(struct ccu_common *common, + struct ccu_mux_internal *cm, + struct clk_rate_request *req, + unsigned long (*round)(struct ccu_mux_internal *, + unsigned long, + unsigned long, + void *), + void *data) +{ + unsigned long best_parent_rate = 0, best_rate = 0; + struct clk_hw *best_parent, *hw = &common->hw; + unsigned int i; + + for (i = 0; i < clk_hw_get_num_parents(hw); i++) { + unsigned long tmp_rate, parent_rate; + struct clk_hw *parent; + + parent = clk_hw_get_parent_by_index(hw, i); + if (!parent) + continue; + + parent_rate = clk_hw_get_rate(parent); + ccu_mux_helper_adjust_parent_for_prediv(common, cm, i, + &parent_rate); + + tmp_rate = round(cm, clk_hw_get_rate(parent), req->rate, data); + if (tmp_rate == req->rate) { + best_parent = parent; + best_parent_rate = parent_rate; + best_rate = tmp_rate; + goto out; + } + + if ((req->rate - tmp_rate) < (req->rate - best_rate)) { + best_rate = tmp_rate; + best_parent_rate = parent_rate; + best_parent = parent; + } + } + + if (best_rate == 0) + return -EINVAL; + +out: + req->best_parent_hw = best_parent; + req->best_parent_rate = best_parent_rate; + req->rate = best_rate; + return 0; +} + +u8 ccu_mux_helper_get_parent(struct ccu_common *common, + struct ccu_mux_internal *cm) +{ + u32 reg; + u8 parent; + + reg = readl(common->base + common->reg); + parent = reg >> cm->shift; + parent &= (1 << cm->width) - 1; + + return parent; +} + +int ccu_mux_helper_set_parent(struct ccu_common *common, + struct ccu_mux_internal *cm, + u8 index) +{ + unsigned long flags; + u32 reg; + + spin_lock_irqsave(common->lock, flags); + + reg = readl(common->base + common->reg); + reg &= ~GENMASK(cm->width + cm->shift - 1, cm->shift); + writel(reg | (index << cm->shift), common->base + common->reg); + + spin_unlock_irqrestore(common->lock, flags); + + return 0; +} + +static void ccu_mux_disable(struct clk_hw *hw) +{ + struct ccu_mux *cm = hw_to_ccu_mux(hw); + + return ccu_gate_helper_disable(&cm->common, cm->enable); +} + +static int ccu_mux_enable(struct clk_hw *hw) +{ + struct ccu_mux *cm = hw_to_ccu_mux(hw); + + return ccu_gate_helper_enable(&cm->common, cm->enable); +} + +static int ccu_mux_is_enabled(struct clk_hw *hw) +{ + struct ccu_mux *cm = hw_to_ccu_mux(hw); + + return ccu_gate_helper_is_enabled(&cm->common, cm->enable); +} + +static u8 ccu_mux_get_parent(struct clk_hw *hw) +{ + struct ccu_mux *cm = hw_to_ccu_mux(hw); + + return ccu_mux_helper_get_parent(&cm->common, &cm->mux); +} + +static int ccu_mux_set_parent(struct clk_hw *hw, u8 index) +{ + struct ccu_mux *cm = hw_to_ccu_mux(hw); + + return ccu_mux_helper_set_parent(&cm->common, &cm->mux, index); +} + +static unsigned long ccu_mux_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct ccu_mux *cm = hw_to_ccu_mux(hw); + + ccu_mux_helper_adjust_parent_for_prediv(&cm->common, &cm->mux, -1, + &parent_rate); + + return parent_rate; +} + +const struct clk_ops ccu_mux_ops = { + .disable = ccu_mux_disable, + .enable = ccu_mux_enable, + .is_enabled = ccu_mux_is_enabled, + + .get_parent = ccu_mux_get_parent, + .set_parent = ccu_mux_set_parent, + + .determine_rate = __clk_mux_determine_rate, + .recalc_rate = ccu_mux_recalc_rate, +}; diff --git a/drivers/clk/sunxi-ng/ccu_mux.h b/drivers/clk/sunxi-ng/ccu_mux.h new file mode 100644 index 000000000000..945082631e7d --- /dev/null +++ b/drivers/clk/sunxi-ng/ccu_mux.h @@ -0,0 +1,91 @@ +#ifndef _CCU_MUX_H_ +#define _CCU_MUX_H_ + +#include + +#include "ccu_common.h" + +struct ccu_mux_internal { + u8 shift; + u8 width; + + struct { + u8 index; + u8 div; + } fixed_prediv; + + struct { + u8 index; + u8 shift; + u8 width; + } variable_prediv; +}; + +#define SUNXI_CLK_MUX(_shift, _width) \ + { \ + .shift = _shift, \ + .width = _width, \ + } + +struct ccu_mux { + u16 reg; + u32 enable; + + struct ccu_mux_internal mux; + struct ccu_common common; +}; + +#define SUNXI_CCU_MUX(_struct, _name, _parents, _reg, _shift, _width, _flags) \ + struct ccu_mux _struct = { \ + .mux = SUNXI_CLK_MUX(_shift, _width), \ + .common = { \ + .reg = _reg, \ + .hw.init = CLK_HW_INIT_PARENTS(_name, \ + _parents, \ + &ccu_mux_ops, \ + _flags), \ + } \ + } + +#define SUNXI_CCU_MUX_WITH_GATE(_struct, _name, _parents, _reg, \ + _shift, _width, _gate, _flags) \ + struct ccu_mux _struct = { \ + .enable = _gate, \ + .mux = SUNXI_CLK_MUX(_shift, _width), \ + .common = { \ + .reg = _reg, \ + .hw.init = CLK_HW_INIT_PARENTS(_name, \ + _parents, \ + &ccu_mux_ops, \ + _flags), \ + } \ + } + +static inline struct ccu_mux *hw_to_ccu_mux(struct clk_hw *hw) +{ + struct ccu_common *common = hw_to_ccu_common(hw); + + return container_of(common, struct ccu_mux, common); +} + +extern const struct clk_ops ccu_mux_ops; + +void ccu_mux_helper_adjust_parent_for_prediv(struct ccu_common *common, + struct ccu_mux_internal *cm, + int parent_index, + unsigned long *parent_rate); +int ccu_mux_helper_determine_rate(struct ccu_common *common, + struct ccu_mux_internal *cm, + struct clk_rate_request *req, + unsigned long (*round)(struct ccu_mux_internal *, + unsigned long, + unsigned long, + void *), + void *data); +u8 ccu_mux_helper_get_parent(struct ccu_common *common, + struct ccu_mux_internal *cm); +int ccu_mux_helper_set_parent(struct ccu_common *common, + struct ccu_mux_internal *cm, + u8 index); + +#endif /* _CCU_MUX_H_ */ -- cgit v1.2.3 From 6f9f7f876ec050ae1c352a6561616fee050dfc42 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Wed, 29 Jun 2016 21:05:27 +0200 Subject: clk: sunxi-ng: Add phase clock support Add support for the clocks in the CCU that introduce a phase shift from their parent clock. Signed-off-by: Maxime Ripard Signed-off-by: Michael Turquette Link: lkml.kernel.org/r/20160629190535.11855-7-maxime.ripard@free-electrons.com --- drivers/clk/sunxi-ng/Kconfig | 3 + drivers/clk/sunxi-ng/Makefile | 1 + drivers/clk/sunxi-ng/ccu_phase.c | 126 +++++++++++++++++++++++++++++++++++++++ drivers/clk/sunxi-ng/ccu_phase.h | 50 ++++++++++++++++ 4 files changed, 180 insertions(+) create mode 100644 drivers/clk/sunxi-ng/ccu_phase.c create mode 100644 drivers/clk/sunxi-ng/ccu_phase.h diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-ng/Kconfig index 4699a602e0c1..3a3bc4368a2a 100644 --- a/drivers/clk/sunxi-ng/Kconfig +++ b/drivers/clk/sunxi-ng/Kconfig @@ -15,4 +15,7 @@ config SUNXI_CCU_GATE config SUNXI_CCU_MUX bool +config SUNXI_CCU_PHASE + bool + endif diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile index eaa833721245..a0c53c56ebfe 100644 --- a/drivers/clk/sunxi-ng/Makefile +++ b/drivers/clk/sunxi-ng/Makefile @@ -6,3 +6,4 @@ obj-$(CONFIG_SUNXI_CCU) += ccu_reset.o obj-$(CONFIG_SUNXI_CCU_FRAC) += ccu_frac.o obj-$(CONFIG_SUNXI_CCU_GATE) += ccu_gate.o obj-$(CONFIG_SUNXI_CCU_MUX) += ccu_mux.o +obj-$(CONFIG_SUNXI_CCU_PHASE) += ccu_phase.o diff --git a/drivers/clk/sunxi-ng/ccu_phase.c b/drivers/clk/sunxi-ng/ccu_phase.c new file mode 100644 index 000000000000..400c58ad72fd --- /dev/null +++ b/drivers/clk/sunxi-ng/ccu_phase.c @@ -0,0 +1,126 @@ +/* + * Copyright (C) 2016 Maxime Ripard + * Maxime Ripard + * + * 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 "ccu_phase.h" + +static int ccu_phase_get_phase(struct clk_hw *hw) +{ + struct ccu_phase *phase = hw_to_ccu_phase(hw); + struct clk_hw *parent, *grandparent; + unsigned int parent_rate, grandparent_rate; + u16 step, parent_div; + u32 reg; + u8 delay; + + reg = readl(phase->common.base + phase->common.reg); + delay = (reg >> phase->shift); + delay &= (1 << phase->width) - 1; + + if (!delay) + return 180; + + /* Get our parent clock, it's the one that can adjust its rate */ + parent = clk_hw_get_parent(hw); + if (!parent) + return -EINVAL; + + /* And its rate */ + parent_rate = clk_hw_get_rate(parent); + if (!parent_rate) + return -EINVAL; + + /* Now, get our parent's parent (most likely some PLL) */ + grandparent = clk_hw_get_parent(parent); + if (!grandparent) + return -EINVAL; + + /* And its rate */ + grandparent_rate = clk_hw_get_rate(grandparent); + if (!grandparent_rate) + return -EINVAL; + + /* Get our parent clock divider */ + parent_div = grandparent_rate / parent_rate; + + step = DIV_ROUND_CLOSEST(360, parent_div); + return delay * step; +} + +static int ccu_phase_set_phase(struct clk_hw *hw, int degrees) +{ + struct ccu_phase *phase = hw_to_ccu_phase(hw); + struct clk_hw *parent, *grandparent; + unsigned int parent_rate, grandparent_rate; + unsigned long flags; + u32 reg; + u8 delay; + + /* Get our parent clock, it's the one that can adjust its rate */ + parent = clk_hw_get_parent(hw); + if (!parent) + return -EINVAL; + + /* And its rate */ + parent_rate = clk_hw_get_rate(parent); + if (!parent_rate) + return -EINVAL; + + /* Now, get our parent's parent (most likely some PLL) */ + grandparent = clk_hw_get_parent(parent); + if (!grandparent) + return -EINVAL; + + /* And its rate */ + grandparent_rate = clk_hw_get_rate(grandparent); + if (!grandparent_rate) + return -EINVAL; + + if (degrees != 180) { + u16 step, parent_div; + + /* Get our parent divider */ + parent_div = grandparent_rate / parent_rate; + + /* + * We can only outphase the clocks by multiple of the + * PLL's period. + * + * Since our parent clock is only a divider, and the + * formula to get the outphasing in degrees is deg = + * 360 * delta / period + * + * If we simplify this formula, we can see that the + * only thing that we're concerned about is the number + * of period we want to outphase our clock from, and + * the divider set by our parent clock. + */ + step = DIV_ROUND_CLOSEST(360, parent_div); + delay = DIV_ROUND_CLOSEST(degrees, step); + } else { + delay = 0; + } + + spin_lock_irqsave(phase->common.lock, flags); + reg = readl(phase->common.base + phase->common.reg); + reg &= ~GENMASK(phase->width + phase->shift - 1, phase->shift); + writel(reg | (delay << phase->shift), + phase->common.base + phase->common.reg); + spin_unlock_irqrestore(phase->common.lock, flags); + + return 0; +} + +const struct clk_ops ccu_phase_ops = { + .get_phase = ccu_phase_get_phase, + .set_phase = ccu_phase_set_phase, +}; diff --git a/drivers/clk/sunxi-ng/ccu_phase.h b/drivers/clk/sunxi-ng/ccu_phase.h new file mode 100644 index 000000000000..75a091a4c565 --- /dev/null +++ b/drivers/clk/sunxi-ng/ccu_phase.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2016 Maxime Ripard. All rights reserved. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + */ + +#ifndef _CCU_PHASE_H_ +#define _CCU_PHASE_H_ + +#include + +#include "ccu_common.h" + +struct ccu_phase { + u8 shift; + u8 width; + + struct ccu_common common; +}; + +#define SUNXI_CCU_PHASE(_struct, _name, _parent, _reg, _shift, _width, _flags) \ + struct ccu_phase _struct = { \ + .shift = _shift, \ + .width = _width, \ + .common = { \ + .reg = _reg, \ + .hw.init = CLK_HW_INIT(_name, \ + _parent, \ + &ccu_phase_ops, \ + _flags), \ + } \ + } + +static inline struct ccu_phase *hw_to_ccu_phase(struct clk_hw *hw) +{ + struct ccu_common *common = hw_to_ccu_common(hw); + + return container_of(common, struct ccu_phase, common); +} + +extern const struct clk_ops ccu_phase_ops; + +#endif /* _CCU_PHASE_H_ */ -- cgit v1.2.3 From e9b93213103fd442ed72802a1c3869f0939c3705 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Wed, 29 Jun 2016 21:05:28 +0200 Subject: clk: sunxi-ng: Add divider Add support for the various dividers (linear, table or pow-of-two based) found in the CCU. Signed-off-by: Maxime Ripard Signed-off-by: Michael Turquette Link: lkml.kernel.org/r/20160629190535.11855-8-maxime.ripard@free-electrons.com --- drivers/clk/sunxi-ng/Kconfig | 4 ++ drivers/clk/sunxi-ng/Makefile | 1 + drivers/clk/sunxi-ng/ccu_div.c | 136 +++++++++++++++++++++++++++++++++++++++++ drivers/clk/sunxi-ng/ccu_div.h | 133 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 274 insertions(+) create mode 100644 drivers/clk/sunxi-ng/ccu_div.c create mode 100644 drivers/clk/sunxi-ng/ccu_div.h diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-ng/Kconfig index 3a3bc4368a2a..7e65e776e7a8 100644 --- a/drivers/clk/sunxi-ng/Kconfig +++ b/drivers/clk/sunxi-ng/Kconfig @@ -6,6 +6,10 @@ if SUNXI_CCU # Base clock types +config SUNXI_CCU_DIV + bool + select SUNXI_CCU_MUX + config SUNXI_CCU_FRAC bool diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile index a0c53c56ebfe..4bc5b6168560 100644 --- a/drivers/clk/sunxi-ng/Makefile +++ b/drivers/clk/sunxi-ng/Makefile @@ -3,6 +3,7 @@ obj-$(CONFIG_SUNXI_CCU) += ccu_common.o obj-$(CONFIG_SUNXI_CCU) += ccu_reset.o # Base clock types +obj-$(CONFIG_SUNXI_CCU_DIV) += ccu_div.o obj-$(CONFIG_SUNXI_CCU_FRAC) += ccu_frac.o obj-$(CONFIG_SUNXI_CCU_GATE) += ccu_gate.o obj-$(CONFIG_SUNXI_CCU_MUX) += ccu_mux.o diff --git a/drivers/clk/sunxi-ng/ccu_div.c b/drivers/clk/sunxi-ng/ccu_div.c new file mode 100644 index 000000000000..8659b4cb6c20 --- /dev/null +++ b/drivers/clk/sunxi-ng/ccu_div.c @@ -0,0 +1,136 @@ +/* + * Copyright (C) 2016 Maxime Ripard + * Maxime Ripard + * + * 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 "ccu_gate.h" +#include "ccu_div.h" + +static unsigned long ccu_div_round_rate(struct ccu_mux_internal *mux, + unsigned long parent_rate, + unsigned long rate, + void *data) +{ + struct ccu_div *cd = data; + unsigned long val; + + /* + * We can't use divider_round_rate that assumes that there's + * several parents, while we might be called to evaluate + * several different parents. + */ + val = divider_get_val(rate, parent_rate, cd->div.table, cd->div.width, + cd->div.flags); + + return divider_recalc_rate(&cd->common.hw, parent_rate, val, + cd->div.table, cd->div.flags); +} + +static void ccu_div_disable(struct clk_hw *hw) +{ + struct ccu_div *cd = hw_to_ccu_div(hw); + + return ccu_gate_helper_disable(&cd->common, cd->enable); +} + +static int ccu_div_enable(struct clk_hw *hw) +{ + struct ccu_div *cd = hw_to_ccu_div(hw); + + return ccu_gate_helper_enable(&cd->common, cd->enable); +} + +static int ccu_div_is_enabled(struct clk_hw *hw) +{ + struct ccu_div *cd = hw_to_ccu_div(hw); + + return ccu_gate_helper_is_enabled(&cd->common, cd->enable); +} + +static unsigned long ccu_div_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct ccu_div *cd = hw_to_ccu_div(hw); + unsigned long val; + u32 reg; + + reg = readl(cd->common.base + cd->common.reg); + val = reg >> cd->div.shift; + val &= (1 << cd->div.width) - 1; + + ccu_mux_helper_adjust_parent_for_prediv(&cd->common, &cd->mux, -1, + &parent_rate); + + return divider_recalc_rate(hw, parent_rate, val, cd->div.table, + cd->div.flags); +} + +static int ccu_div_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) +{ + struct ccu_div *cd = hw_to_ccu_div(hw); + + return ccu_mux_helper_determine_rate(&cd->common, &cd->mux, + req, ccu_div_round_rate, cd); +} + +static int ccu_div_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct ccu_div *cd = hw_to_ccu_div(hw); + unsigned long flags; + unsigned long val; + u32 reg; + + ccu_mux_helper_adjust_parent_for_prediv(&cd->common, &cd->mux, -1, + &parent_rate); + + val = divider_get_val(rate, parent_rate, cd->div.table, cd->div.width, + cd->div.flags); + + spin_lock_irqsave(cd->common.lock, flags); + + reg = readl(cd->common.base + cd->common.reg); + reg &= ~GENMASK(cd->div.width + cd->div.shift - 1, cd->div.shift); + + writel(reg | (val << cd->div.shift), + cd->common.base + cd->common.reg); + + spin_unlock_irqrestore(cd->common.lock, flags); + + return 0; +} + +static u8 ccu_div_get_parent(struct clk_hw *hw) +{ + struct ccu_div *cd = hw_to_ccu_div(hw); + + return ccu_mux_helper_get_parent(&cd->common, &cd->mux); +} + +static int ccu_div_set_parent(struct clk_hw *hw, u8 index) +{ + struct ccu_div *cd = hw_to_ccu_div(hw); + + return ccu_mux_helper_set_parent(&cd->common, &cd->mux, index); +} + +const struct clk_ops ccu_div_ops = { + .disable = ccu_div_disable, + .enable = ccu_div_enable, + .is_enabled = ccu_div_is_enabled, + + .get_parent = ccu_div_get_parent, + .set_parent = ccu_div_set_parent, + + .determine_rate = ccu_div_determine_rate, + .recalc_rate = ccu_div_recalc_rate, + .set_rate = ccu_div_set_rate, +}; diff --git a/drivers/clk/sunxi-ng/ccu_div.h b/drivers/clk/sunxi-ng/ccu_div.h new file mode 100644 index 000000000000..653ade5769b3 --- /dev/null +++ b/drivers/clk/sunxi-ng/ccu_div.h @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2016 Maxime Ripard. All rights reserved. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + */ + +#ifndef _CCU_DIV_H_ +#define _CCU_DIV_H_ + +#include + +#include "ccu_common.h" +#include "ccu_mux.h" + +struct _ccu_div { + u8 shift; + u8 width; + + u32 flags; + + struct clk_div_table *table; +}; + +#define _SUNXI_CCU_DIV_TABLE_FLAGS(_shift, _width, _table, _flags) \ + { \ + .shift = _shift, \ + .width = _width, \ + .flags = _flags, \ + .table = _table, \ + } + +#define _SUNXI_CCU_DIV_FLAGS(_shift, _width, _flags) \ + _SUNXI_CCU_DIV_TABLE_FLAGS(_shift, _width, NULL, _flags) + +#define _SUNXI_CCU_DIV_TABLE(_shift, _width, _table) \ + _SUNXI_CCU_DIV_TABLE_FLAGS(_shift, _width, _table, 0) + +#define _SUNXI_CCU_DIV(_shift, _width) \ + _SUNXI_CCU_DIV_TABLE_FLAGS(_shift, _width, NULL, 0) + +struct ccu_div { + u32 enable; + + struct _ccu_div div; + struct ccu_mux_internal mux; + struct ccu_common common; +}; + +#define SUNXI_CCU_DIV_TABLE_WITH_GATE(_struct, _name, _parent, _reg, \ + _shift, _width, \ + _table, _gate, _flags) \ + struct ccu_div _struct = { \ + .div = _SUNXI_CCU_DIV_TABLE(_shift, _width, \ + _table), \ + .enable = _gate, \ + .common = { \ + .reg = _reg, \ + .hw.init = CLK_HW_INIT(_name, \ + _parent, \ + &ccu_div_ops, \ + _flags), \ + } \ + } + + +#define SUNXI_CCU_DIV_TABLE(_struct, _name, _parent, _reg, \ + _shift, _width, \ + _table, _flags) \ + SUNXI_CCU_DIV_TABLE_WITH_GATE(_struct, _name, _parent, _reg, \ + _shift, _width, _table, 0, \ + _flags) + +#define SUNXI_CCU_M_WITH_MUX_GATE(_struct, _name, _parents, _reg, \ + _mshift, _mwidth, _muxshift, _muxwidth, \ + _gate, _flags) \ + struct ccu_div _struct = { \ + .enable = _gate, \ + .div = _SUNXI_CCU_DIV(_mshift, _mwidth), \ + .mux = SUNXI_CLK_MUX(_muxshift, _muxwidth), \ + .common = { \ + .reg = _reg, \ + .hw.init = CLK_HW_INIT_PARENTS(_name, \ + _parents, \ + &ccu_div_ops, \ + _flags), \ + }, \ + } + +#define SUNXI_CCU_M_WITH_MUX(_struct, _name, _parents, _reg, \ + _mshift, _mwidth, _muxshift, _muxwidth, \ + _flags) \ + SUNXI_CCU_M_WITH_MUX_GATE(_struct, _name, _parents, _reg, \ + _mshift, _mwidth, _muxshift, _muxwidth, \ + 0, _flags) + + +#define SUNXI_CCU_M_WITH_GATE(_struct, _name, _parent, _reg, \ + _mshift, _mwidth, _gate, \ + _flags) \ + struct ccu_div _struct = { \ + .enable = _gate, \ + .div = _SUNXI_CCU_DIV(_mshift, _mwidth), \ + .common = { \ + .reg = _reg, \ + .hw.init = CLK_HW_INIT(_name, \ + _parent, \ + &ccu_div_ops, \ + _flags), \ + }, \ + } + +#define SUNXI_CCU_M(_struct, _name, _parent, _reg, _mshift, _mwidth, \ + _flags) \ + SUNXI_CCU_M_WITH_GATE(_struct, _name, _parent, _reg, \ + _mshift, _mwidth, 0, _flags) + +static inline struct ccu_div *hw_to_ccu_div(struct clk_hw *hw) +{ + struct ccu_common *common = hw_to_ccu_common(hw); + + return container_of(common, struct ccu_div, common); +} + +extern const struct clk_ops ccu_div_ops; + +#endif /* _CCU_DIV_H_ */ -- cgit v1.2.3 From 2ab836db5097427c3bfa58f9bd7230513c2f3665 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Wed, 29 Jun 2016 21:05:29 +0200 Subject: clk: sunxi-ng: Add M-P factor clock support Introduce support for the clocks that combine a linear divider and a power-of-two based one. Signed-off-by: Maxime Ripard Signed-off-by: Michael Turquette Link: lkml.kernel.org/r/20160629190535.11855-9-maxime.ripard@free-electrons.com --- drivers/clk/sunxi-ng/Kconfig | 7 ++ drivers/clk/sunxi-ng/Makefile | 3 + drivers/clk/sunxi-ng/ccu_mp.c | 158 ++++++++++++++++++++++++++++++++++++++++++ drivers/clk/sunxi-ng/ccu_mp.h | 77 ++++++++++++++++++++ 4 files changed, 245 insertions(+) create mode 100644 drivers/clk/sunxi-ng/ccu_mp.c create mode 100644 drivers/clk/sunxi-ng/ccu_mp.h diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-ng/Kconfig index 7e65e776e7a8..fc970b5a28c6 100644 --- a/drivers/clk/sunxi-ng/Kconfig +++ b/drivers/clk/sunxi-ng/Kconfig @@ -22,4 +22,11 @@ config SUNXI_CCU_MUX config SUNXI_CCU_PHASE bool +# Multi-factor clocks + +config SUNXI_CCU_MP + bool + select SUNXI_CCU_GATE + select SUNXI_CCU_MUX + endif diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile index 4bc5b6168560..501dec9451f4 100644 --- a/drivers/clk/sunxi-ng/Makefile +++ b/drivers/clk/sunxi-ng/Makefile @@ -8,3 +8,6 @@ obj-$(CONFIG_SUNXI_CCU_FRAC) += ccu_frac.o obj-$(CONFIG_SUNXI_CCU_GATE) += ccu_gate.o obj-$(CONFIG_SUNXI_CCU_MUX) += ccu_mux.o obj-$(CONFIG_SUNXI_CCU_PHASE) += ccu_phase.o + +# Multi-factor clocks +obj-$(CONFIG_SUNXI_CCU_MP) += ccu_mp.o diff --git a/drivers/clk/sunxi-ng/ccu_mp.c b/drivers/clk/sunxi-ng/ccu_mp.c new file mode 100644 index 000000000000..cbf33ef5faa9 --- /dev/null +++ b/drivers/clk/sunxi-ng/ccu_mp.c @@ -0,0 +1,158 @@ +/* + * Copyright (C) 2016 Maxime Ripard + * Maxime Ripard + * + * 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 "ccu_gate.h" +#include "ccu_mp.h" + +static void ccu_mp_find_best(unsigned long parent, unsigned long rate, + unsigned int max_m, unsigned int max_p, + unsigned int *m, unsigned int *p) +{ + unsigned long best_rate = 0; + unsigned int best_m = 0, best_p = 0; + unsigned int _m, _p; + + for (_p = 0; _p <= max_p; _p++) { + for (_m = 1; _m <= max_m; _m++) { + unsigned long tmp_rate = (parent >> _p) / _m; + + if (tmp_rate > rate) + continue; + + if ((rate - tmp_rate) < (rate - best_rate)) { + best_rate = tmp_rate; + best_m = _m; + best_p = _p; + } + } + } + + *m = best_m; + *p = best_p; +} + +static unsigned long ccu_mp_round_rate(struct ccu_mux_internal *mux, + unsigned long parent_rate, + unsigned long rate, + void *data) +{ + struct ccu_mp *cmp = data; + unsigned int m, p; + + ccu_mp_find_best(parent_rate, rate, + 1 << cmp->m.width, (1 << cmp->p.width) - 1, + &m, &p); + + return (parent_rate >> p) / m; +} + +static void ccu_mp_disable(struct clk_hw *hw) +{ + struct ccu_mp *cmp = hw_to_ccu_mp(hw); + + return ccu_gate_helper_disable(&cmp->common, cmp->enable); +} + +static int ccu_mp_enable(struct clk_hw *hw) +{ + struct ccu_mp *cmp = hw_to_ccu_mp(hw); + + return ccu_gate_helper_enable(&cmp->common, cmp->enable); +} + +static int ccu_mp_is_enabled(struct clk_hw *hw) +{ + struct ccu_mp *cmp = hw_to_ccu_mp(hw); + + return ccu_gate_helper_is_enabled(&cmp->common, cmp->enable); +} + +static unsigned long ccu_mp_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct ccu_mp *cmp = hw_to_ccu_mp(hw); + unsigned int m, p; + u32 reg; + + reg = readl(cmp->common.base + cmp->common.reg); + + m = reg >> cmp->m.shift; + m &= (1 << cmp->m.width) - 1; + + p = reg >> cmp->p.shift; + p &= (1 << cmp->p.width) - 1; + + return (parent_rate >> p) / (m + 1); +} + +static int ccu_mp_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) +{ + struct ccu_mp *cmp = hw_to_ccu_mp(hw); + + return ccu_mux_helper_determine_rate(&cmp->common, &cmp->mux, + req, ccu_mp_round_rate, cmp); +} + +static int ccu_mp_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct ccu_mp *cmp = hw_to_ccu_mp(hw); + unsigned long flags; + unsigned int m, p; + u32 reg; + + ccu_mp_find_best(parent_rate, rate, + 1 << cmp->m.width, (1 << cmp->p.width) - 1, + &m, &p); + + + spin_lock_irqsave(cmp->common.lock, flags); + + reg = readl(cmp->common.base + cmp->common.reg); + reg &= ~GENMASK(cmp->m.width + cmp->m.shift - 1, cmp->m.shift); + reg &= ~GENMASK(cmp->p.width + cmp->p.shift - 1, cmp->p.shift); + + writel(reg | (p << cmp->p.shift) | ((m - 1) << cmp->m.shift), + cmp->common.base + cmp->common.reg); + + spin_unlock_irqrestore(cmp->common.lock, flags); + + return 0; +} + +static u8 ccu_mp_get_parent(struct clk_hw *hw) +{ + struct ccu_mp *cmp = hw_to_ccu_mp(hw); + + return ccu_mux_helper_get_parent(&cmp->common, &cmp->mux); +} + +static int ccu_mp_set_parent(struct clk_hw *hw, u8 index) +{ + struct ccu_mp *cmp = hw_to_ccu_mp(hw); + + return ccu_mux_helper_set_parent(&cmp->common, &cmp->mux, index); +} + +const struct clk_ops ccu_mp_ops = { + .disable = ccu_mp_disable, + .enable = ccu_mp_enable, + .is_enabled = ccu_mp_is_enabled, + + .get_parent = ccu_mp_get_parent, + .set_parent = ccu_mp_set_parent, + + .determine_rate = ccu_mp_determine_rate, + .recalc_rate = ccu_mp_recalc_rate, + .set_rate = ccu_mp_set_rate, +}; diff --git a/drivers/clk/sunxi-ng/ccu_mp.h b/drivers/clk/sunxi-ng/ccu_mp.h new file mode 100644 index 000000000000..3cf12bf95962 --- /dev/null +++ b/drivers/clk/sunxi-ng/ccu_mp.h @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2016 Maxime Ripard. All rights reserved. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + */ + +#ifndef _CCU_MP_H_ +#define _CCU_MP_H_ + +#include + +#include "ccu_common.h" +#include "ccu_div.h" +#include "ccu_mult.h" +#include "ccu_mux.h" + +/* + * struct ccu_mp - Definition of an M-P clock + * + * Clocks based on the formula parent >> P / M + */ +struct ccu_mp { + u32 enable; + + struct _ccu_div m; + struct _ccu_div p; + struct ccu_mux_internal mux; + struct ccu_common common; +}; + +#define SUNXI_CCU_MP_WITH_MUX_GATE(_struct, _name, _parents, _reg, \ + _mshift, _mwidth, \ + _pshift, _pwidth, \ + _muxshift, _muxwidth, \ + _gate, _flags) \ + struct ccu_mp _struct = { \ + .enable = _gate, \ + .m = _SUNXI_CCU_DIV(_mshift, _mwidth), \ + .p = _SUNXI_CCU_DIV(_pshift, _pwidth), \ + .mux = SUNXI_CLK_MUX(_muxshift, _muxwidth), \ + .common = { \ + .reg = _reg, \ + .hw.init = CLK_HW_INIT_PARENTS(_name, \ + _parents, \ + &ccu_mp_ops, \ + _flags), \ + } \ + } + +#define SUNXI_CCU_MP_WITH_MUX(_struct, _name, _parents, _reg, \ + _mshift, _mwidth, \ + _pshift, _pwidth, \ + _muxshift, _muxwidth, \ + _flags) \ + SUNXI_CCU_MP_WITH_MUX_GATE(_struct, _name, _parents, _reg, \ + _mshift, _mwidth, \ + _pshift, _pwidth, \ + _muxshift, _muxwidth, \ + 0, _flags) + +static inline struct ccu_mp *hw_to_ccu_mp(struct clk_hw *hw) +{ + struct ccu_common *common = hw_to_ccu_common(hw); + + return container_of(common, struct ccu_mp, common); +} + +extern const struct clk_ops ccu_mp_ops; + +#endif /* _CCU_MP_H_ */ -- cgit v1.2.3 From adbfb0056e03d556b98ffe93da0d7126bd630096 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Wed, 29 Jun 2016 21:05:30 +0200 Subject: clk: sunxi-ng: Add N-K-factor clock support Introduce support for clocks that use a combination of two linear multipliers. Signed-off-by: Maxime Ripard Signed-off-by: Michael Turquette Link: lkml.kernel.org/r/20160629190535.11855-10-maxime.ripard@free-electrons.com --- drivers/clk/sunxi-ng/Kconfig | 4 ++ drivers/clk/sunxi-ng/Makefile | 1 + drivers/clk/sunxi-ng/ccu_nk.c | 147 ++++++++++++++++++++++++++++++++++++++++++ drivers/clk/sunxi-ng/ccu_nk.h | 71 ++++++++++++++++++++ 4 files changed, 223 insertions(+) create mode 100644 drivers/clk/sunxi-ng/ccu_nk.c create mode 100644 drivers/clk/sunxi-ng/ccu_nk.h diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-ng/Kconfig index fc970b5a28c6..2eb0fc6b41d5 100644 --- a/drivers/clk/sunxi-ng/Kconfig +++ b/drivers/clk/sunxi-ng/Kconfig @@ -24,6 +24,10 @@ config SUNXI_CCU_PHASE # Multi-factor clocks +config SUNXI_CCU_NK + bool + select SUNXI_CCU_GATE + config SUNXI_CCU_MP bool select SUNXI_CCU_GATE diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile index 501dec9451f4..22951e60f876 100644 --- a/drivers/clk/sunxi-ng/Makefile +++ b/drivers/clk/sunxi-ng/Makefile @@ -10,4 +10,5 @@ obj-$(CONFIG_SUNXI_CCU_MUX) += ccu_mux.o obj-$(CONFIG_SUNXI_CCU_PHASE) += ccu_phase.o # Multi-factor clocks +obj-$(CONFIG_SUNXI_CCU_NK) += ccu_nk.o obj-$(CONFIG_SUNXI_CCU_MP) += ccu_mp.o diff --git a/drivers/clk/sunxi-ng/ccu_nk.c b/drivers/clk/sunxi-ng/ccu_nk.c new file mode 100644 index 000000000000..4470ffc8cf0d --- /dev/null +++ b/drivers/clk/sunxi-ng/ccu_nk.c @@ -0,0 +1,147 @@ +/* + * Copyright (C) 2016 Maxime Ripard + * Maxime Ripard + * + * 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 "ccu_gate.h" +#include "ccu_nk.h" + +void ccu_nk_find_best(unsigned long parent, unsigned long rate, + unsigned int max_n, unsigned int max_k, + unsigned int *n, unsigned int *k) +{ + unsigned long best_rate = 0; + unsigned int best_k = 0, best_n = 0; + unsigned int _k, _n; + + for (_k = 1; _k <= max_k; _k++) { + for (_n = 1; _n <= max_n; _n++) { + unsigned long tmp_rate = parent * _n * _k; + + if (tmp_rate > rate) + continue; + + if ((rate - tmp_rate) < (rate - best_rate)) { + best_rate = tmp_rate; + best_k = _k; + best_n = _n; + } + } + } + + *k = best_k; + *n = best_n; +} + +static void ccu_nk_disable(struct clk_hw *hw) +{ + struct ccu_nk *nk = hw_to_ccu_nk(hw); + + return ccu_gate_helper_disable(&nk->common, nk->enable); +} + +static int ccu_nk_enable(struct clk_hw *hw) +{ + struct ccu_nk *nk = hw_to_ccu_nk(hw); + + return ccu_gate_helper_enable(&nk->common, nk->enable); +} + +static int ccu_nk_is_enabled(struct clk_hw *hw) +{ + struct ccu_nk *nk = hw_to_ccu_nk(hw); + + return ccu_gate_helper_is_enabled(&nk->common, nk->enable); +} + +static unsigned long ccu_nk_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct ccu_nk *nk = hw_to_ccu_nk(hw); + unsigned long rate, n, k; + u32 reg; + + reg = readl(nk->common.base + nk->common.reg); + + n = reg >> nk->n.shift; + n &= (1 << nk->n.width) - 1; + + k = reg >> nk->k.shift; + k &= (1 << nk->k.width) - 1; + + rate = parent_rate * (n + 1) * (k + 1); + + if (nk->common.features & CCU_FEATURE_FIXED_POSTDIV) + rate /= nk->fixed_post_div; + + return rate; +} + +static long ccu_nk_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *parent_rate) +{ + struct ccu_nk *nk = hw_to_ccu_nk(hw); + unsigned int n, k; + + if (nk->common.features & CCU_FEATURE_FIXED_POSTDIV) + rate *= nk->fixed_post_div; + + ccu_nk_find_best(*parent_rate, rate, + 1 << nk->n.width, 1 << nk->k.width, + &n, &k); + + rate = *parent_rate * n * k; + if (nk->common.features & CCU_FEATURE_FIXED_POSTDIV) + rate = rate / nk->fixed_post_div; + + return rate; +} + +static int ccu_nk_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct ccu_nk *nk = hw_to_ccu_nk(hw); + unsigned long flags; + unsigned int n, k; + u32 reg; + + if (nk->common.features & CCU_FEATURE_FIXED_POSTDIV) + rate = rate * nk->fixed_post_div; + + ccu_nk_find_best(parent_rate, rate, + 1 << nk->n.width, 1 << nk->k.width, + &n, &k); + + spin_lock_irqsave(nk->common.lock, flags); + + reg = readl(nk->common.base + nk->common.reg); + reg &= ~GENMASK(nk->n.width + nk->n.shift - 1, nk->n.shift); + reg &= ~GENMASK(nk->k.width + nk->k.shift - 1, nk->k.shift); + + writel(reg | ((k - 1) << nk->k.shift) | ((n - 1) << nk->n.shift), + nk->common.base + nk->common.reg); + + spin_unlock_irqrestore(nk->common.lock, flags); + + ccu_helper_wait_for_lock(&nk->common, nk->lock); + + return 0; +} + +const struct clk_ops ccu_nk_ops = { + .disable = ccu_nk_disable, + .enable = ccu_nk_enable, + .is_enabled = ccu_nk_is_enabled, + + .recalc_rate = ccu_nk_recalc_rate, + .round_rate = ccu_nk_round_rate, + .set_rate = ccu_nk_set_rate, +}; diff --git a/drivers/clk/sunxi-ng/ccu_nk.h b/drivers/clk/sunxi-ng/ccu_nk.h new file mode 100644 index 000000000000..4b52da0c29fe --- /dev/null +++ b/drivers/clk/sunxi-ng/ccu_nk.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2016 Maxime Ripard. All rights reserved. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + */ + +#ifndef _CCU_NK_H_ +#define _CCU_NK_H_ + +#include + +#include "ccu_common.h" +#include "ccu_div.h" +#include "ccu_mult.h" + +/* + * struct ccu_nk - Definition of an N-K clock + * + * Clocks based on the formula parent * N * K + */ +struct ccu_nk { + u16 reg; + u32 enable; + u32 lock; + + struct _ccu_mult n; + struct _ccu_mult k; + + unsigned int fixed_post_div; + + struct ccu_common common; +}; + +#define SUNXI_CCU_NK_WITH_GATE_LOCK_POSTDIV(_struct, _name, _parent, _reg, \ + _nshift, _nwidth, \ + _kshift, _kwidth, \ + _gate, _lock, _postdiv, \ + _flags) \ + struct ccu_nk _struct = { \ + .enable = _gate, \ + .lock = _lock, \ + .k = _SUNXI_CCU_MULT(_kshift, _kwidth), \ + .n = _SUNXI_CCU_MULT(_nshift, _nwidth), \ + .fixed_post_div = _postdiv, \ + .common = { \ + .reg = _reg, \ + .features = CCU_FEATURE_FIXED_POSTDIV, \ + .hw.init = CLK_HW_INIT(_name, \ + _parent, \ + &ccu_nk_ops, \ + _flags), \ + }, \ + } + +static inline struct ccu_nk *hw_to_ccu_nk(struct clk_hw *hw) +{ + struct ccu_common *common = hw_to_ccu_common(hw); + + return container_of(common, struct ccu_nk, common); +} + +extern const struct clk_ops ccu_nk_ops; + +#endif /* _CCU_NK_H_ */ -- cgit v1.2.3 From 6174a1e24b0d13f85f64ff570e9d4efc6b0d6287 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Wed, 29 Jun 2016 21:05:31 +0200 Subject: clk: sunxi-ng: Add N-M-factor clock support Introduce support for clocks that multiply and divide using linear factors. Signed-off-by: Maxime Ripard Signed-off-by: Michael Turquette Link: lkml.kernel.org/r/20160629190535.11855-11-maxime.ripard@free-electrons.com --- drivers/clk/sunxi-ng/Kconfig | 6 +++ drivers/clk/sunxi-ng/Makefile | 1 + drivers/clk/sunxi-ng/ccu_nm.c | 114 ++++++++++++++++++++++++++++++++++++++++++ drivers/clk/sunxi-ng/ccu_nm.h | 91 +++++++++++++++++++++++++++++++++ 4 files changed, 212 insertions(+) create mode 100644 drivers/clk/sunxi-ng/ccu_nm.c create mode 100644 drivers/clk/sunxi-ng/ccu_nm.h diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-ng/Kconfig index 2eb0fc6b41d5..d8a5da270778 100644 --- a/drivers/clk/sunxi-ng/Kconfig +++ b/drivers/clk/sunxi-ng/Kconfig @@ -28,6 +28,12 @@ config SUNXI_CCU_NK bool select SUNXI_CCU_GATE +config SUNXI_CCU_NM + bool + select RATIONAL + select SUNXI_CCU_FRAC + select SUNXI_CCU_GATE + config SUNXI_CCU_MP bool select SUNXI_CCU_GATE diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile index 22951e60f876..7d2cd2a47a39 100644 --- a/drivers/clk/sunxi-ng/Makefile +++ b/drivers/clk/sunxi-ng/Makefile @@ -11,4 +11,5 @@ obj-$(CONFIG_SUNXI_CCU_PHASE) += ccu_phase.o # Multi-factor clocks obj-$(CONFIG_SUNXI_CCU_NK) += ccu_nk.o +obj-$(CONFIG_SUNXI_CCU_NM) += ccu_nm.o obj-$(CONFIG_SUNXI_CCU_MP) += ccu_mp.o diff --git a/drivers/clk/sunxi-ng/ccu_nm.c b/drivers/clk/sunxi-ng/ccu_nm.c new file mode 100644 index 000000000000..e35ddd8eec8b --- /dev/null +++ b/drivers/clk/sunxi-ng/ccu_nm.c @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2016 Maxime Ripard + * Maxime Ripard + * + * 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 "ccu_frac.h" +#include "ccu_gate.h" +#include "ccu_nm.h" + +static void ccu_nm_disable(struct clk_hw *hw) +{ + struct ccu_nm *nm = hw_to_ccu_nm(hw); + + return ccu_gate_helper_disable(&nm->common, nm->enable); +} + +static int ccu_nm_enable(struct clk_hw *hw) +{ + struct ccu_nm *nm = hw_to_ccu_nm(hw); + + return ccu_gate_helper_enable(&nm->common, nm->enable); +} + +static int ccu_nm_is_enabled(struct clk_hw *hw) +{ + struct ccu_nm *nm = hw_to_ccu_nm(hw); + + return ccu_gate_helper_is_enabled(&nm->common, nm->enable); +} + +static unsigned long ccu_nm_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct ccu_nm *nm = hw_to_ccu_nm(hw); + unsigned long n, m; + u32 reg; + + if (ccu_frac_helper_is_enabled(&nm->common, &nm->frac)) + return ccu_frac_helper_read_rate(&nm->common, &nm->frac); + + reg = readl(nm->common.base + nm->common.reg); + + n = reg >> nm->n.shift; + n &= (1 << nm->n.width) - 1; + + m = reg >> nm->m.shift; + m &= (1 << nm->m.width) - 1; + + return parent_rate * (n + 1) / (m + 1); +} + +static long ccu_nm_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *parent_rate) +{ + struct ccu_nm *nm = hw_to_ccu_nm(hw); + unsigned long n, m; + + rational_best_approximation(rate, *parent_rate, + 1 << nm->n.width, 1 << nm->m.width, + &n, &m); + + return *parent_rate * n / m; +} + +static int ccu_nm_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct ccu_nm *nm = hw_to_ccu_nm(hw); + unsigned long flags; + unsigned long n, m; + u32 reg; + + if (ccu_frac_helper_has_rate(&nm->common, &nm->frac, rate)) + return ccu_frac_helper_set_rate(&nm->common, &nm->frac, rate); + else + ccu_frac_helper_disable(&nm->common, &nm->frac); + + rational_best_approximation(rate, parent_rate, + 1 << nm->n.width, 1 << nm->m.width, + &n, &m); + + spin_lock_irqsave(nm->common.lock, flags); + + reg = readl(nm->common.base + nm->common.reg); + reg &= ~GENMASK(nm->n.width + nm->n.shift - 1, nm->n.shift); + reg &= ~GENMASK(nm->m.width + nm->m.shift - 1, nm->m.shift); + + writel(reg | ((m - 1) << nm->m.shift) | ((n - 1) << nm->n.shift), + nm->common.base + nm->common.reg); + + spin_unlock_irqrestore(nm->common.lock, flags); + + ccu_helper_wait_for_lock(&nm->common, nm->lock); + + return 0; +} + +const struct clk_ops ccu_nm_ops = { + .disable = ccu_nm_disable, + .enable = ccu_nm_enable, + .is_enabled = ccu_nm_is_enabled, + + .recalc_rate = ccu_nm_recalc_rate, + .round_rate = ccu_nm_round_rate, + .set_rate = ccu_nm_set_rate, +}; diff --git a/drivers/clk/sunxi-ng/ccu_nm.h b/drivers/clk/sunxi-ng/ccu_nm.h new file mode 100644 index 000000000000..0b7bcd33a2df --- /dev/null +++ b/drivers/clk/sunxi-ng/ccu_nm.h @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2016 Maxime Ripard. All rights reserved. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + */ + +#ifndef _CCU_NM_H_ +#define _CCU_NM_H_ + +#include + +#include "ccu_common.h" +#include "ccu_div.h" +#include "ccu_frac.h" +#include "ccu_mult.h" + +/* + * struct ccu_nm - Definition of an N-M clock + * + * Clocks based on the formula parent * N / M + */ +struct ccu_nm { + u32 enable; + u32 lock; + + struct _ccu_mult n; + struct _ccu_div m; + struct _ccu_frac frac; + + struct ccu_common common; +}; + +#define SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(_struct, _name, _parent, _reg, \ + _nshift, _nwidth, \ + _mshift, _mwidth, \ + _frac_en, _frac_sel, \ + _frac_rate_0, _frac_rate_1, \ + _gate, _lock, _flags) \ + struct ccu_nm _struct = { \ + .enable = _gate, \ + .lock = _lock, \ + .n = _SUNXI_CCU_MULT(_nshift, _nwidth), \ + .m = _SUNXI_CCU_DIV(_mshift, _mwidth), \ + .frac = _SUNXI_CCU_FRAC(_frac_en, _frac_sel, \ + _frac_rate_0, \ + _frac_rate_1), \ + .common = { \ + .reg = _reg, \ + .features = CCU_FEATURE_FRACTIONAL, \ + .hw.init = CLK_HW_INIT(_name, \ + _parent, \ + &ccu_nm_ops, \ + _flags), \ + }, \ + } + +#define SUNXI_CCU_NM_WITH_GATE_LOCK(_struct, _name, _parent, _reg, \ + _nshift, _nwidth, \ + _mshift, _mwidth, \ + _gate, _lock, _flags) \ + struct ccu_nm _struct = { \ + .enable = _gate, \ + .lock = _lock, \ + .n = _SUNXI_CCU_MULT(_nshift, _nwidth), \ + .m = _SUNXI_CCU_DIV(_mshift, _mwidth), \ + .common = { \ + .reg = _reg, \ + .hw.init = CLK_HW_INIT(_name, \ + _parent, \ + &ccu_nm_ops, \ + _flags), \ + }, \ + } + +static inline struct ccu_nm *hw_to_ccu_nm(struct clk_hw *hw) +{ + struct ccu_common *common = hw_to_ccu_common(hw); + + return container_of(common, struct ccu_nm, common); +} + +extern const struct clk_ops ccu_nm_ops; + +#endif /* _CCU_NM_H_ */ -- cgit v1.2.3 From df6561e60244c0283340286664b0baf67e846599 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Wed, 29 Jun 2016 21:05:32 +0200 Subject: clk: sunxi-ng: Add N-K-M Factor clock Introduce support for clocks that multiply and divide using two linear multipliers and one linear divider. Signed-off-by: Maxime Ripard Signed-off-by: Michael Turquette Link: lkml.kernel.org/r/20160629190535.11855-12-maxime.ripard@free-electrons.com --- drivers/clk/sunxi-ng/Kconfig | 5 ++ drivers/clk/sunxi-ng/Makefile | 1 + drivers/clk/sunxi-ng/ccu_nkm.c | 153 +++++++++++++++++++++++++++++++++++++++++ drivers/clk/sunxi-ng/ccu_nkm.h | 68 ++++++++++++++++++ 4 files changed, 227 insertions(+) create mode 100644 drivers/clk/sunxi-ng/ccu_nkm.c create mode 100644 drivers/clk/sunxi-ng/ccu_nkm.h diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-ng/Kconfig index d8a5da270778..4c571b86bfd1 100644 --- a/drivers/clk/sunxi-ng/Kconfig +++ b/drivers/clk/sunxi-ng/Kconfig @@ -28,6 +28,11 @@ config SUNXI_CCU_NK bool select SUNXI_CCU_GATE +config SUNXI_CCU_NKM + bool + select RATIONAL + select SUNXI_CCU_GATE + config SUNXI_CCU_NM bool select RATIONAL diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile index 7d2cd2a47a39..2d6fdca0d3cc 100644 --- a/drivers/clk/sunxi-ng/Makefile +++ b/drivers/clk/sunxi-ng/Makefile @@ -11,5 +11,6 @@ obj-$(CONFIG_SUNXI_CCU_PHASE) += ccu_phase.o # Multi-factor clocks obj-$(CONFIG_SUNXI_CCU_NK) += ccu_nk.o +obj-$(CONFIG_SUNXI_CCU_NKM) += ccu_nkm.o obj-$(CONFIG_SUNXI_CCU_NM) += ccu_nm.o obj-$(CONFIG_SUNXI_CCU_MP) += ccu_mp.o diff --git a/drivers/clk/sunxi-ng/ccu_nkm.c b/drivers/clk/sunxi-ng/ccu_nkm.c new file mode 100644 index 000000000000..2071822b1e9c --- /dev/null +++ b/drivers/clk/sunxi-ng/ccu_nkm.c @@ -0,0 +1,153 @@ +/* + * Copyright (C) 2016 Maxime Ripard + * Maxime Ripard + * + * 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 "ccu_gate.h" +#include "ccu_nkm.h" + +struct _ccu_nkm { + unsigned long n, max_n; + unsigned long k, max_k; + unsigned long m, max_m; +}; + +static void ccu_nkm_find_best(unsigned long parent, unsigned long rate, + struct _ccu_nkm *nkm) +{ + unsigned long best_rate = 0; + unsigned long best_n = 0, best_k = 0, best_m = 0; + unsigned long _n, _k, _m; + + for (_k = 1; _k <= nkm->max_k; _k++) { + unsigned long tmp_rate; + + rational_best_approximation(rate / _k, parent, + nkm->max_n, nkm->max_m, &_n, &_m); + + tmp_rate = parent * _n * _k / _m; + + if (tmp_rate > rate) + continue; + + if ((rate - tmp_rate) < (rate - best_rate)) { + best_rate = tmp_rate; + best_n = _n; + best_k = _k; + best_m = _m; + } + } + + nkm->n = best_n; + nkm->k = best_k; + nkm->m = best_m; +} + +static void ccu_nkm_disable(struct clk_hw *hw) +{ + struct ccu_nkm *nkm = hw_to_ccu_nkm(hw); + + return ccu_gate_helper_disable(&nkm->common, nkm->enable); +} + +static int ccu_nkm_enable(struct clk_hw *hw) +{ + struct ccu_nkm *nkm = hw_to_ccu_nkm(hw); + + return ccu_gate_helper_enable(&nkm->common, nkm->enable); +} + +static int ccu_nkm_is_enabled(struct clk_hw *hw) +{ + struct ccu_nkm *nkm = hw_to_ccu_nkm(hw); + + return ccu_gate_helper_is_enabled(&nkm->common, nkm->enable); +} + +static unsigned long ccu_nkm_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct ccu_nkm *nkm = hw_to_ccu_nkm(hw); + unsigned long n, m, k; + u32 reg; + + reg = readl(nkm->common.base + nkm->common.reg); + + n = reg >> nkm->n.shift; + n &= (1 << nkm->n.width) - 1; + + k = reg >> nkm->k.shift; + k &= (1 << nkm->k.width) - 1; + + m = reg >> nkm->m.shift; + m &= (1 << nkm->m.width) - 1; + + return parent_rate * (n + 1) * (k + 1) / (m + 1); +} + +static long ccu_nkm_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *parent_rate) +{ + struct ccu_nkm *nkm = hw_to_ccu_nkm(hw); + struct _ccu_nkm _nkm; + + _nkm.max_n = 1 << nkm->n.width; + _nkm.max_k = 1 << nkm->k.width; + _nkm.max_m = 1 << nkm->m.width; + + ccu_nkm_find_best(*parent_rate, rate, &_nkm); + + return *parent_rate * _nkm.n * _nkm.k / _nkm.m; +} + +static int ccu_nkm_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct ccu_nkm *nkm = hw_to_ccu_nkm(hw); + struct _ccu_nkm _nkm; + unsigned long flags; + u32 reg; + + _nkm.max_n = 1 << nkm->n.width; + _nkm.max_k = 1 << nkm->k.width; + _nkm.max_m = 1 << nkm->m.width; + + ccu_nkm_find_best(parent_rate, rate, &_nkm); + + spin_lock_irqsave(nkm->common.lock, flags); + + reg = readl(nkm->common.base + nkm->common.reg); + reg &= ~GENMASK(nkm->n.width + nkm->n.shift - 1, nkm->n.shift); + reg &= ~GENMASK(nkm->k.width + nkm->k.shift - 1, nkm->k.shift); + reg &= ~GENMASK(nkm->m.width + nkm->m.shift - 1, nkm->m.shift); + + reg |= (_nkm.n - 1) << nkm->n.shift; + reg |= (_nkm.k - 1) << nkm->k.shift; + reg |= (_nkm.m - 1) << nkm->m.shift; + + writel(reg, nkm->common.base + nkm->common.reg); + + spin_unlock_irqrestore(nkm->common.lock, flags); + + ccu_helper_wait_for_lock(&nkm->common, nkm->lock); + + return 0; +} + +const struct clk_ops ccu_nkm_ops = { + .disable = ccu_nkm_disable, + .enable = ccu_nkm_enable, + .is_enabled = ccu_nkm_is_enabled, + + .recalc_rate = ccu_nkm_recalc_rate, + .round_rate = ccu_nkm_round_rate, + .set_rate = ccu_nkm_set_rate, +}; diff --git a/drivers/clk/sunxi-ng/ccu_nkm.h b/drivers/clk/sunxi-ng/ccu_nkm.h new file mode 100644 index 000000000000..1936ac1c6b37 --- /dev/null +++ b/drivers/clk/sunxi-ng/ccu_nkm.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2016 Maxime Ripard. All rights reserved. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + */ + +#ifndef _CCU_NKM_H_ +#define _CCU_NKM_H_ + +#include + +#include "ccu_common.h" +#include "ccu_div.h" +#include "ccu_mult.h" + +/* + * struct ccu_nkm - Definition of an N-K-M clock + * + * Clocks based on the formula parent * N * K / M + */ +struct ccu_nkm { + u32 enable; + u32 lock; + + struct _ccu_mult n; + struct _ccu_mult k; + struct _ccu_div m; + + struct ccu_common common; +}; + +#define SUNXI_CCU_NKM_WITH_GATE_LOCK(_struct, _name, _parent, _reg, \ + _nshift, _nwidth, \ + _kshift, _kwidth, \ + _mshift, _mwidth, \ + _gate, _lock, _flags) \ + struct ccu_nkm _struct = { \ + .enable = _gate, \ + .lock = _lock, \ + .k = _SUNXI_CCU_MULT(_kshift, _kwidth), \ + .n = _SUNXI_CCU_MULT(_nshift, _nwidth), \ + .m = _SUNXI_CCU_DIV(_mshift, _mwidth), \ + .common = { \ + .reg = _reg, \ + .hw.init = CLK_HW_INIT(_name, \ + _parent, \ + &ccu_nkm_ops, \ + _flags), \ + }, \ + } + +static inline struct ccu_nkm *hw_to_ccu_nkm(struct clk_hw *hw) +{ + struct ccu_common *common = hw_to_ccu_common(hw); + + return container_of(common, struct ccu_nkm, common); +} + +extern const struct clk_ops ccu_nkm_ops; + +#endif /* _CCU_NKM_H_ */ -- cgit v1.2.3 From 4f728b5db7cb125af71e5da8154ac3b72653d819 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Wed, 29 Jun 2016 21:05:33 +0200 Subject: clk: sunxi-ng: Add N-K-M-P factor clock Introduce support for clocks that use a combination of two linear multipliers (N and K factors), one linear divider (M) and one power of two divider (P). Signed-off-by: Maxime Ripard Signed-off-by: Michael Turquette Link: lkml.kernel.org/r/20160629190535.11855-13-maxime.ripard@free-electrons.com --- drivers/clk/sunxi-ng/Kconfig | 5 ++ drivers/clk/sunxi-ng/Makefile | 1 + drivers/clk/sunxi-ng/ccu_nkmp.c | 167 ++++++++++++++++++++++++++++++++++++++++ drivers/clk/sunxi-ng/ccu_nkmp.h | 71 +++++++++++++++++ 4 files changed, 244 insertions(+) create mode 100644 drivers/clk/sunxi-ng/ccu_nkmp.c create mode 100644 drivers/clk/sunxi-ng/ccu_nkmp.h diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-ng/Kconfig index 4c571b86bfd1..24fc9e4cc546 100644 --- a/drivers/clk/sunxi-ng/Kconfig +++ b/drivers/clk/sunxi-ng/Kconfig @@ -33,6 +33,11 @@ config SUNXI_CCU_NKM select RATIONAL select SUNXI_CCU_GATE +config SUNXI_CCU_NKMP + bool + select RATIONAL + select SUNXI_CCU_GATE + config SUNXI_CCU_NM bool select RATIONAL diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile index 2d6fdca0d3cc..5c342cc698d2 100644 --- a/drivers/clk/sunxi-ng/Makefile +++ b/drivers/clk/sunxi-ng/Makefile @@ -12,5 +12,6 @@ obj-$(CONFIG_SUNXI_CCU_PHASE) += ccu_phase.o # Multi-factor clocks obj-$(CONFIG_SUNXI_CCU_NK) += ccu_nk.o obj-$(CONFIG_SUNXI_CCU_NKM) += ccu_nkm.o +obj-$(CONFIG_SUNXI_CCU_NKMP) += ccu_nkmp.o obj-$(CONFIG_SUNXI_CCU_NM) += ccu_nm.o obj-$(CONFIG_SUNXI_CCU_MP) += ccu_mp.o diff --git a/drivers/clk/sunxi-ng/ccu_nkmp.c b/drivers/clk/sunxi-ng/ccu_nkmp.c new file mode 100644 index 000000000000..9f2b98e19dc9 --- /dev/null +++ b/drivers/clk/sunxi-ng/ccu_nkmp.c @@ -0,0 +1,167 @@ +/* + * Copyright (C) 2016 Maxime Ripard + * Maxime Ripard + * + * 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 "ccu_gate.h" +#include "ccu_nkmp.h" + +struct _ccu_nkmp { + unsigned long n, max_n; + unsigned long k, max_k; + unsigned long m, max_m; + unsigned long p, max_p; +}; + +static void ccu_nkmp_find_best(unsigned long parent, unsigned long rate, + struct _ccu_nkmp *nkmp) +{ + unsigned long best_rate = 0; + unsigned long best_n = 0, best_k = 0, best_m = 0, best_p = 0; + unsigned long _n, _k, _m, _p; + + for (_k = 1; _k <= nkmp->max_k; _k++) { + for (_p = 0; _p <= nkmp->max_p; _p++) { + unsigned long tmp_rate; + + rational_best_approximation(rate / _k, parent >> _p, + nkmp->max_n, nkmp->max_m, + &_n, &_m); + + tmp_rate = (parent * _n * _k >> _p) / _m; + + if (tmp_rate > rate) + continue; + + if ((rate - tmp_rate) < (rate - best_rate)) { + best_rate = tmp_rate; + best_n = _n; + best_k = _k; + best_m = _m; + best_p = _p; + } + } + } + + nkmp->n = best_n; + nkmp->k = best_k; + nkmp->m = best_m; + nkmp->p = best_p; +} + +static void ccu_nkmp_disable(struct clk_hw *hw) +{ + struct ccu_nkmp *nkmp = hw_to_ccu_nkmp(hw); + + return ccu_gate_helper_disable(&nkmp->common, nkmp->enable); +} + +static int ccu_nkmp_enable(struct clk_hw *hw) +{ + struct ccu_nkmp *nkmp = hw_to_ccu_nkmp(hw); + + return ccu_gate_helper_enable(&nkmp->common, nkmp->enable); +} + +static int ccu_nkmp_is_enabled(struct clk_hw *hw) +{ + struct ccu_nkmp *nkmp = hw_to_ccu_nkmp(hw); + + return ccu_gate_helper_is_enabled(&nkmp->common, nkmp->enable); +} + +static unsigned long ccu_nkmp_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct ccu_nkmp *nkmp = hw_to_ccu_nkmp(hw); + unsigned long n, m, k, p; + u32 reg; + + reg = readl(nkmp->common.base + nkmp->common.reg); + + n = reg >> nkmp->n.shift; + n &= (1 << nkmp->n.width) - 1; + + k = reg >> nkmp->k.shift; + k &= (1 << nkmp->k.width) - 1; + + m = reg >> nkmp->m.shift; + m &= (1 << nkmp->m.width) - 1; + + p = reg >> nkmp->p.shift; + p &= (1 << nkmp->p.width) - 1; + + return (parent_rate * (n + 1) * (k + 1) >> p) / (m + 1); +} + +static long ccu_nkmp_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *parent_rate) +{ + struct ccu_nkmp *nkmp = hw_to_ccu_nkmp(hw); + struct _ccu_nkmp _nkmp; + + _nkmp.max_n = 1 << nkmp->n.width; + _nkmp.max_k = 1 << nkmp->k.width; + _nkmp.max_m = 1 << nkmp->m.width; + _nkmp.max_p = (1 << nkmp->p.width) - 1; + + ccu_nkmp_find_best(*parent_rate, rate, + &_nkmp); + + return (*parent_rate * _nkmp.n * _nkmp.k >> _nkmp.p) / _nkmp.m; +} + +static int ccu_nkmp_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct ccu_nkmp *nkmp = hw_to_ccu_nkmp(hw); + struct _ccu_nkmp _nkmp; + unsigned long flags; + u32 reg; + + _nkmp.max_n = 1 << nkmp->n.width; + _nkmp.max_k = 1 << nkmp->k.width; + _nkmp.max_m = 1 << nkmp->m.width; + _nkmp.max_p = (1 << nkmp->p.width) - 1; + + ccu_nkmp_find_best(parent_rate, rate, &_nkmp); + + spin_lock_irqsave(nkmp->common.lock, flags); + + reg = readl(nkmp->common.base + nkmp->common.reg); + reg &= ~GENMASK(nkmp->n.width + nkmp->n.shift - 1, nkmp->n.shift); + reg &= ~GENMASK(nkmp->k.width + nkmp->k.shift - 1, nkmp->k.shift); + reg &= ~GENMASK(nkmp->m.width + nkmp->m.shift - 1, nkmp->m.shift); + reg &= ~GENMASK(nkmp->p.width + nkmp->p.shift - 1, nkmp->p.shift); + + reg |= (_nkmp.n - 1) << nkmp->n.shift; + reg |= (_nkmp.k - 1) << nkmp->k.shift; + reg |= (_nkmp.m - 1) << nkmp->m.shift; + reg |= _nkmp.p << nkmp->p.shift; + + writel(reg, nkmp->common.base + nkmp->common.reg); + + spin_unlock_irqrestore(nkmp->common.lock, flags); + + ccu_helper_wait_for_lock(&nkmp->common, nkmp->lock); + + return 0; +} + +const struct clk_ops ccu_nkmp_ops = { + .disable = ccu_nkmp_disable, + .enable = ccu_nkmp_enable, + .is_enabled = ccu_nkmp_is_enabled, + + .recalc_rate = ccu_nkmp_recalc_rate, + .round_rate = ccu_nkmp_round_rate, + .set_rate = ccu_nkmp_set_rate, +}; diff --git a/drivers/clk/sunxi-ng/ccu_nkmp.h b/drivers/clk/sunxi-ng/ccu_nkmp.h new file mode 100644 index 000000000000..5adb0c92a614 --- /dev/null +++ b/drivers/clk/sunxi-ng/ccu_nkmp.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2016 Maxime Ripard. All rights reserved. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + */ + +#ifndef _CCU_NKMP_H_ +#define _CCU_NKMP_H_ + +#include + +#include "ccu_common.h" +#include "ccu_div.h" +#include "ccu_mult.h" + +/* + * struct ccu_nkmp - Definition of an N-K-M-P clock + * + * Clocks based on the formula parent * N * K >> P / M + */ +struct ccu_nkmp { + u32 enable; + u32 lock; + + struct _ccu_mult n; + struct _ccu_mult k; + struct _ccu_div m; + struct _ccu_div p; + + struct ccu_common common; +}; + +#define SUNXI_CCU_NKMP_WITH_GATE_LOCK(_struct, _name, _parent, _reg, \ + _nshift, _nwidth, \ + _kshift, _kwidth, \ + _mshift, _mwidth, \ + _pshift, _pwidth, \ + _gate, _lock, _flags) \ + struct ccu_nkmp _struct = { \ + .enable = _gate, \ + .lock = _lock, \ + .n = _SUNXI_CCU_MULT(_nshift, _nwidth), \ + .k = _SUNXI_CCU_MULT(_kshift, _kwidth), \ + .m = _SUNXI_CCU_DIV(_mshift, _mwidth), \ + .p = _SUNXI_CCU_DIV(_pshift, _pwidth), \ + .common = { \ + .reg = _reg, \ + .hw.init = CLK_HW_INIT(_name, \ + _parent, \ + &ccu_nkmp_ops, \ + _flags), \ + }, \ + } + +static inline struct ccu_nkmp *hw_to_ccu_nkmp(struct clk_hw *hw) +{ + struct ccu_common *common = hw_to_ccu_common(hw); + + return container_of(common, struct ccu_nkmp, common); +} + +extern const struct clk_ops ccu_nkmp_ops; + +#endif /* _CCU_NKMP_H_ */ -- cgit v1.2.3 From 0577e4853bfb4c65f620fa56d3157692df7f766e Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Wed, 29 Jun 2016 21:05:34 +0200 Subject: clk: sunxi-ng: Add H3 clocks Add the list of clocks and resets found in the H3 CCU. Signed-off-by: Maxime Ripard Signed-off-by: Michael Turquette Link: lkml.kernel.org/r/20160629190535.11855-14-maxime.ripard@free-electrons.com --- drivers/clk/sunxi-ng/Kconfig | 13 + drivers/clk/sunxi-ng/Makefile | 3 + drivers/clk/sunxi-ng/ccu-sun8i-h3.c | 826 +++++++++++++++++++++++++++++++ drivers/clk/sunxi-ng/ccu-sun8i-h3.h | 62 +++ include/dt-bindings/clock/sun8i-h3-ccu.h | 145 ++++++ include/dt-bindings/reset/sun8i-h3-ccu.h | 103 ++++ 6 files changed, 1152 insertions(+) create mode 100644 drivers/clk/sunxi-ng/ccu-sun8i-h3.c create mode 100644 drivers/clk/sunxi-ng/ccu-sun8i-h3.h create mode 100644 include/dt-bindings/clock/sun8i-h3-ccu.h create mode 100644 include/dt-bindings/reset/sun8i-h3-ccu.h diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-ng/Kconfig index 24fc9e4cc546..41e53e8d4d41 100644 --- a/drivers/clk/sunxi-ng/Kconfig +++ b/drivers/clk/sunxi-ng/Kconfig @@ -49,4 +49,17 @@ config SUNXI_CCU_MP select SUNXI_CCU_GATE select SUNXI_CCU_MUX +# SoC Drivers + +config SUN8I_H3_CCU + bool "Support for the Allwinner H3 CCU" + select SUNXI_CCU_DIV + select SUNXI_CCU_NK + select SUNXI_CCU_NKM + select SUNXI_CCU_NKMP + select SUNXI_CCU_NM + select SUNXI_CCU_MP + select SUNXI_CCU_PHASE + default ARCH_SUN8I + endif diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile index 5c342cc698d2..633ce642ffae 100644 --- a/drivers/clk/sunxi-ng/Makefile +++ b/drivers/clk/sunxi-ng/Makefile @@ -15,3 +15,6 @@ obj-$(CONFIG_SUNXI_CCU_NKM) += ccu_nkm.o obj-$(CONFIG_SUNXI_CCU_NKMP) += ccu_nkmp.o obj-$(CONFIG_SUNXI_CCU_NM) += ccu_nm.o obj-$(CONFIG_SUNXI_CCU_MP) += ccu_mp.o + +# SoC support +obj-$(CONFIG_SUN8I_H3_CCU) += ccu-sun8i-h3.o diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-h3.c b/drivers/clk/sunxi-ng/ccu-sun8i-h3.c new file mode 100644 index 000000000000..bcc0a95549d3 --- /dev/null +++ b/drivers/clk/sunxi-ng/ccu-sun8i-h3.c @@ -0,0 +1,826 @@ +/* + * Copyright (c) 2016 Maxime Ripard. All rights reserved. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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 "ccu_common.h" +#include "ccu_reset.h" + +#include "ccu_div.h" +#include "ccu_gate.h" +#include "ccu_mp.h" +#include "ccu_mult.h" +#include "ccu_nk.h" +#include "ccu_nkm.h" +#include "ccu_nkmp.h" +#include "ccu_nm.h" +#include "ccu_phase.h" + +#include "ccu-sun8i-h3.h" + +static SUNXI_CCU_NKMP_WITH_GATE_LOCK(pll_cpux_clk, "pll-cpux", + "osc24M", 0x000, + 8, 5, /* N */ + 4, 2, /* K */ + 0, 2, /* M */ + 16, 2, /* P */ + BIT(31), /* gate */ + BIT(28), /* lock */ + 0); + +/* + * The Audio PLL is supposed to have 4 outputs: 3 fixed factors from + * the base (2x, 4x and 8x), and one variable divider (the one true + * pll audio). + * + * We don't have any need for the variable divider for now, so we just + * hardcode it to match with the clock names + */ +#define SUN8I_H3_PLL_AUDIO_REG 0x008 + +static SUNXI_CCU_NM_WITH_GATE_LOCK(pll_audio_base_clk, "pll-audio-base", + "osc24M", 0x008, + 8, 7, /* N */ + 0, 5, /* M */ + BIT(31), /* gate */ + BIT(28), /* lock */ + 0); + +static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_video_clk, "pll-video", + "osc24M", 0x0010, + 8, 7, /* N */ + 0, 4, /* M */ + BIT(24), /* frac enable */ + BIT(25), /* frac select */ + 270000000, /* frac rate 0 */ + 297000000, /* frac rate 1 */ + BIT(31), /* gate */ + BIT(28), /* lock */ + 0); + +static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_ve_clk, "pll-ve", + "osc24M", 0x0018, + 8, 7, /* N */ + 0, 4, /* M */ + BIT(24), /* frac enable */ + BIT(25), /* frac select */ + 270000000, /* frac rate 0 */ + 297000000, /* frac rate 1 */ + BIT(31), /* gate */ + BIT(28), /* lock */ + 0); + +static SUNXI_CCU_NKM_WITH_GATE_LOCK(pll_ddr_clk, "pll-ddr", + "osc24M", 0x020, + 8, 5, /* N */ + 4, 2, /* K */ + 0, 2, /* M */ + BIT(31), /* gate */ + BIT(28), /* lock */ + 0); + +static SUNXI_CCU_NK_WITH_GATE_LOCK_POSTDIV(pll_periph0_clk, "pll-periph0", + "osc24M", 0x028, + 8, 5, /* N */ + 4, 2, /* K */ + BIT(31), /* gate */ + BIT(28), /* lock */ + 2, /* post-div */ + 0); + +static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_gpu_clk, "pll-gpu", + "osc24M", 0x0038, + 8, 7, /* N */ + 0, 4, /* M */ + BIT(24), /* frac enable */ + BIT(25), /* frac select */ + 270000000, /* frac rate 0 */ + 297000000, /* frac rate 1 */ + BIT(31), /* gate */ + BIT(28), /* lock */ + 0); + +static SUNXI_CCU_NK_WITH_GATE_LOCK_POSTDIV(pll_periph1_clk, "pll-periph1", + "osc24M", 0x044, + 8, 5, /* N */ + 4, 2, /* K */ + BIT(31), /* gate */ + BIT(28), /* lock */ + 2, /* post-div */ + 0); + +static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_de_clk, "pll-de", + "osc24M", 0x0048, + 8, 7, /* N */ + 0, 4, /* M */ + BIT(24), /* frac enable */ + BIT(25), /* frac select */ + 270000000, /* frac rate 0 */ + 297000000, /* frac rate 1 */ + BIT(31), /* gate */ + BIT(28), /* lock */ + 0); + +static const char * const cpux_parents[] = { "osc32k", "osc24M", + "pll-cpux" , "pll-cpux" }; +static SUNXI_CCU_MUX(cpux_clk, "cpux", cpux_parents, + 0x050, 16, 2, CLK_IS_CRITICAL); + +static SUNXI_CCU_M(axi_clk, "axi", "cpux", 0x050, 0, 2, 0); + +static const char * const ahb1_parents[] = { "osc32k", "osc24M", + "axi" , "pll-periph0" }; +static struct ccu_div ahb1_clk = { + .div = _SUNXI_CCU_DIV_FLAGS(4, 2, CLK_DIVIDER_POWER_OF_TWO), + + .mux = { + .shift = 12, + .width = 2, + + .variable_prediv = { + .index = 3, + .shift = 6, + .width = 2, + }, + }, + + .common = { + .reg = 0x054, + .features = CCU_FEATURE_VARIABLE_PREDIV, + .hw.init = CLK_HW_INIT_PARENTS("ahb1", + ahb1_parents, + &ccu_div_ops, + 0), + }, +}; + +static struct clk_div_table apb1_div_table[] = { + { .val = 0, .div = 2 }, + { .val = 1, .div = 2 }, + { .val = 2, .div = 4 }, + { .val = 3, .div = 8 }, + { /* Sentinel */ }, +}; +static SUNXI_CCU_DIV_TABLE(apb1_clk, "apb1", "ahb1", + 0x054, 8, 2, apb1_div_table, 0); + +static const char * const apb2_parents[] = { "osc32k", "osc24M", + "pll-periph0" , "pll-periph0" }; +static SUNXI_CCU_MP_WITH_MUX(apb2_clk, "apb2", apb2_parents, 0x058, + 0, 5, /* M */ + 16, 2, /* P */ + 24, 2, /* mux */ + 0); + +static const char * const ahb2_parents[] = { "ahb1" , "pll-periph0" }; +static struct ccu_mux ahb2_clk = { + .mux = { + .shift = 0, + .width = 1, + + .fixed_prediv = { + .index = 1, + .div = 2, + }, + }, + + .common = { + .reg = 0x05c, + .features = CCU_FEATURE_FIXED_PREDIV, + .hw.init = CLK_HW_INIT_PARENTS("ahb2", + ahb2_parents, + &ccu_mux_ops, + 0), + }, +}; + +static SUNXI_CCU_GATE(bus_ce_clk, "bus-ce", "ahb1", + 0x060, BIT(5), 0); +static SUNXI_CCU_GATE(bus_dma_clk, "bus-dma", "ahb1", + 0x060, BIT(6), 0); +static SUNXI_CCU_GATE(bus_mmc0_clk, "bus-mmc0", "ahb1", + 0x060, BIT(8), 0); +static SUNXI_CCU_GATE(bus_mmc1_clk, "bus-mmc1", "ahb1", + 0x060, BIT(9), 0); +static SUNXI_CCU_GATE(bus_mmc2_clk, "bus-mmc2", "ahb1", + 0x060, BIT(10), 0); +static SUNXI_CCU_GATE(bus_nand_clk, "bus-nand", "ahb1", + 0x060, BIT(13), 0); +static SUNXI_CCU_GATE(bus_dram_clk, "bus-dram", "ahb1", + 0x060, BIT(14), 0); +static SUNXI_CCU_GATE(bus_emac_clk, "bus-emac", "ahb2", + 0x060, BIT(17), 0); +static SUNXI_CCU_GATE(bus_ts_clk, "bus-ts", "ahb1", + 0x060, BIT(18), 0); +static SUNXI_CCU_GATE(bus_hstimer_clk, "bus-hstimer", "ahb1", + 0x060, BIT(19), 0); +static SUNXI_CCU_GATE(bus_spi0_clk, "bus-spi0", "ahb1", + 0x060, BIT(20), 0); +static SUNXI_CCU_GATE(bus_spi1_clk, "bus-spi1", "ahb1", + 0x060, BIT(21), 0); +static SUNXI_CCU_GATE(bus_otg_clk, "bus-otg", "ahb1", + 0x060, BIT(23), 0); +static SUNXI_CCU_GATE(bus_ehci0_clk, "bus-ehci0", "ahb1", + 0x060, BIT(24), 0); +static SUNXI_CCU_GATE(bus_ehci1_clk, "bus-ehci1", "ahb2", + 0x060, BIT(25), 0); +static SUNXI_CCU_GATE(bus_ehci2_clk, "bus-ehci2", "ahb2", + 0x060, BIT(26), 0); +static SUNXI_CCU_GATE(bus_ehci3_clk, "bus-ehci3", "ahb2", + 0x060, BIT(27), 0); +static SUNXI_CCU_GATE(bus_ohci0_clk, "bus-ohci0", "ahb1", + 0x060, BIT(28), 0); +static SUNXI_CCU_GATE(bus_ohci1_clk, "bus-ohci1", "ahb2", + 0x060, BIT(29), 0); +static SUNXI_CCU_GATE(bus_ohci2_clk, "bus-ohci2", "ahb2", + 0x060, BIT(30), 0); +static SUNXI_CCU_GATE(bus_ohci3_clk, "bus-ohci3", "ahb2", + 0x060, BIT(31), 0); + +static SUNXI_CCU_GATE(bus_ve_clk, "bus-ve", "ahb1", + 0x064, BIT(0), 0); +static SUNXI_CCU_GATE(bus_tcon0_clk, "bus-tcon0", "ahb1", + 0x064, BIT(3), 0); +static SUNXI_CCU_GATE(bus_tcon1_clk, "bus-tcon1", "ahb1", + 0x064, BIT(4), 0); +static SUNXI_CCU_GATE(bus_deinterlace_clk, "bus-deinterlace", "ahb1", + 0x064, BIT(5), 0); +static SUNXI_CCU_GATE(bus_csi_clk, "bus-csi", "ahb1", + 0x064, BIT(8), 0); +static SUNXI_CCU_GATE(bus_tve_clk, "bus-tve", "ahb1", + 0x064, BIT(9), 0); +static SUNXI_CCU_GATE(bus_hdmi_clk, "bus-hdmi", "ahb1", + 0x064, BIT(11), 0); +static SUNXI_CCU_GATE(bus_de_clk, "bus-de", "ahb1", + 0x064, BIT(12), 0); +static SUNXI_CCU_GATE(bus_gpu_clk, "bus-gpu", "ahb1", + 0x064, BIT(20), 0); +static SUNXI_CCU_GATE(bus_msgbox_clk, "bus-msgbox", "ahb1", + 0x064, BIT(21), 0); +static SUNXI_CCU_GATE(bus_spinlock_clk, "bus-spinlock", "ahb1", + 0x064, BIT(22), 0); + +static SUNXI_CCU_GATE(bus_codec_clk, "bus-codec", "apb1", + 0x068, BIT(0), 0); +static SUNXI_CCU_GATE(bus_spdif_clk, "bus-spdif", "apb1", + 0x068, BIT(1), 0); +static SUNXI_CCU_GATE(bus_pio_clk, "bus-pio", "apb1", + 0x068, BIT(5), 0); +static SUNXI_CCU_GATE(bus_ths_clk, "bus-ths", "apb1", + 0x068, BIT(8), 0); +static SUNXI_CCU_GATE(bus_i2s0_clk, "bus-i2s0", "apb1", + 0x068, BIT(12), 0); +static SUNXI_CCU_GATE(bus_i2s1_clk, "bus-i2s1", "apb1", + 0x068, BIT(13), 0); +static SUNXI_CCU_GATE(bus_i2s2_clk, "bus-i2s2", "apb1", + 0x068, BIT(14), 0); + +static SUNXI_CCU_GATE(bus_i2c0_clk, "bus-i2c0", "apb2", + 0x06c, BIT(0), 0); +static SUNXI_CCU_GATE(bus_i2c1_clk, "bus-i2c1", "apb2", + 0x06c, BIT(1), 0); +static SUNXI_CCU_GATE(bus_i2c2_clk, "bus-i2c2", "apb2", + 0x06c, BIT(2), 0); +static SUNXI_CCU_GATE(bus_uart0_clk, "bus-uart0", "apb2", + 0x06c, BIT(16), 0); +static SUNXI_CCU_GATE(bus_uart1_clk, "bus-uart1", "apb2", + 0x06c, BIT(17), 0); +static SUNXI_CCU_GATE(bus_uart2_clk, "bus-uart2", "apb2", + 0x06c, BIT(18), 0); +static SUNXI_CCU_GATE(bus_uart3_clk, "bus-uart3", "apb2", + 0x06c, BIT(19), 0); +static SUNXI_CCU_GATE(bus_scr_clk, "bus-scr", "apb2", + 0x06c, BIT(20), 0); + +static SUNXI_CCU_GATE(bus_ephy_clk, "bus-ephy", "ahb1", + 0x070, BIT(0), 0); +static SUNXI_CCU_GATE(bus_dbg_clk, "bus-dbg", "ahb1", + 0x070, BIT(7), 0); + +static struct clk_div_table ths_div_table[] = { + { .val = 0, .div = 1 }, + { .val = 1, .div = 2 }, + { .val = 2, .div = 4 }, + { .val = 3, .div = 6 }, +}; +static SUNXI_CCU_DIV_TABLE_WITH_GATE(ths_clk, "ths", "osc24M", + 0x074, 0, 2, ths_div_table, BIT(31), 0); + +static const char * const mod0_default_parents[] = { "osc24M", "pll-periph0", + "pll-periph1" }; +static SUNXI_CCU_MP_WITH_MUX_GATE(nand_clk, "nand", mod0_default_parents, 0x080, + 0, 4, /* M */ + 16, 2, /* P */ + 24, 2, /* mux */ + BIT(31), /* gate */ + 0); + +static SUNXI_CCU_MP_WITH_MUX_GATE(mmc0_clk, "mmc0", mod0_default_parents, 0x088, + 0, 4, /* M */ + 16, 2, /* P */ + 24, 2, /* mux */ + BIT(31), /* gate */ + 0); + +static SUNXI_CCU_PHASE(mmc0_sample_clk, "mmc0_sample", "mmc0", + 0x088, 20, 3, 0); +static SUNXI_CCU_PHASE(mmc0_output_clk, "mmc0_output", "mmc0", + 0x088, 8, 3, 0); + +static SUNXI_CCU_MP_WITH_MUX_GATE(mmc1_clk, "mmc1", mod0_default_parents, 0x08c, + 0, 4, /* M */ + 16, 2, /* P */ + 24, 2, /* mux */ + BIT(31), /* gate */ + 0); + +static SUNXI_CCU_PHASE(mmc1_sample_clk, "mmc1_sample", "mmc1", + 0x08c, 20, 3, 0); +static SUNXI_CCU_PHASE(mmc1_output_clk, "mmc1_output", "mmc1", + 0x08c, 8, 3, 0); + +static SUNXI_CCU_MP_WITH_MUX_GATE(mmc2_clk, "mmc2", mod0_default_parents, 0x090, + 0, 4, /* M */ + 16, 2, /* P */ + 24, 2, /* mux */ + BIT(31), /* gate */ + 0); + +static SUNXI_CCU_PHASE(mmc2_sample_clk, "mmc2_sample", "mmc2", + 0x090, 20, 3, 0); +static SUNXI_CCU_PHASE(mmc2_output_clk, "mmc2_output", "mmc2", + 0x090, 8, 3, 0); + +static const char * const ts_parents[] = { "osc24M", "pll-periph0", }; +static SUNXI_CCU_MP_WITH_MUX_GATE(ts_clk, "ts", ts_parents, 0x098, + 0, 4, /* M */ + 16, 2, /* P */ + 24, 2, /* mux */ + BIT(31), /* gate */ + 0); + +static SUNXI_CCU_MP_WITH_MUX_GATE(ce_clk, "ce", mod0_default_parents, 0x09c, + 0, 4, /* M */ + 16, 2, /* P */ + 24, 2, /* mux */ + BIT(31), /* gate */ + 0); + +static SUNXI_CCU_MP_WITH_MUX_GATE(spi0_clk, "spi0", mod0_default_parents, 0x0a0, + 0, 4, /* M */ + 16, 2, /* P */ + 24, 2, /* mux */ + BIT(31), /* gate */ + 0); + +static SUNXI_CCU_MP_WITH_MUX_GATE(spi1_clk, "spi1", mod0_default_parents, 0x0a4, + 0, 4, /* M */ + 16, 2, /* P */ + 24, 2, /* mux */ + BIT(31), /* gate */ + 0); + +static const char * const i2s_parents[] = { "pll-audio-8x", "pll-audio-4x", + "pll-audio-2x", "pll-audio" }; +static SUNXI_CCU_MUX_WITH_GATE(i2s0_clk, "i2s0", i2s_parents, + 0x0b0, 16, 2, BIT(31), 0); + +static SUNXI_CCU_MUX_WITH_GATE(i2s1_clk, "i2s1", i2s_parents, + 0x0b4, 16, 2, BIT(31), 0); + +static SUNXI_CCU_MUX_WITH_GATE(i2s2_clk, "i2s2", i2s_parents, + 0x0b8, 16, 2, BIT(31), 0); + +static SUNXI_CCU_M_WITH_GATE(spdif_clk, "spdif", "pll-audio", + 0x0c0, 0, 4, BIT(31), 0); + +static SUNXI_CCU_GATE(usb_phy0_clk, "usb-phy0", "osc24M", + 0x0cc, BIT(8), 0); +static SUNXI_CCU_GATE(usb_phy1_clk, "usb-phy1", "osc24M", + 0x0cc, BIT(9), 0); +static SUNXI_CCU_GATE(usb_phy2_clk, "usb-phy2", "osc24M", + 0x0cc, BIT(10), 0); +static SUNXI_CCU_GATE(usb_phy3_clk, "usb-phy3", "osc24M", + 0x0cc, BIT(11), 0); +static SUNXI_CCU_GATE(usb_ohci0_clk, "usb-ohci0", "osc24M", + 0x0cc, BIT(16), 0); +static SUNXI_CCU_GATE(usb_ohci1_clk, "usb-ohci1", "osc24M", + 0x0cc, BIT(17), 0); +static SUNXI_CCU_GATE(usb_ohci2_clk, "usb-ohci2", "osc24M", + 0x0cc, BIT(18), 0); +static SUNXI_CCU_GATE(usb_ohci3_clk, "usb-ohci3", "osc24M", + 0x0cc, BIT(19), 0); + +static const char * const dram_parents[] = { "pll-ddr", "pll-periph0-2x" }; +static SUNXI_CCU_M_WITH_MUX(dram_clk, "dram", dram_parents, + 0x0f4, 0, 4, 20, 2, CLK_IS_CRITICAL); + +static SUNXI_CCU_GATE(dram_ve_clk, "dram-ve", "dram", + 0x100, BIT(0), 0); +static SUNXI_CCU_GATE(dram_csi_clk, "dram-csi", "dram", + 0x100, BIT(1), 0); +static SUNXI_CCU_GATE(dram_deinterlace_clk, "dram-deinterlace", "dram", + 0x100, BIT(2), 0); +static SUNXI_CCU_GATE(dram_ts_clk, "dram-ts", "dram", + 0x100, BIT(3), 0); + +static const char * const de_parents[] = { "pll-periph0-2x", "pll-de" }; +static SUNXI_CCU_M_WITH_MUX_GATE(de_clk, "de", de_parents, + 0x104, 0, 4, 24, 3, BIT(31), 0); + +static const char * const tcon_parents[] = { "pll-video" }; +static SUNXI_CCU_M_WITH_MUX_GATE(tcon_clk, "tcon", tcon_parents, + 0x118, 0, 4, 24, 3, BIT(31), 0); + +static const char * const tve_parents[] = { "pll-de", "pll-periph1" }; +static SUNXI_CCU_M_WITH_MUX_GATE(tve_clk, "tve", tve_parents, + 0x120, 0, 4, 24, 3, BIT(31), 0); + +static const char * const deinterlace_parents[] = { "pll-periph0", "pll-periph1" }; +static SUNXI_CCU_M_WITH_MUX_GATE(deinterlace_clk, "deinterlace", deinterlace_parents, + 0x124, 0, 4, 24, 3, BIT(31), 0); + +static SUNXI_CCU_GATE(csi_misc_clk, "csi-misc", "osc24M", + 0x130, BIT(31), 0); + +static const char * const csi_sclk_parents[] = { "pll-periph0", "pll-periph1" }; +static SUNXI_CCU_M_WITH_MUX_GATE(csi_sclk_clk, "csi-sclk", csi_sclk_parents, + 0x134, 16, 4, 24, 3, BIT(31), 0); + +static const char * const csi_mclk_parents[] = { "osc24M", "pll-video", "pll-periph0" }; +static SUNXI_CCU_M_WITH_MUX_GATE(csi_mclk_clk, "csi-mclk", csi_mclk_parents, + 0x134, 0, 5, 8, 3, BIT(15), 0); + +static SUNXI_CCU_M_WITH_GATE(ve_clk, "ve", "pll-ve", + 0x13c, 16, 3, BIT(31), 0); + +static SUNXI_CCU_GATE(ac_dig_clk, "ac-dig", "pll-audio", + 0x140, BIT(31), 0); +static SUNXI_CCU_GATE(avs_clk, "avs", "osc24M", + 0x144, BIT(31), 0); + +static const char * const hdmi_parents[] = { "pll-video" }; +static SUNXI_CCU_M_WITH_MUX_GATE(hdmi_clk, "hdmi", hdmi_parents, + 0x150, 0, 4, 24, 2, BIT(31), 0); + +static SUNXI_CCU_GATE(hdmi_ddc_clk, "hdmi-ddc", "osc24M", + 0x154, BIT(31), 0); + +static const char * const mbus_parents[] = { "osc24M", "pll-periph0-2x", "pll-ddr" }; +static SUNXI_CCU_M_WITH_MUX_GATE(mbus_clk, "mbus", mbus_parents, + 0x15c, 0, 3, 24, 2, BIT(31), CLK_IS_CRITICAL); + +static SUNXI_CCU_M_WITH_GATE(gpu_clk, "gpu", "pll-gpu", + 0x1a0, 0, 3, BIT(31), 0); + +static struct ccu_common *sun8i_h3_ccu_clks[] = { + &pll_cpux_clk.common, + &pll_audio_base_clk.common, + &pll_video_clk.common, + &pll_ve_clk.common, + &pll_ddr_clk.common, + &pll_periph0_clk.common, + &pll_gpu_clk.common, + &pll_periph1_clk.common, + &pll_de_clk.common, + &cpux_clk.common, + &axi_clk.common, + &ahb1_clk.common, + &apb1_clk.common, + &apb2_clk.common, + &ahb2_clk.common, + &bus_ce_clk.common, + &bus_dma_clk.common, + &bus_mmc0_clk.common, + &bus_mmc1_clk.common, + &bus_mmc2_clk.common, + &bus_nand_clk.common, + &bus_dram_clk.common, + &bus_emac_clk.common, + &bus_ts_clk.common, + &bus_hstimer_clk.common, + &bus_spi0_clk.common, + &bus_spi1_clk.common, + &bus_otg_clk.common, + &bus_ehci0_clk.common, + &bus_ehci1_clk.common, + &bus_ehci2_clk.common, + &bus_ehci3_clk.common, + &bus_ohci0_clk.common, + &bus_ohci1_clk.common, + &bus_ohci2_clk.common, + &bus_ohci3_clk.common, + &bus_ve_clk.common, + &bus_tcon0_clk.common, + &bus_tcon1_clk.common, + &bus_deinterlace_clk.common, + &bus_csi_clk.common, + &bus_tve_clk.common, + &bus_hdmi_clk.common, + &bus_de_clk.common, + &bus_gpu_clk.common, + &bus_msgbox_clk.common, + &bus_spinlock_clk.common, + &bus_codec_clk.common, + &bus_spdif_clk.common, + &bus_pio_clk.common, + &bus_ths_clk.common, + &bus_i2s0_clk.common, + &bus_i2s1_clk.common, + &bus_i2s2_clk.common, + &bus_i2c0_clk.common, + &bus_i2c1_clk.common, + &bus_i2c2_clk.common, + &bus_uart0_clk.common, + &bus_uart1_clk.common, + &bus_uart2_clk.common, + &bus_uart3_clk.common, + &bus_scr_clk.common, + &bus_ephy_clk.common, + &bus_dbg_clk.common, + &ths_clk.common, + &nand_clk.common, + &mmc0_clk.common, + &mmc0_sample_clk.common, + &mmc0_output_clk.common, + &mmc1_clk.common, + &mmc1_sample_clk.common, + &mmc1_output_clk.common, + &mmc2_clk.common, + &mmc2_sample_clk.common, + &mmc2_output_clk.common, + &ts_clk.common, + &ce_clk.common, + &spi0_clk.common, + &spi1_clk.common, + &i2s0_clk.common, + &i2s1_clk.common, + &i2s2_clk.common, + &spdif_clk.common, + &usb_phy0_clk.common, + &usb_phy1_clk.common, + &usb_phy2_clk.common, + &usb_phy3_clk.common, + &usb_ohci0_clk.common, + &usb_ohci1_clk.common, + &usb_ohci2_clk.common, + &usb_ohci3_clk.common, + &dram_clk.common, + &dram_ve_clk.common, + &dram_csi_clk.common, + &dram_deinterlace_clk.common, + &dram_ts_clk.common, + &de_clk.common, + &tcon_clk.common, + &tve_clk.common, + &deinterlace_clk.common, + &csi_misc_clk.common, + &csi_sclk_clk.common, + &csi_mclk_clk.common, + &ve_clk.common, + &ac_dig_clk.common, + &avs_clk.common, + &hdmi_clk.common, + &hdmi_ddc_clk.common, + &mbus_clk.common, + &gpu_clk.common, +}; + +/* We hardcode the divider to 4 for now */ +static CLK_FIXED_FACTOR(pll_audio_clk, "pll-audio", + "pll-audio-base", 4, 1, CLK_SET_RATE_PARENT); +static CLK_FIXED_FACTOR(pll_audio_2x_clk, "pll-audio-2x", + "pll-audio-base", 2, 1, CLK_SET_RATE_PARENT); +static CLK_FIXED_FACTOR(pll_audio_4x_clk, "pll-audio-4x", + "pll-audio-base", 1, 1, CLK_SET_RATE_PARENT); +static CLK_FIXED_FACTOR(pll_audio_8x_clk, "pll-audio-8x", + "pll-audio-base", 1, 2, CLK_SET_RATE_PARENT); +static CLK_FIXED_FACTOR(pll_periph0_2x_clk, "pll-periph0-2x", + "pll-periph0", 1, 2, 0); + +static struct clk_hw_onecell_data sun8i_h3_hw_clks = { + .hws = { + [CLK_PLL_CPUX] = &pll_cpux_clk.common.hw, + [CLK_PLL_AUDIO_BASE] = &pll_audio_base_clk.common.hw, + [CLK_PLL_AUDIO] = &pll_audio_clk.hw, + [CLK_PLL_AUDIO_2X] = &pll_audio_2x_clk.hw, + [CLK_PLL_AUDIO_4X] = &pll_audio_4x_clk.hw, + [CLK_PLL_AUDIO_8X] = &pll_audio_8x_clk.hw, + [CLK_PLL_VIDEO] = &pll_video_clk.common.hw, + [CLK_PLL_VE] = &pll_ve_clk.common.hw, + [CLK_PLL_DDR] = &pll_ddr_clk.common.hw, + [CLK_PLL_PERIPH0] = &pll_periph0_clk.common.hw, + [CLK_PLL_PERIPH0_2X] = &pll_periph0_2x_clk.hw, + [CLK_PLL_GPU] = &pll_gpu_clk.common.hw, + [CLK_PLL_PERIPH1] = &pll_periph1_clk.common.hw, + [CLK_PLL_DE] = &pll_de_clk.common.hw, + [CLK_CPUX] = &cpux_clk.common.hw, + [CLK_AXI] = &axi_clk.common.hw, + [CLK_AHB1] = &ahb1_clk.common.hw, + [CLK_APB1] = &apb1_clk.common.hw, + [CLK_APB2] = &apb2_clk.common.hw, + [CLK_AHB2] = &ahb2_clk.common.hw, + [CLK_BUS_CE] = &bus_ce_clk.common.hw, + [CLK_BUS_DMA] = &bus_dma_clk.common.hw, + [CLK_BUS_MMC0] = &bus_mmc0_clk.common.hw, + [CLK_BUS_MMC1] = &bus_mmc1_clk.common.hw, + [CLK_BUS_MMC2] = &bus_mmc2_clk.common.hw, + [CLK_BUS_NAND] = &bus_nand_clk.common.hw, + [CLK_BUS_DRAM] = &bus_dram_clk.common.hw, + [CLK_BUS_EMAC] = &bus_emac_clk.common.hw, + [CLK_BUS_TS] = &bus_ts_clk.common.hw, + [CLK_BUS_HSTIMER] = &bus_hstimer_clk.common.hw, + [CLK_BUS_SPI0] = &bus_spi0_clk.common.hw, + [CLK_BUS_SPI1] = &bus_spi1_clk.common.hw, + [CLK_BUS_OTG] = &bus_otg_clk.common.hw, + [CLK_BUS_EHCI0] = &bus_ehci0_clk.common.hw, + [CLK_BUS_EHCI1] = &bus_ehci1_clk.common.hw, + [CLK_BUS_EHCI2] = &bus_ehci2_clk.common.hw, + [CLK_BUS_EHCI3] = &bus_ehci3_clk.common.hw, + [CLK_BUS_OHCI0] = &bus_ohci0_clk.common.hw, + [CLK_BUS_OHCI1] = &bus_ohci1_clk.common.hw, + [CLK_BUS_OHCI2] = &bus_ohci2_clk.common.hw, + [CLK_BUS_OHCI3] = &bus_ohci3_clk.common.hw, + [CLK_BUS_VE] = &bus_ve_clk.common.hw, + [CLK_BUS_TCON0] = &bus_tcon0_clk.common.hw, + [CLK_BUS_TCON1] = &bus_tcon1_clk.common.hw, + [CLK_BUS_DEINTERLACE] = &bus_deinterlace_clk.common.hw, + [CLK_BUS_CSI] = &bus_csi_clk.common.hw, + [CLK_BUS_TVE] = &bus_tve_clk.common.hw, + [CLK_BUS_HDMI] = &bus_hdmi_clk.common.hw, + [CLK_BUS_DE] = &bus_de_clk.common.hw, + [CLK_BUS_GPU] = &bus_gpu_clk.common.hw, + [CLK_BUS_MSGBOX] = &bus_msgbox_clk.common.hw, + [CLK_BUS_SPINLOCK] = &bus_spinlock_clk.common.hw, + [CLK_BUS_CODEC] = &bus_codec_clk.common.hw, + [CLK_BUS_SPDIF] = &bus_spdif_clk.common.hw, + [CLK_BUS_PIO] = &bus_pio_clk.common.hw, + [CLK_BUS_THS] = &bus_ths_clk.common.hw, + [CLK_BUS_I2S0] = &bus_i2s0_clk.common.hw, + [CLK_BUS_I2S1] = &bus_i2s1_clk.common.hw, + [CLK_BUS_I2S2] = &bus_i2s2_clk.common.hw, + [CLK_BUS_I2C0] = &bus_i2c0_clk.common.hw, + [CLK_BUS_I2C1] = &bus_i2c1_clk.common.hw, + [CLK_BUS_I2C2] = &bus_i2c2_clk.common.hw, + [CLK_BUS_UART0] = &bus_uart0_clk.common.hw, + [CLK_BUS_UART1] = &bus_uart1_clk.common.hw, + [CLK_BUS_UART2] = &bus_uart2_clk.common.hw, + [CLK_BUS_UART3] = &bus_uart3_clk.common.hw, + [CLK_BUS_SCR] = &bus_scr_clk.common.hw, + [CLK_BUS_EPHY] = &bus_ephy_clk.common.hw, + [CLK_BUS_DBG] = &bus_dbg_clk.common.hw, + [CLK_THS] = &ths_clk.common.hw, + [CLK_NAND] = &nand_clk.common.hw, + [CLK_MMC0] = &mmc0_clk.common.hw, + [CLK_MMC0_SAMPLE] = &mmc0_sample_clk.common.hw, + [CLK_MMC0_OUTPUT] = &mmc0_output_clk.common.hw, + [CLK_MMC1] = &mmc1_clk.common.hw, + [CLK_MMC1_SAMPLE] = &mmc1_sample_clk.common.hw, + [CLK_MMC1_OUTPUT] = &mmc1_output_clk.common.hw, + [CLK_MMC2] = &mmc2_clk.common.hw, + [CLK_MMC2_SAMPLE] = &mmc2_sample_clk.common.hw, + [CLK_MMC2_OUTPUT] = &mmc2_output_clk.common.hw, + [CLK_TS] = &ts_clk.common.hw, + [CLK_CE] = &ce_clk.common.hw, + [CLK_SPI0] = &spi0_clk.common.hw, + [CLK_SPI1] = &spi1_clk.common.hw, + [CLK_I2S0] = &i2s0_clk.common.hw, + [CLK_I2S1] = &i2s1_clk.common.hw, + [CLK_I2S2] = &i2s2_clk.common.hw, + [CLK_SPDIF] = &spdif_clk.common.hw, + [CLK_USB_PHY0] = &usb_phy0_clk.common.hw, + [CLK_USB_PHY1] = &usb_phy1_clk.common.hw, + [CLK_USB_PHY2] = &usb_phy2_clk.common.hw, + [CLK_USB_PHY3] = &usb_phy3_clk.common.hw, + [CLK_USB_OHCI0] = &usb_ohci0_clk.common.hw, + [CLK_USB_OHCI1] = &usb_ohci1_clk.common.hw, + [CLK_USB_OHCI2] = &usb_ohci2_clk.common.hw, + [CLK_USB_OHCI3] = &usb_ohci3_clk.common.hw, + [CLK_DRAM] = &dram_clk.common.hw, + [CLK_DRAM_VE] = &dram_ve_clk.common.hw, + [CLK_DRAM_CSI] = &dram_csi_clk.common.hw, + [CLK_DRAM_DEINTERLACE] = &dram_deinterlace_clk.common.hw, + [CLK_DRAM_TS] = &dram_ts_clk.common.hw, + [CLK_DE] = &de_clk.common.hw, + [CLK_TCON0] = &tcon_clk.common.hw, + [CLK_TVE] = &tve_clk.common.hw, + [CLK_DEINTERLACE] = &deinterlace_clk.common.hw, + [CLK_CSI_MISC] = &csi_misc_clk.common.hw, + [CLK_CSI_SCLK] = &csi_sclk_clk.common.hw, + [CLK_CSI_MCLK] = &csi_mclk_clk.common.hw, + [CLK_VE] = &ve_clk.common.hw, + [CLK_AC_DIG] = &ac_dig_clk.common.hw, + [CLK_AVS] = &avs_clk.common.hw, + [CLK_HDMI] = &hdmi_clk.common.hw, + [CLK_HDMI_DDC] = &hdmi_ddc_clk.common.hw, + [CLK_MBUS] = &mbus_clk.common.hw, + [CLK_GPU] = &gpu_clk.common.hw, + }, + .num = CLK_NUMBER, +}; + +static struct ccu_reset_map sun8i_h3_ccu_resets[] = { + [RST_USB_PHY0] = { 0x0cc, BIT(0) }, + [RST_USB_PHY1] = { 0x0cc, BIT(1) }, + [RST_USB_PHY2] = { 0x0cc, BIT(2) }, + [RST_USB_PHY3] = { 0x0cc, BIT(3) }, + + [RST_MBUS] = { 0x0fc, BIT(31) }, + + [RST_BUS_CE] = { 0x2c0, BIT(5) }, + [RST_BUS_DMA] = { 0x2c0, BIT(6) }, + [RST_BUS_MMC0] = { 0x2c0, BIT(8) }, + [RST_BUS_MMC1] = { 0x2c0, BIT(9) }, + [RST_BUS_MMC2] = { 0x2c0, BIT(10) }, + [RST_BUS_NAND] = { 0x2c0, BIT(13) }, + [RST_BUS_DRAM] = { 0x2c0, BIT(14) }, + [RST_BUS_EMAC] = { 0x2c0, BIT(17) }, + [RST_BUS_TS] = { 0x2c0, BIT(18) }, + [RST_BUS_HSTIMER] = { 0x2c0, BIT(19) }, + [RST_BUS_SPI0] = { 0x2c0, BIT(20) }, + [RST_BUS_SPI1] = { 0x2c0, BIT(21) }, + [RST_BUS_OTG] = { 0x2c0, BIT(23) }, + [RST_BUS_EHCI0] = { 0x2c0, BIT(24) }, + [RST_BUS_EHCI1] = { 0x2c0, BIT(25) }, + [RST_BUS_EHCI2] = { 0x2c0, BIT(26) }, + [RST_BUS_EHCI3] = { 0x2c0, BIT(27) }, + [RST_BUS_OHCI0] = { 0x2c0, BIT(28) }, + [RST_BUS_OHCI1] = { 0x2c0, BIT(29) }, + [RST_BUS_OHCI2] = { 0x2c0, BIT(30) }, + [RST_BUS_OHCI3] = { 0x2c0, BIT(31) }, + + [RST_BUS_VE] = { 0x2c4, BIT(0) }, + [RST_BUS_TCON0] = { 0x2c4, BIT(3) }, + [RST_BUS_TCON1] = { 0x2c4, BIT(4) }, + [RST_BUS_DEINTERLACE] = { 0x2c4, BIT(5) }, + [RST_BUS_CSI] = { 0x2c4, BIT(8) }, + [RST_BUS_TVE] = { 0x2c4, BIT(9) }, + [RST_BUS_HDMI0] = { 0x2c4, BIT(10) }, + [RST_BUS_HDMI1] = { 0x2c4, BIT(11) }, + [RST_BUS_DE] = { 0x2c4, BIT(12) }, + [RST_BUS_GPU] = { 0x2c4, BIT(20) }, + [RST_BUS_MSGBOX] = { 0x2c4, BIT(21) }, + [RST_BUS_SPINLOCK] = { 0x2c4, BIT(22) }, + [RST_BUS_DBG] = { 0x2c4, BIT(31) }, + + [RST_BUS_EPHY] = { 0x2c8, BIT(2) }, + + [RST_BUS_CODEC] = { 0x2d0, BIT(0) }, + [RST_BUS_SPDIF] = { 0x2d0, BIT(1) }, + [RST_BUS_THS] = { 0x2d0, BIT(8) }, + [RST_BUS_I2S0] = { 0x2d0, BIT(12) }, + [RST_BUS_I2S1] = { 0x2d0, BIT(13) }, + [RST_BUS_I2S2] = { 0x2d0, BIT(14) }, + + [RST_BUS_I2C0] = { 0x2d4, BIT(0) }, + [RST_BUS_I2C1] = { 0x2d4, BIT(1) }, + [RST_BUS_I2C2] = { 0x2d4, BIT(2) }, + [RST_BUS_UART0] = { 0x2d4, BIT(16) }, + [RST_BUS_UART1] = { 0x2d4, BIT(17) }, + [RST_BUS_UART2] = { 0x2d4, BIT(18) }, + [RST_BUS_UART3] = { 0x2d4, BIT(19) }, + [RST_BUS_SCR] = { 0x2d4, BIT(20) }, +}; + +static const struct sunxi_ccu_desc sun8i_h3_ccu_desc = { + .ccu_clks = sun8i_h3_ccu_clks, + .num_ccu_clks = ARRAY_SIZE(sun8i_h3_ccu_clks), + + .hw_clks = &sun8i_h3_hw_clks, + + .resets = sun8i_h3_ccu_resets, + .num_resets = ARRAY_SIZE(sun8i_h3_ccu_resets), +}; + +static void __init sun8i_h3_ccu_setup(struct device_node *node) +{ + void __iomem *reg; + u32 val; + + reg = of_io_request_and_map(node, 0, of_node_full_name(node)); + if (IS_ERR(reg)) { + pr_err("%s: Could not map the clock registers\n", + of_node_full_name(node)); + return; + } + + /* Force the PLL-Audio-1x divider to 4 */ + val = readl(reg + SUN8I_H3_PLL_AUDIO_REG); + val &= ~GENMASK(4, 0); + writel(val | 3, reg + SUN8I_H3_PLL_AUDIO_REG); + + sunxi_ccu_probe(node, reg, &sun8i_h3_ccu_desc); +} +CLK_OF_DECLARE(sun8i_h3_ccu, "allwinner,sun8i-h3-ccu", + sun8i_h3_ccu_setup); diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-h3.h b/drivers/clk/sunxi-ng/ccu-sun8i-h3.h new file mode 100644 index 000000000000..78be712c7487 --- /dev/null +++ b/drivers/clk/sunxi-ng/ccu-sun8i-h3.h @@ -0,0 +1,62 @@ +/* + * Copyright 2016 Maxime Ripard + * + * Maxime Ripard + * + * 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. + */ + +#ifndef _CCU_SUN8I_H3_H_ +#define _CCU_SUN8I_H3_H_ + +#include +#include + +#define CLK_PLL_CPUX 0 +#define CLK_PLL_AUDIO_BASE 1 +#define CLK_PLL_AUDIO 2 +#define CLK_PLL_AUDIO_2X 3 +#define CLK_PLL_AUDIO_4X 4 +#define CLK_PLL_AUDIO_8X 5 +#define CLK_PLL_VIDEO 6 +#define CLK_PLL_VE 7 +#define CLK_PLL_DDR 8 +#define CLK_PLL_PERIPH0 9 +#define CLK_PLL_PERIPH0_2X 10 +#define CLK_PLL_GPU 11 +#define CLK_PLL_PERIPH1 12 +#define CLK_PLL_DE 13 + +/* The CPUX clock is exported */ + +#define CLK_AXI 15 +#define CLK_AHB1 16 +#define CLK_APB1 17 +#define CLK_APB2 18 +#define CLK_AHB2 19 + +/* All the bus gates are exported */ + +/* The first bunch of module clocks are exported */ + +#define CLK_DRAM 96 + +/* All the DRAM gates are exported */ + +/* Some more module clocks are exported */ + +#define CLK_MBUS 113 + +/* And the GPU module clock is exported */ + +#define CLK_NUMBER (CLK_GPU + 1) + +#endif /* _CCU_SUN8I_H3_H_ */ diff --git a/include/dt-bindings/clock/sun8i-h3-ccu.h b/include/dt-bindings/clock/sun8i-h3-ccu.h new file mode 100644 index 000000000000..efb7ba2bd515 --- /dev/null +++ b/include/dt-bindings/clock/sun8i-h3-ccu.h @@ -0,0 +1,145 @@ +/* + * Copyright (C) 2016 Maxime Ripard + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file 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 file 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. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef _DT_BINDINGS_CLK_SUN8I_H3_H_ +#define _DT_BINDINGS_CLK_SUN8I_H3_H_ + +#define CLK_CPUX 14 + +#define CLK_BUS_CE 20 +#define CLK_BUS_DMA 21 +#define CLK_BUS_MMC0 22 +#define CLK_BUS_MMC1 23 +#define CLK_BUS_MMC2 24 +#define CLK_BUS_NAND 25 +#define CLK_BUS_DRAM 26 +#define CLK_BUS_EMAC 27 +#define CLK_BUS_TS 28 +#define CLK_BUS_HSTIMER 29 +#define CLK_BUS_SPI0 30 +#define CLK_BUS_SPI1 31 +#define CLK_BUS_OTG 32 +#define CLK_BUS_EHCI0 33 +#define CLK_BUS_EHCI1 34 +#define CLK_BUS_EHCI2 35 +#define CLK_BUS_EHCI3 36 +#define CLK_BUS_OHCI0 37 +#define CLK_BUS_OHCI1 38 +#define CLK_BUS_OHCI2 39 +#define CLK_BUS_OHCI3 40 +#define CLK_BUS_VE 41 +#define CLK_BUS_TCON0 42 +#define CLK_BUS_TCON1 43 +#define CLK_BUS_DEINTERLACE 44 +#define CLK_BUS_CSI 45 +#define CLK_BUS_TVE 46 +#define CLK_BUS_HDMI 47 +#define CLK_BUS_DE 48 +#define CLK_BUS_GPU 49 +#define CLK_BUS_MSGBOX 50 +#define CLK_BUS_SPINLOCK 51 +#define CLK_BUS_CODEC 52 +#define CLK_BUS_SPDIF 53 +#define CLK_BUS_PIO 54 +#define CLK_BUS_THS 55 +#define CLK_BUS_I2S0 56 +#define CLK_BUS_I2S1 57 +#define CLK_BUS_I2S2 58 +#define CLK_BUS_I2C0 59 +#define CLK_BUS_I2C1 60 +#define CLK_BUS_I2C2 61 +#define CLK_BUS_UART0 62 +#define CLK_BUS_UART1 63 +#define CLK_BUS_UART2 64 +#define CLK_BUS_UART3 65 +#define CLK_BUS_SCR 66 +#define CLK_BUS_EPHY 67 +#define CLK_BUS_DBG 68 + +#define CLK_THS 69 +#define CLK_NAND 70 +#define CLK_MMC0 71 +#define CLK_MMC0_SAMPLE 72 +#define CLK_MMC0_OUTPUT 73 +#define CLK_MMC1 74 +#define CLK_MMC1_SAMPLE 75 +#define CLK_MMC1_OUTPUT 76 +#define CLK_MMC2 77 +#define CLK_MMC2_SAMPLE 78 +#define CLK_MMC2_OUTPUT 79 +#define CLK_TS 80 +#define CLK_CE 81 +#define CLK_SPI0 82 +#define CLK_SPI1 83 +#define CLK_I2S0 84 +#define CLK_I2S1 85 +#define CLK_I2S2 86 +#define CLK_SPDIF 87 +#define CLK_USB_PHY0 88 +#define CLK_USB_PHY1 89 +#define CLK_USB_PHY2 90 +#define CLK_USB_PHY3 91 +#define CLK_USB_OHCI0 92 +#define CLK_USB_OHCI1 93 +#define CLK_USB_OHCI2 94 +#define CLK_USB_OHCI3 95 + +#define CLK_DRAM_VE 97 +#define CLK_DRAM_CSI 98 +#define CLK_DRAM_DEINTERLACE 99 +#define CLK_DRAM_TS 100 +#define CLK_DE 101 +#define CLK_TCON0 102 +#define CLK_TVE 103 +#define CLK_DEINTERLACE 104 +#define CLK_CSI_MISC 105 +#define CLK_CSI_SCLK 106 +#define CLK_CSI_MCLK 107 +#define CLK_VE 108 +#define CLK_AC_DIG 109 +#define CLK_AVS 110 +#define CLK_HDMI 111 +#define CLK_HDMI_DDC 112 + +#define CLK_GPU 114 + +#endif /* _DT_BINDINGS_CLK_SUN8I_H3_H_ */ diff --git a/include/dt-bindings/reset/sun8i-h3-ccu.h b/include/dt-bindings/reset/sun8i-h3-ccu.h new file mode 100644 index 000000000000..6b7af80c26ec --- /dev/null +++ b/include/dt-bindings/reset/sun8i-h3-ccu.h @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2016 Maxime Ripard + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file 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 file 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. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef _DT_BINDINGS_RST_SUN8I_H3_H_ +#define _DT_BINDINGS_RST_SUN8I_H3_H_ + +#define RST_USB_PHY0 0 +#define RST_USB_PHY1 1 +#define RST_USB_PHY2 2 +#define RST_USB_PHY3 3 + +#define RST_MBUS 4 + +#define RST_BUS_CE 5 +#define RST_BUS_DMA 6 +#define RST_BUS_MMC0 7 +#define RST_BUS_MMC1 8 +#define RST_BUS_MMC2 9 +#define RST_BUS_NAND 10 +#define RST_BUS_DRAM 11 +#define RST_BUS_EMAC 12 +#define RST_BUS_TS 13 +#define RST_BUS_HSTIMER 14 +#define RST_BUS_SPI0 15 +#define RST_BUS_SPI1 16 +#define RST_BUS_OTG 17 +#define RST_BUS_EHCI0 18 +#define RST_BUS_EHCI1 19 +#define RST_BUS_EHCI2 20 +#define RST_BUS_EHCI3 21 +#define RST_BUS_OHCI0 22 +#define RST_BUS_OHCI1 23 +#define RST_BUS_OHCI2 24 +#define RST_BUS_OHCI3 25 +#define RST_BUS_VE 26 +#define RST_BUS_TCON0 27 +#define RST_BUS_TCON1 28 +#define RST_BUS_DEINTERLACE 29 +#define RST_BUS_CSI 30 +#define RST_BUS_TVE 31 +#define RST_BUS_HDMI0 32 +#define RST_BUS_HDMI1 33 +#define RST_BUS_DE 34 +#define RST_BUS_GPU 35 +#define RST_BUS_MSGBOX 36 +#define RST_BUS_SPINLOCK 37 +#define RST_BUS_DBG 38 +#define RST_BUS_EPHY 39 +#define RST_BUS_CODEC 40 +#define RST_BUS_SPDIF 41 +#define RST_BUS_THS 42 +#define RST_BUS_I2S0 43 +#define RST_BUS_I2S1 44 +#define RST_BUS_I2S2 45 +#define RST_BUS_I2C0 46 +#define RST_BUS_I2C1 47 +#define RST_BUS_I2C2 48 +#define RST_BUS_UART0 49 +#define RST_BUS_UART1 50 +#define RST_BUS_UART2 51 +#define RST_BUS_UART3 52 +#define RST_BUS_SCR 53 + +#endif /* _DT_BINDINGS_RST_SUN8I_H3_H_ */ -- cgit v1.2.3 From 0bd8fa260821f34a64163c01a74f293745527cef Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 11 Jul 2016 22:34:47 +0200 Subject: clk: sunxi-ng: h3: Fix audio clock divider offset The code had a typo and got the wrong offset for the hardcoded divider, fix that. Signed-off-by: Maxime Ripard Reported-by: Jean-Francois Moine Reported-by: Chen-Yu Tsai Signed-off-by: Michael Turquette Link: lkml.kernel.org/r/20160711203448.18062-1-maxime.ripard@free-electrons.com --- drivers/clk/sunxi-ng/ccu-sun8i-h3.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-h3.c b/drivers/clk/sunxi-ng/ccu-sun8i-h3.c index bcc0a95549d3..9af359544110 100644 --- a/drivers/clk/sunxi-ng/ccu-sun8i-h3.c +++ b/drivers/clk/sunxi-ng/ccu-sun8i-h3.c @@ -817,8 +817,8 @@ static void __init sun8i_h3_ccu_setup(struct device_node *node) /* Force the PLL-Audio-1x divider to 4 */ val = readl(reg + SUN8I_H3_PLL_AUDIO_REG); - val &= ~GENMASK(4, 0); - writel(val | 3, reg + SUN8I_H3_PLL_AUDIO_REG); + val &= ~GENMASK(19, 16); + writel(val | (3 << 16), reg + SUN8I_H3_PLL_AUDIO_REG); sunxi_ccu_probe(node, reg, &sun8i_h3_ccu_desc); } -- cgit v1.2.3 From 5dc3916386c58fc97741abb1a013258a2b2b7346 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 11 Jul 2016 22:34:48 +0200 Subject: clk: sunxi-ng: h3: Fix Kconfig symbol typo The Kconfig symbol for the sun8i SoC family was mistyped. Fix that. Signed-off-by: Maxime Ripard Signed-off-by: Michael Turquette Link: lkml.kernel.org/r/20160711203448.18062-2-maxime.ripard@free-electrons.com --- drivers/clk/sunxi-ng/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-ng/Kconfig index 41e53e8d4d41..2afcbd39e41e 100644 --- a/drivers/clk/sunxi-ng/Kconfig +++ b/drivers/clk/sunxi-ng/Kconfig @@ -60,6 +60,6 @@ config SUN8I_H3_CCU select SUNXI_CCU_NM select SUNXI_CCU_MP select SUNXI_CCU_PHASE - default ARCH_SUN8I + default MACH_SUN8I endif -- cgit v1.2.3 From f38f51992347f80f982e50160596fd5388a43797 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Wed, 29 Jun 2016 21:05:35 +0200 Subject: ARM: dt: sun8i: switch the H3 to the new CCU driver Now that we have a different clock representation, switch to it. Signed-off-by: Maxime Ripard Signed-off-by: Michael Turquette Link: lkml.kernel.org/r/20160629190535.11855-15-maxime.ripard@free-electrons.com --- arch/arm/boot/dts/sun8i-h3.dtsi | 312 ++++++++-------------------------------- 1 file changed, 60 insertions(+), 252 deletions(-) diff --git a/arch/arm/boot/dts/sun8i-h3.dtsi b/arch/arm/boot/dts/sun8i-h3.dtsi index 4a4926b0b0ed..9871bad34742 100644 --- a/arch/arm/boot/dts/sun8i-h3.dtsi +++ b/arch/arm/boot/dts/sun8i-h3.dtsi @@ -42,8 +42,10 @@ #include "skeleton.dtsi" +#include #include #include +#include / { interrupt-parent = <&gic>; @@ -104,191 +106,6 @@ clock-output-names = "osc32k"; }; - pll1: clk@01c20000 { - #clock-cells = <0>; - compatible = "allwinner,sun8i-a23-pll1-clk"; - reg = <0x01c20000 0x4>; - clocks = <&osc24M>; - clock-output-names = "pll1"; - }; - - /* dummy clock until actually implemented */ - pll5: pll5_clk { - #clock-cells = <0>; - compatible = "fixed-clock"; - clock-frequency = <0>; - clock-output-names = "pll5"; - }; - - pll6: clk@01c20028 { - #clock-cells = <1>; - compatible = "allwinner,sun6i-a31-pll6-clk"; - reg = <0x01c20028 0x4>; - clocks = <&osc24M>; - clock-output-names = "pll6", "pll6x2"; - }; - - pll6d2: pll6d2_clk { - #clock-cells = <0>; - compatible = "fixed-factor-clock"; - clock-div = <2>; - clock-mult = <1>; - clocks = <&pll6 0>; - clock-output-names = "pll6d2"; - }; - - /* dummy clock until pll6 can be reused */ - pll8: pll8_clk { - #clock-cells = <0>; - compatible = "fixed-clock"; - clock-frequency = <1>; - clock-output-names = "pll8"; - }; - - cpu: cpu_clk@01c20050 { - #clock-cells = <0>; - compatible = "allwinner,sun4i-a10-cpu-clk"; - reg = <0x01c20050 0x4>; - clocks = <&osc32k>, <&osc24M>, <&pll1>, <&pll1>; - clock-output-names = "cpu"; - }; - - axi: axi_clk@01c20050 { - #clock-cells = <0>; - compatible = "allwinner,sun4i-a10-axi-clk"; - reg = <0x01c20050 0x4>; - clocks = <&cpu>; - clock-output-names = "axi"; - }; - - ahb1: ahb1_clk@01c20054 { - #clock-cells = <0>; - compatible = "allwinner,sun6i-a31-ahb1-clk"; - reg = <0x01c20054 0x4>; - clocks = <&osc32k>, <&osc24M>, <&axi>, <&pll6 0>; - clock-output-names = "ahb1"; - }; - - ahb2: ahb2_clk@01c2005c { - #clock-cells = <0>; - compatible = "allwinner,sun8i-h3-ahb2-clk"; - reg = <0x01c2005c 0x4>; - clocks = <&ahb1>, <&pll6d2>; - clock-output-names = "ahb2"; - }; - - apb1: apb1_clk@01c20054 { - #clock-cells = <0>; - compatible = "allwinner,sun4i-a10-apb0-clk"; - reg = <0x01c20054 0x4>; - clocks = <&ahb1>; - clock-output-names = "apb1"; - }; - - apb2: apb2_clk@01c20058 { - #clock-cells = <0>; - compatible = "allwinner,sun4i-a10-apb1-clk"; - reg = <0x01c20058 0x4>; - clocks = <&osc32k>, <&osc24M>, <&pll6 0>, <&pll6 0>; - clock-output-names = "apb2"; - }; - - bus_gates: clk@01c20060 { - #clock-cells = <1>; - compatible = "allwinner,sun8i-h3-bus-gates-clk"; - reg = <0x01c20060 0x14>; - clocks = <&ahb1>, <&ahb2>, <&apb1>, <&apb2>; - clock-names = "ahb1", "ahb2", "apb1", "apb2"; - clock-indices = <5>, <6>, <8>, - <9>, <10>, <13>, - <14>, <17>, <18>, - <19>, <20>, - <21>, <23>, - <24>, <25>, - <26>, <27>, - <28>, <29>, - <30>, <31>, <32>, - <35>, <36>, <37>, - <40>, <41>, <43>, - <44>, <52>, <53>, - <54>, <64>, - <65>, <69>, <72>, - <76>, <77>, <78>, - <96>, <97>, <98>, - <112>, <113>, - <114>, <115>, - <116>, <128>, <135>; - clock-output-names = "bus_ce", "bus_dma", "bus_mmc0", - "bus_mmc1", "bus_mmc2", "bus_nand", - "bus_sdram", "bus_gmac", "bus_ts", - "bus_hstimer", "bus_spi0", - "bus_spi1", "bus_otg", - "bus_otg_ehci0", "bus_ehci1", - "bus_ehci2", "bus_ehci3", - "bus_otg_ohci0", "bus_ohci1", - "bus_ohci2", "bus_ohci3", "bus_ve", - "bus_lcd0", "bus_lcd1", "bus_deint", - "bus_csi", "bus_tve", "bus_hdmi", - "bus_de", "bus_gpu", "bus_msgbox", - "bus_spinlock", "bus_codec", - "bus_spdif", "bus_pio", "bus_ths", - "bus_i2s0", "bus_i2s1", "bus_i2s2", - "bus_i2c0", "bus_i2c1", "bus_i2c2", - "bus_uart0", "bus_uart1", - "bus_uart2", "bus_uart3", - "bus_scr", "bus_ephy", "bus_dbg"; - }; - - mmc0_clk: clk@01c20088 { - #clock-cells = <1>; - compatible = "allwinner,sun4i-a10-mmc-clk"; - reg = <0x01c20088 0x4>; - clocks = <&osc24M>, <&pll6 0>, <&pll8>; - clock-output-names = "mmc0", - "mmc0_output", - "mmc0_sample"; - }; - - mmc1_clk: clk@01c2008c { - #clock-cells = <1>; - compatible = "allwinner,sun4i-a10-mmc-clk"; - reg = <0x01c2008c 0x4>; - clocks = <&osc24M>, <&pll6 0>, <&pll8>; - clock-output-names = "mmc1", - "mmc1_output", - "mmc1_sample"; - }; - - mmc2_clk: clk@01c20090 { - #clock-cells = <1>; - compatible = "allwinner,sun4i-a10-mmc-clk"; - reg = <0x01c20090 0x4>; - clocks = <&osc24M>, <&pll6 0>, <&pll8>; - clock-output-names = "mmc2", - "mmc2_output", - "mmc2_sample"; - }; - - usb_clk: clk@01c200cc { - #clock-cells = <1>; - #reset-cells = <1>; - compatible = "allwinner,sun8i-h3-usb-clk"; - reg = <0x01c200cc 0x4>; - clocks = <&osc24M>; - clock-output-names = "usb_phy0", "usb_phy1", - "usb_phy2", "usb_phy3", - "usb_ohci0", "usb_ohci1", - "usb_ohci2", "usb_ohci3"; - }; - - mbus_clk: clk@01c2015c { - #clock-cells = <0>; - compatible = "allwinner,sun8i-a23-mbus-clk"; - reg = <0x01c2015c 0x4>; - clocks = <&osc24M>, <&pll6 1>, <&pll5>; - clock-output-names = "mbus"; - }; - apb0: apb0_clk { compatible = "fixed-factor-clock"; #clock-cells = <0>; @@ -327,23 +144,23 @@ compatible = "allwinner,sun8i-h3-dma"; reg = <0x01c02000 0x1000>; interrupts = ; - clocks = <&bus_gates 6>; - resets = <&ahb_rst 6>; + clocks = <&ccu CLK_BUS_DMA>; + resets = <&ccu RST_BUS_DMA>; #dma-cells = <1>; }; mmc0: mmc@01c0f000 { compatible = "allwinner,sun5i-a13-mmc"; reg = <0x01c0f000 0x1000>; - clocks = <&bus_gates 8>, - <&mmc0_clk 0>, - <&mmc0_clk 1>, - <&mmc0_clk 2>; + clocks = <&ccu CLK_BUS_MMC0>, + <&ccu CLK_MMC0>, + <&ccu CLK_MMC0_OUTPUT>, + <&ccu CLK_MMC0_SAMPLE>; clock-names = "ahb", "mmc", "output", "sample"; - resets = <&ahb_rst 8>; + resets = <&ccu RST_BUS_MMC0>; reset-names = "ahb"; interrupts = ; status = "disabled"; @@ -354,15 +171,15 @@ mmc1: mmc@01c10000 { compatible = "allwinner,sun5i-a13-mmc"; reg = <0x01c10000 0x1000>; - clocks = <&bus_gates 9>, - <&mmc1_clk 0>, - <&mmc1_clk 1>, - <&mmc1_clk 2>; + clocks = <&ccu CLK_BUS_MMC1>, + <&ccu CLK_MMC1>, + <&ccu CLK_MMC1_OUTPUT>, + <&ccu CLK_MMC1_SAMPLE>; clock-names = "ahb", "mmc", "output", "sample"; - resets = <&ahb_rst 9>; + resets = <&ccu RST_BUS_MMC1>; reset-names = "ahb"; interrupts = ; status = "disabled"; @@ -373,15 +190,15 @@ mmc2: mmc@01c11000 { compatible = "allwinner,sun5i-a13-mmc"; reg = <0x01c11000 0x1000>; - clocks = <&bus_gates 10>, - <&mmc2_clk 0>, - <&mmc2_clk 1>, - <&mmc2_clk 2>; + clocks = <&ccu CLK_BUS_MMC2>, + <&ccu CLK_MMC2>, + <&ccu CLK_MMC2_OUTPUT>, + <&ccu CLK_MMC2_SAMPLE>; clock-names = "ahb", "mmc", "output", "sample"; - resets = <&ahb_rst 10>; + resets = <&ccu RST_BUS_MMC2>; reset-names = "ahb"; interrupts = ; status = "disabled"; @@ -401,18 +218,18 @@ "pmu1", "pmu2", "pmu3"; - clocks = <&usb_clk 8>, - <&usb_clk 9>, - <&usb_clk 10>, - <&usb_clk 11>; + clocks = <&ccu CLK_USB_PHY0>, + <&ccu CLK_USB_PHY1>, + <&ccu CLK_USB_PHY2>, + <&ccu CLK_USB_PHY3>; clock-names = "usb0_phy", "usb1_phy", "usb2_phy", "usb3_phy"; - resets = <&usb_clk 0>, - <&usb_clk 1>, - <&usb_clk 2>, - <&usb_clk 3>; + resets = <&ccu RST_USB_PHY0>, + <&ccu RST_USB_PHY1>, + <&ccu RST_USB_PHY2>, + <&ccu RST_USB_PHY3>; reset-names = "usb0_reset", "usb1_reset", "usb2_reset", @@ -425,8 +242,8 @@ compatible = "allwinner,sun8i-h3-ehci", "generic-ehci"; reg = <0x01c1b000 0x100>; interrupts = ; - clocks = <&bus_gates 25>, <&bus_gates 29>; - resets = <&ahb_rst 25>, <&ahb_rst 29>; + clocks = <&ccu CLK_BUS_EHCI1>, <&ccu CLK_BUS_OHCI1>; + resets = <&ccu RST_BUS_EHCI1>, <&ccu RST_BUS_OHCI1>; phys = <&usbphy 1>; phy-names = "usb"; status = "disabled"; @@ -436,9 +253,9 @@ compatible = "allwinner,sun8i-h3-ohci", "generic-ohci"; reg = <0x01c1b400 0x100>; interrupts = ; - clocks = <&bus_gates 29>, <&bus_gates 25>, - <&usb_clk 17>; - resets = <&ahb_rst 29>, <&ahb_rst 25>; + clocks = <&ccu CLK_BUS_EHCI1>, <&ccu CLK_BUS_OHCI1>, + <&ccu CLK_USB_OHCI1>; + resets = <&ccu RST_BUS_EHCI1>, <&ccu RST_BUS_OHCI1>; phys = <&usbphy 1>; phy-names = "usb"; status = "disabled"; @@ -448,8 +265,8 @@ compatible = "allwinner,sun8i-h3-ehci", "generic-ehci"; reg = <0x01c1c000 0x100>; interrupts = ; - clocks = <&bus_gates 26>, <&bus_gates 30>; - resets = <&ahb_rst 26>, <&ahb_rst 30>; + clocks = <&ccu CLK_BUS_EHCI2>, <&ccu CLK_BUS_OHCI2>; + resets = <&ccu RST_BUS_EHCI2>, <&ccu RST_BUS_OHCI2>; phys = <&usbphy 2>; phy-names = "usb"; status = "disabled"; @@ -459,9 +276,9 @@ compatible = "allwinner,sun8i-h3-ohci", "generic-ohci"; reg = <0x01c1c400 0x100>; interrupts = ; - clocks = <&bus_gates 30>, <&bus_gates 26>, - <&usb_clk 18>; - resets = <&ahb_rst 30>, <&ahb_rst 26>; + clocks = <&ccu CLK_BUS_EHCI2>, <&ccu CLK_BUS_OHCI2>, + <&ccu CLK_USB_OHCI2>; + resets = <&ccu RST_BUS_EHCI2>, <&ccu RST_BUS_OHCI2>; phys = <&usbphy 2>; phy-names = "usb"; status = "disabled"; @@ -471,8 +288,8 @@ compatible = "allwinner,sun8i-h3-ehci", "generic-ehci"; reg = <0x01c1d000 0x100>; interrupts = ; - clocks = <&bus_gates 27>, <&bus_gates 31>; - resets = <&ahb_rst 27>, <&ahb_rst 31>; + clocks = <&ccu CLK_BUS_EHCI3>, <&ccu CLK_BUS_OHCI3>; + resets = <&ccu RST_BUS_EHCI3>, <&ccu RST_BUS_OHCI3>; phys = <&usbphy 3>; phy-names = "usb"; status = "disabled"; @@ -482,20 +299,29 @@ compatible = "allwinner,sun8i-h3-ohci", "generic-ohci"; reg = <0x01c1d400 0x100>; interrupts = ; - clocks = <&bus_gates 31>, <&bus_gates 27>, - <&usb_clk 19>; - resets = <&ahb_rst 31>, <&ahb_rst 27>; + clocks = <&ccu CLK_BUS_EHCI3>, <&ccu CLK_BUS_OHCI3>, + <&ccu CLK_USB_OHCI3>; + resets = <&ccu RST_BUS_EHCI3>, <&ccu RST_BUS_OHCI3>; phys = <&usbphy 3>; phy-names = "usb"; status = "disabled"; }; + ccu: clock@01c20000 { + compatible = "allwinner,sun8i-h3-ccu"; + reg = <0x01c20000 0x400>; + clocks = <&osc24M>, <&osc32k>; + clock-names = "hosc", "losc"; + #clock-cells = <1>; + #reset-cells = <1>; + }; + pio: pinctrl@01c20800 { compatible = "allwinner,sun8i-h3-pinctrl"; reg = <0x01c20800 0x400>; interrupts = , ; - clocks = <&bus_gates 69>; + clocks = <&ccu CLK_BUS_PIO>; gpio-controller; #gpio-cells = <3>; interrupt-controller; @@ -542,24 +368,6 @@ }; }; - ahb_rst: reset@01c202c0 { - #reset-cells = <1>; - compatible = "allwinner,sun6i-a31-ahb1-reset"; - reg = <0x01c202c0 0xc>; - }; - - apb1_rst: reset@01c202d0 { - #reset-cells = <1>; - compatible = "allwinner,sun6i-a31-clock-reset"; - reg = <0x01c202d0 0x4>; - }; - - apb2_rst: reset@01c202d8 { - #reset-cells = <1>; - compatible = "allwinner,sun6i-a31-clock-reset"; - reg = <0x01c202d8 0x4>; - }; - timer@01c20c00 { compatible = "allwinner,sun4i-a10-timer"; reg = <0x01c20c00 0xa0>; @@ -580,8 +388,8 @@ interrupts = ; reg-shift = <2>; reg-io-width = <4>; - clocks = <&bus_gates 112>; - resets = <&apb2_rst 16>; + clocks = <&ccu CLK_BUS_UART0>; + resets = <&ccu RST_BUS_UART0>; dmas = <&dma 6>, <&dma 6>; dma-names = "rx", "tx"; status = "disabled"; @@ -593,8 +401,8 @@ interrupts = ; reg-shift = <2>; reg-io-width = <4>; - clocks = <&bus_gates 113>; - resets = <&apb2_rst 17>; + clocks = <&ccu CLK_BUS_UART1>; + resets = <&ccu RST_BUS_UART1>; dmas = <&dma 7>, <&dma 7>; dma-names = "rx", "tx"; status = "disabled"; @@ -606,8 +414,8 @@ interrupts = ; reg-shift = <2>; reg-io-width = <4>; - clocks = <&bus_gates 114>; - resets = <&apb2_rst 18>; + clocks = <&ccu CLK_BUS_UART2>; + resets = <&ccu RST_BUS_UART2>; dmas = <&dma 8>, <&dma 8>; dma-names = "rx", "tx"; status = "disabled"; @@ -619,8 +427,8 @@ interrupts = ; reg-shift = <2>; reg-io-width = <4>; - clocks = <&bus_gates 115>; - resets = <&apb2_rst 19>; + clocks = <&ccu CLK_BUS_UART3>; + resets = <&ccu RST_BUS_UART3>; dmas = <&dma 9>, <&dma 9>; dma-names = "rx", "tx"; status = "disabled"; -- cgit v1.2.3 From 5e33ebff7eddcf333287482e29541a3c06da3db5 Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Sun, 3 Jul 2016 10:48:13 -0700 Subject: clk: imx7d: do not set parent of ethernet time/ref clocks All device trees currently in mainline specify the time clock parent using the assigned-clocks/assigned-clock-parents method, there is no need to statically assign the parent in the core clock driver. Also all current boards provide an Ethernet reference clock for the PHY externally, hence configuring the internal PHY reference clock. Furthermore, and the actual driver of this patch, specify ethernet related parents at that early point in boot leads to a warning: bad: scheduling from the idle thread! The reason for the warning is that setting the parent enables the ENET PLL since we are using CLK_OPS_PARENT_ENABLE. Enabling the ENET PLL can cause clk_pllv3_wait_lock to sleep. See also: commit fc8726a2c021 ("clk: core: support clocks which requires parents enable (part 2)"). Note that setting the ENET AXI root clock parent also requires ENET PLL to be enabled. However, U-Boot typically leaves the ENET PLL on, hence when the framework sets the parent of the first clock, it does not need to wait for the PLL to come up. But because there is currently no user of that clock, the PLL gets disabled after setting the parent. Therefore, subsequent reparenting calls of any clock which somehow rely on the ENET PLL, need to reenable the ENET PLL which leads to a sleep. Removing those subsequent reparenting calls works around this issue. Also remove comments. The code is really verbose enough. Signed-off-by: Stefan Agner Tested-by: Fabio Estevam Signed-off-by: Michael Turquette Link: lkml.kernel.org/r/20160703174813.13970-1-stefan@agner.ch --- drivers/clk/imx/clk-imx7d.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/drivers/clk/imx/clk-imx7d.c b/drivers/clk/imx/clk-imx7d.c index 79293edeb380..6ed4f8fa0667 100644 --- a/drivers/clk/imx/clk-imx7d.c +++ b/drivers/clk/imx/clk-imx7d.c @@ -860,16 +860,7 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node) /* use old gpt clk setting, gpt1 root clk must be twice as gpt counter freq */ clk_set_parent(clks[IMX7D_GPT1_ROOT_SRC], clks[IMX7D_OSC_24M_CLK]); - /* - * init enet clock source: - * AXI clock source is 250MHz - * Phy refrence clock is 25MHz - * 1588 time clock source is 100MHz - */ clk_set_parent(clks[IMX7D_ENET_AXI_ROOT_SRC], clks[IMX7D_PLL_ENET_MAIN_250M_CLK]); - clk_set_parent(clks[IMX7D_ENET_PHY_REF_ROOT_SRC], clks[IMX7D_PLL_ENET_MAIN_25M_CLK]); - clk_set_parent(clks[IMX7D_ENET1_TIME_ROOT_SRC], clks[IMX7D_PLL_ENET_MAIN_100M_CLK]); - clk_set_parent(clks[IMX7D_ENET2_TIME_ROOT_SRC], clks[IMX7D_PLL_ENET_MAIN_100M_CLK]); /* set uart module clock's parent clock source that must be great then 80MHz */ clk_set_parent(clks[IMX7D_UART1_ROOT_SRC], clks[IMX7D_OSC_24M_CLK]); -- cgit v1.2.3 From 821f9946e07b7b201fe4581bd5f6005d84b7bd42 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Thu, 7 Jul 2016 09:18:44 +0200 Subject: clk: oxnas: Add hardware dependencies The clk-oxnas driver is specific to its architecture, so do not propose it on other architectures, unless build-testing. Signed-off-by: Jean Delvare Cc: Stephen Boyd Acked-by: Neil Armstrong Signed-off-by: Michael Turquette Link: lkml.kernel.org/r/20160707091844.196a7930@endymion --- drivers/clk/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index 4d84be999f55..e2d9bd760c84 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -203,6 +203,7 @@ config COMMON_CLK_PIC32 config COMMON_CLK_OXNAS bool "Clock driver for the OXNAS SoC Family" + depends on ARCH_OXNAS || COMPILE_TEST select MFD_SYSCON ---help--- Support for the OXNAS SoC Family clocks. -- cgit v1.2.3 From 9893c9bf6a9c02ff571686f1b5820e4f0841e581 Mon Sep 17 00:00:00 2001 From: Andi Shyti Date: Tue, 12 Jul 2016 19:02:16 +0900 Subject: clk: exynos5433: remove CLK_IGNORE_UNUSED flag from SPI clocks Because the Exynos5433 SPI driver supports the ioclk handling and the following patch: http://marc.info/?l=linux-kernel&m=146787645626318&w=2 fixes a synchronus abort issue, none of the SPI clocks require any critical handling: remove, then, the CLK_IGNORE_UNUSED flag for the SPI related clocks. Signed-off-by: Andi Shyti Reviewed-by: Krzysztof Kozlowski Acked-by: Sylwester Nawrocki Signed-off-by: Michael Turquette Link: lkml.kernel.org/r/1468317736-18841-8-git-send-email-andi.shyti@samsung.com --- drivers/clk/samsung/clk-exynos5433.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/clk/samsung/clk-exynos5433.c b/drivers/clk/samsung/clk-exynos5433.c index 4204eb828d86..ea1608682d7f 100644 --- a/drivers/clk/samsung/clk-exynos5433.c +++ b/drivers/clk/samsung/clk-exynos5433.c @@ -1661,8 +1661,7 @@ static const struct samsung_gate_clock peric_gate_clks[] __initconst = { GATE(CLK_SCLK_IOCLK_SPI2, "sclk_ioclk_spi2", "ioclk_spi2_clk_in", ENABLE_SCLK_PERIC, 13, CLK_SET_RATE_PARENT, 0), GATE(CLK_SCLK_IOCLK_SPI1, "sclk_ioclk_spi1", "ioclk_spi1_clk_in", - ENABLE_SCLK_PERIC, 12, - CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0), + ENABLE_SCLK_PERIC, 12, CLK_SET_RATE_PARENT, 0), GATE(CLK_SCLK_IOCLK_SPI0, "sclk_ioclk_spi0", "ioclk_spi0_clk_in", ENABLE_SCLK_PERIC, 11, CLK_SET_RATE_PARENT, 0), GATE(CLK_SCLK_IOCLK_I2S1_BCLK, "sclk_ioclk_i2s1_bclk", @@ -1677,7 +1676,7 @@ static const struct samsung_gate_clock peric_gate_clks[] __initconst = { GATE(CLK_SCLK_SPI2, "sclk_spi2", "sclk_spi2_peric", ENABLE_SCLK_PERIC, 5, CLK_SET_RATE_PARENT, 0), GATE(CLK_SCLK_SPI1, "sclk_spi1", "sclk_spi1_peric", ENABLE_SCLK_PERIC, - 4, CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0), + 4, CLK_SET_RATE_PARENT, 0), GATE(CLK_SCLK_SPI0, "sclk_spi0", "sclk_spi0_peric", ENABLE_SCLK_PERIC, 3, CLK_SET_RATE_PARENT, 0), GATE(CLK_SCLK_UART2, "sclk_uart2", "sclk_uart2_peric", -- cgit v1.2.3 From 4c7c28ffe9658ebfb43e638d9d267e1be2ffb71c Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Mon, 4 Jul 2016 17:12:17 -0400 Subject: clk: samsung: make clk-s5pv210-audss explicitly non-modular The Kconfig currently controlling compilation of this code is: arch/arm/mach-s5pv210/Kconfig:config ARCH_S5PV210 arch/arm/mach-s5pv210/Kconfig: bool "Samsung S5PV210/S5PC110" if ARCH_MULTI_V7 ...meaning that it currently is not being built as a module by anyone. Lets remove the modular code that is essentially orphaned, so that when reading the driver there is no doubt it is builtin-only. We explicitly disallow a driver unbind, since that doesn't have a sensible use case anyway, and it allows us to drop the ".remove" code for non-modular drivers. Since this code is already not using module_init, case, the init ordering remains unchanged with this commit. We also delete the MODULE_LICENSE tags etc. since all that information is already contained at the top of the file in the comments. Cc: Tomasz Figa Cc: Stephen Boyd Cc: linux-samsung-soc@vger.kernel.org Cc: linux-clk@vger.kernel.org Signed-off-by: Paul Gortmaker Acked-by: Sylwester Nawrocki Signed-off-by: Michael Turquette Link: lkml.kernel.org/r/20160704211220.5685-8-paul.gortmaker@windriver.com --- drivers/clk/samsung/clk-s5pv210-audss.c | 29 ++--------------------------- 1 file changed, 2 insertions(+), 27 deletions(-) diff --git a/drivers/clk/samsung/clk-s5pv210-audss.c b/drivers/clk/samsung/clk-s5pv210-audss.c index eefb84b22566..c66ed2d1450e 100644 --- a/drivers/clk/samsung/clk-s5pv210-audss.c +++ b/drivers/clk/samsung/clk-s5pv210-audss.c @@ -18,7 +18,7 @@ #include #include #include -#include +#include #include #include @@ -194,20 +194,6 @@ unregister: return ret; } -static int s5pv210_audss_clk_remove(struct platform_device *pdev) -{ - int i; - - of_clk_del_provider(pdev->dev.of_node); - - for (i = 0; i < clk_data.clk_num; i++) { - if (!IS_ERR(clk_table[i])) - clk_unregister(clk_table[i]); - } - - return 0; -} - static const struct of_device_id s5pv210_audss_clk_of_match[] = { { .compatible = "samsung,s5pv210-audss-clock", }, {}, @@ -216,10 +202,10 @@ static const struct of_device_id s5pv210_audss_clk_of_match[] = { static struct platform_driver s5pv210_audss_clk_driver = { .driver = { .name = "s5pv210-audss-clk", + .suppress_bind_attrs = true, .of_match_table = s5pv210_audss_clk_of_match, }, .probe = s5pv210_audss_clk_probe, - .remove = s5pv210_audss_clk_remove, }; static int __init s5pv210_audss_clk_init(void) @@ -227,14 +213,3 @@ static int __init s5pv210_audss_clk_init(void) return platform_driver_register(&s5pv210_audss_clk_driver); } core_initcall(s5pv210_audss_clk_init); - -static void __exit s5pv210_audss_clk_exit(void) -{ - platform_driver_unregister(&s5pv210_audss_clk_driver); -} -module_exit(s5pv210_audss_clk_exit); - -MODULE_AUTHOR("Tomasz Figa "); -MODULE_DESCRIPTION("S5PV210 Audio Subsystem Clock Controller"); -MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("platform:s5pv210-audss-clk"); -- cgit v1.2.3 From 4d252fd5719bd047a178668aa09ee8bc9de85c7c Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Fri, 8 Jul 2016 16:15:00 +0200 Subject: clk: samsung: Allow modular build of the Audio Subsystem CLKCON driver Any clock dependencies can be properly handled with deferred probing so we can remove core_initcall and switch to a proper loadable platform driver module. This change has been tested on Exynos4412 Odroid U3 based board. Signed-off-by: Sylwester Nawrocki Reviewed-by: Krzysztof Kozlowski Signed-off-by: Michael Turquette Link: lkml.kernel.org/r/1467987300-31450-1-git-send-email-s.nawrocki@samsung.com --- drivers/clk/samsung/Kconfig | 9 +++++++++ drivers/clk/samsung/Makefile | 2 +- drivers/clk/samsung/clk-exynos-audss.c | 12 +----------- 3 files changed, 11 insertions(+), 12 deletions(-) diff --git a/drivers/clk/samsung/Kconfig b/drivers/clk/samsung/Kconfig index 20c5fe92ab4a..addc65270e43 100644 --- a/drivers/clk/samsung/Kconfig +++ b/drivers/clk/samsung/Kconfig @@ -9,6 +9,15 @@ config EXYNOS_ARM64_COMMON_CLK bool "Samsung Exynos ARMv8-family clock controller support" if COMPILE_TEST depends on COMMON_CLK_SAMSUNG +config EXYNOS_AUDSS_CLK_CON + tristate "Samsung Exynos AUDSS clock controller support" + depends on COMMON_CLK_SAMSUNG + default y if ARCH_EXYNOS + help + Support for the Audio Subsystem CLKCON clock controller present + on some Exynos SoC variants. Choose M or Y here if you want to + use audio devices such as I2S, PCM, etc. + # For S3C24XX platforms, select following symbols: config S3C2410_COMMON_CLK bool "Samsung S3C2410 clock controller support" if COMPILE_TEST diff --git a/drivers/clk/samsung/Makefile b/drivers/clk/samsung/Makefile index fc367d4b2902..57f4dc6dc447 100644 --- a/drivers/clk/samsung/Makefile +++ b/drivers/clk/samsung/Makefile @@ -12,7 +12,7 @@ obj-$(CONFIG_SOC_EXYNOS5410) += clk-exynos5410.o obj-$(CONFIG_SOC_EXYNOS5420) += clk-exynos5420.o obj-$(CONFIG_EXYNOS_ARM64_COMMON_CLK) += clk-exynos5433.o obj-$(CONFIG_SOC_EXYNOS5440) += clk-exynos5440.o -obj-$(CONFIG_ARCH_EXYNOS) += clk-exynos-audss.o +obj-$(CONFIG_EXYNOS_AUDSS_CLK_CON) += clk-exynos-audss.o obj-$(CONFIG_ARCH_EXYNOS) += clk-exynos-clkout.o obj-$(CONFIG_EXYNOS_ARM64_COMMON_CLK) += clk-exynos7.o obj-$(CONFIG_S3C2410_COMMON_CLK)+= clk-s3c2410.o diff --git a/drivers/clk/samsung/clk-exynos-audss.c b/drivers/clk/samsung/clk-exynos-audss.c index 4e9584d79089..bdf8b971f332 100644 --- a/drivers/clk/samsung/clk-exynos-audss.c +++ b/drivers/clk/samsung/clk-exynos-audss.c @@ -273,17 +273,7 @@ static struct platform_driver exynos_audss_clk_driver = { .remove = exynos_audss_clk_remove, }; -static int __init exynos_audss_clk_init(void) -{ - return platform_driver_register(&exynos_audss_clk_driver); -} -core_initcall(exynos_audss_clk_init); - -static void __exit exynos_audss_clk_exit(void) -{ - platform_driver_unregister(&exynos_audss_clk_driver); -} -module_exit(exynos_audss_clk_exit); +module_platform_driver(exynos_audss_clk_driver); MODULE_AUTHOR("Padmavathi Venna "); MODULE_DESCRIPTION("Exynos Audio Subsystem Clock Controller"); -- cgit v1.2.3 From ca1d2e269f593b318a75f3ffb9befc1ec8b6f2fd Mon Sep 17 00:00:00 2001 From: Michael Turquette Date: Fri, 15 Jul 2016 19:13:36 -0700 Subject: Revert "clk: gxbb: expose CLKID_MMC_PCLK" This reverts commit e16fb2e6355c1c1b41623af9e01ada196e2af098. Updated documentation from the chip vendor reveals that this clock is not required for correct operation of the MMC controller. As such, do not expose it to DT. Signed-off-by: Michael Turquette --- drivers/clk/meson/gxbb.h | 2 +- include/dt-bindings/clock/gxbb-clkc.h | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/clk/meson/gxbb.h b/drivers/clk/meson/gxbb.h index 8355ecd27b81..a2adf3448b59 100644 --- a/drivers/clk/meson/gxbb.h +++ b/drivers/clk/meson/gxbb.h @@ -234,7 +234,7 @@ #define CLKID_HDMI_PCLK 63 #define CLKID_USB1_DDR_BRIDGE 64 #define CLKID_USB0_DDR_BRIDGE 65 -/* CLKID_MMC_PCLK */ +#define CLKID_MMC_PCLK 66 #define CLKID_DVIN 67 #define CLKID_UART2 68 #define CLKID_SANA 69 diff --git a/include/dt-bindings/clock/gxbb-clkc.h b/include/dt-bindings/clock/gxbb-clkc.h index 5eb69ec74f6b..f889d80246cb 100644 --- a/include/dt-bindings/clock/gxbb-clkc.h +++ b/include/dt-bindings/clock/gxbb-clkc.h @@ -8,6 +8,5 @@ #define CLKID_CPUCLK 1 #define CLKID_CLK81 12 #define CLKID_ETH 36 -#define CLKID_MMC_PCLK 66 #endif /* __GXBB_CLKC_H */ -- cgit v1.2.3 From b328d2c110ad7b45af9cde2bce70803df28e9553 Mon Sep 17 00:00:00 2001 From: Michael Turquette Date: Wed, 15 Jun 2016 17:09:25 -0700 Subject: clk: Makefile: re-sort and clean up Sorting is hard. Signed-off-by: Michael Turquette --- drivers/clk/Makefile | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index afbf1ad64cc2..3b6f9cf3464a 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -16,13 +16,14 @@ obj-$(CONFIG_COMMON_CLK) += clk-conf.o endif # hardware specific clock types -# please keep this section sorted lexicographically by file/directory path name +# please keep this section sorted lexicographically by file path name obj-$(CONFIG_MACH_ASM9260) += clk-asm9260.o obj-$(CONFIG_COMMON_CLK_AXI_CLKGEN) += clk-axi-clkgen.o obj-$(CONFIG_ARCH_AXXIA) += clk-axm5516.o obj-$(CONFIG_COMMON_CLK_CDCE706) += clk-cdce706.o -obj-$(CONFIG_COMMON_CLK_CS2000_CP) += clk-cs2000-cp.o +obj-$(CONFIG_COMMON_CLK_CDCE925) += clk-cdce925.o obj-$(CONFIG_ARCH_CLPS711X) += clk-clps711x.o +obj-$(CONFIG_COMMON_CLK_CS2000_CP) += clk-cs2000-cp.o obj-$(CONFIG_ARCH_EFM32) += clk-efm32gg.o obj-$(CONFIG_ARCH_HIGHBANK) += clk-highbank.o obj-$(CONFIG_MACH_LOONGSON32) += clk-ls1x.o @@ -35,6 +36,7 @@ obj-$(CONFIG_ARCH_NOMADIK) += clk-nomadik.o obj-$(CONFIG_ARCH_NSPIRE) += clk-nspire.o obj-$(CONFIG_COMMON_CLK_OXNAS) += clk-oxnas.o obj-$(CONFIG_COMMON_CLK_PALMAS) += clk-palmas.o +obj-$(CONFIG_COMMON_CLK_PWM) += clk-pwm.o obj-$(CONFIG_CLK_QORIQ) += clk-qoriq.o obj-$(CONFIG_COMMON_CLK_RK808) += clk-rk808.o obj-$(CONFIG_COMMON_CLK_S2MPS11) += clk-s2mps11.o @@ -42,7 +44,6 @@ obj-$(CONFIG_COMMON_CLK_SCPI) += clk-scpi.o obj-$(CONFIG_COMMON_CLK_SI5351) += clk-si5351.o obj-$(CONFIG_COMMON_CLK_SI514) += clk-si514.o obj-$(CONFIG_COMMON_CLK_SI570) += clk-si570.o -obj-$(CONFIG_COMMON_CLK_CDCE925) += clk-cdce925.o obj-$(CONFIG_ARCH_STM32) += clk-stm32f4.o obj-$(CONFIG_ARCH_TANGO) += clk-tango4.o obj-$(CONFIG_CLK_TWL6040) += clk-twl6040.o @@ -50,30 +51,33 @@ obj-$(CONFIG_ARCH_U300) += clk-u300.o obj-$(CONFIG_ARCH_VT8500) += clk-vt8500.o obj-$(CONFIG_COMMON_CLK_WM831X) += clk-wm831x.o obj-$(CONFIG_COMMON_CLK_XGENE) += clk-xgene.o -obj-$(CONFIG_COMMON_CLK_PWM) += clk-pwm.o + +# please keep this section sorted lexicographically by directory path name obj-$(CONFIG_COMMON_CLK_AT91) += at91/ obj-$(CONFIG_ARCH_ARTPEC) += axis/ +obj-$(CONFIG_ARC_PLAT_AXS10X) += axs10x/ obj-y += bcm/ obj-$(CONFIG_ARCH_BERLIN) += berlin/ +obj-$(CONFIG_H8300) += h8300/ obj-$(CONFIG_ARCH_HISI) += hisilicon/ obj-$(CONFIG_ARCH_MXC) += imx/ obj-$(CONFIG_MACH_INGENIC) += ingenic/ obj-$(CONFIG_COMMON_CLK_KEYSTONE) += keystone/ obj-$(CONFIG_ARCH_MEDIATEK) += mediatek/ +obj-$(CONFIG_COMMON_CLK_AMLOGIC) += meson/ obj-$(CONFIG_MACH_PIC32) += microchip/ ifeq ($(CONFIG_COMMON_CLK), y) obj-$(CONFIG_ARCH_MMP) += mmp/ endif obj-y += mvebu/ -obj-$(CONFIG_COMMON_CLK_AMLOGIC) += meson/ obj-$(CONFIG_ARCH_MXS) += mxs/ -obj-$(CONFIG_MACH_PISTACHIO) += pistachio/ obj-$(CONFIG_COMMON_CLK_NXP) += nxp/ +obj-$(CONFIG_MACH_PISTACHIO) += pistachio/ obj-$(CONFIG_COMMON_CLK_PXA) += pxa/ obj-$(CONFIG_COMMON_CLK_QCOM) += qcom/ +obj-$(CONFIG_ARCH_RENESAS) += renesas/ obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/ obj-$(CONFIG_COMMON_CLK_SAMSUNG) += samsung/ -obj-$(CONFIG_ARCH_RENESAS) += renesas/ obj-$(CONFIG_ARCH_SIRF) += sirf/ obj-$(CONFIG_ARCH_SOCFPGA) += socfpga/ obj-$(CONFIG_PLAT_SPEAR) += spear/ @@ -87,5 +91,3 @@ obj-$(CONFIG_COMMON_CLK_VERSATILE) += versatile/ obj-$(CONFIG_X86) += x86/ obj-$(CONFIG_ARCH_ZX) += zte/ obj-$(CONFIG_ARCH_ZYNQ) += zynq/ -obj-$(CONFIG_H8300) += h8300/ -obj-$(CONFIG_ARC_PLAT_AXS10X) += axs10x/ -- cgit v1.2.3