1 // SPDX-License-Identifier: GPL-2.0
3 #include <linux/clk-provider.h>
4 #include <linux/init.h>
6 #include <linux/of_device.h>
7 #include <linux/platform_device.h>
9 #include <dt-bindings/clock/bcm3368-clock.h>
10 #include <dt-bindings/clock/bcm6318-clock.h>
11 #include <dt-bindings/clock/bcm6328-clock.h>
12 #include <dt-bindings/clock/bcm6358-clock.h>
13 #include <dt-bindings/clock/bcm6362-clock.h>
14 #include <dt-bindings/clock/bcm6368-clock.h>
15 #include <dt-bindings/clock/bcm63268-clock.h>
17 struct clk_bcm63xx_table_entry
{
18 const char * const name
;
23 struct clk_bcm63xx_hw
{
27 struct clk_hw_onecell_data data
;
30 static const struct clk_bcm63xx_table_entry bcm3368_clocks
[] = {
33 .bit
= BCM3368_CLK_MAC
,
36 .bit
= BCM3368_CLK_TC
,
39 .bit
= BCM3368_CLK_US_TOP
,
42 .bit
= BCM3368_CLK_DS_TOP
,
45 .bit
= BCM3368_CLK_ACM
,
48 .bit
= BCM3368_CLK_SPI
,
51 .bit
= BCM3368_CLK_USBS
,
54 .bit
= BCM3368_CLK_BMU
,
57 .bit
= BCM3368_CLK_PCM
,
60 .bit
= BCM3368_CLK_NTP
,
63 .bit
= BCM3368_CLK_ACP_B
,
66 .bit
= BCM3368_CLK_ACP_A
,
69 .bit
= BCM3368_CLK_EMUSB
,
72 .bit
= BCM3368_CLK_ENET0
,
75 .bit
= BCM3368_CLK_ENET1
,
78 .bit
= BCM3368_CLK_USBSU
,
81 .bit
= BCM3368_CLK_EPHY
,
87 static const struct clk_bcm63xx_table_entry bcm6318_clocks
[] = {
90 .bit
= BCM6318_CLK_ADSL_ASB
,
93 .bit
= BCM6318_CLK_USB_ASB
,
96 .bit
= BCM6318_CLK_MIPS_ASB
,
99 .bit
= BCM6318_CLK_PCIE_ASB
,
101 .name
= "phymips_asb",
102 .bit
= BCM6318_CLK_PHYMIPS_ASB
,
104 .name
= "robosw_asb",
105 .bit
= BCM6318_CLK_ROBOSW_ASB
,
108 .bit
= BCM6318_CLK_SAR_ASB
,
111 .bit
= BCM6318_CLK_SDR_ASB
,
114 .bit
= BCM6318_CLK_SWREG_ASB
,
116 .name
= "periph_asb",
117 .bit
= BCM6318_CLK_PERIPH_ASB
,
120 .bit
= BCM6318_CLK_CPUBUS160
,
123 .bit
= BCM6318_CLK_ADSL
,
126 .bit
= BCM6318_CLK_SAR125
,
129 .bit
= BCM6318_CLK_MIPS
,
130 .flags
= CLK_IS_CRITICAL
,
133 .bit
= BCM6318_CLK_PCIE
,
136 .bit
= BCM6318_CLK_ROBOSW250
,
139 .bit
= BCM6318_CLK_ROBOSW025
,
142 .bit
= BCM6318_CLK_SDR
,
143 .flags
= CLK_IS_CRITICAL
,
146 .bit
= BCM6318_CLK_USBD
,
149 .bit
= BCM6318_CLK_HSSPI
,
152 .bit
= BCM6318_CLK_PCIE25
,
155 .bit
= BCM6318_CLK_PHYMIPS
,
158 .bit
= BCM6318_CLK_AFE
,
161 .bit
= BCM6318_CLK_QPROC
,
167 static const struct clk_bcm63xx_table_entry bcm6318_ubus_clocks
[] = {
170 .bit
= BCM6318_UCLK_ADSL
,
173 .bit
= BCM6318_UCLK_ARB
,
174 .flags
= CLK_IS_CRITICAL
,
177 .bit
= BCM6318_UCLK_MIPS
,
178 .flags
= CLK_IS_CRITICAL
,
181 .bit
= BCM6318_UCLK_PCIE
,
183 .name
= "periph-ubus",
184 .bit
= BCM6318_UCLK_PERIPH
,
185 .flags
= CLK_IS_CRITICAL
,
187 .name
= "phymips-ubus",
188 .bit
= BCM6318_UCLK_PHYMIPS
,
190 .name
= "robosw-ubus",
191 .bit
= BCM6318_UCLK_ROBOSW
,
194 .bit
= BCM6318_UCLK_SAR
,
197 .bit
= BCM6318_UCLK_SDR
,
200 .bit
= BCM6318_UCLK_USB
,
206 static const struct clk_bcm63xx_table_entry bcm6328_clocks
[] = {
209 .bit
= BCM6328_CLK_PHYMIPS
,
211 .name
= "adsl_qproc",
212 .bit
= BCM6328_CLK_ADSL_QPROC
,
215 .bit
= BCM6328_CLK_ADSL_AFE
,
218 .bit
= BCM6328_CLK_ADSL
,
221 .bit
= BCM6328_CLK_MIPS
,
222 .flags
= CLK_IS_CRITICAL
,
225 .bit
= BCM6328_CLK_SAR
,
228 .bit
= BCM6328_CLK_PCM
,
231 .bit
= BCM6328_CLK_USBD
,
234 .bit
= BCM6328_CLK_USBH
,
237 .bit
= BCM6328_CLK_HSSPI
,
240 .bit
= BCM6328_CLK_PCIE
,
243 .bit
= BCM6328_CLK_ROBOSW
,
249 static const struct clk_bcm63xx_table_entry bcm6358_clocks
[] = {
252 .bit
= BCM6358_CLK_ENET
,
255 .bit
= BCM6358_CLK_ADSLPHY
,
258 .bit
= BCM6358_CLK_PCM
,
261 .bit
= BCM6358_CLK_SPI
,
264 .bit
= BCM6358_CLK_USBS
,
267 .bit
= BCM6358_CLK_SAR
,
270 .bit
= BCM6358_CLK_EMUSB
,
273 .bit
= BCM6358_CLK_ENET0
,
276 .bit
= BCM6358_CLK_ENET1
,
279 .bit
= BCM6358_CLK_USBSU
,
282 .bit
= BCM6358_CLK_EPHY
,
288 static const struct clk_bcm63xx_table_entry bcm6362_clocks
[] = {
290 .name
= "adsl_qproc",
291 .bit
= BCM6362_CLK_ADSL_QPROC
,
294 .bit
= BCM6362_CLK_ADSL_AFE
,
297 .bit
= BCM6362_CLK_ADSL
,
300 .bit
= BCM6362_CLK_MIPS
,
301 .flags
= CLK_IS_CRITICAL
,
304 .bit
= BCM6362_CLK_WLAN_OCP
,
307 .bit
= BCM6362_CLK_SWPKT_USB
,
310 .bit
= BCM6362_CLK_SWPKT_SAR
,
313 .bit
= BCM6362_CLK_SAR
,
316 .bit
= BCM6362_CLK_ROBOSW
,
319 .bit
= BCM6362_CLK_PCM
,
322 .bit
= BCM6362_CLK_USBD
,
325 .bit
= BCM6362_CLK_USBH
,
328 .bit
= BCM6362_CLK_IPSEC
,
331 .bit
= BCM6362_CLK_SPI
,
334 .bit
= BCM6362_CLK_HSSPI
,
337 .bit
= BCM6362_CLK_PCIE
,
340 .bit
= BCM6362_CLK_FAP
,
343 .bit
= BCM6362_CLK_PHYMIPS
,
346 .bit
= BCM6362_CLK_NAND
,
352 static const struct clk_bcm63xx_table_entry bcm6368_clocks
[] = {
354 .name
= "vdsl_qproc",
355 .bit
= BCM6368_CLK_VDSL_QPROC
,
358 .bit
= BCM6368_CLK_VDSL_AFE
,
360 .name
= "vdsl_bonding",
361 .bit
= BCM6368_CLK_VDSL_BONDING
,
364 .bit
= BCM6368_CLK_VDSL
,
367 .bit
= BCM6368_CLK_PHYMIPS
,
370 .bit
= BCM6368_CLK_SWPKT_USB
,
373 .bit
= BCM6368_CLK_SWPKT_SAR
,
376 .bit
= BCM6368_CLK_SPI
,
379 .bit
= BCM6368_CLK_USBD
,
382 .bit
= BCM6368_CLK_SAR
,
385 .bit
= BCM6368_CLK_ROBOSW
,
388 .bit
= BCM6368_CLK_UTOPIA
,
391 .bit
= BCM6368_CLK_PCM
,
394 .bit
= BCM6368_CLK_USBH
,
396 .name
= "disable_gless",
397 .bit
= BCM6368_CLK_DIS_GLESS
,
400 .bit
= BCM6368_CLK_NAND
,
403 .bit
= BCM6368_CLK_IPSEC
,
409 static const struct clk_bcm63xx_table_entry bcm63268_clocks
[] = {
411 .name
= "disable_gless",
412 .bit
= BCM63268_CLK_DIS_GLESS
,
414 .name
= "vdsl_qproc",
415 .bit
= BCM63268_CLK_VDSL_QPROC
,
418 .bit
= BCM63268_CLK_VDSL_AFE
,
421 .bit
= BCM63268_CLK_VDSL
,
424 .bit
= BCM63268_CLK_MIPS
,
425 .flags
= CLK_IS_CRITICAL
,
428 .bit
= BCM63268_CLK_WLAN_OCP
,
431 .bit
= BCM63268_CLK_DECT
,
434 .bit
= BCM63268_CLK_FAP0
,
437 .bit
= BCM63268_CLK_FAP1
,
440 .bit
= BCM63268_CLK_SAR
,
443 .bit
= BCM63268_CLK_ROBOSW
,
446 .bit
= BCM63268_CLK_PCM
,
449 .bit
= BCM63268_CLK_USBD
,
452 .bit
= BCM63268_CLK_USBH
,
455 .bit
= BCM63268_CLK_IPSEC
,
458 .bit
= BCM63268_CLK_SPI
,
461 .bit
= BCM63268_CLK_HSSPI
,
464 .bit
= BCM63268_CLK_PCIE
,
467 .bit
= BCM63268_CLK_PHYMIPS
,
470 .bit
= BCM63268_CLK_GMAC
,
473 .bit
= BCM63268_CLK_NAND
,
476 .bit
= BCM63268_CLK_TBUS
,
479 .bit
= BCM63268_CLK_ROBOSW250
,
485 static int clk_bcm63xx_probe(struct platform_device
*pdev
)
487 const struct clk_bcm63xx_table_entry
*entry
, *table
;
488 struct clk_bcm63xx_hw
*hw
;
492 table
= of_device_get_match_data(&pdev
->dev
);
496 for (entry
= table
; entry
->name
; entry
++)
497 maxbit
= max_t(u8
, maxbit
, entry
->bit
);
500 hw
= devm_kzalloc(&pdev
->dev
, struct_size(hw
, data
.hws
, maxbit
),
505 platform_set_drvdata(pdev
, hw
);
507 spin_lock_init(&hw
->lock
);
509 hw
->data
.num
= maxbit
;
510 for (i
= 0; i
< maxbit
; i
++)
511 hw
->data
.hws
[i
] = ERR_PTR(-ENODEV
);
513 hw
->regs
= devm_platform_ioremap_resource(pdev
, 0);
514 if (IS_ERR(hw
->regs
))
515 return PTR_ERR(hw
->regs
);
517 for (entry
= table
; entry
->name
; entry
++) {
520 clk
= clk_hw_register_gate(&pdev
->dev
, entry
->name
, NULL
,
521 entry
->flags
, hw
->regs
, entry
->bit
,
522 CLK_GATE_BIG_ENDIAN
, &hw
->lock
);
528 hw
->data
.hws
[entry
->bit
] = clk
;
531 ret
= of_clk_add_hw_provider(pdev
->dev
.of_node
, of_clk_hw_onecell_get
,
536 for (i
= 0; i
< hw
->data
.num
; i
++) {
537 if (!IS_ERR(hw
->data
.hws
[i
]))
538 clk_hw_unregister_gate(hw
->data
.hws
[i
]);
544 static int clk_bcm63xx_remove(struct platform_device
*pdev
)
546 struct clk_bcm63xx_hw
*hw
= platform_get_drvdata(pdev
);
549 of_clk_del_provider(pdev
->dev
.of_node
);
551 for (i
= 0; i
< hw
->data
.num
; i
++) {
552 if (!IS_ERR(hw
->data
.hws
[i
]))
553 clk_hw_unregister_gate(hw
->data
.hws
[i
]);
559 static const struct of_device_id clk_bcm63xx_dt_ids
[] = {
560 { .compatible
= "brcm,bcm3368-clocks", .data
= &bcm3368_clocks
, },
561 { .compatible
= "brcm,bcm6318-clocks", .data
= &bcm6318_clocks
, },
562 { .compatible
= "brcm,bcm6318-ubus-clocks", .data
= &bcm6318_ubus_clocks
, },
563 { .compatible
= "brcm,bcm6328-clocks", .data
= &bcm6328_clocks
, },
564 { .compatible
= "brcm,bcm6358-clocks", .data
= &bcm6358_clocks
, },
565 { .compatible
= "brcm,bcm6362-clocks", .data
= &bcm6362_clocks
, },
566 { .compatible
= "brcm,bcm6368-clocks", .data
= &bcm6368_clocks
, },
567 { .compatible
= "brcm,bcm63268-clocks", .data
= &bcm63268_clocks
, },
571 static struct platform_driver clk_bcm63xx
= {
572 .probe
= clk_bcm63xx_probe
,
573 .remove
= clk_bcm63xx_remove
,
575 .name
= "bcm63xx-clock",
576 .of_match_table
= clk_bcm63xx_dt_ids
,
579 builtin_platform_driver(clk_bcm63xx
);