702-powerpc_ibm_phy_add_dt_parser.patch 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328
  1. From b1c54da602ae9215cfbde1c3ed3b6296b76f07fc Mon Sep 17 00:00:00 2001
  2. Message-Id: <b1c54da602ae9215cfbde1c3ed3b6296b76f07fc.1486337989.git.chunkeey@googlemail.com>
  3. In-Reply-To: <246bd6614529d28dc48b11981ab5dae7a7364fc2.1486337989.git.chunkeey@googlemail.com>
  4. References: <246bd6614529d28dc48b11981ab5dae7a7364fc2.1486337989.git.chunkeey@googlemail.com>
  5. From: Christian Lamparter <[email protected]>
  6. Date: Mon, 13 Jun 2016 15:42:21 +0200
  7. Subject: [RFC 2/2] net: emac: add support for device-tree based PHY discovery
  8. and setup
  9. To: [email protected],
  10. [email protected]
  11. Cc: David S. Miller <[email protected]>,
  12. Ivan Mikhaylov <[email protected]>,
  13. Mark Rutland <[email protected]>,
  14. Rob Herring <[email protected]>
  15. This patch adds glue-code that allows the EMAC driver to interface
  16. with the existing dt-supported PHYs in drivers/net/phy.
  17. Because currently, the emac driver maintains a small library of
  18. supported phys for in a private phy.c file located in the drivers
  19. directory.
  20. The support is limited to mostly single ethernet transceiver like the:
  21. CIS8201, BCM5248, ET1011C, Marvell 88E1111 and 88E1112, AR8035.
  22. However, routers like the Netgear WNDR4700 and Cisco Meraki MX60(W)
  23. have a 5-port switch (QCA8327N) attached to the MDIO of the EMAC.
  24. The switch chip has already a proper phy-driver (ar8216) that uses
  25. the generic phy library.
  26. Signed-off-by: Christian Lamparter <[email protected]>
  27. ---
  28. --- a/drivers/net/ethernet/ibm/emac/core.c
  29. +++ b/drivers/net/ethernet/ibm/emac/core.c
  30. @@ -42,6 +42,7 @@
  31. #include <linux/of_address.h>
  32. #include <linux/of_irq.h>
  33. #include <linux/of_net.h>
  34. +#include <linux/of_mdio.h>
  35. #include <linux/slab.h>
  36. #include <asm/processor.h>
  37. @@ -2422,6 +2423,229 @@ static int emac_read_uint_prop(struct de
  38. return 0;
  39. }
  40. +static void emac_adjust_link(struct net_device *ndev)
  41. +{
  42. + struct emac_instance *dev = netdev_priv(ndev);
  43. + struct phy_device *phy = dev->phy_dev;
  44. +
  45. + dev->phy.autoneg = phy->autoneg;
  46. + dev->phy.speed = phy->speed;
  47. + dev->phy.duplex = phy->duplex;
  48. + dev->phy.pause = phy->pause;
  49. + dev->phy.asym_pause = phy->asym_pause;
  50. + dev->phy.advertising = phy->advertising;
  51. +}
  52. +
  53. +static int emac_mii_bus_read(struct mii_bus *bus, int addr, int regnum)
  54. +{
  55. + return emac_mdio_read(bus->priv, addr, regnum);
  56. +}
  57. +
  58. +static int emac_mii_bus_write(struct mii_bus *bus, int addr, int regnum, u16 val)
  59. +{
  60. + emac_mdio_write(bus->priv, addr, regnum, val);
  61. + return 0;
  62. +}
  63. +
  64. +static int emac_mii_bus_reset(struct mii_bus *bus)
  65. +{
  66. + struct emac_instance *dev = netdev_priv(bus->priv);
  67. + int err;
  68. +
  69. + err = emac_reset(dev);
  70. + if (err)
  71. + return err;
  72. + /* Meraki MX60(W)'s uboot will disable the switch and
  73. + * a bus reset won't do anything. */
  74. + emac_mii_reset_phy(&dev->phy);
  75. + return 0;
  76. +}
  77. +
  78. +static int emac_mdio_setup_aneg(struct mii_phy *phy, u32 advertise)
  79. +{
  80. + struct net_device *ndev = phy->dev;
  81. + struct emac_instance *dev = netdev_priv(ndev);
  82. +
  83. + dev->phy.autoneg = AUTONEG_ENABLE;
  84. + dev->phy.speed = SPEED_1000;
  85. + dev->phy.duplex = DUPLEX_FULL;
  86. + dev->phy.advertising = advertise;
  87. + phy->autoneg = AUTONEG_ENABLE;
  88. + phy->speed = dev->phy.speed;
  89. + phy->duplex = dev->phy.duplex;
  90. + phy->advertising = advertise;
  91. + return phy_start_aneg(dev->phy_dev);
  92. +}
  93. +
  94. +static int emac_mdio_setup_forced(struct mii_phy *phy, int speed, int fd)
  95. +{
  96. + struct net_device *ndev = phy->dev;
  97. + struct emac_instance *dev = netdev_priv(ndev);
  98. +
  99. + dev->phy.autoneg = AUTONEG_DISABLE;
  100. + dev->phy.speed = speed;
  101. + dev->phy.duplex = fd;
  102. + phy->autoneg = AUTONEG_DISABLE;
  103. + phy->speed = speed;
  104. + phy->duplex = fd;
  105. + return phy_start_aneg(dev->phy_dev);
  106. +}
  107. +
  108. +static int emac_mdio_poll_link(struct mii_phy *phy)
  109. +{
  110. + struct net_device *ndev = phy->dev;
  111. + struct emac_instance *dev = netdev_priv(ndev);
  112. + int res;
  113. +
  114. + res = phy_read_status(dev->phy_dev);
  115. + if (res) {
  116. + dev_err(&dev->ofdev->dev, "link update failed (%d).", res);
  117. + return ethtool_op_get_link(ndev);
  118. + }
  119. +
  120. + return dev->phy_dev->link;
  121. +}
  122. +
  123. +static int emac_mdio_read_link(struct mii_phy *phy)
  124. +{
  125. + struct net_device *ndev = phy->dev;
  126. + struct emac_instance *dev = netdev_priv(ndev);
  127. + int res;
  128. +
  129. + res = phy_read_status(dev->phy_dev);
  130. + if (res)
  131. + return res;
  132. +
  133. + dev->phy.speed = phy->speed;
  134. + dev->phy.duplex = phy->duplex;
  135. + dev->phy.pause = phy->pause;
  136. + dev->phy.asym_pause = phy->asym_pause;
  137. + return 0;
  138. +}
  139. +
  140. +static int emac_mdio_init_phy(struct mii_phy *phy)
  141. +{
  142. + struct net_device *ndev = phy->dev;
  143. + struct emac_instance *dev = netdev_priv(ndev);
  144. +
  145. + phy_start(dev->phy_dev);
  146. + dev->phy.autoneg = phy->autoneg;
  147. + dev->phy.speed = phy->speed;
  148. + dev->phy.duplex = phy->duplex;
  149. + dev->phy.advertising = phy->advertising;
  150. + dev->phy.pause = phy->pause;
  151. + dev->phy.asym_pause = phy->asym_pause;
  152. +
  153. + return phy_init_hw(dev->phy_dev);
  154. +}
  155. +
  156. +static const struct mii_phy_ops emac_dt_mdio_phy_ops = {
  157. + .init = emac_mdio_init_phy,
  158. + .setup_aneg = emac_mdio_setup_aneg,
  159. + .setup_forced = emac_mdio_setup_forced,
  160. + .poll_link = emac_mdio_poll_link,
  161. + .read_link = emac_mdio_read_link,
  162. +};
  163. +
  164. +static int emac_dt_mdio_probe(struct emac_instance *dev)
  165. +{
  166. + struct device_node *mii_np;
  167. + int res;
  168. +
  169. + mii_np = of_get_child_by_name(dev->ofdev->dev.of_node, "mdio");
  170. + if (!mii_np) {
  171. + dev_err(&dev->ofdev->dev, "no mdio definition found.");
  172. + return -ENODEV;
  173. + }
  174. +
  175. + if (!of_device_is_available(mii_np)) {
  176. + res = 1;
  177. + goto put_node;
  178. + }
  179. +
  180. + dev->mii_bus = devm_mdiobus_alloc(&dev->ofdev->dev);
  181. + if (!dev->mii_bus) {
  182. + res = -ENOMEM;
  183. + goto put_node;
  184. + }
  185. +
  186. + dev->mii_bus->priv = dev->ndev;
  187. + dev->mii_bus->parent = dev->ndev->dev.parent;
  188. + dev->mii_bus->name = "emac_mdio";
  189. + dev->mii_bus->read = &emac_mii_bus_read;
  190. + dev->mii_bus->write = &emac_mii_bus_write;
  191. + dev->mii_bus->reset = &emac_mii_bus_reset;
  192. + snprintf(dev->mii_bus->id, MII_BUS_ID_SIZE, "%s", dev->ofdev->name);
  193. + res = of_mdiobus_register(dev->mii_bus, mii_np);
  194. + if (res) {
  195. + dev_err(&dev->ofdev->dev, "cannot register MDIO bus %s (%d)",
  196. + dev->mii_bus->name, res);
  197. + }
  198. +
  199. + put_node:
  200. + of_node_put(mii_np);
  201. + return res;
  202. +}
  203. +
  204. +static int emac_dt_phy_probe(struct emac_instance *dev,
  205. + struct device_node *phy_handle)
  206. +{
  207. + u32 phy_flags = 0;
  208. + int res;
  209. +
  210. + res = of_property_read_u32(phy_handle, "phy-flags", &phy_flags);
  211. + if (res < 0 && res != -EINVAL)
  212. + return res;
  213. +
  214. + dev->phy.def = devm_kzalloc(&dev->ofdev->dev, sizeof(*dev->phy.def),
  215. + GFP_KERNEL);
  216. + if (!dev->phy.def)
  217. + return -ENOMEM;
  218. +
  219. + dev->phy_dev = of_phy_connect(dev->ndev, phy_handle,
  220. + &emac_adjust_link, phy_flags,
  221. + PHY_INTERFACE_MODE_RGMII);
  222. + if (!dev->phy_dev) {
  223. + dev_err(&dev->ofdev->dev, "failed to connect to PHY.\n");
  224. + return -ENODEV;
  225. + }
  226. +
  227. + dev->phy.def->phy_id = dev->phy_dev->drv->phy_id;
  228. + dev->phy.def->phy_id_mask = dev->phy_dev->drv->phy_id_mask;
  229. + dev->phy.def->name = dev->phy_dev->drv->name;
  230. + dev->phy.def->ops = &emac_dt_mdio_phy_ops;
  231. + dev->phy.features = dev->phy_dev->supported;
  232. + dev->phy.address = dev->phy_dev->mdio.addr;
  233. + dev->phy.mode = dev->phy_dev->interface;
  234. + return 0;
  235. +}
  236. +
  237. +static int emac_probe_dt_phy(struct emac_instance *dev)
  238. +{
  239. + struct device_node *np = dev->ofdev->dev.of_node;
  240. + struct device_node *phy_handle;
  241. + int res = 0;
  242. +
  243. + phy_handle = of_parse_phandle(np, "phy-handle", 0);
  244. +
  245. + if (phy_handle) {
  246. + res = emac_dt_mdio_probe(dev);
  247. + if (!res) {
  248. + res = emac_dt_phy_probe(dev, phy_handle);
  249. + if (!res)
  250. + res = 1;
  251. + else
  252. + mdiobus_unregister(dev->mii_bus);
  253. + }
  254. + }
  255. +
  256. + of_node_put(phy_handle);
  257. + /* if no phy device was specified in the device tree, then we fallback
  258. + * to the old emac_phy.c probe code for compatibility reasons.
  259. + */
  260. + return res;
  261. +}
  262. +
  263. static int emac_init_phy(struct emac_instance *dev)
  264. {
  265. struct device_node *np = dev->ofdev->dev.of_node;
  266. @@ -2492,6 +2716,22 @@ static int emac_init_phy(struct emac_ins
  267. emac_configure(dev);
  268. + if (emac_has_feature(dev, EMAC_FTR_HAS_RGMII)) {
  269. + int res = emac_probe_dt_phy(dev);
  270. +
  271. + if (res == 1) {
  272. + mutex_unlock(&emac_phy_map_lock);
  273. + goto init_phy;
  274. + } else if (res < 0) {
  275. + mutex_unlock(&emac_phy_map_lock);
  276. + dev_err(&dev->ofdev->dev, "failed to attach dt phy (%d).\n",
  277. + res);
  278. + return res;
  279. + }
  280. +
  281. + /* continue with old code */
  282. + }
  283. +
  284. if (dev->phy_address != 0xffffffff)
  285. phy_map = ~(1 << dev->phy_address);
  286. @@ -2519,6 +2759,7 @@ static int emac_init_phy(struct emac_ins
  287. return -ENXIO;
  288. }
  289. + init_phy:
  290. /* Init PHY */
  291. if (dev->phy.def->ops->init)
  292. dev->phy.def->ops->init(&dev->phy);
  293. @@ -2988,6 +3229,12 @@ static int emac_remove(struct platform_d
  294. if (emac_has_feature(dev, EMAC_FTR_HAS_ZMII))
  295. zmii_detach(dev->zmii_dev, dev->zmii_port);
  296. + if (dev->phy_dev)
  297. + phy_disconnect(dev->phy_dev);
  298. +
  299. + if (dev->mii_bus)
  300. + mdiobus_unregister(dev->mii_bus);
  301. +
  302. busy_phy_map &= ~(1 << dev->phy.address);
  303. DBG(dev, "busy_phy_map now %#x" NL, busy_phy_map);
  304. --- a/drivers/net/ethernet/ibm/emac/core.h
  305. +++ b/drivers/net/ethernet/ibm/emac/core.h
  306. @@ -199,6 +199,10 @@ struct emac_instance {
  307. struct emac_instance *mdio_instance;
  308. struct mutex mdio_lock;
  309. + /* Device-tree based phy configuration */
  310. + struct mii_bus *mii_bus;
  311. + struct phy_device *phy_dev;
  312. +
  313. /* ZMII infos if any */
  314. u32 zmii_ph;
  315. u32 zmii_port;