aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/clock/marvell,pxa910.txt21
-rw-r--r--drivers/clk/mmp/Makefile2
-rw-r--r--drivers/clk/mmp/clk-of-pxa910.c301
-rw-r--r--include/dt-bindings/clock/marvell,pxa910.h54
4 files changed, 377 insertions, 1 deletions
diff --git a/Documentation/devicetree/bindings/clock/marvell,pxa910.txt b/Documentation/devicetree/bindings/clock/marvell,pxa910.txt
new file mode 100644
index 000000000000..d9f41f3c03a0
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/marvell,pxa910.txt
@@ -0,0 +1,21 @@
1* Marvell PXA910 Clock Controller
2
3The PXA910 clock subsystem generates and supplies clock to various
4controllers within the PXA910 SoC.
5
6Required Properties:
7
8- compatible: should be one of the following.
9 - "marvell,pxa910-clock" - controller compatible with PXA910 SoC.
10
11- reg: physical base address of the clock subsystem and length of memory mapped
12 region. There are 4 places in SOC has clock control logic:
13 "mpmu", "apmu", "apbc", "apbcp". So four reg spaces need to be defined.
14
15- #clock-cells: should be 1.
16- #reset-cells: should be 1.
17
18Each clock is assigned an identifier and client nodes use this identifier
19to specify the clock which they consume.
20
21All these identifier could be found in <dt-bindings/clock/marvell-pxa910.h>.
diff --git a/drivers/clk/mmp/Makefile b/drivers/clk/mmp/Makefile
index 733acc7aa484..947cd74a82a7 100644
--- a/drivers/clk/mmp/Makefile
+++ b/drivers/clk/mmp/Makefile
@@ -6,7 +6,7 @@ obj-y += clk-apbc.o clk-apmu.o clk-frac.o clk-mix.o clk-gate.o clk.o
6 6
7obj-$(CONFIG_RESET_CONTROLLER) += reset.o 7obj-$(CONFIG_RESET_CONTROLLER) += reset.o
8 8
9obj-$(CONFIG_MACH_MMP_DT) += clk-of-pxa168.o 9obj-$(CONFIG_MACH_MMP_DT) += clk-of-pxa168.o clk-of-pxa910.o
10 10
11obj-$(CONFIG_CPU_PXA168) += clk-pxa168.o 11obj-$(CONFIG_CPU_PXA168) += clk-pxa168.o
12obj-$(CONFIG_CPU_PXA910) += clk-pxa910.o 12obj-$(CONFIG_CPU_PXA910) += clk-pxa910.o
diff --git a/drivers/clk/mmp/clk-of-pxa910.c b/drivers/clk/mmp/clk-of-pxa910.c
new file mode 100644
index 000000000000..5e3c80dad336
--- /dev/null
+++ b/drivers/clk/mmp/clk-of-pxa910.c
@@ -0,0 +1,301 @@
1/*
2 * pxa910 clock framework source file
3 *
4 * Copyright (C) 2012 Marvell
5 * Chao Xie <xiechao.mail@gmail.com>
6 *
7 * This file is licensed under the terms of the GNU General Public
8 * License version 2. This program is licensed "as is" without any
9 * warranty of any kind, whether express or implied.
10 */
11
12#include <linux/module.h>
13#include <linux/kernel.h>
14#include <linux/spinlock.h>
15#include <linux/io.h>
16#include <linux/delay.h>
17#include <linux/err.h>
18#include <linux/of_address.h>
19
20#include <dt-bindings/clock/marvell,pxa910.h>
21
22#include "clk.h"
23#include "reset.h"
24
25#define APBC_RTC 0x28
26#define APBC_TWSI0 0x2c
27#define APBC_KPC 0x18
28#define APBC_UART0 0x0
29#define APBC_UART1 0x4
30#define APBC_GPIO 0x8
31#define APBC_PWM0 0xc
32#define APBC_PWM1 0x10
33#define APBC_PWM2 0x14
34#define APBC_PWM3 0x18
35#define APBC_SSP0 0x1c
36#define APBC_SSP1 0x20
37#define APBC_SSP2 0x4c
38#define APBCP_TWSI1 0x28
39#define APBCP_UART2 0x1c
40#define APMU_SDH0 0x54
41#define APMU_SDH1 0x58
42#define APMU_USB 0x5c
43#define APMU_DISP0 0x4c
44#define APMU_CCIC0 0x50
45#define APMU_DFC 0x60
46#define MPMU_UART_PLL 0x14
47
48struct pxa910_clk_unit {
49 struct mmp_clk_unit unit;
50 void __iomem *mpmu_base;
51 void __iomem *apmu_base;
52 void __iomem *apbc_base;
53 void __iomem *apbcp_base;
54};
55
56static struct mmp_param_fixed_rate_clk fixed_rate_clks[] = {
57 {PXA910_CLK_CLK32, "clk32", NULL, CLK_IS_ROOT, 32768},
58 {PXA910_CLK_VCTCXO, "vctcxo", NULL, CLK_IS_ROOT, 26000000},
59 {PXA910_CLK_PLL1, "pll1", NULL, CLK_IS_ROOT, 624000000},
60};
61
62static struct mmp_param_fixed_factor_clk fixed_factor_clks[] = {
63 {PXA910_CLK_PLL1_2, "pll1_2", "pll1", 1, 2, 0},
64 {PXA910_CLK_PLL1_4, "pll1_4", "pll1_2", 1, 2, 0},
65 {PXA910_CLK_PLL1_8, "pll1_8", "pll1_4", 1, 2, 0},
66 {PXA910_CLK_PLL1_16, "pll1_16", "pll1_8", 1, 2, 0},
67 {PXA910_CLK_PLL1_6, "pll1_6", "pll1_2", 1, 3, 0},
68 {PXA910_CLK_PLL1_12, "pll1_12", "pll1_6", 1, 2, 0},
69 {PXA910_CLK_PLL1_24, "pll1_24", "pll1_12", 1, 2, 0},
70 {PXA910_CLK_PLL1_48, "pll1_48", "pll1_24", 1, 2, 0},
71 {PXA910_CLK_PLL1_96, "pll1_96", "pll1_48", 1, 2, 0},
72 {PXA910_CLK_PLL1_13, "pll1_13", "pll1", 1, 13, 0},
73 {PXA910_CLK_PLL1_13_1_5, "pll1_13_1_5", "pll1_13", 2, 3, 0},
74 {PXA910_CLK_PLL1_2_1_5, "pll1_2_1_5", "pll1_2", 2, 3, 0},
75 {PXA910_CLK_PLL1_3_16, "pll1_3_16", "pll1", 3, 16, 0},
76};
77
78static struct mmp_clk_factor_masks uart_factor_masks = {
79 .factor = 2,
80 .num_mask = 0x1fff,
81 .den_mask = 0x1fff,
82 .num_shift = 16,
83 .den_shift = 0,
84};
85
86static struct mmp_clk_factor_tbl uart_factor_tbl[] = {
87 {.num = 8125, .den = 1536}, /*14.745MHZ */
88};
89
90static void pxa910_pll_init(struct pxa910_clk_unit *pxa_unit)
91{
92 struct clk *clk;
93 struct mmp_clk_unit *unit = &pxa_unit->unit;
94
95 mmp_register_fixed_rate_clks(unit, fixed_rate_clks,
96 ARRAY_SIZE(fixed_rate_clks));
97
98 mmp_register_fixed_factor_clks(unit, fixed_factor_clks,
99 ARRAY_SIZE(fixed_factor_clks));
100
101 clk = mmp_clk_register_factor("uart_pll", "pll1_4",
102 CLK_SET_RATE_PARENT,
103 pxa_unit->mpmu_base + MPMU_UART_PLL,
104 &uart_factor_masks, uart_factor_tbl,
105 ARRAY_SIZE(uart_factor_tbl), NULL);
106 mmp_clk_add(unit, PXA910_CLK_UART_PLL, clk);
107}
108
109static DEFINE_SPINLOCK(uart0_lock);
110static DEFINE_SPINLOCK(uart1_lock);
111static DEFINE_SPINLOCK(uart2_lock);
112static const char *uart_parent_names[] = {"pll1_3_16", "uart_pll"};
113
114static DEFINE_SPINLOCK(ssp0_lock);
115static DEFINE_SPINLOCK(ssp1_lock);
116static const char *ssp_parent_names[] = {"pll1_96", "pll1_48", "pll1_24", "pll1_12"};
117
118static DEFINE_SPINLOCK(reset_lock);
119
120static struct mmp_param_mux_clk apbc_mux_clks[] = {
121 {0, "uart0_mux", uart_parent_names, ARRAY_SIZE(uart_parent_names), CLK_SET_RATE_PARENT, APBC_UART0, 4, 3, 0, &uart0_lock},
122 {0, "uart1_mux", uart_parent_names, ARRAY_SIZE(uart_parent_names), CLK_SET_RATE_PARENT, APBC_UART1, 4, 3, 0, &uart1_lock},
123 {0, "ssp0_mux", ssp_parent_names, ARRAY_SIZE(ssp_parent_names), CLK_SET_RATE_PARENT, APBC_SSP0, 4, 3, 0, &ssp0_lock},
124 {0, "ssp1_mux", ssp_parent_names, ARRAY_SIZE(ssp_parent_names), CLK_SET_RATE_PARENT, APBC_SSP1, 4, 3, 0, &ssp1_lock},
125};
126
127static struct mmp_param_mux_clk apbcp_mux_clks[] = {
128 {0, "uart2_mux", uart_parent_names, ARRAY_SIZE(uart_parent_names), CLK_SET_RATE_PARENT, APBCP_UART2, 4, 3, 0, &uart2_lock},
129};
130
131static struct mmp_param_gate_clk apbc_gate_clks[] = {
132 {PXA910_CLK_TWSI0, "twsi0_clk", "pll1_13_1_5", CLK_SET_RATE_PARENT, APBC_TWSI0, 0x3, 0x3, 0x0, 0, &reset_lock},
133 {PXA910_CLK_GPIO, "gpio_clk", "vctcxo", CLK_SET_RATE_PARENT, APBC_GPIO, 0x3, 0x3, 0x0, 0, &reset_lock},
134 {PXA910_CLK_KPC, "kpc_clk", "clk32", CLK_SET_RATE_PARENT, APBC_KPC, 0x3, 0x3, 0x0, MMP_CLK_GATE_NEED_DELAY, NULL},
135 {PXA910_CLK_RTC, "rtc_clk", "clk32", CLK_SET_RATE_PARENT, APBC_RTC, 0x83, 0x83, 0x0, MMP_CLK_GATE_NEED_DELAY, NULL},
136 {PXA910_CLK_PWM0, "pwm0_clk", "pll1_48", CLK_SET_RATE_PARENT, APBC_PWM0, 0x3, 0x3, 0x0, 0, &reset_lock},
137 {PXA910_CLK_PWM1, "pwm1_clk", "pll1_48", CLK_SET_RATE_PARENT, APBC_PWM1, 0x3, 0x3, 0x0, 0, &reset_lock},
138 {PXA910_CLK_PWM2, "pwm2_clk", "pll1_48", CLK_SET_RATE_PARENT, APBC_PWM2, 0x3, 0x3, 0x0, 0, &reset_lock},
139 {PXA910_CLK_PWM3, "pwm3_clk", "pll1_48", CLK_SET_RATE_PARENT, APBC_PWM3, 0x3, 0x3, 0x0, 0, &reset_lock},
140 /* The gate clocks has mux parent. */
141 {PXA910_CLK_UART0, "uart0_clk", "uart0_mux", CLK_SET_RATE_PARENT, APBC_UART0, 0x3, 0x3, 0x0, 0, &uart0_lock},
142 {PXA910_CLK_UART1, "uart1_clk", "uart1_mux", CLK_SET_RATE_PARENT, APBC_UART1, 0x3, 0x3, 0x0, 0, &uart1_lock},
143 {PXA910_CLK_SSP0, "ssp0_clk", "ssp0_mux", CLK_SET_RATE_PARENT, APBC_SSP0, 0x3, 0x3, 0x0, 0, &ssp0_lock},
144 {PXA910_CLK_SSP1, "ssp1_clk", "ssp1_mux", CLK_SET_RATE_PARENT, APBC_SSP1, 0x3, 0x3, 0x0, 0, &ssp1_lock},
145};
146
147static struct mmp_param_gate_clk apbcp_gate_clks[] = {
148 {PXA910_CLK_TWSI1, "twsi1_clk", "pll1_13_1_5", CLK_SET_RATE_PARENT, APBCP_TWSI1, 0x3, 0x3, 0x0, 0, &reset_lock},
149 /* The gate clocks has mux parent. */
150 {PXA910_CLK_UART2, "uart2_clk", "uart2_mux", CLK_SET_RATE_PARENT, APBCP_UART2, 0x3, 0x3, 0x0, 0, &uart2_lock},
151};
152
153static void pxa910_apb_periph_clk_init(struct pxa910_clk_unit *pxa_unit)
154{
155 struct mmp_clk_unit *unit = &pxa_unit->unit;
156
157 mmp_register_mux_clks(unit, apbc_mux_clks, pxa_unit->apbc_base,
158 ARRAY_SIZE(apbc_mux_clks));
159
160 mmp_register_mux_clks(unit, apbcp_mux_clks, pxa_unit->apbcp_base,
161 ARRAY_SIZE(apbcp_mux_clks));
162
163 mmp_register_gate_clks(unit, apbc_gate_clks, pxa_unit->apbc_base,
164 ARRAY_SIZE(apbc_gate_clks));
165
166 mmp_register_gate_clks(unit, apbcp_gate_clks, pxa_unit->apbcp_base,
167 ARRAY_SIZE(apbcp_gate_clks));
168}
169
170static DEFINE_SPINLOCK(sdh0_lock);
171static DEFINE_SPINLOCK(sdh1_lock);
172static const char *sdh_parent_names[] = {"pll1_12", "pll1_13"};
173
174static DEFINE_SPINLOCK(usb_lock);
175
176static DEFINE_SPINLOCK(disp0_lock);
177static const char *disp_parent_names[] = {"pll1_2", "pll1_12"};
178
179static DEFINE_SPINLOCK(ccic0_lock);
180static const char *ccic_parent_names[] = {"pll1_2", "pll1_12"};
181static const char *ccic_phy_parent_names[] = {"pll1_6", "pll1_12"};
182
183static struct mmp_param_mux_clk apmu_mux_clks[] = {
184 {0, "sdh0_mux", sdh_parent_names, ARRAY_SIZE(sdh_parent_names), CLK_SET_RATE_PARENT, APMU_SDH0, 6, 1, 0, &sdh0_lock},
185 {0, "sdh1_mux", sdh_parent_names, ARRAY_SIZE(sdh_parent_names), CLK_SET_RATE_PARENT, APMU_SDH1, 6, 1, 0, &sdh1_lock},
186 {0, "disp0_mux", disp_parent_names, ARRAY_SIZE(disp_parent_names), CLK_SET_RATE_PARENT, APMU_DISP0, 6, 1, 0, &disp0_lock},
187 {0, "ccic0_mux", ccic_parent_names, ARRAY_SIZE(ccic_parent_names), CLK_SET_RATE_PARENT, APMU_CCIC0, 6, 1, 0, &ccic0_lock},
188 {0, "ccic0_phy_mux", ccic_phy_parent_names, ARRAY_SIZE(ccic_phy_parent_names), CLK_SET_RATE_PARENT, APMU_CCIC0, 7, 1, 0, &ccic0_lock},
189};
190
191static struct mmp_param_div_clk apmu_div_clks[] = {
192 {0, "ccic0_sphy_div", "ccic0_mux", CLK_SET_RATE_PARENT, APMU_CCIC0, 10, 5, 0, &ccic0_lock},
193};
194
195static struct mmp_param_gate_clk apmu_gate_clks[] = {
196 {PXA910_CLK_DFC, "dfc_clk", "pll1_4", CLK_SET_RATE_PARENT, APMU_DFC, 0x19b, 0x19b, 0x0, 0, NULL},
197 {PXA910_CLK_USB, "usb_clk", "usb_pll", 0, APMU_USB, 0x9, 0x9, 0x0, 0, &usb_lock},
198 {PXA910_CLK_SPH, "sph_clk", "usb_pll", 0, APMU_USB, 0x12, 0x12, 0x0, 0, &usb_lock},
199 /* The gate clocks has mux parent. */
200 {PXA910_CLK_SDH0, "sdh0_clk", "sdh0_mux", CLK_SET_RATE_PARENT, APMU_SDH0, 0x1b, 0x1b, 0x0, 0, &sdh0_lock},
201 {PXA910_CLK_SDH1, "sdh1_clk", "sdh1_mux", CLK_SET_RATE_PARENT, APMU_SDH1, 0x1b, 0x1b, 0x0, 0, &sdh1_lock},
202 {PXA910_CLK_DISP0, "disp0_clk", "disp0_mux", CLK_SET_RATE_PARENT, APMU_DISP0, 0x1b, 0x1b, 0x0, 0, &disp0_lock},
203 {PXA910_CLK_CCIC0, "ccic0_clk", "ccic0_mux", CLK_SET_RATE_PARENT, APMU_CCIC0, 0x1b, 0x1b, 0x0, 0, &ccic0_lock},
204 {PXA910_CLK_CCIC0_PHY, "ccic0_phy_clk", "ccic0_phy_mux", CLK_SET_RATE_PARENT, APMU_CCIC0, 0x24, 0x24, 0x0, 0, &ccic0_lock},
205 {PXA910_CLK_CCIC0_SPHY, "ccic0_sphy_clk", "ccic0_sphy_div", CLK_SET_RATE_PARENT, APMU_CCIC0, 0x300, 0x300, 0x0, 0, &ccic0_lock},
206};
207
208static void pxa910_axi_periph_clk_init(struct pxa910_clk_unit *pxa_unit)
209{
210 struct mmp_clk_unit *unit = &pxa_unit->unit;
211
212 mmp_register_mux_clks(unit, apmu_mux_clks, pxa_unit->apmu_base,
213 ARRAY_SIZE(apmu_mux_clks));
214
215 mmp_register_div_clks(unit, apmu_div_clks, pxa_unit->apmu_base,
216 ARRAY_SIZE(apmu_div_clks));
217
218 mmp_register_gate_clks(unit, apmu_gate_clks, pxa_unit->apmu_base,
219 ARRAY_SIZE(apmu_gate_clks));
220}
221
222static void pxa910_clk_reset_init(struct device_node *np,
223 struct pxa910_clk_unit *pxa_unit)
224{
225 struct mmp_clk_reset_cell *cells;
226 int i, base, nr_resets_apbc, nr_resets_apbcp, nr_resets;
227
228 nr_resets_apbc = ARRAY_SIZE(apbc_gate_clks);
229 nr_resets_apbcp = ARRAY_SIZE(apbcp_gate_clks);
230 nr_resets = nr_resets_apbc + nr_resets_apbcp;
231 cells = kcalloc(nr_resets, sizeof(*cells), GFP_KERNEL);
232 if (!cells)
233 return;
234
235 base = 0;
236 for (i = 0; i < nr_resets_apbc; i++) {
237 cells[base + i].clk_id = apbc_gate_clks[i].id;
238 cells[base + i].reg =
239 pxa_unit->apbc_base + apbc_gate_clks[i].offset;
240 cells[base + i].flags = 0;
241 cells[base + i].lock = apbc_gate_clks[i].lock;
242 cells[base + i].bits = 0x4;
243 }
244
245 base = nr_resets_apbc;
246 for (i = 0; i < nr_resets_apbcp; i++) {
247 cells[base + i].clk_id = apbcp_gate_clks[i].id;
248 cells[base + i].reg =
249 pxa_unit->apbc_base + apbc_gate_clks[i].offset;
250 cells[base + i].flags = 0;
251 cells[base + i].lock = apbc_gate_clks[i].lock;
252 cells[base + i].bits = 0x4;
253 }
254
255 mmp_clk_reset_register(np, cells, nr_resets);
256}
257
258static void __init pxa910_clk_init(struct device_node *np)
259{
260 struct pxa910_clk_unit *pxa_unit;
261
262 pxa_unit = kzalloc(sizeof(*pxa_unit), GFP_KERNEL);
263 if (!pxa_unit)
264 return;
265
266 pxa_unit->mpmu_base = of_iomap(np, 0);
267 if (!pxa_unit->mpmu_base) {
268 pr_err("failed to map mpmu registers\n");
269 return;
270 }
271
272 pxa_unit->apmu_base = of_iomap(np, 1);
273 if (!pxa_unit->mpmu_base) {
274 pr_err("failed to map apmu registers\n");
275 return;
276 }
277
278 pxa_unit->apbc_base = of_iomap(np, 2);
279 if (!pxa_unit->apbc_base) {
280 pr_err("failed to map apbc registers\n");
281 return;
282 }
283
284 pxa_unit->apbcp_base = of_iomap(np, 3);
285 if (!pxa_unit->mpmu_base) {
286 pr_err("failed to map apbcp registers\n");
287 return;
288 }
289
290 mmp_clk_init(np, &pxa_unit->unit, PXA910_NR_CLKS);
291
292 pxa910_pll_init(pxa_unit);
293
294 pxa910_apb_periph_clk_init(pxa_unit);
295
296 pxa910_axi_periph_clk_init(pxa_unit);
297
298 pxa910_clk_reset_init(np, pxa_unit);
299}
300
301CLK_OF_DECLARE(pxa910_clk, "marvell,pxa910-clock", pxa910_clk_init);
diff --git a/include/dt-bindings/clock/marvell,pxa910.h b/include/dt-bindings/clock/marvell,pxa910.h
new file mode 100644
index 000000000000..719cffb2bea2
--- /dev/null
+++ b/include/dt-bindings/clock/marvell,pxa910.h
@@ -0,0 +1,54 @@
1#ifndef __DTS_MARVELL_PXA910_CLOCK_H
2#define __DTS_MARVELL_PXA910_CLOCK_H
3
4/* fixed clocks and plls */
5#define PXA910_CLK_CLK32 1
6#define PXA910_CLK_VCTCXO 2
7#define PXA910_CLK_PLL1 3
8#define PXA910_CLK_PLL1_2 8
9#define PXA910_CLK_PLL1_4 9
10#define PXA910_CLK_PLL1_8 10
11#define PXA910_CLK_PLL1_16 11
12#define PXA910_CLK_PLL1_6 12
13#define PXA910_CLK_PLL1_12 13
14#define PXA910_CLK_PLL1_24 14
15#define PXA910_CLK_PLL1_48 15
16#define PXA910_CLK_PLL1_96 16
17#define PXA910_CLK_PLL1_13 17
18#define PXA910_CLK_PLL1_13_1_5 18
19#define PXA910_CLK_PLL1_2_1_5 19
20#define PXA910_CLK_PLL1_3_16 20
21#define PXA910_CLK_UART_PLL 27
22
23/* apb periphrals */
24#define PXA910_CLK_TWSI0 60
25#define PXA910_CLK_TWSI1 61
26#define PXA910_CLK_TWSI2 62
27#define PXA910_CLK_TWSI3 63
28#define PXA910_CLK_GPIO 64
29#define PXA910_CLK_KPC 65
30#define PXA910_CLK_RTC 66
31#define PXA910_CLK_PWM0 67
32#define PXA910_CLK_PWM1 68
33#define PXA910_CLK_PWM2 69
34#define PXA910_CLK_PWM3 70
35#define PXA910_CLK_UART0 71
36#define PXA910_CLK_UART1 72
37#define PXA910_CLK_UART2 73
38#define PXA910_CLK_SSP0 74
39#define PXA910_CLK_SSP1 75
40
41/* axi periphrals */
42#define PXA910_CLK_DFC 100
43#define PXA910_CLK_SDH0 101
44#define PXA910_CLK_SDH1 102
45#define PXA910_CLK_SDH2 103
46#define PXA910_CLK_USB 104
47#define PXA910_CLK_SPH 105
48#define PXA910_CLK_DISP0 106
49#define PXA910_CLK_CCIC0 107
50#define PXA910_CLK_CCIC0_PHY 108
51#define PXA910_CLK_CCIC0_SPHY 109
52
53#define PXA910_NR_CLKS 200
54#endif