pic32_mdio.c 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * pic32_mdio.c: PIC32 MDIO/MII driver, part of pic32_eth.c.
  4. *
  5. * Copyright 2015 Microchip Inc.
  6. * Purna Chandra Mandal <purna.mandal@microchip.com>
  7. */
  8. #include <common.h>
  9. #include <phy.h>
  10. #include <miiphy.h>
  11. #include <errno.h>
  12. #include <wait_bit.h>
  13. #include <asm/io.h>
  14. #include "pic32_eth.h"
  15. static int pic32_mdio_write(struct mii_dev *bus,
  16. int addr, int dev_addr,
  17. int reg, u16 value)
  18. {
  19. u32 v;
  20. struct pic32_mii_regs *mii_regs = bus->priv;
  21. /* Wait for the previous operation to finish */
  22. wait_for_bit_le32(&mii_regs->mind.raw, MIIMIND_BUSY,
  23. false, CONFIG_SYS_HZ, true);
  24. /* Put phyaddr and regaddr into MIIMADD */
  25. v = (addr << MIIMADD_PHYADDR_SHIFT) | (reg & MIIMADD_REGADDR);
  26. writel(v, &mii_regs->madr.raw);
  27. /* Initiate a write command */
  28. writel(value, &mii_regs->mwtd.raw);
  29. /* Wait 30 clock cycles for busy flag to be set */
  30. udelay(12);
  31. /* Wait for write to complete */
  32. wait_for_bit_le32(&mii_regs->mind.raw, MIIMIND_BUSY,
  33. false, CONFIG_SYS_HZ, true);
  34. return 0;
  35. }
  36. static int pic32_mdio_read(struct mii_dev *bus, int addr, int devaddr, int reg)
  37. {
  38. u32 v;
  39. struct pic32_mii_regs *mii_regs = bus->priv;
  40. /* Wait for the previous operation to finish */
  41. wait_for_bit_le32(&mii_regs->mind.raw, MIIMIND_BUSY,
  42. false, CONFIG_SYS_HZ, true);
  43. /* Put phyaddr and regaddr into MIIMADD */
  44. v = (addr << MIIMADD_PHYADDR_SHIFT) | (reg & MIIMADD_REGADDR);
  45. writel(v, &mii_regs->madr.raw);
  46. /* Initiate a read command */
  47. writel(MIIMCMD_READ, &mii_regs->mcmd.raw);
  48. /* Wait 30 clock cycles for busy flag to be set */
  49. udelay(12);
  50. /* Wait for read to complete */
  51. wait_for_bit_le32(&mii_regs->mind.raw,
  52. MIIMIND_NOTVALID | MIIMIND_BUSY,
  53. false, CONFIG_SYS_HZ, false);
  54. /* Clear the command register */
  55. writel(0, &mii_regs->mcmd.raw);
  56. /* Grab the value read from the PHY */
  57. v = readl(&mii_regs->mrdd.raw);
  58. return v;
  59. }
  60. static int pic32_mdio_reset(struct mii_dev *bus)
  61. {
  62. struct pic32_mii_regs *mii_regs = bus->priv;
  63. /* Reset MII (due to new addresses) */
  64. writel(MIIMCFG_RSTMGMT, &mii_regs->mcfg.raw);
  65. /* Wait for the operation to finish */
  66. wait_for_bit_le32(&mii_regs->mind.raw, MIIMIND_BUSY,
  67. false, CONFIG_SYS_HZ, true);
  68. /* Clear reset bit */
  69. writel(0, &mii_regs->mcfg);
  70. /* Wait for the operation to finish */
  71. wait_for_bit_le32(&mii_regs->mind.raw, MIIMIND_BUSY,
  72. false, CONFIG_SYS_HZ, true);
  73. /* Set the MII Management Clock (MDC) - no faster than 2.5 MHz */
  74. writel(MIIMCFG_CLKSEL_DIV40, &mii_regs->mcfg.raw);
  75. /* Wait for the operation to finish */
  76. wait_for_bit_le32(&mii_regs->mind.raw, MIIMIND_BUSY,
  77. false, CONFIG_SYS_HZ, true);
  78. return 0;
  79. }
  80. int pic32_mdio_init(const char *name, ulong ioaddr)
  81. {
  82. struct mii_dev *bus;
  83. bus = mdio_alloc();
  84. if (!bus) {
  85. printf("Failed to allocate PIC32-MDIO bus\n");
  86. return -ENOMEM;
  87. }
  88. bus->read = pic32_mdio_read;
  89. bus->write = pic32_mdio_write;
  90. bus->reset = pic32_mdio_reset;
  91. strncpy(bus->name, name, sizeof(bus->name));
  92. bus->priv = (void *)ioaddr;
  93. return mdio_register(bus);
  94. }