1 | // SPDX-License-Identifier: GPL-2.0-only |
---|---|
2 | |
3 | #include <linux/delay.h> |
4 | #include <linux/clk-provider.h> |
5 | #include <linux/io.h> |
6 | #include <linux/mfd/syscon.h> |
7 | #include <linux/platform_device.h> |
8 | #include <linux/property.h> |
9 | #include <linux/regmap.h> |
10 | #include <linux/reset-controller.h> |
11 | #include <dt-bindings/clock/en7523-clk.h> |
12 | #include <dt-bindings/reset/airoha,en7581-reset.h> |
13 | |
14 | #define RST_NR_PER_BANK 32 |
15 | |
16 | #define REG_PCI_CONTROL 0x88 |
17 | #define REG_PCI_CONTROL_PERSTOUT BIT(29) |
18 | #define REG_PCI_CONTROL_PERSTOUT1 BIT(26) |
19 | #define REG_PCI_CONTROL_REFCLK_EN0 BIT(23) |
20 | #define REG_PCI_CONTROL_REFCLK_EN1 BIT(22) |
21 | #define REG_PCI_CONTROL_PERSTOUT2 BIT(16) |
22 | #define REG_GSW_CLK_DIV_SEL 0x1b4 |
23 | #define REG_EMI_CLK_DIV_SEL 0x1b8 |
24 | #define REG_BUS_CLK_DIV_SEL 0x1bc |
25 | #define REG_SPI_CLK_DIV_SEL 0x1c4 |
26 | #define REG_SPI_CLK_FREQ_SEL 0x1c8 |
27 | #define REG_NPU_CLK_DIV_SEL 0x1fc |
28 | #define REG_CRYPTO_CLKSRC 0x200 |
29 | #define REG_RESET_CONTROL2 0x830 |
30 | #define REG_RESET2_CONTROL_PCIE2 BIT(27) |
31 | #define REG_RESET_CONTROL1 0x834 |
32 | #define REG_RESET_CONTROL_PCIEHB BIT(29) |
33 | #define REG_RESET_CONTROL_PCIE1 BIT(27) |
34 | #define REG_RESET_CONTROL_PCIE2 BIT(26) |
35 | /* EN7581 */ |
36 | #define REG_NP_SCU_PCIC 0x88 |
37 | #define REG_NP_SCU_SSTR 0x9c |
38 | #define REG_PCIE_XSI0_SEL_MASK GENMASK(14, 13) |
39 | #define REG_PCIE_XSI1_SEL_MASK GENMASK(12, 11) |
40 | #define REG_CRYPTO_CLKSRC2 0x20c |
41 | |
42 | #define REG_RST_CTRL2 0x830 |
43 | #define REG_RST_CTRL1 0x834 |
44 | |
45 | struct en_clk_desc { |
46 | int id; |
47 | const char *name; |
48 | u32 base_reg; |
49 | u8 base_bits; |
50 | u8 base_shift; |
51 | union { |
52 | const unsigned int *base_values; |
53 | unsigned int base_value; |
54 | }; |
55 | size_t n_base_values; |
56 | |
57 | u16 div_reg; |
58 | u8 div_bits; |
59 | u8 div_shift; |
60 | u16 div_val0; |
61 | u8 div_step; |
62 | u8 div_offset; |
63 | }; |
64 | |
65 | struct en_clk_gate { |
66 | void __iomem *base; |
67 | struct clk_hw hw; |
68 | }; |
69 | |
70 | struct en_rst_data { |
71 | const u16 *bank_ofs; |
72 | const u16 *idx_map; |
73 | void __iomem *base; |
74 | struct reset_controller_dev rcdev; |
75 | }; |
76 | |
77 | struct en_clk_soc_data { |
78 | u32 num_clocks; |
79 | const struct clk_ops pcie_ops; |
80 | int (*hw_init)(struct platform_device *pdev, |
81 | struct clk_hw_onecell_data *clk_data); |
82 | }; |
83 | |
84 | static const u32 gsw_base[] = { 400000000, 500000000 }; |
85 | static const u32 emi_base[] = { 333000000, 400000000 }; |
86 | static const u32 bus_base[] = { 500000000, 540000000 }; |
87 | static const u32 slic_base[] = { 100000000, 3125000 }; |
88 | static const u32 npu_base[] = { 333000000, 400000000, 500000000 }; |
89 | /* EN7581 */ |
90 | static const u32 emi7581_base[] = { 540000000, 480000000, 400000000, 300000000 }; |
91 | static const u32 bus7581_base[] = { 600000000, 540000000 }; |
92 | static const u32 npu7581_base[] = { 800000000, 750000000, 720000000, 600000000 }; |
93 | static const u32 crypto_base[] = { 540000000, 480000000 }; |
94 | static const u32 emmc7581_base[] = { 200000000, 150000000 }; |
95 | |
96 | static const struct en_clk_desc en7523_base_clks[] = { |
97 | { |
98 | .id = EN7523_CLK_GSW, |
99 | .name = "gsw", |
100 | |
101 | .base_reg = REG_GSW_CLK_DIV_SEL, |
102 | .base_bits = 1, |
103 | .base_shift = 8, |
104 | .base_values = gsw_base, |
105 | .n_base_values = ARRAY_SIZE(gsw_base), |
106 | |
107 | .div_bits = 3, |
108 | .div_shift = 0, |
109 | .div_step = 1, |
110 | .div_offset = 1, |
111 | }, { |
112 | .id = EN7523_CLK_EMI, |
113 | .name = "emi", |
114 | |
115 | .base_reg = REG_EMI_CLK_DIV_SEL, |
116 | .base_bits = 1, |
117 | .base_shift = 8, |
118 | .base_values = emi_base, |
119 | .n_base_values = ARRAY_SIZE(emi_base), |
120 | |
121 | .div_bits = 3, |
122 | .div_shift = 0, |
123 | .div_step = 1, |
124 | .div_offset = 1, |
125 | }, { |
126 | .id = EN7523_CLK_BUS, |
127 | .name = "bus", |
128 | |
129 | .base_reg = REG_BUS_CLK_DIV_SEL, |
130 | .base_bits = 1, |
131 | .base_shift = 8, |
132 | .base_values = bus_base, |
133 | .n_base_values = ARRAY_SIZE(bus_base), |
134 | |
135 | .div_bits = 3, |
136 | .div_shift = 0, |
137 | .div_step = 1, |
138 | .div_offset = 1, |
139 | }, { |
140 | .id = EN7523_CLK_SLIC, |
141 | .name = "slic", |
142 | |
143 | .base_reg = REG_SPI_CLK_FREQ_SEL, |
144 | .base_bits = 1, |
145 | .base_shift = 0, |
146 | .base_values = slic_base, |
147 | .n_base_values = ARRAY_SIZE(slic_base), |
148 | |
149 | .div_reg = REG_SPI_CLK_DIV_SEL, |
150 | .div_bits = 5, |
151 | .div_shift = 24, |
152 | .div_val0 = 20, |
153 | .div_step = 2, |
154 | }, { |
155 | .id = EN7523_CLK_SPI, |
156 | .name = "spi", |
157 | |
158 | .base_reg = REG_SPI_CLK_DIV_SEL, |
159 | |
160 | .base_value = 400000000, |
161 | |
162 | .div_bits = 5, |
163 | .div_shift = 8, |
164 | .div_val0 = 40, |
165 | .div_step = 2, |
166 | }, { |
167 | .id = EN7523_CLK_NPU, |
168 | .name = "npu", |
169 | |
170 | .base_reg = REG_NPU_CLK_DIV_SEL, |
171 | .base_bits = 2, |
172 | .base_shift = 8, |
173 | .base_values = npu_base, |
174 | .n_base_values = ARRAY_SIZE(npu_base), |
175 | |
176 | .div_bits = 3, |
177 | .div_shift = 0, |
178 | .div_step = 1, |
179 | .div_offset = 1, |
180 | }, { |
181 | .id = EN7523_CLK_CRYPTO, |
182 | .name = "crypto", |
183 | |
184 | .base_reg = REG_CRYPTO_CLKSRC, |
185 | .base_bits = 1, |
186 | .base_shift = 0, |
187 | .base_values = emi_base, |
188 | .n_base_values = ARRAY_SIZE(emi_base), |
189 | } |
190 | }; |
191 | |
192 | static const struct en_clk_desc en7581_base_clks[] = { |
193 | { |
194 | .id = EN7523_CLK_GSW, |
195 | .name = "gsw", |
196 | |
197 | .base_reg = REG_GSW_CLK_DIV_SEL, |
198 | .base_bits = 1, |
199 | .base_shift = 8, |
200 | .base_values = gsw_base, |
201 | .n_base_values = ARRAY_SIZE(gsw_base), |
202 | |
203 | .div_bits = 3, |
204 | .div_shift = 0, |
205 | .div_step = 1, |
206 | .div_offset = 1, |
207 | }, { |
208 | .id = EN7523_CLK_EMI, |
209 | .name = "emi", |
210 | |
211 | .base_reg = REG_EMI_CLK_DIV_SEL, |
212 | .base_bits = 2, |
213 | .base_shift = 8, |
214 | .base_values = emi7581_base, |
215 | .n_base_values = ARRAY_SIZE(emi7581_base), |
216 | |
217 | .div_bits = 3, |
218 | .div_shift = 0, |
219 | .div_step = 1, |
220 | .div_offset = 1, |
221 | }, { |
222 | .id = EN7523_CLK_BUS, |
223 | .name = "bus", |
224 | |
225 | .base_reg = REG_BUS_CLK_DIV_SEL, |
226 | .base_bits = 1, |
227 | .base_shift = 8, |
228 | .base_values = bus7581_base, |
229 | .n_base_values = ARRAY_SIZE(bus7581_base), |
230 | |
231 | .div_bits = 3, |
232 | .div_shift = 0, |
233 | .div_step = 1, |
234 | .div_offset = 1, |
235 | }, { |
236 | .id = EN7523_CLK_SLIC, |
237 | .name = "slic", |
238 | |
239 | .base_reg = REG_SPI_CLK_FREQ_SEL, |
240 | .base_bits = 1, |
241 | .base_shift = 0, |
242 | .base_values = slic_base, |
243 | .n_base_values = ARRAY_SIZE(slic_base), |
244 | |
245 | .div_reg = REG_SPI_CLK_DIV_SEL, |
246 | .div_bits = 5, |
247 | .div_shift = 24, |
248 | .div_val0 = 20, |
249 | .div_step = 2, |
250 | }, { |
251 | .id = EN7523_CLK_SPI, |
252 | .name = "spi", |
253 | |
254 | .base_reg = REG_SPI_CLK_DIV_SEL, |
255 | |
256 | .base_value = 400000000, |
257 | |
258 | .div_bits = 5, |
259 | .div_shift = 8, |
260 | .div_val0 = 40, |
261 | .div_step = 2, |
262 | }, { |
263 | .id = EN7523_CLK_NPU, |
264 | .name = "npu", |
265 | |
266 | .base_reg = REG_NPU_CLK_DIV_SEL, |
267 | .base_bits = 2, |
268 | .base_shift = 8, |
269 | .base_values = npu7581_base, |
270 | .n_base_values = ARRAY_SIZE(npu7581_base), |
271 | |
272 | .div_bits = 3, |
273 | .div_shift = 0, |
274 | .div_step = 1, |
275 | .div_offset = 1, |
276 | }, { |
277 | .id = EN7523_CLK_CRYPTO, |
278 | .name = "crypto", |
279 | |
280 | .base_reg = REG_CRYPTO_CLKSRC2, |
281 | .base_bits = 1, |
282 | .base_shift = 0, |
283 | .base_values = crypto_base, |
284 | .n_base_values = ARRAY_SIZE(crypto_base), |
285 | }, { |
286 | .id = EN7581_CLK_EMMC, |
287 | .name = "emmc", |
288 | |
289 | .base_reg = REG_CRYPTO_CLKSRC2, |
290 | .base_bits = 1, |
291 | .base_shift = 12, |
292 | .base_values = emmc7581_base, |
293 | .n_base_values = ARRAY_SIZE(emmc7581_base), |
294 | } |
295 | }; |
296 | |
297 | static const u16 en7581_rst_ofs[] = { |
298 | REG_RST_CTRL2, |
299 | REG_RST_CTRL1, |
300 | }; |
301 | |
302 | static const u16 en7581_rst_map[] = { |
303 | /* RST_CTRL2 */ |
304 | [EN7581_XPON_PHY_RST] = 0, |
305 | [EN7581_CPU_TIMER2_RST] = 2, |
306 | [EN7581_HSUART_RST] = 3, |
307 | [EN7581_UART4_RST] = 4, |
308 | [EN7581_UART5_RST] = 5, |
309 | [EN7581_I2C2_RST] = 6, |
310 | [EN7581_XSI_MAC_RST] = 7, |
311 | [EN7581_XSI_PHY_RST] = 8, |
312 | [EN7581_NPU_RST] = 9, |
313 | [EN7581_I2S_RST] = 10, |
314 | [EN7581_TRNG_RST] = 11, |
315 | [EN7581_TRNG_MSTART_RST] = 12, |
316 | [EN7581_DUAL_HSI0_RST] = 13, |
317 | [EN7581_DUAL_HSI1_RST] = 14, |
318 | [EN7581_HSI_RST] = 15, |
319 | [EN7581_DUAL_HSI0_MAC_RST] = 16, |
320 | [EN7581_DUAL_HSI1_MAC_RST] = 17, |
321 | [EN7581_HSI_MAC_RST] = 18, |
322 | [EN7581_WDMA_RST] = 19, |
323 | [EN7581_WOE0_RST] = 20, |
324 | [EN7581_WOE1_RST] = 21, |
325 | [EN7581_HSDMA_RST] = 22, |
326 | [EN7581_TDMA_RST] = 24, |
327 | [EN7581_EMMC_RST] = 25, |
328 | [EN7581_SOE_RST] = 26, |
329 | [EN7581_PCIE2_RST] = 27, |
330 | [EN7581_XFP_MAC_RST] = 28, |
331 | [EN7581_USB_HOST_P1_RST] = 29, |
332 | [EN7581_USB_HOST_P1_U3_PHY_RST] = 30, |
333 | /* RST_CTRL1 */ |
334 | [EN7581_PCM1_ZSI_ISI_RST] = RST_NR_PER_BANK + 0, |
335 | [EN7581_FE_PDMA_RST] = RST_NR_PER_BANK + 1, |
336 | [EN7581_FE_QDMA_RST] = RST_NR_PER_BANK + 2, |
337 | [EN7581_PCM_SPIWP_RST] = RST_NR_PER_BANK + 4, |
338 | [EN7581_CRYPTO_RST] = RST_NR_PER_BANK + 6, |
339 | [EN7581_TIMER_RST] = RST_NR_PER_BANK + 8, |
340 | [EN7581_PCM1_RST] = RST_NR_PER_BANK + 11, |
341 | [EN7581_UART_RST] = RST_NR_PER_BANK + 12, |
342 | [EN7581_GPIO_RST] = RST_NR_PER_BANK + 13, |
343 | [EN7581_GDMA_RST] = RST_NR_PER_BANK + 14, |
344 | [EN7581_I2C_MASTER_RST] = RST_NR_PER_BANK + 16, |
345 | [EN7581_PCM2_ZSI_ISI_RST] = RST_NR_PER_BANK + 17, |
346 | [EN7581_SFC_RST] = RST_NR_PER_BANK + 18, |
347 | [EN7581_UART2_RST] = RST_NR_PER_BANK + 19, |
348 | [EN7581_GDMP_RST] = RST_NR_PER_BANK + 20, |
349 | [EN7581_FE_RST] = RST_NR_PER_BANK + 21, |
350 | [EN7581_USB_HOST_P0_RST] = RST_NR_PER_BANK + 22, |
351 | [EN7581_GSW_RST] = RST_NR_PER_BANK + 23, |
352 | [EN7581_SFC2_PCM_RST] = RST_NR_PER_BANK + 25, |
353 | [EN7581_PCIE0_RST] = RST_NR_PER_BANK + 26, |
354 | [EN7581_PCIE1_RST] = RST_NR_PER_BANK + 27, |
355 | [EN7581_CPU_TIMER_RST] = RST_NR_PER_BANK + 28, |
356 | [EN7581_PCIE_HB_RST] = RST_NR_PER_BANK + 29, |
357 | [EN7581_XPON_MAC_RST] = RST_NR_PER_BANK + 31, |
358 | }; |
359 | |
360 | static u32 en7523_get_base_rate(const struct en_clk_desc *desc, u32 val) |
361 | { |
362 | if (!desc->base_bits) |
363 | return desc->base_value; |
364 | |
365 | val >>= desc->base_shift; |
366 | val &= (1 << desc->base_bits) - 1; |
367 | |
368 | if (val >= desc->n_base_values) |
369 | return 0; |
370 | |
371 | return desc->base_values[val]; |
372 | } |
373 | |
374 | static u32 en7523_get_div(const struct en_clk_desc *desc, u32 val) |
375 | { |
376 | if (!desc->div_bits) |
377 | return 1; |
378 | |
379 | val >>= desc->div_shift; |
380 | val &= (1 << desc->div_bits) - 1; |
381 | |
382 | if (!val && desc->div_val0) |
383 | return desc->div_val0; |
384 | |
385 | return (val + desc->div_offset) * desc->div_step; |
386 | } |
387 | |
388 | static int en7523_pci_is_enabled(struct clk_hw *hw) |
389 | { |
390 | struct en_clk_gate *cg = container_of(hw, struct en_clk_gate, hw); |
391 | |
392 | return !!(readl(addr: cg->base + REG_PCI_CONTROL) & REG_PCI_CONTROL_REFCLK_EN1); |
393 | } |
394 | |
395 | static int en7523_pci_prepare(struct clk_hw *hw) |
396 | { |
397 | struct en_clk_gate *cg = container_of(hw, struct en_clk_gate, hw); |
398 | void __iomem *np_base = cg->base; |
399 | u32 val, mask; |
400 | |
401 | /* Need to pull device low before reset */ |
402 | val = readl(addr: np_base + REG_PCI_CONTROL); |
403 | val &= ~(REG_PCI_CONTROL_PERSTOUT1 | REG_PCI_CONTROL_PERSTOUT); |
404 | writel(val, addr: np_base + REG_PCI_CONTROL); |
405 | usleep_range(min: 1000, max: 2000); |
406 | |
407 | /* Enable PCIe port 1 */ |
408 | val |= REG_PCI_CONTROL_REFCLK_EN1; |
409 | writel(val, addr: np_base + REG_PCI_CONTROL); |
410 | usleep_range(min: 1000, max: 2000); |
411 | |
412 | /* Reset to default */ |
413 | val = readl(addr: np_base + REG_RESET_CONTROL1); |
414 | mask = REG_RESET_CONTROL_PCIE1 | REG_RESET_CONTROL_PCIE2 | |
415 | REG_RESET_CONTROL_PCIEHB; |
416 | writel(val: val & ~mask, addr: np_base + REG_RESET_CONTROL1); |
417 | usleep_range(min: 1000, max: 2000); |
418 | writel(val: val | mask, addr: np_base + REG_RESET_CONTROL1); |
419 | msleep(msecs: 100); |
420 | writel(val: val & ~mask, addr: np_base + REG_RESET_CONTROL1); |
421 | usleep_range(min: 5000, max: 10000); |
422 | |
423 | /* Release device */ |
424 | mask = REG_PCI_CONTROL_PERSTOUT1 | REG_PCI_CONTROL_PERSTOUT; |
425 | val = readl(addr: np_base + REG_PCI_CONTROL); |
426 | writel(val: val & ~mask, addr: np_base + REG_PCI_CONTROL); |
427 | usleep_range(min: 1000, max: 2000); |
428 | writel(val: val | mask, addr: np_base + REG_PCI_CONTROL); |
429 | msleep(msecs: 250); |
430 | |
431 | return 0; |
432 | } |
433 | |
434 | static void en7523_pci_unprepare(struct clk_hw *hw) |
435 | { |
436 | struct en_clk_gate *cg = container_of(hw, struct en_clk_gate, hw); |
437 | void __iomem *np_base = cg->base; |
438 | u32 val; |
439 | |
440 | val = readl(addr: np_base + REG_PCI_CONTROL); |
441 | val &= ~REG_PCI_CONTROL_REFCLK_EN1; |
442 | writel(val, addr: np_base + REG_PCI_CONTROL); |
443 | } |
444 | |
445 | static struct clk_hw *en7523_register_pcie_clk(struct device *dev, |
446 | void __iomem *np_base) |
447 | { |
448 | const struct en_clk_soc_data *soc_data = device_get_match_data(dev); |
449 | struct clk_init_data init = { |
450 | .name = "pcie", |
451 | .ops = &soc_data->pcie_ops, |
452 | }; |
453 | struct en_clk_gate *cg; |
454 | |
455 | cg = devm_kzalloc(dev, size: sizeof(*cg), GFP_KERNEL); |
456 | if (!cg) |
457 | return NULL; |
458 | |
459 | cg->base = np_base; |
460 | cg->hw.init = &init; |
461 | |
462 | if (init.ops->unprepare) |
463 | init.ops->unprepare(&cg->hw); |
464 | |
465 | if (clk_hw_register(dev, hw: &cg->hw)) |
466 | return NULL; |
467 | |
468 | return &cg->hw; |
469 | } |
470 | |
471 | static int en7581_pci_is_enabled(struct clk_hw *hw) |
472 | { |
473 | struct en_clk_gate *cg = container_of(hw, struct en_clk_gate, hw); |
474 | u32 val, mask; |
475 | |
476 | mask = REG_PCI_CONTROL_REFCLK_EN0 | REG_PCI_CONTROL_REFCLK_EN1; |
477 | val = readl(addr: cg->base + REG_PCI_CONTROL); |
478 | return (val & mask) == mask; |
479 | } |
480 | |
481 | static int en7581_pci_enable(struct clk_hw *hw) |
482 | { |
483 | struct en_clk_gate *cg = container_of(hw, struct en_clk_gate, hw); |
484 | void __iomem *np_base = cg->base; |
485 | u32 val, mask; |
486 | |
487 | mask = REG_PCI_CONTROL_REFCLK_EN0 | REG_PCI_CONTROL_REFCLK_EN1 | |
488 | REG_PCI_CONTROL_PERSTOUT1 | REG_PCI_CONTROL_PERSTOUT2 | |
489 | REG_PCI_CONTROL_PERSTOUT; |
490 | val = readl(addr: np_base + REG_PCI_CONTROL); |
491 | writel(val: val | mask, addr: np_base + REG_PCI_CONTROL); |
492 | |
493 | return 0; |
494 | } |
495 | |
496 | static void en7581_pci_disable(struct clk_hw *hw) |
497 | { |
498 | struct en_clk_gate *cg = container_of(hw, struct en_clk_gate, hw); |
499 | void __iomem *np_base = cg->base; |
500 | u32 val, mask; |
501 | |
502 | mask = REG_PCI_CONTROL_REFCLK_EN0 | REG_PCI_CONTROL_REFCLK_EN1 | |
503 | REG_PCI_CONTROL_PERSTOUT1 | REG_PCI_CONTROL_PERSTOUT2 | |
504 | REG_PCI_CONTROL_PERSTOUT; |
505 | val = readl(addr: np_base + REG_PCI_CONTROL); |
506 | writel(val: val & ~mask, addr: np_base + REG_PCI_CONTROL); |
507 | usleep_range(min: 1000, max: 2000); |
508 | } |
509 | |
510 | static void en7523_register_clocks(struct device *dev, struct clk_hw_onecell_data *clk_data, |
511 | void __iomem *base, void __iomem *np_base) |
512 | { |
513 | struct clk_hw *hw; |
514 | u32 rate; |
515 | int i; |
516 | |
517 | for (i = 0; i < ARRAY_SIZE(en7523_base_clks); i++) { |
518 | const struct en_clk_desc *desc = &en7523_base_clks[i]; |
519 | u32 reg = desc->div_reg ? desc->div_reg : desc->base_reg; |
520 | u32 val = readl(addr: base + desc->base_reg); |
521 | |
522 | rate = en7523_get_base_rate(desc, val); |
523 | val = readl(addr: base + reg); |
524 | rate /= en7523_get_div(desc, val); |
525 | |
526 | hw = clk_hw_register_fixed_rate(dev, desc->name, NULL, 0, rate); |
527 | if (IS_ERR(ptr: hw)) { |
528 | pr_err("Failed to register clk %s: %ld\n", |
529 | desc->name, PTR_ERR(hw)); |
530 | continue; |
531 | } |
532 | |
533 | clk_data->hws[desc->id] = hw; |
534 | } |
535 | |
536 | hw = en7523_register_pcie_clk(dev, np_base); |
537 | clk_data->hws[EN7523_CLK_PCIE] = hw; |
538 | } |
539 | |
540 | static int en7523_clk_hw_init(struct platform_device *pdev, |
541 | struct clk_hw_onecell_data *clk_data) |
542 | { |
543 | void __iomem *base, *np_base; |
544 | |
545 | base = devm_platform_ioremap_resource(pdev, index: 0); |
546 | if (IS_ERR(ptr: base)) |
547 | return PTR_ERR(ptr: base); |
548 | |
549 | np_base = devm_platform_ioremap_resource(pdev, index: 1); |
550 | if (IS_ERR(ptr: np_base)) |
551 | return PTR_ERR(ptr: np_base); |
552 | |
553 | en7523_register_clocks(dev: &pdev->dev, clk_data, base, np_base); |
554 | |
555 | return 0; |
556 | } |
557 | |
558 | static void en7581_register_clocks(struct device *dev, struct clk_hw_onecell_data *clk_data, |
559 | struct regmap *map, void __iomem *base) |
560 | { |
561 | struct clk_hw *hw; |
562 | u32 rate; |
563 | int i; |
564 | |
565 | for (i = 0; i < ARRAY_SIZE(en7581_base_clks); i++) { |
566 | const struct en_clk_desc *desc = &en7581_base_clks[i]; |
567 | u32 val, reg = desc->div_reg ? desc->div_reg : desc->base_reg; |
568 | int err; |
569 | |
570 | err = regmap_read(map, reg: desc->base_reg, val: &val); |
571 | if (err) { |
572 | pr_err("Failed reading fixed clk rate %s: %d\n", |
573 | desc->name, err); |
574 | continue; |
575 | } |
576 | rate = en7523_get_base_rate(desc, val); |
577 | |
578 | err = regmap_read(map, reg, val: &val); |
579 | if (err) { |
580 | pr_err("Failed reading fixed clk div %s: %d\n", |
581 | desc->name, err); |
582 | continue; |
583 | } |
584 | rate /= en7523_get_div(desc, val); |
585 | |
586 | hw = clk_hw_register_fixed_rate(dev, desc->name, NULL, 0, rate); |
587 | if (IS_ERR(ptr: hw)) { |
588 | pr_err("Failed to register clk %s: %ld\n", |
589 | desc->name, PTR_ERR(hw)); |
590 | continue; |
591 | } |
592 | |
593 | clk_data->hws[desc->id] = hw; |
594 | } |
595 | |
596 | hw = en7523_register_pcie_clk(dev, np_base: base); |
597 | clk_data->hws[EN7523_CLK_PCIE] = hw; |
598 | } |
599 | |
600 | static int en7523_reset_update(struct reset_controller_dev *rcdev, |
601 | unsigned long id, bool assert) |
602 | { |
603 | struct en_rst_data *rst_data = container_of(rcdev, struct en_rst_data, rcdev); |
604 | void __iomem *addr = rst_data->base + rst_data->bank_ofs[id / RST_NR_PER_BANK]; |
605 | u32 val; |
606 | |
607 | val = readl(addr); |
608 | if (assert) |
609 | val |= BIT(id % RST_NR_PER_BANK); |
610 | else |
611 | val &= ~BIT(id % RST_NR_PER_BANK); |
612 | writel(val, addr); |
613 | |
614 | return 0; |
615 | } |
616 | |
617 | static int en7523_reset_assert(struct reset_controller_dev *rcdev, |
618 | unsigned long id) |
619 | { |
620 | return en7523_reset_update(rcdev, id, assert: true); |
621 | } |
622 | |
623 | static int en7523_reset_deassert(struct reset_controller_dev *rcdev, |
624 | unsigned long id) |
625 | { |
626 | return en7523_reset_update(rcdev, id, assert: false); |
627 | } |
628 | |
629 | static int en7523_reset_status(struct reset_controller_dev *rcdev, |
630 | unsigned long id) |
631 | { |
632 | struct en_rst_data *rst_data = container_of(rcdev, struct en_rst_data, rcdev); |
633 | void __iomem *addr = rst_data->base + rst_data->bank_ofs[id / RST_NR_PER_BANK]; |
634 | |
635 | return !!(readl(addr) & BIT(id % RST_NR_PER_BANK)); |
636 | } |
637 | |
638 | static int en7523_reset_xlate(struct reset_controller_dev *rcdev, |
639 | const struct of_phandle_args *reset_spec) |
640 | { |
641 | struct en_rst_data *rst_data = container_of(rcdev, struct en_rst_data, rcdev); |
642 | |
643 | if (reset_spec->args[0] >= rcdev->nr_resets) |
644 | return -EINVAL; |
645 | |
646 | return rst_data->idx_map[reset_spec->args[0]]; |
647 | } |
648 | |
649 | static const struct reset_control_ops en7581_reset_ops = { |
650 | .assert = en7523_reset_assert, |
651 | .deassert = en7523_reset_deassert, |
652 | .status = en7523_reset_status, |
653 | }; |
654 | |
655 | static int en7581_reset_register(struct device *dev, void __iomem *base) |
656 | { |
657 | struct en_rst_data *rst_data; |
658 | |
659 | rst_data = devm_kzalloc(dev, size: sizeof(*rst_data), GFP_KERNEL); |
660 | if (!rst_data) |
661 | return -ENOMEM; |
662 | |
663 | rst_data->bank_ofs = en7581_rst_ofs; |
664 | rst_data->idx_map = en7581_rst_map; |
665 | rst_data->base = base; |
666 | |
667 | rst_data->rcdev.nr_resets = ARRAY_SIZE(en7581_rst_map); |
668 | rst_data->rcdev.of_xlate = en7523_reset_xlate; |
669 | rst_data->rcdev.ops = &en7581_reset_ops; |
670 | rst_data->rcdev.of_node = dev->of_node; |
671 | rst_data->rcdev.of_reset_n_cells = 1; |
672 | rst_data->rcdev.owner = THIS_MODULE; |
673 | rst_data->rcdev.dev = dev; |
674 | |
675 | return devm_reset_controller_register(dev, rcdev: &rst_data->rcdev); |
676 | } |
677 | |
678 | static int en7581_clk_hw_init(struct platform_device *pdev, |
679 | struct clk_hw_onecell_data *clk_data) |
680 | { |
681 | struct regmap *map; |
682 | void __iomem *base; |
683 | u32 val; |
684 | |
685 | map = syscon_regmap_lookup_by_compatible(s: "airoha,en7581-chip-scu"); |
686 | if (IS_ERR(ptr: map)) |
687 | return PTR_ERR(ptr: map); |
688 | |
689 | base = devm_platform_ioremap_resource(pdev, index: 0); |
690 | if (IS_ERR(ptr: base)) |
691 | return PTR_ERR(ptr: base); |
692 | |
693 | en7581_register_clocks(dev: &pdev->dev, clk_data, map, base); |
694 | |
695 | val = readl(addr: base + REG_NP_SCU_SSTR); |
696 | val &= ~(REG_PCIE_XSI0_SEL_MASK | REG_PCIE_XSI1_SEL_MASK); |
697 | writel(val, addr: base + REG_NP_SCU_SSTR); |
698 | val = readl(addr: base + REG_NP_SCU_PCIC); |
699 | writel(val: val | 3, addr: base + REG_NP_SCU_PCIC); |
700 | |
701 | return en7581_reset_register(dev: &pdev->dev, base); |
702 | } |
703 | |
704 | static int en7523_clk_probe(struct platform_device *pdev) |
705 | { |
706 | struct device_node *node = pdev->dev.of_node; |
707 | const struct en_clk_soc_data *soc_data; |
708 | struct clk_hw_onecell_data *clk_data; |
709 | int r; |
710 | |
711 | soc_data = device_get_match_data(dev: &pdev->dev); |
712 | |
713 | clk_data = devm_kzalloc(dev: &pdev->dev, |
714 | struct_size(clk_data, hws, soc_data->num_clocks), |
715 | GFP_KERNEL); |
716 | if (!clk_data) |
717 | return -ENOMEM; |
718 | |
719 | clk_data->num = soc_data->num_clocks; |
720 | r = soc_data->hw_init(pdev, clk_data); |
721 | if (r) |
722 | return r; |
723 | |
724 | return of_clk_add_hw_provider(np: node, get: of_clk_hw_onecell_get, data: clk_data); |
725 | } |
726 | |
727 | static const struct en_clk_soc_data en7523_data = { |
728 | .num_clocks = ARRAY_SIZE(en7523_base_clks) + 1, |
729 | .pcie_ops = { |
730 | .is_enabled = en7523_pci_is_enabled, |
731 | .prepare = en7523_pci_prepare, |
732 | .unprepare = en7523_pci_unprepare, |
733 | }, |
734 | .hw_init = en7523_clk_hw_init, |
735 | }; |
736 | |
737 | static const struct en_clk_soc_data en7581_data = { |
738 | /* We increment num_clocks by 1 to account for additional PCIe clock */ |
739 | .num_clocks = ARRAY_SIZE(en7581_base_clks) + 1, |
740 | .pcie_ops = { |
741 | .is_enabled = en7581_pci_is_enabled, |
742 | .enable = en7581_pci_enable, |
743 | .disable = en7581_pci_disable, |
744 | }, |
745 | .hw_init = en7581_clk_hw_init, |
746 | }; |
747 | |
748 | static const struct of_device_id of_match_clk_en7523[] = { |
749 | { .compatible = "airoha,en7523-scu", .data = &en7523_data }, |
750 | { .compatible = "airoha,en7581-scu", .data = &en7581_data }, |
751 | { /* sentinel */ } |
752 | }; |
753 | |
754 | static struct platform_driver clk_en7523_drv = { |
755 | .probe = en7523_clk_probe, |
756 | .driver = { |
757 | .name = "clk-en7523", |
758 | .of_match_table = of_match_clk_en7523, |
759 | .suppress_bind_attrs = true, |
760 | }, |
761 | }; |
762 | |
763 | static int __init clk_en7523_init(void) |
764 | { |
765 | return platform_driver_register(&clk_en7523_drv); |
766 | } |
767 | |
768 | arch_initcall(clk_en7523_init); |
769 |
Definitions
- en_clk_desc
- en_clk_gate
- en_rst_data
- en_clk_soc_data
- gsw_base
- emi_base
- bus_base
- slic_base
- npu_base
- emi7581_base
- bus7581_base
- npu7581_base
- crypto_base
- emmc7581_base
- en7523_base_clks
- en7581_base_clks
- en7581_rst_ofs
- en7581_rst_map
- en7523_get_base_rate
- en7523_get_div
- en7523_pci_is_enabled
- en7523_pci_prepare
- en7523_pci_unprepare
- en7523_register_pcie_clk
- en7581_pci_is_enabled
- en7581_pci_enable
- en7581_pci_disable
- en7523_register_clocks
- en7523_clk_hw_init
- en7581_register_clocks
- en7523_reset_update
- en7523_reset_assert
- en7523_reset_deassert
- en7523_reset_status
- en7523_reset_xlate
- en7581_reset_ops
- en7581_reset_register
- en7581_clk_hw_init
- en7523_clk_probe
- en7523_data
- en7581_data
- of_match_clk_en7523
- clk_en7523_drv
Improve your Profiling and Debugging skills
Find out more