fsl_ls_mdio.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright 2020 NXP
  4. */
  5. #include <common.h>
  6. #include <dm.h>
  7. #include <errno.h>
  8. #include <miiphy.h>
  9. #include <asm/io.h>
  10. #include <fsl_memac.h>
  11. #ifdef CONFIG_SYS_MEMAC_LITTLE_ENDIAN
  12. #define memac_out_32(a, v) out_le32(a, v)
  13. #define memac_clrbits_32(a, v) clrbits_le32(a, v)
  14. #define memac_setbits_32(a, v) setbits_le32(a, v)
  15. #else
  16. #define memac_out_32(a, v) out_be32(a, v)
  17. #define memac_clrbits_32(a, v) clrbits_be32(a, v)
  18. #define memac_setbits_32(a, v) setbits_be32(a, v)
  19. #endif
  20. static u32 memac_in_32(u32 *reg)
  21. {
  22. #ifdef CONFIG_SYS_MEMAC_LITTLE_ENDIAN
  23. return in_le32(reg);
  24. #else
  25. return in_be32(reg);
  26. #endif
  27. }
  28. struct fsl_ls_mdio_priv {
  29. void *regs_base;
  30. };
  31. static u32 fsl_ls_mdio_setup_operation(struct udevice *dev, int addr, int devad,
  32. int reg)
  33. {
  34. struct fsl_ls_mdio_priv *priv = dev_get_priv(dev);
  35. struct memac_mdio_controller *regs;
  36. u32 mdio_ctl;
  37. u32 c45 = 1;
  38. regs = (struct memac_mdio_controller *)(priv->regs_base);
  39. if (devad == MDIO_DEVAD_NONE) {
  40. c45 = 0; /* clause 22 */
  41. devad = reg & 0x1f;
  42. memac_clrbits_32(&regs->mdio_stat, MDIO_STAT_ENC);
  43. } else {
  44. memac_setbits_32(&regs->mdio_stat, MDIO_STAT_ENC);
  45. }
  46. /* Wait till the bus is free */
  47. while ((memac_in_32(&regs->mdio_stat)) & MDIO_STAT_BSY)
  48. ;
  49. /* Set the Port and Device Addrs */
  50. mdio_ctl = MDIO_CTL_PORT_ADDR(addr) | MDIO_CTL_DEV_ADDR(devad);
  51. memac_out_32(&regs->mdio_ctl, mdio_ctl);
  52. /* Set the register address */
  53. if (c45)
  54. memac_out_32(&regs->mdio_addr, reg & 0xffff);
  55. /* Wait till the bus is free */
  56. while ((memac_in_32(&regs->mdio_stat)) & MDIO_STAT_BSY)
  57. ;
  58. return mdio_ctl;
  59. }
  60. static int dm_fsl_ls_mdio_read(struct udevice *dev, int addr,
  61. int devad, int reg)
  62. {
  63. struct fsl_ls_mdio_priv *priv = dev_get_priv(dev);
  64. struct memac_mdio_controller *regs;
  65. u32 mdio_ctl;
  66. regs = (struct memac_mdio_controller *)(priv->regs_base);
  67. mdio_ctl = fsl_ls_mdio_setup_operation(dev, addr, devad, reg);
  68. /* Initiate the read */
  69. mdio_ctl |= MDIO_CTL_READ;
  70. memac_out_32(&regs->mdio_ctl, mdio_ctl);
  71. /* Wait till the MDIO write is complete */
  72. while ((memac_in_32(&regs->mdio_data)) & MDIO_DATA_BSY)
  73. ;
  74. /* Return all Fs if nothing was there */
  75. if (memac_in_32(&regs->mdio_stat) & MDIO_STAT_RD_ER)
  76. return 0xffff;
  77. return memac_in_32(&regs->mdio_data) & 0xffff;
  78. }
  79. static int dm_fsl_ls_mdio_write(struct udevice *dev, int addr, int devad,
  80. int reg, u16 val)
  81. {
  82. struct fsl_ls_mdio_priv *priv = dev_get_priv(dev);
  83. struct memac_mdio_controller *regs;
  84. regs = (struct memac_mdio_controller *)(priv->regs_base);
  85. fsl_ls_mdio_setup_operation(dev, addr, devad, reg);
  86. /* Write the value to the register */
  87. memac_out_32(&regs->mdio_data, MDIO_DATA(val));
  88. /* Wait till the MDIO write is complete */
  89. while ((memac_in_32(&regs->mdio_data)) & MDIO_DATA_BSY)
  90. ;
  91. return 0;
  92. }
  93. static const struct mdio_ops fsl_ls_mdio_ops = {
  94. .read = dm_fsl_ls_mdio_read,
  95. .write = dm_fsl_ls_mdio_write,
  96. };
  97. static int fsl_ls_mdio_probe(struct udevice *dev)
  98. {
  99. struct fsl_ls_mdio_priv *priv = dev_get_priv(dev);
  100. struct memac_mdio_controller *regs;
  101. priv->regs_base = dev_read_addr_ptr(dev);
  102. regs = (struct memac_mdio_controller *)(priv->regs_base);
  103. memac_setbits_32(&regs->mdio_stat,
  104. MDIO_STAT_CLKDIV(258) | MDIO_STAT_NEG);
  105. return 0;
  106. }
  107. static const struct udevice_id fsl_ls_mdio_of_ids[] = {
  108. { .compatible = "fsl,ls-mdio" },
  109. };
  110. U_BOOT_DRIVER(fsl_ls_mdio) = {
  111. .name = "fsl_ls_mdio",
  112. .id = UCLASS_MDIO,
  113. .of_match = fsl_ls_mdio_of_ids,
  114. .probe = fsl_ls_mdio_probe,
  115. .ops = &fsl_ls_mdio_ops,
  116. .priv_auto_alloc_size = sizeof(struct fsl_ls_mdio_priv),
  117. };