GNU Linux-libre 6.8.9-gnu
[releases.git] / drivers / clk / bcm / clk-bcm63xx-gate.c
1 // SPDX-License-Identifier: GPL-2.0
2
3 #include <linux/clk-provider.h>
4 #include <linux/init.h>
5 #include <linux/of.h>
6 #include <linux/platform_device.h>
7
8 #include <dt-bindings/clock/bcm3368-clock.h>
9 #include <dt-bindings/clock/bcm6318-clock.h>
10 #include <dt-bindings/clock/bcm6328-clock.h>
11 #include <dt-bindings/clock/bcm6358-clock.h>
12 #include <dt-bindings/clock/bcm6362-clock.h>
13 #include <dt-bindings/clock/bcm6368-clock.h>
14 #include <dt-bindings/clock/bcm63268-clock.h>
15
16 struct clk_bcm63xx_table_entry {
17         const char * const name;
18         u8 bit;
19         unsigned long flags;
20 };
21
22 struct clk_bcm63xx_hw {
23         void __iomem *regs;
24         spinlock_t lock;
25
26         struct clk_hw_onecell_data data;
27 };
28
29 static const struct clk_bcm63xx_table_entry bcm3368_clocks[] = {
30         {
31                 .name = "mac",
32                 .bit = BCM3368_CLK_MAC,
33         }, {
34                 .name = "tc",
35                 .bit = BCM3368_CLK_TC,
36         }, {
37                 .name = "us_top",
38                 .bit = BCM3368_CLK_US_TOP,
39         }, {
40                 .name = "ds_top",
41                 .bit = BCM3368_CLK_DS_TOP,
42         }, {
43                 .name = "acm",
44                 .bit = BCM3368_CLK_ACM,
45         }, {
46                 .name = "spi",
47                 .bit = BCM3368_CLK_SPI,
48         }, {
49                 .name = "usbs",
50                 .bit = BCM3368_CLK_USBS,
51         }, {
52                 .name = "bmu",
53                 .bit = BCM3368_CLK_BMU,
54         }, {
55                 .name = "pcm",
56                 .bit = BCM3368_CLK_PCM,
57         }, {
58                 .name = "ntp",
59                 .bit = BCM3368_CLK_NTP,
60         }, {
61                 .name = "acp_b",
62                 .bit = BCM3368_CLK_ACP_B,
63         }, {
64                 .name = "acp_a",
65                 .bit = BCM3368_CLK_ACP_A,
66         }, {
67                 .name = "emusb",
68                 .bit = BCM3368_CLK_EMUSB,
69         }, {
70                 .name = "enet0",
71                 .bit = BCM3368_CLK_ENET0,
72         }, {
73                 .name = "enet1",
74                 .bit = BCM3368_CLK_ENET1,
75         }, {
76                 .name = "usbsu",
77                 .bit = BCM3368_CLK_USBSU,
78         }, {
79                 .name = "ephy",
80                 .bit = BCM3368_CLK_EPHY,
81         }, {
82                 /* sentinel */
83         },
84 };
85
86 static const struct clk_bcm63xx_table_entry bcm6318_clocks[] = {
87         {
88                 .name = "adsl_asb",
89                 .bit = BCM6318_CLK_ADSL_ASB,
90         }, {
91                 .name = "usb_asb",
92                 .bit = BCM6318_CLK_USB_ASB,
93         }, {
94                 .name = "mips_asb",
95                 .bit = BCM6318_CLK_MIPS_ASB,
96         }, {
97                 .name = "pcie_asb",
98                 .bit = BCM6318_CLK_PCIE_ASB,
99         }, {
100                 .name = "phymips_asb",
101                 .bit = BCM6318_CLK_PHYMIPS_ASB,
102         }, {
103                 .name = "robosw_asb",
104                 .bit = BCM6318_CLK_ROBOSW_ASB,
105         }, {
106                 .name = "sar_asb",
107                 .bit = BCM6318_CLK_SAR_ASB,
108         }, {
109                 .name = "sdr_asb",
110                 .bit = BCM6318_CLK_SDR_ASB,
111         }, {
112                 .name = "swreg_asb",
113                 .bit = BCM6318_CLK_SWREG_ASB,
114         }, {
115                 .name = "periph_asb",
116                 .bit = BCM6318_CLK_PERIPH_ASB,
117         }, {
118                 .name = "cpubus160",
119                 .bit = BCM6318_CLK_CPUBUS160,
120         }, {
121                 .name = "adsl",
122                 .bit = BCM6318_CLK_ADSL,
123         }, {
124                 .name = "sar125",
125                 .bit = BCM6318_CLK_SAR125,
126         }, {
127                 .name = "mips",
128                 .bit = BCM6318_CLK_MIPS,
129                 .flags = CLK_IS_CRITICAL,
130         }, {
131                 .name = "pcie",
132                 .bit = BCM6318_CLK_PCIE,
133         }, {
134                 .name = "robosw250",
135                 .bit = BCM6318_CLK_ROBOSW250,
136         }, {
137                 .name = "robosw025",
138                 .bit = BCM6318_CLK_ROBOSW025,
139         }, {
140                 .name = "sdr",
141                 .bit = BCM6318_CLK_SDR,
142                 .flags = CLK_IS_CRITICAL,
143         }, {
144                 .name = "usbd",
145                 .bit = BCM6318_CLK_USBD,
146         }, {
147                 .name = "hsspi",
148                 .bit = BCM6318_CLK_HSSPI,
149         }, {
150                 .name = "pcie25",
151                 .bit = BCM6318_CLK_PCIE25,
152         }, {
153                 .name = "phymips",
154                 .bit = BCM6318_CLK_PHYMIPS,
155         }, {
156                 .name = "afe",
157                 .bit = BCM6318_CLK_AFE,
158         }, {
159                 .name = "qproc",
160                 .bit = BCM6318_CLK_QPROC,
161         }, {
162                 /* sentinel */
163         },
164 };
165
166 static const struct clk_bcm63xx_table_entry bcm6318_ubus_clocks[] = {
167         {
168                 .name = "adsl-ubus",
169                 .bit = BCM6318_UCLK_ADSL,
170         }, {
171                 .name = "arb-ubus",
172                 .bit = BCM6318_UCLK_ARB,
173                 .flags = CLK_IS_CRITICAL,
174         }, {
175                 .name = "mips-ubus",
176                 .bit = BCM6318_UCLK_MIPS,
177                 .flags = CLK_IS_CRITICAL,
178         }, {
179                 .name = "pcie-ubus",
180                 .bit = BCM6318_UCLK_PCIE,
181         }, {
182                 .name = "periph-ubus",
183                 .bit = BCM6318_UCLK_PERIPH,
184                 .flags = CLK_IS_CRITICAL,
185         }, {
186                 .name = "phymips-ubus",
187                 .bit = BCM6318_UCLK_PHYMIPS,
188         }, {
189                 .name = "robosw-ubus",
190                 .bit = BCM6318_UCLK_ROBOSW,
191         }, {
192                 .name = "sar-ubus",
193                 .bit = BCM6318_UCLK_SAR,
194         }, {
195                 .name = "sdr-ubus",
196                 .bit = BCM6318_UCLK_SDR,
197         }, {
198                 .name = "usb-ubus",
199                 .bit = BCM6318_UCLK_USB,
200         }, {
201                 /* sentinel */
202         },
203 };
204
205 static const struct clk_bcm63xx_table_entry bcm6328_clocks[] = {
206         {
207                 .name = "phy_mips",
208                 .bit = BCM6328_CLK_PHYMIPS,
209         }, {
210                 .name = "adsl_qproc",
211                 .bit = BCM6328_CLK_ADSL_QPROC,
212         }, {
213                 .name = "adsl_afe",
214                 .bit = BCM6328_CLK_ADSL_AFE,
215         }, {
216                 .name = "adsl",
217                 .bit = BCM6328_CLK_ADSL,
218         }, {
219                 .name = "mips",
220                 .bit = BCM6328_CLK_MIPS,
221                 .flags = CLK_IS_CRITICAL,
222         }, {
223                 .name = "sar",
224                 .bit = BCM6328_CLK_SAR,
225         }, {
226                 .name = "pcm",
227                 .bit = BCM6328_CLK_PCM,
228         }, {
229                 .name = "usbd",
230                 .bit = BCM6328_CLK_USBD,
231         }, {
232                 .name = "usbh",
233                 .bit = BCM6328_CLK_USBH,
234         }, {
235                 .name = "hsspi",
236                 .bit = BCM6328_CLK_HSSPI,
237         }, {
238                 .name = "pcie",
239                 .bit = BCM6328_CLK_PCIE,
240         }, {
241                 .name = "robosw",
242                 .bit = BCM6328_CLK_ROBOSW,
243         }, {
244                 /* sentinel */
245         },
246 };
247
248 static const struct clk_bcm63xx_table_entry bcm6358_clocks[] = {
249         {
250                 .name = "enet",
251                 .bit = BCM6358_CLK_ENET,
252         }, {
253                 .name = "adslphy",
254                 .bit = BCM6358_CLK_ADSLPHY,
255         }, {
256                 .name = "pcm",
257                 .bit = BCM6358_CLK_PCM,
258         }, {
259                 .name = "spi",
260                 .bit = BCM6358_CLK_SPI,
261         }, {
262                 .name = "usbs",
263                 .bit = BCM6358_CLK_USBS,
264         }, {
265                 .name = "sar",
266                 .bit = BCM6358_CLK_SAR,
267         }, {
268                 .name = "emusb",
269                 .bit = BCM6358_CLK_EMUSB,
270         }, {
271                 .name = "enet0",
272                 .bit = BCM6358_CLK_ENET0,
273         }, {
274                 .name = "enet1",
275                 .bit = BCM6358_CLK_ENET1,
276         }, {
277                 .name = "usbsu",
278                 .bit = BCM6358_CLK_USBSU,
279         }, {
280                 .name = "ephy",
281                 .bit = BCM6358_CLK_EPHY,
282         }, {
283                 /* sentinel */
284         },
285 };
286
287 static const struct clk_bcm63xx_table_entry bcm6362_clocks[] = {
288         {
289                 .name = "adsl_qproc",
290                 .bit = BCM6362_CLK_ADSL_QPROC,
291         }, {
292                 .name = "adsl_afe",
293                 .bit = BCM6362_CLK_ADSL_AFE,
294         }, {
295                 .name = "adsl",
296                 .bit = BCM6362_CLK_ADSL,
297         }, {
298                 .name = "mips",
299                 .bit = BCM6362_CLK_MIPS,
300                 .flags = CLK_IS_CRITICAL,
301         }, {
302                 .name = "wlan_ocp",
303                 .bit = BCM6362_CLK_WLAN_OCP,
304         }, {
305                 .name = "swpkt_usb",
306                 .bit = BCM6362_CLK_SWPKT_USB,
307         }, {
308                 .name = "swpkt_sar",
309                 .bit = BCM6362_CLK_SWPKT_SAR,
310         }, {
311                 .name = "sar",
312                 .bit = BCM6362_CLK_SAR,
313         }, {
314                 .name = "robosw",
315                 .bit = BCM6362_CLK_ROBOSW,
316         }, {
317                 .name = "pcm",
318                 .bit = BCM6362_CLK_PCM,
319         }, {
320                 .name = "usbd",
321                 .bit = BCM6362_CLK_USBD,
322         }, {
323                 .name = "usbh",
324                 .bit = BCM6362_CLK_USBH,
325         }, {
326                 .name = "ipsec",
327                 .bit = BCM6362_CLK_IPSEC,
328         }, {
329                 .name = "spi",
330                 .bit = BCM6362_CLK_SPI,
331         }, {
332                 .name = "hsspi",
333                 .bit = BCM6362_CLK_HSSPI,
334         }, {
335                 .name = "pcie",
336                 .bit = BCM6362_CLK_PCIE,
337         }, {
338                 .name = "fap",
339                 .bit = BCM6362_CLK_FAP,
340         }, {
341                 .name = "phymips",
342                 .bit = BCM6362_CLK_PHYMIPS,
343         }, {
344                 .name = "nand",
345                 .bit = BCM6362_CLK_NAND,
346         }, {
347                 /* sentinel */
348         },
349 };
350
351 static const struct clk_bcm63xx_table_entry bcm6368_clocks[] = {
352         {
353                 .name = "vdsl_qproc",
354                 .bit = BCM6368_CLK_VDSL_QPROC,
355         }, {
356                 .name = "vdsl_afe",
357                 .bit = BCM6368_CLK_VDSL_AFE,
358         }, {
359                 .name = "vdsl_bonding",
360                 .bit = BCM6368_CLK_VDSL_BONDING,
361         }, {
362                 .name = "vdsl",
363                 .bit = BCM6368_CLK_VDSL,
364         }, {
365                 .name = "phymips",
366                 .bit = BCM6368_CLK_PHYMIPS,
367         }, {
368                 .name = "swpkt_usb",
369                 .bit = BCM6368_CLK_SWPKT_USB,
370         }, {
371                 .name = "swpkt_sar",
372                 .bit = BCM6368_CLK_SWPKT_SAR,
373         }, {
374                 .name = "spi",
375                 .bit = BCM6368_CLK_SPI,
376         }, {
377                 .name = "usbd",
378                 .bit = BCM6368_CLK_USBD,
379         }, {
380                 .name = "sar",
381                 .bit = BCM6368_CLK_SAR,
382         }, {
383                 .name = "robosw",
384                 .bit = BCM6368_CLK_ROBOSW,
385         }, {
386                 .name = "utopia",
387                 .bit = BCM6368_CLK_UTOPIA,
388         }, {
389                 .name = "pcm",
390                 .bit = BCM6368_CLK_PCM,
391         }, {
392                 .name = "usbh",
393                 .bit = BCM6368_CLK_USBH,
394         }, {
395                 .name = "disable_gless",
396                 .bit = BCM6368_CLK_DIS_GLESS,
397         }, {
398                 .name = "nand",
399                 .bit = BCM6368_CLK_NAND,
400         }, {
401                 .name = "ipsec",
402                 .bit = BCM6368_CLK_IPSEC,
403         }, {
404                 /* sentinel */
405         },
406 };
407
408 static const struct clk_bcm63xx_table_entry bcm63268_clocks[] = {
409         {
410                 .name = "disable_gless",
411                 .bit = BCM63268_CLK_DIS_GLESS,
412         }, {
413                 .name = "vdsl_qproc",
414                 .bit = BCM63268_CLK_VDSL_QPROC,
415         }, {
416                 .name = "vdsl_afe",
417                 .bit = BCM63268_CLK_VDSL_AFE,
418         }, {
419                 .name = "vdsl",
420                 .bit = BCM63268_CLK_VDSL,
421         }, {
422                 .name = "mips",
423                 .bit = BCM63268_CLK_MIPS,
424                 .flags = CLK_IS_CRITICAL,
425         }, {
426                 .name = "wlan_ocp",
427                 .bit = BCM63268_CLK_WLAN_OCP,
428         }, {
429                 .name = "dect",
430                 .bit = BCM63268_CLK_DECT,
431         }, {
432                 .name = "fap0",
433                 .bit = BCM63268_CLK_FAP0,
434         }, {
435                 .name = "fap1",
436                 .bit = BCM63268_CLK_FAP1,
437         }, {
438                 .name = "sar",
439                 .bit = BCM63268_CLK_SAR,
440         }, {
441                 .name = "robosw",
442                 .bit = BCM63268_CLK_ROBOSW,
443         }, {
444                 .name = "pcm",
445                 .bit = BCM63268_CLK_PCM,
446         }, {
447                 .name = "usbd",
448                 .bit = BCM63268_CLK_USBD,
449         }, {
450                 .name = "usbh",
451                 .bit = BCM63268_CLK_USBH,
452         }, {
453                 .name = "ipsec",
454                 .bit = BCM63268_CLK_IPSEC,
455         }, {
456                 .name = "spi",
457                 .bit = BCM63268_CLK_SPI,
458         }, {
459                 .name = "hsspi",
460                 .bit = BCM63268_CLK_HSSPI,
461         }, {
462                 .name = "pcie",
463                 .bit = BCM63268_CLK_PCIE,
464         }, {
465                 .name = "phymips",
466                 .bit = BCM63268_CLK_PHYMIPS,
467         }, {
468                 .name = "gmac",
469                 .bit = BCM63268_CLK_GMAC,
470         }, {
471                 .name = "nand",
472                 .bit = BCM63268_CLK_NAND,
473         }, {
474                 .name = "tbus",
475                 .bit = BCM63268_CLK_TBUS,
476         }, {
477                 .name = "robosw250",
478                 .bit = BCM63268_CLK_ROBOSW250,
479         }, {
480                 /* sentinel */
481         },
482 };
483
484 static int clk_bcm63xx_probe(struct platform_device *pdev)
485 {
486         const struct clk_bcm63xx_table_entry *entry, *table;
487         struct clk_bcm63xx_hw *hw;
488         u8 maxbit = 0;
489         int i, ret;
490
491         table = of_device_get_match_data(&pdev->dev);
492         if (!table)
493                 return -EINVAL;
494
495         for (entry = table; entry->name; entry++)
496                 maxbit = max_t(u8, maxbit, entry->bit);
497         maxbit++;
498
499         hw = devm_kzalloc(&pdev->dev, struct_size(hw, data.hws, maxbit),
500                           GFP_KERNEL);
501         if (!hw)
502                 return -ENOMEM;
503
504         platform_set_drvdata(pdev, hw);
505
506         spin_lock_init(&hw->lock);
507
508         hw->data.num = maxbit;
509         for (i = 0; i < maxbit; i++)
510                 hw->data.hws[i] = ERR_PTR(-ENODEV);
511
512         hw->regs = devm_platform_ioremap_resource(pdev, 0);
513         if (IS_ERR(hw->regs))
514                 return PTR_ERR(hw->regs);
515
516         for (entry = table; entry->name; entry++) {
517                 struct clk_hw *clk;
518
519                 clk = clk_hw_register_gate(&pdev->dev, entry->name, NULL,
520                                            entry->flags, hw->regs, entry->bit,
521                                            CLK_GATE_BIG_ENDIAN, &hw->lock);
522                 if (IS_ERR(clk)) {
523                         ret = PTR_ERR(clk);
524                         goto out_err;
525                 }
526
527                 hw->data.hws[entry->bit] = clk;
528         }
529
530         ret = of_clk_add_hw_provider(pdev->dev.of_node, of_clk_hw_onecell_get,
531                                      &hw->data);
532         if (!ret)
533                 return 0;
534 out_err:
535         for (i = 0; i < hw->data.num; i++) {
536                 if (!IS_ERR(hw->data.hws[i]))
537                         clk_hw_unregister_gate(hw->data.hws[i]);
538         }
539
540         return ret;
541 }
542
543 static void clk_bcm63xx_remove(struct platform_device *pdev)
544 {
545         struct clk_bcm63xx_hw *hw = platform_get_drvdata(pdev);
546         int i;
547
548         of_clk_del_provider(pdev->dev.of_node);
549
550         for (i = 0; i < hw->data.num; i++) {
551                 if (!IS_ERR(hw->data.hws[i]))
552                         clk_hw_unregister_gate(hw->data.hws[i]);
553         }
554 }
555
556 static const struct of_device_id clk_bcm63xx_dt_ids[] = {
557         { .compatible = "brcm,bcm3368-clocks", .data = &bcm3368_clocks, },
558         { .compatible = "brcm,bcm6318-clocks", .data = &bcm6318_clocks, },
559         { .compatible = "brcm,bcm6318-ubus-clocks", .data = &bcm6318_ubus_clocks, },
560         { .compatible = "brcm,bcm6328-clocks", .data = &bcm6328_clocks, },
561         { .compatible = "brcm,bcm6358-clocks", .data = &bcm6358_clocks, },
562         { .compatible = "brcm,bcm6362-clocks", .data = &bcm6362_clocks, },
563         { .compatible = "brcm,bcm6368-clocks", .data = &bcm6368_clocks, },
564         { .compatible = "brcm,bcm63268-clocks", .data = &bcm63268_clocks, },
565         { }
566 };
567
568 static struct platform_driver clk_bcm63xx = {
569         .probe = clk_bcm63xx_probe,
570         .remove_new = clk_bcm63xx_remove,
571         .driver = {
572                 .name = "bcm63xx-clock",
573                 .of_match_table = clk_bcm63xx_dt_ids,
574         },
575 };
576 builtin_platform_driver(clk_bcm63xx);