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