pic32_mdio.c 3.0 KB

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