1063c1263SAndy Fleming /* 2*5be00a01SClaudiu Manoil * Copyright 2009-2010, 2013 Freescale Semiconductor, Inc. 3063c1263SAndy Fleming * Jun-jie Zhang <b18070@freescale.com> 4063c1263SAndy Fleming * Mingkai Hu <Mingkai.hu@freescale.com> 5063c1263SAndy Fleming * 61a459660SWolfgang Denk * SPDX-License-Identifier: GPL-2.0+ 7063c1263SAndy Fleming */ 8063c1263SAndy Fleming #include <common.h> 9063c1263SAndy Fleming #include <miiphy.h> 10063c1263SAndy Fleming #include <phy.h> 11063c1263SAndy Fleming #include <fsl_mdio.h> 12063c1263SAndy Fleming #include <asm/io.h> 13063c1263SAndy Fleming #include <asm/errno.h> 14063c1263SAndy Fleming #include <asm/fsl_enet.h> 15063c1263SAndy Fleming 16*5be00a01SClaudiu Manoil void tsec_local_mdio_write(struct tsec_mii_mng __iomem *phyregs, int port_addr, 17063c1263SAndy Fleming int dev_addr, int regnum, int value) 18063c1263SAndy Fleming { 19063c1263SAndy Fleming int timeout = 1000000; 20063c1263SAndy Fleming 21063c1263SAndy Fleming out_be32(&phyregs->miimadd, (port_addr << 8) | (regnum & 0x1f)); 22063c1263SAndy Fleming out_be32(&phyregs->miimcon, value); 23063c1263SAndy Fleming asm("sync"); 24063c1263SAndy Fleming 25063c1263SAndy Fleming while ((in_be32(&phyregs->miimind) & MIIMIND_BUSY) && timeout--) 26063c1263SAndy Fleming ; 27063c1263SAndy Fleming } 28063c1263SAndy Fleming 29*5be00a01SClaudiu Manoil int tsec_local_mdio_read(struct tsec_mii_mng __iomem *phyregs, int port_addr, 30063c1263SAndy Fleming int dev_addr, int regnum) 31063c1263SAndy Fleming { 32063c1263SAndy Fleming int value; 33063c1263SAndy Fleming int timeout = 1000000; 34063c1263SAndy Fleming 35063c1263SAndy Fleming /* Put the address of the phy, and the register 36063c1263SAndy Fleming * number into MIIMADD */ 37063c1263SAndy Fleming out_be32(&phyregs->miimadd, (port_addr << 8) | (regnum & 0x1f)); 38063c1263SAndy Fleming 39063c1263SAndy Fleming /* Clear the command register, and wait */ 40063c1263SAndy Fleming out_be32(&phyregs->miimcom, 0); 41063c1263SAndy Fleming asm("sync"); 42063c1263SAndy Fleming 43063c1263SAndy Fleming /* Initiate a read command, and wait */ 44063c1263SAndy Fleming out_be32(&phyregs->miimcom, MIIMCOM_READ_CYCLE); 45063c1263SAndy Fleming asm("sync"); 46063c1263SAndy Fleming 47063c1263SAndy Fleming /* Wait for the the indication that the read is done */ 48063c1263SAndy Fleming while ((in_be32(&phyregs->miimind) & (MIIMIND_NOTVALID | MIIMIND_BUSY)) 49063c1263SAndy Fleming && timeout--) 50063c1263SAndy Fleming ; 51063c1263SAndy Fleming 52063c1263SAndy Fleming /* Grab the value read from the PHY */ 53063c1263SAndy Fleming value = in_be32(&phyregs->miimstat); 54063c1263SAndy Fleming 55063c1263SAndy Fleming return value; 56063c1263SAndy Fleming } 57063c1263SAndy Fleming 58063c1263SAndy Fleming static int fsl_pq_mdio_reset(struct mii_dev *bus) 59063c1263SAndy Fleming { 60*5be00a01SClaudiu Manoil struct tsec_mii_mng __iomem *regs = 61*5be00a01SClaudiu Manoil (struct tsec_mii_mng __iomem *)bus->priv; 62063c1263SAndy Fleming 63063c1263SAndy Fleming /* Reset MII (due to new addresses) */ 64063c1263SAndy Fleming out_be32(®s->miimcfg, MIIMCFG_RESET_MGMT); 65063c1263SAndy Fleming 66063c1263SAndy Fleming out_be32(®s->miimcfg, MIIMCFG_INIT_VALUE); 67063c1263SAndy Fleming 68063c1263SAndy Fleming while (in_be32(®s->miimind) & MIIMIND_BUSY) 69063c1263SAndy Fleming ; 70063c1263SAndy Fleming 71063c1263SAndy Fleming return 0; 72063c1263SAndy Fleming } 73063c1263SAndy Fleming 74063c1263SAndy Fleming int tsec_phy_read(struct mii_dev *bus, int addr, int dev_addr, int regnum) 75063c1263SAndy Fleming { 76*5be00a01SClaudiu Manoil struct tsec_mii_mng __iomem *phyregs = 77*5be00a01SClaudiu Manoil (struct tsec_mii_mng __iomem *)bus->priv; 78063c1263SAndy Fleming 79063c1263SAndy Fleming return tsec_local_mdio_read(phyregs, addr, dev_addr, regnum); 80063c1263SAndy Fleming } 81063c1263SAndy Fleming 82063c1263SAndy Fleming int tsec_phy_write(struct mii_dev *bus, int addr, int dev_addr, int regnum, 83063c1263SAndy Fleming u16 value) 84063c1263SAndy Fleming { 85*5be00a01SClaudiu Manoil struct tsec_mii_mng __iomem *phyregs = 86*5be00a01SClaudiu Manoil (struct tsec_mii_mng __iomem *)bus->priv; 87063c1263SAndy Fleming 88063c1263SAndy Fleming tsec_local_mdio_write(phyregs, addr, dev_addr, regnum, value); 89063c1263SAndy Fleming 90063c1263SAndy Fleming return 0; 91063c1263SAndy Fleming } 92063c1263SAndy Fleming 93063c1263SAndy Fleming int fsl_pq_mdio_init(bd_t *bis, struct fsl_pq_mdio_info *info) 94063c1263SAndy Fleming { 95063c1263SAndy Fleming struct mii_dev *bus = mdio_alloc(); 96063c1263SAndy Fleming 97063c1263SAndy Fleming if (!bus) { 98063c1263SAndy Fleming printf("Failed to allocate FSL MDIO bus\n"); 99063c1263SAndy Fleming return -1; 100063c1263SAndy Fleming } 101063c1263SAndy Fleming 102063c1263SAndy Fleming bus->read = tsec_phy_read; 103063c1263SAndy Fleming bus->write = tsec_phy_write; 104063c1263SAndy Fleming bus->reset = fsl_pq_mdio_reset; 105063c1263SAndy Fleming sprintf(bus->name, info->name); 106063c1263SAndy Fleming 107*5be00a01SClaudiu Manoil bus->priv = (void *)info->regs; 108063c1263SAndy Fleming 109063c1263SAndy Fleming return mdio_register(bus); 110063c1263SAndy Fleming } 111