089-0001-phy-bcm-ns-usb2-new-driver-for-USB-2.0-PHY-on-Norths.patch 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. From d3feb406733544dbf0e239ef945a09decdceac88 Mon Sep 17 00:00:00 2001
  2. From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
  3. Date: Thu, 14 Apr 2016 11:37:43 +0200
  4. Subject: [PATCH] phy: bcm-ns-usb2: new driver for USB 2.0 PHY on Northstar
  5. MIME-Version: 1.0
  6. Content-Type: text/plain; charset=UTF-8
  7. Content-Transfer-Encoding: 8bit
  8. Northstar is a family of SoCs used in home routers. They have USB 2.0
  9. and 3.0 controllers with PHYs that need to be properly initialized.
  10. This driver provides PHY init support in a generic way and can be bound
  11. with an EHCI controller driver.
  12. There are (just a few) registers being defined in bcma header. It's
  13. because DMU/CRU registers will be also needed in other drivers. We will
  14. need them e.g. in PCIe controller/PHY driver and at some point probably
  15. in clock driver for BCM53573 chipset. By using include/linux/bcma/ we
  16. avoid code duplication.
  17. Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
  18. Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
  19. ---
  20. .../devicetree/bindings/phy/bcm-ns-usb2-phy.txt | 21 ++++
  21. drivers/phy/Kconfig | 9 ++
  22. drivers/phy/Makefile | 1 +
  23. drivers/phy/phy-bcm-ns-usb2.c | 137 +++++++++++++++++++++
  24. include/linux/bcma/bcma.h | 1 +
  25. include/linux/bcma/bcma_driver_arm_c9.h | 15 +++
  26. 6 files changed, 184 insertions(+)
  27. create mode 100644 Documentation/devicetree/bindings/phy/bcm-ns-usb2-phy.txt
  28. create mode 100644 drivers/phy/phy-bcm-ns-usb2.c
  29. create mode 100644 include/linux/bcma/bcma_driver_arm_c9.h
  30. diff --git a/Documentation/devicetree/bindings/phy/bcm-ns-usb2-phy.txt b/Documentation/devicetree/bindings/phy/bcm-ns-usb2-phy.txt
  31. new file mode 100644
  32. index 0000000..a7aee9e
  33. --- /dev/null
  34. +++ b/Documentation/devicetree/bindings/phy/bcm-ns-usb2-phy.txt
  35. @@ -0,0 +1,21 @@
  36. +Driver for Broadcom Northstar USB 2.0 PHY
  37. +
  38. +Required properties:
  39. +- compatible: brcm,ns-usb2-phy
  40. +- reg: iomem address range of DMU (Device Management Unit)
  41. +- reg-names: "dmu", the only needed & supported reg right now
  42. +- clocks: USB PHY reference clock
  43. +- clock-names: "phy-ref-clk", the only needed & supported clock right now
  44. +
  45. +To initialize USB 2.0 PHY driver needs to setup PLL correctly. To do this it
  46. +requires passing phandle to the USB PHY reference clock.
  47. +
  48. +Example:
  49. + usb2-phy {
  50. + compatible = "brcm,ns-usb2-phy";
  51. + reg = <0x1800c000 0x1000>;
  52. + reg-names = "dmu";
  53. + #phy-cells = <0>;
  54. + clocks = <&genpll BCM_NSP_GENPLL_USB_PHY_REF_CLK>;
  55. + clock-names = "phy-ref-clk";
  56. + };
  57. diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
  58. index f6ff76e..f2b458f 100644
  59. --- a/drivers/phy/Kconfig
  60. +++ b/drivers/phy/Kconfig
  61. @@ -15,6 +15,15 @@ config GENERIC_PHY
  62. phy users can obtain reference to the PHY. All the users of this
  63. framework should select this config.
  64. +config PHY_BCM_NS_USB2
  65. + tristate "Broadcom Northstar USB 2.0 PHY Driver"
  66. + depends on ARCH_BCM_IPROC || COMPILE_TEST
  67. + depends on HAS_IOMEM && OF
  68. + select GENERIC_PHY
  69. + help
  70. + Enable this to support Broadcom USB 2.0 PHY connected to the USB
  71. + controller on Northstar family.
  72. +
  73. config PHY_BERLIN_USB
  74. tristate "Marvell Berlin USB PHY Driver"
  75. depends on ARCH_BERLIN && RESET_CONTROLLER && HAS_IOMEM && OF
  76. diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
  77. index f03fa1f..0de09e1 100644
  78. --- a/drivers/phy/Makefile
  79. +++ b/drivers/phy/Makefile
  80. @@ -3,6 +3,7 @@
  81. #
  82. obj-$(CONFIG_GENERIC_PHY) += phy-core.o
  83. +obj-$(CONFIG_PHY_BCM_NS_USB2) += phy-bcm-ns-usb2.o
  84. obj-$(CONFIG_PHY_BERLIN_USB) += phy-berlin-usb.o
  85. obj-$(CONFIG_PHY_BERLIN_SATA) += phy-berlin-sata.o
  86. obj-$(CONFIG_PHY_DM816X_USB) += phy-dm816x-usb.o
  87. diff --git a/drivers/phy/phy-bcm-ns-usb2.c b/drivers/phy/phy-bcm-ns-usb2.c
  88. new file mode 100644
  89. index 0000000..95ab6b2
  90. --- /dev/null
  91. +++ b/drivers/phy/phy-bcm-ns-usb2.c
  92. @@ -0,0 +1,137 @@
  93. +/*
  94. + * Broadcom Northstar USB 2.0 PHY Driver
  95. + *
  96. + * Copyright (C) 2016 Rafał Miłecki <zajec5@gmail.com>
  97. + *
  98. + * This program is free software; you can redistribute it and/or modify
  99. + * it under the terms of the GNU General Public License version 2 as
  100. + * published by the Free Software Foundation.
  101. + *
  102. + */
  103. +
  104. +#include <linux/bcma/bcma.h>
  105. +#include <linux/clk.h>
  106. +#include <linux/delay.h>
  107. +#include <linux/err.h>
  108. +#include <linux/module.h>
  109. +#include <linux/of_address.h>
  110. +#include <linux/of_platform.h>
  111. +#include <linux/phy/phy.h>
  112. +#include <linux/platform_device.h>
  113. +#include <linux/slab.h>
  114. +
  115. +struct bcm_ns_usb2 {
  116. + struct device *dev;
  117. + struct clk *ref_clk;
  118. + struct phy *phy;
  119. + void __iomem *dmu;
  120. +};
  121. +
  122. +static int bcm_ns_usb2_phy_init(struct phy *phy)
  123. +{
  124. + struct bcm_ns_usb2 *usb2 = phy_get_drvdata(phy);
  125. + struct device *dev = usb2->dev;
  126. + void __iomem *dmu = usb2->dmu;
  127. + u32 ref_clk_rate, usb2ctl, usb_pll_ndiv, usb_pll_pdiv;
  128. + int err = 0;
  129. +
  130. + err = clk_prepare_enable(usb2->ref_clk);
  131. + if (err < 0) {
  132. + dev_err(dev, "Failed to prepare ref clock: %d\n", err);
  133. + goto err_out;
  134. + }
  135. +
  136. + ref_clk_rate = clk_get_rate(usb2->ref_clk);
  137. + if (!ref_clk_rate) {
  138. + dev_err(dev, "Failed to get ref clock rate\n");
  139. + err = -EINVAL;
  140. + goto err_clk_off;
  141. + }
  142. +
  143. + usb2ctl = readl(dmu + BCMA_DMU_CRU_USB2_CONTROL);
  144. +
  145. + if (usb2ctl & BCMA_DMU_CRU_USB2_CONTROL_USB_PLL_PDIV_MASK) {
  146. + usb_pll_pdiv = usb2ctl;
  147. + usb_pll_pdiv &= BCMA_DMU_CRU_USB2_CONTROL_USB_PLL_PDIV_MASK;
  148. + usb_pll_pdiv >>= BCMA_DMU_CRU_USB2_CONTROL_USB_PLL_PDIV_SHIFT;
  149. + } else {
  150. + usb_pll_pdiv = 1 << 3;
  151. + }
  152. +
  153. + /* Calculate ndiv based on a solid 1920 MHz that is for USB2 PHY */
  154. + usb_pll_ndiv = (1920000000 * usb_pll_pdiv) / ref_clk_rate;
  155. +
  156. + /* Unlock DMU PLL settings with some magic value */
  157. + writel(0x0000ea68, dmu + BCMA_DMU_CRU_CLKSET_KEY);
  158. +
  159. + /* Write USB 2.0 PLL control setting */
  160. + usb2ctl &= ~BCMA_DMU_CRU_USB2_CONTROL_USB_PLL_NDIV_MASK;
  161. + usb2ctl |= usb_pll_ndiv << BCMA_DMU_CRU_USB2_CONTROL_USB_PLL_NDIV_SHIFT;
  162. + writel(usb2ctl, dmu + BCMA_DMU_CRU_USB2_CONTROL);
  163. +
  164. + /* Lock DMU PLL settings */
  165. + writel(0x00000000, dmu + BCMA_DMU_CRU_CLKSET_KEY);
  166. +
  167. +err_clk_off:
  168. + clk_disable_unprepare(usb2->ref_clk);
  169. +err_out:
  170. + return err;
  171. +}
  172. +
  173. +static const struct phy_ops ops = {
  174. + .init = bcm_ns_usb2_phy_init,
  175. + .owner = THIS_MODULE,
  176. +};
  177. +
  178. +static int bcm_ns_usb2_probe(struct platform_device *pdev)
  179. +{
  180. + struct device *dev = &pdev->dev;
  181. + struct bcm_ns_usb2 *usb2;
  182. + struct resource *res;
  183. + struct phy_provider *phy_provider;
  184. +
  185. + usb2 = devm_kzalloc(&pdev->dev, sizeof(*usb2), GFP_KERNEL);
  186. + if (!usb2)
  187. + return -ENOMEM;
  188. + usb2->dev = dev;
  189. +
  190. + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dmu");
  191. + usb2->dmu = devm_ioremap_resource(dev, res);
  192. + if (IS_ERR(usb2->dmu)) {
  193. + dev_err(dev, "Failed to map DMU regs\n");
  194. + return PTR_ERR(usb2->dmu);
  195. + }
  196. +
  197. + usb2->ref_clk = devm_clk_get(dev, "phy-ref-clk");
  198. + if (IS_ERR(usb2->ref_clk)) {
  199. + dev_err(dev, "Clock not defined\n");
  200. + return PTR_ERR(usb2->ref_clk);
  201. + }
  202. +
  203. + usb2->phy = devm_phy_create(dev, NULL, &ops);
  204. + if (IS_ERR(dev))
  205. + return PTR_ERR(dev);
  206. +
  207. + phy_set_drvdata(usb2->phy, usb2);
  208. + platform_set_drvdata(pdev, usb2);
  209. +
  210. + phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
  211. + return PTR_ERR_OR_ZERO(phy_provider);
  212. +}
  213. +
  214. +static const struct of_device_id bcm_ns_usb2_id_table[] = {
  215. + { .compatible = "brcm,ns-usb2-phy", },
  216. + {},
  217. +};
  218. +MODULE_DEVICE_TABLE(of, bcm_ns_usb2_id_table);
  219. +
  220. +static struct platform_driver bcm_ns_usb2_driver = {
  221. + .probe = bcm_ns_usb2_probe,
  222. + .driver = {
  223. + .name = "bcm_ns_usb2",
  224. + .of_match_table = bcm_ns_usb2_id_table,
  225. + },
  226. +};
  227. +module_platform_driver(bcm_ns_usb2_driver);
  228. +
  229. +MODULE_LICENSE("GPL v2");
  230. diff --git a/include/linux/bcma/bcma.h b/include/linux/bcma/bcma.h
  231. index 0367c63..e6b41f4 100644
  232. --- a/include/linux/bcma/bcma.h
  233. +++ b/include/linux/bcma/bcma.h
  234. @@ -4,6 +4,7 @@
  235. #include <linux/pci.h>
  236. #include <linux/mod_devicetable.h>
  237. +#include <linux/bcma/bcma_driver_arm_c9.h>
  238. #include <linux/bcma/bcma_driver_chipcommon.h>
  239. #include <linux/bcma/bcma_driver_pci.h>
  240. #include <linux/bcma/bcma_driver_pcie2.h>
  241. diff --git a/include/linux/bcma/bcma_driver_arm_c9.h b/include/linux/bcma/bcma_driver_arm_c9.h
  242. new file mode 100644
  243. index 0000000..93bd73d
  244. --- /dev/null
  245. +++ b/include/linux/bcma/bcma_driver_arm_c9.h
  246. @@ -0,0 +1,15 @@
  247. +#ifndef LINUX_BCMA_DRIVER_ARM_C9_H_
  248. +#define LINUX_BCMA_DRIVER_ARM_C9_H_
  249. +
  250. +/* DMU (Device Management Unit) */
  251. +#define BCMA_DMU_CRU_USB2_CONTROL 0x0164
  252. +#define BCMA_DMU_CRU_USB2_CONTROL_USB_PLL_NDIV_MASK 0x00000FFC
  253. +#define BCMA_DMU_CRU_USB2_CONTROL_USB_PLL_NDIV_SHIFT 2
  254. +#define BCMA_DMU_CRU_USB2_CONTROL_USB_PLL_PDIV_MASK 0x00007000
  255. +#define BCMA_DMU_CRU_USB2_CONTROL_USB_PLL_PDIV_SHIFT 12
  256. +#define BCMA_DMU_CRU_CLKSET_KEY 0x0180
  257. +#define BCMA_DMU_CRU_STRAPS_CTRL 0x02A0
  258. +#define BCMA_DMU_CRU_STRAPS_CTRL_USB3 0x00000010
  259. +#define BCMA_DMU_CRU_STRAPS_CTRL_4BYTE 0x00008000
  260. +
  261. +#endif /* LINUX_BCMA_DRIVER_ARM_C9_H_ */
  262. --
  263. 1.8.4.5