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