phy-brcm-usb.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * phy-brcm-usb.c - Broadcom USB Phy Driver
  4. *
  5. * Copyright (C) 2015-2017 Broadcom
  6. */
  7. #include <linux/clk.h>
  8. #include <linux/delay.h>
  9. #include <linux/err.h>
  10. #include <linux/io.h>
  11. #include <linux/module.h>
  12. #include <linux/of.h>
  13. #include <linux/phy/phy.h>
  14. #include <linux/platform_device.h>
  15. #include <linux/interrupt.h>
  16. #include <linux/soc/brcmstb/brcmstb.h>
  17. #include <dt-bindings/phy/phy.h>
  18. #include <linux/mfd/syscon.h>
  19. #include <linux/suspend.h>
  20. #include "phy-brcm-usb-init.h"
  21. static DEFINE_MUTEX(sysfs_lock);
  22. enum brcm_usb_phy_id {
  23. BRCM_USB_PHY_2_0 = 0,
  24. BRCM_USB_PHY_3_0,
  25. BRCM_USB_PHY_ID_MAX
  26. };
  27. struct value_to_name_map {
  28. int value;
  29. const char *name;
  30. };
  31. struct match_chip_info {
  32. void (*init_func)(struct brcm_usb_init_params *params);
  33. u8 required_regs[BRCM_REGS_MAX + 1];
  34. u8 optional_reg;
  35. };
  36. static const struct value_to_name_map brcm_dr_mode_to_name[] = {
  37. { USB_CTLR_MODE_HOST, "host" },
  38. { USB_CTLR_MODE_DEVICE, "peripheral" },
  39. { USB_CTLR_MODE_DRD, "drd" },
  40. { USB_CTLR_MODE_TYPEC_PD, "typec-pd" }
  41. };
  42. static const struct value_to_name_map brcm_dual_mode_to_name[] = {
  43. { 0, "host" },
  44. { 1, "device" },
  45. { 2, "auto" },
  46. };
  47. struct brcm_usb_phy {
  48. struct phy *phy;
  49. unsigned int id;
  50. bool inited;
  51. };
  52. struct brcm_usb_phy_data {
  53. struct brcm_usb_init_params ini;
  54. bool has_eohci;
  55. bool has_xhci;
  56. struct clk *usb_20_clk;
  57. struct clk *usb_30_clk;
  58. struct clk *suspend_clk;
  59. struct mutex mutex; /* serialize phy init */
  60. int init_count;
  61. int wake_irq;
  62. struct brcm_usb_phy phys[BRCM_USB_PHY_ID_MAX];
  63. struct notifier_block pm_notifier;
  64. bool pm_active;
  65. };
  66. static s8 *node_reg_names[BRCM_REGS_MAX] = {
  67. "crtl", "xhci_ec", "xhci_gbl", "usb_phy", "usb_mdio", "bdc_ec"
  68. };
  69. static int brcm_pm_notifier(struct notifier_block *notifier,
  70. unsigned long pm_event,
  71. void *unused)
  72. {
  73. struct brcm_usb_phy_data *priv =
  74. container_of(notifier, struct brcm_usb_phy_data, pm_notifier);
  75. switch (pm_event) {
  76. case PM_HIBERNATION_PREPARE:
  77. case PM_SUSPEND_PREPARE:
  78. priv->pm_active = true;
  79. break;
  80. case PM_POST_RESTORE:
  81. case PM_POST_HIBERNATION:
  82. case PM_POST_SUSPEND:
  83. priv->pm_active = false;
  84. break;
  85. }
  86. return NOTIFY_DONE;
  87. }
  88. static irqreturn_t brcm_usb_phy_wake_isr(int irq, void *dev_id)
  89. {
  90. struct device *dev = dev_id;
  91. pm_wakeup_event(dev, 0);
  92. return IRQ_HANDLED;
  93. }
  94. static int brcm_usb_phy_init(struct phy *gphy)
  95. {
  96. struct brcm_usb_phy *phy = phy_get_drvdata(gphy);
  97. struct brcm_usb_phy_data *priv =
  98. container_of(phy, struct brcm_usb_phy_data, phys[phy->id]);
  99. if (priv->pm_active)
  100. return 0;
  101. /*
  102. * Use a lock to make sure a second caller waits until
  103. * the base phy is inited before using it.
  104. */
  105. mutex_lock(&priv->mutex);
  106. if (priv->init_count++ == 0) {
  107. clk_prepare_enable(priv->usb_20_clk);
  108. clk_prepare_enable(priv->usb_30_clk);
  109. clk_prepare_enable(priv->suspend_clk);
  110. brcm_usb_init_common(&priv->ini);
  111. }
  112. mutex_unlock(&priv->mutex);
  113. if (phy->id == BRCM_USB_PHY_2_0)
  114. brcm_usb_init_eohci(&priv->ini);
  115. else if (phy->id == BRCM_USB_PHY_3_0)
  116. brcm_usb_init_xhci(&priv->ini);
  117. phy->inited = true;
  118. dev_dbg(&gphy->dev, "INIT, id: %d, total: %d\n", phy->id,
  119. priv->init_count);
  120. return 0;
  121. }
  122. static int brcm_usb_phy_exit(struct phy *gphy)
  123. {
  124. struct brcm_usb_phy *phy = phy_get_drvdata(gphy);
  125. struct brcm_usb_phy_data *priv =
  126. container_of(phy, struct brcm_usb_phy_data, phys[phy->id]);
  127. if (priv->pm_active)
  128. return 0;
  129. dev_dbg(&gphy->dev, "EXIT\n");
  130. if (phy->id == BRCM_USB_PHY_2_0)
  131. brcm_usb_uninit_eohci(&priv->ini);
  132. if (phy->id == BRCM_USB_PHY_3_0)
  133. brcm_usb_uninit_xhci(&priv->ini);
  134. /* If both xhci and eohci are gone, reset everything else */
  135. mutex_lock(&priv->mutex);
  136. if (--priv->init_count == 0) {
  137. brcm_usb_uninit_common(&priv->ini);
  138. clk_disable_unprepare(priv->usb_20_clk);
  139. clk_disable_unprepare(priv->usb_30_clk);
  140. clk_disable_unprepare(priv->suspend_clk);
  141. }
  142. mutex_unlock(&priv->mutex);
  143. phy->inited = false;
  144. return 0;
  145. }
  146. static const struct phy_ops brcm_usb_phy_ops = {
  147. .init = brcm_usb_phy_init,
  148. .exit = brcm_usb_phy_exit,
  149. .owner = THIS_MODULE,
  150. };
  151. static struct phy *brcm_usb_phy_xlate(struct device *dev,
  152. const struct of_phandle_args *args)
  153. {
  154. struct brcm_usb_phy_data *data = dev_get_drvdata(dev);
  155. /*
  156. * values 0 and 1 are for backward compatibility with
  157. * device tree nodes from older bootloaders.
  158. */
  159. switch (args->args[0]) {
  160. case 0:
  161. case PHY_TYPE_USB2:
  162. if (data->phys[BRCM_USB_PHY_2_0].phy)
  163. return data->phys[BRCM_USB_PHY_2_0].phy;
  164. dev_warn(dev, "Error, 2.0 Phy not found\n");
  165. break;
  166. case 1:
  167. case PHY_TYPE_USB3:
  168. if (data->phys[BRCM_USB_PHY_3_0].phy)
  169. return data->phys[BRCM_USB_PHY_3_0].phy;
  170. dev_warn(dev, "Error, 3.0 Phy not found\n");
  171. break;
  172. }
  173. return ERR_PTR(-ENODEV);
  174. }
  175. static int name_to_value(const struct value_to_name_map *table, int count,
  176. const char *name, int *value)
  177. {
  178. int x;
  179. *value = 0;
  180. for (x = 0; x < count; x++) {
  181. if (sysfs_streq(name, table[x].name)) {
  182. *value = x;
  183. return 0;
  184. }
  185. }
  186. return -EINVAL;
  187. }
  188. static const char *value_to_name(const struct value_to_name_map *table, int count,
  189. int value)
  190. {
  191. if (value >= count)
  192. return "unknown";
  193. return table[value].name;
  194. }
  195. static ssize_t dr_mode_show(struct device *dev,
  196. struct device_attribute *attr,
  197. char *buf)
  198. {
  199. struct brcm_usb_phy_data *priv = dev_get_drvdata(dev);
  200. return sprintf(buf, "%s\n",
  201. value_to_name(&brcm_dr_mode_to_name[0],
  202. ARRAY_SIZE(brcm_dr_mode_to_name),
  203. priv->ini.supported_port_modes));
  204. }
  205. static DEVICE_ATTR_RO(dr_mode);
  206. static ssize_t dual_select_store(struct device *dev,
  207. struct device_attribute *attr,
  208. const char *buf, size_t len)
  209. {
  210. struct brcm_usb_phy_data *priv = dev_get_drvdata(dev);
  211. int value;
  212. int res;
  213. mutex_lock(&sysfs_lock);
  214. res = name_to_value(&brcm_dual_mode_to_name[0],
  215. ARRAY_SIZE(brcm_dual_mode_to_name), buf, &value);
  216. if (!res) {
  217. priv->ini.port_mode = value;
  218. brcm_usb_set_dual_select(&priv->ini);
  219. res = len;
  220. }
  221. mutex_unlock(&sysfs_lock);
  222. return res;
  223. }
  224. static ssize_t dual_select_show(struct device *dev,
  225. struct device_attribute *attr,
  226. char *buf)
  227. {
  228. struct brcm_usb_phy_data *priv = dev_get_drvdata(dev);
  229. int value;
  230. mutex_lock(&sysfs_lock);
  231. value = brcm_usb_get_dual_select(&priv->ini);
  232. mutex_unlock(&sysfs_lock);
  233. return sprintf(buf, "%s\n",
  234. value_to_name(&brcm_dual_mode_to_name[0],
  235. ARRAY_SIZE(brcm_dual_mode_to_name),
  236. value));
  237. }
  238. static DEVICE_ATTR_RW(dual_select);
  239. static struct attribute *brcm_usb_phy_attrs[] = {
  240. &dev_attr_dr_mode.attr,
  241. &dev_attr_dual_select.attr,
  242. NULL
  243. };
  244. static const struct attribute_group brcm_usb_phy_group = {
  245. .attrs = brcm_usb_phy_attrs,
  246. };
  247. static const struct match_chip_info chip_info_4908 = {
  248. .init_func = &brcm_usb_dvr_init_4908,
  249. .required_regs = {
  250. BRCM_REGS_CTRL,
  251. BRCM_REGS_XHCI_EC,
  252. -1,
  253. },
  254. };
  255. static const struct match_chip_info chip_info_7216 = {
  256. .init_func = &brcm_usb_dvr_init_7216,
  257. .required_regs = {
  258. BRCM_REGS_CTRL,
  259. BRCM_REGS_XHCI_EC,
  260. BRCM_REGS_XHCI_GBL,
  261. -1,
  262. },
  263. };
  264. static const struct match_chip_info chip_info_7211b0 = {
  265. .init_func = &brcm_usb_dvr_init_7211b0,
  266. .required_regs = {
  267. BRCM_REGS_CTRL,
  268. BRCM_REGS_XHCI_EC,
  269. BRCM_REGS_XHCI_GBL,
  270. BRCM_REGS_USB_PHY,
  271. BRCM_REGS_USB_MDIO,
  272. -1,
  273. },
  274. .optional_reg = BRCM_REGS_BDC_EC,
  275. };
  276. static const struct match_chip_info chip_info_7445 = {
  277. .init_func = &brcm_usb_dvr_init_7445,
  278. .required_regs = {
  279. BRCM_REGS_CTRL,
  280. BRCM_REGS_XHCI_EC,
  281. -1,
  282. },
  283. };
  284. static const struct of_device_id brcm_usb_dt_ids[] = {
  285. {
  286. .compatible = "brcm,bcm4908-usb-phy",
  287. .data = &chip_info_4908,
  288. },
  289. {
  290. .compatible = "brcm,bcm7216-usb-phy",
  291. .data = &chip_info_7216,
  292. },
  293. {
  294. .compatible = "brcm,bcm7211-usb-phy",
  295. .data = &chip_info_7211b0,
  296. },
  297. {
  298. .compatible = "brcm,brcmstb-usb-phy",
  299. .data = &chip_info_7445,
  300. },
  301. { /* sentinel */ }
  302. };
  303. static int brcm_usb_get_regs(struct platform_device *pdev,
  304. enum brcmusb_reg_sel regs,
  305. struct brcm_usb_init_params *ini,
  306. bool optional)
  307. {
  308. struct resource *res;
  309. /* Older DT nodes have ctrl and optional xhci_ec by index only */
  310. res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
  311. node_reg_names[regs]);
  312. if (res == NULL) {
  313. if (regs == BRCM_REGS_CTRL) {
  314. res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  315. } else if (regs == BRCM_REGS_XHCI_EC) {
  316. res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
  317. /* XHCI_EC registers are optional */
  318. if (res == NULL)
  319. return 0;
  320. }
  321. if (res == NULL) {
  322. if (optional) {
  323. dev_dbg(&pdev->dev,
  324. "Optional reg %s not found\n",
  325. node_reg_names[regs]);
  326. return 0;
  327. }
  328. dev_err(&pdev->dev, "can't get %s base addr\n",
  329. node_reg_names[regs]);
  330. return 1;
  331. }
  332. }
  333. ini->regs[regs] = devm_ioremap_resource(&pdev->dev, res);
  334. if (IS_ERR(ini->regs[regs])) {
  335. dev_err(&pdev->dev, "can't map %s register space\n",
  336. node_reg_names[regs]);
  337. return 1;
  338. }
  339. return 0;
  340. }
  341. static int brcm_usb_phy_dvr_init(struct platform_device *pdev,
  342. struct brcm_usb_phy_data *priv,
  343. struct device_node *dn)
  344. {
  345. struct device *dev = &pdev->dev;
  346. struct phy *gphy = NULL;
  347. int err;
  348. priv->usb_20_clk = of_clk_get_by_name(dn, "sw_usb");
  349. if (IS_ERR(priv->usb_20_clk)) {
  350. if (PTR_ERR(priv->usb_20_clk) == -EPROBE_DEFER)
  351. return -EPROBE_DEFER;
  352. dev_info(dev, "Clock not found in Device Tree\n");
  353. priv->usb_20_clk = NULL;
  354. }
  355. err = clk_prepare_enable(priv->usb_20_clk);
  356. if (err)
  357. return err;
  358. if (priv->has_eohci) {
  359. gphy = devm_phy_create(dev, NULL, &brcm_usb_phy_ops);
  360. if (IS_ERR(gphy)) {
  361. dev_err(dev, "failed to create EHCI/OHCI PHY\n");
  362. return PTR_ERR(gphy);
  363. }
  364. priv->phys[BRCM_USB_PHY_2_0].phy = gphy;
  365. priv->phys[BRCM_USB_PHY_2_0].id = BRCM_USB_PHY_2_0;
  366. phy_set_drvdata(gphy, &priv->phys[BRCM_USB_PHY_2_0]);
  367. }
  368. if (priv->has_xhci) {
  369. gphy = devm_phy_create(dev, NULL, &brcm_usb_phy_ops);
  370. if (IS_ERR(gphy)) {
  371. dev_err(dev, "failed to create XHCI PHY\n");
  372. return PTR_ERR(gphy);
  373. }
  374. priv->phys[BRCM_USB_PHY_3_0].phy = gphy;
  375. priv->phys[BRCM_USB_PHY_3_0].id = BRCM_USB_PHY_3_0;
  376. phy_set_drvdata(gphy, &priv->phys[BRCM_USB_PHY_3_0]);
  377. priv->usb_30_clk = of_clk_get_by_name(dn, "sw_usb3");
  378. if (IS_ERR(priv->usb_30_clk)) {
  379. if (PTR_ERR(priv->usb_30_clk) == -EPROBE_DEFER)
  380. return -EPROBE_DEFER;
  381. dev_info(dev,
  382. "USB3.0 clock not found in Device Tree\n");
  383. priv->usb_30_clk = NULL;
  384. }
  385. err = clk_prepare_enable(priv->usb_30_clk);
  386. if (err)
  387. return err;
  388. }
  389. priv->suspend_clk = clk_get(dev, "usb0_freerun");
  390. if (IS_ERR(priv->suspend_clk)) {
  391. if (PTR_ERR(priv->suspend_clk) == -EPROBE_DEFER)
  392. return -EPROBE_DEFER;
  393. dev_err(dev, "Suspend Clock not found in Device Tree\n");
  394. priv->suspend_clk = NULL;
  395. }
  396. priv->wake_irq = platform_get_irq_byname_optional(pdev, "wake");
  397. if (priv->wake_irq < 0)
  398. priv->wake_irq = platform_get_irq_byname_optional(pdev, "wakeup");
  399. if (priv->wake_irq >= 0) {
  400. err = devm_request_irq(dev, priv->wake_irq,
  401. brcm_usb_phy_wake_isr, 0,
  402. dev_name(dev), dev);
  403. if (err < 0)
  404. return err;
  405. device_set_wakeup_capable(dev, 1);
  406. } else {
  407. dev_info(dev,
  408. "Wake interrupt missing, system wake not supported\n");
  409. }
  410. return 0;
  411. }
  412. static int brcm_usb_phy_probe(struct platform_device *pdev)
  413. {
  414. struct device *dev = &pdev->dev;
  415. struct brcm_usb_phy_data *priv;
  416. struct phy_provider *phy_provider;
  417. struct device_node *dn = pdev->dev.of_node;
  418. int err;
  419. const char *mode;
  420. const struct match_chip_info *info;
  421. struct regmap *rmap;
  422. int x;
  423. priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
  424. if (!priv)
  425. return -ENOMEM;
  426. platform_set_drvdata(pdev, priv);
  427. priv->ini.family_id = brcmstb_get_family_id();
  428. priv->ini.product_id = brcmstb_get_product_id();
  429. info = of_device_get_match_data(&pdev->dev);
  430. if (!info)
  431. return -ENOENT;
  432. info->init_func(&priv->ini);
  433. dev_dbg(dev, "Best mapping table is for %s\n",
  434. priv->ini.family_name);
  435. of_property_read_u32(dn, "brcm,ipp", &priv->ini.ipp);
  436. of_property_read_u32(dn, "brcm,ioc", &priv->ini.ioc);
  437. priv->ini.supported_port_modes = USB_CTLR_MODE_HOST;
  438. err = of_property_read_string(dn, "dr_mode", &mode);
  439. if (err == 0) {
  440. name_to_value(&brcm_dr_mode_to_name[0],
  441. ARRAY_SIZE(brcm_dr_mode_to_name),
  442. mode, &priv->ini.supported_port_modes);
  443. }
  444. /* Default port_mode to supported port_modes */
  445. priv->ini.port_mode = priv->ini.supported_port_modes;
  446. if (of_property_read_bool(dn, "brcm,has-xhci"))
  447. priv->has_xhci = true;
  448. if (of_property_read_bool(dn, "brcm,has-eohci"))
  449. priv->has_eohci = true;
  450. for (x = 0; x < BRCM_REGS_MAX; x++) {
  451. if (info->required_regs[x] >= BRCM_REGS_MAX)
  452. break;
  453. err = brcm_usb_get_regs(pdev, info->required_regs[x],
  454. &priv->ini, false);
  455. if (err)
  456. return -EINVAL;
  457. }
  458. if (info->optional_reg) {
  459. err = brcm_usb_get_regs(pdev, info->optional_reg,
  460. &priv->ini, true);
  461. if (err)
  462. return -EINVAL;
  463. }
  464. err = brcm_usb_phy_dvr_init(pdev, priv, dn);
  465. if (err)
  466. return err;
  467. priv->pm_notifier.notifier_call = brcm_pm_notifier;
  468. register_pm_notifier(&priv->pm_notifier);
  469. mutex_init(&priv->mutex);
  470. /* make sure invert settings are correct */
  471. brcm_usb_init_ipp(&priv->ini);
  472. /*
  473. * Create sysfs entries for mode.
  474. * Remove "dual_select" attribute if not in dual mode
  475. */
  476. if (priv->ini.supported_port_modes != USB_CTLR_MODE_DRD)
  477. brcm_usb_phy_attrs[1] = NULL;
  478. err = sysfs_create_group(&dev->kobj, &brcm_usb_phy_group);
  479. if (err)
  480. dev_warn(dev, "Error creating sysfs attributes\n");
  481. /* Get piarbctl syscon if it exists */
  482. rmap = syscon_regmap_lookup_by_phandle(dev->of_node,
  483. "syscon-piarbctl");
  484. if (IS_ERR(rmap))
  485. rmap = syscon_regmap_lookup_by_phandle(dev->of_node,
  486. "brcm,syscon-piarbctl");
  487. if (!IS_ERR(rmap))
  488. priv->ini.syscon_piarbctl = rmap;
  489. /* start with everything off */
  490. if (priv->has_xhci)
  491. brcm_usb_uninit_xhci(&priv->ini);
  492. if (priv->has_eohci)
  493. brcm_usb_uninit_eohci(&priv->ini);
  494. brcm_usb_uninit_common(&priv->ini);
  495. clk_disable_unprepare(priv->usb_20_clk);
  496. clk_disable_unprepare(priv->usb_30_clk);
  497. phy_provider = devm_of_phy_provider_register(dev, brcm_usb_phy_xlate);
  498. return PTR_ERR_OR_ZERO(phy_provider);
  499. }
  500. static void brcm_usb_phy_remove(struct platform_device *pdev)
  501. {
  502. struct brcm_usb_phy_data *priv = dev_get_drvdata(&pdev->dev);
  503. sysfs_remove_group(&pdev->dev.kobj, &brcm_usb_phy_group);
  504. unregister_pm_notifier(&priv->pm_notifier);
  505. }
  506. #ifdef CONFIG_PM_SLEEP
  507. static int brcm_usb_phy_suspend(struct device *dev)
  508. {
  509. struct brcm_usb_phy_data *priv = dev_get_drvdata(dev);
  510. if (priv->init_count) {
  511. dev_dbg(dev, "SUSPEND\n");
  512. priv->ini.wake_enabled = device_may_wakeup(dev);
  513. if (priv->phys[BRCM_USB_PHY_3_0].inited)
  514. brcm_usb_uninit_xhci(&priv->ini);
  515. if (priv->phys[BRCM_USB_PHY_2_0].inited)
  516. brcm_usb_uninit_eohci(&priv->ini);
  517. brcm_usb_uninit_common(&priv->ini);
  518. /*
  519. * Handle the clocks unless needed for wake. This has
  520. * to work for both older XHCI->3.0-clks, EOHCI->2.0-clks
  521. * and newer XHCI->2.0-clks/3.0-clks.
  522. */
  523. if (!priv->ini.wake_enabled) {
  524. if (priv->phys[BRCM_USB_PHY_3_0].inited)
  525. clk_disable_unprepare(priv->usb_30_clk);
  526. if (priv->phys[BRCM_USB_PHY_2_0].inited ||
  527. !priv->has_eohci)
  528. clk_disable_unprepare(priv->usb_20_clk);
  529. }
  530. if (priv->wake_irq >= 0)
  531. enable_irq_wake(priv->wake_irq);
  532. }
  533. return 0;
  534. }
  535. static int brcm_usb_phy_resume(struct device *dev)
  536. {
  537. struct brcm_usb_phy_data *priv = dev_get_drvdata(dev);
  538. if (!priv->ini.wake_enabled) {
  539. clk_prepare_enable(priv->usb_20_clk);
  540. clk_prepare_enable(priv->usb_30_clk);
  541. }
  542. brcm_usb_init_ipp(&priv->ini);
  543. /*
  544. * Initialize anything that was previously initialized.
  545. * Uninitialize anything that wasn't previously initialized.
  546. */
  547. if (priv->init_count) {
  548. dev_dbg(dev, "RESUME\n");
  549. if (priv->wake_irq >= 0)
  550. disable_irq_wake(priv->wake_irq);
  551. brcm_usb_init_common(&priv->ini);
  552. if (priv->phys[BRCM_USB_PHY_2_0].inited) {
  553. brcm_usb_init_eohci(&priv->ini);
  554. } else if (priv->has_eohci) {
  555. brcm_usb_uninit_eohci(&priv->ini);
  556. clk_disable_unprepare(priv->usb_20_clk);
  557. }
  558. if (priv->phys[BRCM_USB_PHY_3_0].inited) {
  559. brcm_usb_init_xhci(&priv->ini);
  560. } else if (priv->has_xhci) {
  561. brcm_usb_uninit_xhci(&priv->ini);
  562. clk_disable_unprepare(priv->usb_30_clk);
  563. if (!priv->has_eohci)
  564. clk_disable_unprepare(priv->usb_20_clk);
  565. }
  566. } else {
  567. if (priv->has_xhci)
  568. brcm_usb_uninit_xhci(&priv->ini);
  569. if (priv->has_eohci)
  570. brcm_usb_uninit_eohci(&priv->ini);
  571. brcm_usb_uninit_common(&priv->ini);
  572. clk_disable_unprepare(priv->usb_20_clk);
  573. clk_disable_unprepare(priv->usb_30_clk);
  574. }
  575. priv->ini.wake_enabled = false;
  576. return 0;
  577. }
  578. #endif /* CONFIG_PM_SLEEP */
  579. static const struct dev_pm_ops brcm_usb_phy_pm_ops = {
  580. SET_LATE_SYSTEM_SLEEP_PM_OPS(brcm_usb_phy_suspend, brcm_usb_phy_resume)
  581. };
  582. MODULE_DEVICE_TABLE(of, brcm_usb_dt_ids);
  583. static struct platform_driver brcm_usb_driver = {
  584. .probe = brcm_usb_phy_probe,
  585. .remove_new = brcm_usb_phy_remove,
  586. .driver = {
  587. .name = "brcmstb-usb-phy",
  588. .pm = &brcm_usb_phy_pm_ops,
  589. .of_match_table = brcm_usb_dt_ids,
  590. },
  591. };
  592. module_platform_driver(brcm_usb_driver);
  593. MODULE_ALIAS("platform:brcmstb-usb-phy");
  594. MODULE_AUTHOR("Al Cooper <acooper@broadcom.com>");
  595. MODULE_DESCRIPTION("BRCM USB PHY driver");
  596. MODULE_LICENSE("GPL v2");