aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-08-08 14:14:29 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-08-08 14:14:29 -0400
commitb3345d7c57d70e6cb6749af25cdbe80515582e99 (patch)
tree04cce706bc7e944ad1fb257108a8ae735948f97f /drivers
parent44c916d58b9ef1f2c4aec2def57fa8289c716a60 (diff)
parentc2fff85e21818952aa0ee5778926beee6c03e579 (diff)
Merge tag 'soc-for-3.17' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
Pull ARM SoC platform changes from Olof Johansson: "This is the bulk of new SoC enablement and other platform changes for 3.17: - Samsung S5PV210 has been converted to DT and multiplatform - Clock drivers and bindings for some of the lower-end i.MX 1/2 platforms - Kirkwood, one of the popular Marvell platforms, is folded into the mvebu platform code, removing mach-kirkwood - Hwmod data for TI AM43xx and DRA7 platforms - More additions of Renesas shmobile platform support - Removal of plat-samsung contents that can be removed with S5PV210 being multiplatform/DT-enabled and the other two old platforms being removed New platforms (most with only basic support right now): - Hisilicon X5HD2 settop box chipset is introduced - Mediatek MT6589 (mobile chipset) is introduced - Broadcom BCM7xxx settop box chipset is introduced + as usual a lot other pieces all over the platform code" * tag 'soc-for-3.17' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (240 commits) ARM: hisi: remove smp from machine descriptor power: reset: move hisilicon reboot code ARM: dts: Add hix5hd2-dkb dts file. ARM: debug: Rename Hi3716 to HIX5HD2 ARM: hisi: enable hix5hd2 SoC ARM: hisi: add ARCH_HISI MAINTAINERS: add entry for Broadcom ARM STB architecture ARM: brcmstb: select GISB arbiter and interrupt drivers ARM: brcmstb: add infrastructure for ARM-based Broadcom STB SoCs ARM: configs: enable SMP in bcm_defconfig ARM: add SMP support for Broadcom mobile SoCs Documentation: arm: misc updates to Marvell EBU SoC status Documentation: arm: add URLs to public datasheets for the Marvell Armada XP SoC ARM: mvebu: fix build without platforms selected ARM: mvebu: add cpuidle support for Armada 38x ARM: mvebu: add cpuidle support for Armada 370 cpuidle: mvebu: add Armada 38x support cpuidle: mvebu: add Armada 370 support cpuidle: mvebu: rename the driver from armada-370-xp to mvebu-v7 ARM: mvebu: export the SCU address ...
Diffstat (limited to 'drivers')
-rw-r--r--drivers/bus/imx-weim.c4
-rw-r--r--drivers/clk/mvebu/clk-cpu.c80
-rw-r--r--drivers/clk/samsung/Makefile1
-rw-r--r--drivers/clk/samsung/clk-s5pv210-audss.c241
-rw-r--r--drivers/clk/samsung/clk-s5pv210.c856
-rw-r--r--drivers/clk/versatile/Makefile3
-rw-r--r--drivers/clk/versatile/clk-versatile.c (renamed from drivers/clk/versatile/clk-integrator.c)38
-rw-r--r--drivers/clocksource/tegra20_timer.c13
-rw-r--r--drivers/cpufreq/s3c2410-cpufreq.c2
-rw-r--r--drivers/cpufreq/s3c2412-cpufreq.c3
-rw-r--r--drivers/cpufreq/s3c2440-cpufreq.c3
-rw-r--r--drivers/cpufreq/s3c24xx-cpufreq.c1
-rw-r--r--drivers/cpufreq/s5pv210-cpufreq.c131
-rw-r--r--drivers/cpuidle/Kconfig.arm14
-rw-r--r--drivers/cpuidle/Makefile2
-rw-r--r--drivers/cpuidle/cpuidle-armada-370-xp.c93
-rw-r--r--drivers/cpuidle/cpuidle-big_little.c12
-rw-r--r--drivers/cpuidle/cpuidle-mvebu-v7.c150
-rw-r--r--drivers/gpio/gpio-samsung.c240
-rw-r--r--drivers/irqchip/irq-versatile-fpga.c18
-rw-r--r--drivers/phy/Kconfig10
-rw-r--r--drivers/phy/Makefile1
-rw-r--r--drivers/phy/phy-s5pv210-usb2.c187
-rw-r--r--drivers/phy/phy-samsung-usb2.c6
-rw-r--r--drivers/phy/phy-samsung-usb2.h1
-rw-r--r--drivers/power/reset/Kconfig6
-rw-r--r--drivers/power/reset/Makefile1
-rw-r--r--drivers/power/reset/hisi-reboot.c67
-rw-r--r--drivers/tty/serial/samsung.c4
29 files changed, 1812 insertions, 376 deletions
diff --git a/drivers/bus/imx-weim.c b/drivers/bus/imx-weim.c
index f8ee13c7bf7b..75c9681f8021 100644
--- a/drivers/bus/imx-weim.c
+++ b/drivers/bus/imx-weim.c
@@ -162,7 +162,9 @@ static int __init weim_parse_dt(struct platform_device *pdev,
162 } 162 }
163 } 163 }
164 164
165 ret = of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev); 165 ret = of_platform_populate(pdev->dev.of_node,
166 of_default_bus_match_table,
167 NULL, &pdev->dev);
166 if (ret) 168 if (ret)
167 dev_err(&pdev->dev, "%s fail to create devices.\n", 169 dev_err(&pdev->dev, "%s fail to create devices.\n",
168 pdev->dev.of_node->full_name); 170 pdev->dev.of_node->full_name);
diff --git a/drivers/clk/mvebu/clk-cpu.c b/drivers/clk/mvebu/clk-cpu.c
index 8ebf757d29e2..3821a88077ea 100644
--- a/drivers/clk/mvebu/clk-cpu.c
+++ b/drivers/clk/mvebu/clk-cpu.c
@@ -16,10 +16,19 @@
16#include <linux/io.h> 16#include <linux/io.h>
17#include <linux/of.h> 17#include <linux/of.h>
18#include <linux/delay.h> 18#include <linux/delay.h>
19#include <linux/mvebu-pmsu.h>
20#include <asm/smp_plat.h>
19 21
20#define SYS_CTRL_CLK_DIVIDER_CTRL_OFFSET 0x0 22#define SYS_CTRL_CLK_DIVIDER_CTRL_OFFSET 0x0
21#define SYS_CTRL_CLK_DIVIDER_VALUE_OFFSET 0xC 23#define SYS_CTRL_CLK_DIVIDER_CTRL_RESET_ALL 0xff
22#define SYS_CTRL_CLK_DIVIDER_MASK 0x3F 24#define SYS_CTRL_CLK_DIVIDER_CTRL_RESET_SHIFT 8
25#define SYS_CTRL_CLK_DIVIDER_CTRL2_OFFSET 0x8
26#define SYS_CTRL_CLK_DIVIDER_CTRL2_NBCLK_RATIO_SHIFT 16
27#define SYS_CTRL_CLK_DIVIDER_VALUE_OFFSET 0xC
28#define SYS_CTRL_CLK_DIVIDER_MASK 0x3F
29
30#define PMU_DFS_RATIO_SHIFT 16
31#define PMU_DFS_RATIO_MASK 0x3F
23 32
24#define MAX_CPU 4 33#define MAX_CPU 4
25struct cpu_clk { 34struct cpu_clk {
@@ -28,6 +37,7 @@ struct cpu_clk {
28 const char *clk_name; 37 const char *clk_name;
29 const char *parent_name; 38 const char *parent_name;
30 void __iomem *reg_base; 39 void __iomem *reg_base;
40 void __iomem *pmu_dfs;
31}; 41};
32 42
33static struct clk **clks; 43static struct clk **clks;
@@ -62,8 +72,9 @@ static long clk_cpu_round_rate(struct clk_hw *hwclk, unsigned long rate,
62 return *parent_rate / div; 72 return *parent_rate / div;
63} 73}
64 74
65static int clk_cpu_set_rate(struct clk_hw *hwclk, unsigned long rate, 75static int clk_cpu_off_set_rate(struct clk_hw *hwclk, unsigned long rate,
66 unsigned long parent_rate) 76 unsigned long parent_rate)
77
67{ 78{
68 struct cpu_clk *cpuclk = to_cpu_clk(hwclk); 79 struct cpu_clk *cpuclk = to_cpu_clk(hwclk);
69 u32 reg, div; 80 u32 reg, div;
@@ -95,6 +106,58 @@ static int clk_cpu_set_rate(struct clk_hw *hwclk, unsigned long rate,
95 return 0; 106 return 0;
96} 107}
97 108
109static int clk_cpu_on_set_rate(struct clk_hw *hwclk, unsigned long rate,
110 unsigned long parent_rate)
111{
112 u32 reg;
113 unsigned long fabric_div, target_div, cur_rate;
114 struct cpu_clk *cpuclk = to_cpu_clk(hwclk);
115
116 /*
117 * PMU DFS registers are not mapped, Device Tree does not
118 * describes them. We cannot change the frequency dynamically.
119 */
120 if (!cpuclk->pmu_dfs)
121 return -ENODEV;
122
123 cur_rate = __clk_get_rate(hwclk->clk);
124
125 reg = readl(cpuclk->reg_base + SYS_CTRL_CLK_DIVIDER_CTRL2_OFFSET);
126 fabric_div = (reg >> SYS_CTRL_CLK_DIVIDER_CTRL2_NBCLK_RATIO_SHIFT) &
127 SYS_CTRL_CLK_DIVIDER_MASK;
128
129 /* Frequency is going up */
130 if (rate == 2 * cur_rate)
131 target_div = fabric_div / 2;
132 /* Frequency is going down */
133 else
134 target_div = fabric_div;
135
136 if (target_div == 0)
137 target_div = 1;
138
139 reg = readl(cpuclk->pmu_dfs);
140 reg &= ~(PMU_DFS_RATIO_MASK << PMU_DFS_RATIO_SHIFT);
141 reg |= (target_div << PMU_DFS_RATIO_SHIFT);
142 writel(reg, cpuclk->pmu_dfs);
143
144 reg = readl(cpuclk->reg_base + SYS_CTRL_CLK_DIVIDER_CTRL_OFFSET);
145 reg |= (SYS_CTRL_CLK_DIVIDER_CTRL_RESET_ALL <<
146 SYS_CTRL_CLK_DIVIDER_CTRL_RESET_SHIFT);
147 writel(reg, cpuclk->reg_base + SYS_CTRL_CLK_DIVIDER_CTRL_OFFSET);
148
149 return mvebu_pmsu_dfs_request(cpuclk->cpu);
150}
151
152static int clk_cpu_set_rate(struct clk_hw *hwclk, unsigned long rate,
153 unsigned long parent_rate)
154{
155 if (__clk_is_enabled(hwclk->clk))
156 return clk_cpu_on_set_rate(hwclk, rate, parent_rate);
157 else
158 return clk_cpu_off_set_rate(hwclk, rate, parent_rate);
159}
160
98static const struct clk_ops cpu_ops = { 161static const struct clk_ops cpu_ops = {
99 .recalc_rate = clk_cpu_recalc_rate, 162 .recalc_rate = clk_cpu_recalc_rate,
100 .round_rate = clk_cpu_round_rate, 163 .round_rate = clk_cpu_round_rate,
@@ -105,6 +168,7 @@ static void __init of_cpu_clk_setup(struct device_node *node)
105{ 168{
106 struct cpu_clk *cpuclk; 169 struct cpu_clk *cpuclk;
107 void __iomem *clock_complex_base = of_iomap(node, 0); 170 void __iomem *clock_complex_base = of_iomap(node, 0);
171 void __iomem *pmu_dfs_base = of_iomap(node, 1);
108 int ncpus = 0; 172 int ncpus = 0;
109 struct device_node *dn; 173 struct device_node *dn;
110 174
@@ -114,6 +178,10 @@ static void __init of_cpu_clk_setup(struct device_node *node)
114 return; 178 return;
115 } 179 }
116 180
181 if (pmu_dfs_base == NULL)
182 pr_warn("%s: pmu-dfs base register not set, dynamic frequency scaling not available\n",
183 __func__);
184
117 for_each_node_by_type(dn, "cpu") 185 for_each_node_by_type(dn, "cpu")
118 ncpus++; 186 ncpus++;
119 187
@@ -146,6 +214,8 @@ static void __init of_cpu_clk_setup(struct device_node *node)
146 cpuclk[cpu].clk_name = clk_name; 214 cpuclk[cpu].clk_name = clk_name;
147 cpuclk[cpu].cpu = cpu; 215 cpuclk[cpu].cpu = cpu;
148 cpuclk[cpu].reg_base = clock_complex_base; 216 cpuclk[cpu].reg_base = clock_complex_base;
217 if (pmu_dfs_base)
218 cpuclk[cpu].pmu_dfs = pmu_dfs_base + 4 * cpu;
149 cpuclk[cpu].hw.init = &init; 219 cpuclk[cpu].hw.init = &init;
150 220
151 init.name = cpuclk[cpu].clk_name; 221 init.name = cpuclk[cpu].clk_name;
diff --git a/drivers/clk/samsung/Makefile b/drivers/clk/samsung/Makefile
index 2949a556af8f..6fb4bc602e8a 100644
--- a/drivers/clk/samsung/Makefile
+++ b/drivers/clk/samsung/Makefile
@@ -17,3 +17,4 @@ obj-$(CONFIG_S3C2410_COMMON_DCLK)+= clk-s3c2410-dclk.o
17obj-$(CONFIG_S3C2412_COMMON_CLK)+= clk-s3c2412.o 17obj-$(CONFIG_S3C2412_COMMON_CLK)+= clk-s3c2412.o
18obj-$(CONFIG_S3C2443_COMMON_CLK)+= clk-s3c2443.o 18obj-$(CONFIG_S3C2443_COMMON_CLK)+= clk-s3c2443.o
19obj-$(CONFIG_ARCH_S3C64XX) += clk-s3c64xx.o 19obj-$(CONFIG_ARCH_S3C64XX) += clk-s3c64xx.o
20obj-$(CONFIG_ARCH_S5PV210) += clk-s5pv210.o clk-s5pv210-audss.o
diff --git a/drivers/clk/samsung/clk-s5pv210-audss.c b/drivers/clk/samsung/clk-s5pv210-audss.c
new file mode 100644
index 000000000000..a8053b4aca56
--- /dev/null
+++ b/drivers/clk/samsung/clk-s5pv210-audss.c
@@ -0,0 +1,241 @@
1/*
2 * Copyright (c) 2014 Tomasz Figa <t.figa@samsung.com>
3 *
4 * Based on Exynos Audio Subsystem Clock Controller driver:
5 *
6 * Copyright (c) 2013 Samsung Electronics Co., Ltd.
7 * Author: Padmavathi Venna <padma.v@samsung.com>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 *
13 * Driver for Audio Subsystem Clock Controller of S5PV210-compatible SoCs.
14*/
15
16#include <linux/clkdev.h>
17#include <linux/io.h>
18#include <linux/clk-provider.h>
19#include <linux/of_address.h>
20#include <linux/syscore_ops.h>
21#include <linux/module.h>
22#include <linux/platform_device.h>
23
24#include <dt-bindings/clock/s5pv210-audss.h>
25
26static DEFINE_SPINLOCK(lock);
27static struct clk **clk_table;
28static void __iomem *reg_base;
29static struct clk_onecell_data clk_data;
30
31#define ASS_CLK_SRC 0x0
32#define ASS_CLK_DIV 0x4
33#define ASS_CLK_GATE 0x8
34
35#ifdef CONFIG_PM_SLEEP
36static unsigned long reg_save[][2] = {
37 {ASS_CLK_SRC, 0},
38 {ASS_CLK_DIV, 0},
39 {ASS_CLK_GATE, 0},
40};
41
42static int s5pv210_audss_clk_suspend(void)
43{
44 int i;
45
46 for (i = 0; i < ARRAY_SIZE(reg_save); i++)
47 reg_save[i][1] = readl(reg_base + reg_save[i][0]);
48
49 return 0;
50}
51
52static void s5pv210_audss_clk_resume(void)
53{
54 int i;
55
56 for (i = 0; i < ARRAY_SIZE(reg_save); i++)
57 writel(reg_save[i][1], reg_base + reg_save[i][0]);
58}
59
60static struct syscore_ops s5pv210_audss_clk_syscore_ops = {
61 .suspend = s5pv210_audss_clk_suspend,
62 .resume = s5pv210_audss_clk_resume,
63};
64#endif /* CONFIG_PM_SLEEP */
65
66/* register s5pv210_audss clocks */
67static int s5pv210_audss_clk_probe(struct platform_device *pdev)
68{
69 int i, ret = 0;
70 struct resource *res;
71 const char *mout_audss_p[2];
72 const char *mout_i2s_p[3];
73 const char *hclk_p;
74 struct clk *hclk, *pll_ref, *pll_in, *cdclk, *sclk_audio;
75
76 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
77 reg_base = devm_ioremap_resource(&pdev->dev, res);
78 if (IS_ERR(reg_base)) {
79 dev_err(&pdev->dev, "failed to map audss registers\n");
80 return PTR_ERR(reg_base);
81 }
82
83 clk_table = devm_kzalloc(&pdev->dev,
84 sizeof(struct clk *) * AUDSS_MAX_CLKS,
85 GFP_KERNEL);
86 if (!clk_table)
87 return -ENOMEM;
88
89 clk_data.clks = clk_table;
90 clk_data.clk_num = AUDSS_MAX_CLKS;
91
92 hclk = devm_clk_get(&pdev->dev, "hclk");
93 if (IS_ERR(hclk)) {
94 dev_err(&pdev->dev, "failed to get hclk clock\n");
95 return PTR_ERR(hclk);
96 }
97
98 pll_in = devm_clk_get(&pdev->dev, "fout_epll");
99 if (IS_ERR(pll_in)) {
100 dev_err(&pdev->dev, "failed to get fout_epll clock\n");
101 return PTR_ERR(pll_in);
102 }
103
104 sclk_audio = devm_clk_get(&pdev->dev, "sclk_audio0");
105 if (IS_ERR(sclk_audio)) {
106 dev_err(&pdev->dev, "failed to get sclk_audio0 clock\n");
107 return PTR_ERR(sclk_audio);
108 }
109
110 /* iiscdclk0 is an optional external I2S codec clock */
111 cdclk = devm_clk_get(&pdev->dev, "iiscdclk0");
112 pll_ref = devm_clk_get(&pdev->dev, "xxti");
113
114 if (!IS_ERR(pll_ref))
115 mout_audss_p[0] = __clk_get_name(pll_ref);
116 else
117 mout_audss_p[0] = "xxti";
118 mout_audss_p[1] = __clk_get_name(pll_in);
119 clk_table[CLK_MOUT_AUDSS] = clk_register_mux(NULL, "mout_audss",
120 mout_audss_p, ARRAY_SIZE(mout_audss_p),
121 CLK_SET_RATE_NO_REPARENT,
122 reg_base + ASS_CLK_SRC, 0, 1, 0, &lock);
123
124 mout_i2s_p[0] = "mout_audss";
125 if (!IS_ERR(cdclk))
126 mout_i2s_p[1] = __clk_get_name(cdclk);
127 else
128 mout_i2s_p[1] = "iiscdclk0";
129 mout_i2s_p[2] = __clk_get_name(sclk_audio);
130 clk_table[CLK_MOUT_I2S_A] = clk_register_mux(NULL, "mout_i2s_audss",
131 mout_i2s_p, ARRAY_SIZE(mout_i2s_p),
132 CLK_SET_RATE_NO_REPARENT,
133 reg_base + ASS_CLK_SRC, 2, 2, 0, &lock);
134
135 clk_table[CLK_DOUT_AUD_BUS] = clk_register_divider(NULL,
136 "dout_aud_bus", "mout_audss", 0,
137 reg_base + ASS_CLK_DIV, 0, 4, 0, &lock);
138 clk_table[CLK_DOUT_I2S_A] = clk_register_divider(NULL, "dout_i2s_audss",
139 "mout_i2s_audss", 0, reg_base + ASS_CLK_DIV,
140 4, 4, 0, &lock);
141
142 clk_table[CLK_I2S] = clk_register_gate(NULL, "i2s_audss",
143 "dout_i2s_audss", CLK_SET_RATE_PARENT,
144 reg_base + ASS_CLK_GATE, 6, 0, &lock);
145
146 hclk_p = __clk_get_name(hclk);
147
148 clk_table[CLK_HCLK_I2S] = clk_register_gate(NULL, "hclk_i2s_audss",
149 hclk_p, CLK_IGNORE_UNUSED,
150 reg_base + ASS_CLK_GATE, 5, 0, &lock);
151 clk_table[CLK_HCLK_UART] = clk_register_gate(NULL, "hclk_uart_audss",
152 hclk_p, CLK_IGNORE_UNUSED,
153 reg_base + ASS_CLK_GATE, 4, 0, &lock);
154 clk_table[CLK_HCLK_HWA] = clk_register_gate(NULL, "hclk_hwa_audss",
155 hclk_p, CLK_IGNORE_UNUSED,
156 reg_base + ASS_CLK_GATE, 3, 0, &lock);
157 clk_table[CLK_HCLK_DMA] = clk_register_gate(NULL, "hclk_dma_audss",
158 hclk_p, CLK_IGNORE_UNUSED,
159 reg_base + ASS_CLK_GATE, 2, 0, &lock);
160 clk_table[CLK_HCLK_BUF] = clk_register_gate(NULL, "hclk_buf_audss",
161 hclk_p, CLK_IGNORE_UNUSED,
162 reg_base + ASS_CLK_GATE, 1, 0, &lock);
163 clk_table[CLK_HCLK_RP] = clk_register_gate(NULL, "hclk_rp_audss",
164 hclk_p, CLK_IGNORE_UNUSED,
165 reg_base + ASS_CLK_GATE, 0, 0, &lock);
166
167 for (i = 0; i < clk_data.clk_num; i++) {
168 if (IS_ERR(clk_table[i])) {
169 dev_err(&pdev->dev, "failed to register clock %d\n", i);
170 ret = PTR_ERR(clk_table[i]);
171 goto unregister;
172 }
173 }
174
175 ret = of_clk_add_provider(pdev->dev.of_node, of_clk_src_onecell_get,
176 &clk_data);
177 if (ret) {
178 dev_err(&pdev->dev, "failed to add clock provider\n");
179 goto unregister;
180 }
181
182#ifdef CONFIG_PM_SLEEP
183 register_syscore_ops(&s5pv210_audss_clk_syscore_ops);
184#endif
185
186 return 0;
187
188unregister:
189 for (i = 0; i < clk_data.clk_num; i++) {
190 if (!IS_ERR(clk_table[i]))
191 clk_unregister(clk_table[i]);
192 }
193
194 return ret;
195}
196
197static int s5pv210_audss_clk_remove(struct platform_device *pdev)
198{
199 int i;
200
201 of_clk_del_provider(pdev->dev.of_node);
202
203 for (i = 0; i < clk_data.clk_num; i++) {
204 if (!IS_ERR(clk_table[i]))
205 clk_unregister(clk_table[i]);
206 }
207
208 return 0;
209}
210
211static const struct of_device_id s5pv210_audss_clk_of_match[] = {
212 { .compatible = "samsung,s5pv210-audss-clock", },
213 {},
214};
215
216static struct platform_driver s5pv210_audss_clk_driver = {
217 .driver = {
218 .name = "s5pv210-audss-clk",
219 .owner = THIS_MODULE,
220 .of_match_table = s5pv210_audss_clk_of_match,
221 },
222 .probe = s5pv210_audss_clk_probe,
223 .remove = s5pv210_audss_clk_remove,
224};
225
226static int __init s5pv210_audss_clk_init(void)
227{
228 return platform_driver_register(&s5pv210_audss_clk_driver);
229}
230core_initcall(s5pv210_audss_clk_init);
231
232static void __exit s5pv210_audss_clk_exit(void)
233{
234 platform_driver_unregister(&s5pv210_audss_clk_driver);
235}
236module_exit(s5pv210_audss_clk_exit);
237
238MODULE_AUTHOR("Tomasz Figa <t.figa@samsung.com>");
239MODULE_DESCRIPTION("S5PV210 Audio Subsystem Clock Controller");
240MODULE_LICENSE("GPL v2");
241MODULE_ALIAS("platform:s5pv210-audss-clk");
diff --git a/drivers/clk/samsung/clk-s5pv210.c b/drivers/clk/samsung/clk-s5pv210.c
new file mode 100644
index 000000000000..d270a2084644
--- /dev/null
+++ b/drivers/clk/samsung/clk-s5pv210.c
@@ -0,0 +1,856 @@
1/*
2 * Copyright (c) 2013 Samsung Electronics Co., Ltd.
3 * Author: Mateusz Krawczuk <m.krawczuk@partner.samsung.com>
4 *
5 * Based on clock drivers for S3C64xx and Exynos4 SoCs.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 *
11 * Common Clock Framework support for all S5PC110/S5PV210 SoCs.
12 */
13
14#include <linux/clk.h>
15#include <linux/clkdev.h>
16#include <linux/clk-provider.h>
17#include <linux/of.h>
18#include <linux/of_address.h>
19#include <linux/syscore_ops.h>
20
21#include "clk.h"
22#include "clk-pll.h"
23
24#include <dt-bindings/clock/s5pv210.h>
25
26/* S5PC110/S5PV210 clock controller register offsets */
27#define APLL_LOCK 0x0000
28#define MPLL_LOCK 0x0008
29#define EPLL_LOCK 0x0010
30#define VPLL_LOCK 0x0020
31#define APLL_CON0 0x0100
32#define APLL_CON1 0x0104
33#define MPLL_CON 0x0108
34#define EPLL_CON0 0x0110
35#define EPLL_CON1 0x0114
36#define VPLL_CON 0x0120
37#define CLK_SRC0 0x0200
38#define CLK_SRC1 0x0204
39#define CLK_SRC2 0x0208
40#define CLK_SRC3 0x020c
41#define CLK_SRC4 0x0210
42#define CLK_SRC5 0x0214
43#define CLK_SRC6 0x0218
44#define CLK_SRC_MASK0 0x0280
45#define CLK_SRC_MASK1 0x0284
46#define CLK_DIV0 0x0300
47#define CLK_DIV1 0x0304
48#define CLK_DIV2 0x0308
49#define CLK_DIV3 0x030c
50#define CLK_DIV4 0x0310
51#define CLK_DIV5 0x0314
52#define CLK_DIV6 0x0318
53#define CLK_DIV7 0x031c
54#define CLK_GATE_MAIN0 0x0400
55#define CLK_GATE_MAIN1 0x0404
56#define CLK_GATE_MAIN2 0x0408
57#define CLK_GATE_PERI0 0x0420
58#define CLK_GATE_PERI1 0x0424
59#define CLK_GATE_SCLK0 0x0440
60#define CLK_GATE_SCLK1 0x0444
61#define CLK_GATE_IP0 0x0460
62#define CLK_GATE_IP1 0x0464
63#define CLK_GATE_IP2 0x0468
64#define CLK_GATE_IP3 0x046c
65#define CLK_GATE_IP4 0x0470
66#define CLK_GATE_BLOCK 0x0480
67#define CLK_GATE_IP5 0x0484
68#define CLK_OUT 0x0500
69#define MISC 0xe000
70#define OM_STAT 0xe100
71
72/* IDs of PLLs available on S5PV210/S5P6442 SoCs */
73enum {
74 apll,
75 mpll,
76 epll,
77 vpll,
78};
79
80/* IDs of external clocks (used for legacy boards) */
81enum {
82 xxti,
83 xusbxti,
84};
85
86static void __iomem *reg_base;
87
88#ifdef CONFIG_PM_SLEEP
89static struct samsung_clk_reg_dump *s5pv210_clk_dump;
90
91/* List of registers that need to be preserved across suspend/resume. */
92static unsigned long s5pv210_clk_regs[] __initdata = {
93 CLK_SRC0,
94 CLK_SRC1,
95 CLK_SRC2,
96 CLK_SRC3,
97 CLK_SRC4,
98 CLK_SRC5,
99 CLK_SRC6,
100 CLK_SRC_MASK0,
101 CLK_SRC_MASK1,
102 CLK_DIV0,
103 CLK_DIV1,
104 CLK_DIV2,
105 CLK_DIV3,
106 CLK_DIV4,
107 CLK_DIV5,
108 CLK_DIV6,
109 CLK_DIV7,
110 CLK_GATE_MAIN0,
111 CLK_GATE_MAIN1,
112 CLK_GATE_MAIN2,
113 CLK_GATE_PERI0,
114 CLK_GATE_PERI1,
115 CLK_GATE_SCLK0,
116 CLK_GATE_SCLK1,
117 CLK_GATE_IP0,
118 CLK_GATE_IP1,
119 CLK_GATE_IP2,
120 CLK_GATE_IP3,
121 CLK_GATE_IP4,
122 CLK_GATE_IP5,
123 CLK_GATE_BLOCK,
124 APLL_LOCK,
125 MPLL_LOCK,
126 EPLL_LOCK,
127 VPLL_LOCK,
128 APLL_CON0,
129 APLL_CON1,
130 MPLL_CON,
131 EPLL_CON0,
132 EPLL_CON1,
133 VPLL_CON,
134 CLK_OUT,
135};
136
137static int s5pv210_clk_suspend(void)
138{
139 samsung_clk_save(reg_base, s5pv210_clk_dump,
140 ARRAY_SIZE(s5pv210_clk_regs));
141 return 0;
142}
143
144static void s5pv210_clk_resume(void)
145{
146 samsung_clk_restore(reg_base, s5pv210_clk_dump,
147 ARRAY_SIZE(s5pv210_clk_regs));
148}
149
150static struct syscore_ops s5pv210_clk_syscore_ops = {
151 .suspend = s5pv210_clk_suspend,
152 .resume = s5pv210_clk_resume,
153};
154
155static void s5pv210_clk_sleep_init(void)
156{
157 s5pv210_clk_dump =
158 samsung_clk_alloc_reg_dump(s5pv210_clk_regs,
159 ARRAY_SIZE(s5pv210_clk_regs));
160 if (!s5pv210_clk_dump) {
161 pr_warn("%s: Failed to allocate sleep save data\n", __func__);
162 return;
163 }
164
165 register_syscore_ops(&s5pv210_clk_syscore_ops);
166}
167#else
168static inline void s5pv210_clk_sleep_init(void) { }
169#endif
170
171/* Mux parent lists. */
172static const char *fin_pll_p[] __initconst = {
173 "xxti",
174 "xusbxti"
175};
176
177static const char *mout_apll_p[] __initconst = {
178 "fin_pll",
179 "fout_apll"
180};
181
182static const char *mout_mpll_p[] __initconst = {
183 "fin_pll",
184 "fout_mpll"
185};
186
187static const char *mout_epll_p[] __initconst = {
188 "fin_pll",
189 "fout_epll"
190};
191
192static const char *mout_vpllsrc_p[] __initconst = {
193 "fin_pll",
194 "sclk_hdmi27m"
195};
196
197static const char *mout_vpll_p[] __initconst = {
198 "mout_vpllsrc",
199 "fout_vpll"
200};
201
202static const char *mout_group1_p[] __initconst = {
203 "dout_a2m",
204 "mout_mpll",
205 "mout_epll",
206 "mout_vpll"
207};
208
209static const char *mout_group2_p[] __initconst = {
210 "xxti",
211 "xusbxti",
212 "sclk_hdmi27m",
213 "sclk_usbphy0",
214 "sclk_usbphy1",
215 "sclk_hdmiphy",
216 "mout_mpll",
217 "mout_epll",
218 "mout_vpll",
219};
220
221static const char *mout_audio0_p[] __initconst = {
222 "xxti",
223 "pcmcdclk0",
224 "sclk_hdmi27m",
225 "sclk_usbphy0",
226 "sclk_usbphy1",
227 "sclk_hdmiphy",
228 "mout_mpll",
229 "mout_epll",
230 "mout_vpll",
231};
232
233static const char *mout_audio1_p[] __initconst = {
234 "i2scdclk1",
235 "pcmcdclk1",
236 "sclk_hdmi27m",
237 "sclk_usbphy0",
238 "sclk_usbphy1",
239 "sclk_hdmiphy",
240 "mout_mpll",
241 "mout_epll",
242 "mout_vpll",
243};
244
245static const char *mout_audio2_p[] __initconst = {
246 "i2scdclk2",
247 "pcmcdclk2",
248 "sclk_hdmi27m",
249 "sclk_usbphy0",
250 "sclk_usbphy1",
251 "sclk_hdmiphy",
252 "mout_mpll",
253 "mout_epll",
254 "mout_vpll",
255};
256
257static const char *mout_spdif_p[] __initconst = {
258 "dout_audio0",
259 "dout_audio1",
260 "dout_audio3",
261};
262
263static const char *mout_group3_p[] __initconst = {
264 "mout_apll",
265 "mout_mpll"
266};
267
268static const char *mout_group4_p[] __initconst = {
269 "mout_mpll",
270 "dout_a2m"
271};
272
273static const char *mout_flash_p[] __initconst = {
274 "dout_hclkd",
275 "dout_hclkp"
276};
277
278static const char *mout_dac_p[] __initconst = {
279 "mout_vpll",
280 "sclk_hdmiphy"
281};
282
283static const char *mout_hdmi_p[] __initconst = {
284 "sclk_hdmiphy",
285 "dout_tblk"
286};
287
288static const char *mout_mixer_p[] __initconst = {
289 "mout_dac",
290 "mout_hdmi"
291};
292
293static const char *mout_vpll_6442_p[] __initconst = {
294 "fin_pll",
295 "fout_vpll"
296};
297
298static const char *mout_mixer_6442_p[] __initconst = {
299 "mout_vpll",
300 "dout_mixer"
301};
302
303static const char *mout_d0sync_6442_p[] __initconst = {
304 "mout_dsys",
305 "div_apll"
306};
307
308static const char *mout_d1sync_6442_p[] __initconst = {
309 "mout_psys",
310 "div_apll"
311};
312
313static const char *mout_group2_6442_p[] __initconst = {
314 "fin_pll",
315 "none",
316 "none",
317 "sclk_usbphy0",
318 "none",
319 "none",
320 "mout_mpll",
321 "mout_epll",
322 "mout_vpll",
323};
324
325static const char *mout_audio0_6442_p[] __initconst = {
326 "fin_pll",
327 "pcmcdclk0",
328 "none",
329 "sclk_usbphy0",
330 "none",
331 "none",
332 "mout_mpll",
333 "mout_epll",
334 "mout_vpll",
335};
336
337static const char *mout_audio1_6442_p[] __initconst = {
338 "i2scdclk1",
339 "pcmcdclk1",
340 "none",
341 "sclk_usbphy0",
342 "none",
343 "none",
344 "mout_mpll",
345 "mout_epll",
346 "mout_vpll",
347 "fin_pll",
348};
349
350static const char *mout_clksel_p[] __initconst = {
351 "fout_apll_clkout",
352 "fout_mpll_clkout",
353 "fout_epll",
354 "fout_vpll",
355 "sclk_usbphy0",
356 "sclk_usbphy1",
357 "sclk_hdmiphy",
358 "rtc",
359 "rtc_tick",
360 "dout_hclkm",
361 "dout_pclkm",
362 "dout_hclkd",
363 "dout_pclkd",
364 "dout_hclkp",
365 "dout_pclkp",
366 "dout_apll_clkout",
367 "dout_hpm",
368 "xxti",
369 "xusbxti",
370 "div_dclk"
371};
372
373static const char *mout_clksel_6442_p[] __initconst = {
374 "fout_apll_clkout",
375 "fout_mpll_clkout",
376 "fout_epll",
377 "fout_vpll",
378 "sclk_usbphy0",
379 "none",
380 "none",
381 "rtc",
382 "rtc_tick",
383 "none",
384 "none",
385 "dout_hclkd",
386 "dout_pclkd",
387 "dout_hclkp",
388 "dout_pclkp",
389 "dout_apll_clkout",
390 "none",
391 "fin_pll",
392 "none",
393 "div_dclk"
394};
395
396static const char *mout_clkout_p[] __initconst = {
397 "dout_clkout",
398 "none",
399 "xxti",
400 "xusbxti"
401};
402
403/* Common fixed factor clocks. */
404static struct samsung_fixed_factor_clock ffactor_clks[] __initdata = {
405 FFACTOR(FOUT_APLL_CLKOUT, "fout_apll_clkout", "fout_apll", 1, 4, 0),
406 FFACTOR(FOUT_MPLL_CLKOUT, "fout_mpll_clkout", "fout_mpll", 1, 2, 0),
407 FFACTOR(DOUT_APLL_CLKOUT, "dout_apll_clkout", "dout_apll", 1, 4, 0),
408};
409
410/* PLL input mux (fin_pll), which needs to be registered before PLLs. */
411static struct samsung_mux_clock early_mux_clks[] __initdata = {
412 MUX_F(FIN_PLL, "fin_pll", fin_pll_p, OM_STAT, 0, 1,
413 CLK_MUX_READ_ONLY, 0),
414};
415
416/* Common clock muxes. */
417static struct samsung_mux_clock mux_clks[] __initdata = {
418 MUX(MOUT_FLASH, "mout_flash", mout_flash_p, CLK_SRC0, 28, 1),
419 MUX(MOUT_PSYS, "mout_psys", mout_group4_p, CLK_SRC0, 24, 1),
420 MUX(MOUT_DSYS, "mout_dsys", mout_group4_p, CLK_SRC0, 20, 1),
421 MUX(MOUT_MSYS, "mout_msys", mout_group3_p, CLK_SRC0, 16, 1),
422 MUX(MOUT_EPLL, "mout_epll", mout_epll_p, CLK_SRC0, 8, 1),
423 MUX(MOUT_MPLL, "mout_mpll", mout_mpll_p, CLK_SRC0, 4, 1),
424 MUX(MOUT_APLL, "mout_apll", mout_apll_p, CLK_SRC0, 0, 1),
425
426 MUX(MOUT_CLKOUT, "mout_clkout", mout_clkout_p, MISC, 8, 2),
427};
428
429/* S5PV210-specific clock muxes. */
430static struct samsung_mux_clock s5pv210_mux_clks[] __initdata = {
431 MUX(MOUT_VPLL, "mout_vpll", mout_vpll_p, CLK_SRC0, 12, 1),
432
433 MUX(MOUT_VPLLSRC, "mout_vpllsrc", mout_vpllsrc_p, CLK_SRC1, 28, 1),
434 MUX(MOUT_CSIS, "mout_csis", mout_group2_p, CLK_SRC1, 24, 4),
435 MUX(MOUT_FIMD, "mout_fimd", mout_group2_p, CLK_SRC1, 20, 4),
436 MUX(MOUT_CAM1, "mout_cam1", mout_group2_p, CLK_SRC1, 16, 4),
437 MUX(MOUT_CAM0, "mout_cam0", mout_group2_p, CLK_SRC1, 12, 4),
438 MUX(MOUT_DAC, "mout_dac", mout_dac_p, CLK_SRC1, 8, 1),
439 MUX(MOUT_MIXER, "mout_mixer", mout_mixer_p, CLK_SRC1, 4, 1),
440 MUX(MOUT_HDMI, "mout_hdmi", mout_hdmi_p, CLK_SRC1, 0, 1),
441
442 MUX(MOUT_G2D, "mout_g2d", mout_group1_p, CLK_SRC2, 8, 2),
443 MUX(MOUT_MFC, "mout_mfc", mout_group1_p, CLK_SRC2, 4, 2),
444 MUX(MOUT_G3D, "mout_g3d", mout_group1_p, CLK_SRC2, 0, 2),
445
446 MUX(MOUT_FIMC2, "mout_fimc2", mout_group2_p, CLK_SRC3, 20, 4),
447 MUX(MOUT_FIMC1, "mout_fimc1", mout_group2_p, CLK_SRC3, 16, 4),
448 MUX(MOUT_FIMC0, "mout_fimc0", mout_group2_p, CLK_SRC3, 12, 4),
449
450 MUX(MOUT_UART3, "mout_uart3", mout_group2_p, CLK_SRC4, 28, 4),
451 MUX(MOUT_UART2, "mout_uart2", mout_group2_p, CLK_SRC4, 24, 4),
452 MUX(MOUT_UART1, "mout_uart1", mout_group2_p, CLK_SRC4, 20, 4),
453 MUX(MOUT_UART0, "mout_uart0", mout_group2_p, CLK_SRC4, 16, 4),
454 MUX(MOUT_MMC3, "mout_mmc3", mout_group2_p, CLK_SRC4, 12, 4),
455 MUX(MOUT_MMC2, "mout_mmc2", mout_group2_p, CLK_SRC4, 8, 4),
456 MUX(MOUT_MMC1, "mout_mmc1", mout_group2_p, CLK_SRC4, 4, 4),
457 MUX(MOUT_MMC0, "mout_mmc0", mout_group2_p, CLK_SRC4, 0, 4),
458
459 MUX(MOUT_PWM, "mout_pwm", mout_group2_p, CLK_SRC5, 12, 4),
460 MUX(MOUT_SPI1, "mout_spi1", mout_group2_p, CLK_SRC5, 4, 4),
461 MUX(MOUT_SPI0, "mout_spi0", mout_group2_p, CLK_SRC5, 0, 4),
462
463 MUX(MOUT_DMC0, "mout_dmc0", mout_group1_p, CLK_SRC6, 24, 2),
464 MUX(MOUT_PWI, "mout_pwi", mout_group2_p, CLK_SRC6, 20, 4),
465 MUX(MOUT_HPM, "mout_hpm", mout_group3_p, CLK_SRC6, 16, 1),
466 MUX(MOUT_SPDIF, "mout_spdif", mout_spdif_p, CLK_SRC6, 12, 2),
467 MUX(MOUT_AUDIO2, "mout_audio2", mout_audio2_p, CLK_SRC6, 8, 4),
468 MUX(MOUT_AUDIO1, "mout_audio1", mout_audio1_p, CLK_SRC6, 4, 4),
469 MUX(MOUT_AUDIO0, "mout_audio0", mout_audio0_p, CLK_SRC6, 0, 4),
470
471 MUX(MOUT_CLKSEL, "mout_clksel", mout_clksel_p, CLK_OUT, 12, 5),
472};
473
474/* S5P6442-specific clock muxes. */
475static struct samsung_mux_clock s5p6442_mux_clks[] __initdata = {
476 MUX(MOUT_VPLL, "mout_vpll", mout_vpll_6442_p, CLK_SRC0, 12, 1),
477
478 MUX(MOUT_FIMD, "mout_fimd", mout_group2_6442_p, CLK_SRC1, 20, 4),
479 MUX(MOUT_CAM1, "mout_cam1", mout_group2_6442_p, CLK_SRC1, 16, 4),
480 MUX(MOUT_CAM0, "mout_cam0", mout_group2_6442_p, CLK_SRC1, 12, 4),
481 MUX(MOUT_MIXER, "mout_mixer", mout_mixer_6442_p, CLK_SRC1, 4, 1),
482
483 MUX(MOUT_D0SYNC, "mout_d0sync", mout_d0sync_6442_p, CLK_SRC2, 28, 1),
484 MUX(MOUT_D1SYNC, "mout_d1sync", mout_d1sync_6442_p, CLK_SRC2, 24, 1),
485
486 MUX(MOUT_FIMC2, "mout_fimc2", mout_group2_6442_p, CLK_SRC3, 20, 4),
487 MUX(MOUT_FIMC1, "mout_fimc1", mout_group2_6442_p, CLK_SRC3, 16, 4),
488 MUX(MOUT_FIMC0, "mout_fimc0", mout_group2_6442_p, CLK_SRC3, 12, 4),
489
490 MUX(MOUT_UART2, "mout_uart2", mout_group2_6442_p, CLK_SRC4, 24, 4),
491 MUX(MOUT_UART1, "mout_uart1", mout_group2_6442_p, CLK_SRC4, 20, 4),
492 MUX(MOUT_UART0, "mout_uart0", mout_group2_6442_p, CLK_SRC4, 16, 4),
493 MUX(MOUT_MMC2, "mout_mmc2", mout_group2_6442_p, CLK_SRC4, 8, 4),
494 MUX(MOUT_MMC1, "mout_mmc1", mout_group2_6442_p, CLK_SRC4, 4, 4),
495 MUX(MOUT_MMC0, "mout_mmc0", mout_group2_6442_p, CLK_SRC4, 0, 4),
496
497 MUX(MOUT_PWM, "mout_pwm", mout_group2_6442_p, CLK_SRC5, 12, 4),
498 MUX(MOUT_SPI0, "mout_spi0", mout_group2_6442_p, CLK_SRC5, 0, 4),
499
500 MUX(MOUT_AUDIO1, "mout_audio1", mout_audio1_6442_p, CLK_SRC6, 4, 4),
501 MUX(MOUT_AUDIO0, "mout_audio0", mout_audio0_6442_p, CLK_SRC6, 0, 4),
502
503 MUX(MOUT_CLKSEL, "mout_clksel", mout_clksel_6442_p, CLK_OUT, 12, 5),
504};
505
506/* S5PV210-specific fixed rate clocks generated inside the SoC. */
507static struct samsung_fixed_rate_clock s5pv210_frate_clks[] __initdata = {
508 FRATE(SCLK_HDMI27M, "sclk_hdmi27m", NULL, CLK_IS_ROOT, 27000000),
509 FRATE(SCLK_HDMIPHY, "sclk_hdmiphy", NULL, CLK_IS_ROOT, 27000000),
510 FRATE(SCLK_USBPHY0, "sclk_usbphy0", NULL, CLK_IS_ROOT, 48000000),
511 FRATE(SCLK_USBPHY1, "sclk_usbphy1", NULL, CLK_IS_ROOT, 48000000),
512};
513
514/* S5P6442-specific fixed rate clocks generated inside the SoC. */
515static struct samsung_fixed_rate_clock s5p6442_frate_clks[] __initdata = {
516 FRATE(SCLK_USBPHY0, "sclk_usbphy0", NULL, CLK_IS_ROOT, 30000000),
517};
518
519/* Common clock dividers. */
520static struct samsung_div_clock div_clks[] __initdata = {
521 DIV(DOUT_PCLKP, "dout_pclkp", "dout_hclkp", CLK_DIV0, 28, 3),
522 DIV(DOUT_PCLKD, "dout_pclkd", "dout_hclkd", CLK_DIV0, 20, 3),
523 DIV(DOUT_A2M, "dout_a2m", "mout_apll", CLK_DIV0, 4, 3),
524 DIV(DOUT_APLL, "dout_apll", "mout_msys", CLK_DIV0, 0, 3),
525
526 DIV(DOUT_FIMD, "dout_fimd", "mout_fimd", CLK_DIV1, 20, 4),
527 DIV(DOUT_CAM1, "dout_cam1", "mout_cam1", CLK_DIV1, 16, 4),
528 DIV(DOUT_CAM0, "dout_cam0", "mout_cam0", CLK_DIV1, 12, 4),
529
530 DIV(DOUT_FIMC2, "dout_fimc2", "mout_fimc2", CLK_DIV3, 20, 4),
531 DIV(DOUT_FIMC1, "dout_fimc1", "mout_fimc1", CLK_DIV3, 16, 4),
532 DIV(DOUT_FIMC0, "dout_fimc0", "mout_fimc0", CLK_DIV3, 12, 4),
533
534 DIV(DOUT_UART2, "dout_uart2", "mout_uart2", CLK_DIV4, 24, 4),
535 DIV(DOUT_UART1, "dout_uart1", "mout_uart1", CLK_DIV4, 20, 4),
536 DIV(DOUT_UART0, "dout_uart0", "mout_uart0", CLK_DIV4, 16, 4),
537 DIV(DOUT_MMC2, "dout_mmc2", "mout_mmc2", CLK_DIV4, 8, 4),
538 DIV(DOUT_MMC1, "dout_mmc1", "mout_mmc1", CLK_DIV4, 4, 4),
539 DIV(DOUT_MMC0, "dout_mmc0", "mout_mmc0", CLK_DIV4, 0, 4),
540
541 DIV(DOUT_PWM, "dout_pwm", "mout_pwm", CLK_DIV5, 12, 4),
542 DIV(DOUT_SPI0, "dout_spi0", "mout_spi0", CLK_DIV5, 0, 4),
543
544 DIV(DOUT_FLASH, "dout_flash", "mout_flash", CLK_DIV6, 12, 3),
545 DIV(DOUT_AUDIO1, "dout_audio1", "mout_audio1", CLK_DIV6, 4, 4),
546 DIV(DOUT_AUDIO0, "dout_audio0", "mout_audio0", CLK_DIV6, 0, 4),
547
548 DIV(DOUT_CLKOUT, "dout_clkout", "mout_clksel", CLK_OUT, 20, 4),
549};
550
551/* S5PV210-specific clock dividers. */
552static struct samsung_div_clock s5pv210_div_clks[] __initdata = {
553 DIV(DOUT_HCLKP, "dout_hclkp", "mout_psys", CLK_DIV0, 24, 4),
554 DIV(DOUT_HCLKD, "dout_hclkd", "mout_dsys", CLK_DIV0, 16, 4),
555 DIV(DOUT_PCLKM, "dout_pclkm", "dout_hclkm", CLK_DIV0, 12, 3),
556 DIV(DOUT_HCLKM, "dout_hclkm", "dout_apll", CLK_DIV0, 8, 3),
557
558 DIV(DOUT_CSIS, "dout_csis", "mout_csis", CLK_DIV1, 28, 4),
559 DIV(DOUT_TBLK, "dout_tblk", "mout_vpll", CLK_DIV1, 0, 4),
560
561 DIV(DOUT_G2D, "dout_g2d", "mout_g2d", CLK_DIV2, 8, 4),
562 DIV(DOUT_MFC, "dout_mfc", "mout_mfc", CLK_DIV2, 4, 4),
563 DIV(DOUT_G3D, "dout_g3d", "mout_g3d", CLK_DIV2, 0, 4),
564
565 DIV(DOUT_UART3, "dout_uart3", "mout_uart3", CLK_DIV4, 28, 4),
566 DIV(DOUT_MMC3, "dout_mmc3", "mout_mmc3", CLK_DIV4, 12, 4),
567
568 DIV(DOUT_SPI1, "dout_spi1", "mout_spi1", CLK_DIV5, 4, 4),
569
570 DIV(DOUT_DMC0, "dout_dmc0", "mout_dmc0", CLK_DIV6, 28, 4),
571 DIV(DOUT_PWI, "dout_pwi", "mout_pwi", CLK_DIV6, 24, 4),
572 DIV(DOUT_HPM, "dout_hpm", "dout_copy", CLK_DIV6, 20, 3),
573 DIV(DOUT_COPY, "dout_copy", "mout_hpm", CLK_DIV6, 16, 3),
574 DIV(DOUT_AUDIO2, "dout_audio2", "mout_audio2", CLK_DIV6, 8, 4),
575
576 DIV(DOUT_DPM, "dout_dpm", "dout_pclkp", CLK_DIV7, 8, 7),
577 DIV(DOUT_DVSEM, "dout_dvsem", "dout_pclkp", CLK_DIV7, 0, 7),
578};
579
580/* S5P6442-specific clock dividers. */
581static struct samsung_div_clock s5p6442_div_clks[] __initdata = {
582 DIV(DOUT_HCLKP, "dout_hclkp", "mout_d1sync", CLK_DIV0, 24, 4),
583 DIV(DOUT_HCLKD, "dout_hclkd", "mout_d0sync", CLK_DIV0, 16, 4),
584
585 DIV(DOUT_MIXER, "dout_mixer", "mout_vpll", CLK_DIV1, 0, 4),
586};
587
588/* Common clock gates. */
589static struct samsung_gate_clock gate_clks[] __initdata = {
590 GATE(CLK_ROTATOR, "rotator", "dout_hclkd", CLK_GATE_IP0, 29, 0, 0),
591 GATE(CLK_FIMC2, "fimc2", "dout_hclkd", CLK_GATE_IP0, 26, 0, 0),
592 GATE(CLK_FIMC1, "fimc1", "dout_hclkd", CLK_GATE_IP0, 25, 0, 0),
593 GATE(CLK_FIMC0, "fimc0", "dout_hclkd", CLK_GATE_IP0, 24, 0, 0),
594 GATE(CLK_PDMA0, "pdma0", "dout_hclkp", CLK_GATE_IP0, 3, 0, 0),
595 GATE(CLK_MDMA, "mdma", "dout_hclkd", CLK_GATE_IP0, 2, 0, 0),
596
597 GATE(CLK_SROMC, "sromc", "dout_hclkp", CLK_GATE_IP1, 26, 0, 0),
598 GATE(CLK_NANDXL, "nandxl", "dout_hclkp", CLK_GATE_IP1, 24, 0, 0),
599 GATE(CLK_USB_OTG, "usb_otg", "dout_hclkp", CLK_GATE_IP1, 16, 0, 0),
600 GATE(CLK_TVENC, "tvenc", "dout_hclkd", CLK_GATE_IP1, 10, 0, 0),
601 GATE(CLK_MIXER, "mixer", "dout_hclkd", CLK_GATE_IP1, 9, 0, 0),
602 GATE(CLK_VP, "vp", "dout_hclkd", CLK_GATE_IP1, 8, 0, 0),
603 GATE(CLK_FIMD, "fimd", "dout_hclkd", CLK_GATE_IP1, 0, 0, 0),
604
605 GATE(CLK_HSMMC2, "hsmmc2", "dout_hclkp", CLK_GATE_IP2, 18, 0, 0),
606 GATE(CLK_HSMMC1, "hsmmc1", "dout_hclkp", CLK_GATE_IP2, 17, 0, 0),
607 GATE(CLK_HSMMC0, "hsmmc0", "dout_hclkp", CLK_GATE_IP2, 16, 0, 0),
608 GATE(CLK_MODEMIF, "modemif", "dout_hclkp", CLK_GATE_IP2, 9, 0, 0),
609 GATE(CLK_SECSS, "secss", "dout_hclkp", CLK_GATE_IP2, 0, 0, 0),
610
611 GATE(CLK_PCM1, "pcm1", "dout_pclkp", CLK_GATE_IP3, 29, 0, 0),
612 GATE(CLK_PCM0, "pcm0", "dout_pclkp", CLK_GATE_IP3, 28, 0, 0),
613 GATE(CLK_TSADC, "tsadc", "dout_pclkp", CLK_GATE_IP3, 24, 0, 0),
614 GATE(CLK_PWM, "pwm", "dout_pclkp", CLK_GATE_IP3, 23, 0, 0),
615 GATE(CLK_WDT, "watchdog", "dout_pclkp", CLK_GATE_IP3, 22, 0, 0),
616 GATE(CLK_KEYIF, "keyif", "dout_pclkp", CLK_GATE_IP3, 21, 0, 0),
617 GATE(CLK_UART2, "uart2", "dout_pclkp", CLK_GATE_IP3, 19, 0, 0),
618 GATE(CLK_UART1, "uart1", "dout_pclkp", CLK_GATE_IP3, 18, 0, 0),
619 GATE(CLK_UART0, "uart0", "dout_pclkp", CLK_GATE_IP3, 17, 0, 0),
620 GATE(CLK_SYSTIMER, "systimer", "dout_pclkp", CLK_GATE_IP3, 16, 0, 0),
621 GATE(CLK_RTC, "rtc", "dout_pclkp", CLK_GATE_IP3, 15, 0, 0),
622 GATE(CLK_SPI0, "spi0", "dout_pclkp", CLK_GATE_IP3, 12, 0, 0),
623 GATE(CLK_I2C2, "i2c2", "dout_pclkp", CLK_GATE_IP3, 9, 0, 0),
624 GATE(CLK_I2C0, "i2c0", "dout_pclkp", CLK_GATE_IP3, 7, 0, 0),
625 GATE(CLK_I2S1, "i2s1", "dout_pclkp", CLK_GATE_IP3, 5, 0, 0),
626 GATE(CLK_I2S0, "i2s0", "dout_pclkp", CLK_GATE_IP3, 4, 0, 0),
627
628 GATE(CLK_SECKEY, "seckey", "dout_pclkp", CLK_GATE_IP4, 3, 0, 0),
629 GATE(CLK_CHIPID, "chipid", "dout_pclkp", CLK_GATE_IP4, 0, 0, 0),
630
631 GATE(SCLK_AUDIO1, "sclk_audio1", "dout_audio1", CLK_SRC_MASK0, 25,
632 CLK_SET_RATE_PARENT, 0),
633 GATE(SCLK_AUDIO0, "sclk_audio0", "dout_audio0", CLK_SRC_MASK0, 24,
634 CLK_SET_RATE_PARENT, 0),
635 GATE(SCLK_PWM, "sclk_pwm", "dout_pwm", CLK_SRC_MASK0, 19,
636 CLK_SET_RATE_PARENT, 0),
637 GATE(SCLK_SPI0, "sclk_spi0", "dout_spi0", CLK_SRC_MASK0, 16,
638 CLK_SET_RATE_PARENT, 0),
639 GATE(SCLK_UART2, "sclk_uart2", "dout_uart2", CLK_SRC_MASK0, 14,
640 CLK_SET_RATE_PARENT, 0),
641 GATE(SCLK_UART1, "sclk_uart1", "dout_uart1", CLK_SRC_MASK0, 13,
642 CLK_SET_RATE_PARENT, 0),
643 GATE(SCLK_UART0, "sclk_uart0", "dout_uart0", CLK_SRC_MASK0, 12,
644 CLK_SET_RATE_PARENT, 0),
645 GATE(SCLK_MMC2, "sclk_mmc2", "dout_mmc2", CLK_SRC_MASK0, 10,
646 CLK_SET_RATE_PARENT, 0),
647 GATE(SCLK_MMC1, "sclk_mmc1", "dout_mmc1", CLK_SRC_MASK0, 9,
648 CLK_SET_RATE_PARENT, 0),
649 GATE(SCLK_MMC0, "sclk_mmc0", "dout_mmc0", CLK_SRC_MASK0, 8,
650 CLK_SET_RATE_PARENT, 0),
651 GATE(SCLK_FIMD, "sclk_fimd", "dout_fimd", CLK_SRC_MASK0, 5,
652 CLK_SET_RATE_PARENT, 0),
653 GATE(SCLK_CAM1, "sclk_cam1", "dout_cam1", CLK_SRC_MASK0, 4,
654 CLK_SET_RATE_PARENT, 0),
655 GATE(SCLK_CAM0, "sclk_cam0", "dout_cam0", CLK_SRC_MASK0, 3,
656 CLK_SET_RATE_PARENT, 0),
657 GATE(SCLK_MIXER, "sclk_mixer", "mout_mixer", CLK_SRC_MASK0, 1,
658 CLK_SET_RATE_PARENT, 0),
659
660 GATE(SCLK_FIMC2, "sclk_fimc2", "dout_fimc2", CLK_SRC_MASK1, 4,
661 CLK_SET_RATE_PARENT, 0),
662 GATE(SCLK_FIMC1, "sclk_fimc1", "dout_fimc1", CLK_SRC_MASK1, 3,
663 CLK_SET_RATE_PARENT, 0),
664 GATE(SCLK_FIMC0, "sclk_fimc0", "dout_fimc0", CLK_SRC_MASK1, 2,
665 CLK_SET_RATE_PARENT, 0),
666};
667
668/* S5PV210-specific clock gates. */
669static struct samsung_gate_clock s5pv210_gate_clks[] __initdata = {
670 GATE(CLK_CSIS, "clk_csis", "dout_hclkd", CLK_GATE_IP0, 31, 0, 0),
671 GATE(CLK_MFC, "mfc", "dout_hclkm", CLK_GATE_IP0, 16, 0, 0),
672 GATE(CLK_G2D, "g2d", "dout_hclkd", CLK_GATE_IP0, 12, 0, 0),
673 GATE(CLK_G3D, "g3d", "dout_hclkm", CLK_GATE_IP0, 8, 0, 0),
674 GATE(CLK_IMEM, "imem", "dout_hclkm", CLK_GATE_IP0, 5, 0, 0),
675 GATE(CLK_PDMA1, "pdma1", "dout_hclkp", CLK_GATE_IP0, 4, 0, 0),
676
677 GATE(CLK_NFCON, "nfcon", "dout_hclkp", CLK_GATE_IP1, 28, 0, 0),
678 GATE(CLK_CFCON, "cfcon", "dout_hclkp", CLK_GATE_IP1, 25, 0, 0),
679 GATE(CLK_USB_HOST, "usb_host", "dout_hclkp", CLK_GATE_IP1, 17, 0, 0),
680 GATE(CLK_HDMI, "hdmi", "dout_hclkd", CLK_GATE_IP1, 11, 0, 0),
681 GATE(CLK_DSIM, "dsim", "dout_pclkd", CLK_GATE_IP1, 2, 0, 0),
682
683 GATE(CLK_TZIC3, "tzic3", "dout_hclkm", CLK_GATE_IP2, 31, 0, 0),
684 GATE(CLK_TZIC2, "tzic2", "dout_hclkm", CLK_GATE_IP2, 30, 0, 0),
685 GATE(CLK_TZIC1, "tzic1", "dout_hclkm", CLK_GATE_IP2, 29, 0, 0),
686 GATE(CLK_TZIC0, "tzic0", "dout_hclkm", CLK_GATE_IP2, 28, 0, 0),
687 GATE(CLK_TSI, "tsi", "dout_hclkd", CLK_GATE_IP2, 20, 0, 0),
688 GATE(CLK_HSMMC3, "hsmmc3", "dout_hclkp", CLK_GATE_IP2, 19, 0, 0),
689 GATE(CLK_JTAG, "jtag", "dout_hclkp", CLK_GATE_IP2, 11, 0, 0),
690 GATE(CLK_CORESIGHT, "coresight", "dout_pclkp", CLK_GATE_IP2, 8, 0, 0),
691 GATE(CLK_SDM, "sdm", "dout_pclkm", CLK_GATE_IP2, 1, 0, 0),
692
693 GATE(CLK_PCM2, "pcm2", "dout_pclkp", CLK_GATE_IP3, 30, 0, 0),
694 GATE(CLK_UART3, "uart3", "dout_pclkp", CLK_GATE_IP3, 20, 0, 0),
695 GATE(CLK_SPI1, "spi1", "dout_pclkp", CLK_GATE_IP3, 13, 0, 0),
696 GATE(CLK_I2C_HDMI_PHY, "i2c_hdmi_phy", "dout_pclkd",
697 CLK_GATE_IP3, 11, 0, 0),
698 GATE(CLK_I2C1, "i2c1", "dout_pclkd", CLK_GATE_IP3, 10, 0, 0),
699 GATE(CLK_I2S2, "i2s2", "dout_pclkp", CLK_GATE_IP3, 6, 0, 0),
700 GATE(CLK_AC97, "ac97", "dout_pclkp", CLK_GATE_IP3, 1, 0, 0),
701 GATE(CLK_SPDIF, "spdif", "dout_pclkp", CLK_GATE_IP3, 0, 0, 0),
702
703 GATE(CLK_TZPC3, "tzpc.3", "dout_pclkd", CLK_GATE_IP4, 8, 0, 0),
704 GATE(CLK_TZPC2, "tzpc.2", "dout_pclkd", CLK_GATE_IP4, 7, 0, 0),
705 GATE(CLK_TZPC1, "tzpc.1", "dout_pclkp", CLK_GATE_IP4, 6, 0, 0),
706 GATE(CLK_TZPC0, "tzpc.0", "dout_pclkm", CLK_GATE_IP4, 5, 0, 0),
707 GATE(CLK_IEM_APC, "iem_apc", "dout_pclkp", CLK_GATE_IP4, 2, 0, 0),
708 GATE(CLK_IEM_IEC, "iem_iec", "dout_pclkp", CLK_GATE_IP4, 1, 0, 0),
709
710 GATE(CLK_JPEG, "jpeg", "dout_hclkd", CLK_GATE_IP5, 29, 0, 0),
711
712 GATE(SCLK_SPDIF, "sclk_spdif", "mout_spdif", CLK_SRC_MASK0, 27,
713 CLK_SET_RATE_PARENT, 0),
714 GATE(SCLK_AUDIO2, "sclk_audio2", "dout_audio2", CLK_SRC_MASK0, 26,
715 CLK_SET_RATE_PARENT, 0),
716 GATE(SCLK_SPI1, "sclk_spi1", "dout_spi1", CLK_SRC_MASK0, 17,
717 CLK_SET_RATE_PARENT, 0),
718 GATE(SCLK_UART3, "sclk_uart3", "dout_uart3", CLK_SRC_MASK0, 15,
719 CLK_SET_RATE_PARENT, 0),
720 GATE(SCLK_MMC3, "sclk_mmc3", "dout_mmc3", CLK_SRC_MASK0, 11,
721 CLK_SET_RATE_PARENT, 0),
722 GATE(SCLK_CSIS, "sclk_csis", "dout_csis", CLK_SRC_MASK0, 6,
723 CLK_SET_RATE_PARENT, 0),
724 GATE(SCLK_DAC, "sclk_dac", "mout_dac", CLK_SRC_MASK0, 2,
725 CLK_SET_RATE_PARENT, 0),
726 GATE(SCLK_HDMI, "sclk_hdmi", "mout_hdmi", CLK_SRC_MASK0, 0,
727 CLK_SET_RATE_PARENT, 0),
728};
729
730/* S5P6442-specific clock gates. */
731static struct samsung_gate_clock s5p6442_gate_clks[] __initdata = {
732 GATE(CLK_JPEG, "jpeg", "dout_hclkd", CLK_GATE_IP0, 28, 0, 0),
733 GATE(CLK_MFC, "mfc", "dout_hclkd", CLK_GATE_IP0, 16, 0, 0),
734 GATE(CLK_G2D, "g2d", "dout_hclkd", CLK_GATE_IP0, 12, 0, 0),
735 GATE(CLK_G3D, "g3d", "dout_hclkd", CLK_GATE_IP0, 8, 0, 0),
736 GATE(CLK_IMEM, "imem", "dout_hclkd", CLK_GATE_IP0, 5, 0, 0),
737
738 GATE(CLK_ETB, "etb", "dout_hclkd", CLK_GATE_IP1, 31, 0, 0),
739 GATE(CLK_ETM, "etm", "dout_hclkd", CLK_GATE_IP1, 30, 0, 0),
740
741 GATE(CLK_I2C1, "i2c1", "dout_pclkp", CLK_GATE_IP3, 8, 0, 0),
742
743 GATE(SCLK_DAC, "sclk_dac", "mout_vpll", CLK_SRC_MASK0, 2,
744 CLK_SET_RATE_PARENT, 0),
745};
746
747/*
748 * Clock aliases for legacy clkdev look-up.
749 * NOTE: Needed only to support legacy board files.
750 */
751static struct samsung_clock_alias s5pv210_aliases[] = {
752 ALIAS(DOUT_APLL, NULL, "armclk"),
753 ALIAS(DOUT_HCLKM, NULL, "hclk_msys"),
754 ALIAS(MOUT_DMC0, NULL, "sclk_dmc0"),
755};
756
757/* S5PV210-specific PLLs. */
758static struct samsung_pll_clock s5pv210_pll_clks[] __initdata = {
759 [apll] = PLL(pll_4508, FOUT_APLL, "fout_apll", "fin_pll",
760 APLL_LOCK, APLL_CON0, NULL),
761 [mpll] = PLL(pll_4502, FOUT_MPLL, "fout_mpll", "fin_pll",
762 MPLL_LOCK, MPLL_CON, NULL),
763 [epll] = PLL(pll_4600, FOUT_EPLL, "fout_epll", "fin_pll",
764 EPLL_LOCK, EPLL_CON0, NULL),
765 [vpll] = PLL(pll_4502, FOUT_VPLL, "fout_vpll", "mout_vpllsrc",
766 VPLL_LOCK, VPLL_CON, NULL),
767};
768
769/* S5P6442-specific PLLs. */
770static struct samsung_pll_clock s5p6442_pll_clks[] __initdata = {
771 [apll] = PLL(pll_4502, FOUT_APLL, "fout_apll", "fin_pll",
772 APLL_LOCK, APLL_CON0, NULL),
773 [mpll] = PLL(pll_4502, FOUT_MPLL, "fout_mpll", "fin_pll",
774 MPLL_LOCK, MPLL_CON, NULL),
775 [epll] = PLL(pll_4500, FOUT_EPLL, "fout_epll", "fin_pll",
776 EPLL_LOCK, EPLL_CON0, NULL),
777 [vpll] = PLL(pll_4500, FOUT_VPLL, "fout_vpll", "fin_pll",
778 VPLL_LOCK, VPLL_CON, NULL),
779};
780
781static void __init __s5pv210_clk_init(struct device_node *np,
782 unsigned long xxti_f,
783 unsigned long xusbxti_f,
784 bool is_s5p6442)
785{
786 struct samsung_clk_provider *ctx;
787
788 ctx = samsung_clk_init(np, reg_base, NR_CLKS);
789 if (!ctx)
790 panic("%s: unable to allocate context.\n", __func__);
791
792 samsung_clk_register_mux(ctx, early_mux_clks,
793 ARRAY_SIZE(early_mux_clks));
794
795 if (is_s5p6442) {
796 samsung_clk_register_fixed_rate(ctx, s5p6442_frate_clks,
797 ARRAY_SIZE(s5p6442_frate_clks));
798 samsung_clk_register_pll(ctx, s5p6442_pll_clks,
799 ARRAY_SIZE(s5p6442_pll_clks), reg_base);
800 samsung_clk_register_mux(ctx, s5p6442_mux_clks,
801 ARRAY_SIZE(s5p6442_mux_clks));
802 samsung_clk_register_div(ctx, s5p6442_div_clks,
803 ARRAY_SIZE(s5p6442_div_clks));
804 samsung_clk_register_gate(ctx, s5p6442_gate_clks,
805 ARRAY_SIZE(s5p6442_gate_clks));
806 } else {
807 samsung_clk_register_fixed_rate(ctx, s5pv210_frate_clks,
808 ARRAY_SIZE(s5pv210_frate_clks));
809 samsung_clk_register_pll(ctx, s5pv210_pll_clks,
810 ARRAY_SIZE(s5pv210_pll_clks), reg_base);
811 samsung_clk_register_mux(ctx, s5pv210_mux_clks,
812 ARRAY_SIZE(s5pv210_mux_clks));
813 samsung_clk_register_div(ctx, s5pv210_div_clks,
814 ARRAY_SIZE(s5pv210_div_clks));
815 samsung_clk_register_gate(ctx, s5pv210_gate_clks,
816 ARRAY_SIZE(s5pv210_gate_clks));
817 }
818
819 samsung_clk_register_mux(ctx, mux_clks, ARRAY_SIZE(mux_clks));
820 samsung_clk_register_div(ctx, div_clks, ARRAY_SIZE(div_clks));
821 samsung_clk_register_gate(ctx, gate_clks, ARRAY_SIZE(gate_clks));
822
823 samsung_clk_register_fixed_factor(ctx, ffactor_clks,
824 ARRAY_SIZE(ffactor_clks));
825
826 samsung_clk_register_alias(ctx, s5pv210_aliases,
827 ARRAY_SIZE(s5pv210_aliases));
828
829 s5pv210_clk_sleep_init();
830
831 pr_info("%s clocks: mout_apll = %ld, mout_mpll = %ld\n"
832 "\tmout_epll = %ld, mout_vpll = %ld\n",
833 is_s5p6442 ? "S5P6442" : "S5PV210",
834 _get_rate("mout_apll"), _get_rate("mout_mpll"),
835 _get_rate("mout_epll"), _get_rate("mout_vpll"));
836}
837
838static void __init s5pv210_clk_dt_init(struct device_node *np)
839{
840 reg_base = of_iomap(np, 0);
841 if (!reg_base)
842 panic("%s: failed to map registers\n", __func__);
843
844 __s5pv210_clk_init(np, 0, 0, false);
845}
846CLK_OF_DECLARE(s5pv210_clk, "samsung,s5pv210-clock", s5pv210_clk_dt_init);
847
848static void __init s5p6442_clk_dt_init(struct device_node *np)
849{
850 reg_base = of_iomap(np, 0);
851 if (!reg_base)
852 panic("%s: failed to map registers\n", __func__);
853
854 __s5pv210_clk_init(np, 0, 0, true);
855}
856CLK_OF_DECLARE(s5p6442_clk, "samsung,s5p6442-clock", s5p6442_clk_dt_init);
diff --git a/drivers/clk/versatile/Makefile b/drivers/clk/versatile/Makefile
index fd449f9b006d..162e519cb0f9 100644
--- a/drivers/clk/versatile/Makefile
+++ b/drivers/clk/versatile/Makefile
@@ -1,6 +1,5 @@
1# Makefile for Versatile-specific clocks 1# Makefile for Versatile-specific clocks
2obj-$(CONFIG_ICST) += clk-icst.o 2obj-$(CONFIG_ICST) += clk-icst.o clk-versatile.o
3obj-$(CONFIG_ARCH_INTEGRATOR) += clk-integrator.o
4obj-$(CONFIG_INTEGRATOR_IMPD1) += clk-impd1.o 3obj-$(CONFIG_INTEGRATOR_IMPD1) += clk-impd1.o
5obj-$(CONFIG_ARCH_REALVIEW) += clk-realview.o 4obj-$(CONFIG_ARCH_REALVIEW) += clk-realview.o
6obj-$(CONFIG_ARCH_VEXPRESS) += clk-vexpress.o 5obj-$(CONFIG_ARCH_VEXPRESS) += clk-vexpress.o
diff --git a/drivers/clk/versatile/clk-integrator.c b/drivers/clk/versatile/clk-versatile.c
index 734c4b8fe6ab..a76981e88cb6 100644
--- a/drivers/clk/versatile/clk-integrator.c
+++ b/drivers/clk/versatile/clk-versatile.c
@@ -1,5 +1,6 @@
1/* 1/*
2 * Clock driver for the ARM Integrator/AP and Integrator/CP boards 2 * Clock driver for the ARM Integrator/AP, Integrator/CP, Versatile AB and
3 * Versatile PB boards.
3 * Copyright (C) 2012 Linus Walleij 4 * Copyright (C) 2012 Linus Walleij
4 * 5 *
5 * This program is free software; you can redistribute it and/or modify 6 * This program is free software; you can redistribute it and/or modify
@@ -17,6 +18,9 @@
17 18
18#define INTEGRATOR_HDR_LOCK_OFFSET 0x14 19#define INTEGRATOR_HDR_LOCK_OFFSET 0x14
19 20
21#define VERSATILE_SYS_OSCCLCD_OFFSET 0x1c
22#define VERSATILE_SYS_LOCK_OFFSET 0x20
23
20/* Base offset for the core module */ 24/* Base offset for the core module */
21static void __iomem *cm_base; 25static void __iomem *cm_base;
22 26
@@ -37,11 +41,27 @@ static const struct clk_icst_desc __initdata cm_auxosc_desc = {
37 .lock_offset = INTEGRATOR_HDR_LOCK_OFFSET, 41 .lock_offset = INTEGRATOR_HDR_LOCK_OFFSET,
38}; 42};
39 43
40static void __init of_integrator_cm_osc_setup(struct device_node *np) 44static const struct icst_params versatile_auxosc_params = {
45 .vco_max = ICST307_VCO_MAX,
46 .vco_min = ICST307_VCO_MIN,
47 .vd_min = 4 + 8,
48 .vd_max = 511 + 8,
49 .rd_min = 1 + 2,
50 .rd_max = 127 + 2,
51 .s2div = icst307_s2div,
52 .idx2s = icst307_idx2s,
53};
54
55static const struct clk_icst_desc versatile_auxosc_desc __initconst = {
56 .params = &versatile_auxosc_params,
57 .vco_offset = VERSATILE_SYS_OSCCLCD_OFFSET,
58 .lock_offset = VERSATILE_SYS_LOCK_OFFSET,
59};
60static void __init cm_osc_setup(struct device_node *np,
61 const struct clk_icst_desc *desc)
41{ 62{
42 struct clk *clk = ERR_PTR(-EINVAL); 63 struct clk *clk = ERR_PTR(-EINVAL);
43 const char *clk_name = np->name; 64 const char *clk_name = np->name;
44 const struct clk_icst_desc *desc = &cm_auxosc_desc;
45 const char *parent_name; 65 const char *parent_name;
46 66
47 if (!cm_base) { 67 if (!cm_base) {
@@ -65,5 +85,17 @@ static void __init of_integrator_cm_osc_setup(struct device_node *np)
65 if (!IS_ERR(clk)) 85 if (!IS_ERR(clk))
66 of_clk_add_provider(np, of_clk_src_simple_get, clk); 86 of_clk_add_provider(np, of_clk_src_simple_get, clk);
67} 87}
88
89static void __init of_integrator_cm_osc_setup(struct device_node *np)
90{
91 cm_osc_setup(np, &cm_auxosc_desc);
92}
68CLK_OF_DECLARE(integrator_cm_auxosc_clk, 93CLK_OF_DECLARE(integrator_cm_auxosc_clk,
69 "arm,integrator-cm-auxosc", of_integrator_cm_osc_setup); 94 "arm,integrator-cm-auxosc", of_integrator_cm_osc_setup);
95
96static void __init of_versatile_cm_osc_setup(struct device_node *np)
97{
98 cm_osc_setup(np, &versatile_auxosc_desc);
99}
100CLK_OF_DECLARE(versatile_cm_auxosc_clk,
101 "arm,versatile-cm-auxosc", of_versatile_cm_osc_setup);
diff --git a/drivers/clocksource/tegra20_timer.c b/drivers/clocksource/tegra20_timer.c
index d1869f02051c..d2616ef16770 100644
--- a/drivers/clocksource/tegra20_timer.c
+++ b/drivers/clocksource/tegra20_timer.c
@@ -27,6 +27,7 @@
27#include <linux/of_address.h> 27#include <linux/of_address.h>
28#include <linux/of_irq.h> 28#include <linux/of_irq.h>
29#include <linux/sched_clock.h> 29#include <linux/sched_clock.h>
30#include <linux/delay.h>
30 31
31#include <asm/mach/time.h> 32#include <asm/mach/time.h>
32#include <asm/smp_twd.h> 33#include <asm/smp_twd.h>
@@ -53,6 +54,8 @@ static void __iomem *rtc_base;
53static struct timespec persistent_ts; 54static struct timespec persistent_ts;
54static u64 persistent_ms, last_persistent_ms; 55static u64 persistent_ms, last_persistent_ms;
55 56
57static struct delay_timer tegra_delay_timer;
58
56#define timer_writel(value, reg) \ 59#define timer_writel(value, reg) \
57 __raw_writel(value, timer_reg_base + (reg)) 60 __raw_writel(value, timer_reg_base + (reg))
58#define timer_readl(reg) \ 61#define timer_readl(reg) \
@@ -139,6 +142,11 @@ static void tegra_read_persistent_clock(struct timespec *ts)
139 *ts = *tsp; 142 *ts = *tsp;
140} 143}
141 144
145static unsigned long tegra_delay_timer_read_counter_long(void)
146{
147 return readl(timer_reg_base + TIMERUS_CNTR_1US);
148}
149
142static irqreturn_t tegra_timer_interrupt(int irq, void *dev_id) 150static irqreturn_t tegra_timer_interrupt(int irq, void *dev_id)
143{ 151{
144 struct clock_event_device *evt = (struct clock_event_device *)dev_id; 152 struct clock_event_device *evt = (struct clock_event_device *)dev_id;
@@ -206,6 +214,11 @@ static void __init tegra20_init_timer(struct device_node *np)
206 BUG(); 214 BUG();
207 } 215 }
208 216
217 tegra_delay_timer.read_current_timer =
218 tegra_delay_timer_read_counter_long;
219 tegra_delay_timer.freq = 1000000;
220 register_current_timer_delay(&tegra_delay_timer);
221
209 ret = setup_irq(tegra_timer_irq.irq, &tegra_timer_irq); 222 ret = setup_irq(tegra_timer_irq.irq, &tegra_timer_irq);
210 if (ret) { 223 if (ret) {
211 pr_err("Failed to register timer IRQ: %d\n", ret); 224 pr_err("Failed to register timer IRQ: %d\n", ret);
diff --git a/drivers/cpufreq/s3c2410-cpufreq.c b/drivers/cpufreq/s3c2410-cpufreq.c
index cfa0dd8723ec..b8e5da8e188b 100644
--- a/drivers/cpufreq/s3c2410-cpufreq.c
+++ b/drivers/cpufreq/s3c2410-cpufreq.c
@@ -26,7 +26,6 @@
26#include <mach/regs-clock.h> 26#include <mach/regs-clock.h>
27 27
28#include <plat/cpu.h> 28#include <plat/cpu.h>
29#include <plat/clock.h>
30#include <plat/cpu-freq-core.h> 29#include <plat/cpu-freq-core.h>
31 30
32/* Note, 2410A has an extra mode for 1:4:4 ratio, bit 2 of CLKDIV */ 31/* Note, 2410A has an extra mode for 1:4:4 ratio, bit 2 of CLKDIV */
@@ -104,7 +103,6 @@ static struct s3c_cpufreq_info s3c2410_cpufreq_info = {
104 .calc_iotiming = s3c2410_iotiming_calc, 103 .calc_iotiming = s3c2410_iotiming_calc,
105 .set_iotiming = s3c2410_iotiming_set, 104 .set_iotiming = s3c2410_iotiming_set,
106 .get_iotiming = s3c2410_iotiming_get, 105 .get_iotiming = s3c2410_iotiming_get,
107 .resume_clocks = s3c2410_setup_clocks,
108 106
109 .set_fvco = s3c2410_set_fvco, 107 .set_fvco = s3c2410_set_fvco,
110 .set_refresh = s3c2410_cpufreq_setrefresh, 108 .set_refresh = s3c2410_cpufreq_setrefresh,
diff --git a/drivers/cpufreq/s3c2412-cpufreq.c b/drivers/cpufreq/s3c2412-cpufreq.c
index 4645b4898996..eb262133fef2 100644
--- a/drivers/cpufreq/s3c2412-cpufreq.c
+++ b/drivers/cpufreq/s3c2412-cpufreq.c
@@ -28,7 +28,6 @@
28#include <mach/s3c2412.h> 28#include <mach/s3c2412.h>
29 29
30#include <plat/cpu.h> 30#include <plat/cpu.h>
31#include <plat/clock.h>
32#include <plat/cpu-freq-core.h> 31#include <plat/cpu-freq-core.h>
33 32
34/* our clock resources. */ 33/* our clock resources. */
@@ -188,8 +187,6 @@ static struct s3c_cpufreq_info s3c2412_cpufreq_info = {
188 .set_iotiming = s3c2412_iotiming_set, 187 .set_iotiming = s3c2412_iotiming_set,
189 .get_iotiming = s3c2412_iotiming_get, 188 .get_iotiming = s3c2412_iotiming_get,
190 189
191 .resume_clocks = s3c2412_setup_clocks,
192
193 .debug_io_show = s3c_cpufreq_debugfs_call(s3c2412_iotiming_debugfs), 190 .debug_io_show = s3c_cpufreq_debugfs_call(s3c2412_iotiming_debugfs),
194}; 191};
195 192
diff --git a/drivers/cpufreq/s3c2440-cpufreq.c b/drivers/cpufreq/s3c2440-cpufreq.c
index f84ed10755b5..0129f5c70a61 100644
--- a/drivers/cpufreq/s3c2440-cpufreq.c
+++ b/drivers/cpufreq/s3c2440-cpufreq.c
@@ -29,7 +29,6 @@
29 29
30#include <plat/cpu.h> 30#include <plat/cpu.h>
31#include <plat/cpu-freq-core.h> 31#include <plat/cpu-freq-core.h>
32#include <plat/clock.h>
33 32
34static struct clk *xtal; 33static struct clk *xtal;
35static struct clk *fclk; 34static struct clk *fclk;
@@ -262,8 +261,6 @@ static struct s3c_cpufreq_info s3c2440_cpufreq_info = {
262 .calc_divs = s3c2440_cpufreq_calcdivs, 261 .calc_divs = s3c2440_cpufreq_calcdivs,
263 .calc_freqtable = s3c2440_cpufreq_calctable, 262 .calc_freqtable = s3c2440_cpufreq_calctable,
264 263
265 .resume_clocks = s3c244x_setup_clocks,
266
267 .debug_io_show = s3c_cpufreq_debugfs_call(s3c2410_iotiming_debugfs), 264 .debug_io_show = s3c_cpufreq_debugfs_call(s3c2410_iotiming_debugfs),
268}; 265};
269 266
diff --git a/drivers/cpufreq/s3c24xx-cpufreq.c b/drivers/cpufreq/s3c24xx-cpufreq.c
index 227ebf7c1eea..d00f1cee4509 100644
--- a/drivers/cpufreq/s3c24xx-cpufreq.c
+++ b/drivers/cpufreq/s3c24xx-cpufreq.c
@@ -27,7 +27,6 @@
27#include <asm/mach/map.h> 27#include <asm/mach/map.h>
28 28
29#include <plat/cpu.h> 29#include <plat/cpu.h>
30#include <plat/clock.h>
31#include <plat/cpu-freq-core.h> 30#include <plat/cpu-freq-core.h>
32 31
33#include <mach/regs-clock.h> 32#include <mach/regs-clock.h>
diff --git a/drivers/cpufreq/s5pv210-cpufreq.c b/drivers/cpufreq/s5pv210-cpufreq.c
index 19a10b89fef7..9a68225a757e 100644
--- a/drivers/cpufreq/s5pv210-cpufreq.c
+++ b/drivers/cpufreq/s5pv210-cpufreq.c
@@ -16,11 +16,70 @@
16#include <linux/clk.h> 16#include <linux/clk.h>
17#include <linux/io.h> 17#include <linux/io.h>
18#include <linux/cpufreq.h> 18#include <linux/cpufreq.h>
19#include <linux/of.h>
20#include <linux/of_address.h>
21#include <linux/platform_device.h>
19#include <linux/reboot.h> 22#include <linux/reboot.h>
20#include <linux/regulator/consumer.h> 23#include <linux/regulator/consumer.h>
21 24
22#include <mach/map.h> 25static void __iomem *clk_base;
23#include <mach/regs-clock.h> 26static void __iomem *dmc_base[2];
27
28#define S5P_CLKREG(x) (clk_base + (x))
29
30#define S5P_APLL_LOCK S5P_CLKREG(0x00)
31#define S5P_APLL_CON S5P_CLKREG(0x100)
32#define S5P_CLK_SRC0 S5P_CLKREG(0x200)
33#define S5P_CLK_SRC2 S5P_CLKREG(0x208)
34#define S5P_CLK_DIV0 S5P_CLKREG(0x300)
35#define S5P_CLK_DIV2 S5P_CLKREG(0x308)
36#define S5P_CLK_DIV6 S5P_CLKREG(0x318)
37#define S5P_CLKDIV_STAT0 S5P_CLKREG(0x1000)
38#define S5P_CLKDIV_STAT1 S5P_CLKREG(0x1004)
39#define S5P_CLKMUX_STAT0 S5P_CLKREG(0x1100)
40#define S5P_CLKMUX_STAT1 S5P_CLKREG(0x1104)
41
42#define S5P_ARM_MCS_CON S5P_CLKREG(0x6100)
43
44/* CLKSRC0 */
45#define S5P_CLKSRC0_MUX200_SHIFT (16)
46#define S5P_CLKSRC0_MUX200_MASK (0x1 << S5P_CLKSRC0_MUX200_SHIFT)
47#define S5P_CLKSRC0_MUX166_MASK (0x1<<20)
48#define S5P_CLKSRC0_MUX133_MASK (0x1<<24)
49
50/* CLKSRC2 */
51#define S5P_CLKSRC2_G3D_SHIFT (0)
52#define S5P_CLKSRC2_G3D_MASK (0x3 << S5P_CLKSRC2_G3D_SHIFT)
53#define S5P_CLKSRC2_MFC_SHIFT (4)
54#define S5P_CLKSRC2_MFC_MASK (0x3 << S5P_CLKSRC2_MFC_SHIFT)
55
56/* CLKDIV0 */
57#define S5P_CLKDIV0_APLL_SHIFT (0)
58#define S5P_CLKDIV0_APLL_MASK (0x7 << S5P_CLKDIV0_APLL_SHIFT)
59#define S5P_CLKDIV0_A2M_SHIFT (4)
60#define S5P_CLKDIV0_A2M_MASK (0x7 << S5P_CLKDIV0_A2M_SHIFT)
61#define S5P_CLKDIV0_HCLK200_SHIFT (8)
62#define S5P_CLKDIV0_HCLK200_MASK (0x7 << S5P_CLKDIV0_HCLK200_SHIFT)
63#define S5P_CLKDIV0_PCLK100_SHIFT (12)
64#define S5P_CLKDIV0_PCLK100_MASK (0x7 << S5P_CLKDIV0_PCLK100_SHIFT)
65#define S5P_CLKDIV0_HCLK166_SHIFT (16)
66#define S5P_CLKDIV0_HCLK166_MASK (0xF << S5P_CLKDIV0_HCLK166_SHIFT)
67#define S5P_CLKDIV0_PCLK83_SHIFT (20)
68#define S5P_CLKDIV0_PCLK83_MASK (0x7 << S5P_CLKDIV0_PCLK83_SHIFT)
69#define S5P_CLKDIV0_HCLK133_SHIFT (24)
70#define S5P_CLKDIV0_HCLK133_MASK (0xF << S5P_CLKDIV0_HCLK133_SHIFT)
71#define S5P_CLKDIV0_PCLK66_SHIFT (28)
72#define S5P_CLKDIV0_PCLK66_MASK (0x7 << S5P_CLKDIV0_PCLK66_SHIFT)
73
74/* CLKDIV2 */
75#define S5P_CLKDIV2_G3D_SHIFT (0)
76#define S5P_CLKDIV2_G3D_MASK (0xF << S5P_CLKDIV2_G3D_SHIFT)
77#define S5P_CLKDIV2_MFC_SHIFT (4)
78#define S5P_CLKDIV2_MFC_MASK (0xF << S5P_CLKDIV2_MFC_SHIFT)
79
80/* CLKDIV6 */
81#define S5P_CLKDIV6_ONEDRAM_SHIFT (28)
82#define S5P_CLKDIV6_ONEDRAM_MASK (0xF << S5P_CLKDIV6_ONEDRAM_SHIFT)
24 83
25static struct clk *dmc0_clk; 84static struct clk *dmc0_clk;
26static struct clk *dmc1_clk; 85static struct clk *dmc1_clk;
@@ -142,9 +201,9 @@ static void s5pv210_set_refresh(enum s5pv210_dmc_port ch, unsigned long freq)
142 void __iomem *reg = NULL; 201 void __iomem *reg = NULL;
143 202
144 if (ch == DMC0) { 203 if (ch == DMC0) {
145 reg = (S5P_VA_DMC0 + 0x30); 204 reg = (dmc_base[0] + 0x30);
146 } else if (ch == DMC1) { 205 } else if (ch == DMC1) {
147 reg = (S5P_VA_DMC1 + 0x30); 206 reg = (dmc_base[1] + 0x30);
148 } else { 207 } else {
149 printk(KERN_ERR "Cannot find DMC port\n"); 208 printk(KERN_ERR "Cannot find DMC port\n");
150 return; 209 return;
@@ -472,7 +531,7 @@ static int __init s5pv210_cpu_init(struct cpufreq_policy *policy)
472 * check_mem_type : This driver only support LPDDR & LPDDR2. 531 * check_mem_type : This driver only support LPDDR & LPDDR2.
473 * other memory type is not supported. 532 * other memory type is not supported.
474 */ 533 */
475 mem_type = check_mem_type(S5P_VA_DMC0); 534 mem_type = check_mem_type(dmc_base[0]);
476 535
477 if ((mem_type != LPDDR) && (mem_type != LPDDR2)) { 536 if ((mem_type != LPDDR) && (mem_type != LPDDR2)) {
478 printk(KERN_ERR "CPUFreq doesn't support this memory type\n"); 537 printk(KERN_ERR "CPUFreq doesn't support this memory type\n");
@@ -481,10 +540,10 @@ static int __init s5pv210_cpu_init(struct cpufreq_policy *policy)
481 } 540 }
482 541
483 /* Find current refresh counter and frequency each DMC */ 542 /* Find current refresh counter and frequency each DMC */
484 s5pv210_dram_conf[0].refresh = (__raw_readl(S5P_VA_DMC0 + 0x30) * 1000); 543 s5pv210_dram_conf[0].refresh = (__raw_readl(dmc_base[0] + 0x30) * 1000);
485 s5pv210_dram_conf[0].freq = clk_get_rate(dmc0_clk); 544 s5pv210_dram_conf[0].freq = clk_get_rate(dmc0_clk);
486 545
487 s5pv210_dram_conf[1].refresh = (__raw_readl(S5P_VA_DMC1 + 0x30) * 1000); 546 s5pv210_dram_conf[1].refresh = (__raw_readl(dmc_base[1] + 0x30) * 1000);
488 s5pv210_dram_conf[1].freq = clk_get_rate(dmc1_clk); 547 s5pv210_dram_conf[1].freq = clk_get_rate(dmc1_clk);
489 548
490 policy->suspend_freq = SLEEP_FREQ; 549 policy->suspend_freq = SLEEP_FREQ;
@@ -527,8 +586,55 @@ static struct notifier_block s5pv210_cpufreq_reboot_notifier = {
527 .notifier_call = s5pv210_cpufreq_reboot_notifier_event, 586 .notifier_call = s5pv210_cpufreq_reboot_notifier_event,
528}; 587};
529 588
530static int __init s5pv210_cpufreq_init(void) 589static int s5pv210_cpufreq_probe(struct platform_device *pdev)
531{ 590{
591 struct device_node *np;
592 int id;
593
594 /*
595 * HACK: This is a temporary workaround to get access to clock
596 * and DMC controller registers directly and remove static mappings
597 * and dependencies on platform headers. It is necessary to enable
598 * S5PV210 multi-platform support and will be removed together with
599 * this whole driver as soon as S5PV210 gets migrated to use
600 * cpufreq-cpu0 driver.
601 */
602 np = of_find_compatible_node(NULL, NULL, "samsung,s5pv210-clock");
603 if (!np) {
604 pr_err("%s: failed to find clock controller DT node\n",
605 __func__);
606 return -ENODEV;
607 }
608
609 clk_base = of_iomap(np, 0);
610 if (!clk_base) {
611 pr_err("%s: failed to map clock registers\n", __func__);
612 return -EFAULT;
613 }
614
615 for_each_compatible_node(np, NULL, "samsung,s5pv210-dmc") {
616 id = of_alias_get_id(np, "dmc");
617 if (id < 0 || id >= ARRAY_SIZE(dmc_base)) {
618 pr_err("%s: failed to get alias of dmc node '%s'\n",
619 __func__, np->name);
620 return id;
621 }
622
623 dmc_base[id] = of_iomap(np, 0);
624 if (!dmc_base[id]) {
625 pr_err("%s: failed to map dmc%d registers\n",
626 __func__, id);
627 return -EFAULT;
628 }
629 }
630
631 for (id = 0; id < ARRAY_SIZE(dmc_base); ++id) {
632 if (!dmc_base[id]) {
633 pr_err("%s: failed to find dmc%d node\n", __func__, id);
634 return -ENODEV;
635 }
636 }
637
532 arm_regulator = regulator_get(NULL, "vddarm"); 638 arm_regulator = regulator_get(NULL, "vddarm");
533 if (IS_ERR(arm_regulator)) { 639 if (IS_ERR(arm_regulator)) {
534 pr_err("failed to get regulator vddarm"); 640 pr_err("failed to get regulator vddarm");
@@ -547,4 +653,11 @@ static int __init s5pv210_cpufreq_init(void)
547 return cpufreq_register_driver(&s5pv210_driver); 653 return cpufreq_register_driver(&s5pv210_driver);
548} 654}
549 655
550late_initcall(s5pv210_cpufreq_init); 656static struct platform_driver s5pv210_cpufreq_platdrv = {
657 .driver = {
658 .name = "s5pv210-cpufreq",
659 .owner = THIS_MODULE,
660 },
661 .probe = s5pv210_cpufreq_probe,
662};
663module_platform_driver(s5pv210_cpufreq_platdrv);
diff --git a/drivers/cpuidle/Kconfig.arm b/drivers/cpuidle/Kconfig.arm
index a186dec8e5df..38cff69ffe06 100644
--- a/drivers/cpuidle/Kconfig.arm
+++ b/drivers/cpuidle/Kconfig.arm
@@ -1,15 +1,9 @@
1# 1#
2# ARM CPU Idle drivers 2# ARM CPU Idle drivers
3# 3#
4config ARM_ARMADA_370_XP_CPUIDLE
5 bool "CPU Idle Driver for Armada 370/XP family processors"
6 depends on ARCH_MVEBU
7 help
8 Select this to enable cpuidle on Armada 370/XP processors.
9
10config ARM_BIG_LITTLE_CPUIDLE 4config ARM_BIG_LITTLE_CPUIDLE
11 bool "Support for ARM big.LITTLE processors" 5 bool "Support for ARM big.LITTLE processors"
12 depends on ARCH_VEXPRESS_TC2_PM 6 depends on ARCH_VEXPRESS_TC2_PM || ARCH_EXYNOS
13 depends on MCPM 7 depends on MCPM
14 select ARM_CPU_SUSPEND 8 select ARM_CPU_SUSPEND
15 select CPU_IDLE_MULTIPLE_DRIVERS 9 select CPU_IDLE_MULTIPLE_DRIVERS
@@ -62,3 +56,9 @@ config ARM_EXYNOS_CPUIDLE
62 depends on ARCH_EXYNOS 56 depends on ARCH_EXYNOS
63 help 57 help
64 Select this to enable cpuidle for Exynos processors 58 Select this to enable cpuidle for Exynos processors
59
60config ARM_MVEBU_V7_CPUIDLE
61 bool "CPU Idle Driver for mvebu v7 family processors"
62 depends on ARCH_MVEBU
63 help
64 Select this to enable cpuidle on Armada 370, 38x and XP processors.
diff --git a/drivers/cpuidle/Makefile b/drivers/cpuidle/Makefile
index d8bb1ff72561..11edb31c55e9 100644
--- a/drivers/cpuidle/Makefile
+++ b/drivers/cpuidle/Makefile
@@ -7,7 +7,7 @@ obj-$(CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED) += coupled.o
7 7
8################################################################################## 8##################################################################################
9# ARM SoC drivers 9# ARM SoC drivers
10obj-$(CONFIG_ARM_ARMADA_370_XP_CPUIDLE) += cpuidle-armada-370-xp.o 10obj-$(CONFIG_ARM_MVEBU_V7_CPUIDLE) += cpuidle-mvebu-v7.o
11obj-$(CONFIG_ARM_BIG_LITTLE_CPUIDLE) += cpuidle-big_little.o 11obj-$(CONFIG_ARM_BIG_LITTLE_CPUIDLE) += cpuidle-big_little.o
12obj-$(CONFIG_ARM_CLPS711X_CPUIDLE) += cpuidle-clps711x.o 12obj-$(CONFIG_ARM_CLPS711X_CPUIDLE) += cpuidle-clps711x.o
13obj-$(CONFIG_ARM_HIGHBANK_CPUIDLE) += cpuidle-calxeda.o 13obj-$(CONFIG_ARM_HIGHBANK_CPUIDLE) += cpuidle-calxeda.o
diff --git a/drivers/cpuidle/cpuidle-armada-370-xp.c b/drivers/cpuidle/cpuidle-armada-370-xp.c
deleted file mode 100644
index a5fba0287bfb..000000000000
--- a/drivers/cpuidle/cpuidle-armada-370-xp.c
+++ /dev/null
@@ -1,93 +0,0 @@
1/*
2 * Marvell Armada 370 and Armada XP SoC cpuidle driver
3 *
4 * Copyright (C) 2014 Marvell
5 *
6 * Nadav Haklai <nadavh@marvell.com>
7 * Gregory CLEMENT <gregory.clement@free-electrons.com>
8 *
9 * This file is licensed under the terms of the GNU General Public
10 * License version 2. This program is licensed "as is" without any
11 * warranty of any kind, whether express or implied.
12 *
13 * Maintainer: Gregory CLEMENT <gregory.clement@free-electrons.com>
14 */
15
16#include <linux/cpu_pm.h>
17#include <linux/cpuidle.h>
18#include <linux/module.h>
19#include <linux/of.h>
20#include <linux/suspend.h>
21#include <linux/platform_device.h>
22#include <asm/cpuidle.h>
23
24#define ARMADA_370_XP_MAX_STATES 3
25#define ARMADA_370_XP_FLAG_DEEP_IDLE 0x10000
26
27static int (*armada_370_xp_cpu_suspend)(int);
28
29static int armada_370_xp_enter_idle(struct cpuidle_device *dev,
30 struct cpuidle_driver *drv,
31 int index)
32{
33 int ret;
34 bool deepidle = false;
35 cpu_pm_enter();
36
37 if (drv->states[index].flags & ARMADA_370_XP_FLAG_DEEP_IDLE)
38 deepidle = true;
39
40 ret = armada_370_xp_cpu_suspend(deepidle);
41 if (ret)
42 return ret;
43
44 cpu_pm_exit();
45
46 return index;
47}
48
49static struct cpuidle_driver armada_370_xp_idle_driver = {
50 .name = "armada_370_xp_idle",
51 .states[0] = ARM_CPUIDLE_WFI_STATE,
52 .states[1] = {
53 .enter = armada_370_xp_enter_idle,
54 .exit_latency = 10,
55 .power_usage = 50,
56 .target_residency = 100,
57 .flags = CPUIDLE_FLAG_TIME_VALID,
58 .name = "Idle",
59 .desc = "CPU power down",
60 },
61 .states[2] = {
62 .enter = armada_370_xp_enter_idle,
63 .exit_latency = 100,
64 .power_usage = 5,
65 .target_residency = 1000,
66 .flags = CPUIDLE_FLAG_TIME_VALID |
67 ARMADA_370_XP_FLAG_DEEP_IDLE,
68 .name = "Deep idle",
69 .desc = "CPU and L2 Fabric power down",
70 },
71 .state_count = ARMADA_370_XP_MAX_STATES,
72};
73
74static int armada_370_xp_cpuidle_probe(struct platform_device *pdev)
75{
76
77 armada_370_xp_cpu_suspend = (void *)(pdev->dev.platform_data);
78 return cpuidle_register(&armada_370_xp_idle_driver, NULL);
79}
80
81static struct platform_driver armada_370_xp_cpuidle_plat_driver = {
82 .driver = {
83 .name = "cpuidle-armada-370-xp",
84 .owner = THIS_MODULE,
85 },
86 .probe = armada_370_xp_cpuidle_probe,
87};
88
89module_platform_driver(armada_370_xp_cpuidle_plat_driver);
90
91MODULE_AUTHOR("Gregory CLEMENT <gregory.clement@free-electrons.com>");
92MODULE_DESCRIPTION("Armada 370/XP cpu idle driver");
93MODULE_LICENSE("GPL");
diff --git a/drivers/cpuidle/cpuidle-big_little.c b/drivers/cpuidle/cpuidle-big_little.c
index b45fc6249041..344d79fa3407 100644
--- a/drivers/cpuidle/cpuidle-big_little.c
+++ b/drivers/cpuidle/cpuidle-big_little.c
@@ -163,14 +163,24 @@ static int __init bl_idle_driver_init(struct cpuidle_driver *drv, int cpu_id)
163 return 0; 163 return 0;
164} 164}
165 165
166static const struct of_device_id compatible_machine_match[] = {
167 { .compatible = "arm,vexpress,v2p-ca15_a7" },
168 { .compatible = "samsung,exynos5420" },
169 {},
170};
171
166static int __init bl_idle_init(void) 172static int __init bl_idle_init(void)
167{ 173{
168 int ret; 174 int ret;
175 struct device_node *root = of_find_node_by_path("/");
176
177 if (!root)
178 return -ENODEV;
169 179
170 /* 180 /*
171 * Initialize the driver just for a compliant set of machines 181 * Initialize the driver just for a compliant set of machines
172 */ 182 */
173 if (!of_machine_is_compatible("arm,vexpress,v2p-ca15_a7")) 183 if (!of_match_node(compatible_machine_match, root))
174 return -ENODEV; 184 return -ENODEV;
175 /* 185 /*
176 * For now the differentiation between little and big cores 186 * For now the differentiation between little and big cores
diff --git a/drivers/cpuidle/cpuidle-mvebu-v7.c b/drivers/cpuidle/cpuidle-mvebu-v7.c
new file mode 100644
index 000000000000..45371bb16214
--- /dev/null
+++ b/drivers/cpuidle/cpuidle-mvebu-v7.c
@@ -0,0 +1,150 @@
1/*
2 * Marvell Armada 370, 38x and XP SoC cpuidle driver
3 *
4 * Copyright (C) 2014 Marvell
5 *
6 * Nadav Haklai <nadavh@marvell.com>
7 * Gregory CLEMENT <gregory.clement@free-electrons.com>
8 *
9 * This file is licensed under the terms of the GNU General Public
10 * License version 2. This program is licensed "as is" without any
11 * warranty of any kind, whether express or implied.
12 *
13 * Maintainer: Gregory CLEMENT <gregory.clement@free-electrons.com>
14 */
15
16#include <linux/cpu_pm.h>
17#include <linux/cpuidle.h>
18#include <linux/module.h>
19#include <linux/of.h>
20#include <linux/suspend.h>
21#include <linux/platform_device.h>
22#include <asm/cpuidle.h>
23
24#define MVEBU_V7_FLAG_DEEP_IDLE 0x10000
25
26static int (*mvebu_v7_cpu_suspend)(int);
27
28static int mvebu_v7_enter_idle(struct cpuidle_device *dev,
29 struct cpuidle_driver *drv,
30 int index)
31{
32 int ret;
33 bool deepidle = false;
34 cpu_pm_enter();
35
36 if (drv->states[index].flags & MVEBU_V7_FLAG_DEEP_IDLE)
37 deepidle = true;
38
39 ret = mvebu_v7_cpu_suspend(deepidle);
40 if (ret)
41 return ret;
42
43 cpu_pm_exit();
44
45 return index;
46}
47
48static struct cpuidle_driver armadaxp_idle_driver = {
49 .name = "armada_xp_idle",
50 .states[0] = ARM_CPUIDLE_WFI_STATE,
51 .states[1] = {
52 .enter = mvebu_v7_enter_idle,
53 .exit_latency = 10,
54 .power_usage = 50,
55 .target_residency = 100,
56 .flags = CPUIDLE_FLAG_TIME_VALID,
57 .name = "MV CPU IDLE",
58 .desc = "CPU power down",
59 },
60 .states[2] = {
61 .enter = mvebu_v7_enter_idle,
62 .exit_latency = 100,
63 .power_usage = 5,
64 .target_residency = 1000,
65 .flags = CPUIDLE_FLAG_TIME_VALID |
66 MVEBU_V7_FLAG_DEEP_IDLE,
67 .name = "MV CPU DEEP IDLE",
68 .desc = "CPU and L2 Fabric power down",
69 },
70 .state_count = 3,
71};
72
73static struct cpuidle_driver armada370_idle_driver = {
74 .name = "armada_370_idle",
75 .states[0] = ARM_CPUIDLE_WFI_STATE,
76 .states[1] = {
77 .enter = mvebu_v7_enter_idle,
78 .exit_latency = 100,
79 .power_usage = 5,
80 .target_residency = 1000,
81 .flags = (CPUIDLE_FLAG_TIME_VALID |
82 MVEBU_V7_FLAG_DEEP_IDLE),
83 .name = "Deep Idle",
84 .desc = "CPU and L2 Fabric power down",
85 },
86 .state_count = 2,
87};
88
89static struct cpuidle_driver armada38x_idle_driver = {
90 .name = "armada_38x_idle",
91 .states[0] = ARM_CPUIDLE_WFI_STATE,
92 .states[1] = {
93 .enter = mvebu_v7_enter_idle,
94 .exit_latency = 10,
95 .power_usage = 5,
96 .target_residency = 100,
97 .flags = CPUIDLE_FLAG_TIME_VALID,
98 .name = "Idle",
99 .desc = "CPU and SCU power down",
100 },
101 .state_count = 2,
102};
103
104static int mvebu_v7_cpuidle_probe(struct platform_device *pdev)
105{
106 mvebu_v7_cpu_suspend = pdev->dev.platform_data;
107
108 if (!strcmp(pdev->dev.driver->name, "cpuidle-armada-xp"))
109 return cpuidle_register(&armadaxp_idle_driver, NULL);
110 else if (!strcmp(pdev->dev.driver->name, "cpuidle-armada-370"))
111 return cpuidle_register(&armada370_idle_driver, NULL);
112 else if (!strcmp(pdev->dev.driver->name, "cpuidle-armada-38x"))
113 return cpuidle_register(&armada38x_idle_driver, NULL);
114 else
115 return -EINVAL;
116}
117
118static struct platform_driver armadaxp_cpuidle_plat_driver = {
119 .driver = {
120 .name = "cpuidle-armada-xp",
121 .owner = THIS_MODULE,
122 },
123 .probe = mvebu_v7_cpuidle_probe,
124};
125
126module_platform_driver(armadaxp_cpuidle_plat_driver);
127
128static struct platform_driver armada370_cpuidle_plat_driver = {
129 .driver = {
130 .name = "cpuidle-armada-370",
131 .owner = THIS_MODULE,
132 },
133 .probe = mvebu_v7_cpuidle_probe,
134};
135
136module_platform_driver(armada370_cpuidle_plat_driver);
137
138static struct platform_driver armada38x_cpuidle_plat_driver = {
139 .driver = {
140 .name = "cpuidle-armada-38x",
141 .owner = THIS_MODULE,
142 },
143 .probe = mvebu_v7_cpuidle_probe,
144};
145
146module_platform_driver(armada38x_cpuidle_plat_driver);
147
148MODULE_AUTHOR("Gregory CLEMENT <gregory.clement@free-electrons.com>");
149MODULE_DESCRIPTION("Marvell EBU v7 cpuidle driver");
150MODULE_LICENSE("GPL");
diff --git a/drivers/gpio/gpio-samsung.c b/drivers/gpio/gpio-samsung.c
index d9cff026827e..3810da47043f 100644
--- a/drivers/gpio/gpio-samsung.c
+++ b/drivers/gpio/gpio-samsung.c
@@ -1166,234 +1166,9 @@ static struct samsung_gpio_chip s3c64xx_gpios_2bit[] = {
1166#endif 1166#endif
1167}; 1167};
1168 1168
1169/*
1170 * Followings are the gpio banks in S5PV210/S5PC110
1171 *
1172 * The 'config' member when left to NULL, is initialized to the default
1173 * structure samsung_gpio_cfgs[3] in the init function below.
1174 *
1175 * The 'base' member is also initialized in the init function below.
1176 * Note: The initialization of 'base' member of samsung_gpio_chip structure
1177 * uses the above macro and depends on the banks being listed in order here.
1178 */
1179
1180static struct samsung_gpio_chip s5pv210_gpios_4bit[] = {
1181#ifdef CONFIG_CPU_S5PV210
1182 {
1183 .chip = {
1184 .base = S5PV210_GPA0(0),
1185 .ngpio = S5PV210_GPIO_A0_NR,
1186 .label = "GPA0",
1187 },
1188 }, {
1189 .chip = {
1190 .base = S5PV210_GPA1(0),
1191 .ngpio = S5PV210_GPIO_A1_NR,
1192 .label = "GPA1",
1193 },
1194 }, {
1195 .chip = {
1196 .base = S5PV210_GPB(0),
1197 .ngpio = S5PV210_GPIO_B_NR,
1198 .label = "GPB",
1199 },
1200 }, {
1201 .chip = {
1202 .base = S5PV210_GPC0(0),
1203 .ngpio = S5PV210_GPIO_C0_NR,
1204 .label = "GPC0",
1205 },
1206 }, {
1207 .chip = {
1208 .base = S5PV210_GPC1(0),
1209 .ngpio = S5PV210_GPIO_C1_NR,
1210 .label = "GPC1",
1211 },
1212 }, {
1213 .chip = {
1214 .base = S5PV210_GPD0(0),
1215 .ngpio = S5PV210_GPIO_D0_NR,
1216 .label = "GPD0",
1217 },
1218 }, {
1219 .chip = {
1220 .base = S5PV210_GPD1(0),
1221 .ngpio = S5PV210_GPIO_D1_NR,
1222 .label = "GPD1",
1223 },
1224 }, {
1225 .chip = {
1226 .base = S5PV210_GPE0(0),
1227 .ngpio = S5PV210_GPIO_E0_NR,
1228 .label = "GPE0",
1229 },
1230 }, {
1231 .chip = {
1232 .base = S5PV210_GPE1(0),
1233 .ngpio = S5PV210_GPIO_E1_NR,
1234 .label = "GPE1",
1235 },
1236 }, {
1237 .chip = {
1238 .base = S5PV210_GPF0(0),
1239 .ngpio = S5PV210_GPIO_F0_NR,
1240 .label = "GPF0",
1241 },
1242 }, {
1243 .chip = {
1244 .base = S5PV210_GPF1(0),
1245 .ngpio = S5PV210_GPIO_F1_NR,
1246 .label = "GPF1",
1247 },
1248 }, {
1249 .chip = {
1250 .base = S5PV210_GPF2(0),
1251 .ngpio = S5PV210_GPIO_F2_NR,
1252 .label = "GPF2",
1253 },
1254 }, {
1255 .chip = {
1256 .base = S5PV210_GPF3(0),
1257 .ngpio = S5PV210_GPIO_F3_NR,
1258 .label = "GPF3",
1259 },
1260 }, {
1261 .chip = {
1262 .base = S5PV210_GPG0(0),
1263 .ngpio = S5PV210_GPIO_G0_NR,
1264 .label = "GPG0",
1265 },
1266 }, {
1267 .chip = {
1268 .base = S5PV210_GPG1(0),
1269 .ngpio = S5PV210_GPIO_G1_NR,
1270 .label = "GPG1",
1271 },
1272 }, {
1273 .chip = {
1274 .base = S5PV210_GPG2(0),
1275 .ngpio = S5PV210_GPIO_G2_NR,
1276 .label = "GPG2",
1277 },
1278 }, {
1279 .chip = {
1280 .base = S5PV210_GPG3(0),
1281 .ngpio = S5PV210_GPIO_G3_NR,
1282 .label = "GPG3",
1283 },
1284 }, {
1285 .chip = {
1286 .base = S5PV210_GPI(0),
1287 .ngpio = S5PV210_GPIO_I_NR,
1288 .label = "GPI",
1289 },
1290 }, {
1291 .chip = {
1292 .base = S5PV210_GPJ0(0),
1293 .ngpio = S5PV210_GPIO_J0_NR,
1294 .label = "GPJ0",
1295 },
1296 }, {
1297 .chip = {
1298 .base = S5PV210_GPJ1(0),
1299 .ngpio = S5PV210_GPIO_J1_NR,
1300 .label = "GPJ1",
1301 },
1302 }, {
1303 .chip = {
1304 .base = S5PV210_GPJ2(0),
1305 .ngpio = S5PV210_GPIO_J2_NR,
1306 .label = "GPJ2",
1307 },
1308 }, {
1309 .chip = {
1310 .base = S5PV210_GPJ3(0),
1311 .ngpio = S5PV210_GPIO_J3_NR,
1312 .label = "GPJ3",
1313 },
1314 }, {
1315 .chip = {
1316 .base = S5PV210_GPJ4(0),
1317 .ngpio = S5PV210_GPIO_J4_NR,
1318 .label = "GPJ4",
1319 },
1320 }, {
1321 .chip = {
1322 .base = S5PV210_MP01(0),
1323 .ngpio = S5PV210_GPIO_MP01_NR,
1324 .label = "MP01",
1325 },
1326 }, {
1327 .chip = {
1328 .base = S5PV210_MP02(0),
1329 .ngpio = S5PV210_GPIO_MP02_NR,
1330 .label = "MP02",
1331 },
1332 }, {
1333 .chip = {
1334 .base = S5PV210_MP03(0),
1335 .ngpio = S5PV210_GPIO_MP03_NR,
1336 .label = "MP03",
1337 },
1338 }, {
1339 .chip = {
1340 .base = S5PV210_MP04(0),
1341 .ngpio = S5PV210_GPIO_MP04_NR,
1342 .label = "MP04",
1343 },
1344 }, {
1345 .chip = {
1346 .base = S5PV210_MP05(0),
1347 .ngpio = S5PV210_GPIO_MP05_NR,
1348 .label = "MP05",
1349 },
1350 }, {
1351 .base = (S5P_VA_GPIO + 0xC00),
1352 .irq_base = IRQ_EINT(0),
1353 .chip = {
1354 .base = S5PV210_GPH0(0),
1355 .ngpio = S5PV210_GPIO_H0_NR,
1356 .label = "GPH0",
1357 .to_irq = samsung_gpiolib_to_irq,
1358 },
1359 }, {
1360 .base = (S5P_VA_GPIO + 0xC20),
1361 .irq_base = IRQ_EINT(8),
1362 .chip = {
1363 .base = S5PV210_GPH1(0),
1364 .ngpio = S5PV210_GPIO_H1_NR,
1365 .label = "GPH1",
1366 .to_irq = samsung_gpiolib_to_irq,
1367 },
1368 }, {
1369 .base = (S5P_VA_GPIO + 0xC40),
1370 .irq_base = IRQ_EINT(16),
1371 .chip = {
1372 .base = S5PV210_GPH2(0),
1373 .ngpio = S5PV210_GPIO_H2_NR,
1374 .label = "GPH2",
1375 .to_irq = samsung_gpiolib_to_irq,
1376 },
1377 }, {
1378 .base = (S5P_VA_GPIO + 0xC60),
1379 .irq_base = IRQ_EINT(24),
1380 .chip = {
1381 .base = S5PV210_GPH3(0),
1382 .ngpio = S5PV210_GPIO_H3_NR,
1383 .label = "GPH3",
1384 .to_irq = samsung_gpiolib_to_irq,
1385 },
1386 },
1387#endif
1388};
1389
1390/* TODO: cleanup soc_is_* */ 1169/* TODO: cleanup soc_is_* */
1391static __init int samsung_gpiolib_init(void) 1170static __init int samsung_gpiolib_init(void)
1392{ 1171{
1393 struct samsung_gpio_chip *chip;
1394 int i, nr_chips;
1395 int group = 0;
1396
1397 /* 1172 /*
1398 * Currently there are two drivers that can provide GPIO support for 1173 * Currently there are two drivers that can provide GPIO support for
1399 * Samsung SoCs. For device tree enabled platforms, the new 1174 * Samsung SoCs. For device tree enabled platforms, the new
@@ -1417,21 +1192,6 @@ static __init int samsung_gpiolib_init(void)
1417 S3C64XX_VA_GPIO); 1192 S3C64XX_VA_GPIO);
1418 samsung_gpiolib_add_4bit2_chips(s3c64xx_gpios_4bit2, 1193 samsung_gpiolib_add_4bit2_chips(s3c64xx_gpios_4bit2,
1419 ARRAY_SIZE(s3c64xx_gpios_4bit2)); 1194 ARRAY_SIZE(s3c64xx_gpios_4bit2));
1420 } else if (soc_is_s5pv210()) {
1421 group = 0;
1422 chip = s5pv210_gpios_4bit;
1423 nr_chips = ARRAY_SIZE(s5pv210_gpios_4bit);
1424
1425 for (i = 0; i < nr_chips; i++, chip++) {
1426 if (!chip->config) {
1427 chip->config = &samsung_gpio_cfgs[3];
1428 chip->group = group++;
1429 }
1430 }
1431 samsung_gpiolib_add_4bit_chips(s5pv210_gpios_4bit, nr_chips, S5P_VA_GPIO);
1432#if defined(CONFIG_CPU_S5PV210) && defined(CONFIG_S5P_GPIO_INT)
1433 s5p_register_gpioint_bank(IRQ_GPIOINT, 0, S5P_GPIOINT_GROUP_MAXNR);
1434#endif
1435 } else { 1195 } else {
1436 WARN(1, "Unknown SoC in gpio-samsung, no GPIOs added\n"); 1196 WARN(1, "Unknown SoC in gpio-samsung, no GPIOs added\n");
1437 return -ENODEV; 1197 return -ENODEV;
diff --git a/drivers/irqchip/irq-versatile-fpga.c b/drivers/irqchip/irq-versatile-fpga.c
index 3ae2bb8d9cf2..ccf58548b161 100644
--- a/drivers/irqchip/irq-versatile-fpga.c
+++ b/drivers/irqchip/irq-versatile-fpga.c
@@ -14,6 +14,8 @@
14#include <asm/exception.h> 14#include <asm/exception.h>
15#include <asm/mach/irq.h> 15#include <asm/mach/irq.h>
16 16
17#include "irqchip.h"
18
17#define IRQ_STATUS 0x00 19#define IRQ_STATUS 0x00
18#define IRQ_RAW_STATUS 0x04 20#define IRQ_RAW_STATUS 0x04
19#define IRQ_ENABLE_SET 0x08 21#define IRQ_ENABLE_SET 0x08
@@ -26,6 +28,8 @@
26#define FIQ_ENABLE_SET 0x28 28#define FIQ_ENABLE_SET 0x28
27#define FIQ_ENABLE_CLEAR 0x2C 29#define FIQ_ENABLE_CLEAR 0x2C
28 30
31#define PIC_ENABLES 0x20 /* set interrupt pass through bits */
32
29/** 33/**
30 * struct fpga_irq_data - irq data container for the FPGA IRQ controller 34 * struct fpga_irq_data - irq data container for the FPGA IRQ controller
31 * @base: memory offset in virtual memory 35 * @base: memory offset in virtual memory
@@ -201,14 +205,26 @@ int __init fpga_irq_of_init(struct device_node *node,
201 205
202 /* Some chips are cascaded from a parent IRQ */ 206 /* Some chips are cascaded from a parent IRQ */
203 parent_irq = irq_of_parse_and_map(node, 0); 207 parent_irq = irq_of_parse_and_map(node, 0);
204 if (!parent_irq) 208 if (!parent_irq) {
209 set_handle_irq(fpga_handle_irq);
205 parent_irq = -1; 210 parent_irq = -1;
211 }
206 212
207 fpga_irq_init(base, node->name, 0, parent_irq, valid_mask, node); 213 fpga_irq_init(base, node->name, 0, parent_irq, valid_mask, node);
208 214
209 writel(clear_mask, base + IRQ_ENABLE_CLEAR); 215 writel(clear_mask, base + IRQ_ENABLE_CLEAR);
210 writel(clear_mask, base + FIQ_ENABLE_CLEAR); 216 writel(clear_mask, base + FIQ_ENABLE_CLEAR);
211 217
218 /*
219 * On Versatile AB/PB, some secondary interrupts have a direct
220 * pass-thru to the primary controller for IRQs 20 and 22-31 which need
221 * to be enabled. See section 3.10 of the Versatile AB user guide.
222 */
223 if (of_device_is_compatible(node, "arm,versatile-sic"))
224 writel(0xffd00000, base + PIC_ENABLES);
225
212 return 0; 226 return 0;
213} 227}
228IRQCHIP_DECLARE(arm_fpga, "arm,versatile-fpga-irq", fpga_irq_of_init);
229IRQCHIP_DECLARE(arm_fpga_sic, "arm,versatile-sic", fpga_irq_of_init);
214#endif 230#endif
diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index cc97c897945a..d1f5fc924c93 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -159,6 +159,16 @@ config PHY_SAMSUNG_USB2
159 for particular PHYs will be enabled based on the SoC type in addition 159 for particular PHYs will be enabled based on the SoC type in addition
160 to this driver. 160 to this driver.
161 161
162config PHY_S5PV210_USB2
163 bool "Support for S5PV210"
164 depends on PHY_SAMSUNG_USB2
165 depends on ARCH_S5PV210
166 help
167 Enable USB PHY support for S5PV210. This option requires that Samsung
168 USB 2.0 PHY driver is enabled and means that support for this
169 particular SoC is compiled in the driver. In case of S5PV210 two phys
170 are available - device and host.
171
162config PHY_EXYNOS4210_USB2 172config PHY_EXYNOS4210_USB2
163 bool 173 bool
164 depends on PHY_SAMSUNG_USB2 174 depends on PHY_SAMSUNG_USB2
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
index 971ad0aac388..ec24e915349b 100644
--- a/drivers/phy/Makefile
+++ b/drivers/phy/Makefile
@@ -21,6 +21,7 @@ phy-exynos-usb2-y += phy-samsung-usb2.o
21phy-exynos-usb2-$(CONFIG_PHY_EXYNOS4210_USB2) += phy-exynos4210-usb2.o 21phy-exynos-usb2-$(CONFIG_PHY_EXYNOS4210_USB2) += phy-exynos4210-usb2.o
22phy-exynos-usb2-$(CONFIG_PHY_EXYNOS4X12_USB2) += phy-exynos4x12-usb2.o 22phy-exynos-usb2-$(CONFIG_PHY_EXYNOS4X12_USB2) += phy-exynos4x12-usb2.o
23phy-exynos-usb2-$(CONFIG_PHY_EXYNOS5250_USB2) += phy-exynos5250-usb2.o 23phy-exynos-usb2-$(CONFIG_PHY_EXYNOS5250_USB2) += phy-exynos5250-usb2.o
24phy-exynos-usb2-$(CONFIG_PHY_S5PV210_USB2) += phy-s5pv210-usb2.o
24obj-$(CONFIG_PHY_EXYNOS5_USBDRD) += phy-exynos5-usbdrd.o 25obj-$(CONFIG_PHY_EXYNOS5_USBDRD) += phy-exynos5-usbdrd.o
25obj-$(CONFIG_PHY_XGENE) += phy-xgene.o 26obj-$(CONFIG_PHY_XGENE) += phy-xgene.o
26obj-$(CONFIG_PHY_QCOM_APQ8064_SATA) += phy-qcom-apq8064-sata.o 27obj-$(CONFIG_PHY_QCOM_APQ8064_SATA) += phy-qcom-apq8064-sata.o
diff --git a/drivers/phy/phy-s5pv210-usb2.c b/drivers/phy/phy-s5pv210-usb2.c
new file mode 100644
index 000000000000..004d320767e4
--- /dev/null
+++ b/drivers/phy/phy-s5pv210-usb2.c
@@ -0,0 +1,187 @@
1/*
2 * Samsung SoC USB 1.1/2.0 PHY driver - S5PV210 support
3 *
4 * Copyright (C) 2013 Samsung Electronics Co., Ltd.
5 * Authors: Kamil Debski <k.debski@samsung.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11
12#include <linux/delay.h>
13#include <linux/io.h>
14#include <linux/phy/phy.h>
15#include "phy-samsung-usb2.h"
16
17/* Exynos USB PHY registers */
18
19/* PHY power control */
20#define S5PV210_UPHYPWR 0x0
21
22#define S5PV210_UPHYPWR_PHY0_SUSPEND BIT(0)
23#define S5PV210_UPHYPWR_PHY0_PWR BIT(3)
24#define S5PV210_UPHYPWR_PHY0_OTG_PWR BIT(4)
25#define S5PV210_UPHYPWR_PHY0 ( \
26 S5PV210_UPHYPWR_PHY0_SUSPEND | \
27 S5PV210_UPHYPWR_PHY0_PWR | \
28 S5PV210_UPHYPWR_PHY0_OTG_PWR)
29
30#define S5PV210_UPHYPWR_PHY1_SUSPEND BIT(6)
31#define S5PV210_UPHYPWR_PHY1_PWR BIT(7)
32#define S5PV210_UPHYPWR_PHY1 ( \
33 S5PV210_UPHYPWR_PHY1_SUSPEND | \
34 S5PV210_UPHYPWR_PHY1_PWR)
35
36/* PHY clock control */
37#define S5PV210_UPHYCLK 0x4
38
39#define S5PV210_UPHYCLK_PHYFSEL_MASK (0x3 << 0)
40#define S5PV210_UPHYCLK_PHYFSEL_48MHZ (0x0 << 0)
41#define S5PV210_UPHYCLK_PHYFSEL_24MHZ (0x3 << 0)
42#define S5PV210_UPHYCLK_PHYFSEL_12MHZ (0x2 << 0)
43
44#define S5PV210_UPHYCLK_PHY0_ID_PULLUP BIT(2)
45#define S5PV210_UPHYCLK_PHY0_COMMON_ON BIT(4)
46#define S5PV210_UPHYCLK_PHY1_COMMON_ON BIT(7)
47
48/* PHY reset control */
49#define S5PV210_UPHYRST 0x8
50
51#define S5PV210_URSTCON_PHY0 BIT(0)
52#define S5PV210_URSTCON_OTG_HLINK BIT(1)
53#define S5PV210_URSTCON_OTG_PHYLINK BIT(2)
54#define S5PV210_URSTCON_PHY1_ALL BIT(3)
55#define S5PV210_URSTCON_HOST_LINK_ALL BIT(4)
56
57/* Isolation, configured in the power management unit */
58#define S5PV210_USB_ISOL_OFFSET 0x680c
59#define S5PV210_USB_ISOL_DEVICE BIT(0)
60#define S5PV210_USB_ISOL_HOST BIT(1)
61
62
63enum s5pv210_phy_id {
64 S5PV210_DEVICE,
65 S5PV210_HOST,
66 S5PV210_NUM_PHYS,
67};
68
69/*
70 * s5pv210_rate_to_clk() converts the supplied clock rate to the value that
71 * can be written to the phy register.
72 */
73static int s5pv210_rate_to_clk(unsigned long rate, u32 *reg)
74{
75 switch (rate) {
76 case 12 * MHZ:
77 *reg = S5PV210_UPHYCLK_PHYFSEL_12MHZ;
78 break;
79 case 24 * MHZ:
80 *reg = S5PV210_UPHYCLK_PHYFSEL_24MHZ;
81 break;
82 case 48 * MHZ:
83 *reg = S5PV210_UPHYCLK_PHYFSEL_48MHZ;
84 break;
85 default:
86 return -EINVAL;
87 }
88
89 return 0;
90}
91
92static void s5pv210_isol(struct samsung_usb2_phy_instance *inst, bool on)
93{
94 struct samsung_usb2_phy_driver *drv = inst->drv;
95 u32 mask;
96
97 switch (inst->cfg->id) {
98 case S5PV210_DEVICE:
99 mask = S5PV210_USB_ISOL_DEVICE;
100 break;
101 case S5PV210_HOST:
102 mask = S5PV210_USB_ISOL_HOST;
103 break;
104 default:
105 return;
106 };
107
108 regmap_update_bits(drv->reg_pmu, S5PV210_USB_ISOL_OFFSET,
109 mask, on ? 0 : mask);
110}
111
112static void s5pv210_phy_pwr(struct samsung_usb2_phy_instance *inst, bool on)
113{
114 struct samsung_usb2_phy_driver *drv = inst->drv;
115 u32 rstbits = 0;
116 u32 phypwr = 0;
117 u32 rst;
118 u32 pwr;
119
120 switch (inst->cfg->id) {
121 case S5PV210_DEVICE:
122 phypwr = S5PV210_UPHYPWR_PHY0;
123 rstbits = S5PV210_URSTCON_PHY0;
124 break;
125 case S5PV210_HOST:
126 phypwr = S5PV210_UPHYPWR_PHY1;
127 rstbits = S5PV210_URSTCON_PHY1_ALL |
128 S5PV210_URSTCON_HOST_LINK_ALL;
129 break;
130 };
131
132 if (on) {
133 writel(drv->ref_reg_val, drv->reg_phy + S5PV210_UPHYCLK);
134
135 pwr = readl(drv->reg_phy + S5PV210_UPHYPWR);
136 pwr &= ~phypwr;
137 writel(pwr, drv->reg_phy + S5PV210_UPHYPWR);
138
139 rst = readl(drv->reg_phy + S5PV210_UPHYRST);
140 rst |= rstbits;
141 writel(rst, drv->reg_phy + S5PV210_UPHYRST);
142 udelay(10);
143 rst &= ~rstbits;
144 writel(rst, drv->reg_phy + S5PV210_UPHYRST);
145 } else {
146 pwr = readl(drv->reg_phy + S5PV210_UPHYPWR);
147 pwr |= phypwr;
148 writel(pwr, drv->reg_phy + S5PV210_UPHYPWR);
149 }
150}
151
152static int s5pv210_power_on(struct samsung_usb2_phy_instance *inst)
153{
154 s5pv210_isol(inst, 0);
155 s5pv210_phy_pwr(inst, 1);
156
157 return 0;
158}
159
160static int s5pv210_power_off(struct samsung_usb2_phy_instance *inst)
161{
162 s5pv210_phy_pwr(inst, 0);
163 s5pv210_isol(inst, 1);
164
165 return 0;
166}
167
168static const struct samsung_usb2_common_phy s5pv210_phys[S5PV210_NUM_PHYS] = {
169 [S5PV210_DEVICE] = {
170 .label = "device",
171 .id = S5PV210_DEVICE,
172 .power_on = s5pv210_power_on,
173 .power_off = s5pv210_power_off,
174 },
175 [S5PV210_HOST] = {
176 .label = "host",
177 .id = S5PV210_HOST,
178 .power_on = s5pv210_power_on,
179 .power_off = s5pv210_power_off,
180 },
181};
182
183const struct samsung_usb2_phy_config s5pv210_usb2_phy_config = {
184 .num_phys = ARRAY_SIZE(s5pv210_phys),
185 .phys = s5pv210_phys,
186 .rate_to_clk = s5pv210_rate_to_clk,
187};
diff --git a/drivers/phy/phy-samsung-usb2.c b/drivers/phy/phy-samsung-usb2.c
index ae30640a411d..3732ca25e09f 100644
--- a/drivers/phy/phy-samsung-usb2.c
+++ b/drivers/phy/phy-samsung-usb2.c
@@ -111,6 +111,12 @@ static const struct of_device_id samsung_usb2_phy_of_match[] = {
111 .data = &exynos5250_usb2_phy_config, 111 .data = &exynos5250_usb2_phy_config,
112 }, 112 },
113#endif 113#endif
114#ifdef CONFIG_PHY_S5PV210_USB2
115 {
116 .compatible = "samsung,s5pv210-usb2-phy",
117 .data = &s5pv210_usb2_phy_config,
118 },
119#endif
114 { }, 120 { },
115}; 121};
116MODULE_DEVICE_TABLE(of, samsung_usb2_phy_of_match); 122MODULE_DEVICE_TABLE(of, samsung_usb2_phy_of_match);
diff --git a/drivers/phy/phy-samsung-usb2.h b/drivers/phy/phy-samsung-usb2.h
index b03da0ef39ac..44bead9b8f34 100644
--- a/drivers/phy/phy-samsung-usb2.h
+++ b/drivers/phy/phy-samsung-usb2.h
@@ -67,4 +67,5 @@ extern const struct samsung_usb2_phy_config exynos3250_usb2_phy_config;
67extern const struct samsung_usb2_phy_config exynos4210_usb2_phy_config; 67extern const struct samsung_usb2_phy_config exynos4210_usb2_phy_config;
68extern const struct samsung_usb2_phy_config exynos4x12_usb2_phy_config; 68extern const struct samsung_usb2_phy_config exynos4x12_usb2_phy_config;
69extern const struct samsung_usb2_phy_config exynos5250_usb2_phy_config; 69extern const struct samsung_usb2_phy_config exynos5250_usb2_phy_config;
70extern const struct samsung_usb2_phy_config s5pv210_usb2_phy_config;
70#endif 71#endif
diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig
index f2ac54df496f..ca41523bbebf 100644
--- a/drivers/power/reset/Kconfig
+++ b/drivers/power/reset/Kconfig
@@ -39,6 +39,12 @@ config POWER_RESET_GPIO
39 If your board needs a GPIO high/low to power down, say Y and 39 If your board needs a GPIO high/low to power down, say Y and
40 create a binding in your devicetree. 40 create a binding in your devicetree.
41 41
42config POWER_RESET_HISI
43 bool "Hisilicon power-off driver"
44 depends on POWER_RESET && ARCH_HISI
45 help
46 Reboot support for Hisilicon boards.
47
42config POWER_RESET_MSM 48config POWER_RESET_MSM
43 bool "Qualcomm MSM power-off driver" 49 bool "Qualcomm MSM power-off driver"
44 depends on POWER_RESET && ARCH_QCOM 50 depends on POWER_RESET && ARCH_QCOM
diff --git a/drivers/power/reset/Makefile b/drivers/power/reset/Makefile
index 7379818ca69d..a42e70edd037 100644
--- a/drivers/power/reset/Makefile
+++ b/drivers/power/reset/Makefile
@@ -2,6 +2,7 @@ obj-$(CONFIG_POWER_RESET_AS3722) += as3722-poweroff.o
2obj-$(CONFIG_POWER_RESET_AXXIA) += axxia-reset.o 2obj-$(CONFIG_POWER_RESET_AXXIA) += axxia-reset.o
3obj-$(CONFIG_POWER_RESET_BRCMSTB) += brcmstb-reboot.o 3obj-$(CONFIG_POWER_RESET_BRCMSTB) += brcmstb-reboot.o
4obj-$(CONFIG_POWER_RESET_GPIO) += gpio-poweroff.o 4obj-$(CONFIG_POWER_RESET_GPIO) += gpio-poweroff.o
5obj-$(CONFIG_POWER_RESET_HISI) += hisi-reboot.o
5obj-$(CONFIG_POWER_RESET_MSM) += msm-poweroff.o 6obj-$(CONFIG_POWER_RESET_MSM) += msm-poweroff.o
6obj-$(CONFIG_POWER_RESET_QNAP) += qnap-poweroff.o 7obj-$(CONFIG_POWER_RESET_QNAP) += qnap-poweroff.o
7obj-$(CONFIG_POWER_RESET_RESTART) += restart-poweroff.o 8obj-$(CONFIG_POWER_RESET_RESTART) += restart-poweroff.o
diff --git a/drivers/power/reset/hisi-reboot.c b/drivers/power/reset/hisi-reboot.c
new file mode 100644
index 000000000000..0c91d0231d36
--- /dev/null
+++ b/drivers/power/reset/hisi-reboot.c
@@ -0,0 +1,67 @@
1/*
2 * Hisilicon SoC reset code
3 *
4 * Copyright (c) 2014 Hisilicon Ltd.
5 * Copyright (c) 2014 Linaro Ltd.
6 *
7 * Author: Haojian Zhuang <haojian.zhuang@linaro.org>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 */
13
14#include <linux/delay.h>
15#include <linux/io.h>
16#include <linux/module.h>
17#include <linux/of_address.h>
18#include <linux/platform_device.h>
19#include <linux/reboot.h>
20
21#include <asm/proc-fns.h>
22#include <asm/system_misc.h>
23
24static void __iomem *base;
25static u32 reboot_offset;
26
27static void hisi_restart(enum reboot_mode mode, const char *cmd)
28{
29 writel_relaxed(0xdeadbeef, base + reboot_offset);
30
31 while (1)
32 cpu_do_idle();
33}
34
35static int hisi_reboot_probe(struct platform_device *pdev)
36{
37 struct device_node *np = pdev->dev.of_node;
38
39 base = of_iomap(np, 0);
40 if (!base) {
41 WARN(1, "failed to map base address");
42 return -ENODEV;
43 }
44
45 if (of_property_read_u32(np, "reboot-offset", &reboot_offset) < 0) {
46 pr_err("failed to find reboot-offset property\n");
47 return -EINVAL;
48 }
49
50 arm_pm_restart = hisi_restart;
51
52 return 0;
53}
54
55static struct of_device_id hisi_reboot_of_match[] = {
56 { .compatible = "hisilicon,sysctrl" },
57 {}
58};
59
60static struct platform_driver hisi_reboot_driver = {
61 .probe = hisi_reboot_probe,
62 .driver = {
63 .name = "hisi-reboot",
64 .of_match_table = hisi_reboot_of_match,
65 },
66};
67module_platform_driver(hisi_reboot_driver);
diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c
index 4aff02d6712e..c78f43a481ce 100644
--- a/drivers/tty/serial/samsung.c
+++ b/drivers/tty/serial/samsung.c
@@ -47,10 +47,6 @@
47 47
48#include <asm/irq.h> 48#include <asm/irq.h>
49 49
50#ifdef CONFIG_SAMSUNG_CLOCK
51#include <plat/clock.h>
52#endif
53
54#include "samsung.h" 50#include "samsung.h"
55 51
56#if defined(CONFIG_SERIAL_SAMSUNG_DEBUG) && \ 52#if defined(CONFIG_SERIAL_SAMSUNG_DEBUG) && \