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