Home | History | Annotate | Download | only in net
      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 (at) 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 
     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 
     23 	/* Wait for the previous operation to finish */
     24 	wait_for_bit_le32(&mii_regs->mind.raw, MIIMIND_BUSY,
     25 			  false, CONFIG_SYS_HZ, true);
     26 
     27 	/* Put phyaddr and regaddr into MIIMADD */
     28 	v = (addr << MIIMADD_PHYADDR_SHIFT) | (reg & MIIMADD_REGADDR);
     29 	writel(v, &mii_regs->madr.raw);
     30 
     31 	/* Initiate a write command */
     32 	writel(value, &mii_regs->mwtd.raw);
     33 
     34 	/* Wait 30 clock cycles for busy flag to be set */
     35 	udelay(12);
     36 
     37 	/* Wait for write to complete */
     38 	wait_for_bit_le32(&mii_regs->mind.raw, MIIMIND_BUSY,
     39 			  false, CONFIG_SYS_HZ, true);
     40 
     41 	return 0;
     42 }
     43 
     44 static int pic32_mdio_read(struct mii_dev *bus, int addr, int devaddr, int reg)
     45 {
     46 	u32 v;
     47 	struct pic32_mii_regs *mii_regs = bus->priv;
     48 
     49 	/* Wait for the previous operation to finish */
     50 	wait_for_bit_le32(&mii_regs->mind.raw, MIIMIND_BUSY,
     51 			  false, CONFIG_SYS_HZ, true);
     52 
     53 	/* Put phyaddr and regaddr into MIIMADD */
     54 	v = (addr << MIIMADD_PHYADDR_SHIFT) | (reg & MIIMADD_REGADDR);
     55 	writel(v, &mii_regs->madr.raw);
     56 
     57 	/* Initiate a read command */
     58 	writel(MIIMCMD_READ, &mii_regs->mcmd.raw);
     59 
     60 	/* Wait 30 clock cycles for busy flag to be set */
     61 	udelay(12);
     62 
     63 	/* Wait for read to complete */
     64 	wait_for_bit_le32(&mii_regs->mind.raw,
     65 			  MIIMIND_NOTVALID | MIIMIND_BUSY,
     66 			  false, CONFIG_SYS_HZ, false);
     67 
     68 	/* Clear the command register */
     69 	writel(0, &mii_regs->mcmd.raw);
     70 
     71 	/* Grab the value read from the PHY */
     72 	v = readl(&mii_regs->mrdd.raw);
     73 	return v;
     74 }
     75 
     76 static int pic32_mdio_reset(struct mii_dev *bus)
     77 {
     78 	struct pic32_mii_regs *mii_regs = bus->priv;
     79 
     80 	/* Reset MII (due to new addresses) */
     81 	writel(MIIMCFG_RSTMGMT, &mii_regs->mcfg.raw);
     82 
     83 	/* Wait for the operation to finish */
     84 	wait_for_bit_le32(&mii_regs->mind.raw, MIIMIND_BUSY,
     85 		     false, CONFIG_SYS_HZ, true);
     86 
     87 	/* Clear reset bit */
     88 	writel(0, &mii_regs->mcfg);
     89 
     90 	/* Wait for the operation to finish */
     91 	wait_for_bit_le32(&mii_regs->mind.raw, MIIMIND_BUSY,
     92 			  false, CONFIG_SYS_HZ, true);
     93 
     94 	/* Set the MII Management Clock (MDC) - no faster than 2.5 MHz */
     95 	writel(MIIMCFG_CLKSEL_DIV40, &mii_regs->mcfg.raw);
     96 
     97 	/* Wait for the operation to finish */
     98 	wait_for_bit_le32(&mii_regs->mind.raw, MIIMIND_BUSY,
     99 			  false, CONFIG_SYS_HZ, true);
    100 	return 0;
    101 }
    102 
    103 int pic32_mdio_init(const char *name, ulong ioaddr)
    104 {
    105 	struct mii_dev *bus;
    106 
    107 	bus = mdio_alloc();
    108 	if (!bus) {
    109 		printf("Failed to allocate PIC32-MDIO bus\n");
    110 		return -ENOMEM;
    111 	}
    112 
    113 	bus->read = pic32_mdio_read;
    114 	bus->write = pic32_mdio_write;
    115 	bus->reset = pic32_mdio_reset;
    116 	strncpy(bus->name, name, sizeof(bus->name));
    117 	bus->priv = (void *)ioaddr;
    118 
    119 	return mdio_register(bus);
    120 }
    121