1fc9a8e8dSKaricheri, Muralidharan /* 2fc9a8e8dSKaricheri, Muralidharan * Ethernet driver for TI K2HK EVM. 3fc9a8e8dSKaricheri, Muralidharan * 4fc9a8e8dSKaricheri, Muralidharan * (C) Copyright 2012-2014 5fc9a8e8dSKaricheri, Muralidharan * Texas Instruments Incorporated, <www.ti.com> 6fc9a8e8dSKaricheri, Muralidharan * 7fc9a8e8dSKaricheri, Muralidharan * SPDX-License-Identifier: GPL-2.0+ 8fc9a8e8dSKaricheri, Muralidharan */ 9fc9a8e8dSKaricheri, Muralidharan #include <common.h> 10fc9a8e8dSKaricheri, Muralidharan #include <command.h> 11fc9a8e8dSKaricheri, Muralidharan 12fc9a8e8dSKaricheri, Muralidharan #include <net.h> 133fe93623SKhoronzhuk, Ivan #include <phy.h> 14fc9a8e8dSKaricheri, Muralidharan #include <miiphy.h> 15fc9a8e8dSKaricheri, Muralidharan #include <malloc.h> 16ef454717SKhoronzhuk, Ivan #include <asm/ti-common/keystone_nav.h> 170935cac6SKhoronzhuk, Ivan #include <asm/ti-common/keystone_net.h> 18a43febdeSKhoronzhuk, Ivan #include <asm/ti-common/keystone_serdes.h> 19fc9a8e8dSKaricheri, Muralidharan 20fc9a8e8dSKaricheri, Muralidharan unsigned int emac_open; 21550c5ce6SKhoronzhuk, Ivan static struct mii_dev *mdio_bus; 22fc9a8e8dSKaricheri, Muralidharan static unsigned int sys_has_mdio = 1; 23fc9a8e8dSKaricheri, Muralidharan 24fc9a8e8dSKaricheri, Muralidharan #ifdef KEYSTONE2_EMAC_GIG_ENABLE 25fc9a8e8dSKaricheri, Muralidharan #define emac_gigabit_enable(x) keystone2_eth_gigabit_enable(x) 26fc9a8e8dSKaricheri, Muralidharan #else 27fc9a8e8dSKaricheri, Muralidharan #define emac_gigabit_enable(x) /* no gigabit to enable */ 28fc9a8e8dSKaricheri, Muralidharan #endif 29fc9a8e8dSKaricheri, Muralidharan 30fc9a8e8dSKaricheri, Muralidharan #define RX_BUFF_NUMS 24 31fc9a8e8dSKaricheri, Muralidharan #define RX_BUFF_LEN 1520 32fc9a8e8dSKaricheri, Muralidharan #define MAX_SIZE_STREAM_BUFFER RX_BUFF_LEN 33fc9a8e8dSKaricheri, Muralidharan 34fc9a8e8dSKaricheri, Muralidharan static u8 rx_buffs[RX_BUFF_NUMS * RX_BUFF_LEN] __aligned(16); 35fc9a8e8dSKaricheri, Muralidharan 36fc9a8e8dSKaricheri, Muralidharan struct rx_buff_desc net_rx_buffs = { 37fc9a8e8dSKaricheri, Muralidharan .buff_ptr = rx_buffs, 38fc9a8e8dSKaricheri, Muralidharan .num_buffs = RX_BUFF_NUMS, 39fc9a8e8dSKaricheri, Muralidharan .buff_len = RX_BUFF_LEN, 40fc9a8e8dSKaricheri, Muralidharan .rx_flow = 22, 41fc9a8e8dSKaricheri, Muralidharan }; 42fc9a8e8dSKaricheri, Muralidharan 43a43febdeSKhoronzhuk, Ivan static void keystone2_net_serdes_setup(void); 44fc9a8e8dSKaricheri, Muralidharan 45fc9a8e8dSKaricheri, Muralidharan int keystone2_eth_read_mac_addr(struct eth_device *dev) 46fc9a8e8dSKaricheri, Muralidharan { 47fc9a8e8dSKaricheri, Muralidharan struct eth_priv_t *eth_priv; 48fc9a8e8dSKaricheri, Muralidharan u32 maca = 0; 49fc9a8e8dSKaricheri, Muralidharan u32 macb = 0; 50fc9a8e8dSKaricheri, Muralidharan 51fc9a8e8dSKaricheri, Muralidharan eth_priv = (struct eth_priv_t *)dev->priv; 52fc9a8e8dSKaricheri, Muralidharan 53fc9a8e8dSKaricheri, Muralidharan /* Read the e-fuse mac address */ 54fc9a8e8dSKaricheri, Muralidharan if (eth_priv->slave_port == 1) { 55fc9a8e8dSKaricheri, Muralidharan maca = __raw_readl(MAC_ID_BASE_ADDR); 56fc9a8e8dSKaricheri, Muralidharan macb = __raw_readl(MAC_ID_BASE_ADDR + 4); 57fc9a8e8dSKaricheri, Muralidharan } 58fc9a8e8dSKaricheri, Muralidharan 59fc9a8e8dSKaricheri, Muralidharan dev->enetaddr[0] = (macb >> 8) & 0xff; 60fc9a8e8dSKaricheri, Muralidharan dev->enetaddr[1] = (macb >> 0) & 0xff; 61fc9a8e8dSKaricheri, Muralidharan dev->enetaddr[2] = (maca >> 24) & 0xff; 62fc9a8e8dSKaricheri, Muralidharan dev->enetaddr[3] = (maca >> 16) & 0xff; 63fc9a8e8dSKaricheri, Muralidharan dev->enetaddr[4] = (maca >> 8) & 0xff; 64fc9a8e8dSKaricheri, Muralidharan dev->enetaddr[5] = (maca >> 0) & 0xff; 65fc9a8e8dSKaricheri, Muralidharan 66fc9a8e8dSKaricheri, Muralidharan return 0; 67fc9a8e8dSKaricheri, Muralidharan } 68fc9a8e8dSKaricheri, Muralidharan 69550c5ce6SKhoronzhuk, Ivan /* MDIO */ 70550c5ce6SKhoronzhuk, Ivan 71550c5ce6SKhoronzhuk, Ivan static int keystone2_mdio_reset(struct mii_dev *bus) 72fc9a8e8dSKaricheri, Muralidharan { 73fc9a8e8dSKaricheri, Muralidharan u_int32_t clkdiv; 74550c5ce6SKhoronzhuk, Ivan struct mdio_regs *adap_mdio = bus->priv; 75fc9a8e8dSKaricheri, Muralidharan 76fc9a8e8dSKaricheri, Muralidharan clkdiv = (EMAC_MDIO_BUS_FREQ / EMAC_MDIO_CLOCK_FREQ) - 1; 77fc9a8e8dSKaricheri, Muralidharan 78550c5ce6SKhoronzhuk, Ivan writel((clkdiv & 0xffff) | MDIO_CONTROL_ENABLE | 79550c5ce6SKhoronzhuk, Ivan MDIO_CONTROL_FAULT | MDIO_CONTROL_FAULT_ENABLE, 80fc9a8e8dSKaricheri, Muralidharan &adap_mdio->control); 81fc9a8e8dSKaricheri, Muralidharan 82fc9a8e8dSKaricheri, Muralidharan while (readl(&adap_mdio->control) & MDIO_CONTROL_IDLE) 83fc9a8e8dSKaricheri, Muralidharan ; 84550c5ce6SKhoronzhuk, Ivan 85550c5ce6SKhoronzhuk, Ivan return 0; 86fc9a8e8dSKaricheri, Muralidharan } 87fc9a8e8dSKaricheri, Muralidharan 88550c5ce6SKhoronzhuk, Ivan /** 89550c5ce6SKhoronzhuk, Ivan * keystone2_mdio_read - read a PHY register via MDIO interface. 90550c5ce6SKhoronzhuk, Ivan * Blocks until operation is complete. 91550c5ce6SKhoronzhuk, Ivan */ 92550c5ce6SKhoronzhuk, Ivan static int keystone2_mdio_read(struct mii_dev *bus, 93550c5ce6SKhoronzhuk, Ivan int addr, int devad, int reg) 94fc9a8e8dSKaricheri, Muralidharan { 95fc9a8e8dSKaricheri, Muralidharan int tmp; 96550c5ce6SKhoronzhuk, Ivan struct mdio_regs *adap_mdio = bus->priv; 97fc9a8e8dSKaricheri, Muralidharan 98fc9a8e8dSKaricheri, Muralidharan while (readl(&adap_mdio->useraccess0) & MDIO_USERACCESS0_GO) 99fc9a8e8dSKaricheri, Muralidharan ; 100fc9a8e8dSKaricheri, Muralidharan 101550c5ce6SKhoronzhuk, Ivan writel(MDIO_USERACCESS0_GO | MDIO_USERACCESS0_WRITE_READ | 102550c5ce6SKhoronzhuk, Ivan ((reg & 0x1f) << 21) | ((addr & 0x1f) << 16), 103fc9a8e8dSKaricheri, Muralidharan &adap_mdio->useraccess0); 104fc9a8e8dSKaricheri, Muralidharan 105fc9a8e8dSKaricheri, Muralidharan /* Wait for command to complete */ 106fc9a8e8dSKaricheri, Muralidharan while ((tmp = readl(&adap_mdio->useraccess0)) & MDIO_USERACCESS0_GO) 107fc9a8e8dSKaricheri, Muralidharan ; 108fc9a8e8dSKaricheri, Muralidharan 109550c5ce6SKhoronzhuk, Ivan if (tmp & MDIO_USERACCESS0_ACK) 110550c5ce6SKhoronzhuk, Ivan return tmp & 0xffff; 111fc9a8e8dSKaricheri, Muralidharan 112fc9a8e8dSKaricheri, Muralidharan return -1; 113fc9a8e8dSKaricheri, Muralidharan } 114fc9a8e8dSKaricheri, Muralidharan 115550c5ce6SKhoronzhuk, Ivan /** 116550c5ce6SKhoronzhuk, Ivan * keystone2_mdio_write - write to a PHY register via MDIO interface. 117fc9a8e8dSKaricheri, Muralidharan * Blocks until operation is complete. 118fc9a8e8dSKaricheri, Muralidharan */ 119550c5ce6SKhoronzhuk, Ivan static int keystone2_mdio_write(struct mii_dev *bus, 120550c5ce6SKhoronzhuk, Ivan int addr, int devad, int reg, u16 val) 121fc9a8e8dSKaricheri, Muralidharan { 122550c5ce6SKhoronzhuk, Ivan struct mdio_regs *adap_mdio = bus->priv; 123550c5ce6SKhoronzhuk, Ivan 124fc9a8e8dSKaricheri, Muralidharan while (readl(&adap_mdio->useraccess0) & MDIO_USERACCESS0_GO) 125fc9a8e8dSKaricheri, Muralidharan ; 126fc9a8e8dSKaricheri, Muralidharan 127550c5ce6SKhoronzhuk, Ivan writel(MDIO_USERACCESS0_GO | MDIO_USERACCESS0_WRITE_WRITE | 128550c5ce6SKhoronzhuk, Ivan ((reg & 0x1f) << 21) | ((addr & 0x1f) << 16) | 129550c5ce6SKhoronzhuk, Ivan (val & 0xffff), &adap_mdio->useraccess0); 130fc9a8e8dSKaricheri, Muralidharan 131fc9a8e8dSKaricheri, Muralidharan /* Wait for command to complete */ 132fc9a8e8dSKaricheri, Muralidharan while (readl(&adap_mdio->useraccess0) & MDIO_USERACCESS0_GO) 133fc9a8e8dSKaricheri, Muralidharan ; 134fc9a8e8dSKaricheri, Muralidharan 135fc9a8e8dSKaricheri, Muralidharan return 0; 136fc9a8e8dSKaricheri, Muralidharan } 137fc9a8e8dSKaricheri, Muralidharan 138fc9a8e8dSKaricheri, Muralidharan static void __attribute__((unused)) 139fc9a8e8dSKaricheri, Muralidharan keystone2_eth_gigabit_enable(struct eth_device *dev) 140fc9a8e8dSKaricheri, Muralidharan { 141fc9a8e8dSKaricheri, Muralidharan u_int16_t data; 142fc9a8e8dSKaricheri, Muralidharan struct eth_priv_t *eth_priv = (struct eth_priv_t *)dev->priv; 143fc9a8e8dSKaricheri, Muralidharan 144fc9a8e8dSKaricheri, Muralidharan if (sys_has_mdio) { 145550c5ce6SKhoronzhuk, Ivan data = keystone2_mdio_read(mdio_bus, eth_priv->phy_addr, 146550c5ce6SKhoronzhuk, Ivan MDIO_DEVAD_NONE, 0); 147550c5ce6SKhoronzhuk, Ivan /* speed selection MSB */ 148550c5ce6SKhoronzhuk, Ivan if (!(data & (1 << 6))) 149fc9a8e8dSKaricheri, Muralidharan return; 150fc9a8e8dSKaricheri, Muralidharan } 151fc9a8e8dSKaricheri, Muralidharan 152fc9a8e8dSKaricheri, Muralidharan /* 153fc9a8e8dSKaricheri, Muralidharan * Check if link detected is giga-bit 154fc9a8e8dSKaricheri, Muralidharan * If Gigabit mode detected, enable gigbit in MAC 155fc9a8e8dSKaricheri, Muralidharan */ 156b2cfe322SHao Zhang writel(readl(DEVICE_EMACSL_BASE(eth_priv->slave_port - 1) + 157b2cfe322SHao Zhang CPGMACSL_REG_CTL) | 158fc9a8e8dSKaricheri, Muralidharan EMAC_MACCONTROL_GIGFORCE | EMAC_MACCONTROL_GIGABIT_ENABLE, 159b2cfe322SHao Zhang DEVICE_EMACSL_BASE(eth_priv->slave_port - 1) + CPGMACSL_REG_CTL); 160fc9a8e8dSKaricheri, Muralidharan } 161fc9a8e8dSKaricheri, Muralidharan 162fc9a8e8dSKaricheri, Muralidharan int keystone_sgmii_link_status(int port) 163fc9a8e8dSKaricheri, Muralidharan { 164fc9a8e8dSKaricheri, Muralidharan u32 status = 0; 165fc9a8e8dSKaricheri, Muralidharan 166fc9a8e8dSKaricheri, Muralidharan status = __raw_readl(SGMII_STATUS_REG(port)); 167fc9a8e8dSKaricheri, Muralidharan 168a4d2adeeSKhoronzhuk, Ivan return (status & SGMII_REG_STATUS_LOCK) && 169a4d2adeeSKhoronzhuk, Ivan (status & SGMII_REG_STATUS_LINK); 170fc9a8e8dSKaricheri, Muralidharan } 171fc9a8e8dSKaricheri, Muralidharan 172fc9a8e8dSKaricheri, Muralidharan int keystone_sgmii_config(int port, int interface) 173fc9a8e8dSKaricheri, Muralidharan { 174fc9a8e8dSKaricheri, Muralidharan unsigned int i, status, mask; 175fc9a8e8dSKaricheri, Muralidharan unsigned int mr_adv_ability, control; 176fc9a8e8dSKaricheri, Muralidharan 177fc9a8e8dSKaricheri, Muralidharan switch (interface) { 178fc9a8e8dSKaricheri, Muralidharan case SGMII_LINK_MAC_MAC_AUTONEG: 179fc9a8e8dSKaricheri, Muralidharan mr_adv_ability = (SGMII_REG_MR_ADV_ENABLE | 180fc9a8e8dSKaricheri, Muralidharan SGMII_REG_MR_ADV_LINK | 181fc9a8e8dSKaricheri, Muralidharan SGMII_REG_MR_ADV_FULL_DUPLEX | 182fc9a8e8dSKaricheri, Muralidharan SGMII_REG_MR_ADV_GIG_MODE); 183fc9a8e8dSKaricheri, Muralidharan control = (SGMII_REG_CONTROL_MASTER | 184fc9a8e8dSKaricheri, Muralidharan SGMII_REG_CONTROL_AUTONEG); 185fc9a8e8dSKaricheri, Muralidharan 186fc9a8e8dSKaricheri, Muralidharan break; 187fc9a8e8dSKaricheri, Muralidharan case SGMII_LINK_MAC_PHY: 188fc9a8e8dSKaricheri, Muralidharan case SGMII_LINK_MAC_PHY_FORCED: 189fc9a8e8dSKaricheri, Muralidharan mr_adv_ability = SGMII_REG_MR_ADV_ENABLE; 190fc9a8e8dSKaricheri, Muralidharan control = SGMII_REG_CONTROL_AUTONEG; 191fc9a8e8dSKaricheri, Muralidharan 192fc9a8e8dSKaricheri, Muralidharan break; 193fc9a8e8dSKaricheri, Muralidharan case SGMII_LINK_MAC_MAC_FORCED: 194fc9a8e8dSKaricheri, Muralidharan mr_adv_ability = (SGMII_REG_MR_ADV_ENABLE | 195fc9a8e8dSKaricheri, Muralidharan SGMII_REG_MR_ADV_LINK | 196fc9a8e8dSKaricheri, Muralidharan SGMII_REG_MR_ADV_FULL_DUPLEX | 197fc9a8e8dSKaricheri, Muralidharan SGMII_REG_MR_ADV_GIG_MODE); 198fc9a8e8dSKaricheri, Muralidharan control = SGMII_REG_CONTROL_MASTER; 199fc9a8e8dSKaricheri, Muralidharan 200fc9a8e8dSKaricheri, Muralidharan break; 201fc9a8e8dSKaricheri, Muralidharan case SGMII_LINK_MAC_FIBER: 202fc9a8e8dSKaricheri, Muralidharan mr_adv_ability = 0x20; 203fc9a8e8dSKaricheri, Muralidharan control = SGMII_REG_CONTROL_AUTONEG; 204fc9a8e8dSKaricheri, Muralidharan 205fc9a8e8dSKaricheri, Muralidharan break; 206fc9a8e8dSKaricheri, Muralidharan default: 207fc9a8e8dSKaricheri, Muralidharan mr_adv_ability = SGMII_REG_MR_ADV_ENABLE; 208fc9a8e8dSKaricheri, Muralidharan control = SGMII_REG_CONTROL_AUTONEG; 209fc9a8e8dSKaricheri, Muralidharan } 210fc9a8e8dSKaricheri, Muralidharan 211fc9a8e8dSKaricheri, Muralidharan __raw_writel(0, SGMII_CTL_REG(port)); 212fc9a8e8dSKaricheri, Muralidharan 213fc9a8e8dSKaricheri, Muralidharan /* 214fc9a8e8dSKaricheri, Muralidharan * Wait for the SerDes pll to lock, 215fc9a8e8dSKaricheri, Muralidharan * but don't trap if lock is never read 216fc9a8e8dSKaricheri, Muralidharan */ 217fc9a8e8dSKaricheri, Muralidharan for (i = 0; i < 1000; i++) { 218fc9a8e8dSKaricheri, Muralidharan udelay(2000); 219fc9a8e8dSKaricheri, Muralidharan status = __raw_readl(SGMII_STATUS_REG(port)); 220fc9a8e8dSKaricheri, Muralidharan if ((status & SGMII_REG_STATUS_LOCK) != 0) 221fc9a8e8dSKaricheri, Muralidharan break; 222fc9a8e8dSKaricheri, Muralidharan } 223fc9a8e8dSKaricheri, Muralidharan 224fc9a8e8dSKaricheri, Muralidharan __raw_writel(mr_adv_ability, SGMII_MRADV_REG(port)); 225fc9a8e8dSKaricheri, Muralidharan __raw_writel(control, SGMII_CTL_REG(port)); 226fc9a8e8dSKaricheri, Muralidharan 227fc9a8e8dSKaricheri, Muralidharan 228fc9a8e8dSKaricheri, Muralidharan mask = SGMII_REG_STATUS_LINK; 229fc9a8e8dSKaricheri, Muralidharan 230fc9a8e8dSKaricheri, Muralidharan if (control & SGMII_REG_CONTROL_AUTONEG) 231fc9a8e8dSKaricheri, Muralidharan mask |= SGMII_REG_STATUS_AUTONEG; 232fc9a8e8dSKaricheri, Muralidharan 233fc9a8e8dSKaricheri, Muralidharan for (i = 0; i < 1000; i++) { 234fc9a8e8dSKaricheri, Muralidharan status = __raw_readl(SGMII_STATUS_REG(port)); 235fc9a8e8dSKaricheri, Muralidharan if ((status & mask) == mask) 236fc9a8e8dSKaricheri, Muralidharan break; 237fc9a8e8dSKaricheri, Muralidharan } 238fc9a8e8dSKaricheri, Muralidharan 239fc9a8e8dSKaricheri, Muralidharan return 0; 240fc9a8e8dSKaricheri, Muralidharan } 241fc9a8e8dSKaricheri, Muralidharan 242fc9a8e8dSKaricheri, Muralidharan int mac_sl_reset(u32 port) 243fc9a8e8dSKaricheri, Muralidharan { 244fc9a8e8dSKaricheri, Muralidharan u32 i, v; 245fc9a8e8dSKaricheri, Muralidharan 246fc9a8e8dSKaricheri, Muralidharan if (port >= DEVICE_N_GMACSL_PORTS) 247fc9a8e8dSKaricheri, Muralidharan return GMACSL_RET_INVALID_PORT; 248fc9a8e8dSKaricheri, Muralidharan 249fc9a8e8dSKaricheri, Muralidharan /* Set the soft reset bit */ 250e6c9428aSKhoronzhuk, Ivan writel(CPGMAC_REG_RESET_VAL_RESET, 251e6c9428aSKhoronzhuk, Ivan DEVICE_EMACSL_BASE(port) + CPGMACSL_REG_RESET); 252fc9a8e8dSKaricheri, Muralidharan 253fc9a8e8dSKaricheri, Muralidharan /* Wait for the bit to clear */ 254fc9a8e8dSKaricheri, Muralidharan for (i = 0; i < DEVICE_EMACSL_RESET_POLL_COUNT; i++) { 255e6c9428aSKhoronzhuk, Ivan v = readl(DEVICE_EMACSL_BASE(port) + CPGMACSL_REG_RESET); 256fc9a8e8dSKaricheri, Muralidharan if ((v & CPGMAC_REG_RESET_VAL_RESET_MASK) != 257fc9a8e8dSKaricheri, Muralidharan CPGMAC_REG_RESET_VAL_RESET) 258fc9a8e8dSKaricheri, Muralidharan return GMACSL_RET_OK; 259fc9a8e8dSKaricheri, Muralidharan } 260fc9a8e8dSKaricheri, Muralidharan 261fc9a8e8dSKaricheri, Muralidharan /* Timeout on the reset */ 262fc9a8e8dSKaricheri, Muralidharan return GMACSL_RET_WARN_RESET_INCOMPLETE; 263fc9a8e8dSKaricheri, Muralidharan } 264fc9a8e8dSKaricheri, Muralidharan 265fc9a8e8dSKaricheri, Muralidharan int mac_sl_config(u_int16_t port, struct mac_sl_cfg *cfg) 266fc9a8e8dSKaricheri, Muralidharan { 267fc9a8e8dSKaricheri, Muralidharan u32 v, i; 268fc9a8e8dSKaricheri, Muralidharan int ret = GMACSL_RET_OK; 269fc9a8e8dSKaricheri, Muralidharan 270fc9a8e8dSKaricheri, Muralidharan if (port >= DEVICE_N_GMACSL_PORTS) 271fc9a8e8dSKaricheri, Muralidharan return GMACSL_RET_INVALID_PORT; 272fc9a8e8dSKaricheri, Muralidharan 273fc9a8e8dSKaricheri, Muralidharan if (cfg->max_rx_len > CPGMAC_REG_MAXLEN_LEN) { 274fc9a8e8dSKaricheri, Muralidharan cfg->max_rx_len = CPGMAC_REG_MAXLEN_LEN; 275fc9a8e8dSKaricheri, Muralidharan ret = GMACSL_RET_WARN_MAXLEN_TOO_BIG; 276fc9a8e8dSKaricheri, Muralidharan } 277fc9a8e8dSKaricheri, Muralidharan 278fc9a8e8dSKaricheri, Muralidharan /* Must wait if the device is undergoing reset */ 279fc9a8e8dSKaricheri, Muralidharan for (i = 0; i < DEVICE_EMACSL_RESET_POLL_COUNT; i++) { 280e6c9428aSKhoronzhuk, Ivan v = readl(DEVICE_EMACSL_BASE(port) + CPGMACSL_REG_RESET); 281fc9a8e8dSKaricheri, Muralidharan if ((v & CPGMAC_REG_RESET_VAL_RESET_MASK) != 282fc9a8e8dSKaricheri, Muralidharan CPGMAC_REG_RESET_VAL_RESET) 283fc9a8e8dSKaricheri, Muralidharan break; 284fc9a8e8dSKaricheri, Muralidharan } 285fc9a8e8dSKaricheri, Muralidharan 286fc9a8e8dSKaricheri, Muralidharan if (i == DEVICE_EMACSL_RESET_POLL_COUNT) 287fc9a8e8dSKaricheri, Muralidharan return GMACSL_RET_CONFIG_FAIL_RESET_ACTIVE; 288fc9a8e8dSKaricheri, Muralidharan 289e6c9428aSKhoronzhuk, Ivan writel(cfg->max_rx_len, DEVICE_EMACSL_BASE(port) + CPGMACSL_REG_MAXLEN); 290e6c9428aSKhoronzhuk, Ivan writel(cfg->ctl, DEVICE_EMACSL_BASE(port) + CPGMACSL_REG_CTL); 291fc9a8e8dSKaricheri, Muralidharan 292fc9a8e8dSKaricheri, Muralidharan return ret; 293fc9a8e8dSKaricheri, Muralidharan } 294fc9a8e8dSKaricheri, Muralidharan 295fc9a8e8dSKaricheri, Muralidharan int ethss_config(u32 ctl, u32 max_pkt_size) 296fc9a8e8dSKaricheri, Muralidharan { 297fc9a8e8dSKaricheri, Muralidharan u32 i; 298fc9a8e8dSKaricheri, Muralidharan 299fc9a8e8dSKaricheri, Muralidharan /* Max length register */ 300e6c9428aSKhoronzhuk, Ivan writel(max_pkt_size, DEVICE_CPSW_BASE + CPSW_REG_MAXLEN); 301fc9a8e8dSKaricheri, Muralidharan 302fc9a8e8dSKaricheri, Muralidharan /* Control register */ 303e6c9428aSKhoronzhuk, Ivan writel(ctl, DEVICE_CPSW_BASE + CPSW_REG_CTL); 304fc9a8e8dSKaricheri, Muralidharan 305fc9a8e8dSKaricheri, Muralidharan /* All statistics enabled by default */ 306e6c9428aSKhoronzhuk, Ivan writel(CPSW_REG_VAL_STAT_ENABLE_ALL, 307e6c9428aSKhoronzhuk, Ivan DEVICE_CPSW_BASE + CPSW_REG_STAT_PORT_EN); 308fc9a8e8dSKaricheri, Muralidharan 309fc9a8e8dSKaricheri, Muralidharan /* Reset and enable the ALE */ 310e6c9428aSKhoronzhuk, Ivan writel(CPSW_REG_VAL_ALE_CTL_RESET_AND_ENABLE | 311e6c9428aSKhoronzhuk, Ivan CPSW_REG_VAL_ALE_CTL_BYPASS, 312e6c9428aSKhoronzhuk, Ivan DEVICE_CPSW_BASE + CPSW_REG_ALE_CONTROL); 313fc9a8e8dSKaricheri, Muralidharan 314fc9a8e8dSKaricheri, Muralidharan /* All ports put into forward mode */ 315fc9a8e8dSKaricheri, Muralidharan for (i = 0; i < DEVICE_CPSW_NUM_PORTS; i++) 316e6c9428aSKhoronzhuk, Ivan writel(CPSW_REG_VAL_PORTCTL_FORWARD_MODE, 317e6c9428aSKhoronzhuk, Ivan DEVICE_CPSW_BASE + CPSW_REG_ALE_PORTCTL(i)); 318fc9a8e8dSKaricheri, Muralidharan 319fc9a8e8dSKaricheri, Muralidharan return 0; 320fc9a8e8dSKaricheri, Muralidharan } 321fc9a8e8dSKaricheri, Muralidharan 322fc9a8e8dSKaricheri, Muralidharan int ethss_start(void) 323fc9a8e8dSKaricheri, Muralidharan { 324fc9a8e8dSKaricheri, Muralidharan int i; 325fc9a8e8dSKaricheri, Muralidharan struct mac_sl_cfg cfg; 326fc9a8e8dSKaricheri, Muralidharan 327fc9a8e8dSKaricheri, Muralidharan cfg.max_rx_len = MAX_SIZE_STREAM_BUFFER; 328fc9a8e8dSKaricheri, Muralidharan cfg.ctl = GMACSL_ENABLE | GMACSL_RX_ENABLE_EXT_CTL; 329fc9a8e8dSKaricheri, Muralidharan 330fc9a8e8dSKaricheri, Muralidharan for (i = 0; i < DEVICE_N_GMACSL_PORTS; i++) { 331fc9a8e8dSKaricheri, Muralidharan mac_sl_reset(i); 332fc9a8e8dSKaricheri, Muralidharan mac_sl_config(i, &cfg); 333fc9a8e8dSKaricheri, Muralidharan } 334fc9a8e8dSKaricheri, Muralidharan 335fc9a8e8dSKaricheri, Muralidharan return 0; 336fc9a8e8dSKaricheri, Muralidharan } 337fc9a8e8dSKaricheri, Muralidharan 338fc9a8e8dSKaricheri, Muralidharan int ethss_stop(void) 339fc9a8e8dSKaricheri, Muralidharan { 340fc9a8e8dSKaricheri, Muralidharan int i; 341fc9a8e8dSKaricheri, Muralidharan 342fc9a8e8dSKaricheri, Muralidharan for (i = 0; i < DEVICE_N_GMACSL_PORTS; i++) 343fc9a8e8dSKaricheri, Muralidharan mac_sl_reset(i); 344fc9a8e8dSKaricheri, Muralidharan 345fc9a8e8dSKaricheri, Muralidharan return 0; 346fc9a8e8dSKaricheri, Muralidharan } 347fc9a8e8dSKaricheri, Muralidharan 348fc9a8e8dSKaricheri, Muralidharan int32_t cpmac_drv_send(u32 *buffer, int num_bytes, int slave_port_num) 349fc9a8e8dSKaricheri, Muralidharan { 350fc9a8e8dSKaricheri, Muralidharan if (num_bytes < EMAC_MIN_ETHERNET_PKT_SIZE) 351fc9a8e8dSKaricheri, Muralidharan num_bytes = EMAC_MIN_ETHERNET_PKT_SIZE; 352fc9a8e8dSKaricheri, Muralidharan 3539ea9021aSKhoronzhuk, Ivan return ksnav_send(&netcp_pktdma, buffer, 3549ea9021aSKhoronzhuk, Ivan num_bytes, (slave_port_num) << 16); 355fc9a8e8dSKaricheri, Muralidharan } 356fc9a8e8dSKaricheri, Muralidharan 357fc9a8e8dSKaricheri, Muralidharan /* Eth device open */ 358fc9a8e8dSKaricheri, Muralidharan static int keystone2_eth_open(struct eth_device *dev, bd_t *bis) 359fc9a8e8dSKaricheri, Muralidharan { 360fc9a8e8dSKaricheri, Muralidharan struct eth_priv_t *eth_priv = (struct eth_priv_t *)dev->priv; 3613fe93623SKhoronzhuk, Ivan struct phy_device *phy_dev = eth_priv->phy_dev; 362fc9a8e8dSKaricheri, Muralidharan 363fc9a8e8dSKaricheri, Muralidharan debug("+ emac_open\n"); 364fc9a8e8dSKaricheri, Muralidharan 365fc9a8e8dSKaricheri, Muralidharan net_rx_buffs.rx_flow = eth_priv->rx_flow; 366fc9a8e8dSKaricheri, Muralidharan 367fc9a8e8dSKaricheri, Muralidharan sys_has_mdio = 368fc9a8e8dSKaricheri, Muralidharan (eth_priv->sgmii_link_type == SGMII_LINK_MAC_PHY) ? 1 : 0; 369fc9a8e8dSKaricheri, Muralidharan 370a43febdeSKhoronzhuk, Ivan keystone2_net_serdes_setup(); 371fc9a8e8dSKaricheri, Muralidharan 372fc9a8e8dSKaricheri, Muralidharan keystone_sgmii_config(eth_priv->slave_port - 1, 373fc9a8e8dSKaricheri, Muralidharan eth_priv->sgmii_link_type); 374fc9a8e8dSKaricheri, Muralidharan 375fc9a8e8dSKaricheri, Muralidharan udelay(10000); 376fc9a8e8dSKaricheri, Muralidharan 377fc9a8e8dSKaricheri, Muralidharan /* On chip switch configuration */ 378fc9a8e8dSKaricheri, Muralidharan ethss_config(target_get_switch_ctl(), SWITCH_MAX_PKT_SIZE); 379fc9a8e8dSKaricheri, Muralidharan 380fc9a8e8dSKaricheri, Muralidharan /* TODO: add error handling code */ 381fc9a8e8dSKaricheri, Muralidharan if (qm_init()) { 382fc9a8e8dSKaricheri, Muralidharan printf("ERROR: qm_init()\n"); 383fc9a8e8dSKaricheri, Muralidharan return -1; 384fc9a8e8dSKaricheri, Muralidharan } 3859ea9021aSKhoronzhuk, Ivan if (ksnav_init(&netcp_pktdma, &net_rx_buffs)) { 386fc9a8e8dSKaricheri, Muralidharan qm_close(); 387fc9a8e8dSKaricheri, Muralidharan printf("ERROR: netcp_init()\n"); 388fc9a8e8dSKaricheri, Muralidharan return -1; 389fc9a8e8dSKaricheri, Muralidharan } 390fc9a8e8dSKaricheri, Muralidharan 391fc9a8e8dSKaricheri, Muralidharan /* 392fc9a8e8dSKaricheri, Muralidharan * Streaming switch configuration. If not present this 393fc9a8e8dSKaricheri, Muralidharan * statement is defined to void in target.h. 394fc9a8e8dSKaricheri, Muralidharan * If present this is usually defined to a series of register writes 395fc9a8e8dSKaricheri, Muralidharan */ 396fc9a8e8dSKaricheri, Muralidharan hw_config_streaming_switch(); 397fc9a8e8dSKaricheri, Muralidharan 398fc9a8e8dSKaricheri, Muralidharan if (sys_has_mdio) { 399550c5ce6SKhoronzhuk, Ivan keystone2_mdio_reset(mdio_bus); 400fc9a8e8dSKaricheri, Muralidharan 4013fe93623SKhoronzhuk, Ivan phy_startup(phy_dev); 4023fe93623SKhoronzhuk, Ivan if (phy_dev->link == 0) { 4039ea9021aSKhoronzhuk, Ivan ksnav_close(&netcp_pktdma); 404fc9a8e8dSKaricheri, Muralidharan qm_close(); 405fc9a8e8dSKaricheri, Muralidharan return -1; 406fc9a8e8dSKaricheri, Muralidharan } 407fc9a8e8dSKaricheri, Muralidharan } 408fc9a8e8dSKaricheri, Muralidharan 409fc9a8e8dSKaricheri, Muralidharan emac_gigabit_enable(dev); 410fc9a8e8dSKaricheri, Muralidharan 411fc9a8e8dSKaricheri, Muralidharan ethss_start(); 412fc9a8e8dSKaricheri, Muralidharan 413fc9a8e8dSKaricheri, Muralidharan debug("- emac_open\n"); 414fc9a8e8dSKaricheri, Muralidharan 415fc9a8e8dSKaricheri, Muralidharan emac_open = 1; 416fc9a8e8dSKaricheri, Muralidharan 417fc9a8e8dSKaricheri, Muralidharan return 0; 418fc9a8e8dSKaricheri, Muralidharan } 419fc9a8e8dSKaricheri, Muralidharan 420fc9a8e8dSKaricheri, Muralidharan /* Eth device close */ 421fc9a8e8dSKaricheri, Muralidharan void keystone2_eth_close(struct eth_device *dev) 422fc9a8e8dSKaricheri, Muralidharan { 4233fe93623SKhoronzhuk, Ivan struct eth_priv_t *eth_priv = (struct eth_priv_t *)dev->priv; 4243fe93623SKhoronzhuk, Ivan struct phy_device *phy_dev = eth_priv->phy_dev; 4253fe93623SKhoronzhuk, Ivan 426fc9a8e8dSKaricheri, Muralidharan debug("+ emac_close\n"); 427fc9a8e8dSKaricheri, Muralidharan 428fc9a8e8dSKaricheri, Muralidharan if (!emac_open) 429fc9a8e8dSKaricheri, Muralidharan return; 430fc9a8e8dSKaricheri, Muralidharan 431fc9a8e8dSKaricheri, Muralidharan ethss_stop(); 432fc9a8e8dSKaricheri, Muralidharan 4339ea9021aSKhoronzhuk, Ivan ksnav_close(&netcp_pktdma); 434fc9a8e8dSKaricheri, Muralidharan qm_close(); 4353fe93623SKhoronzhuk, Ivan phy_shutdown(phy_dev); 436fc9a8e8dSKaricheri, Muralidharan 437fc9a8e8dSKaricheri, Muralidharan emac_open = 0; 438fc9a8e8dSKaricheri, Muralidharan 439fc9a8e8dSKaricheri, Muralidharan debug("- emac_close\n"); 440fc9a8e8dSKaricheri, Muralidharan } 441fc9a8e8dSKaricheri, Muralidharan 442fc9a8e8dSKaricheri, Muralidharan /* 443fc9a8e8dSKaricheri, Muralidharan * This function sends a single packet on the network and returns 444fc9a8e8dSKaricheri, Muralidharan * positive number (number of bytes transmitted) or negative for error 445fc9a8e8dSKaricheri, Muralidharan */ 446fc9a8e8dSKaricheri, Muralidharan static int keystone2_eth_send_packet(struct eth_device *dev, 447fc9a8e8dSKaricheri, Muralidharan void *packet, int length) 448fc9a8e8dSKaricheri, Muralidharan { 449fc9a8e8dSKaricheri, Muralidharan int ret_status = -1; 450fc9a8e8dSKaricheri, Muralidharan struct eth_priv_t *eth_priv = (struct eth_priv_t *)dev->priv; 451a4d2adeeSKhoronzhuk, Ivan struct phy_device *phy_dev = eth_priv->phy_dev; 452fc9a8e8dSKaricheri, Muralidharan 453a4d2adeeSKhoronzhuk, Ivan genphy_update_link(phy_dev); 454a4d2adeeSKhoronzhuk, Ivan if (phy_dev->link == 0) 455fc9a8e8dSKaricheri, Muralidharan return -1; 456fc9a8e8dSKaricheri, Muralidharan 457fc9a8e8dSKaricheri, Muralidharan if (cpmac_drv_send((u32 *)packet, length, eth_priv->slave_port) != 0) 458fc9a8e8dSKaricheri, Muralidharan return ret_status; 459fc9a8e8dSKaricheri, Muralidharan 460fc9a8e8dSKaricheri, Muralidharan return length; 461fc9a8e8dSKaricheri, Muralidharan } 462fc9a8e8dSKaricheri, Muralidharan 463fc9a8e8dSKaricheri, Muralidharan /* 464fc9a8e8dSKaricheri, Muralidharan * This function handles receipt of a packet from the network 465fc9a8e8dSKaricheri, Muralidharan */ 466fc9a8e8dSKaricheri, Muralidharan static int keystone2_eth_rcv_packet(struct eth_device *dev) 467fc9a8e8dSKaricheri, Muralidharan { 468fc9a8e8dSKaricheri, Muralidharan void *hd; 469fc9a8e8dSKaricheri, Muralidharan int pkt_size; 470fc9a8e8dSKaricheri, Muralidharan u32 *pkt; 471fc9a8e8dSKaricheri, Muralidharan 4729ea9021aSKhoronzhuk, Ivan hd = ksnav_recv(&netcp_pktdma, &pkt, &pkt_size); 473fc9a8e8dSKaricheri, Muralidharan if (hd == NULL) 474fc9a8e8dSKaricheri, Muralidharan return 0; 475fc9a8e8dSKaricheri, Muralidharan 476fc9a8e8dSKaricheri, Muralidharan NetReceive((uchar *)pkt, pkt_size); 477fc9a8e8dSKaricheri, Muralidharan 4789ea9021aSKhoronzhuk, Ivan ksnav_release_rxhd(&netcp_pktdma, hd); 479fc9a8e8dSKaricheri, Muralidharan 480fc9a8e8dSKaricheri, Muralidharan return pkt_size; 481fc9a8e8dSKaricheri, Muralidharan } 482fc9a8e8dSKaricheri, Muralidharan 483fc9a8e8dSKaricheri, Muralidharan /* 484fc9a8e8dSKaricheri, Muralidharan * This function initializes the EMAC hardware. 485fc9a8e8dSKaricheri, Muralidharan */ 486fc9a8e8dSKaricheri, Muralidharan int keystone2_emac_initialize(struct eth_priv_t *eth_priv) 487fc9a8e8dSKaricheri, Muralidharan { 488550c5ce6SKhoronzhuk, Ivan int res; 489fc9a8e8dSKaricheri, Muralidharan struct eth_device *dev; 4903fe93623SKhoronzhuk, Ivan struct phy_device *phy_dev; 491fc9a8e8dSKaricheri, Muralidharan 492fc9a8e8dSKaricheri, Muralidharan dev = malloc(sizeof(struct eth_device)); 493fc9a8e8dSKaricheri, Muralidharan if (dev == NULL) 494fc9a8e8dSKaricheri, Muralidharan return -1; 495fc9a8e8dSKaricheri, Muralidharan 496fc9a8e8dSKaricheri, Muralidharan memset(dev, 0, sizeof(struct eth_device)); 497fc9a8e8dSKaricheri, Muralidharan 498fc9a8e8dSKaricheri, Muralidharan strcpy(dev->name, eth_priv->int_name); 499fc9a8e8dSKaricheri, Muralidharan dev->priv = eth_priv; 500fc9a8e8dSKaricheri, Muralidharan 501fc9a8e8dSKaricheri, Muralidharan keystone2_eth_read_mac_addr(dev); 502fc9a8e8dSKaricheri, Muralidharan 503fc9a8e8dSKaricheri, Muralidharan dev->iobase = 0; 504fc9a8e8dSKaricheri, Muralidharan dev->init = keystone2_eth_open; 505fc9a8e8dSKaricheri, Muralidharan dev->halt = keystone2_eth_close; 506fc9a8e8dSKaricheri, Muralidharan dev->send = keystone2_eth_send_packet; 507fc9a8e8dSKaricheri, Muralidharan dev->recv = keystone2_eth_rcv_packet; 508fc9a8e8dSKaricheri, Muralidharan 509fc9a8e8dSKaricheri, Muralidharan eth_register(dev); 510fc9a8e8dSKaricheri, Muralidharan 511550c5ce6SKhoronzhuk, Ivan /* Register MDIO bus if it's not registered yet */ 512550c5ce6SKhoronzhuk, Ivan if (!mdio_bus) { 513550c5ce6SKhoronzhuk, Ivan mdio_bus = mdio_alloc(); 514550c5ce6SKhoronzhuk, Ivan mdio_bus->read = keystone2_mdio_read; 515550c5ce6SKhoronzhuk, Ivan mdio_bus->write = keystone2_mdio_write; 516550c5ce6SKhoronzhuk, Ivan mdio_bus->reset = keystone2_mdio_reset; 517550c5ce6SKhoronzhuk, Ivan mdio_bus->priv = (void *)EMAC_MDIO_BASE_ADDR; 518550c5ce6SKhoronzhuk, Ivan sprintf(mdio_bus->name, "ethernet-mdio"); 519550c5ce6SKhoronzhuk, Ivan 520550c5ce6SKhoronzhuk, Ivan res = mdio_register(mdio_bus); 521550c5ce6SKhoronzhuk, Ivan if (res) 522550c5ce6SKhoronzhuk, Ivan return res; 523550c5ce6SKhoronzhuk, Ivan } 524550c5ce6SKhoronzhuk, Ivan 5253fe93623SKhoronzhuk, Ivan /* Create phy device and bind it with driver */ 5263fe93623SKhoronzhuk, Ivan #ifdef CONFIG_KSNET_MDIO_PHY_CONFIG_ENABLE 5273fe93623SKhoronzhuk, Ivan phy_dev = phy_connect(mdio_bus, eth_priv->phy_addr, 5283fe93623SKhoronzhuk, Ivan dev, PHY_INTERFACE_MODE_SGMII); 5293fe93623SKhoronzhuk, Ivan phy_config(phy_dev); 5303fe93623SKhoronzhuk, Ivan #else 5313fe93623SKhoronzhuk, Ivan phy_dev = phy_find_by_mask(mdio_bus, 1 << eth_priv->phy_addr, 5323fe93623SKhoronzhuk, Ivan PHY_INTERFACE_MODE_SGMII); 5333fe93623SKhoronzhuk, Ivan phy_dev->dev = dev; 5343fe93623SKhoronzhuk, Ivan #endif 5353fe93623SKhoronzhuk, Ivan eth_priv->phy_dev = phy_dev; 5363fe93623SKhoronzhuk, Ivan 537fc9a8e8dSKaricheri, Muralidharan return 0; 538fc9a8e8dSKaricheri, Muralidharan } 539fc9a8e8dSKaricheri, Muralidharan 54092a16c81SHao Zhang struct ks2_serdes ks2_serdes_sgmii_156p25mhz = { 54192a16c81SHao Zhang .clk = SERDES_CLOCK_156P25M, 54292a16c81SHao Zhang .rate = SERDES_RATE_5G, 54392a16c81SHao Zhang .rate_mode = SERDES_QUARTER_RATE, 54492a16c81SHao Zhang .intf = SERDES_PHY_SGMII, 54592a16c81SHao Zhang .loopback = 0, 54692a16c81SHao Zhang }; 54792a16c81SHao Zhang 548a43febdeSKhoronzhuk, Ivan static void keystone2_net_serdes_setup(void) 549fc9a8e8dSKaricheri, Muralidharan { 55092a16c81SHao Zhang ks2_serdes_init(CONFIG_KSNET_SERDES_SGMII_BASE, 55192a16c81SHao Zhang &ks2_serdes_sgmii_156p25mhz, 55292a16c81SHao Zhang CONFIG_KSNET_SERDES_LANES_PER_SGMII); 55392a16c81SHao Zhang 554*3c61502aSKhoronzhuk, Ivan #ifdef CONFIG_SOC_K2E 555*3c61502aSKhoronzhuk, Ivan ks2_serdes_init(CONFIG_KSNET_SERDES_SGMII2_BASE, 556*3c61502aSKhoronzhuk, Ivan &ks2_serdes_sgmii_156p25mhz, 557*3c61502aSKhoronzhuk, Ivan CONFIG_KSNET_SERDES_LANES_PER_SGMII); 558*3c61502aSKhoronzhuk, Ivan #endif 559*3c61502aSKhoronzhuk, Ivan 56092a16c81SHao Zhang /* wait till setup */ 56192a16c81SHao Zhang udelay(5000); 562fc9a8e8dSKaricheri, Muralidharan } 563