Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/drivers/clk/bcm/clk-bcm63xx-gate.c
26282 views
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 = 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);
577
578