123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121 |
- /*
- * pic32_mdio.c: PIC32 MDIO/MII driver, part of pic32_eth.c.
- *
- * Copyright 2015 Microchip Inc.
- * Purna Chandra Mandal <purna.mandal@microchip.com>
- *
- * SPDX-License-Identifier: GPL-2.0+
- */
- #include <common.h>
- #include <phy.h>
- #include <miiphy.h>
- #include <errno.h>
- #include <wait_bit.h>
- #include <asm/io.h>
- #include "pic32_eth.h"
- static int pic32_mdio_write(struct mii_dev *bus,
- int addr, int dev_addr,
- int reg, u16 value)
- {
- u32 v;
- struct pic32_mii_regs *mii_regs = bus->priv;
- /* Wait for the previous operation to finish */
- wait_for_bit(__func__, &mii_regs->mind.raw, MIIMIND_BUSY,
- false, CONFIG_SYS_HZ, true);
- /* Put phyaddr and regaddr into MIIMADD */
- v = (addr << MIIMADD_PHYADDR_SHIFT) | (reg & MIIMADD_REGADDR);
- writel(v, &mii_regs->madr.raw);
- /* Initiate a write command */
- writel(value, &mii_regs->mwtd.raw);
- /* Wait 30 clock cycles for busy flag to be set */
- udelay(12);
- /* Wait for write to complete */
- wait_for_bit(__func__, &mii_regs->mind.raw, MIIMIND_BUSY,
- false, CONFIG_SYS_HZ, true);
- return 0;
- }
- static int pic32_mdio_read(struct mii_dev *bus, int addr, int devaddr, int reg)
- {
- u32 v;
- struct pic32_mii_regs *mii_regs = bus->priv;
- /* Wait for the previous operation to finish */
- wait_for_bit(__func__, &mii_regs->mind.raw, MIIMIND_BUSY,
- false, CONFIG_SYS_HZ, true);
- /* Put phyaddr and regaddr into MIIMADD */
- v = (addr << MIIMADD_PHYADDR_SHIFT) | (reg & MIIMADD_REGADDR);
- writel(v, &mii_regs->madr.raw);
- /* Initiate a read command */
- writel(MIIMCMD_READ, &mii_regs->mcmd.raw);
- /* Wait 30 clock cycles for busy flag to be set */
- udelay(12);
- /* Wait for read to complete */
- wait_for_bit(__func__, &mii_regs->mind.raw,
- MIIMIND_NOTVALID | MIIMIND_BUSY,
- false, CONFIG_SYS_HZ, false);
- /* Clear the command register */
- writel(0, &mii_regs->mcmd.raw);
- /* Grab the value read from the PHY */
- v = readl(&mii_regs->mrdd.raw);
- return v;
- }
- static int pic32_mdio_reset(struct mii_dev *bus)
- {
- struct pic32_mii_regs *mii_regs = bus->priv;
- /* Reset MII (due to new addresses) */
- writel(MIIMCFG_RSTMGMT, &mii_regs->mcfg.raw);
- /* Wait for the operation to finish */
- wait_for_bit(__func__, &mii_regs->mind.raw, MIIMIND_BUSY,
- false, CONFIG_SYS_HZ, true);
- /* Clear reset bit */
- writel(0, &mii_regs->mcfg);
- /* Wait for the operation to finish */
- wait_for_bit(__func__, &mii_regs->mind.raw, MIIMIND_BUSY,
- false, CONFIG_SYS_HZ, true);
- /* Set the MII Management Clock (MDC) - no faster than 2.5 MHz */
- writel(MIIMCFG_CLKSEL_DIV40, &mii_regs->mcfg.raw);
- /* Wait for the operation to finish */
- wait_for_bit(__func__, &mii_regs->mind.raw, MIIMIND_BUSY,
- false, CONFIG_SYS_HZ, true);
- return 0;
- }
- int pic32_mdio_init(const char *name, ulong ioaddr)
- {
- struct mii_dev *bus;
- bus = mdio_alloc();
- if (!bus) {
- printf("Failed to allocate PIC32-MDIO bus\n");
- return -ENOMEM;
- }
- bus->read = pic32_mdio_read;
- bus->write = pic32_mdio_write;
- bus->reset = pic32_mdio_reset;
- strncpy(bus->name, name, sizeof(bus->name));
- bus->priv = (void *)ioaddr;
- return mdio_register(bus);
- }
|