1 /* 2 * Copyright 2009-2011 Freescale Semiconductor, Inc. 3 * Andy Fleming <afleming@gmail.com> 4 * 5 * SPDX-License-Identifier: GPL-2.0+ 6 * Some part is taken from tsec.c 7 */ 8 #include <common.h> 9 #include <miiphy.h> 10 #include <phy.h> 11 #include <asm/io.h> 12 #include <asm/fsl_tgec.h> 13 #include <fm_eth.h> 14 15 /* 16 * Write value to the PHY for this device to the register at regnum, waiting 17 * until the write is done before it returns. All PHY configuration has to be 18 * done through the TSEC1 MIIM regs 19 */ 20 static int tgec_mdio_write(struct mii_dev *bus, int port_addr, int dev_addr, 21 int regnum, u16 value) 22 { 23 u32 mdio_ctl; 24 u32 stat_val; 25 struct tgec_mdio_controller *regs = bus->priv; 26 27 if (dev_addr == MDIO_DEVAD_NONE) 28 return 0; 29 30 /* Wait till the bus is free */ 31 stat_val = MDIO_STAT_CLKDIV(100); 32 out_be32(®s->mdio_stat, stat_val); 33 while ((in_be32(®s->mdio_stat)) & MDIO_STAT_BSY) 34 ; 35 36 /* Set the port and dev addr */ 37 mdio_ctl = MDIO_CTL_PORT_ADDR(port_addr) | MDIO_CTL_DEV_ADDR(dev_addr); 38 out_be32(®s->mdio_ctl, mdio_ctl); 39 40 /* Set the register address */ 41 out_be32(®s->mdio_addr, regnum & 0xffff); 42 43 /* Wait till the bus is free */ 44 while ((in_be32(®s->mdio_stat)) & MDIO_STAT_BSY) 45 ; 46 47 /* Write the value to the register */ 48 out_be32(®s->mdio_data, MDIO_DATA(value)); 49 50 /* Wait till the MDIO write is complete */ 51 while ((in_be32(®s->mdio_data)) & MDIO_DATA_BSY) 52 ; 53 54 return 0; 55 } 56 57 /* 58 * Reads from register regnum in the PHY for device dev, returning the value. 59 * Clears miimcom first. All PHY configuration has to be done through the 60 * TSEC1 MIIM regs 61 */ 62 static int tgec_mdio_read(struct mii_dev *bus, int port_addr, int dev_addr, 63 int regnum) 64 { 65 u32 mdio_ctl; 66 u32 stat_val; 67 struct tgec_mdio_controller *regs = bus->priv; 68 69 if (dev_addr == MDIO_DEVAD_NONE) 70 return 0xffff; 71 72 stat_val = MDIO_STAT_CLKDIV(100); 73 out_be32(®s->mdio_stat, stat_val); 74 /* Wait till the bus is free */ 75 while ((in_be32(®s->mdio_stat)) & MDIO_STAT_BSY) 76 ; 77 78 /* Set the Port and Device Addrs */ 79 mdio_ctl = MDIO_CTL_PORT_ADDR(port_addr) | MDIO_CTL_DEV_ADDR(dev_addr); 80 out_be32(®s->mdio_ctl, mdio_ctl); 81 82 /* Set the register address */ 83 out_be32(®s->mdio_addr, regnum & 0xffff); 84 85 /* Wait till the bus is free */ 86 while ((in_be32(®s->mdio_stat)) & MDIO_STAT_BSY) 87 ; 88 89 /* Initiate the read */ 90 mdio_ctl |= MDIO_CTL_READ; 91 out_be32(®s->mdio_ctl, mdio_ctl); 92 93 /* Wait till the MDIO write is complete */ 94 while ((in_be32(®s->mdio_data)) & MDIO_DATA_BSY) 95 ; 96 97 /* Return all Fs if nothing was there */ 98 if (in_be32(®s->mdio_stat) & MDIO_STAT_RD_ER) 99 return 0xffff; 100 101 return in_be32(®s->mdio_data) & 0xffff; 102 } 103 104 static int tgec_mdio_reset(struct mii_dev *bus) 105 { 106 return 0; 107 } 108 109 int fm_tgec_mdio_init(bd_t *bis, struct tgec_mdio_info *info) 110 { 111 struct mii_dev *bus = mdio_alloc(); 112 113 if (!bus) { 114 printf("Failed to allocate FM TGEC MDIO bus\n"); 115 return -1; 116 } 117 118 bus->read = tgec_mdio_read; 119 bus->write = tgec_mdio_write; 120 bus->reset = tgec_mdio_reset; 121 sprintf(bus->name, info->name); 122 123 bus->priv = info->regs; 124 125 return mdio_register(bus); 126 } 127