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> 13fc9a8e8dSKaricheri, Muralidharan #include <miiphy.h> 14fc9a8e8dSKaricheri, Muralidharan #include <malloc.h> 15fc9a8e8dSKaricheri, Muralidharan #include <asm/arch/emac_defs.h> 16fc9a8e8dSKaricheri, Muralidharan #include <asm/arch/psc_defs.h> 17*ef454717SKhoronzhuk, Ivan #include <asm/ti-common/keystone_nav.h> 18fc9a8e8dSKaricheri, Muralidharan 19fc9a8e8dSKaricheri, Muralidharan unsigned int emac_dbg; 20fc9a8e8dSKaricheri, Muralidharan 21fc9a8e8dSKaricheri, Muralidharan unsigned int emac_open; 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 43fc9a8e8dSKaricheri, Muralidharan static void keystone2_eth_mdio_enable(void); 44fc9a8e8dSKaricheri, Muralidharan 45fc9a8e8dSKaricheri, Muralidharan static int gen_get_link_speed(int phy_addr); 46fc9a8e8dSKaricheri, Muralidharan 47fc9a8e8dSKaricheri, Muralidharan /* EMAC Addresses */ 48fc9a8e8dSKaricheri, Muralidharan static volatile struct emac_regs *adap_emac = 49fc9a8e8dSKaricheri, Muralidharan (struct emac_regs *)EMAC_EMACSL_BASE_ADDR; 50fc9a8e8dSKaricheri, Muralidharan static volatile struct mdio_regs *adap_mdio = 51fc9a8e8dSKaricheri, Muralidharan (struct mdio_regs *)EMAC_MDIO_BASE_ADDR; 52fc9a8e8dSKaricheri, Muralidharan 53fc9a8e8dSKaricheri, Muralidharan int keystone2_eth_read_mac_addr(struct eth_device *dev) 54fc9a8e8dSKaricheri, Muralidharan { 55fc9a8e8dSKaricheri, Muralidharan struct eth_priv_t *eth_priv; 56fc9a8e8dSKaricheri, Muralidharan u32 maca = 0; 57fc9a8e8dSKaricheri, Muralidharan u32 macb = 0; 58fc9a8e8dSKaricheri, Muralidharan 59fc9a8e8dSKaricheri, Muralidharan eth_priv = (struct eth_priv_t *)dev->priv; 60fc9a8e8dSKaricheri, Muralidharan 61fc9a8e8dSKaricheri, Muralidharan /* Read the e-fuse mac address */ 62fc9a8e8dSKaricheri, Muralidharan if (eth_priv->slave_port == 1) { 63fc9a8e8dSKaricheri, Muralidharan maca = __raw_readl(MAC_ID_BASE_ADDR); 64fc9a8e8dSKaricheri, Muralidharan macb = __raw_readl(MAC_ID_BASE_ADDR + 4); 65fc9a8e8dSKaricheri, Muralidharan } 66fc9a8e8dSKaricheri, Muralidharan 67fc9a8e8dSKaricheri, Muralidharan dev->enetaddr[0] = (macb >> 8) & 0xff; 68fc9a8e8dSKaricheri, Muralidharan dev->enetaddr[1] = (macb >> 0) & 0xff; 69fc9a8e8dSKaricheri, Muralidharan dev->enetaddr[2] = (maca >> 24) & 0xff; 70fc9a8e8dSKaricheri, Muralidharan dev->enetaddr[3] = (maca >> 16) & 0xff; 71fc9a8e8dSKaricheri, Muralidharan dev->enetaddr[4] = (maca >> 8) & 0xff; 72fc9a8e8dSKaricheri, Muralidharan dev->enetaddr[5] = (maca >> 0) & 0xff; 73fc9a8e8dSKaricheri, Muralidharan 74fc9a8e8dSKaricheri, Muralidharan return 0; 75fc9a8e8dSKaricheri, Muralidharan } 76fc9a8e8dSKaricheri, Muralidharan 77fc9a8e8dSKaricheri, Muralidharan static void keystone2_eth_mdio_enable(void) 78fc9a8e8dSKaricheri, Muralidharan { 79fc9a8e8dSKaricheri, Muralidharan u_int32_t clkdiv; 80fc9a8e8dSKaricheri, Muralidharan 81fc9a8e8dSKaricheri, Muralidharan clkdiv = (EMAC_MDIO_BUS_FREQ / EMAC_MDIO_CLOCK_FREQ) - 1; 82fc9a8e8dSKaricheri, Muralidharan 83fc9a8e8dSKaricheri, Muralidharan writel((clkdiv & 0xffff) | 84fc9a8e8dSKaricheri, Muralidharan MDIO_CONTROL_ENABLE | 85fc9a8e8dSKaricheri, Muralidharan MDIO_CONTROL_FAULT | 86fc9a8e8dSKaricheri, Muralidharan MDIO_CONTROL_FAULT_ENABLE, 87fc9a8e8dSKaricheri, Muralidharan &adap_mdio->control); 88fc9a8e8dSKaricheri, Muralidharan 89fc9a8e8dSKaricheri, Muralidharan while (readl(&adap_mdio->control) & MDIO_CONTROL_IDLE) 90fc9a8e8dSKaricheri, Muralidharan ; 91fc9a8e8dSKaricheri, Muralidharan } 92fc9a8e8dSKaricheri, Muralidharan 93fc9a8e8dSKaricheri, Muralidharan /* Read a PHY register via MDIO inteface. Returns 1 on success, 0 otherwise */ 94fc9a8e8dSKaricheri, Muralidharan int keystone2_eth_phy_read(u_int8_t phy_addr, u_int8_t reg_num, u_int16_t *data) 95fc9a8e8dSKaricheri, Muralidharan { 96fc9a8e8dSKaricheri, Muralidharan int tmp; 97fc9a8e8dSKaricheri, Muralidharan 98fc9a8e8dSKaricheri, Muralidharan while (readl(&adap_mdio->useraccess0) & MDIO_USERACCESS0_GO) 99fc9a8e8dSKaricheri, Muralidharan ; 100fc9a8e8dSKaricheri, Muralidharan 101fc9a8e8dSKaricheri, Muralidharan writel(MDIO_USERACCESS0_GO | 102fc9a8e8dSKaricheri, Muralidharan MDIO_USERACCESS0_WRITE_READ | 103fc9a8e8dSKaricheri, Muralidharan ((reg_num & 0x1f) << 21) | 104fc9a8e8dSKaricheri, Muralidharan ((phy_addr & 0x1f) << 16), 105fc9a8e8dSKaricheri, Muralidharan &adap_mdio->useraccess0); 106fc9a8e8dSKaricheri, Muralidharan 107fc9a8e8dSKaricheri, Muralidharan /* Wait for command to complete */ 108fc9a8e8dSKaricheri, Muralidharan while ((tmp = readl(&adap_mdio->useraccess0)) & MDIO_USERACCESS0_GO) 109fc9a8e8dSKaricheri, Muralidharan ; 110fc9a8e8dSKaricheri, Muralidharan 111fc9a8e8dSKaricheri, Muralidharan if (tmp & MDIO_USERACCESS0_ACK) { 112fc9a8e8dSKaricheri, Muralidharan *data = tmp & 0xffff; 113fc9a8e8dSKaricheri, Muralidharan return 0; 114fc9a8e8dSKaricheri, Muralidharan } 115fc9a8e8dSKaricheri, Muralidharan 116fc9a8e8dSKaricheri, Muralidharan *data = -1; 117fc9a8e8dSKaricheri, Muralidharan return -1; 118fc9a8e8dSKaricheri, Muralidharan } 119fc9a8e8dSKaricheri, Muralidharan 120fc9a8e8dSKaricheri, Muralidharan /* 121fc9a8e8dSKaricheri, Muralidharan * Write to a PHY register via MDIO inteface. 122fc9a8e8dSKaricheri, Muralidharan * Blocks until operation is complete. 123fc9a8e8dSKaricheri, Muralidharan */ 124fc9a8e8dSKaricheri, Muralidharan int keystone2_eth_phy_write(u_int8_t phy_addr, u_int8_t reg_num, u_int16_t data) 125fc9a8e8dSKaricheri, Muralidharan { 126fc9a8e8dSKaricheri, Muralidharan while (readl(&adap_mdio->useraccess0) & MDIO_USERACCESS0_GO) 127fc9a8e8dSKaricheri, Muralidharan ; 128fc9a8e8dSKaricheri, Muralidharan 129fc9a8e8dSKaricheri, Muralidharan writel(MDIO_USERACCESS0_GO | 130fc9a8e8dSKaricheri, Muralidharan MDIO_USERACCESS0_WRITE_WRITE | 131fc9a8e8dSKaricheri, Muralidharan ((reg_num & 0x1f) << 21) | 132fc9a8e8dSKaricheri, Muralidharan ((phy_addr & 0x1f) << 16) | 133fc9a8e8dSKaricheri, Muralidharan (data & 0xffff), 134fc9a8e8dSKaricheri, Muralidharan &adap_mdio->useraccess0); 135fc9a8e8dSKaricheri, Muralidharan 136fc9a8e8dSKaricheri, Muralidharan /* Wait for command to complete */ 137fc9a8e8dSKaricheri, Muralidharan while (readl(&adap_mdio->useraccess0) & MDIO_USERACCESS0_GO) 138fc9a8e8dSKaricheri, Muralidharan ; 139fc9a8e8dSKaricheri, Muralidharan 140fc9a8e8dSKaricheri, Muralidharan return 0; 141fc9a8e8dSKaricheri, Muralidharan } 142fc9a8e8dSKaricheri, Muralidharan 143fc9a8e8dSKaricheri, Muralidharan /* PHY functions for a generic PHY */ 144fc9a8e8dSKaricheri, Muralidharan static int gen_get_link_speed(int phy_addr) 145fc9a8e8dSKaricheri, Muralidharan { 146fc9a8e8dSKaricheri, Muralidharan u_int16_t tmp; 147fc9a8e8dSKaricheri, Muralidharan 148fc9a8e8dSKaricheri, Muralidharan if ((!keystone2_eth_phy_read(phy_addr, MII_STATUS_REG, &tmp)) && 149fc9a8e8dSKaricheri, Muralidharan (tmp & 0x04)) { 150fc9a8e8dSKaricheri, Muralidharan return 0; 151fc9a8e8dSKaricheri, Muralidharan } 152fc9a8e8dSKaricheri, Muralidharan 153fc9a8e8dSKaricheri, Muralidharan return -1; 154fc9a8e8dSKaricheri, Muralidharan } 155fc9a8e8dSKaricheri, Muralidharan 156fc9a8e8dSKaricheri, Muralidharan static void __attribute__((unused)) 157fc9a8e8dSKaricheri, Muralidharan keystone2_eth_gigabit_enable(struct eth_device *dev) 158fc9a8e8dSKaricheri, Muralidharan { 159fc9a8e8dSKaricheri, Muralidharan u_int16_t data; 160fc9a8e8dSKaricheri, Muralidharan struct eth_priv_t *eth_priv = (struct eth_priv_t *)dev->priv; 161fc9a8e8dSKaricheri, Muralidharan 162fc9a8e8dSKaricheri, Muralidharan if (sys_has_mdio) { 163fc9a8e8dSKaricheri, Muralidharan if (keystone2_eth_phy_read(eth_priv->phy_addr, 0, &data) || 164fc9a8e8dSKaricheri, Muralidharan !(data & (1 << 6))) /* speed selection MSB */ 165fc9a8e8dSKaricheri, Muralidharan return; 166fc9a8e8dSKaricheri, Muralidharan } 167fc9a8e8dSKaricheri, Muralidharan 168fc9a8e8dSKaricheri, Muralidharan /* 169fc9a8e8dSKaricheri, Muralidharan * Check if link detected is giga-bit 170fc9a8e8dSKaricheri, Muralidharan * If Gigabit mode detected, enable gigbit in MAC 171fc9a8e8dSKaricheri, Muralidharan */ 172fc9a8e8dSKaricheri, Muralidharan writel(readl(&(adap_emac[eth_priv->slave_port - 1].maccontrol)) | 173fc9a8e8dSKaricheri, Muralidharan EMAC_MACCONTROL_GIGFORCE | EMAC_MACCONTROL_GIGABIT_ENABLE, 174fc9a8e8dSKaricheri, Muralidharan &(adap_emac[eth_priv->slave_port - 1].maccontrol)) 175fc9a8e8dSKaricheri, Muralidharan ; 176fc9a8e8dSKaricheri, Muralidharan } 177fc9a8e8dSKaricheri, Muralidharan 178fc9a8e8dSKaricheri, Muralidharan int keystone_sgmii_link_status(int port) 179fc9a8e8dSKaricheri, Muralidharan { 180fc9a8e8dSKaricheri, Muralidharan u32 status = 0; 181fc9a8e8dSKaricheri, Muralidharan 182fc9a8e8dSKaricheri, Muralidharan status = __raw_readl(SGMII_STATUS_REG(port)); 183fc9a8e8dSKaricheri, Muralidharan 184fc9a8e8dSKaricheri, Muralidharan return status & SGMII_REG_STATUS_LINK; 185fc9a8e8dSKaricheri, Muralidharan } 186fc9a8e8dSKaricheri, Muralidharan 187fc9a8e8dSKaricheri, Muralidharan 188fc9a8e8dSKaricheri, Muralidharan int keystone_get_link_status(struct eth_device *dev) 189fc9a8e8dSKaricheri, Muralidharan { 190fc9a8e8dSKaricheri, Muralidharan struct eth_priv_t *eth_priv = (struct eth_priv_t *)dev->priv; 191fc9a8e8dSKaricheri, Muralidharan int sgmii_link; 192fc9a8e8dSKaricheri, Muralidharan int link_state = 0; 193fc9a8e8dSKaricheri, Muralidharan #if CONFIG_GET_LINK_STATUS_ATTEMPTS > 1 194fc9a8e8dSKaricheri, Muralidharan int j; 195fc9a8e8dSKaricheri, Muralidharan 196fc9a8e8dSKaricheri, Muralidharan for (j = 0; (j < CONFIG_GET_LINK_STATUS_ATTEMPTS) && (link_state == 0); 197fc9a8e8dSKaricheri, Muralidharan j++) { 198fc9a8e8dSKaricheri, Muralidharan #endif 199fc9a8e8dSKaricheri, Muralidharan sgmii_link = 200fc9a8e8dSKaricheri, Muralidharan keystone_sgmii_link_status(eth_priv->slave_port - 1); 201fc9a8e8dSKaricheri, Muralidharan 202fc9a8e8dSKaricheri, Muralidharan if (sgmii_link) { 203fc9a8e8dSKaricheri, Muralidharan link_state = 1; 204fc9a8e8dSKaricheri, Muralidharan 205fc9a8e8dSKaricheri, Muralidharan if (eth_priv->sgmii_link_type == SGMII_LINK_MAC_PHY) 206fc9a8e8dSKaricheri, Muralidharan if (gen_get_link_speed(eth_priv->phy_addr)) 207fc9a8e8dSKaricheri, Muralidharan link_state = 0; 208fc9a8e8dSKaricheri, Muralidharan } 209fc9a8e8dSKaricheri, Muralidharan #if CONFIG_GET_LINK_STATUS_ATTEMPTS > 1 210fc9a8e8dSKaricheri, Muralidharan } 211fc9a8e8dSKaricheri, Muralidharan #endif 212fc9a8e8dSKaricheri, Muralidharan return link_state; 213fc9a8e8dSKaricheri, Muralidharan } 214fc9a8e8dSKaricheri, Muralidharan 215fc9a8e8dSKaricheri, Muralidharan int keystone_sgmii_config(int port, int interface) 216fc9a8e8dSKaricheri, Muralidharan { 217fc9a8e8dSKaricheri, Muralidharan unsigned int i, status, mask; 218fc9a8e8dSKaricheri, Muralidharan unsigned int mr_adv_ability, control; 219fc9a8e8dSKaricheri, Muralidharan 220fc9a8e8dSKaricheri, Muralidharan switch (interface) { 221fc9a8e8dSKaricheri, Muralidharan case SGMII_LINK_MAC_MAC_AUTONEG: 222fc9a8e8dSKaricheri, Muralidharan mr_adv_ability = (SGMII_REG_MR_ADV_ENABLE | 223fc9a8e8dSKaricheri, Muralidharan SGMII_REG_MR_ADV_LINK | 224fc9a8e8dSKaricheri, Muralidharan SGMII_REG_MR_ADV_FULL_DUPLEX | 225fc9a8e8dSKaricheri, Muralidharan SGMII_REG_MR_ADV_GIG_MODE); 226fc9a8e8dSKaricheri, Muralidharan control = (SGMII_REG_CONTROL_MASTER | 227fc9a8e8dSKaricheri, Muralidharan SGMII_REG_CONTROL_AUTONEG); 228fc9a8e8dSKaricheri, Muralidharan 229fc9a8e8dSKaricheri, Muralidharan break; 230fc9a8e8dSKaricheri, Muralidharan case SGMII_LINK_MAC_PHY: 231fc9a8e8dSKaricheri, Muralidharan case SGMII_LINK_MAC_PHY_FORCED: 232fc9a8e8dSKaricheri, Muralidharan mr_adv_ability = SGMII_REG_MR_ADV_ENABLE; 233fc9a8e8dSKaricheri, Muralidharan control = SGMII_REG_CONTROL_AUTONEG; 234fc9a8e8dSKaricheri, Muralidharan 235fc9a8e8dSKaricheri, Muralidharan break; 236fc9a8e8dSKaricheri, Muralidharan case SGMII_LINK_MAC_MAC_FORCED: 237fc9a8e8dSKaricheri, Muralidharan mr_adv_ability = (SGMII_REG_MR_ADV_ENABLE | 238fc9a8e8dSKaricheri, Muralidharan SGMII_REG_MR_ADV_LINK | 239fc9a8e8dSKaricheri, Muralidharan SGMII_REG_MR_ADV_FULL_DUPLEX | 240fc9a8e8dSKaricheri, Muralidharan SGMII_REG_MR_ADV_GIG_MODE); 241fc9a8e8dSKaricheri, Muralidharan control = SGMII_REG_CONTROL_MASTER; 242fc9a8e8dSKaricheri, Muralidharan 243fc9a8e8dSKaricheri, Muralidharan break; 244fc9a8e8dSKaricheri, Muralidharan case SGMII_LINK_MAC_FIBER: 245fc9a8e8dSKaricheri, Muralidharan mr_adv_ability = 0x20; 246fc9a8e8dSKaricheri, Muralidharan control = SGMII_REG_CONTROL_AUTONEG; 247fc9a8e8dSKaricheri, Muralidharan 248fc9a8e8dSKaricheri, Muralidharan break; 249fc9a8e8dSKaricheri, Muralidharan default: 250fc9a8e8dSKaricheri, Muralidharan mr_adv_ability = SGMII_REG_MR_ADV_ENABLE; 251fc9a8e8dSKaricheri, Muralidharan control = SGMII_REG_CONTROL_AUTONEG; 252fc9a8e8dSKaricheri, Muralidharan } 253fc9a8e8dSKaricheri, Muralidharan 254fc9a8e8dSKaricheri, Muralidharan __raw_writel(0, SGMII_CTL_REG(port)); 255fc9a8e8dSKaricheri, Muralidharan 256fc9a8e8dSKaricheri, Muralidharan /* 257fc9a8e8dSKaricheri, Muralidharan * Wait for the SerDes pll to lock, 258fc9a8e8dSKaricheri, Muralidharan * but don't trap if lock is never read 259fc9a8e8dSKaricheri, Muralidharan */ 260fc9a8e8dSKaricheri, Muralidharan for (i = 0; i < 1000; i++) { 261fc9a8e8dSKaricheri, Muralidharan udelay(2000); 262fc9a8e8dSKaricheri, Muralidharan status = __raw_readl(SGMII_STATUS_REG(port)); 263fc9a8e8dSKaricheri, Muralidharan if ((status & SGMII_REG_STATUS_LOCK) != 0) 264fc9a8e8dSKaricheri, Muralidharan break; 265fc9a8e8dSKaricheri, Muralidharan } 266fc9a8e8dSKaricheri, Muralidharan 267fc9a8e8dSKaricheri, Muralidharan __raw_writel(mr_adv_ability, SGMII_MRADV_REG(port)); 268fc9a8e8dSKaricheri, Muralidharan __raw_writel(control, SGMII_CTL_REG(port)); 269fc9a8e8dSKaricheri, Muralidharan 270fc9a8e8dSKaricheri, Muralidharan 271fc9a8e8dSKaricheri, Muralidharan mask = SGMII_REG_STATUS_LINK; 272fc9a8e8dSKaricheri, Muralidharan 273fc9a8e8dSKaricheri, Muralidharan if (control & SGMII_REG_CONTROL_AUTONEG) 274fc9a8e8dSKaricheri, Muralidharan mask |= SGMII_REG_STATUS_AUTONEG; 275fc9a8e8dSKaricheri, Muralidharan 276fc9a8e8dSKaricheri, Muralidharan for (i = 0; i < 1000; i++) { 277fc9a8e8dSKaricheri, Muralidharan status = __raw_readl(SGMII_STATUS_REG(port)); 278fc9a8e8dSKaricheri, Muralidharan if ((status & mask) == mask) 279fc9a8e8dSKaricheri, Muralidharan break; 280fc9a8e8dSKaricheri, Muralidharan } 281fc9a8e8dSKaricheri, Muralidharan 282fc9a8e8dSKaricheri, Muralidharan return 0; 283fc9a8e8dSKaricheri, Muralidharan } 284fc9a8e8dSKaricheri, Muralidharan 285fc9a8e8dSKaricheri, Muralidharan int mac_sl_reset(u32 port) 286fc9a8e8dSKaricheri, Muralidharan { 287fc9a8e8dSKaricheri, Muralidharan u32 i, v; 288fc9a8e8dSKaricheri, Muralidharan 289fc9a8e8dSKaricheri, Muralidharan if (port >= DEVICE_N_GMACSL_PORTS) 290fc9a8e8dSKaricheri, Muralidharan return GMACSL_RET_INVALID_PORT; 291fc9a8e8dSKaricheri, Muralidharan 292fc9a8e8dSKaricheri, Muralidharan /* Set the soft reset bit */ 293e6c9428aSKhoronzhuk, Ivan writel(CPGMAC_REG_RESET_VAL_RESET, 294e6c9428aSKhoronzhuk, Ivan DEVICE_EMACSL_BASE(port) + CPGMACSL_REG_RESET); 295fc9a8e8dSKaricheri, Muralidharan 296fc9a8e8dSKaricheri, Muralidharan /* Wait for the bit to clear */ 297fc9a8e8dSKaricheri, Muralidharan for (i = 0; i < DEVICE_EMACSL_RESET_POLL_COUNT; i++) { 298e6c9428aSKhoronzhuk, Ivan v = readl(DEVICE_EMACSL_BASE(port) + CPGMACSL_REG_RESET); 299fc9a8e8dSKaricheri, Muralidharan if ((v & CPGMAC_REG_RESET_VAL_RESET_MASK) != 300fc9a8e8dSKaricheri, Muralidharan CPGMAC_REG_RESET_VAL_RESET) 301fc9a8e8dSKaricheri, Muralidharan return GMACSL_RET_OK; 302fc9a8e8dSKaricheri, Muralidharan } 303fc9a8e8dSKaricheri, Muralidharan 304fc9a8e8dSKaricheri, Muralidharan /* Timeout on the reset */ 305fc9a8e8dSKaricheri, Muralidharan return GMACSL_RET_WARN_RESET_INCOMPLETE; 306fc9a8e8dSKaricheri, Muralidharan } 307fc9a8e8dSKaricheri, Muralidharan 308fc9a8e8dSKaricheri, Muralidharan int mac_sl_config(u_int16_t port, struct mac_sl_cfg *cfg) 309fc9a8e8dSKaricheri, Muralidharan { 310fc9a8e8dSKaricheri, Muralidharan u32 v, i; 311fc9a8e8dSKaricheri, Muralidharan int ret = GMACSL_RET_OK; 312fc9a8e8dSKaricheri, Muralidharan 313fc9a8e8dSKaricheri, Muralidharan if (port >= DEVICE_N_GMACSL_PORTS) 314fc9a8e8dSKaricheri, Muralidharan return GMACSL_RET_INVALID_PORT; 315fc9a8e8dSKaricheri, Muralidharan 316fc9a8e8dSKaricheri, Muralidharan if (cfg->max_rx_len > CPGMAC_REG_MAXLEN_LEN) { 317fc9a8e8dSKaricheri, Muralidharan cfg->max_rx_len = CPGMAC_REG_MAXLEN_LEN; 318fc9a8e8dSKaricheri, Muralidharan ret = GMACSL_RET_WARN_MAXLEN_TOO_BIG; 319fc9a8e8dSKaricheri, Muralidharan } 320fc9a8e8dSKaricheri, Muralidharan 321fc9a8e8dSKaricheri, Muralidharan /* Must wait if the device is undergoing reset */ 322fc9a8e8dSKaricheri, Muralidharan for (i = 0; i < DEVICE_EMACSL_RESET_POLL_COUNT; i++) { 323e6c9428aSKhoronzhuk, Ivan v = readl(DEVICE_EMACSL_BASE(port) + CPGMACSL_REG_RESET); 324fc9a8e8dSKaricheri, Muralidharan if ((v & CPGMAC_REG_RESET_VAL_RESET_MASK) != 325fc9a8e8dSKaricheri, Muralidharan CPGMAC_REG_RESET_VAL_RESET) 326fc9a8e8dSKaricheri, Muralidharan break; 327fc9a8e8dSKaricheri, Muralidharan } 328fc9a8e8dSKaricheri, Muralidharan 329fc9a8e8dSKaricheri, Muralidharan if (i == DEVICE_EMACSL_RESET_POLL_COUNT) 330fc9a8e8dSKaricheri, Muralidharan return GMACSL_RET_CONFIG_FAIL_RESET_ACTIVE; 331fc9a8e8dSKaricheri, Muralidharan 332e6c9428aSKhoronzhuk, Ivan writel(cfg->max_rx_len, DEVICE_EMACSL_BASE(port) + CPGMACSL_REG_MAXLEN); 333e6c9428aSKhoronzhuk, Ivan writel(cfg->ctl, DEVICE_EMACSL_BASE(port) + CPGMACSL_REG_CTL); 334fc9a8e8dSKaricheri, Muralidharan 335fc9a8e8dSKaricheri, Muralidharan return ret; 336fc9a8e8dSKaricheri, Muralidharan } 337fc9a8e8dSKaricheri, Muralidharan 338fc9a8e8dSKaricheri, Muralidharan int ethss_config(u32 ctl, u32 max_pkt_size) 339fc9a8e8dSKaricheri, Muralidharan { 340fc9a8e8dSKaricheri, Muralidharan u32 i; 341fc9a8e8dSKaricheri, Muralidharan 342fc9a8e8dSKaricheri, Muralidharan /* Max length register */ 343e6c9428aSKhoronzhuk, Ivan writel(max_pkt_size, DEVICE_CPSW_BASE + CPSW_REG_MAXLEN); 344fc9a8e8dSKaricheri, Muralidharan 345fc9a8e8dSKaricheri, Muralidharan /* Control register */ 346e6c9428aSKhoronzhuk, Ivan writel(ctl, DEVICE_CPSW_BASE + CPSW_REG_CTL); 347fc9a8e8dSKaricheri, Muralidharan 348fc9a8e8dSKaricheri, Muralidharan /* All statistics enabled by default */ 349e6c9428aSKhoronzhuk, Ivan writel(CPSW_REG_VAL_STAT_ENABLE_ALL, 350e6c9428aSKhoronzhuk, Ivan DEVICE_CPSW_BASE + CPSW_REG_STAT_PORT_EN); 351fc9a8e8dSKaricheri, Muralidharan 352fc9a8e8dSKaricheri, Muralidharan /* Reset and enable the ALE */ 353e6c9428aSKhoronzhuk, Ivan writel(CPSW_REG_VAL_ALE_CTL_RESET_AND_ENABLE | 354e6c9428aSKhoronzhuk, Ivan CPSW_REG_VAL_ALE_CTL_BYPASS, 355e6c9428aSKhoronzhuk, Ivan DEVICE_CPSW_BASE + CPSW_REG_ALE_CONTROL); 356fc9a8e8dSKaricheri, Muralidharan 357fc9a8e8dSKaricheri, Muralidharan /* All ports put into forward mode */ 358fc9a8e8dSKaricheri, Muralidharan for (i = 0; i < DEVICE_CPSW_NUM_PORTS; i++) 359e6c9428aSKhoronzhuk, Ivan writel(CPSW_REG_VAL_PORTCTL_FORWARD_MODE, 360e6c9428aSKhoronzhuk, Ivan DEVICE_CPSW_BASE + CPSW_REG_ALE_PORTCTL(i)); 361fc9a8e8dSKaricheri, Muralidharan 362fc9a8e8dSKaricheri, Muralidharan return 0; 363fc9a8e8dSKaricheri, Muralidharan } 364fc9a8e8dSKaricheri, Muralidharan 365fc9a8e8dSKaricheri, Muralidharan int ethss_start(void) 366fc9a8e8dSKaricheri, Muralidharan { 367fc9a8e8dSKaricheri, Muralidharan int i; 368fc9a8e8dSKaricheri, Muralidharan struct mac_sl_cfg cfg; 369fc9a8e8dSKaricheri, Muralidharan 370fc9a8e8dSKaricheri, Muralidharan cfg.max_rx_len = MAX_SIZE_STREAM_BUFFER; 371fc9a8e8dSKaricheri, Muralidharan cfg.ctl = GMACSL_ENABLE | GMACSL_RX_ENABLE_EXT_CTL; 372fc9a8e8dSKaricheri, Muralidharan 373fc9a8e8dSKaricheri, Muralidharan for (i = 0; i < DEVICE_N_GMACSL_PORTS; i++) { 374fc9a8e8dSKaricheri, Muralidharan mac_sl_reset(i); 375fc9a8e8dSKaricheri, Muralidharan mac_sl_config(i, &cfg); 376fc9a8e8dSKaricheri, Muralidharan } 377fc9a8e8dSKaricheri, Muralidharan 378fc9a8e8dSKaricheri, Muralidharan return 0; 379fc9a8e8dSKaricheri, Muralidharan } 380fc9a8e8dSKaricheri, Muralidharan 381fc9a8e8dSKaricheri, Muralidharan int ethss_stop(void) 382fc9a8e8dSKaricheri, Muralidharan { 383fc9a8e8dSKaricheri, Muralidharan int i; 384fc9a8e8dSKaricheri, Muralidharan 385fc9a8e8dSKaricheri, Muralidharan for (i = 0; i < DEVICE_N_GMACSL_PORTS; i++) 386fc9a8e8dSKaricheri, Muralidharan mac_sl_reset(i); 387fc9a8e8dSKaricheri, Muralidharan 388fc9a8e8dSKaricheri, Muralidharan return 0; 389fc9a8e8dSKaricheri, Muralidharan } 390fc9a8e8dSKaricheri, Muralidharan 391fc9a8e8dSKaricheri, Muralidharan int32_t cpmac_drv_send(u32 *buffer, int num_bytes, int slave_port_num) 392fc9a8e8dSKaricheri, Muralidharan { 393fc9a8e8dSKaricheri, Muralidharan if (num_bytes < EMAC_MIN_ETHERNET_PKT_SIZE) 394fc9a8e8dSKaricheri, Muralidharan num_bytes = EMAC_MIN_ETHERNET_PKT_SIZE; 395fc9a8e8dSKaricheri, Muralidharan 396fc9a8e8dSKaricheri, Muralidharan return netcp_send(buffer, num_bytes, (slave_port_num) << 16); 397fc9a8e8dSKaricheri, Muralidharan } 398fc9a8e8dSKaricheri, Muralidharan 399fc9a8e8dSKaricheri, Muralidharan /* Eth device open */ 400fc9a8e8dSKaricheri, Muralidharan static int keystone2_eth_open(struct eth_device *dev, bd_t *bis) 401fc9a8e8dSKaricheri, Muralidharan { 402fc9a8e8dSKaricheri, Muralidharan u_int32_t clkdiv; 403fc9a8e8dSKaricheri, Muralidharan int link; 404fc9a8e8dSKaricheri, Muralidharan struct eth_priv_t *eth_priv = (struct eth_priv_t *)dev->priv; 405fc9a8e8dSKaricheri, Muralidharan 406fc9a8e8dSKaricheri, Muralidharan debug("+ emac_open\n"); 407fc9a8e8dSKaricheri, Muralidharan 408fc9a8e8dSKaricheri, Muralidharan net_rx_buffs.rx_flow = eth_priv->rx_flow; 409fc9a8e8dSKaricheri, Muralidharan 410fc9a8e8dSKaricheri, Muralidharan sys_has_mdio = 411fc9a8e8dSKaricheri, Muralidharan (eth_priv->sgmii_link_type == SGMII_LINK_MAC_PHY) ? 1 : 0; 412fc9a8e8dSKaricheri, Muralidharan 413fc9a8e8dSKaricheri, Muralidharan psc_enable_module(KS2_LPSC_PA); 414fc9a8e8dSKaricheri, Muralidharan psc_enable_module(KS2_LPSC_CPGMAC); 415fc9a8e8dSKaricheri, Muralidharan 416fc9a8e8dSKaricheri, Muralidharan sgmii_serdes_setup_156p25mhz(); 417fc9a8e8dSKaricheri, Muralidharan 418fc9a8e8dSKaricheri, Muralidharan if (sys_has_mdio) 419fc9a8e8dSKaricheri, Muralidharan keystone2_eth_mdio_enable(); 420fc9a8e8dSKaricheri, Muralidharan 421fc9a8e8dSKaricheri, Muralidharan keystone_sgmii_config(eth_priv->slave_port - 1, 422fc9a8e8dSKaricheri, Muralidharan eth_priv->sgmii_link_type); 423fc9a8e8dSKaricheri, Muralidharan 424fc9a8e8dSKaricheri, Muralidharan udelay(10000); 425fc9a8e8dSKaricheri, Muralidharan 426fc9a8e8dSKaricheri, Muralidharan /* On chip switch configuration */ 427fc9a8e8dSKaricheri, Muralidharan ethss_config(target_get_switch_ctl(), SWITCH_MAX_PKT_SIZE); 428fc9a8e8dSKaricheri, Muralidharan 429fc9a8e8dSKaricheri, Muralidharan /* TODO: add error handling code */ 430fc9a8e8dSKaricheri, Muralidharan if (qm_init()) { 431fc9a8e8dSKaricheri, Muralidharan printf("ERROR: qm_init()\n"); 432fc9a8e8dSKaricheri, Muralidharan return -1; 433fc9a8e8dSKaricheri, Muralidharan } 434fc9a8e8dSKaricheri, Muralidharan if (netcp_init(&net_rx_buffs)) { 435fc9a8e8dSKaricheri, Muralidharan qm_close(); 436fc9a8e8dSKaricheri, Muralidharan printf("ERROR: netcp_init()\n"); 437fc9a8e8dSKaricheri, Muralidharan return -1; 438fc9a8e8dSKaricheri, Muralidharan } 439fc9a8e8dSKaricheri, Muralidharan 440fc9a8e8dSKaricheri, Muralidharan /* 441fc9a8e8dSKaricheri, Muralidharan * Streaming switch configuration. If not present this 442fc9a8e8dSKaricheri, Muralidharan * statement is defined to void in target.h. 443fc9a8e8dSKaricheri, Muralidharan * If present this is usually defined to a series of register writes 444fc9a8e8dSKaricheri, Muralidharan */ 445fc9a8e8dSKaricheri, Muralidharan hw_config_streaming_switch(); 446fc9a8e8dSKaricheri, Muralidharan 447fc9a8e8dSKaricheri, Muralidharan if (sys_has_mdio) { 448fc9a8e8dSKaricheri, Muralidharan /* Init MDIO & get link state */ 449fc9a8e8dSKaricheri, Muralidharan clkdiv = (EMAC_MDIO_BUS_FREQ / EMAC_MDIO_CLOCK_FREQ) - 1; 450fc9a8e8dSKaricheri, Muralidharan writel((clkdiv & 0xff) | MDIO_CONTROL_ENABLE | 451fc9a8e8dSKaricheri, Muralidharan MDIO_CONTROL_FAULT, &adap_mdio->control) 452fc9a8e8dSKaricheri, Muralidharan ; 453fc9a8e8dSKaricheri, Muralidharan 454fc9a8e8dSKaricheri, Muralidharan /* We need to wait for MDIO to start */ 455fc9a8e8dSKaricheri, Muralidharan udelay(1000); 456fc9a8e8dSKaricheri, Muralidharan 457fc9a8e8dSKaricheri, Muralidharan link = keystone_get_link_status(dev); 458fc9a8e8dSKaricheri, Muralidharan if (link == 0) { 459fc9a8e8dSKaricheri, Muralidharan netcp_close(); 460fc9a8e8dSKaricheri, Muralidharan qm_close(); 461fc9a8e8dSKaricheri, Muralidharan return -1; 462fc9a8e8dSKaricheri, Muralidharan } 463fc9a8e8dSKaricheri, Muralidharan } 464fc9a8e8dSKaricheri, Muralidharan 465fc9a8e8dSKaricheri, Muralidharan emac_gigabit_enable(dev); 466fc9a8e8dSKaricheri, Muralidharan 467fc9a8e8dSKaricheri, Muralidharan ethss_start(); 468fc9a8e8dSKaricheri, Muralidharan 469fc9a8e8dSKaricheri, Muralidharan debug("- emac_open\n"); 470fc9a8e8dSKaricheri, Muralidharan 471fc9a8e8dSKaricheri, Muralidharan emac_open = 1; 472fc9a8e8dSKaricheri, Muralidharan 473fc9a8e8dSKaricheri, Muralidharan return 0; 474fc9a8e8dSKaricheri, Muralidharan } 475fc9a8e8dSKaricheri, Muralidharan 476fc9a8e8dSKaricheri, Muralidharan /* Eth device close */ 477fc9a8e8dSKaricheri, Muralidharan void keystone2_eth_close(struct eth_device *dev) 478fc9a8e8dSKaricheri, Muralidharan { 479fc9a8e8dSKaricheri, Muralidharan debug("+ emac_close\n"); 480fc9a8e8dSKaricheri, Muralidharan 481fc9a8e8dSKaricheri, Muralidharan if (!emac_open) 482fc9a8e8dSKaricheri, Muralidharan return; 483fc9a8e8dSKaricheri, Muralidharan 484fc9a8e8dSKaricheri, Muralidharan ethss_stop(); 485fc9a8e8dSKaricheri, Muralidharan 486fc9a8e8dSKaricheri, Muralidharan netcp_close(); 487fc9a8e8dSKaricheri, Muralidharan qm_close(); 488fc9a8e8dSKaricheri, Muralidharan 489fc9a8e8dSKaricheri, Muralidharan emac_open = 0; 490fc9a8e8dSKaricheri, Muralidharan 491fc9a8e8dSKaricheri, Muralidharan debug("- emac_close\n"); 492fc9a8e8dSKaricheri, Muralidharan } 493fc9a8e8dSKaricheri, Muralidharan 494fc9a8e8dSKaricheri, Muralidharan static int tx_send_loop; 495fc9a8e8dSKaricheri, Muralidharan 496fc9a8e8dSKaricheri, Muralidharan /* 497fc9a8e8dSKaricheri, Muralidharan * This function sends a single packet on the network and returns 498fc9a8e8dSKaricheri, Muralidharan * positive number (number of bytes transmitted) or negative for error 499fc9a8e8dSKaricheri, Muralidharan */ 500fc9a8e8dSKaricheri, Muralidharan static int keystone2_eth_send_packet(struct eth_device *dev, 501fc9a8e8dSKaricheri, Muralidharan void *packet, int length) 502fc9a8e8dSKaricheri, Muralidharan { 503fc9a8e8dSKaricheri, Muralidharan int ret_status = -1; 504fc9a8e8dSKaricheri, Muralidharan struct eth_priv_t *eth_priv = (struct eth_priv_t *)dev->priv; 505fc9a8e8dSKaricheri, Muralidharan 506fc9a8e8dSKaricheri, Muralidharan tx_send_loop = 0; 507fc9a8e8dSKaricheri, Muralidharan 508fc9a8e8dSKaricheri, Muralidharan if (keystone_get_link_status(dev) == 0) 509fc9a8e8dSKaricheri, Muralidharan return -1; 510fc9a8e8dSKaricheri, Muralidharan 511fc9a8e8dSKaricheri, Muralidharan emac_gigabit_enable(dev); 512fc9a8e8dSKaricheri, Muralidharan 513fc9a8e8dSKaricheri, Muralidharan if (cpmac_drv_send((u32 *)packet, length, eth_priv->slave_port) != 0) 514fc9a8e8dSKaricheri, Muralidharan return ret_status; 515fc9a8e8dSKaricheri, Muralidharan 516fc9a8e8dSKaricheri, Muralidharan if (keystone_get_link_status(dev) == 0) 517fc9a8e8dSKaricheri, Muralidharan return -1; 518fc9a8e8dSKaricheri, Muralidharan 519fc9a8e8dSKaricheri, Muralidharan emac_gigabit_enable(dev); 520fc9a8e8dSKaricheri, Muralidharan 521fc9a8e8dSKaricheri, Muralidharan return length; 522fc9a8e8dSKaricheri, Muralidharan } 523fc9a8e8dSKaricheri, Muralidharan 524fc9a8e8dSKaricheri, Muralidharan /* 525fc9a8e8dSKaricheri, Muralidharan * This function handles receipt of a packet from the network 526fc9a8e8dSKaricheri, Muralidharan */ 527fc9a8e8dSKaricheri, Muralidharan static int keystone2_eth_rcv_packet(struct eth_device *dev) 528fc9a8e8dSKaricheri, Muralidharan { 529fc9a8e8dSKaricheri, Muralidharan void *hd; 530fc9a8e8dSKaricheri, Muralidharan int pkt_size; 531fc9a8e8dSKaricheri, Muralidharan u32 *pkt; 532fc9a8e8dSKaricheri, Muralidharan 533fc9a8e8dSKaricheri, Muralidharan hd = netcp_recv(&pkt, &pkt_size); 534fc9a8e8dSKaricheri, Muralidharan if (hd == NULL) 535fc9a8e8dSKaricheri, Muralidharan return 0; 536fc9a8e8dSKaricheri, Muralidharan 537fc9a8e8dSKaricheri, Muralidharan NetReceive((uchar *)pkt, pkt_size); 538fc9a8e8dSKaricheri, Muralidharan 539fc9a8e8dSKaricheri, Muralidharan netcp_release_rxhd(hd); 540fc9a8e8dSKaricheri, Muralidharan 541fc9a8e8dSKaricheri, Muralidharan return pkt_size; 542fc9a8e8dSKaricheri, Muralidharan } 543fc9a8e8dSKaricheri, Muralidharan 544fc9a8e8dSKaricheri, Muralidharan /* 545fc9a8e8dSKaricheri, Muralidharan * This function initializes the EMAC hardware. 546fc9a8e8dSKaricheri, Muralidharan */ 547fc9a8e8dSKaricheri, Muralidharan int keystone2_emac_initialize(struct eth_priv_t *eth_priv) 548fc9a8e8dSKaricheri, Muralidharan { 549fc9a8e8dSKaricheri, Muralidharan struct eth_device *dev; 550fc9a8e8dSKaricheri, Muralidharan 551fc9a8e8dSKaricheri, Muralidharan dev = malloc(sizeof(struct eth_device)); 552fc9a8e8dSKaricheri, Muralidharan if (dev == NULL) 553fc9a8e8dSKaricheri, Muralidharan return -1; 554fc9a8e8dSKaricheri, Muralidharan 555fc9a8e8dSKaricheri, Muralidharan memset(dev, 0, sizeof(struct eth_device)); 556fc9a8e8dSKaricheri, Muralidharan 557fc9a8e8dSKaricheri, Muralidharan strcpy(dev->name, eth_priv->int_name); 558fc9a8e8dSKaricheri, Muralidharan dev->priv = eth_priv; 559fc9a8e8dSKaricheri, Muralidharan 560fc9a8e8dSKaricheri, Muralidharan keystone2_eth_read_mac_addr(dev); 561fc9a8e8dSKaricheri, Muralidharan 562fc9a8e8dSKaricheri, Muralidharan dev->iobase = 0; 563fc9a8e8dSKaricheri, Muralidharan dev->init = keystone2_eth_open; 564fc9a8e8dSKaricheri, Muralidharan dev->halt = keystone2_eth_close; 565fc9a8e8dSKaricheri, Muralidharan dev->send = keystone2_eth_send_packet; 566fc9a8e8dSKaricheri, Muralidharan dev->recv = keystone2_eth_rcv_packet; 567fc9a8e8dSKaricheri, Muralidharan 568fc9a8e8dSKaricheri, Muralidharan eth_register(dev); 569fc9a8e8dSKaricheri, Muralidharan 570fc9a8e8dSKaricheri, Muralidharan return 0; 571fc9a8e8dSKaricheri, Muralidharan } 572fc9a8e8dSKaricheri, Muralidharan 573fc9a8e8dSKaricheri, Muralidharan void sgmii_serdes_setup_156p25mhz(void) 574fc9a8e8dSKaricheri, Muralidharan { 575fc9a8e8dSKaricheri, Muralidharan unsigned int cnt; 576fc9a8e8dSKaricheri, Muralidharan 577fc9a8e8dSKaricheri, Muralidharan /* 578fc9a8e8dSKaricheri, Muralidharan * configure Serializer/Deserializer (SerDes) hardware. SerDes IP 579fc9a8e8dSKaricheri, Muralidharan * hardware vendor published only register addresses and their values 580fc9a8e8dSKaricheri, Muralidharan * to be used for configuring SerDes. So had to use hardcoded values 581fc9a8e8dSKaricheri, Muralidharan * below. 582fc9a8e8dSKaricheri, Muralidharan */ 583fc9a8e8dSKaricheri, Muralidharan clrsetbits_le32(0x0232a000, 0xffff0000, 0x00800000); 584fc9a8e8dSKaricheri, Muralidharan clrsetbits_le32(0x0232a014, 0x0000ffff, 0x00008282); 585fc9a8e8dSKaricheri, Muralidharan clrsetbits_le32(0x0232a060, 0x00ffffff, 0x00142438); 586fc9a8e8dSKaricheri, Muralidharan clrsetbits_le32(0x0232a064, 0x00ffff00, 0x00c3c700); 587fc9a8e8dSKaricheri, Muralidharan clrsetbits_le32(0x0232a078, 0x0000ff00, 0x0000c000); 588fc9a8e8dSKaricheri, Muralidharan 589fc9a8e8dSKaricheri, Muralidharan clrsetbits_le32(0x0232a204, 0xff0000ff, 0x38000080); 590fc9a8e8dSKaricheri, Muralidharan clrsetbits_le32(0x0232a208, 0x000000ff, 0x00000000); 591fc9a8e8dSKaricheri, Muralidharan clrsetbits_le32(0x0232a20c, 0xff000000, 0x02000000); 592fc9a8e8dSKaricheri, Muralidharan clrsetbits_le32(0x0232a210, 0xff000000, 0x1b000000); 593fc9a8e8dSKaricheri, Muralidharan clrsetbits_le32(0x0232a214, 0x0000ffff, 0x00006fb8); 594fc9a8e8dSKaricheri, Muralidharan clrsetbits_le32(0x0232a218, 0xffff00ff, 0x758000e4); 595fc9a8e8dSKaricheri, Muralidharan clrsetbits_le32(0x0232a2ac, 0x0000ff00, 0x00004400); 596fc9a8e8dSKaricheri, Muralidharan clrsetbits_le32(0x0232a22c, 0x00ffff00, 0x00200800); 597fc9a8e8dSKaricheri, Muralidharan clrsetbits_le32(0x0232a280, 0x00ff00ff, 0x00820082); 598fc9a8e8dSKaricheri, Muralidharan clrsetbits_le32(0x0232a284, 0xffffffff, 0x1d0f0385); 599fc9a8e8dSKaricheri, Muralidharan 600fc9a8e8dSKaricheri, Muralidharan clrsetbits_le32(0x0232a404, 0xff0000ff, 0x38000080); 601fc9a8e8dSKaricheri, Muralidharan clrsetbits_le32(0x0232a408, 0x000000ff, 0x00000000); 602fc9a8e8dSKaricheri, Muralidharan clrsetbits_le32(0x0232a40c, 0xff000000, 0x02000000); 603fc9a8e8dSKaricheri, Muralidharan clrsetbits_le32(0x0232a410, 0xff000000, 0x1b000000); 604fc9a8e8dSKaricheri, Muralidharan clrsetbits_le32(0x0232a414, 0x0000ffff, 0x00006fb8); 605fc9a8e8dSKaricheri, Muralidharan clrsetbits_le32(0x0232a418, 0xffff00ff, 0x758000e4); 606fc9a8e8dSKaricheri, Muralidharan clrsetbits_le32(0x0232a4ac, 0x0000ff00, 0x00004400); 607fc9a8e8dSKaricheri, Muralidharan clrsetbits_le32(0x0232a42c, 0x00ffff00, 0x00200800); 608fc9a8e8dSKaricheri, Muralidharan clrsetbits_le32(0x0232a480, 0x00ff00ff, 0x00820082); 609fc9a8e8dSKaricheri, Muralidharan clrsetbits_le32(0x0232a484, 0xffffffff, 0x1d0f0385); 610fc9a8e8dSKaricheri, Muralidharan 611fc9a8e8dSKaricheri, Muralidharan clrsetbits_le32(0x0232a604, 0xff0000ff, 0x38000080); 612fc9a8e8dSKaricheri, Muralidharan clrsetbits_le32(0x0232a608, 0x000000ff, 0x00000000); 613fc9a8e8dSKaricheri, Muralidharan clrsetbits_le32(0x0232a60c, 0xff000000, 0x02000000); 614fc9a8e8dSKaricheri, Muralidharan clrsetbits_le32(0x0232a610, 0xff000000, 0x1b000000); 615fc9a8e8dSKaricheri, Muralidharan clrsetbits_le32(0x0232a614, 0x0000ffff, 0x00006fb8); 616fc9a8e8dSKaricheri, Muralidharan clrsetbits_le32(0x0232a618, 0xffff00ff, 0x758000e4); 617fc9a8e8dSKaricheri, Muralidharan clrsetbits_le32(0x0232a6ac, 0x0000ff00, 0x00004400); 618fc9a8e8dSKaricheri, Muralidharan clrsetbits_le32(0x0232a62c, 0x00ffff00, 0x00200800); 619fc9a8e8dSKaricheri, Muralidharan clrsetbits_le32(0x0232a680, 0x00ff00ff, 0x00820082); 620fc9a8e8dSKaricheri, Muralidharan clrsetbits_le32(0x0232a684, 0xffffffff, 0x1d0f0385); 621fc9a8e8dSKaricheri, Muralidharan 622fc9a8e8dSKaricheri, Muralidharan clrsetbits_le32(0x0232a804, 0xff0000ff, 0x38000080); 623fc9a8e8dSKaricheri, Muralidharan clrsetbits_le32(0x0232a808, 0x000000ff, 0x00000000); 624fc9a8e8dSKaricheri, Muralidharan clrsetbits_le32(0x0232a80c, 0xff000000, 0x02000000); 625fc9a8e8dSKaricheri, Muralidharan clrsetbits_le32(0x0232a810, 0xff000000, 0x1b000000); 626fc9a8e8dSKaricheri, Muralidharan clrsetbits_le32(0x0232a814, 0x0000ffff, 0x00006fb8); 627fc9a8e8dSKaricheri, Muralidharan clrsetbits_le32(0x0232a818, 0xffff00ff, 0x758000e4); 628fc9a8e8dSKaricheri, Muralidharan clrsetbits_le32(0x0232a8ac, 0x0000ff00, 0x00004400); 629fc9a8e8dSKaricheri, Muralidharan clrsetbits_le32(0x0232a82c, 0x00ffff00, 0x00200800); 630fc9a8e8dSKaricheri, Muralidharan clrsetbits_le32(0x0232a880, 0x00ff00ff, 0x00820082); 631fc9a8e8dSKaricheri, Muralidharan clrsetbits_le32(0x0232a884, 0xffffffff, 0x1d0f0385); 632fc9a8e8dSKaricheri, Muralidharan 633fc9a8e8dSKaricheri, Muralidharan clrsetbits_le32(0x0232aa00, 0x0000ff00, 0x00000800); 634fc9a8e8dSKaricheri, Muralidharan clrsetbits_le32(0x0232aa08, 0xffff0000, 0x38a20000); 635fc9a8e8dSKaricheri, Muralidharan clrsetbits_le32(0x0232aa30, 0x00ffff00, 0x008a8a00); 636fc9a8e8dSKaricheri, Muralidharan clrsetbits_le32(0x0232aa84, 0x0000ff00, 0x00000600); 637fc9a8e8dSKaricheri, Muralidharan clrsetbits_le32(0x0232aa94, 0xff000000, 0x10000000); 638fc9a8e8dSKaricheri, Muralidharan clrsetbits_le32(0x0232aaa0, 0xff000000, 0x81000000); 639fc9a8e8dSKaricheri, Muralidharan clrsetbits_le32(0x0232aabc, 0xff000000, 0xff000000); 640fc9a8e8dSKaricheri, Muralidharan clrsetbits_le32(0x0232aac0, 0x000000ff, 0x0000008b); 641fc9a8e8dSKaricheri, Muralidharan clrsetbits_le32(0x0232ab08, 0xffff0000, 0x583f0000); 642fc9a8e8dSKaricheri, Muralidharan clrsetbits_le32(0x0232ab0c, 0x000000ff, 0x0000004e); 643fc9a8e8dSKaricheri, Muralidharan clrsetbits_le32(0x0232a000, 0x000000ff, 0x00000003); 644fc9a8e8dSKaricheri, Muralidharan clrsetbits_le32(0x0232aa00, 0x000000ff, 0x0000005f); 645fc9a8e8dSKaricheri, Muralidharan 646fc9a8e8dSKaricheri, Muralidharan clrsetbits_le32(0x0232aa48, 0x00ffff00, 0x00fd8c00); 647fc9a8e8dSKaricheri, Muralidharan clrsetbits_le32(0x0232aa54, 0x00ffffff, 0x002fec72); 648fc9a8e8dSKaricheri, Muralidharan clrsetbits_le32(0x0232aa58, 0xffffff00, 0x00f92100); 649fc9a8e8dSKaricheri, Muralidharan clrsetbits_le32(0x0232aa5c, 0xffffffff, 0x00040060); 650fc9a8e8dSKaricheri, Muralidharan clrsetbits_le32(0x0232aa60, 0xffffffff, 0x00008000); 651fc9a8e8dSKaricheri, Muralidharan clrsetbits_le32(0x0232aa64, 0xffffffff, 0x0c581220); 652fc9a8e8dSKaricheri, Muralidharan clrsetbits_le32(0x0232aa68, 0xffffffff, 0xe13b0602); 653fc9a8e8dSKaricheri, Muralidharan clrsetbits_le32(0x0232aa6c, 0xffffffff, 0xb8074cc1); 654fc9a8e8dSKaricheri, Muralidharan clrsetbits_le32(0x0232aa70, 0xffffffff, 0x3f02e989); 655fc9a8e8dSKaricheri, Muralidharan clrsetbits_le32(0x0232aa74, 0x000000ff, 0x00000001); 656fc9a8e8dSKaricheri, Muralidharan clrsetbits_le32(0x0232ab20, 0x00ff0000, 0x00370000); 657fc9a8e8dSKaricheri, Muralidharan clrsetbits_le32(0x0232ab1c, 0xff000000, 0x37000000); 658fc9a8e8dSKaricheri, Muralidharan clrsetbits_le32(0x0232ab20, 0x000000ff, 0x0000005d); 659fc9a8e8dSKaricheri, Muralidharan 660fc9a8e8dSKaricheri, Muralidharan /*Bring SerDes out of Reset if SerDes is Shutdown & is in Reset Mode*/ 661fc9a8e8dSKaricheri, Muralidharan clrbits_le32(0x0232a010, 1 << 28); 662fc9a8e8dSKaricheri, Muralidharan 663fc9a8e8dSKaricheri, Muralidharan /* Enable TX and RX via the LANExCTL_STS 0x0000 + x*4 */ 664fc9a8e8dSKaricheri, Muralidharan clrbits_le32(0x0232a228, 1 << 29); 665fc9a8e8dSKaricheri, Muralidharan writel(0xF800F8C0, 0x0232bfe0); 666fc9a8e8dSKaricheri, Muralidharan clrbits_le32(0x0232a428, 1 << 29); 667fc9a8e8dSKaricheri, Muralidharan writel(0xF800F8C0, 0x0232bfe4); 668fc9a8e8dSKaricheri, Muralidharan clrbits_le32(0x0232a628, 1 << 29); 669fc9a8e8dSKaricheri, Muralidharan writel(0xF800F8C0, 0x0232bfe8); 670fc9a8e8dSKaricheri, Muralidharan clrbits_le32(0x0232a828, 1 << 29); 671fc9a8e8dSKaricheri, Muralidharan writel(0xF800F8C0, 0x0232bfec); 672fc9a8e8dSKaricheri, Muralidharan 673fc9a8e8dSKaricheri, Muralidharan /*Enable pll via the pll_ctrl 0x0014*/ 674fc9a8e8dSKaricheri, Muralidharan writel(0xe0000000, 0x0232bff4) 675fc9a8e8dSKaricheri, Muralidharan ; 676fc9a8e8dSKaricheri, Muralidharan 677fc9a8e8dSKaricheri, Muralidharan /*Waiting for SGMII Serdes PLL lock.*/ 678fc9a8e8dSKaricheri, Muralidharan for (cnt = 10000; cnt > 0 && ((readl(0x02090114) & 0x10) == 0); cnt--) 679fc9a8e8dSKaricheri, Muralidharan ; 680fc9a8e8dSKaricheri, Muralidharan 681fc9a8e8dSKaricheri, Muralidharan for (cnt = 10000; cnt > 0 && ((readl(0x02090214) & 0x10) == 0); cnt--) 682fc9a8e8dSKaricheri, Muralidharan ; 683fc9a8e8dSKaricheri, Muralidharan 684fc9a8e8dSKaricheri, Muralidharan for (cnt = 10000; cnt > 0 && ((readl(0x02090414) & 0x10) == 0); cnt--) 685fc9a8e8dSKaricheri, Muralidharan ; 686fc9a8e8dSKaricheri, Muralidharan 687fc9a8e8dSKaricheri, Muralidharan for (cnt = 10000; cnt > 0 && ((readl(0x02090514) & 0x10) == 0); cnt--) 688fc9a8e8dSKaricheri, Muralidharan ; 689fc9a8e8dSKaricheri, Muralidharan 690fc9a8e8dSKaricheri, Muralidharan udelay(45000); 691fc9a8e8dSKaricheri, Muralidharan } 692fc9a8e8dSKaricheri, Muralidharan 693fc9a8e8dSKaricheri, Muralidharan void sgmii_serdes_shutdown(void) 694fc9a8e8dSKaricheri, Muralidharan { 695fc9a8e8dSKaricheri, Muralidharan /* 696fc9a8e8dSKaricheri, Muralidharan * shutdown SerDes hardware. SerDes hardware vendor published only 697fc9a8e8dSKaricheri, Muralidharan * register addresses and their values. So had to use hardcoded 698fc9a8e8dSKaricheri, Muralidharan * values below. 699fc9a8e8dSKaricheri, Muralidharan */ 700fc9a8e8dSKaricheri, Muralidharan clrbits_le32(0x0232bfe0, 3 << 29 | 3 << 13); 701fc9a8e8dSKaricheri, Muralidharan setbits_le32(0x02320228, 1 << 29); 702fc9a8e8dSKaricheri, Muralidharan clrbits_le32(0x0232bfe4, 3 << 29 | 3 << 13); 703fc9a8e8dSKaricheri, Muralidharan setbits_le32(0x02320428, 1 << 29); 704fc9a8e8dSKaricheri, Muralidharan clrbits_le32(0x0232bfe8, 3 << 29 | 3 << 13); 705fc9a8e8dSKaricheri, Muralidharan setbits_le32(0x02320628, 1 << 29); 706fc9a8e8dSKaricheri, Muralidharan clrbits_le32(0x0232bfec, 3 << 29 | 3 << 13); 707fc9a8e8dSKaricheri, Muralidharan setbits_le32(0x02320828, 1 << 29); 708fc9a8e8dSKaricheri, Muralidharan 709fc9a8e8dSKaricheri, Muralidharan clrbits_le32(0x02320034, 3 << 29); 710fc9a8e8dSKaricheri, Muralidharan setbits_le32(0x02320010, 1 << 28); 711fc9a8e8dSKaricheri, Muralidharan } 712