mvmdio.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright (C) 2018 Marvell International Ltd.
  4. * Author: Ken Ma<make@marvell.com>
  5. */
  6. #include <common.h>
  7. #include <dm.h>
  8. #include <dm/device-internal.h>
  9. #include <dm/lists.h>
  10. #include <miiphy.h>
  11. #include <phy.h>
  12. #include <asm/io.h>
  13. #include <wait_bit.h>
  14. #include <linux/bitops.h>
  15. #define MVMDIO_SMI_DATA_SHIFT 0
  16. #define MVMDIO_SMI_PHY_ADDR_SHIFT 16
  17. #define MVMDIO_SMI_PHY_REG_SHIFT 21
  18. #define MVMDIO_SMI_READ_OPERATION BIT(26)
  19. #define MVMDIO_SMI_WRITE_OPERATION 0
  20. #define MVMDIO_SMI_READ_VALID BIT(27)
  21. #define MVMDIO_SMI_BUSY BIT(28)
  22. #define MVMDIO_XSMI_MGNT_REG 0x0
  23. #define MVMDIO_XSMI_PHYADDR_SHIFT 16
  24. #define MVMDIO_XSMI_DEVADDR_SHIFT 21
  25. #define MVMDIO_XSMI_WRITE_OPERATION (0x5 << 26)
  26. #define MVMDIO_XSMI_READ_OPERATION (0x7 << 26)
  27. #define MVMDIO_XSMI_READ_VALID BIT(29)
  28. #define MVMDIO_XSMI_BUSY BIT(30)
  29. #define MVMDIO_XSMI_ADDR_REG 0x8
  30. enum mvmdio_bus_type {
  31. BUS_TYPE_SMI,
  32. BUS_TYPE_XSMI
  33. };
  34. struct mvmdio_priv {
  35. void *mdio_base;
  36. enum mvmdio_bus_type type;
  37. };
  38. static int mvmdio_smi_read(struct udevice *dev, int addr,
  39. int devad, int reg)
  40. {
  41. struct mvmdio_priv *priv = dev_get_priv(dev);
  42. u32 val;
  43. int ret;
  44. if (devad != MDIO_DEVAD_NONE)
  45. return -EOPNOTSUPP;
  46. ret = wait_for_bit_le32(priv->mdio_base, MVMDIO_SMI_BUSY,
  47. false, CONFIG_SYS_HZ, false);
  48. if (ret < 0)
  49. return ret;
  50. writel(((addr << MVMDIO_SMI_PHY_ADDR_SHIFT) |
  51. (reg << MVMDIO_SMI_PHY_REG_SHIFT) |
  52. MVMDIO_SMI_READ_OPERATION),
  53. priv->mdio_base);
  54. ret = wait_for_bit_le32(priv->mdio_base, MVMDIO_SMI_BUSY,
  55. false, CONFIG_SYS_HZ, false);
  56. if (ret < 0)
  57. return ret;
  58. val = readl(priv->mdio_base);
  59. if (!(val & MVMDIO_SMI_READ_VALID)) {
  60. pr_err("SMI bus read not valid\n");
  61. return -ENODEV;
  62. }
  63. return val & GENMASK(15, 0);
  64. }
  65. static int mvmdio_smi_write(struct udevice *dev, int addr, int devad,
  66. int reg, u16 value)
  67. {
  68. struct mvmdio_priv *priv = dev_get_priv(dev);
  69. int ret;
  70. if (devad != MDIO_DEVAD_NONE)
  71. return -EOPNOTSUPP;
  72. ret = wait_for_bit_le32(priv->mdio_base, MVMDIO_SMI_BUSY,
  73. false, CONFIG_SYS_HZ, false);
  74. if (ret < 0)
  75. return ret;
  76. writel(((addr << MVMDIO_SMI_PHY_ADDR_SHIFT) |
  77. (reg << MVMDIO_SMI_PHY_REG_SHIFT) |
  78. MVMDIO_SMI_WRITE_OPERATION |
  79. (value << MVMDIO_SMI_DATA_SHIFT)),
  80. priv->mdio_base);
  81. return 0;
  82. }
  83. static int mvmdio_xsmi_read(struct udevice *dev, int addr,
  84. int devad, int reg)
  85. {
  86. struct mvmdio_priv *priv = dev_get_priv(dev);
  87. int ret;
  88. if (devad == MDIO_DEVAD_NONE)
  89. return -EOPNOTSUPP;
  90. ret = wait_for_bit_le32(priv->mdio_base, MVMDIO_XSMI_BUSY,
  91. false, CONFIG_SYS_HZ, false);
  92. if (ret < 0)
  93. return ret;
  94. writel(reg & GENMASK(15, 0), priv->mdio_base + MVMDIO_XSMI_ADDR_REG);
  95. writel(((addr << MVMDIO_XSMI_PHYADDR_SHIFT) |
  96. (devad << MVMDIO_XSMI_DEVADDR_SHIFT) |
  97. MVMDIO_XSMI_READ_OPERATION),
  98. priv->mdio_base + MVMDIO_XSMI_MGNT_REG);
  99. ret = wait_for_bit_le32(priv->mdio_base, MVMDIO_XSMI_BUSY,
  100. false, CONFIG_SYS_HZ, false);
  101. if (ret < 0)
  102. return ret;
  103. if (!(readl(priv->mdio_base + MVMDIO_XSMI_MGNT_REG) &
  104. MVMDIO_XSMI_READ_VALID)) {
  105. pr_err("XSMI bus read not valid\n");
  106. return -ENODEV;
  107. }
  108. return readl(priv->mdio_base + MVMDIO_XSMI_MGNT_REG) & GENMASK(15, 0);
  109. }
  110. static int mvmdio_xsmi_write(struct udevice *dev, int addr, int devad,
  111. int reg, u16 value)
  112. {
  113. struct mvmdio_priv *priv = dev_get_priv(dev);
  114. int ret;
  115. if (devad == MDIO_DEVAD_NONE)
  116. return -EOPNOTSUPP;
  117. ret = wait_for_bit_le32(priv->mdio_base, MVMDIO_XSMI_BUSY,
  118. false, CONFIG_SYS_HZ, false);
  119. if (ret < 0)
  120. return ret;
  121. writel(reg & GENMASK(15, 0), priv->mdio_base + MVMDIO_XSMI_ADDR_REG);
  122. writel(((addr << MVMDIO_XSMI_PHYADDR_SHIFT) |
  123. (devad << MVMDIO_XSMI_DEVADDR_SHIFT) |
  124. MVMDIO_XSMI_WRITE_OPERATION | value),
  125. priv->mdio_base + MVMDIO_XSMI_MGNT_REG);
  126. return 0;
  127. }
  128. static int mvmdio_read(struct udevice *dev, int addr, int devad, int reg)
  129. {
  130. struct mvmdio_priv *priv = dev_get_priv(dev);
  131. int err = -ENOTSUPP;
  132. switch (priv->type) {
  133. case BUS_TYPE_SMI:
  134. err = mvmdio_smi_read(dev, addr, devad, reg);
  135. break;
  136. case BUS_TYPE_XSMI:
  137. err = mvmdio_xsmi_read(dev, addr, devad, reg);
  138. break;
  139. }
  140. return err;
  141. }
  142. static int mvmdio_write(struct udevice *dev, int addr, int devad, int reg,
  143. u16 value)
  144. {
  145. struct mvmdio_priv *priv = dev_get_priv(dev);
  146. int err = -ENOTSUPP;
  147. switch (priv->type) {
  148. case BUS_TYPE_SMI:
  149. err = mvmdio_smi_write(dev, addr, devad, reg, value);
  150. break;
  151. case BUS_TYPE_XSMI:
  152. err = mvmdio_xsmi_write(dev, addr, devad, reg, value);
  153. break;
  154. }
  155. return err;
  156. }
  157. /*
  158. * Name the device, we use the device tree node name.
  159. * This can be overwritten by MDIO class code if device-name property is
  160. * present.
  161. */
  162. static int mvmdio_bind(struct udevice *dev)
  163. {
  164. if (ofnode_valid(dev->node))
  165. device_set_name(dev, ofnode_get_name(dev->node));
  166. return 0;
  167. }
  168. /* Get device base address and type, either C22 SMII or C45 XSMI */
  169. static int mvmdio_probe(struct udevice *dev)
  170. {
  171. struct mvmdio_priv *priv = dev_get_priv(dev);
  172. priv->mdio_base = (void *)dev_read_addr(dev);
  173. priv->type = (enum mvmdio_bus_type)dev_get_driver_data(dev);
  174. return 0;
  175. }
  176. static const struct mdio_ops mvmdio_ops = {
  177. .read = mvmdio_read,
  178. .write = mvmdio_write,
  179. };
  180. static const struct udevice_id mvmdio_ids[] = {
  181. { .compatible = "marvell,orion-mdio", .data = BUS_TYPE_SMI },
  182. { .compatible = "marvell,xmdio", .data = BUS_TYPE_XSMI },
  183. { }
  184. };
  185. U_BOOT_DRIVER(mvmdio) = {
  186. .name = "mvmdio",
  187. .id = UCLASS_MDIO,
  188. .of_match = mvmdio_ids,
  189. .bind = mvmdio_bind,
  190. .probe = mvmdio_probe,
  191. .ops = &mvmdio_ops,
  192. .priv_auto_alloc_size = sizeof(struct mvmdio_priv),
  193. };