1111fd19eSRoy Zang /* 2111fd19eSRoy Zang * Copyright 2012 Freescale Semiconductor, Inc. 3b21f87a3SAndy Fleming * Andy Fleming <afleming@gmail.com> 4111fd19eSRoy Zang * Roy Zang <tie-fei.zang@freescale.com> 5111fd19eSRoy Zang * 61a459660SWolfgang Denk * SPDX-License-Identifier: GPL-2.0+ 7111fd19eSRoy Zang * Some part is taken from tsec.c 8111fd19eSRoy Zang */ 9111fd19eSRoy Zang #include <common.h> 10111fd19eSRoy Zang #include <miiphy.h> 11111fd19eSRoy Zang #include <phy.h> 12111fd19eSRoy Zang #include <asm/io.h> 13*cd348efaSShaohui Xie #include <fsl_memac.h> 14111fd19eSRoy Zang #include <fm_eth.h> 15111fd19eSRoy Zang 16*cd348efaSShaohui Xie #ifdef CONFIG_SYS_MEMAC_LITTLE_ENDIAN 17*cd348efaSShaohui Xie #define memac_out_32(a, v) out_le32(a, v) 18*cd348efaSShaohui Xie #define memac_clrbits_32(a, v) clrbits_le32(a, v) 19*cd348efaSShaohui Xie #define memac_setbits_32(a, v) setbits_le32(a, v) 20*cd348efaSShaohui Xie #else 21*cd348efaSShaohui Xie #define memac_out_32(a, v) out_be32(a, v) 22*cd348efaSShaohui Xie #define memac_clrbits_32(a, v) clrbits_be32(a, v) 23*cd348efaSShaohui Xie #define memac_setbits_32(a, v) setbits_be32(a, v) 24*cd348efaSShaohui Xie #endif 25*cd348efaSShaohui Xie 26*cd348efaSShaohui Xie static u32 memac_in_32(u32 *reg) 27*cd348efaSShaohui Xie { 28*cd348efaSShaohui Xie #ifdef CONFIG_SYS_MEMAC_LITTLE_ENDIAN 29*cd348efaSShaohui Xie return in_le32(reg); 30*cd348efaSShaohui Xie #else 31*cd348efaSShaohui Xie return in_be32(reg); 32*cd348efaSShaohui Xie #endif 33*cd348efaSShaohui Xie } 34*cd348efaSShaohui Xie 35111fd19eSRoy Zang /* 36111fd19eSRoy Zang * Write value to the PHY for this device to the register at regnum, waiting 37111fd19eSRoy Zang * until the write is done before it returns. All PHY configuration has to be 38111fd19eSRoy Zang * done through the TSEC1 MIIM regs 39111fd19eSRoy Zang */ 40111fd19eSRoy Zang int memac_mdio_write(struct mii_dev *bus, int port_addr, int dev_addr, 41111fd19eSRoy Zang int regnum, u16 value) 42111fd19eSRoy Zang { 43111fd19eSRoy Zang u32 mdio_ctl; 44111fd19eSRoy Zang struct memac_mdio_controller *regs = bus->priv; 45111fd19eSRoy Zang u32 c45 = 1; /* Default to 10G interface */ 46111fd19eSRoy Zang 47111fd19eSRoy Zang if (dev_addr == MDIO_DEVAD_NONE) { 48111fd19eSRoy Zang c45 = 0; /* clause 22 */ 49111fd19eSRoy Zang dev_addr = regnum & 0x1f; 50*cd348efaSShaohui Xie memac_clrbits_32(®s->mdio_stat, MDIO_STAT_ENC); 513a7ed5aaSShaohui Xie } else 52*cd348efaSShaohui Xie memac_setbits_32(®s->mdio_stat, MDIO_STAT_ENC); 53111fd19eSRoy Zang 54111fd19eSRoy Zang /* Wait till the bus is free */ 55*cd348efaSShaohui Xie while ((memac_in_32(®s->mdio_stat)) & MDIO_STAT_BSY) 56111fd19eSRoy Zang ; 57111fd19eSRoy Zang 58111fd19eSRoy Zang /* Set the port and dev addr */ 59111fd19eSRoy Zang mdio_ctl = MDIO_CTL_PORT_ADDR(port_addr) | MDIO_CTL_DEV_ADDR(dev_addr); 60*cd348efaSShaohui Xie memac_out_32(®s->mdio_ctl, mdio_ctl); 61111fd19eSRoy Zang 62111fd19eSRoy Zang /* Set the register address */ 63111fd19eSRoy Zang if (c45) 64*cd348efaSShaohui Xie memac_out_32(®s->mdio_addr, regnum & 0xffff); 65111fd19eSRoy Zang 66111fd19eSRoy Zang /* Wait till the bus is free */ 67*cd348efaSShaohui Xie while ((memac_in_32(®s->mdio_stat)) & MDIO_STAT_BSY) 68111fd19eSRoy Zang ; 69111fd19eSRoy Zang 70111fd19eSRoy Zang /* Write the value to the register */ 71*cd348efaSShaohui Xie memac_out_32(®s->mdio_data, MDIO_DATA(value)); 72111fd19eSRoy Zang 73111fd19eSRoy Zang /* Wait till the MDIO write is complete */ 74*cd348efaSShaohui Xie while ((memac_in_32(®s->mdio_data)) & MDIO_DATA_BSY) 75111fd19eSRoy Zang ; 76111fd19eSRoy Zang 77111fd19eSRoy Zang return 0; 78111fd19eSRoy Zang } 79111fd19eSRoy Zang 80111fd19eSRoy Zang /* 81111fd19eSRoy Zang * Reads from register regnum in the PHY for device dev, returning the value. 82111fd19eSRoy Zang * Clears miimcom first. All PHY configuration has to be done through the 83111fd19eSRoy Zang * TSEC1 MIIM regs 84111fd19eSRoy Zang */ 85111fd19eSRoy Zang int memac_mdio_read(struct mii_dev *bus, int port_addr, int dev_addr, 86111fd19eSRoy Zang int regnum) 87111fd19eSRoy Zang { 88111fd19eSRoy Zang u32 mdio_ctl; 89111fd19eSRoy Zang struct memac_mdio_controller *regs = bus->priv; 90111fd19eSRoy Zang u32 c45 = 1; 91111fd19eSRoy Zang 92111fd19eSRoy Zang if (dev_addr == MDIO_DEVAD_NONE) { 93ff5fb2a3SShaohui Xie if (!strcmp(bus->name, DEFAULT_FM_TGEC_MDIO_NAME)) 94ff5fb2a3SShaohui Xie return 0xffff; 95111fd19eSRoy Zang c45 = 0; /* clause 22 */ 96111fd19eSRoy Zang dev_addr = regnum & 0x1f; 97*cd348efaSShaohui Xie memac_clrbits_32(®s->mdio_stat, MDIO_STAT_ENC); 983a7ed5aaSShaohui Xie } else 99*cd348efaSShaohui Xie memac_setbits_32(®s->mdio_stat, MDIO_STAT_ENC); 100111fd19eSRoy Zang 101111fd19eSRoy Zang /* Wait till the bus is free */ 102*cd348efaSShaohui Xie while ((memac_in_32(®s->mdio_stat)) & MDIO_STAT_BSY) 103111fd19eSRoy Zang ; 104111fd19eSRoy Zang 105111fd19eSRoy Zang /* Set the Port and Device Addrs */ 106111fd19eSRoy Zang mdio_ctl = MDIO_CTL_PORT_ADDR(port_addr) | MDIO_CTL_DEV_ADDR(dev_addr); 107*cd348efaSShaohui Xie memac_out_32(®s->mdio_ctl, mdio_ctl); 108111fd19eSRoy Zang 109111fd19eSRoy Zang /* Set the register address */ 110111fd19eSRoy Zang if (c45) 111*cd348efaSShaohui Xie memac_out_32(®s->mdio_addr, regnum & 0xffff); 112111fd19eSRoy Zang 113111fd19eSRoy Zang /* Wait till the bus is free */ 114*cd348efaSShaohui Xie while ((memac_in_32(®s->mdio_stat)) & MDIO_STAT_BSY) 115111fd19eSRoy Zang ; 116111fd19eSRoy Zang 117111fd19eSRoy Zang /* Initiate the read */ 118111fd19eSRoy Zang mdio_ctl |= MDIO_CTL_READ; 119*cd348efaSShaohui Xie memac_out_32(®s->mdio_ctl, mdio_ctl); 120111fd19eSRoy Zang 121111fd19eSRoy Zang /* Wait till the MDIO write is complete */ 122*cd348efaSShaohui Xie while ((memac_in_32(®s->mdio_data)) & MDIO_DATA_BSY) 123111fd19eSRoy Zang ; 124111fd19eSRoy Zang 125111fd19eSRoy Zang /* Return all Fs if nothing was there */ 126*cd348efaSShaohui Xie if (memac_in_32(®s->mdio_stat) & MDIO_STAT_RD_ER) 127111fd19eSRoy Zang return 0xffff; 128111fd19eSRoy Zang 129*cd348efaSShaohui Xie return memac_in_32(®s->mdio_data) & 0xffff; 130111fd19eSRoy Zang } 131111fd19eSRoy Zang 132111fd19eSRoy Zang int memac_mdio_reset(struct mii_dev *bus) 133111fd19eSRoy Zang { 134111fd19eSRoy Zang return 0; 135111fd19eSRoy Zang } 136111fd19eSRoy Zang 137111fd19eSRoy Zang int fm_memac_mdio_init(bd_t *bis, struct memac_mdio_info *info) 138111fd19eSRoy Zang { 139111fd19eSRoy Zang struct mii_dev *bus = mdio_alloc(); 140111fd19eSRoy Zang 141111fd19eSRoy Zang if (!bus) { 142111fd19eSRoy Zang printf("Failed to allocate FM TGEC MDIO bus\n"); 143111fd19eSRoy Zang return -1; 144111fd19eSRoy Zang } 145111fd19eSRoy Zang 146111fd19eSRoy Zang bus->read = memac_mdio_read; 147111fd19eSRoy Zang bus->write = memac_mdio_write; 148111fd19eSRoy Zang bus->reset = memac_mdio_reset; 149111fd19eSRoy Zang sprintf(bus->name, info->name); 150111fd19eSRoy Zang 151111fd19eSRoy Zang bus->priv = info->regs; 152111fd19eSRoy Zang 1532ee6c52eSPriyanka Jain /* 1542ee6c52eSPriyanka Jain * On some platforms like B4860, default value of MDIO_CLK_DIV bits 1552ee6c52eSPriyanka Jain * in mdio_stat(mdio_cfg) register generates MDIO clock too high 1562ee6c52eSPriyanka Jain * (much higher than 2.5MHz), violating the IEEE specs. 1572ee6c52eSPriyanka Jain * On other platforms like T1040, default value of MDIO_CLK_DIV bits 1582ee6c52eSPriyanka Jain * is zero, so MDIO clock is disabled. 1592ee6c52eSPriyanka Jain * So, for proper functioning of MDIO, MDIO_CLK_DIV bits needs to 1602ee6c52eSPriyanka Jain * be properly initialized. 161ae6b4583SShaohui Xie * NEG bit default should be '1' as per FMAN-v3 RM, but on platform 162ae6b4583SShaohui Xie * like T2080QDS, this bit default is '0', which leads to MDIO failure 163ae6b4583SShaohui Xie * on XAUI PHY, so set this bit definitely. 1642ee6c52eSPriyanka Jain */ 165*cd348efaSShaohui Xie memac_setbits_32( 166*cd348efaSShaohui Xie &((struct memac_mdio_controller *)info->regs)->mdio_stat, 167ae6b4583SShaohui Xie MDIO_STAT_CLKDIV(258) | MDIO_STAT_NEG); 1682ee6c52eSPriyanka Jain 169111fd19eSRoy Zang return mdio_register(bus); 170111fd19eSRoy Zang } 171