hc
2024-12-19 9370bb92b2d16684ee45cf24e879c93c509162da
kernel/drivers/phy/broadcom/phy-brcm-usb.c
....@@ -1,16 +1,8 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * phy-brcm-usb.c - Broadcom USB Phy Driver
34 *
45 * Copyright (C) 2015-2017 Broadcom
5
- *
6
- * This software is licensed under the terms of the GNU General Public
7
- * License version 2, as published by the Free Software Foundation, and
8
- * may be copied, distributed, and modified under those terms.
9
- *
10
- * This program is distributed in the hope that it will be useful,
11
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- * GNU General Public License for more details.
146 */
157
168 #include <linux/clk.h>
....@@ -24,6 +16,8 @@
2416 #include <linux/interrupt.h>
2517 #include <linux/soc/brcmstb/brcmstb.h>
2618 #include <dt-bindings/phy/phy.h>
19
+#include <linux/mfd/syscon.h>
20
+#include <linux/suspend.h>
2721
2822 #include "phy-brcm-usb-init.h"
2923
....@@ -40,14 +34,20 @@
4034 const char *name;
4135 };
4236
43
-static struct value_to_name_map brcm_dr_mode_to_name[] = {
37
+struct match_chip_info {
38
+ void *init_func;
39
+ u8 required_regs[BRCM_REGS_MAX + 1];
40
+ u8 optional_reg;
41
+};
42
+
43
+static const struct value_to_name_map brcm_dr_mode_to_name[] = {
4444 { USB_CTLR_MODE_HOST, "host" },
4545 { USB_CTLR_MODE_DEVICE, "peripheral" },
4646 { USB_CTLR_MODE_DRD, "drd" },
4747 { USB_CTLR_MODE_TYPEC_PD, "typec-pd" }
4848 };
4949
50
-static struct value_to_name_map brcm_dual_mode_to_name[] = {
50
+static const struct value_to_name_map brcm_dual_mode_to_name[] = {
5151 { 0, "host" },
5252 { 1, "device" },
5353 { 2, "auto" },
....@@ -65,10 +65,48 @@
6565 bool has_xhci;
6666 struct clk *usb_20_clk;
6767 struct clk *usb_30_clk;
68
+ struct clk *suspend_clk;
6869 struct mutex mutex; /* serialize phy init */
6970 int init_count;
71
+ int wake_irq;
7072 struct brcm_usb_phy phys[BRCM_USB_PHY_ID_MAX];
73
+ struct notifier_block pm_notifier;
74
+ bool pm_active;
7175 };
76
+
77
+static s8 *node_reg_names[BRCM_REGS_MAX] = {
78
+ "crtl", "xhci_ec", "xhci_gbl", "usb_phy", "usb_mdio", "bdc_ec"
79
+};
80
+
81
+static int brcm_pm_notifier(struct notifier_block *notifier,
82
+ unsigned long pm_event,
83
+ void *unused)
84
+{
85
+ struct brcm_usb_phy_data *priv =
86
+ container_of(notifier, struct brcm_usb_phy_data, pm_notifier);
87
+
88
+ switch (pm_event) {
89
+ case PM_HIBERNATION_PREPARE:
90
+ case PM_SUSPEND_PREPARE:
91
+ priv->pm_active = true;
92
+ break;
93
+ case PM_POST_RESTORE:
94
+ case PM_POST_HIBERNATION:
95
+ case PM_POST_SUSPEND:
96
+ priv->pm_active = false;
97
+ break;
98
+ }
99
+ return NOTIFY_DONE;
100
+}
101
+
102
+static irqreturn_t brcm_usb_phy_wake_isr(int irq, void *dev_id)
103
+{
104
+ struct device *dev = dev_id;
105
+
106
+ pm_wakeup_event(dev, 0);
107
+
108
+ return IRQ_HANDLED;
109
+}
72110
73111 static int brcm_usb_phy_init(struct phy *gphy)
74112 {
....@@ -76,14 +114,18 @@
76114 struct brcm_usb_phy_data *priv =
77115 container_of(phy, struct brcm_usb_phy_data, phys[phy->id]);
78116
117
+ if (priv->pm_active)
118
+ return 0;
119
+
79120 /*
80121 * Use a lock to make sure a second caller waits until
81122 * the base phy is inited before using it.
82123 */
83124 mutex_lock(&priv->mutex);
84125 if (priv->init_count++ == 0) {
85
- clk_enable(priv->usb_20_clk);
86
- clk_enable(priv->usb_30_clk);
126
+ clk_prepare_enable(priv->usb_20_clk);
127
+ clk_prepare_enable(priv->usb_30_clk);
128
+ clk_prepare_enable(priv->suspend_clk);
87129 brcm_usb_init_common(&priv->ini);
88130 }
89131 mutex_unlock(&priv->mutex);
....@@ -104,6 +146,9 @@
104146 struct brcm_usb_phy_data *priv =
105147 container_of(phy, struct brcm_usb_phy_data, phys[phy->id]);
106148
149
+ if (priv->pm_active)
150
+ return 0;
151
+
107152 dev_dbg(&gphy->dev, "EXIT\n");
108153 if (phy->id == BRCM_USB_PHY_2_0)
109154 brcm_usb_uninit_eohci(&priv->ini);
....@@ -114,15 +159,16 @@
114159 mutex_lock(&priv->mutex);
115160 if (--priv->init_count == 0) {
116161 brcm_usb_uninit_common(&priv->ini);
117
- clk_disable(priv->usb_20_clk);
118
- clk_disable(priv->usb_30_clk);
162
+ clk_disable_unprepare(priv->usb_20_clk);
163
+ clk_disable_unprepare(priv->usb_30_clk);
164
+ clk_disable_unprepare(priv->suspend_clk);
119165 }
120166 mutex_unlock(&priv->mutex);
121167 phy->inited = false;
122168 return 0;
123169 }
124170
125
-static struct phy_ops brcm_usb_phy_ops = {
171
+static const struct phy_ops brcm_usb_phy_ops = {
126172 .init = brcm_usb_phy_init,
127173 .exit = brcm_usb_phy_exit,
128174 .owner = THIS_MODULE,
....@@ -154,7 +200,7 @@
154200 return ERR_PTR(-ENODEV);
155201 }
156202
157
-static int name_to_value(struct value_to_name_map *table, int count,
203
+static int name_to_value(const struct value_to_name_map *table, int count,
158204 const char *name, int *value)
159205 {
160206 int x;
....@@ -169,7 +215,7 @@
169215 return -EINVAL;
170216 }
171217
172
-static const char *value_to_name(struct value_to_name_map *table, int count,
218
+static const char *value_to_name(const struct value_to_name_map *table, int count,
173219 int value)
174220 {
175221 if (value >= count)
....@@ -202,7 +248,7 @@
202248 res = name_to_value(&brcm_dual_mode_to_name[0],
203249 ARRAY_SIZE(brcm_dual_mode_to_name), buf, &value);
204250 if (!res) {
205
- brcm_usb_init_set_dual_select(&priv->ini, value);
251
+ brcm_usb_set_dual_select(&priv->ini, value);
206252 res = len;
207253 }
208254 mutex_unlock(&sysfs_lock);
....@@ -217,7 +263,7 @@
217263 int value;
218264
219265 mutex_lock(&sysfs_lock);
220
- value = brcm_usb_init_get_dual_select(&priv->ini);
266
+ value = brcm_usb_get_dual_select(&priv->ini);
221267 mutex_unlock(&sysfs_lock);
222268 return sprintf(buf, "%s\n",
223269 value_to_name(&brcm_dual_mode_to_name[0],
....@@ -236,15 +282,106 @@
236282 .attrs = brcm_usb_phy_attrs,
237283 };
238284
239
-static int brcm_usb_phy_dvr_init(struct device *dev,
285
+static const struct match_chip_info chip_info_7216 = {
286
+ .init_func = &brcm_usb_dvr_init_7216,
287
+ .required_regs = {
288
+ BRCM_REGS_CTRL,
289
+ BRCM_REGS_XHCI_EC,
290
+ BRCM_REGS_XHCI_GBL,
291
+ -1,
292
+ },
293
+};
294
+
295
+static const struct match_chip_info chip_info_7211b0 = {
296
+ .init_func = &brcm_usb_dvr_init_7211b0,
297
+ .required_regs = {
298
+ BRCM_REGS_CTRL,
299
+ BRCM_REGS_XHCI_EC,
300
+ BRCM_REGS_XHCI_GBL,
301
+ BRCM_REGS_USB_PHY,
302
+ BRCM_REGS_USB_MDIO,
303
+ -1,
304
+ },
305
+ .optional_reg = BRCM_REGS_BDC_EC,
306
+};
307
+
308
+static const struct match_chip_info chip_info_7445 = {
309
+ .init_func = &brcm_usb_dvr_init_7445,
310
+ .required_regs = {
311
+ BRCM_REGS_CTRL,
312
+ BRCM_REGS_XHCI_EC,
313
+ -1,
314
+ },
315
+};
316
+
317
+static const struct of_device_id brcm_usb_dt_ids[] = {
318
+ {
319
+ .compatible = "brcm,bcm7216-usb-phy",
320
+ .data = &chip_info_7216,
321
+ },
322
+ {
323
+ .compatible = "brcm,bcm7211-usb-phy",
324
+ .data = &chip_info_7211b0,
325
+ },
326
+ {
327
+ .compatible = "brcm,brcmstb-usb-phy",
328
+ .data = &chip_info_7445,
329
+ },
330
+ { /* sentinel */ }
331
+};
332
+
333
+static int brcm_usb_get_regs(struct platform_device *pdev,
334
+ enum brcmusb_reg_sel regs,
335
+ struct brcm_usb_init_params *ini,
336
+ bool optional)
337
+{
338
+ struct resource *res;
339
+
340
+ /* Older DT nodes have ctrl and optional xhci_ec by index only */
341
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
342
+ node_reg_names[regs]);
343
+ if (res == NULL) {
344
+ if (regs == BRCM_REGS_CTRL) {
345
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
346
+ } else if (regs == BRCM_REGS_XHCI_EC) {
347
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
348
+ /* XHCI_EC registers are optional */
349
+ if (res == NULL)
350
+ return 0;
351
+ }
352
+ if (res == NULL) {
353
+ if (optional) {
354
+ dev_dbg(&pdev->dev,
355
+ "Optional reg %s not found\n",
356
+ node_reg_names[regs]);
357
+ return 0;
358
+ }
359
+ dev_err(&pdev->dev, "can't get %s base addr\n",
360
+ node_reg_names[regs]);
361
+ return 1;
362
+ }
363
+ }
364
+ ini->regs[regs] = devm_ioremap_resource(&pdev->dev, res);
365
+ if (IS_ERR(ini->regs[regs])) {
366
+ dev_err(&pdev->dev, "can't map %s register space\n",
367
+ node_reg_names[regs]);
368
+ return 1;
369
+ }
370
+ return 0;
371
+}
372
+
373
+static int brcm_usb_phy_dvr_init(struct platform_device *pdev,
240374 struct brcm_usb_phy_data *priv,
241375 struct device_node *dn)
242376 {
243
- struct phy *gphy;
377
+ struct device *dev = &pdev->dev;
378
+ struct phy *gphy = NULL;
244379 int err;
245380
246381 priv->usb_20_clk = of_clk_get_by_name(dn, "sw_usb");
247382 if (IS_ERR(priv->usb_20_clk)) {
383
+ if (PTR_ERR(priv->usb_20_clk) == -EPROBE_DEFER)
384
+ return -EPROBE_DEFER;
248385 dev_info(dev, "Clock not found in Device Tree\n");
249386 priv->usb_20_clk = NULL;
250387 }
....@@ -275,6 +412,8 @@
275412
276413 priv->usb_30_clk = of_clk_get_by_name(dn, "sw_usb3");
277414 if (IS_ERR(priv->usb_30_clk)) {
415
+ if (PTR_ERR(priv->usb_30_clk) == -EPROBE_DEFER)
416
+ return -EPROBE_DEFER;
278417 dev_info(dev,
279418 "USB3.0 clock not found in Device Tree\n");
280419 priv->usb_30_clk = NULL;
....@@ -283,18 +422,46 @@
283422 if (err)
284423 return err;
285424 }
425
+
426
+ priv->suspend_clk = clk_get(dev, "usb0_freerun");
427
+ if (IS_ERR(priv->suspend_clk)) {
428
+ if (PTR_ERR(priv->suspend_clk) == -EPROBE_DEFER)
429
+ return -EPROBE_DEFER;
430
+ dev_err(dev, "Suspend Clock not found in Device Tree\n");
431
+ priv->suspend_clk = NULL;
432
+ }
433
+
434
+ priv->wake_irq = platform_get_irq_byname(pdev, "wake");
435
+ if (priv->wake_irq < 0)
436
+ priv->wake_irq = platform_get_irq_byname(pdev, "wakeup");
437
+ if (priv->wake_irq >= 0) {
438
+ err = devm_request_irq(dev, priv->wake_irq,
439
+ brcm_usb_phy_wake_isr, 0,
440
+ dev_name(dev), dev);
441
+ if (err < 0)
442
+ return err;
443
+ device_set_wakeup_capable(dev, 1);
444
+ } else {
445
+ dev_info(dev,
446
+ "Wake interrupt missing, system wake not supported\n");
447
+ }
448
+
286449 return 0;
287450 }
288451
289452 static int brcm_usb_phy_probe(struct platform_device *pdev)
290453 {
291
- struct resource *res;
292454 struct device *dev = &pdev->dev;
293455 struct brcm_usb_phy_data *priv;
294456 struct phy_provider *phy_provider;
295457 struct device_node *dn = pdev->dev.of_node;
296458 int err;
297459 const char *mode;
460
+ const struct of_device_id *match;
461
+ void (*dvr_init)(struct brcm_usb_init_params *params);
462
+ const struct match_chip_info *info;
463
+ struct regmap *rmap;
464
+ int x;
298465
299466 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
300467 if (!priv)
....@@ -303,30 +470,14 @@
303470
304471 priv->ini.family_id = brcmstb_get_family_id();
305472 priv->ini.product_id = brcmstb_get_product_id();
306
- brcm_usb_set_family_map(&priv->ini);
473
+
474
+ match = of_match_node(brcm_usb_dt_ids, dev->of_node);
475
+ info = match->data;
476
+ dvr_init = info->init_func;
477
+ (*dvr_init)(&priv->ini);
478
+
307479 dev_dbg(dev, "Best mapping table is for %s\n",
308480 priv->ini.family_name);
309
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
310
- if (!res) {
311
- dev_err(dev, "can't get USB_CTRL base address\n");
312
- return -EINVAL;
313
- }
314
- priv->ini.ctrl_regs = devm_ioremap_resource(dev, res);
315
- if (IS_ERR(priv->ini.ctrl_regs)) {
316
- dev_err(dev, "can't map CTRL register space\n");
317
- return -EINVAL;
318
- }
319
-
320
- /* The XHCI EC registers are optional */
321
- res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
322
- if (res) {
323
- priv->ini.xhci_ec_regs =
324
- devm_ioremap_resource(dev, res);
325
- if (IS_ERR(priv->ini.xhci_ec_regs)) {
326
- dev_err(dev, "can't map XHCI EC register space\n");
327
- return -EINVAL;
328
- }
329
- }
330481
331482 of_property_read_u32(dn, "brcm,ipp", &priv->ini.ipp);
332483 of_property_read_u32(dn, "brcm,ioc", &priv->ini.ioc);
....@@ -343,9 +494,28 @@
343494 if (of_property_read_bool(dn, "brcm,has-eohci"))
344495 priv->has_eohci = true;
345496
346
- err = brcm_usb_phy_dvr_init(dev, priv, dn);
497
+ for (x = 0; x < BRCM_REGS_MAX; x++) {
498
+ if (info->required_regs[x] >= BRCM_REGS_MAX)
499
+ break;
500
+
501
+ err = brcm_usb_get_regs(pdev, info->required_regs[x],
502
+ &priv->ini, false);
503
+ if (err)
504
+ return -EINVAL;
505
+ }
506
+ if (info->optional_reg) {
507
+ err = brcm_usb_get_regs(pdev, info->optional_reg,
508
+ &priv->ini, true);
509
+ if (err)
510
+ return -EINVAL;
511
+ }
512
+
513
+ err = brcm_usb_phy_dvr_init(pdev, priv, dn);
347514 if (err)
348515 return err;
516
+
517
+ priv->pm_notifier.notifier_call = brcm_pm_notifier;
518
+ register_pm_notifier(&priv->pm_notifier);
349519
350520 mutex_init(&priv->mutex);
351521
....@@ -362,25 +532,35 @@
362532 if (err)
363533 dev_warn(dev, "Error creating sysfs attributes\n");
364534
535
+ /* Get piarbctl syscon if it exists */
536
+ rmap = syscon_regmap_lookup_by_phandle(dev->of_node,
537
+ "syscon-piarbctl");
538
+ if (IS_ERR(rmap))
539
+ rmap = syscon_regmap_lookup_by_phandle(dev->of_node,
540
+ "brcm,syscon-piarbctl");
541
+ if (!IS_ERR(rmap))
542
+ priv->ini.syscon_piarbctl = rmap;
543
+
365544 /* start with everything off */
366545 if (priv->has_xhci)
367546 brcm_usb_uninit_xhci(&priv->ini);
368547 if (priv->has_eohci)
369548 brcm_usb_uninit_eohci(&priv->ini);
370549 brcm_usb_uninit_common(&priv->ini);
371
- clk_disable(priv->usb_20_clk);
372
- clk_disable(priv->usb_30_clk);
550
+ clk_disable_unprepare(priv->usb_20_clk);
551
+ clk_disable_unprepare(priv->usb_30_clk);
373552
374553 phy_provider = devm_of_phy_provider_register(dev, brcm_usb_phy_xlate);
375
- if (IS_ERR(phy_provider))
376
- return PTR_ERR(phy_provider);
377554
378
- return 0;
555
+ return PTR_ERR_OR_ZERO(phy_provider);
379556 }
380557
381558 static int brcm_usb_phy_remove(struct platform_device *pdev)
382559 {
560
+ struct brcm_usb_phy_data *priv = dev_get_drvdata(&pdev->dev);
561
+
383562 sysfs_remove_group(&pdev->dev.kobj, &brcm_usb_phy_group);
563
+ unregister_pm_notifier(&priv->pm_notifier);
384564
385565 return 0;
386566 }
....@@ -391,8 +571,29 @@
391571 struct brcm_usb_phy_data *priv = dev_get_drvdata(dev);
392572
393573 if (priv->init_count) {
394
- clk_disable(priv->usb_20_clk);
395
- clk_disable(priv->usb_30_clk);
574
+ dev_dbg(dev, "SUSPEND\n");
575
+ priv->ini.wake_enabled = device_may_wakeup(dev);
576
+ if (priv->phys[BRCM_USB_PHY_3_0].inited)
577
+ brcm_usb_uninit_xhci(&priv->ini);
578
+ if (priv->phys[BRCM_USB_PHY_2_0].inited)
579
+ brcm_usb_uninit_eohci(&priv->ini);
580
+ brcm_usb_uninit_common(&priv->ini);
581
+
582
+ /*
583
+ * Handle the clocks unless needed for wake. This has
584
+ * to work for both older XHCI->3.0-clks, EOHCI->2.0-clks
585
+ * and newer XHCI->2.0-clks/3.0-clks.
586
+ */
587
+
588
+ if (!priv->ini.suspend_with_clocks) {
589
+ if (priv->phys[BRCM_USB_PHY_3_0].inited)
590
+ clk_disable_unprepare(priv->usb_30_clk);
591
+ if (priv->phys[BRCM_USB_PHY_2_0].inited ||
592
+ !priv->has_eohci)
593
+ clk_disable_unprepare(priv->usb_20_clk);
594
+ }
595
+ if (priv->wake_irq >= 0)
596
+ enable_irq_wake(priv->wake_irq);
396597 }
397598 return 0;
398599 }
....@@ -401,8 +602,8 @@
401602 {
402603 struct brcm_usb_phy_data *priv = dev_get_drvdata(dev);
403604
404
- clk_enable(priv->usb_20_clk);
405
- clk_enable(priv->usb_30_clk);
605
+ clk_prepare_enable(priv->usb_20_clk);
606
+ clk_prepare_enable(priv->usb_30_clk);
406607 brcm_usb_init_ipp(&priv->ini);
407608
408609 /*
....@@ -410,18 +611,23 @@
410611 * Uninitialize anything that wasn't previously initialized.
411612 */
412613 if (priv->init_count) {
614
+ dev_dbg(dev, "RESUME\n");
615
+ if (priv->wake_irq >= 0)
616
+ disable_irq_wake(priv->wake_irq);
413617 brcm_usb_init_common(&priv->ini);
414618 if (priv->phys[BRCM_USB_PHY_2_0].inited) {
415619 brcm_usb_init_eohci(&priv->ini);
416620 } else if (priv->has_eohci) {
417621 brcm_usb_uninit_eohci(&priv->ini);
418
- clk_disable(priv->usb_20_clk);
622
+ clk_disable_unprepare(priv->usb_20_clk);
419623 }
420624 if (priv->phys[BRCM_USB_PHY_3_0].inited) {
421625 brcm_usb_init_xhci(&priv->ini);
422626 } else if (priv->has_xhci) {
423627 brcm_usb_uninit_xhci(&priv->ini);
424
- clk_disable(priv->usb_30_clk);
628
+ clk_disable_unprepare(priv->usb_30_clk);
629
+ if (!priv->has_eohci)
630
+ clk_disable_unprepare(priv->usb_20_clk);
425631 }
426632 } else {
427633 if (priv->has_xhci)
....@@ -429,21 +635,16 @@
429635 if (priv->has_eohci)
430636 brcm_usb_uninit_eohci(&priv->ini);
431637 brcm_usb_uninit_common(&priv->ini);
432
- clk_disable(priv->usb_20_clk);
433
- clk_disable(priv->usb_30_clk);
638
+ clk_disable_unprepare(priv->usb_20_clk);
639
+ clk_disable_unprepare(priv->usb_30_clk);
434640 }
435
-
641
+ priv->ini.wake_enabled = false;
436642 return 0;
437643 }
438644 #endif /* CONFIG_PM_SLEEP */
439645
440646 static const struct dev_pm_ops brcm_usb_phy_pm_ops = {
441647 SET_LATE_SYSTEM_SLEEP_PM_OPS(brcm_usb_phy_suspend, brcm_usb_phy_resume)
442
-};
443
-
444
-static const struct of_device_id brcm_usb_dt_ids[] = {
445
- { .compatible = "brcm,brcmstb-usb-phy" },
446
- { /* sentinel */ }
447648 };
448649
449650 MODULE_DEVICE_TABLE(of, brcm_usb_dt_ids);
....@@ -453,7 +654,6 @@
453654 .remove = brcm_usb_phy_remove,
454655 .driver = {
455656 .name = "brcmstb-usb-phy",
456
- .owner = THIS_MODULE,
457657 .pm = &brcm_usb_phy_pm_ops,
458658 .of_match_table = brcm_usb_dt_ids,
459659 },