cpsw_mdio.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * CPSW MDIO generic driver for TI AMxx/K2x/EMAC devices.
  4. *
  5. * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
  6. */
  7. #include <common.h>
  8. #include <log.h>
  9. #include <malloc.h>
  10. #include <asm/io.h>
  11. #include <miiphy.h>
  12. #include <wait_bit.h>
  13. #include <linux/bitops.h>
  14. #include <linux/delay.h>
  15. struct cpsw_mdio_regs {
  16. u32 version;
  17. u32 control;
  18. #define CONTROL_IDLE BIT(31)
  19. #define CONTROL_ENABLE BIT(30)
  20. #define CONTROL_FAULT BIT(19)
  21. #define CONTROL_FAULT_ENABLE BIT(18)
  22. #define CONTROL_DIV_MASK GENMASK(15, 0)
  23. u32 alive;
  24. u32 link;
  25. u32 linkintraw;
  26. u32 linkintmasked;
  27. u32 __reserved_0[2];
  28. u32 userintraw;
  29. u32 userintmasked;
  30. u32 userintmaskset;
  31. u32 userintmaskclr;
  32. u32 __reserved_1[20];
  33. struct {
  34. u32 access;
  35. u32 physel;
  36. #define USERACCESS_GO BIT(31)
  37. #define USERACCESS_WRITE BIT(30)
  38. #define USERACCESS_ACK BIT(29)
  39. #define USERACCESS_READ (0)
  40. #define USERACCESS_PHY_REG_SHIFT (21)
  41. #define USERACCESS_PHY_ADDR_SHIFT (16)
  42. #define USERACCESS_DATA GENMASK(15, 0)
  43. } user[0];
  44. };
  45. #define CPSW_MDIO_DIV_DEF 0xff
  46. #define PHY_REG_MASK 0x1f
  47. #define PHY_ID_MASK 0x1f
  48. /*
  49. * This timeout definition is a worst-case ultra defensive measure against
  50. * unexpected controller lock ups. Ideally, we should never ever hit this
  51. * scenario in practice.
  52. */
  53. #define CPSW_MDIO_TIMEOUT 100 /* msecs */
  54. struct cpsw_mdio {
  55. struct cpsw_mdio_regs *regs;
  56. struct mii_dev *bus;
  57. int div;
  58. };
  59. /* wait until hardware is ready for another user access */
  60. static int cpsw_mdio_wait_for_user_access(struct cpsw_mdio *mdio)
  61. {
  62. return wait_for_bit_le32(&mdio->regs->user[0].access,
  63. USERACCESS_GO, false,
  64. CPSW_MDIO_TIMEOUT, false);
  65. }
  66. static int cpsw_mdio_read(struct mii_dev *bus, int phy_id,
  67. int dev_addr, int phy_reg)
  68. {
  69. struct cpsw_mdio *mdio = bus->priv;
  70. int data, ret;
  71. u32 reg;
  72. if (phy_reg & ~PHY_REG_MASK || phy_id & ~PHY_ID_MASK)
  73. return -EINVAL;
  74. ret = cpsw_mdio_wait_for_user_access(mdio);
  75. if (ret)
  76. return ret;
  77. reg = (USERACCESS_GO | USERACCESS_READ |
  78. (phy_reg << USERACCESS_PHY_REG_SHIFT) |
  79. (phy_id << USERACCESS_PHY_ADDR_SHIFT));
  80. writel(reg, &mdio->regs->user[0].access);
  81. ret = cpsw_mdio_wait_for_user_access(mdio);
  82. if (ret)
  83. return ret;
  84. reg = readl(&mdio->regs->user[0].access);
  85. data = (reg & USERACCESS_ACK) ? (reg & USERACCESS_DATA) : -1;
  86. return data;
  87. }
  88. static int cpsw_mdio_write(struct mii_dev *bus, int phy_id, int dev_addr,
  89. int phy_reg, u16 data)
  90. {
  91. struct cpsw_mdio *mdio = bus->priv;
  92. u32 reg;
  93. int ret;
  94. if (phy_reg & ~PHY_REG_MASK || phy_id & ~PHY_ID_MASK)
  95. return -EINVAL;
  96. ret = cpsw_mdio_wait_for_user_access(mdio);
  97. if (ret)
  98. return ret;
  99. reg = (USERACCESS_GO | USERACCESS_WRITE |
  100. (phy_reg << USERACCESS_PHY_REG_SHIFT) |
  101. (phy_id << USERACCESS_PHY_ADDR_SHIFT) |
  102. (data & USERACCESS_DATA));
  103. writel(reg, &mdio->regs->user[0].access);
  104. return cpsw_mdio_wait_for_user_access(mdio);
  105. }
  106. u32 cpsw_mdio_get_alive(struct mii_dev *bus)
  107. {
  108. struct cpsw_mdio *mdio = bus->priv;
  109. u32 val;
  110. val = readl(&mdio->regs->control);
  111. return val & GENMASK(15, 0);
  112. }
  113. struct mii_dev *cpsw_mdio_init(const char *name, phys_addr_t mdio_base,
  114. u32 bus_freq, int fck_freq)
  115. {
  116. struct cpsw_mdio *cpsw_mdio;
  117. int ret;
  118. cpsw_mdio = calloc(1, sizeof(*cpsw_mdio));
  119. if (!cpsw_mdio) {
  120. debug("failed to alloc cpsw_mdio\n");
  121. return NULL;
  122. }
  123. cpsw_mdio->bus = mdio_alloc();
  124. if (!cpsw_mdio->bus) {
  125. debug("failed to alloc mii bus\n");
  126. free(cpsw_mdio);
  127. return NULL;
  128. }
  129. cpsw_mdio->regs = (struct cpsw_mdio_regs *)(uintptr_t)mdio_base;
  130. if (!bus_freq || !fck_freq)
  131. cpsw_mdio->div = CPSW_MDIO_DIV_DEF;
  132. else
  133. cpsw_mdio->div = (fck_freq / bus_freq) - 1;
  134. cpsw_mdio->div &= CONTROL_DIV_MASK;
  135. /* set enable and clock divider */
  136. writel(cpsw_mdio->div | CONTROL_ENABLE | CONTROL_FAULT |
  137. CONTROL_FAULT_ENABLE, &cpsw_mdio->regs->control);
  138. wait_for_bit_le32(&cpsw_mdio->regs->control,
  139. CONTROL_IDLE, false, CPSW_MDIO_TIMEOUT, true);
  140. /*
  141. * wait for scan logic to settle:
  142. * the scan time consists of (a) a large fixed component, and (b) a
  143. * small component that varies with the mii bus frequency. These
  144. * were estimated using measurements at 1.1 and 2.2 MHz on tnetv107x
  145. * silicon. Since the effect of (b) was found to be largely
  146. * negligible, we keep things simple here.
  147. */
  148. mdelay(1);
  149. cpsw_mdio->bus->read = cpsw_mdio_read;
  150. cpsw_mdio->bus->write = cpsw_mdio_write;
  151. cpsw_mdio->bus->priv = cpsw_mdio;
  152. snprintf(cpsw_mdio->bus->name, sizeof(cpsw_mdio->bus->name), name);
  153. ret = mdio_register(cpsw_mdio->bus);
  154. if (ret < 0) {
  155. debug("failed to register mii bus\n");
  156. goto free_bus;
  157. }
  158. return cpsw_mdio->bus;
  159. free_bus:
  160. mdio_free(cpsw_mdio->bus);
  161. free(cpsw_mdio);
  162. return NULL;
  163. }
  164. void cpsw_mdio_free(struct mii_dev *bus)
  165. {
  166. struct cpsw_mdio *mdio = bus->priv;
  167. u32 reg;
  168. /* disable mdio */
  169. reg = readl(&mdio->regs->control);
  170. reg &= ~CONTROL_ENABLE;
  171. writel(reg, &mdio->regs->control);
  172. mdio_unregister(bus);
  173. mdio_free(bus);
  174. free(mdio);
  175. }