Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * phy-brcm-usb.c - Broadcom USB Phy Driver
0004  *
0005  * Copyright (C) 2015-2017 Broadcom
0006  */
0007 
0008 #include <linux/clk.h>
0009 #include <linux/delay.h>
0010 #include <linux/err.h>
0011 #include <linux/io.h>
0012 #include <linux/module.h>
0013 #include <linux/of.h>
0014 #include <linux/of_device.h>
0015 #include <linux/phy/phy.h>
0016 #include <linux/platform_device.h>
0017 #include <linux/interrupt.h>
0018 #include <linux/soc/brcmstb/brcmstb.h>
0019 #include <dt-bindings/phy/phy.h>
0020 #include <linux/mfd/syscon.h>
0021 #include <linux/suspend.h>
0022 
0023 #include "phy-brcm-usb-init.h"
0024 
0025 static DEFINE_MUTEX(sysfs_lock);
0026 
0027 enum brcm_usb_phy_id {
0028     BRCM_USB_PHY_2_0 = 0,
0029     BRCM_USB_PHY_3_0,
0030     BRCM_USB_PHY_ID_MAX
0031 };
0032 
0033 struct value_to_name_map {
0034     int value;
0035     const char *name;
0036 };
0037 
0038 struct match_chip_info {
0039     void (*init_func)(struct brcm_usb_init_params *params);
0040     u8 required_regs[BRCM_REGS_MAX + 1];
0041     u8 optional_reg;
0042 };
0043 
0044 static const struct value_to_name_map brcm_dr_mode_to_name[] = {
0045     { USB_CTLR_MODE_HOST, "host" },
0046     { USB_CTLR_MODE_DEVICE, "peripheral" },
0047     { USB_CTLR_MODE_DRD, "drd" },
0048     { USB_CTLR_MODE_TYPEC_PD, "typec-pd" }
0049 };
0050 
0051 static const struct value_to_name_map brcm_dual_mode_to_name[] = {
0052     { 0, "host" },
0053     { 1, "device" },
0054     { 2, "auto" },
0055 };
0056 
0057 struct brcm_usb_phy {
0058     struct phy *phy;
0059     unsigned int id;
0060     bool inited;
0061 };
0062 
0063 struct brcm_usb_phy_data {
0064     struct  brcm_usb_init_params ini;
0065     bool            has_eohci;
0066     bool            has_xhci;
0067     struct clk      *usb_20_clk;
0068     struct clk      *usb_30_clk;
0069     struct clk      *suspend_clk;
0070     struct mutex        mutex;  /* serialize phy init */
0071     int         init_count;
0072     int         wake_irq;
0073     struct brcm_usb_phy phys[BRCM_USB_PHY_ID_MAX];
0074     struct notifier_block   pm_notifier;
0075     bool            pm_active;
0076 };
0077 
0078 static s8 *node_reg_names[BRCM_REGS_MAX] = {
0079     "crtl", "xhci_ec", "xhci_gbl", "usb_phy", "usb_mdio", "bdc_ec"
0080 };
0081 
0082 static int brcm_pm_notifier(struct notifier_block *notifier,
0083                 unsigned long pm_event,
0084                 void *unused)
0085 {
0086     struct brcm_usb_phy_data *priv =
0087         container_of(notifier, struct brcm_usb_phy_data, pm_notifier);
0088 
0089     switch (pm_event) {
0090     case PM_HIBERNATION_PREPARE:
0091     case PM_SUSPEND_PREPARE:
0092         priv->pm_active = true;
0093         break;
0094     case PM_POST_RESTORE:
0095     case PM_POST_HIBERNATION:
0096     case PM_POST_SUSPEND:
0097         priv->pm_active = false;
0098         break;
0099     }
0100     return NOTIFY_DONE;
0101 }
0102 
0103 static irqreturn_t brcm_usb_phy_wake_isr(int irq, void *dev_id)
0104 {
0105     struct phy *gphy = dev_id;
0106 
0107     pm_wakeup_event(&gphy->dev, 0);
0108 
0109     return IRQ_HANDLED;
0110 }
0111 
0112 static int brcm_usb_phy_init(struct phy *gphy)
0113 {
0114     struct brcm_usb_phy *phy = phy_get_drvdata(gphy);
0115     struct brcm_usb_phy_data *priv =
0116         container_of(phy, struct brcm_usb_phy_data, phys[phy->id]);
0117 
0118     if (priv->pm_active)
0119         return 0;
0120 
0121     /*
0122      * Use a lock to make sure a second caller waits until
0123      * the base phy is inited before using it.
0124      */
0125     mutex_lock(&priv->mutex);
0126     if (priv->init_count++ == 0) {
0127         clk_prepare_enable(priv->usb_20_clk);
0128         clk_prepare_enable(priv->usb_30_clk);
0129         clk_prepare_enable(priv->suspend_clk);
0130         brcm_usb_init_common(&priv->ini);
0131     }
0132     mutex_unlock(&priv->mutex);
0133     if (phy->id == BRCM_USB_PHY_2_0)
0134         brcm_usb_init_eohci(&priv->ini);
0135     else if (phy->id == BRCM_USB_PHY_3_0)
0136         brcm_usb_init_xhci(&priv->ini);
0137     phy->inited = true;
0138     dev_dbg(&gphy->dev, "INIT, id: %d, total: %d\n", phy->id,
0139         priv->init_count);
0140 
0141     return 0;
0142 }
0143 
0144 static int brcm_usb_phy_exit(struct phy *gphy)
0145 {
0146     struct brcm_usb_phy *phy = phy_get_drvdata(gphy);
0147     struct brcm_usb_phy_data *priv =
0148         container_of(phy, struct brcm_usb_phy_data, phys[phy->id]);
0149 
0150     if (priv->pm_active)
0151         return 0;
0152 
0153     dev_dbg(&gphy->dev, "EXIT\n");
0154     if (phy->id == BRCM_USB_PHY_2_0)
0155         brcm_usb_uninit_eohci(&priv->ini);
0156     if (phy->id == BRCM_USB_PHY_3_0)
0157         brcm_usb_uninit_xhci(&priv->ini);
0158 
0159     /* If both xhci and eohci are gone, reset everything else */
0160     mutex_lock(&priv->mutex);
0161     if (--priv->init_count == 0) {
0162         brcm_usb_uninit_common(&priv->ini);
0163         clk_disable_unprepare(priv->usb_20_clk);
0164         clk_disable_unprepare(priv->usb_30_clk);
0165         clk_disable_unprepare(priv->suspend_clk);
0166     }
0167     mutex_unlock(&priv->mutex);
0168     phy->inited = false;
0169     return 0;
0170 }
0171 
0172 static const struct phy_ops brcm_usb_phy_ops = {
0173     .init       = brcm_usb_phy_init,
0174     .exit       = brcm_usb_phy_exit,
0175     .owner      = THIS_MODULE,
0176 };
0177 
0178 static struct phy *brcm_usb_phy_xlate(struct device *dev,
0179                       struct of_phandle_args *args)
0180 {
0181     struct brcm_usb_phy_data *data = dev_get_drvdata(dev);
0182 
0183     /*
0184      * values 0 and 1 are for backward compatibility with
0185      * device tree nodes from older bootloaders.
0186      */
0187     switch (args->args[0]) {
0188     case 0:
0189     case PHY_TYPE_USB2:
0190         if (data->phys[BRCM_USB_PHY_2_0].phy)
0191             return data->phys[BRCM_USB_PHY_2_0].phy;
0192         dev_warn(dev, "Error, 2.0 Phy not found\n");
0193         break;
0194     case 1:
0195     case PHY_TYPE_USB3:
0196         if (data->phys[BRCM_USB_PHY_3_0].phy)
0197             return data->phys[BRCM_USB_PHY_3_0].phy;
0198         dev_warn(dev, "Error, 3.0 Phy not found\n");
0199         break;
0200     }
0201     return ERR_PTR(-ENODEV);
0202 }
0203 
0204 static int name_to_value(const struct value_to_name_map *table, int count,
0205              const char *name, int *value)
0206 {
0207     int x;
0208 
0209     *value = 0;
0210     for (x = 0; x < count; x++) {
0211         if (sysfs_streq(name, table[x].name)) {
0212             *value = x;
0213             return 0;
0214         }
0215     }
0216     return -EINVAL;
0217 }
0218 
0219 static const char *value_to_name(const struct value_to_name_map *table, int count,
0220                  int value)
0221 {
0222     if (value >= count)
0223         return "unknown";
0224     return table[value].name;
0225 }
0226 
0227 static ssize_t dr_mode_show(struct device *dev,
0228                 struct device_attribute *attr,
0229                 char *buf)
0230 {
0231     struct brcm_usb_phy_data *priv = dev_get_drvdata(dev);
0232 
0233     return sprintf(buf, "%s\n",
0234         value_to_name(&brcm_dr_mode_to_name[0],
0235                   ARRAY_SIZE(brcm_dr_mode_to_name),
0236                   priv->ini.mode));
0237 }
0238 static DEVICE_ATTR_RO(dr_mode);
0239 
0240 static ssize_t dual_select_store(struct device *dev,
0241                  struct device_attribute *attr,
0242                  const char *buf, size_t len)
0243 {
0244     struct brcm_usb_phy_data *priv = dev_get_drvdata(dev);
0245     int value;
0246     int res;
0247 
0248     mutex_lock(&sysfs_lock);
0249     res = name_to_value(&brcm_dual_mode_to_name[0],
0250                 ARRAY_SIZE(brcm_dual_mode_to_name), buf, &value);
0251     if (!res) {
0252         brcm_usb_set_dual_select(&priv->ini, value);
0253         res = len;
0254     }
0255     mutex_unlock(&sysfs_lock);
0256     return res;
0257 }
0258 
0259 static ssize_t dual_select_show(struct device *dev,
0260                 struct device_attribute *attr,
0261                 char *buf)
0262 {
0263     struct brcm_usb_phy_data *priv = dev_get_drvdata(dev);
0264     int value;
0265 
0266     mutex_lock(&sysfs_lock);
0267     value = brcm_usb_get_dual_select(&priv->ini);
0268     mutex_unlock(&sysfs_lock);
0269     return sprintf(buf, "%s\n",
0270         value_to_name(&brcm_dual_mode_to_name[0],
0271                   ARRAY_SIZE(brcm_dual_mode_to_name),
0272                   value));
0273 }
0274 static DEVICE_ATTR_RW(dual_select);
0275 
0276 static struct attribute *brcm_usb_phy_attrs[] = {
0277     &dev_attr_dr_mode.attr,
0278     &dev_attr_dual_select.attr,
0279     NULL
0280 };
0281 
0282 static const struct attribute_group brcm_usb_phy_group = {
0283     .attrs = brcm_usb_phy_attrs,
0284 };
0285 
0286 static const struct match_chip_info chip_info_4908 = {
0287     .init_func = &brcm_usb_dvr_init_4908,
0288     .required_regs = {
0289         BRCM_REGS_CTRL,
0290         BRCM_REGS_XHCI_EC,
0291         -1,
0292     },
0293 };
0294 
0295 static const struct match_chip_info chip_info_7216 = {
0296     .init_func = &brcm_usb_dvr_init_7216,
0297     .required_regs = {
0298         BRCM_REGS_CTRL,
0299         BRCM_REGS_XHCI_EC,
0300         BRCM_REGS_XHCI_GBL,
0301         -1,
0302     },
0303 };
0304 
0305 static const struct match_chip_info chip_info_7211b0 = {
0306     .init_func = &brcm_usb_dvr_init_7211b0,
0307     .required_regs = {
0308         BRCM_REGS_CTRL,
0309         BRCM_REGS_XHCI_EC,
0310         BRCM_REGS_XHCI_GBL,
0311         BRCM_REGS_USB_PHY,
0312         BRCM_REGS_USB_MDIO,
0313         -1,
0314     },
0315     .optional_reg = BRCM_REGS_BDC_EC,
0316 };
0317 
0318 static const struct match_chip_info chip_info_7445 = {
0319     .init_func = &brcm_usb_dvr_init_7445,
0320     .required_regs = {
0321         BRCM_REGS_CTRL,
0322         BRCM_REGS_XHCI_EC,
0323         -1,
0324     },
0325 };
0326 
0327 static const struct of_device_id brcm_usb_dt_ids[] = {
0328     {
0329         .compatible = "brcm,bcm4908-usb-phy",
0330         .data = &chip_info_4908,
0331     },
0332     {
0333         .compatible = "brcm,bcm7216-usb-phy",
0334         .data = &chip_info_7216,
0335     },
0336     {
0337         .compatible = "brcm,bcm7211-usb-phy",
0338         .data = &chip_info_7211b0,
0339     },
0340     {
0341         .compatible = "brcm,brcmstb-usb-phy",
0342         .data = &chip_info_7445,
0343     },
0344     { /* sentinel */ }
0345 };
0346 
0347 static int brcm_usb_get_regs(struct platform_device *pdev,
0348                  enum brcmusb_reg_sel regs,
0349                  struct  brcm_usb_init_params *ini,
0350                  bool optional)
0351 {
0352     struct resource *res;
0353 
0354     /* Older DT nodes have ctrl and optional xhci_ec by index only */
0355     res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
0356                         node_reg_names[regs]);
0357     if (res == NULL) {
0358         if (regs == BRCM_REGS_CTRL) {
0359             res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
0360         } else if (regs == BRCM_REGS_XHCI_EC) {
0361             res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
0362             /* XHCI_EC registers are optional */
0363             if (res == NULL)
0364                 return 0;
0365         }
0366         if (res == NULL) {
0367             if (optional) {
0368                 dev_dbg(&pdev->dev,
0369                     "Optional reg %s not found\n",
0370                     node_reg_names[regs]);
0371                 return 0;
0372             }
0373             dev_err(&pdev->dev, "can't get %s base addr\n",
0374                 node_reg_names[regs]);
0375             return 1;
0376         }
0377     }
0378     ini->regs[regs] = devm_ioremap_resource(&pdev->dev, res);
0379     if (IS_ERR(ini->regs[regs])) {
0380         dev_err(&pdev->dev, "can't map %s register space\n",
0381             node_reg_names[regs]);
0382         return 1;
0383     }
0384     return 0;
0385 }
0386 
0387 static int brcm_usb_phy_dvr_init(struct platform_device *pdev,
0388                  struct brcm_usb_phy_data *priv,
0389                  struct device_node *dn)
0390 {
0391     struct device *dev = &pdev->dev;
0392     struct phy *gphy = NULL;
0393     int err;
0394 
0395     priv->usb_20_clk = of_clk_get_by_name(dn, "sw_usb");
0396     if (IS_ERR(priv->usb_20_clk)) {
0397         if (PTR_ERR(priv->usb_20_clk) == -EPROBE_DEFER)
0398             return -EPROBE_DEFER;
0399         dev_info(dev, "Clock not found in Device Tree\n");
0400         priv->usb_20_clk = NULL;
0401     }
0402     err = clk_prepare_enable(priv->usb_20_clk);
0403     if (err)
0404         return err;
0405 
0406     if (priv->has_eohci) {
0407         gphy = devm_phy_create(dev, NULL, &brcm_usb_phy_ops);
0408         if (IS_ERR(gphy)) {
0409             dev_err(dev, "failed to create EHCI/OHCI PHY\n");
0410             return PTR_ERR(gphy);
0411         }
0412         priv->phys[BRCM_USB_PHY_2_0].phy = gphy;
0413         priv->phys[BRCM_USB_PHY_2_0].id = BRCM_USB_PHY_2_0;
0414         phy_set_drvdata(gphy, &priv->phys[BRCM_USB_PHY_2_0]);
0415     }
0416 
0417     if (priv->has_xhci) {
0418         gphy = devm_phy_create(dev, NULL, &brcm_usb_phy_ops);
0419         if (IS_ERR(gphy)) {
0420             dev_err(dev, "failed to create XHCI PHY\n");
0421             return PTR_ERR(gphy);
0422         }
0423         priv->phys[BRCM_USB_PHY_3_0].phy = gphy;
0424         priv->phys[BRCM_USB_PHY_3_0].id = BRCM_USB_PHY_3_0;
0425         phy_set_drvdata(gphy, &priv->phys[BRCM_USB_PHY_3_0]);
0426 
0427         priv->usb_30_clk = of_clk_get_by_name(dn, "sw_usb3");
0428         if (IS_ERR(priv->usb_30_clk)) {
0429             if (PTR_ERR(priv->usb_30_clk) == -EPROBE_DEFER)
0430                 return -EPROBE_DEFER;
0431             dev_info(dev,
0432                  "USB3.0 clock not found in Device Tree\n");
0433             priv->usb_30_clk = NULL;
0434         }
0435         err = clk_prepare_enable(priv->usb_30_clk);
0436         if (err)
0437             return err;
0438     }
0439 
0440     priv->suspend_clk = clk_get(dev, "usb0_freerun");
0441     if (IS_ERR(priv->suspend_clk)) {
0442         if (PTR_ERR(priv->suspend_clk) == -EPROBE_DEFER)
0443             return -EPROBE_DEFER;
0444         dev_err(dev, "Suspend Clock not found in Device Tree\n");
0445         priv->suspend_clk = NULL;
0446     }
0447 
0448     priv->wake_irq = platform_get_irq_byname(pdev, "wake");
0449     if (priv->wake_irq < 0)
0450         priv->wake_irq = platform_get_irq_byname(pdev, "wakeup");
0451     if (priv->wake_irq >= 0) {
0452         err = devm_request_irq(dev, priv->wake_irq,
0453                        brcm_usb_phy_wake_isr, 0,
0454                        dev_name(dev), gphy);
0455         if (err < 0)
0456             return err;
0457         device_set_wakeup_capable(dev, 1);
0458     } else {
0459         dev_info(dev,
0460              "Wake interrupt missing, system wake not supported\n");
0461     }
0462 
0463     return 0;
0464 }
0465 
0466 static int brcm_usb_phy_probe(struct platform_device *pdev)
0467 {
0468     struct device *dev = &pdev->dev;
0469     struct brcm_usb_phy_data *priv;
0470     struct phy_provider *phy_provider;
0471     struct device_node *dn = pdev->dev.of_node;
0472     int err;
0473     const char *mode;
0474     const struct match_chip_info *info;
0475     struct regmap *rmap;
0476     int x;
0477 
0478     priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
0479     if (!priv)
0480         return -ENOMEM;
0481     platform_set_drvdata(pdev, priv);
0482 
0483     priv->ini.family_id = brcmstb_get_family_id();
0484     priv->ini.product_id = brcmstb_get_product_id();
0485 
0486     info = of_device_get_match_data(&pdev->dev);
0487     if (!info)
0488         return -ENOENT;
0489 
0490     info->init_func(&priv->ini);
0491 
0492     dev_dbg(dev, "Best mapping table is for %s\n",
0493         priv->ini.family_name);
0494 
0495     of_property_read_u32(dn, "brcm,ipp", &priv->ini.ipp);
0496     of_property_read_u32(dn, "brcm,ioc", &priv->ini.ioc);
0497 
0498     priv->ini.mode = USB_CTLR_MODE_HOST;
0499     err = of_property_read_string(dn, "dr_mode", &mode);
0500     if (err == 0) {
0501         name_to_value(&brcm_dr_mode_to_name[0],
0502                   ARRAY_SIZE(brcm_dr_mode_to_name),
0503             mode, &priv->ini.mode);
0504     }
0505     if (of_property_read_bool(dn, "brcm,has-xhci"))
0506         priv->has_xhci = true;
0507     if (of_property_read_bool(dn, "brcm,has-eohci"))
0508         priv->has_eohci = true;
0509 
0510     for (x = 0; x < BRCM_REGS_MAX; x++) {
0511         if (info->required_regs[x] >= BRCM_REGS_MAX)
0512             break;
0513 
0514         err = brcm_usb_get_regs(pdev, info->required_regs[x],
0515                     &priv->ini, false);
0516         if (err)
0517             return -EINVAL;
0518     }
0519     if (info->optional_reg) {
0520         err = brcm_usb_get_regs(pdev, info->optional_reg,
0521                     &priv->ini, true);
0522         if (err)
0523             return -EINVAL;
0524     }
0525 
0526     err = brcm_usb_phy_dvr_init(pdev, priv, dn);
0527     if (err)
0528         return err;
0529 
0530     priv->pm_notifier.notifier_call = brcm_pm_notifier;
0531     register_pm_notifier(&priv->pm_notifier);
0532 
0533     mutex_init(&priv->mutex);
0534 
0535     /* make sure invert settings are correct */
0536     brcm_usb_init_ipp(&priv->ini);
0537 
0538     /*
0539      * Create sysfs entries for mode.
0540      * Remove "dual_select" attribute if not in dual mode
0541      */
0542     if (priv->ini.mode != USB_CTLR_MODE_DRD)
0543         brcm_usb_phy_attrs[1] = NULL;
0544     err = sysfs_create_group(&dev->kobj, &brcm_usb_phy_group);
0545     if (err)
0546         dev_warn(dev, "Error creating sysfs attributes\n");
0547 
0548     /* Get piarbctl syscon if it exists */
0549     rmap = syscon_regmap_lookup_by_phandle(dev->of_node,
0550                          "syscon-piarbctl");
0551     if (IS_ERR(rmap))
0552         rmap = syscon_regmap_lookup_by_phandle(dev->of_node,
0553                                "brcm,syscon-piarbctl");
0554     if (!IS_ERR(rmap))
0555         priv->ini.syscon_piarbctl = rmap;
0556 
0557     /* start with everything off */
0558     if (priv->has_xhci)
0559         brcm_usb_uninit_xhci(&priv->ini);
0560     if (priv->has_eohci)
0561         brcm_usb_uninit_eohci(&priv->ini);
0562     brcm_usb_uninit_common(&priv->ini);
0563     clk_disable_unprepare(priv->usb_20_clk);
0564     clk_disable_unprepare(priv->usb_30_clk);
0565 
0566     phy_provider = devm_of_phy_provider_register(dev, brcm_usb_phy_xlate);
0567 
0568     return PTR_ERR_OR_ZERO(phy_provider);
0569 }
0570 
0571 static int brcm_usb_phy_remove(struct platform_device *pdev)
0572 {
0573     struct brcm_usb_phy_data *priv = dev_get_drvdata(&pdev->dev);
0574 
0575     sysfs_remove_group(&pdev->dev.kobj, &brcm_usb_phy_group);
0576     unregister_pm_notifier(&priv->pm_notifier);
0577 
0578     return 0;
0579 }
0580 
0581 #ifdef CONFIG_PM_SLEEP
0582 static int brcm_usb_phy_suspend(struct device *dev)
0583 {
0584     struct brcm_usb_phy_data *priv = dev_get_drvdata(dev);
0585 
0586     if (priv->init_count) {
0587         dev_dbg(dev, "SUSPEND\n");
0588         priv->ini.wake_enabled = device_may_wakeup(dev);
0589         if (priv->phys[BRCM_USB_PHY_3_0].inited)
0590             brcm_usb_uninit_xhci(&priv->ini);
0591         if (priv->phys[BRCM_USB_PHY_2_0].inited)
0592             brcm_usb_uninit_eohci(&priv->ini);
0593         brcm_usb_uninit_common(&priv->ini);
0594 
0595         /*
0596          * Handle the clocks unless needed for wake. This has
0597          * to work for both older XHCI->3.0-clks, EOHCI->2.0-clks
0598          * and newer XHCI->2.0-clks/3.0-clks.
0599          */
0600 
0601         if (!priv->ini.suspend_with_clocks) {
0602             if (priv->phys[BRCM_USB_PHY_3_0].inited)
0603                 clk_disable_unprepare(priv->usb_30_clk);
0604             if (priv->phys[BRCM_USB_PHY_2_0].inited ||
0605                 !priv->has_eohci)
0606                 clk_disable_unprepare(priv->usb_20_clk);
0607         }
0608         if (priv->wake_irq >= 0)
0609             enable_irq_wake(priv->wake_irq);
0610     }
0611     return 0;
0612 }
0613 
0614 static int brcm_usb_phy_resume(struct device *dev)
0615 {
0616     struct brcm_usb_phy_data *priv = dev_get_drvdata(dev);
0617 
0618     clk_prepare_enable(priv->usb_20_clk);
0619     clk_prepare_enable(priv->usb_30_clk);
0620     brcm_usb_init_ipp(&priv->ini);
0621 
0622     /*
0623      * Initialize anything that was previously initialized.
0624      * Uninitialize anything that wasn't previously initialized.
0625      */
0626     if (priv->init_count) {
0627         dev_dbg(dev, "RESUME\n");
0628         if (priv->wake_irq >= 0)
0629             disable_irq_wake(priv->wake_irq);
0630         brcm_usb_init_common(&priv->ini);
0631         if (priv->phys[BRCM_USB_PHY_2_0].inited) {
0632             brcm_usb_init_eohci(&priv->ini);
0633         } else if (priv->has_eohci) {
0634             brcm_usb_uninit_eohci(&priv->ini);
0635             clk_disable_unprepare(priv->usb_20_clk);
0636         }
0637         if (priv->phys[BRCM_USB_PHY_3_0].inited) {
0638             brcm_usb_init_xhci(&priv->ini);
0639         } else if (priv->has_xhci) {
0640             brcm_usb_uninit_xhci(&priv->ini);
0641             clk_disable_unprepare(priv->usb_30_clk);
0642             if (!priv->has_eohci)
0643                 clk_disable_unprepare(priv->usb_20_clk);
0644         }
0645     } else {
0646         if (priv->has_xhci)
0647             brcm_usb_uninit_xhci(&priv->ini);
0648         if (priv->has_eohci)
0649             brcm_usb_uninit_eohci(&priv->ini);
0650         brcm_usb_uninit_common(&priv->ini);
0651         clk_disable_unprepare(priv->usb_20_clk);
0652         clk_disable_unprepare(priv->usb_30_clk);
0653     }
0654     priv->ini.wake_enabled = false;
0655     return 0;
0656 }
0657 #endif /* CONFIG_PM_SLEEP */
0658 
0659 static const struct dev_pm_ops brcm_usb_phy_pm_ops = {
0660     SET_LATE_SYSTEM_SLEEP_PM_OPS(brcm_usb_phy_suspend, brcm_usb_phy_resume)
0661 };
0662 
0663 MODULE_DEVICE_TABLE(of, brcm_usb_dt_ids);
0664 
0665 static struct platform_driver brcm_usb_driver = {
0666     .probe      = brcm_usb_phy_probe,
0667     .remove     = brcm_usb_phy_remove,
0668     .driver     = {
0669         .name   = "brcmstb-usb-phy",
0670         .pm = &brcm_usb_phy_pm_ops,
0671         .of_match_table = brcm_usb_dt_ids,
0672     },
0673 };
0674 
0675 module_platform_driver(brcm_usb_driver);
0676 
0677 MODULE_ALIAS("platform:brcmstb-usb-phy");
0678 MODULE_AUTHOR("Al Cooper <acooper@broadcom.com>");
0679 MODULE_DESCRIPTION("BRCM USB PHY driver");
0680 MODULE_LICENSE("GPL v2");