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