Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

cpufreq: exynos: Fix driver compilation with ARCH_MULTIPLATFORM

Currently Exynos cpufreq drivers rely on globally mapped
clock controller registers to configure frequency of CPU
cores. This is obviously wrong and will be removed in near
future, but to enable support for multi-platform builds
without introducing a regression it needs to be worked
around.

This patch hacks the code to look for clock controller node
in device tree and map its registers using of_iomap(),
instead of relying on global mapping, so dependencies on
platform headers are removed and the driver can compile
again with multiplatform support.

Signed-off-by: Tomasz Figa <t.figa@samsung.com>
Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>

authored by

Tomasz Figa and committed by
Kukjin Kim
4c8d8193 9dfa92ec

+119 -41
+3 -3
drivers/cpufreq/Kconfig.arm
··· 30 30 31 31 config ARM_EXYNOS4210_CPUFREQ 32 32 bool "SAMSUNG EXYNOS4210" 33 - depends on CPU_EXYNOS4210 && !ARCH_MULTIPLATFORM 33 + depends on CPU_EXYNOS4210 34 34 default y 35 35 select ARM_EXYNOS_CPUFREQ 36 36 help ··· 41 41 42 42 config ARM_EXYNOS4X12_CPUFREQ 43 43 bool "SAMSUNG EXYNOS4x12" 44 - depends on (SOC_EXYNOS4212 || SOC_EXYNOS4412) && !ARCH_MULTIPLATFORM 44 + depends on SOC_EXYNOS4212 || SOC_EXYNOS4412 45 45 default y 46 46 select ARM_EXYNOS_CPUFREQ 47 47 help ··· 52 52 53 53 config ARM_EXYNOS5250_CPUFREQ 54 54 bool "SAMSUNG EXYNOS5250" 55 - depends on SOC_EXYNOS5250 && !ARCH_MULTIPLATFORM 55 + depends on SOC_EXYNOS5250 56 56 default y 57 57 select ARM_EXYNOS_CPUFREQ 58 58 help
-2
drivers/cpufreq/exynos-cpufreq.c
··· 19 19 #include <linux/platform_device.h> 20 20 #include <linux/of.h> 21 21 22 - #include <plat/cpu.h> 23 - 24 22 #include "exynos-cpufreq.h" 25 23 26 24 static struct exynos_dvfs_info *exynos_info;
+14 -16
drivers/cpufreq/exynos-cpufreq.h
··· 49 49 struct cpufreq_frequency_table *freq_table; 50 50 void (*set_freq)(unsigned int, unsigned int); 51 51 bool (*need_apll_change)(unsigned int, unsigned int); 52 + void __iomem *cmu_regs; 52 53 }; 53 54 54 55 #ifdef CONFIG_ARM_EXYNOS4210_CPUFREQ ··· 77 76 } 78 77 #endif 79 78 80 - #include <plat/cpu.h> 81 - #include <mach/map.h> 79 + #define EXYNOS4_CLKSRC_CPU 0x14200 80 + #define EXYNOS4_CLKMUX_STATCPU 0x14400 82 81 83 - #define EXYNOS4_CLKSRC_CPU (S5P_VA_CMU + 0x14200) 84 - #define EXYNOS4_CLKMUX_STATCPU (S5P_VA_CMU + 0x14400) 85 - 86 - #define EXYNOS4_CLKDIV_CPU (S5P_VA_CMU + 0x14500) 87 - #define EXYNOS4_CLKDIV_CPU1 (S5P_VA_CMU + 0x14504) 88 - #define EXYNOS4_CLKDIV_STATCPU (S5P_VA_CMU + 0x14600) 89 - #define EXYNOS4_CLKDIV_STATCPU1 (S5P_VA_CMU + 0x14604) 82 + #define EXYNOS4_CLKDIV_CPU 0x14500 83 + #define EXYNOS4_CLKDIV_CPU1 0x14504 84 + #define EXYNOS4_CLKDIV_STATCPU 0x14600 85 + #define EXYNOS4_CLKDIV_STATCPU1 0x14604 90 86 91 87 #define EXYNOS4_CLKSRC_CPU_MUXCORE_SHIFT (16) 92 88 #define EXYNOS4_CLKMUX_STATCPU_MUXCORE_MASK (0x7 << EXYNOS4_CLKSRC_CPU_MUXCORE_SHIFT) 93 89 94 - #define EXYNOS5_APLL_LOCK (S5P_VA_CMU + 0x00000) 95 - #define EXYNOS5_APLL_CON0 (S5P_VA_CMU + 0x00100) 96 - #define EXYNOS5_CLKMUX_STATCPU (S5P_VA_CMU + 0x00400) 97 - #define EXYNOS5_CLKDIV_CPU0 (S5P_VA_CMU + 0x00500) 98 - #define EXYNOS5_CLKDIV_CPU1 (S5P_VA_CMU + 0x00504) 99 - #define EXYNOS5_CLKDIV_STATCPU0 (S5P_VA_CMU + 0x00600) 100 - #define EXYNOS5_CLKDIV_STATCPU1 (S5P_VA_CMU + 0x00604) 90 + #define EXYNOS5_APLL_LOCK 0x00000 91 + #define EXYNOS5_APLL_CON0 0x00100 92 + #define EXYNOS5_CLKMUX_STATCPU 0x00400 93 + #define EXYNOS5_CLKDIV_CPU0 0x00500 94 + #define EXYNOS5_CLKDIV_CPU1 0x00504 95 + #define EXYNOS5_CLKDIV_STATCPU0 0x00600 96 + #define EXYNOS5_CLKDIV_STATCPU1 0x00604
+33 -6
drivers/cpufreq/exynos4210-cpufreq.c
··· 16 16 #include <linux/io.h> 17 17 #include <linux/slab.h> 18 18 #include <linux/cpufreq.h> 19 + #include <linux/of.h> 20 + #include <linux/of_address.h> 19 21 20 22 #include "exynos-cpufreq.h" 21 23 ··· 25 23 static struct clk *moutcore; 26 24 static struct clk *mout_mpll; 27 25 static struct clk *mout_apll; 26 + static struct exynos_dvfs_info *cpufreq; 28 27 29 28 static unsigned int exynos4210_volt_table[] = { 30 29 1250000, 1150000, 1050000, 975000, 950000, ··· 63 60 64 61 tmp = apll_freq_4210[div_index].clk_div_cpu0; 65 62 66 - __raw_writel(tmp, EXYNOS4_CLKDIV_CPU); 63 + __raw_writel(tmp, cpufreq->cmu_regs + EXYNOS4_CLKDIV_CPU); 67 64 68 65 do { 69 - tmp = __raw_readl(EXYNOS4_CLKDIV_STATCPU); 66 + tmp = __raw_readl(cpufreq->cmu_regs + EXYNOS4_CLKDIV_STATCPU); 70 67 } while (tmp & 0x1111111); 71 68 72 69 /* Change Divider - CPU1 */ 73 70 74 71 tmp = apll_freq_4210[div_index].clk_div_cpu1; 75 72 76 - __raw_writel(tmp, EXYNOS4_CLKDIV_CPU1); 73 + __raw_writel(tmp, cpufreq->cmu_regs + EXYNOS4_CLKDIV_CPU1); 77 74 78 75 do { 79 - tmp = __raw_readl(EXYNOS4_CLKDIV_STATCPU1); 76 + tmp = __raw_readl(cpufreq->cmu_regs + EXYNOS4_CLKDIV_STATCPU1); 80 77 } while (tmp & 0x11); 81 78 } 82 79 ··· 88 85 clk_set_parent(moutcore, mout_mpll); 89 86 90 87 do { 91 - tmp = (__raw_readl(EXYNOS4_CLKMUX_STATCPU) 88 + tmp = (__raw_readl(cpufreq->cmu_regs + EXYNOS4_CLKMUX_STATCPU) 92 89 >> EXYNOS4_CLKSRC_CPU_MUXCORE_SHIFT); 93 90 tmp &= 0x7; 94 91 } while (tmp != 0x2); ··· 99 96 clk_set_parent(moutcore, mout_apll); 100 97 101 98 do { 102 - tmp = __raw_readl(EXYNOS4_CLKMUX_STATCPU); 99 + tmp = __raw_readl(cpufreq->cmu_regs + EXYNOS4_CLKMUX_STATCPU); 103 100 tmp &= EXYNOS4_CLKMUX_STATCPU_MUXCORE_MASK; 104 101 } while (tmp != (0x1 << EXYNOS4_CLKSRC_CPU_MUXCORE_SHIFT)); 105 102 } ··· 118 115 119 116 int exynos4210_cpufreq_init(struct exynos_dvfs_info *info) 120 117 { 118 + struct device_node *np; 121 119 unsigned long rate; 120 + 121 + /* 122 + * HACK: This is a temporary workaround to get access to clock 123 + * controller registers directly and remove static mappings and 124 + * dependencies on platform headers. It is necessary to enable 125 + * Exynos multi-platform support and will be removed together with 126 + * this whole driver as soon as Exynos gets migrated to use 127 + * cpufreq-cpu0 driver. 128 + */ 129 + np = of_find_compatible_node(NULL, NULL, "samsung,exynos4210-clock"); 130 + if (!np) { 131 + pr_err("%s: failed to find clock controller DT node\n", 132 + __func__); 133 + return -ENODEV; 134 + } 135 + 136 + info->cmu_regs = of_iomap(np, 0); 137 + if (!info->cmu_regs) { 138 + pr_err("%s: failed to map CMU registers\n", __func__); 139 + return -EFAULT; 140 + } 122 141 123 142 cpu_clk = clk_get(NULL, "armclk"); 124 143 if (IS_ERR(cpu_clk)) ··· 167 142 info->volt_table = exynos4210_volt_table; 168 143 info->freq_table = exynos4210_freq_table; 169 144 info->set_freq = exynos4210_set_frequency; 145 + 146 + cpufreq = info; 170 147 171 148 return 0; 172 149
+34 -6
drivers/cpufreq/exynos4x12-cpufreq.c
··· 16 16 #include <linux/io.h> 17 17 #include <linux/slab.h> 18 18 #include <linux/cpufreq.h> 19 + #include <linux/of.h> 20 + #include <linux/of_address.h> 19 21 20 22 #include "exynos-cpufreq.h" 21 23 ··· 25 23 static struct clk *moutcore; 26 24 static struct clk *mout_mpll; 27 25 static struct clk *mout_apll; 26 + static struct exynos_dvfs_info *cpufreq; 28 27 29 28 static unsigned int exynos4x12_volt_table[] = { 30 29 1350000, 1287500, 1250000, 1187500, 1137500, 1087500, 1037500, ··· 108 105 109 106 tmp = apll_freq_4x12[div_index].clk_div_cpu0; 110 107 111 - __raw_writel(tmp, EXYNOS4_CLKDIV_CPU); 108 + __raw_writel(tmp, cpufreq->cmu_regs + EXYNOS4_CLKDIV_CPU); 112 109 113 - while (__raw_readl(EXYNOS4_CLKDIV_STATCPU) & 0x11111111) 110 + while (__raw_readl(cpufreq->cmu_regs + EXYNOS4_CLKDIV_STATCPU) 111 + & 0x11111111) 114 112 cpu_relax(); 115 113 116 114 /* Change Divider - CPU1 */ 117 115 tmp = apll_freq_4x12[div_index].clk_div_cpu1; 118 116 119 - __raw_writel(tmp, EXYNOS4_CLKDIV_CPU1); 117 + __raw_writel(tmp, cpufreq->cmu_regs + EXYNOS4_CLKDIV_CPU1); 120 118 121 119 do { 122 120 cpu_relax(); 123 - tmp = __raw_readl(EXYNOS4_CLKDIV_STATCPU1); 121 + tmp = __raw_readl(cpufreq->cmu_regs + EXYNOS4_CLKDIV_STATCPU1); 124 122 } while (tmp != 0x0); 125 123 } 126 124 ··· 134 130 135 131 do { 136 132 cpu_relax(); 137 - tmp = (__raw_readl(EXYNOS4_CLKMUX_STATCPU) 133 + tmp = (__raw_readl(cpufreq->cmu_regs + EXYNOS4_CLKMUX_STATCPU) 138 134 >> EXYNOS4_CLKSRC_CPU_MUXCORE_SHIFT); 139 135 tmp &= 0x7; 140 136 } while (tmp != 0x2); ··· 146 142 147 143 do { 148 144 cpu_relax(); 149 - tmp = __raw_readl(EXYNOS4_CLKMUX_STATCPU); 145 + tmp = __raw_readl(cpufreq->cmu_regs + EXYNOS4_CLKMUX_STATCPU); 150 146 tmp &= EXYNOS4_CLKMUX_STATCPU_MUXCORE_MASK; 151 147 } while (tmp != (0x1 << EXYNOS4_CLKSRC_CPU_MUXCORE_SHIFT)); 152 148 } ··· 165 161 166 162 int exynos4x12_cpufreq_init(struct exynos_dvfs_info *info) 167 163 { 164 + struct device_node *np; 168 165 unsigned long rate; 166 + 167 + /* 168 + * HACK: This is a temporary workaround to get access to clock 169 + * controller registers directly and remove static mappings and 170 + * dependencies on platform headers. It is necessary to enable 171 + * Exynos multi-platform support and will be removed together with 172 + * this whole driver as soon as Exynos gets migrated to use 173 + * cpufreq-cpu0 driver. 174 + */ 175 + np = of_find_compatible_node(NULL, NULL, "samsung,exynos4412-clock"); 176 + if (!np) { 177 + pr_err("%s: failed to find clock controller DT node\n", 178 + __func__); 179 + return -ENODEV; 180 + } 181 + 182 + info->cmu_regs = of_iomap(np, 0); 183 + if (!info->cmu_regs) { 184 + pr_err("%s: failed to map CMU registers\n", __func__); 185 + return -EFAULT; 186 + } 169 187 170 188 cpu_clk = clk_get(NULL, "armclk"); 171 189 if (IS_ERR(cpu_clk)) ··· 219 193 info->volt_table = exynos4x12_volt_table; 220 194 info->freq_table = exynos4x12_freq_table; 221 195 info->set_freq = exynos4x12_set_frequency; 196 + 197 + cpufreq = info; 222 198 223 199 return 0; 224 200
+35 -8
drivers/cpufreq/exynos5250-cpufreq.c
··· 16 16 #include <linux/io.h> 17 17 #include <linux/slab.h> 18 18 #include <linux/cpufreq.h> 19 - 20 - #include <mach/map.h> 19 + #include <linux/of.h> 20 + #include <linux/of_address.h> 21 21 22 22 #include "exynos-cpufreq.h" 23 23 ··· 25 25 static struct clk *moutcore; 26 26 static struct clk *mout_mpll; 27 27 static struct clk *mout_apll; 28 + static struct exynos_dvfs_info *cpufreq; 28 29 29 30 static unsigned int exynos5250_volt_table[] = { 30 31 1300000, 1250000, 1225000, 1200000, 1150000, ··· 88 87 89 88 tmp = apll_freq_5250[div_index].clk_div_cpu0; 90 89 91 - __raw_writel(tmp, EXYNOS5_CLKDIV_CPU0); 90 + __raw_writel(tmp, cpufreq->cmu_regs + EXYNOS5_CLKDIV_CPU0); 92 91 93 - while (__raw_readl(EXYNOS5_CLKDIV_STATCPU0) & 0x11111111) 92 + while (__raw_readl(cpufreq->cmu_regs + EXYNOS5_CLKDIV_STATCPU0) 93 + & 0x11111111) 94 94 cpu_relax(); 95 95 96 96 /* Change Divider - CPU1 */ 97 97 tmp = apll_freq_5250[div_index].clk_div_cpu1; 98 98 99 - __raw_writel(tmp, EXYNOS5_CLKDIV_CPU1); 99 + __raw_writel(tmp, cpufreq->cmu_regs + EXYNOS5_CLKDIV_CPU1); 100 100 101 - while (__raw_readl(EXYNOS5_CLKDIV_STATCPU1) & 0x11) 101 + while (__raw_readl(cpufreq->cmu_regs + EXYNOS5_CLKDIV_STATCPU1) & 0x11) 102 102 cpu_relax(); 103 103 } 104 104 ··· 113 111 114 112 do { 115 113 cpu_relax(); 116 - tmp = (__raw_readl(EXYNOS5_CLKMUX_STATCPU) >> 16); 114 + tmp = (__raw_readl(cpufreq->cmu_regs + EXYNOS5_CLKMUX_STATCPU) 115 + >> 16); 117 116 tmp &= 0x7; 118 117 } while (tmp != 0x2); 119 118 ··· 125 122 126 123 do { 127 124 cpu_relax(); 128 - tmp = __raw_readl(EXYNOS5_CLKMUX_STATCPU); 125 + tmp = __raw_readl(cpufreq->cmu_regs + EXYNOS5_CLKMUX_STATCPU); 129 126 tmp &= (0x7 << 16); 130 127 } while (tmp != (0x1 << 16)); 131 128 } ··· 144 141 145 142 int exynos5250_cpufreq_init(struct exynos_dvfs_info *info) 146 143 { 144 + struct device_node *np; 147 145 unsigned long rate; 146 + 147 + /* 148 + * HACK: This is a temporary workaround to get access to clock 149 + * controller registers directly and remove static mappings and 150 + * dependencies on platform headers. It is necessary to enable 151 + * Exynos multi-platform support and will be removed together with 152 + * this whole driver as soon as Exynos gets migrated to use 153 + * cpufreq-cpu0 driver. 154 + */ 155 + np = of_find_compatible_node(NULL, NULL, "samsung,exynos5250-clock"); 156 + if (!np) { 157 + pr_err("%s: failed to find clock controller DT node\n", 158 + __func__); 159 + return -ENODEV; 160 + } 161 + 162 + info->cmu_regs = of_iomap(np, 0); 163 + if (!info->cmu_regs) { 164 + pr_err("%s: failed to map CMU registers\n", __func__); 165 + return -EFAULT; 166 + } 148 167 149 168 cpu_clk = clk_get(NULL, "armclk"); 150 169 if (IS_ERR(cpu_clk)) ··· 193 168 info->volt_table = exynos5250_volt_table; 194 169 info->freq_table = exynos5250_freq_table; 195 170 info->set_freq = exynos5250_set_frequency; 171 + 172 + cpufreq = info; 196 173 197 174 return 0; 198 175