phy-brcm-usb.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682
  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/of_device.h>
  14. #include <linux/phy/phy.h>
  15. #include <linux/platform_device.h>
  16. #include <linux/interrupt.h>
  17. #include <linux/soc/brcmstb/brcmstb.h>
  18. #include <dt-bindings/phy/phy.h>
  19. #include <linux/mfd/syscon.h>
  20. #include <linux/suspend.h>
  21. #include "phy-brcm-usb-init.h"
  22. static DEFINE_MUTEX(sysfs_lock);
  23. enum brcm_usb_phy_id {
  24. BRCM_USB_PHY_2_0 = 0,
  25. BRCM_USB_PHY_3_0,
  26. BRCM_USB_PHY_ID_MAX
  27. };
  28. struct value_to_name_map {
  29. int value;
  30. const char *name;
  31. };
  32. struct match_chip_info {
  33. void (*init_func)(struct brcm_usb_init_params *params);
  34. u8 required_regs[BRCM_REGS_MAX + 1];
  35. u8 optional_reg;
  36. };
  37. static const struct value_to_name_map brcm_dr_mode_to_name[] = {
  38. { USB_CTLR_MODE_HOST, "host" },
  39. { USB_CTLR_MODE_DEVICE, "peripheral" },
  40. { USB_CTLR_MODE_DRD, "drd" },
  41. { USB_CTLR_MODE_TYPEC_PD, "typec-pd" }
  42. };
  43. static const struct value_to_name_map brcm_dual_mode_to_name[] = {
  44. { 0, "host" },
  45. { 1, "device" },
  46. { 2, "auto" },
  47. };
  48. struct brcm_usb_phy {
  49. struct phy *phy;
  50. unsigned int id;
  51. bool inited;
  52. };
  53. struct brcm_usb_phy_data {
  54. struct brcm_usb_init_params ini;
  55. bool has_eohci;
  56. bool has_xhci;
  57. struct clk *usb_20_clk;
  58. struct clk *usb_30_clk;
  59. struct clk *suspend_clk;
  60. struct mutex mutex; /* serialize phy init */
  61. int init_count;
  62. int wake_irq;
  63. struct brcm_usb_phy phys[BRCM_USB_PHY_ID_MAX];
  64. struct notifier_block pm_notifier;
  65. bool pm_active;
  66. };
  67. static s8 *node_reg_names[BRCM_REGS_MAX] = {
  68. "crtl", "xhci_ec", "xhci_gbl", "usb_phy", "usb_mdio", "bdc_ec"
  69. };
  70. static int brcm_pm_notifier(struct notifier_block *notifier,
  71. unsigned long pm_event,
  72. void *unused)
  73. {
  74. struct brcm_usb_phy_data *priv =
  75. container_of(notifier, struct brcm_usb_phy_data, pm_notifier);
  76. switch (pm_event) {
  77. case PM_HIBERNATION_PREPARE:
  78. case PM_SUSPEND_PREPARE:
  79. priv->pm_active = true;
  80. break;
  81. case PM_POST_RESTORE:
  82. case PM_POST_HIBERNATION:
  83. case PM_POST_SUSPEND:
  84. priv->pm_active = false;
  85. break;
  86. }
  87. return NOTIFY_DONE;
  88. }
  89. static irqreturn_t brcm_usb_phy_wake_isr(int irq, void *dev_id)
  90. {
  91. struct device *dev = dev_id;
  92. pm_wakeup_event(dev, 0);
  93. return IRQ_HANDLED;
  94. }
  95. static int brcm_usb_phy_init(struct phy *gphy)
  96. {
  97. struct brcm_usb_phy *phy = phy_get_drvdata(gphy);
  98. struct brcm_usb_phy_data *priv =
  99. container_of(phy, struct brcm_usb_phy_data, phys[phy->id]);
  100. if (priv->pm_active)
  101. return 0;
  102. /*
  103. * Use a lock to make sure a second caller waits until
  104. * the base phy is inited before using it.
  105. */
  106. mutex_lock(&priv->mutex);
  107. if (priv->init_count++ == 0) {
  108. clk_prepare_enable(priv->usb_20_clk);
  109. clk_prepare_enable(priv->usb_30_clk);
  110. clk_prepare_enable(priv->suspend_clk);
  111. brcm_usb_init_common(&priv->ini);
  112. }
  113. mutex_unlock(&priv->mutex);
  114. if (phy->id == BRCM_USB_PHY_2_0)
  115. brcm_usb_init_eohci(&priv->ini);
  116. else if (phy->id == BRCM_USB_PHY_3_0)
  117. brcm_usb_init_xhci(&priv->ini);
  118. phy->inited = true;
  119. dev_dbg(&gphy->dev, "INIT, id: %d, total: %d\n", phy->id,
  120. priv->init_count);
  121. return 0;
  122. }
  123. static int brcm_usb_phy_exit(struct phy *gphy)
  124. {
  125. struct brcm_usb_phy *phy = phy_get_drvdata(gphy);
  126. struct brcm_usb_phy_data *priv =
  127. container_of(phy, struct brcm_usb_phy_data, phys[phy->id]);
  128. if (priv->pm_active)
  129. return 0;
  130. dev_dbg(&gphy->dev, "EXIT\n");
  131. if (phy->id == BRCM_USB_PHY_2_0)
  132. brcm_usb_uninit_eohci(&priv->ini);
  133. if (phy->id == BRCM_USB_PHY_3_0)
  134. brcm_usb_uninit_xhci(&priv->ini);
  135. /* If both xhci and eohci are gone, reset everything else */
  136. mutex_lock(&priv->mutex);
  137. if (--priv->init_count == 0) {
  138. brcm_usb_uninit_common(&priv->ini);
  139. clk_disable_unprepare(priv->usb_20_clk);
  140. clk_disable_unprepare(priv->usb_30_clk);
  141. clk_disable_unprepare(priv->suspend_clk);
  142. }
  143. mutex_unlock(&priv->mutex);
  144. phy->inited = false;
  145. return 0;
  146. }
  147. static const struct phy_ops brcm_usb_phy_ops = {
  148. .init = brcm_usb_phy_init,
  149. .exit = brcm_usb_phy_exit,
  150. .owner = THIS_MODULE,
  151. };
  152. static struct phy *brcm_usb_phy_xlate(struct device *dev,
  153. struct of_phandle_args *args)
  154. {
  155. struct brcm_usb_phy_data *data = dev_get_drvdata(dev);
  156. /*
  157. * values 0 and 1 are for backward compatibility with
  158. * device tree nodes from older bootloaders.
  159. */
  160. switch (args->args[0]) {
  161. case 0:
  162. case PHY_TYPE_USB2:
  163. if (data->phys[BRCM_USB_PHY_2_0].phy)
  164. return data->phys[BRCM_USB_PHY_2_0].phy;
  165. dev_warn(dev, "Error, 2.0 Phy not found\n");
  166. break;
  167. case 1:
  168. case PHY_TYPE_USB3:
  169. if (data->phys[BRCM_USB_PHY_3_0].phy)
  170. return data->phys[BRCM_USB_PHY_3_0].phy;
  171. dev_warn(dev, "Error, 3.0 Phy not found\n");
  172. break;
  173. }
  174. return ERR_PTR(-ENODEV);
  175. }
  176. static int name_to_value(const struct value_to_name_map *table, int count,
  177. const char *name, int *value)
  178. {
  179. int x;
  180. *value = 0;
  181. for (x = 0; x < count; x++) {
  182. if (sysfs_streq(name, table[x].name)) {
  183. *value = x;
  184. return 0;
  185. }
  186. }
  187. return -EINVAL;
  188. }
  189. static const char *value_to_name(const struct value_to_name_map *table, int count,
  190. int value)
  191. {
  192. if (value >= count)
  193. return "unknown";
  194. return table[value].name;
  195. }
  196. static ssize_t dr_mode_show(struct device *dev,
  197. struct device_attribute *attr,
  198. char *buf)
  199. {
  200. struct brcm_usb_phy_data *priv = dev_get_drvdata(dev);
  201. return sprintf(buf, "%s\n",
  202. value_to_name(&brcm_dr_mode_to_name[0],
  203. ARRAY_SIZE(brcm_dr_mode_to_name),
  204. priv->ini.mode));
  205. }
  206. static DEVICE_ATTR_RO(dr_mode);
  207. static ssize_t dual_select_store(struct device *dev,
  208. struct device_attribute *attr,
  209. const char *buf, size_t len)
  210. {
  211. struct brcm_usb_phy_data *priv = dev_get_drvdata(dev);
  212. int value;
  213. int res;
  214. mutex_lock(&sysfs_lock);
  215. res = name_to_value(&brcm_dual_mode_to_name[0],
  216. ARRAY_SIZE(brcm_dual_mode_to_name), buf, &value);
  217. if (!res) {
  218. brcm_usb_set_dual_select(&priv->ini, value);
  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.mode = 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.mode);
  443. }
  444. if (of_property_read_bool(dn, "brcm,has-xhci"))
  445. priv->has_xhci = true;
  446. if (of_property_read_bool(dn, "brcm,has-eohci"))
  447. priv->has_eohci = true;
  448. for (x = 0; x < BRCM_REGS_MAX; x++) {
  449. if (info->required_regs[x] >= BRCM_REGS_MAX)
  450. break;
  451. err = brcm_usb_get_regs(pdev, info->required_regs[x],
  452. &priv->ini, false);
  453. if (err)
  454. return -EINVAL;
  455. }
  456. if (info->optional_reg) {
  457. err = brcm_usb_get_regs(pdev, info->optional_reg,
  458. &priv->ini, true);
  459. if (err)
  460. return -EINVAL;
  461. }
  462. err = brcm_usb_phy_dvr_init(pdev, priv, dn);
  463. if (err)
  464. return err;
  465. priv->pm_notifier.notifier_call = brcm_pm_notifier;
  466. register_pm_notifier(&priv->pm_notifier);
  467. mutex_init(&priv->mutex);
  468. /* make sure invert settings are correct */
  469. brcm_usb_init_ipp(&priv->ini);
  470. /*
  471. * Create sysfs entries for mode.
  472. * Remove "dual_select" attribute if not in dual mode
  473. */
  474. if (priv->ini.mode != USB_CTLR_MODE_DRD)
  475. brcm_usb_phy_attrs[1] = NULL;
  476. err = sysfs_create_group(&dev->kobj, &brcm_usb_phy_group);
  477. if (err)
  478. dev_warn(dev, "Error creating sysfs attributes\n");
  479. /* Get piarbctl syscon if it exists */
  480. rmap = syscon_regmap_lookup_by_phandle(dev->of_node,
  481. "syscon-piarbctl");
  482. if (IS_ERR(rmap))
  483. rmap = syscon_regmap_lookup_by_phandle(dev->of_node,
  484. "brcm,syscon-piarbctl");
  485. if (!IS_ERR(rmap))
  486. priv->ini.syscon_piarbctl = rmap;
  487. /* start with everything off */
  488. if (priv->has_xhci)
  489. brcm_usb_uninit_xhci(&priv->ini);
  490. if (priv->has_eohci)
  491. brcm_usb_uninit_eohci(&priv->ini);
  492. brcm_usb_uninit_common(&priv->ini);
  493. clk_disable_unprepare(priv->usb_20_clk);
  494. clk_disable_unprepare(priv->usb_30_clk);
  495. phy_provider = devm_of_phy_provider_register(dev, brcm_usb_phy_xlate);
  496. return PTR_ERR_OR_ZERO(phy_provider);
  497. }
  498. static int brcm_usb_phy_remove(struct platform_device *pdev)
  499. {
  500. struct brcm_usb_phy_data *priv = dev_get_drvdata(&pdev->dev);
  501. sysfs_remove_group(&pdev->dev.kobj, &brcm_usb_phy_group);
  502. unregister_pm_notifier(&priv->pm_notifier);
  503. return 0;
  504. }
  505. #ifdef CONFIG_PM_SLEEP
  506. static int brcm_usb_phy_suspend(struct device *dev)
  507. {
  508. struct brcm_usb_phy_data *priv = dev_get_drvdata(dev);
  509. if (priv->init_count) {
  510. dev_dbg(dev, "SUSPEND\n");
  511. priv->ini.wake_enabled = device_may_wakeup(dev);
  512. if (priv->phys[BRCM_USB_PHY_3_0].inited)
  513. brcm_usb_uninit_xhci(&priv->ini);
  514. if (priv->phys[BRCM_USB_PHY_2_0].inited)
  515. brcm_usb_uninit_eohci(&priv->ini);
  516. brcm_usb_uninit_common(&priv->ini);
  517. /*
  518. * Handle the clocks unless needed for wake. This has
  519. * to work for both older XHCI->3.0-clks, EOHCI->2.0-clks
  520. * and newer XHCI->2.0-clks/3.0-clks.
  521. */
  522. if (!priv->ini.wake_enabled) {
  523. if (priv->phys[BRCM_USB_PHY_3_0].inited)
  524. clk_disable_unprepare(priv->usb_30_clk);
  525. if (priv->phys[BRCM_USB_PHY_2_0].inited ||
  526. !priv->has_eohci)
  527. clk_disable_unprepare(priv->usb_20_clk);
  528. }
  529. if (priv->wake_irq >= 0)
  530. enable_irq_wake(priv->wake_irq);
  531. }
  532. return 0;
  533. }
  534. static int brcm_usb_phy_resume(struct device *dev)
  535. {
  536. struct brcm_usb_phy_data *priv = dev_get_drvdata(dev);
  537. if (!priv->ini.wake_enabled) {
  538. clk_prepare_enable(priv->usb_20_clk);
  539. clk_prepare_enable(priv->usb_30_clk);
  540. }
  541. brcm_usb_init_ipp(&priv->ini);
  542. /*
  543. * Initialize anything that was previously initialized.
  544. * Uninitialize anything that wasn't previously initialized.
  545. */
  546. if (priv->init_count) {
  547. dev_dbg(dev, "RESUME\n");
  548. if (priv->wake_irq >= 0)
  549. disable_irq_wake(priv->wake_irq);
  550. brcm_usb_init_common(&priv->ini);
  551. if (priv->phys[BRCM_USB_PHY_2_0].inited) {
  552. brcm_usb_init_eohci(&priv->ini);
  553. } else if (priv->has_eohci) {
  554. brcm_usb_uninit_eohci(&priv->ini);
  555. clk_disable_unprepare(priv->usb_20_clk);
  556. }
  557. if (priv->phys[BRCM_USB_PHY_3_0].inited) {
  558. brcm_usb_init_xhci(&priv->ini);
  559. } else if (priv->has_xhci) {
  560. brcm_usb_uninit_xhci(&priv->ini);
  561. clk_disable_unprepare(priv->usb_30_clk);
  562. if (!priv->has_eohci)
  563. clk_disable_unprepare(priv->usb_20_clk);
  564. }
  565. } else {
  566. if (priv->has_xhci)
  567. brcm_usb_uninit_xhci(&priv->ini);
  568. if (priv->has_eohci)
  569. brcm_usb_uninit_eohci(&priv->ini);
  570. brcm_usb_uninit_common(&priv->ini);
  571. clk_disable_unprepare(priv->usb_20_clk);
  572. clk_disable_unprepare(priv->usb_30_clk);
  573. }
  574. priv->ini.wake_enabled = false;
  575. return 0;
  576. }
  577. #endif /* CONFIG_PM_SLEEP */
  578. static const struct dev_pm_ops brcm_usb_phy_pm_ops = {
  579. SET_LATE_SYSTEM_SLEEP_PM_OPS(brcm_usb_phy_suspend, brcm_usb_phy_resume)
  580. };
  581. MODULE_DEVICE_TABLE(of, brcm_usb_dt_ids);
  582. static struct platform_driver brcm_usb_driver = {
  583. .probe = brcm_usb_phy_probe,
  584. .remove = brcm_usb_phy_remove,
  585. .driver = {
  586. .name = "brcmstb-usb-phy",
  587. .pm = &brcm_usb_phy_pm_ops,
  588. .of_match_table = brcm_usb_dt_ids,
  589. },
  590. };
  591. module_platform_driver(brcm_usb_driver);
  592. MODULE_ALIAS("platform:brcmstb-usb-phy");
  593. MODULE_AUTHOR("Al Cooper <[email protected]>");
  594. MODULE_DESCRIPTION("BRCM USB PHY driver");
  595. MODULE_LICENSE("GPL v2");