diff options
author | Paul Cercueil <paul@crapouillou.net> | 2018-08-23 09:17:44 -0400 |
---|---|---|
committer | Stephen Boyd <sboyd@kernel.org> | 2018-10-16 18:19:48 -0400 |
commit | 226dfa4726ebb102479d668e01160a1dc77485e8 (patch) | |
tree | 8863583260db165daa7597ee12313fa7ce064e07 /drivers/clk/ingenic | |
parent | 2fdecde7752be5696c0ae301a0d1b1884081a0f1 (diff) |
clk: Add Ingenic jz4725b CGU driver
Add support for the clocks provided by the CGU in the Ingenic JZ4725B
SoC.
Signed-off-by: Paul Cercueil <paul@crapouillou.net>
Signed-off-by: Stephen Boyd <sboyd@kernel.org>
Diffstat (limited to 'drivers/clk/ingenic')
-rw-r--r-- | drivers/clk/ingenic/Kconfig | 10 | ||||
-rw-r--r-- | drivers/clk/ingenic/Makefile | 1 | ||||
-rw-r--r-- | drivers/clk/ingenic/jz4725b-cgu.c | 225 |
3 files changed, 236 insertions, 0 deletions
diff --git a/drivers/clk/ingenic/Kconfig b/drivers/clk/ingenic/Kconfig index 2445437f8286..34dc0da79c39 100644 --- a/drivers/clk/ingenic/Kconfig +++ b/drivers/clk/ingenic/Kconfig | |||
@@ -14,6 +14,16 @@ config INGENIC_CGU_JZ4740 | |||
14 | 14 | ||
15 | If building for a JZ4740 SoC, you want to say Y here. | 15 | If building for a JZ4740 SoC, you want to say Y here. |
16 | 16 | ||
17 | config INGENIC_CGU_JZ4725B | ||
18 | bool "Ingenic JZ4725B CGU driver" | ||
19 | default MACH_JZ4725B | ||
20 | select INGENIC_CGU_COMMON | ||
21 | help | ||
22 | Support the clocks provided by the CGU hardware on Ingenic JZ4725B | ||
23 | and compatible SoCs. | ||
24 | |||
25 | If building for a JZ4725B SoC, you want to say Y here. | ||
26 | |||
17 | config INGENIC_CGU_JZ4770 | 27 | config INGENIC_CGU_JZ4770 |
18 | bool "Ingenic JZ4770 CGU driver" | 28 | bool "Ingenic JZ4770 CGU driver" |
19 | default MACH_JZ4770 | 29 | default MACH_JZ4770 |
diff --git a/drivers/clk/ingenic/Makefile b/drivers/clk/ingenic/Makefile index 8b8dc79c7ce6..00a79b2fba10 100644 --- a/drivers/clk/ingenic/Makefile +++ b/drivers/clk/ingenic/Makefile | |||
@@ -1,4 +1,5 @@ | |||
1 | obj-$(CONFIG_INGENIC_CGU_COMMON) += cgu.o | 1 | obj-$(CONFIG_INGENIC_CGU_COMMON) += cgu.o |
2 | obj-$(CONFIG_INGENIC_CGU_JZ4740) += jz4740-cgu.o | 2 | obj-$(CONFIG_INGENIC_CGU_JZ4740) += jz4740-cgu.o |
3 | obj-$(CONFIG_INGENIC_CGU_JZ4725B) += jz4725b-cgu.o | ||
3 | obj-$(CONFIG_INGENIC_CGU_JZ4770) += jz4770-cgu.o | 4 | obj-$(CONFIG_INGENIC_CGU_JZ4770) += jz4770-cgu.o |
4 | obj-$(CONFIG_INGENIC_CGU_JZ4780) += jz4780-cgu.o | 5 | obj-$(CONFIG_INGENIC_CGU_JZ4780) += jz4780-cgu.o |
diff --git a/drivers/clk/ingenic/jz4725b-cgu.c b/drivers/clk/ingenic/jz4725b-cgu.c new file mode 100644 index 000000000000..584ff4ff81c7 --- /dev/null +++ b/drivers/clk/ingenic/jz4725b-cgu.c | |||
@@ -0,0 +1,225 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
2 | /* | ||
3 | * Ingenic JZ4725B SoC CGU driver | ||
4 | * | ||
5 | * Copyright (C) 2018 Paul Cercueil | ||
6 | * Author: Paul Cercueil <paul@crapouillou.net> | ||
7 | */ | ||
8 | |||
9 | #include <linux/clk-provider.h> | ||
10 | #include <linux/delay.h> | ||
11 | #include <linux/of.h> | ||
12 | #include <dt-bindings/clock/jz4725b-cgu.h> | ||
13 | #include "cgu.h" | ||
14 | |||
15 | /* CGU register offsets */ | ||
16 | #define CGU_REG_CPCCR 0x00 | ||
17 | #define CGU_REG_LCR 0x04 | ||
18 | #define CGU_REG_CPPCR 0x10 | ||
19 | #define CGU_REG_CLKGR 0x20 | ||
20 | #define CGU_REG_OPCR 0x24 | ||
21 | #define CGU_REG_I2SCDR 0x60 | ||
22 | #define CGU_REG_LPCDR 0x64 | ||
23 | #define CGU_REG_MSCCDR 0x68 | ||
24 | #define CGU_REG_SSICDR 0x74 | ||
25 | #define CGU_REG_CIMCDR 0x78 | ||
26 | |||
27 | /* bits within the LCR register */ | ||
28 | #define LCR_SLEEP BIT(0) | ||
29 | |||
30 | static struct ingenic_cgu *cgu; | ||
31 | |||
32 | static const s8 pll_od_encoding[4] = { | ||
33 | 0x0, 0x1, -1, 0x3, | ||
34 | }; | ||
35 | |||
36 | static const struct ingenic_cgu_clk_info jz4725b_cgu_clocks[] = { | ||
37 | |||
38 | /* External clocks */ | ||
39 | |||
40 | [JZ4725B_CLK_EXT] = { "ext", CGU_CLK_EXT }, | ||
41 | [JZ4725B_CLK_OSC32K] = { "osc32k", CGU_CLK_EXT }, | ||
42 | |||
43 | [JZ4725B_CLK_PLL] = { | ||
44 | "pll", CGU_CLK_PLL, | ||
45 | .parents = { JZ4725B_CLK_EXT, -1, -1, -1 }, | ||
46 | .pll = { | ||
47 | .reg = CGU_REG_CPPCR, | ||
48 | .m_shift = 23, | ||
49 | .m_bits = 9, | ||
50 | .m_offset = 2, | ||
51 | .n_shift = 18, | ||
52 | .n_bits = 5, | ||
53 | .n_offset = 2, | ||
54 | .od_shift = 16, | ||
55 | .od_bits = 2, | ||
56 | .od_max = 4, | ||
57 | .od_encoding = pll_od_encoding, | ||
58 | .stable_bit = 10, | ||
59 | .bypass_bit = 9, | ||
60 | .enable_bit = 8, | ||
61 | }, | ||
62 | }, | ||
63 | |||
64 | /* Muxes & dividers */ | ||
65 | |||
66 | [JZ4725B_CLK_PLL_HALF] = { | ||
67 | "pll half", CGU_CLK_DIV, | ||
68 | .parents = { JZ4725B_CLK_PLL, -1, -1, -1 }, | ||
69 | .div = { CGU_REG_CPCCR, 21, 1, 1, -1, -1, -1 }, | ||
70 | }, | ||
71 | |||
72 | [JZ4725B_CLK_CCLK] = { | ||
73 | "cclk", CGU_CLK_DIV, | ||
74 | .parents = { JZ4725B_CLK_PLL, -1, -1, -1 }, | ||
75 | .div = { CGU_REG_CPCCR, 0, 1, 4, 22, -1, -1 }, | ||
76 | }, | ||
77 | |||
78 | [JZ4725B_CLK_HCLK] = { | ||
79 | "hclk", CGU_CLK_DIV, | ||
80 | .parents = { JZ4725B_CLK_PLL, -1, -1, -1 }, | ||
81 | .div = { CGU_REG_CPCCR, 4, 1, 4, 22, -1, -1 }, | ||
82 | }, | ||
83 | |||
84 | [JZ4725B_CLK_PCLK] = { | ||
85 | "pclk", CGU_CLK_DIV, | ||
86 | .parents = { JZ4725B_CLK_PLL, -1, -1, -1 }, | ||
87 | .div = { CGU_REG_CPCCR, 8, 1, 4, 22, -1, -1 }, | ||
88 | }, | ||
89 | |||
90 | [JZ4725B_CLK_MCLK] = { | ||
91 | "mclk", CGU_CLK_DIV, | ||
92 | .parents = { JZ4725B_CLK_PLL, -1, -1, -1 }, | ||
93 | .div = { CGU_REG_CPCCR, 12, 1, 4, 22, -1, -1 }, | ||
94 | }, | ||
95 | |||
96 | [JZ4725B_CLK_IPU] = { | ||
97 | "ipu", CGU_CLK_DIV | CGU_CLK_GATE, | ||
98 | .parents = { JZ4725B_CLK_PLL, -1, -1, -1 }, | ||
99 | .div = { CGU_REG_CPCCR, 16, 1, 4, 22, -1, -1 }, | ||
100 | .gate = { CGU_REG_CLKGR, 13 }, | ||
101 | }, | ||
102 | |||
103 | [JZ4725B_CLK_LCD] = { | ||
104 | "lcd", CGU_CLK_DIV | CGU_CLK_GATE, | ||
105 | .parents = { JZ4725B_CLK_PLL_HALF, -1, -1, -1 }, | ||
106 | .div = { CGU_REG_LPCDR, 0, 1, 11, -1, -1, -1 }, | ||
107 | .gate = { CGU_REG_CLKGR, 9 }, | ||
108 | }, | ||
109 | |||
110 | [JZ4725B_CLK_I2S] = { | ||
111 | "i2s", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE, | ||
112 | .parents = { JZ4725B_CLK_EXT, JZ4725B_CLK_PLL_HALF, -1, -1 }, | ||
113 | .mux = { CGU_REG_CPCCR, 31, 1 }, | ||
114 | .div = { CGU_REG_I2SCDR, 0, 1, 9, -1, -1, -1 }, | ||
115 | .gate = { CGU_REG_CLKGR, 6 }, | ||
116 | }, | ||
117 | |||
118 | [JZ4725B_CLK_SPI] = { | ||
119 | "spi", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE, | ||
120 | .parents = { JZ4725B_CLK_EXT, JZ4725B_CLK_PLL, -1, -1 }, | ||
121 | .mux = { CGU_REG_SSICDR, 31, 1 }, | ||
122 | .div = { CGU_REG_SSICDR, 0, 1, 4, -1, -1, -1 }, | ||
123 | .gate = { CGU_REG_CLKGR, 4 }, | ||
124 | }, | ||
125 | |||
126 | [JZ4725B_CLK_MMC_MUX] = { | ||
127 | "mmc_mux", CGU_CLK_DIV, | ||
128 | .parents = { JZ4725B_CLK_PLL_HALF, -1, -1, -1 }, | ||
129 | .div = { CGU_REG_MSCCDR, 0, 1, 5, -1, -1, -1 }, | ||
130 | }, | ||
131 | |||
132 | [JZ4725B_CLK_UDC] = { | ||
133 | "udc", CGU_CLK_MUX | CGU_CLK_DIV, | ||
134 | .parents = { JZ4725B_CLK_EXT, JZ4725B_CLK_PLL_HALF, -1, -1 }, | ||
135 | .mux = { CGU_REG_CPCCR, 29, 1 }, | ||
136 | .div = { CGU_REG_CPCCR, 23, 1, 6, -1, -1, -1 }, | ||
137 | }, | ||
138 | |||
139 | /* Gate-only clocks */ | ||
140 | |||
141 | [JZ4725B_CLK_UART] = { | ||
142 | "uart", CGU_CLK_GATE, | ||
143 | .parents = { JZ4725B_CLK_EXT, -1, -1, -1 }, | ||
144 | .gate = { CGU_REG_CLKGR, 0 }, | ||
145 | }, | ||
146 | |||
147 | [JZ4725B_CLK_DMA] = { | ||
148 | "dma", CGU_CLK_GATE, | ||
149 | .parents = { JZ4725B_CLK_PCLK, -1, -1, -1 }, | ||
150 | .gate = { CGU_REG_CLKGR, 12 }, | ||
151 | }, | ||
152 | |||
153 | [JZ4725B_CLK_ADC] = { | ||
154 | "adc", CGU_CLK_GATE, | ||
155 | .parents = { JZ4725B_CLK_EXT, -1, -1, -1 }, | ||
156 | .gate = { CGU_REG_CLKGR, 7 }, | ||
157 | }, | ||
158 | |||
159 | [JZ4725B_CLK_I2C] = { | ||
160 | "i2c", CGU_CLK_GATE, | ||
161 | .parents = { JZ4725B_CLK_EXT, -1, -1, -1 }, | ||
162 | .gate = { CGU_REG_CLKGR, 3 }, | ||
163 | }, | ||
164 | |||
165 | [JZ4725B_CLK_AIC] = { | ||
166 | "aic", CGU_CLK_GATE, | ||
167 | .parents = { JZ4725B_CLK_EXT, -1, -1, -1 }, | ||
168 | .gate = { CGU_REG_CLKGR, 5 }, | ||
169 | }, | ||
170 | |||
171 | [JZ4725B_CLK_MMC0] = { | ||
172 | "mmc0", CGU_CLK_GATE, | ||
173 | .parents = { JZ4725B_CLK_MMC_MUX, -1, -1, -1 }, | ||
174 | .gate = { CGU_REG_CLKGR, 6 }, | ||
175 | }, | ||
176 | |||
177 | [JZ4725B_CLK_MMC1] = { | ||
178 | "mmc1", CGU_CLK_GATE, | ||
179 | .parents = { JZ4725B_CLK_MMC_MUX, -1, -1, -1 }, | ||
180 | .gate = { CGU_REG_CLKGR, 16 }, | ||
181 | }, | ||
182 | |||
183 | [JZ4725B_CLK_BCH] = { | ||
184 | "bch", CGU_CLK_GATE, | ||
185 | .parents = { JZ4725B_CLK_MCLK/* not sure */, -1, -1, -1 }, | ||
186 | .gate = { CGU_REG_CLKGR, 11 }, | ||
187 | }, | ||
188 | |||
189 | [JZ4725B_CLK_TCU] = { | ||
190 | "tcu", CGU_CLK_GATE, | ||
191 | .parents = { JZ4725B_CLK_EXT/* not sure */, -1, -1, -1 }, | ||
192 | .gate = { CGU_REG_CLKGR, 1 }, | ||
193 | }, | ||
194 | |||
195 | [JZ4725B_CLK_EXT512] = { | ||
196 | "ext/512", CGU_CLK_FIXDIV, | ||
197 | .parents = { JZ4725B_CLK_EXT }, | ||
198 | |||
199 | /* Doc calls it EXT512, but it seems to be /256... */ | ||
200 | .fixdiv = { 256 }, | ||
201 | }, | ||
202 | |||
203 | [JZ4725B_CLK_RTC] = { | ||
204 | "rtc", CGU_CLK_MUX, | ||
205 | .parents = { JZ4725B_CLK_EXT512, JZ4725B_CLK_OSC32K, -1, -1 }, | ||
206 | .mux = { CGU_REG_OPCR, 2, 1}, | ||
207 | }, | ||
208 | }; | ||
209 | |||
210 | static void __init jz4725b_cgu_init(struct device_node *np) | ||
211 | { | ||
212 | int retval; | ||
213 | |||
214 | cgu = ingenic_cgu_new(jz4725b_cgu_clocks, | ||
215 | ARRAY_SIZE(jz4725b_cgu_clocks), np); | ||
216 | if (!cgu) { | ||
217 | pr_err("%s: failed to initialise CGU\n", __func__); | ||
218 | return; | ||
219 | } | ||
220 | |||
221 | retval = ingenic_cgu_register_clocks(cgu); | ||
222 | if (retval) | ||
223 | pr_err("%s: failed to register CGU Clocks\n", __func__); | ||
224 | } | ||
225 | CLK_OF_DECLARE(jz4725b_cgu, "ingenic,jz4725b-cgu", jz4725b_cgu_init); | ||