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> 1124b852a7SSimon Glass #include <console.h> 12fc9a8e8dSKaricheri, Muralidharan 136599f369SMugunthan V N #include <dm.h> 14a61f6a55SMugunthan V N #include <dm/lists.h> 156599f369SMugunthan V N 16fc9a8e8dSKaricheri, Muralidharan #include <net.h> 173fe93623SKhoronzhuk, Ivan #include <phy.h> 18c05d05e7SKhoronzhuk, Ivan #include <errno.h> 19fc9a8e8dSKaricheri, Muralidharan #include <miiphy.h> 20fc9a8e8dSKaricheri, Muralidharan #include <malloc.h> 21ef454717SKhoronzhuk, Ivan #include <asm/ti-common/keystone_nav.h> 220935cac6SKhoronzhuk, Ivan #include <asm/ti-common/keystone_net.h> 23a43febdeSKhoronzhuk, Ivan #include <asm/ti-common/keystone_serdes.h> 246599f369SMugunthan V N #include <asm/arch/psc_defs.h> 25fc9a8e8dSKaricheri, Muralidharan 266599f369SMugunthan V N DECLARE_GLOBAL_DATA_PTR; 276599f369SMugunthan V N 286599f369SMugunthan V N #ifndef CONFIG_DM_ETH 29fc9a8e8dSKaricheri, Muralidharan unsigned int emac_open; 30550c5ce6SKhoronzhuk, Ivan static struct mii_dev *mdio_bus; 31fc9a8e8dSKaricheri, Muralidharan static unsigned int sys_has_mdio = 1; 326599f369SMugunthan V N #endif 33fc9a8e8dSKaricheri, Muralidharan 34fc9a8e8dSKaricheri, Muralidharan #ifdef KEYSTONE2_EMAC_GIG_ENABLE 35fc9a8e8dSKaricheri, Muralidharan #define emac_gigabit_enable(x) keystone2_eth_gigabit_enable(x) 36fc9a8e8dSKaricheri, Muralidharan #else 37fc9a8e8dSKaricheri, Muralidharan #define emac_gigabit_enable(x) /* no gigabit to enable */ 38fc9a8e8dSKaricheri, Muralidharan #endif 39fc9a8e8dSKaricheri, Muralidharan 40fc9a8e8dSKaricheri, Muralidharan #define RX_BUFF_NUMS 24 41fc9a8e8dSKaricheri, Muralidharan #define RX_BUFF_LEN 1520 42fc9a8e8dSKaricheri, Muralidharan #define MAX_SIZE_STREAM_BUFFER RX_BUFF_LEN 43c05d05e7SKhoronzhuk, Ivan #define SGMII_ANEG_TIMEOUT 4000 44fc9a8e8dSKaricheri, Muralidharan 45fc9a8e8dSKaricheri, Muralidharan static u8 rx_buffs[RX_BUFF_NUMS * RX_BUFF_LEN] __aligned(16); 46fc9a8e8dSKaricheri, Muralidharan 476599f369SMugunthan V N #ifndef CONFIG_DM_ETH 48fc9a8e8dSKaricheri, Muralidharan struct rx_buff_desc net_rx_buffs = { 49fc9a8e8dSKaricheri, Muralidharan .buff_ptr = rx_buffs, 50fc9a8e8dSKaricheri, Muralidharan .num_buffs = RX_BUFF_NUMS, 51fc9a8e8dSKaricheri, Muralidharan .buff_len = RX_BUFF_LEN, 52fc9a8e8dSKaricheri, Muralidharan .rx_flow = 22, 53fc9a8e8dSKaricheri, Muralidharan }; 544657a2d4SVitaly Andrianov #endif 55fc9a8e8dSKaricheri, Muralidharan 566599f369SMugunthan V N #ifdef CONFIG_DM_ETH 57fc9a8e8dSKaricheri, Muralidharan 586599f369SMugunthan V N enum link_type { 59*1de40662SMugunthan V N LINK_TYPE_SGMII_MAC_TO_MAC_AUTO = 0, 60*1de40662SMugunthan V N LINK_TYPE_SGMII_MAC_TO_PHY_MODE = 1, 61*1de40662SMugunthan V N LINK_TYPE_SGMII_MAC_TO_MAC_FORCED_MODE = 2, 62*1de40662SMugunthan V N LINK_TYPE_SGMII_MAC_TO_FIBRE_MODE = 3, 63*1de40662SMugunthan V N LINK_TYPE_SGMII_MAC_TO_PHY_NO_MDIO_MODE = 4, 64*1de40662SMugunthan V N LINK_TYPE_RGMII_LINK_MAC_PHY = 5, 65*1de40662SMugunthan V N LINK_TYPE_RGMII_LINK_MAC_MAC_FORCED = 6, 66*1de40662SMugunthan V N LINK_TYPE_RGMII_LINK_MAC_PHY_NO_MDIO = 7, 676599f369SMugunthan V N LINK_TYPE_10G_MAC_TO_PHY_MODE = 10, 686599f369SMugunthan V N LINK_TYPE_10G_MAC_TO_MAC_FORCED_MODE = 11, 696599f369SMugunthan V N }; 70fc9a8e8dSKaricheri, Muralidharan 716599f369SMugunthan V N #define mac_hi(mac) (((mac)[0] << 0) | ((mac)[1] << 8) | \ 726599f369SMugunthan V N ((mac)[2] << 16) | ((mac)[3] << 24)) 736599f369SMugunthan V N #define mac_lo(mac) (((mac)[4] << 0) | ((mac)[5] << 8)) 74fc9a8e8dSKaricheri, Muralidharan 756599f369SMugunthan V N #ifdef CONFIG_KSNET_NETCP_V1_0 76fc9a8e8dSKaricheri, Muralidharan 776599f369SMugunthan V N #define EMAC_EMACSW_BASE_OFS 0x90800 786599f369SMugunthan V N #define EMAC_EMACSW_PORT_BASE_OFS (EMAC_EMACSW_BASE_OFS + 0x60) 796599f369SMugunthan V N 806599f369SMugunthan V N /* CPSW Switch slave registers */ 816599f369SMugunthan V N #define CPGMACSL_REG_SA_LO 0x10 826599f369SMugunthan V N #define CPGMACSL_REG_SA_HI 0x14 836599f369SMugunthan V N 846599f369SMugunthan V N #define DEVICE_EMACSW_BASE(base, x) ((base) + EMAC_EMACSW_PORT_BASE_OFS + \ 856599f369SMugunthan V N (x) * 0x30) 866599f369SMugunthan V N 876599f369SMugunthan V N #elif defined CONFIG_KSNET_NETCP_V1_5 886599f369SMugunthan V N 896599f369SMugunthan V N #define EMAC_EMACSW_PORT_BASE_OFS 0x222000 906599f369SMugunthan V N 916599f369SMugunthan V N /* CPSW Switch slave registers */ 926599f369SMugunthan V N #define CPGMACSL_REG_SA_LO 0x308 936599f369SMugunthan V N #define CPGMACSL_REG_SA_HI 0x30c 946599f369SMugunthan V N 956599f369SMugunthan V N #define DEVICE_EMACSW_BASE(base, x) ((base) + EMAC_EMACSW_PORT_BASE_OFS + \ 966599f369SMugunthan V N (x) * 0x1000) 976599f369SMugunthan V N 986599f369SMugunthan V N #endif 996599f369SMugunthan V N 1006599f369SMugunthan V N 1016599f369SMugunthan V N struct ks2_eth_priv { 1026599f369SMugunthan V N struct udevice *dev; 1036599f369SMugunthan V N struct phy_device *phydev; 1046599f369SMugunthan V N struct mii_dev *mdio_bus; 1056599f369SMugunthan V N int phy_addr; 1066599f369SMugunthan V N phy_interface_t phy_if; 1076599f369SMugunthan V N int sgmii_link_type; 1086599f369SMugunthan V N void *mdio_base; 1096599f369SMugunthan V N struct rx_buff_desc net_rx_buffs; 1106599f369SMugunthan V N struct pktdma_cfg *netcp_pktdma; 1116599f369SMugunthan V N void *hd; 1126599f369SMugunthan V N int slave_port; 1136599f369SMugunthan V N enum link_type link_type; 1146599f369SMugunthan V N bool emac_open; 1156599f369SMugunthan V N bool has_mdio; 1166599f369SMugunthan V N }; 1176599f369SMugunthan V N #endif 118fc9a8e8dSKaricheri, Muralidharan 119550c5ce6SKhoronzhuk, Ivan /* MDIO */ 120550c5ce6SKhoronzhuk, Ivan 121550c5ce6SKhoronzhuk, Ivan static int keystone2_mdio_reset(struct mii_dev *bus) 122fc9a8e8dSKaricheri, Muralidharan { 123fc9a8e8dSKaricheri, Muralidharan u_int32_t clkdiv; 124550c5ce6SKhoronzhuk, Ivan struct mdio_regs *adap_mdio = bus->priv; 125fc9a8e8dSKaricheri, Muralidharan 126fc9a8e8dSKaricheri, Muralidharan clkdiv = (EMAC_MDIO_BUS_FREQ / EMAC_MDIO_CLOCK_FREQ) - 1; 127fc9a8e8dSKaricheri, Muralidharan 128550c5ce6SKhoronzhuk, Ivan writel((clkdiv & 0xffff) | MDIO_CONTROL_ENABLE | 129550c5ce6SKhoronzhuk, Ivan MDIO_CONTROL_FAULT | MDIO_CONTROL_FAULT_ENABLE, 130fc9a8e8dSKaricheri, Muralidharan &adap_mdio->control); 131fc9a8e8dSKaricheri, Muralidharan 132fc9a8e8dSKaricheri, Muralidharan while (readl(&adap_mdio->control) & MDIO_CONTROL_IDLE) 133fc9a8e8dSKaricheri, Muralidharan ; 134550c5ce6SKhoronzhuk, Ivan 135550c5ce6SKhoronzhuk, Ivan return 0; 136fc9a8e8dSKaricheri, Muralidharan } 137fc9a8e8dSKaricheri, Muralidharan 138550c5ce6SKhoronzhuk, Ivan /** 139550c5ce6SKhoronzhuk, Ivan * keystone2_mdio_read - read a PHY register via MDIO interface. 140550c5ce6SKhoronzhuk, Ivan * Blocks until operation is complete. 141550c5ce6SKhoronzhuk, Ivan */ 142550c5ce6SKhoronzhuk, Ivan static int keystone2_mdio_read(struct mii_dev *bus, 143550c5ce6SKhoronzhuk, Ivan int addr, int devad, int reg) 144fc9a8e8dSKaricheri, Muralidharan { 145fc9a8e8dSKaricheri, Muralidharan int tmp; 146550c5ce6SKhoronzhuk, Ivan struct mdio_regs *adap_mdio = bus->priv; 147fc9a8e8dSKaricheri, Muralidharan 148fc9a8e8dSKaricheri, Muralidharan while (readl(&adap_mdio->useraccess0) & MDIO_USERACCESS0_GO) 149fc9a8e8dSKaricheri, Muralidharan ; 150fc9a8e8dSKaricheri, Muralidharan 151550c5ce6SKhoronzhuk, Ivan writel(MDIO_USERACCESS0_GO | MDIO_USERACCESS0_WRITE_READ | 152550c5ce6SKhoronzhuk, Ivan ((reg & 0x1f) << 21) | ((addr & 0x1f) << 16), 153fc9a8e8dSKaricheri, Muralidharan &adap_mdio->useraccess0); 154fc9a8e8dSKaricheri, Muralidharan 155fc9a8e8dSKaricheri, Muralidharan /* Wait for command to complete */ 156fc9a8e8dSKaricheri, Muralidharan while ((tmp = readl(&adap_mdio->useraccess0)) & MDIO_USERACCESS0_GO) 157fc9a8e8dSKaricheri, Muralidharan ; 158fc9a8e8dSKaricheri, Muralidharan 159550c5ce6SKhoronzhuk, Ivan if (tmp & MDIO_USERACCESS0_ACK) 160550c5ce6SKhoronzhuk, Ivan return tmp & 0xffff; 161fc9a8e8dSKaricheri, Muralidharan 162fc9a8e8dSKaricheri, Muralidharan return -1; 163fc9a8e8dSKaricheri, Muralidharan } 164fc9a8e8dSKaricheri, Muralidharan 165550c5ce6SKhoronzhuk, Ivan /** 166550c5ce6SKhoronzhuk, Ivan * keystone2_mdio_write - write to a PHY register via MDIO interface. 167fc9a8e8dSKaricheri, Muralidharan * Blocks until operation is complete. 168fc9a8e8dSKaricheri, Muralidharan */ 169550c5ce6SKhoronzhuk, Ivan static int keystone2_mdio_write(struct mii_dev *bus, 170550c5ce6SKhoronzhuk, Ivan int addr, int devad, int reg, u16 val) 171fc9a8e8dSKaricheri, Muralidharan { 172550c5ce6SKhoronzhuk, Ivan struct mdio_regs *adap_mdio = bus->priv; 173550c5ce6SKhoronzhuk, Ivan 174fc9a8e8dSKaricheri, Muralidharan while (readl(&adap_mdio->useraccess0) & MDIO_USERACCESS0_GO) 175fc9a8e8dSKaricheri, Muralidharan ; 176fc9a8e8dSKaricheri, Muralidharan 177550c5ce6SKhoronzhuk, Ivan writel(MDIO_USERACCESS0_GO | MDIO_USERACCESS0_WRITE_WRITE | 178550c5ce6SKhoronzhuk, Ivan ((reg & 0x1f) << 21) | ((addr & 0x1f) << 16) | 179550c5ce6SKhoronzhuk, Ivan (val & 0xffff), &adap_mdio->useraccess0); 180fc9a8e8dSKaricheri, Muralidharan 181fc9a8e8dSKaricheri, Muralidharan /* Wait for command to complete */ 182fc9a8e8dSKaricheri, Muralidharan while (readl(&adap_mdio->useraccess0) & MDIO_USERACCESS0_GO) 183fc9a8e8dSKaricheri, Muralidharan ; 184fc9a8e8dSKaricheri, Muralidharan 185fc9a8e8dSKaricheri, Muralidharan return 0; 186fc9a8e8dSKaricheri, Muralidharan } 187fc9a8e8dSKaricheri, Muralidharan 1886599f369SMugunthan V N #ifndef CONFIG_DM_ETH 189fc9a8e8dSKaricheri, Muralidharan static void __attribute__((unused)) 190fc9a8e8dSKaricheri, Muralidharan keystone2_eth_gigabit_enable(struct eth_device *dev) 191fc9a8e8dSKaricheri, Muralidharan { 192fc9a8e8dSKaricheri, Muralidharan u_int16_t data; 193fc9a8e8dSKaricheri, Muralidharan struct eth_priv_t *eth_priv = (struct eth_priv_t *)dev->priv; 194fc9a8e8dSKaricheri, Muralidharan 195fc9a8e8dSKaricheri, Muralidharan if (sys_has_mdio) { 196550c5ce6SKhoronzhuk, Ivan data = keystone2_mdio_read(mdio_bus, eth_priv->phy_addr, 197550c5ce6SKhoronzhuk, Ivan MDIO_DEVAD_NONE, 0); 198550c5ce6SKhoronzhuk, Ivan /* speed selection MSB */ 199550c5ce6SKhoronzhuk, Ivan if (!(data & (1 << 6))) 200fc9a8e8dSKaricheri, Muralidharan return; 201fc9a8e8dSKaricheri, Muralidharan } 202fc9a8e8dSKaricheri, Muralidharan 203fc9a8e8dSKaricheri, Muralidharan /* 204fc9a8e8dSKaricheri, Muralidharan * Check if link detected is giga-bit 205fc9a8e8dSKaricheri, Muralidharan * If Gigabit mode detected, enable gigbit in MAC 206fc9a8e8dSKaricheri, Muralidharan */ 207b2cfe322SHao Zhang writel(readl(DEVICE_EMACSL_BASE(eth_priv->slave_port - 1) + 208b2cfe322SHao Zhang CPGMACSL_REG_CTL) | 209fc9a8e8dSKaricheri, Muralidharan EMAC_MACCONTROL_GIGFORCE | EMAC_MACCONTROL_GIGABIT_ENABLE, 210b2cfe322SHao Zhang DEVICE_EMACSL_BASE(eth_priv->slave_port - 1) + CPGMACSL_REG_CTL); 211fc9a8e8dSKaricheri, Muralidharan } 2126599f369SMugunthan V N #else 2136599f369SMugunthan V N static void __attribute__((unused)) 2146599f369SMugunthan V N keystone2_eth_gigabit_enable(struct udevice *dev) 2156599f369SMugunthan V N { 2166599f369SMugunthan V N struct ks2_eth_priv *priv = dev_get_priv(dev); 2176599f369SMugunthan V N u_int16_t data; 2186599f369SMugunthan V N 2196599f369SMugunthan V N if (priv->has_mdio) { 2206599f369SMugunthan V N data = keystone2_mdio_read(priv->mdio_bus, priv->phy_addr, 2216599f369SMugunthan V N MDIO_DEVAD_NONE, 0); 2226599f369SMugunthan V N /* speed selection MSB */ 2236599f369SMugunthan V N if (!(data & (1 << 6))) 2246599f369SMugunthan V N return; 2256599f369SMugunthan V N } 2266599f369SMugunthan V N 2276599f369SMugunthan V N /* 2286599f369SMugunthan V N * Check if link detected is giga-bit 2296599f369SMugunthan V N * If Gigabit mode detected, enable gigbit in MAC 2306599f369SMugunthan V N */ 2316599f369SMugunthan V N writel(readl(DEVICE_EMACSL_BASE(priv->slave_port - 1) + 2326599f369SMugunthan V N CPGMACSL_REG_CTL) | 2336599f369SMugunthan V N EMAC_MACCONTROL_GIGFORCE | EMAC_MACCONTROL_GIGABIT_ENABLE, 2346599f369SMugunthan V N DEVICE_EMACSL_BASE(priv->slave_port - 1) + CPGMACSL_REG_CTL); 2356599f369SMugunthan V N } 2366599f369SMugunthan V N #endif 237fc9a8e8dSKaricheri, Muralidharan 2384657a2d4SVitaly Andrianov #ifdef CONFIG_SOC_K2G 2394657a2d4SVitaly Andrianov int keystone_rgmii_config(struct phy_device *phy_dev) 2404657a2d4SVitaly Andrianov { 2414657a2d4SVitaly Andrianov unsigned int i, status; 2424657a2d4SVitaly Andrianov 2434657a2d4SVitaly Andrianov i = 0; 2444657a2d4SVitaly Andrianov do { 2454657a2d4SVitaly Andrianov if (i > SGMII_ANEG_TIMEOUT) { 2464657a2d4SVitaly Andrianov puts(" TIMEOUT !\n"); 2474657a2d4SVitaly Andrianov phy_dev->link = 0; 2484657a2d4SVitaly Andrianov return 0; 2494657a2d4SVitaly Andrianov } 2504657a2d4SVitaly Andrianov 2514657a2d4SVitaly Andrianov if (ctrlc()) { 2524657a2d4SVitaly Andrianov puts("user interrupt!\n"); 2534657a2d4SVitaly Andrianov phy_dev->link = 0; 2544657a2d4SVitaly Andrianov return -EINTR; 2554657a2d4SVitaly Andrianov } 2564657a2d4SVitaly Andrianov 2574657a2d4SVitaly Andrianov if ((i++ % 500) == 0) 2584657a2d4SVitaly Andrianov printf("."); 2594657a2d4SVitaly Andrianov 2604657a2d4SVitaly Andrianov udelay(1000); /* 1 ms */ 2614657a2d4SVitaly Andrianov status = readl(RGMII_STATUS_REG); 2624657a2d4SVitaly Andrianov } while (!(status & RGMII_REG_STATUS_LINK)); 2634657a2d4SVitaly Andrianov 2644657a2d4SVitaly Andrianov puts(" done\n"); 2654657a2d4SVitaly Andrianov 2664657a2d4SVitaly Andrianov return 0; 2674657a2d4SVitaly Andrianov } 2684657a2d4SVitaly Andrianov #else 269c05d05e7SKhoronzhuk, Ivan int keystone_sgmii_config(struct phy_device *phy_dev, int port, int interface) 270fc9a8e8dSKaricheri, Muralidharan { 271fc9a8e8dSKaricheri, Muralidharan unsigned int i, status, mask; 272fc9a8e8dSKaricheri, Muralidharan unsigned int mr_adv_ability, control; 273fc9a8e8dSKaricheri, Muralidharan 274fc9a8e8dSKaricheri, Muralidharan switch (interface) { 275fc9a8e8dSKaricheri, Muralidharan case SGMII_LINK_MAC_MAC_AUTONEG: 276fc9a8e8dSKaricheri, Muralidharan mr_adv_ability = (SGMII_REG_MR_ADV_ENABLE | 277fc9a8e8dSKaricheri, Muralidharan SGMII_REG_MR_ADV_LINK | 278fc9a8e8dSKaricheri, Muralidharan SGMII_REG_MR_ADV_FULL_DUPLEX | 279fc9a8e8dSKaricheri, Muralidharan SGMII_REG_MR_ADV_GIG_MODE); 280fc9a8e8dSKaricheri, Muralidharan control = (SGMII_REG_CONTROL_MASTER | 281fc9a8e8dSKaricheri, Muralidharan SGMII_REG_CONTROL_AUTONEG); 282fc9a8e8dSKaricheri, Muralidharan 283fc9a8e8dSKaricheri, Muralidharan break; 284fc9a8e8dSKaricheri, Muralidharan case SGMII_LINK_MAC_PHY: 285fc9a8e8dSKaricheri, Muralidharan case SGMII_LINK_MAC_PHY_FORCED: 286fc9a8e8dSKaricheri, Muralidharan mr_adv_ability = SGMII_REG_MR_ADV_ENABLE; 287fc9a8e8dSKaricheri, Muralidharan control = SGMII_REG_CONTROL_AUTONEG; 288fc9a8e8dSKaricheri, Muralidharan 289fc9a8e8dSKaricheri, Muralidharan break; 290fc9a8e8dSKaricheri, Muralidharan case SGMII_LINK_MAC_MAC_FORCED: 291fc9a8e8dSKaricheri, Muralidharan mr_adv_ability = (SGMII_REG_MR_ADV_ENABLE | 292fc9a8e8dSKaricheri, Muralidharan SGMII_REG_MR_ADV_LINK | 293fc9a8e8dSKaricheri, Muralidharan SGMII_REG_MR_ADV_FULL_DUPLEX | 294fc9a8e8dSKaricheri, Muralidharan SGMII_REG_MR_ADV_GIG_MODE); 295fc9a8e8dSKaricheri, Muralidharan control = SGMII_REG_CONTROL_MASTER; 296fc9a8e8dSKaricheri, Muralidharan 297fc9a8e8dSKaricheri, Muralidharan break; 298fc9a8e8dSKaricheri, Muralidharan case SGMII_LINK_MAC_FIBER: 299fc9a8e8dSKaricheri, Muralidharan mr_adv_ability = 0x20; 300fc9a8e8dSKaricheri, Muralidharan control = SGMII_REG_CONTROL_AUTONEG; 301fc9a8e8dSKaricheri, Muralidharan 302fc9a8e8dSKaricheri, Muralidharan break; 303fc9a8e8dSKaricheri, Muralidharan default: 304fc9a8e8dSKaricheri, Muralidharan mr_adv_ability = SGMII_REG_MR_ADV_ENABLE; 305fc9a8e8dSKaricheri, Muralidharan control = SGMII_REG_CONTROL_AUTONEG; 306fc9a8e8dSKaricheri, Muralidharan } 307fc9a8e8dSKaricheri, Muralidharan 308fc9a8e8dSKaricheri, Muralidharan __raw_writel(0, SGMII_CTL_REG(port)); 309fc9a8e8dSKaricheri, Muralidharan 310fc9a8e8dSKaricheri, Muralidharan /* 311fc9a8e8dSKaricheri, Muralidharan * Wait for the SerDes pll to lock, 312fc9a8e8dSKaricheri, Muralidharan * but don't trap if lock is never read 313fc9a8e8dSKaricheri, Muralidharan */ 314fc9a8e8dSKaricheri, Muralidharan for (i = 0; i < 1000; i++) { 315fc9a8e8dSKaricheri, Muralidharan udelay(2000); 316fc9a8e8dSKaricheri, Muralidharan status = __raw_readl(SGMII_STATUS_REG(port)); 317fc9a8e8dSKaricheri, Muralidharan if ((status & SGMII_REG_STATUS_LOCK) != 0) 318fc9a8e8dSKaricheri, Muralidharan break; 319fc9a8e8dSKaricheri, Muralidharan } 320fc9a8e8dSKaricheri, Muralidharan 321fc9a8e8dSKaricheri, Muralidharan __raw_writel(mr_adv_ability, SGMII_MRADV_REG(port)); 322fc9a8e8dSKaricheri, Muralidharan __raw_writel(control, SGMII_CTL_REG(port)); 323fc9a8e8dSKaricheri, Muralidharan 324fc9a8e8dSKaricheri, Muralidharan 325fc9a8e8dSKaricheri, Muralidharan mask = SGMII_REG_STATUS_LINK; 326fc9a8e8dSKaricheri, Muralidharan 327fc9a8e8dSKaricheri, Muralidharan if (control & SGMII_REG_CONTROL_AUTONEG) 328fc9a8e8dSKaricheri, Muralidharan mask |= SGMII_REG_STATUS_AUTONEG; 329fc9a8e8dSKaricheri, Muralidharan 330fc9a8e8dSKaricheri, Muralidharan status = __raw_readl(SGMII_STATUS_REG(port)); 331fc9a8e8dSKaricheri, Muralidharan if ((status & mask) == mask) 332c05d05e7SKhoronzhuk, Ivan return 0; 333c05d05e7SKhoronzhuk, Ivan 334c05d05e7SKhoronzhuk, Ivan printf("\n%s Waiting for SGMII auto negotiation to complete", 335c05d05e7SKhoronzhuk, Ivan phy_dev->dev->name); 336c05d05e7SKhoronzhuk, Ivan while ((status & mask) != mask) { 337c05d05e7SKhoronzhuk, Ivan /* 338c05d05e7SKhoronzhuk, Ivan * Timeout reached ? 339c05d05e7SKhoronzhuk, Ivan */ 340c05d05e7SKhoronzhuk, Ivan if (i > SGMII_ANEG_TIMEOUT) { 341c05d05e7SKhoronzhuk, Ivan puts(" TIMEOUT !\n"); 342c05d05e7SKhoronzhuk, Ivan phy_dev->link = 0; 343c05d05e7SKhoronzhuk, Ivan return 0; 344fc9a8e8dSKaricheri, Muralidharan } 345fc9a8e8dSKaricheri, Muralidharan 346c05d05e7SKhoronzhuk, Ivan if (ctrlc()) { 347c05d05e7SKhoronzhuk, Ivan puts("user interrupt!\n"); 348c05d05e7SKhoronzhuk, Ivan phy_dev->link = 0; 349c05d05e7SKhoronzhuk, Ivan return -EINTR; 350c05d05e7SKhoronzhuk, Ivan } 351c05d05e7SKhoronzhuk, Ivan 352c05d05e7SKhoronzhuk, Ivan if ((i++ % 500) == 0) 353c05d05e7SKhoronzhuk, Ivan printf("."); 354c05d05e7SKhoronzhuk, Ivan 355c05d05e7SKhoronzhuk, Ivan udelay(1000); /* 1 ms */ 356c05d05e7SKhoronzhuk, Ivan status = __raw_readl(SGMII_STATUS_REG(port)); 357c05d05e7SKhoronzhuk, Ivan } 358c05d05e7SKhoronzhuk, Ivan puts(" done\n"); 359c05d05e7SKhoronzhuk, Ivan 360fc9a8e8dSKaricheri, Muralidharan return 0; 361fc9a8e8dSKaricheri, Muralidharan } 3624657a2d4SVitaly Andrianov #endif 363fc9a8e8dSKaricheri, Muralidharan 364fc9a8e8dSKaricheri, Muralidharan int mac_sl_reset(u32 port) 365fc9a8e8dSKaricheri, Muralidharan { 366fc9a8e8dSKaricheri, Muralidharan u32 i, v; 367fc9a8e8dSKaricheri, Muralidharan 368fc9a8e8dSKaricheri, Muralidharan if (port >= DEVICE_N_GMACSL_PORTS) 369fc9a8e8dSKaricheri, Muralidharan return GMACSL_RET_INVALID_PORT; 370fc9a8e8dSKaricheri, Muralidharan 371fc9a8e8dSKaricheri, Muralidharan /* Set the soft reset bit */ 372e6c9428aSKhoronzhuk, Ivan writel(CPGMAC_REG_RESET_VAL_RESET, 373e6c9428aSKhoronzhuk, Ivan DEVICE_EMACSL_BASE(port) + CPGMACSL_REG_RESET); 374fc9a8e8dSKaricheri, Muralidharan 375fc9a8e8dSKaricheri, Muralidharan /* Wait for the bit to clear */ 376fc9a8e8dSKaricheri, Muralidharan for (i = 0; i < DEVICE_EMACSL_RESET_POLL_COUNT; i++) { 377e6c9428aSKhoronzhuk, Ivan v = readl(DEVICE_EMACSL_BASE(port) + CPGMACSL_REG_RESET); 378fc9a8e8dSKaricheri, Muralidharan if ((v & CPGMAC_REG_RESET_VAL_RESET_MASK) != 379fc9a8e8dSKaricheri, Muralidharan CPGMAC_REG_RESET_VAL_RESET) 380fc9a8e8dSKaricheri, Muralidharan return GMACSL_RET_OK; 381fc9a8e8dSKaricheri, Muralidharan } 382fc9a8e8dSKaricheri, Muralidharan 383fc9a8e8dSKaricheri, Muralidharan /* Timeout on the reset */ 384fc9a8e8dSKaricheri, Muralidharan return GMACSL_RET_WARN_RESET_INCOMPLETE; 385fc9a8e8dSKaricheri, Muralidharan } 386fc9a8e8dSKaricheri, Muralidharan 387fc9a8e8dSKaricheri, Muralidharan int mac_sl_config(u_int16_t port, struct mac_sl_cfg *cfg) 388fc9a8e8dSKaricheri, Muralidharan { 389fc9a8e8dSKaricheri, Muralidharan u32 v, i; 390fc9a8e8dSKaricheri, Muralidharan int ret = GMACSL_RET_OK; 391fc9a8e8dSKaricheri, Muralidharan 392fc9a8e8dSKaricheri, Muralidharan if (port >= DEVICE_N_GMACSL_PORTS) 393fc9a8e8dSKaricheri, Muralidharan return GMACSL_RET_INVALID_PORT; 394fc9a8e8dSKaricheri, Muralidharan 395fc9a8e8dSKaricheri, Muralidharan if (cfg->max_rx_len > CPGMAC_REG_MAXLEN_LEN) { 396fc9a8e8dSKaricheri, Muralidharan cfg->max_rx_len = CPGMAC_REG_MAXLEN_LEN; 397fc9a8e8dSKaricheri, Muralidharan ret = GMACSL_RET_WARN_MAXLEN_TOO_BIG; 398fc9a8e8dSKaricheri, Muralidharan } 399fc9a8e8dSKaricheri, Muralidharan 400fc9a8e8dSKaricheri, Muralidharan /* Must wait if the device is undergoing reset */ 401fc9a8e8dSKaricheri, Muralidharan for (i = 0; i < DEVICE_EMACSL_RESET_POLL_COUNT; i++) { 402e6c9428aSKhoronzhuk, Ivan v = readl(DEVICE_EMACSL_BASE(port) + CPGMACSL_REG_RESET); 403fc9a8e8dSKaricheri, Muralidharan if ((v & CPGMAC_REG_RESET_VAL_RESET_MASK) != 404fc9a8e8dSKaricheri, Muralidharan CPGMAC_REG_RESET_VAL_RESET) 405fc9a8e8dSKaricheri, Muralidharan break; 406fc9a8e8dSKaricheri, Muralidharan } 407fc9a8e8dSKaricheri, Muralidharan 408fc9a8e8dSKaricheri, Muralidharan if (i == DEVICE_EMACSL_RESET_POLL_COUNT) 409fc9a8e8dSKaricheri, Muralidharan return GMACSL_RET_CONFIG_FAIL_RESET_ACTIVE; 410fc9a8e8dSKaricheri, Muralidharan 411e6c9428aSKhoronzhuk, Ivan writel(cfg->max_rx_len, DEVICE_EMACSL_BASE(port) + CPGMACSL_REG_MAXLEN); 412e6c9428aSKhoronzhuk, Ivan writel(cfg->ctl, DEVICE_EMACSL_BASE(port) + CPGMACSL_REG_CTL); 413fc9a8e8dSKaricheri, Muralidharan 4144657a2d4SVitaly Andrianov #ifndef CONFIG_SOC_K2HK 415ff11c769SKhoronzhuk, Ivan /* Map RX packet flow priority to 0 */ 416ff11c769SKhoronzhuk, Ivan writel(0, DEVICE_EMACSL_BASE(port) + CPGMACSL_REG_RX_PRI_MAP); 417ff11c769SKhoronzhuk, Ivan #endif 418ff11c769SKhoronzhuk, Ivan 419fc9a8e8dSKaricheri, Muralidharan return ret; 420fc9a8e8dSKaricheri, Muralidharan } 421fc9a8e8dSKaricheri, Muralidharan 422fc9a8e8dSKaricheri, Muralidharan int ethss_config(u32 ctl, u32 max_pkt_size) 423fc9a8e8dSKaricheri, Muralidharan { 424fc9a8e8dSKaricheri, Muralidharan u32 i; 425fc9a8e8dSKaricheri, Muralidharan 426fc9a8e8dSKaricheri, Muralidharan /* Max length register */ 427e6c9428aSKhoronzhuk, Ivan writel(max_pkt_size, DEVICE_CPSW_BASE + CPSW_REG_MAXLEN); 428fc9a8e8dSKaricheri, Muralidharan 429fc9a8e8dSKaricheri, Muralidharan /* Control register */ 430e6c9428aSKhoronzhuk, Ivan writel(ctl, DEVICE_CPSW_BASE + CPSW_REG_CTL); 431fc9a8e8dSKaricheri, Muralidharan 432fc9a8e8dSKaricheri, Muralidharan /* All statistics enabled by default */ 433e6c9428aSKhoronzhuk, Ivan writel(CPSW_REG_VAL_STAT_ENABLE_ALL, 434e6c9428aSKhoronzhuk, Ivan DEVICE_CPSW_BASE + CPSW_REG_STAT_PORT_EN); 435fc9a8e8dSKaricheri, Muralidharan 436fc9a8e8dSKaricheri, Muralidharan /* Reset and enable the ALE */ 437e6c9428aSKhoronzhuk, Ivan writel(CPSW_REG_VAL_ALE_CTL_RESET_AND_ENABLE | 438e6c9428aSKhoronzhuk, Ivan CPSW_REG_VAL_ALE_CTL_BYPASS, 439e6c9428aSKhoronzhuk, Ivan DEVICE_CPSW_BASE + CPSW_REG_ALE_CONTROL); 440fc9a8e8dSKaricheri, Muralidharan 441fc9a8e8dSKaricheri, Muralidharan /* All ports put into forward mode */ 442fc9a8e8dSKaricheri, Muralidharan for (i = 0; i < DEVICE_CPSW_NUM_PORTS; i++) 443e6c9428aSKhoronzhuk, Ivan writel(CPSW_REG_VAL_PORTCTL_FORWARD_MODE, 444e6c9428aSKhoronzhuk, Ivan DEVICE_CPSW_BASE + CPSW_REG_ALE_PORTCTL(i)); 445fc9a8e8dSKaricheri, Muralidharan 446fc9a8e8dSKaricheri, Muralidharan return 0; 447fc9a8e8dSKaricheri, Muralidharan } 448fc9a8e8dSKaricheri, Muralidharan 449fc9a8e8dSKaricheri, Muralidharan int ethss_start(void) 450fc9a8e8dSKaricheri, Muralidharan { 451fc9a8e8dSKaricheri, Muralidharan int i; 452fc9a8e8dSKaricheri, Muralidharan struct mac_sl_cfg cfg; 453fc9a8e8dSKaricheri, Muralidharan 454fc9a8e8dSKaricheri, Muralidharan cfg.max_rx_len = MAX_SIZE_STREAM_BUFFER; 455fc9a8e8dSKaricheri, Muralidharan cfg.ctl = GMACSL_ENABLE | GMACSL_RX_ENABLE_EXT_CTL; 456fc9a8e8dSKaricheri, Muralidharan 457fc9a8e8dSKaricheri, Muralidharan for (i = 0; i < DEVICE_N_GMACSL_PORTS; i++) { 458fc9a8e8dSKaricheri, Muralidharan mac_sl_reset(i); 459fc9a8e8dSKaricheri, Muralidharan mac_sl_config(i, &cfg); 460fc9a8e8dSKaricheri, Muralidharan } 461fc9a8e8dSKaricheri, Muralidharan 462fc9a8e8dSKaricheri, Muralidharan return 0; 463fc9a8e8dSKaricheri, Muralidharan } 464fc9a8e8dSKaricheri, Muralidharan 465fc9a8e8dSKaricheri, Muralidharan int ethss_stop(void) 466fc9a8e8dSKaricheri, Muralidharan { 467fc9a8e8dSKaricheri, Muralidharan int i; 468fc9a8e8dSKaricheri, Muralidharan 469fc9a8e8dSKaricheri, Muralidharan for (i = 0; i < DEVICE_N_GMACSL_PORTS; i++) 470fc9a8e8dSKaricheri, Muralidharan mac_sl_reset(i); 471fc9a8e8dSKaricheri, Muralidharan 472fc9a8e8dSKaricheri, Muralidharan return 0; 473fc9a8e8dSKaricheri, Muralidharan } 474fc9a8e8dSKaricheri, Muralidharan 4756599f369SMugunthan V N struct ks2_serdes ks2_serdes_sgmii_156p25mhz = { 4766599f369SMugunthan V N .clk = SERDES_CLOCK_156P25M, 4776599f369SMugunthan V N .rate = SERDES_RATE_5G, 4786599f369SMugunthan V N .rate_mode = SERDES_QUARTER_RATE, 4796599f369SMugunthan V N .intf = SERDES_PHY_SGMII, 4806599f369SMugunthan V N .loopback = 0, 4816599f369SMugunthan V N }; 4826599f369SMugunthan V N 4836599f369SMugunthan V N #ifndef CONFIG_SOC_K2G 4846599f369SMugunthan V N static void keystone2_net_serdes_setup(void) 4856599f369SMugunthan V N { 4866599f369SMugunthan V N ks2_serdes_init(CONFIG_KSNET_SERDES_SGMII_BASE, 4876599f369SMugunthan V N &ks2_serdes_sgmii_156p25mhz, 4886599f369SMugunthan V N CONFIG_KSNET_SERDES_LANES_PER_SGMII); 4896599f369SMugunthan V N 4906599f369SMugunthan V N #if defined(CONFIG_SOC_K2E) || defined(CONFIG_SOC_K2L) 4916599f369SMugunthan V N ks2_serdes_init(CONFIG_KSNET_SERDES_SGMII2_BASE, 4926599f369SMugunthan V N &ks2_serdes_sgmii_156p25mhz, 4936599f369SMugunthan V N CONFIG_KSNET_SERDES_LANES_PER_SGMII); 4946599f369SMugunthan V N #endif 4956599f369SMugunthan V N 4966599f369SMugunthan V N /* wait till setup */ 4976599f369SMugunthan V N udelay(5000); 4986599f369SMugunthan V N } 4996599f369SMugunthan V N #endif 5006599f369SMugunthan V N 5016599f369SMugunthan V N #ifndef CONFIG_DM_ETH 5026599f369SMugunthan V N 5036599f369SMugunthan V N int keystone2_eth_read_mac_addr(struct eth_device *dev) 5046599f369SMugunthan V N { 5056599f369SMugunthan V N struct eth_priv_t *eth_priv; 5066599f369SMugunthan V N u32 maca = 0; 5076599f369SMugunthan V N u32 macb = 0; 5086599f369SMugunthan V N 5096599f369SMugunthan V N eth_priv = (struct eth_priv_t *)dev->priv; 5106599f369SMugunthan V N 5116599f369SMugunthan V N /* Read the e-fuse mac address */ 5126599f369SMugunthan V N if (eth_priv->slave_port == 1) { 5136599f369SMugunthan V N maca = __raw_readl(MAC_ID_BASE_ADDR); 5146599f369SMugunthan V N macb = __raw_readl(MAC_ID_BASE_ADDR + 4); 5156599f369SMugunthan V N } 5166599f369SMugunthan V N 5176599f369SMugunthan V N dev->enetaddr[0] = (macb >> 8) & 0xff; 5186599f369SMugunthan V N dev->enetaddr[1] = (macb >> 0) & 0xff; 5196599f369SMugunthan V N dev->enetaddr[2] = (maca >> 24) & 0xff; 5206599f369SMugunthan V N dev->enetaddr[3] = (maca >> 16) & 0xff; 5216599f369SMugunthan V N dev->enetaddr[4] = (maca >> 8) & 0xff; 5226599f369SMugunthan V N dev->enetaddr[5] = (maca >> 0) & 0xff; 5236599f369SMugunthan V N 5246599f369SMugunthan V N return 0; 5256599f369SMugunthan V N } 5266599f369SMugunthan V N 527fc9a8e8dSKaricheri, Muralidharan int32_t cpmac_drv_send(u32 *buffer, int num_bytes, int slave_port_num) 528fc9a8e8dSKaricheri, Muralidharan { 529fc9a8e8dSKaricheri, Muralidharan if (num_bytes < EMAC_MIN_ETHERNET_PKT_SIZE) 530fc9a8e8dSKaricheri, Muralidharan num_bytes = EMAC_MIN_ETHERNET_PKT_SIZE; 531fc9a8e8dSKaricheri, Muralidharan 5329ea9021aSKhoronzhuk, Ivan return ksnav_send(&netcp_pktdma, buffer, 5339ea9021aSKhoronzhuk, Ivan num_bytes, (slave_port_num) << 16); 534fc9a8e8dSKaricheri, Muralidharan } 535fc9a8e8dSKaricheri, Muralidharan 536fc9a8e8dSKaricheri, Muralidharan /* Eth device open */ 537fc9a8e8dSKaricheri, Muralidharan static int keystone2_eth_open(struct eth_device *dev, bd_t *bis) 538fc9a8e8dSKaricheri, Muralidharan { 539fc9a8e8dSKaricheri, Muralidharan struct eth_priv_t *eth_priv = (struct eth_priv_t *)dev->priv; 5403fe93623SKhoronzhuk, Ivan struct phy_device *phy_dev = eth_priv->phy_dev; 541fc9a8e8dSKaricheri, Muralidharan 542fc9a8e8dSKaricheri, Muralidharan debug("+ emac_open\n"); 543fc9a8e8dSKaricheri, Muralidharan 544fc9a8e8dSKaricheri, Muralidharan net_rx_buffs.rx_flow = eth_priv->rx_flow; 545fc9a8e8dSKaricheri, Muralidharan 546fc9a8e8dSKaricheri, Muralidharan sys_has_mdio = 547fc9a8e8dSKaricheri, Muralidharan (eth_priv->sgmii_link_type == SGMII_LINK_MAC_PHY) ? 1 : 0; 548fc9a8e8dSKaricheri, Muralidharan 5496c0fb41aSKhoronzhuk, Ivan if (sys_has_mdio) 5506c0fb41aSKhoronzhuk, Ivan keystone2_mdio_reset(mdio_bus); 5516c0fb41aSKhoronzhuk, Ivan 5524657a2d4SVitaly Andrianov #ifdef CONFIG_SOC_K2G 5534657a2d4SVitaly Andrianov keystone_rgmii_config(phy_dev); 5544657a2d4SVitaly Andrianov #else 555c05d05e7SKhoronzhuk, Ivan keystone_sgmii_config(phy_dev, eth_priv->slave_port - 1, 556fc9a8e8dSKaricheri, Muralidharan eth_priv->sgmii_link_type); 5574657a2d4SVitaly Andrianov #endif 558fc9a8e8dSKaricheri, Muralidharan 559fc9a8e8dSKaricheri, Muralidharan udelay(10000); 560fc9a8e8dSKaricheri, Muralidharan 561fc9a8e8dSKaricheri, Muralidharan /* On chip switch configuration */ 562fc9a8e8dSKaricheri, Muralidharan ethss_config(target_get_switch_ctl(), SWITCH_MAX_PKT_SIZE); 563fc9a8e8dSKaricheri, Muralidharan 564fc9a8e8dSKaricheri, Muralidharan /* TODO: add error handling code */ 565fc9a8e8dSKaricheri, Muralidharan if (qm_init()) { 566fc9a8e8dSKaricheri, Muralidharan printf("ERROR: qm_init()\n"); 567fc9a8e8dSKaricheri, Muralidharan return -1; 568fc9a8e8dSKaricheri, Muralidharan } 5699ea9021aSKhoronzhuk, Ivan if (ksnav_init(&netcp_pktdma, &net_rx_buffs)) { 570fc9a8e8dSKaricheri, Muralidharan qm_close(); 571fc9a8e8dSKaricheri, Muralidharan printf("ERROR: netcp_init()\n"); 572fc9a8e8dSKaricheri, Muralidharan return -1; 573fc9a8e8dSKaricheri, Muralidharan } 574fc9a8e8dSKaricheri, Muralidharan 575fc9a8e8dSKaricheri, Muralidharan /* 576fc9a8e8dSKaricheri, Muralidharan * Streaming switch configuration. If not present this 577fc9a8e8dSKaricheri, Muralidharan * statement is defined to void in target.h. 578fc9a8e8dSKaricheri, Muralidharan * If present this is usually defined to a series of register writes 579fc9a8e8dSKaricheri, Muralidharan */ 580fc9a8e8dSKaricheri, Muralidharan hw_config_streaming_switch(); 581fc9a8e8dSKaricheri, Muralidharan 582fc9a8e8dSKaricheri, Muralidharan if (sys_has_mdio) { 583550c5ce6SKhoronzhuk, Ivan keystone2_mdio_reset(mdio_bus); 584fc9a8e8dSKaricheri, Muralidharan 5853fe93623SKhoronzhuk, Ivan phy_startup(phy_dev); 5863fe93623SKhoronzhuk, Ivan if (phy_dev->link == 0) { 5879ea9021aSKhoronzhuk, Ivan ksnav_close(&netcp_pktdma); 588fc9a8e8dSKaricheri, Muralidharan qm_close(); 589fc9a8e8dSKaricheri, Muralidharan return -1; 590fc9a8e8dSKaricheri, Muralidharan } 591fc9a8e8dSKaricheri, Muralidharan } 592fc9a8e8dSKaricheri, Muralidharan 593fc9a8e8dSKaricheri, Muralidharan emac_gigabit_enable(dev); 594fc9a8e8dSKaricheri, Muralidharan 595fc9a8e8dSKaricheri, Muralidharan ethss_start(); 596fc9a8e8dSKaricheri, Muralidharan 597fc9a8e8dSKaricheri, Muralidharan debug("- emac_open\n"); 598fc9a8e8dSKaricheri, Muralidharan 599fc9a8e8dSKaricheri, Muralidharan emac_open = 1; 600fc9a8e8dSKaricheri, Muralidharan 601fc9a8e8dSKaricheri, Muralidharan return 0; 602fc9a8e8dSKaricheri, Muralidharan } 603fc9a8e8dSKaricheri, Muralidharan 604fc9a8e8dSKaricheri, Muralidharan /* Eth device close */ 605fc9a8e8dSKaricheri, Muralidharan void keystone2_eth_close(struct eth_device *dev) 606fc9a8e8dSKaricheri, Muralidharan { 6073fe93623SKhoronzhuk, Ivan struct eth_priv_t *eth_priv = (struct eth_priv_t *)dev->priv; 6083fe93623SKhoronzhuk, Ivan struct phy_device *phy_dev = eth_priv->phy_dev; 6093fe93623SKhoronzhuk, Ivan 610fc9a8e8dSKaricheri, Muralidharan debug("+ emac_close\n"); 611fc9a8e8dSKaricheri, Muralidharan 612fc9a8e8dSKaricheri, Muralidharan if (!emac_open) 613fc9a8e8dSKaricheri, Muralidharan return; 614fc9a8e8dSKaricheri, Muralidharan 615fc9a8e8dSKaricheri, Muralidharan ethss_stop(); 616fc9a8e8dSKaricheri, Muralidharan 6179ea9021aSKhoronzhuk, Ivan ksnav_close(&netcp_pktdma); 618fc9a8e8dSKaricheri, Muralidharan qm_close(); 6193fe93623SKhoronzhuk, Ivan phy_shutdown(phy_dev); 620fc9a8e8dSKaricheri, Muralidharan 621fc9a8e8dSKaricheri, Muralidharan emac_open = 0; 622fc9a8e8dSKaricheri, Muralidharan 623fc9a8e8dSKaricheri, Muralidharan debug("- emac_close\n"); 624fc9a8e8dSKaricheri, Muralidharan } 625fc9a8e8dSKaricheri, Muralidharan 626fc9a8e8dSKaricheri, Muralidharan /* 627fc9a8e8dSKaricheri, Muralidharan * This function sends a single packet on the network and returns 628fc9a8e8dSKaricheri, Muralidharan * positive number (number of bytes transmitted) or negative for error 629fc9a8e8dSKaricheri, Muralidharan */ 630fc9a8e8dSKaricheri, Muralidharan static int keystone2_eth_send_packet(struct eth_device *dev, 631fc9a8e8dSKaricheri, Muralidharan void *packet, int length) 632fc9a8e8dSKaricheri, Muralidharan { 633fc9a8e8dSKaricheri, Muralidharan int ret_status = -1; 634fc9a8e8dSKaricheri, Muralidharan struct eth_priv_t *eth_priv = (struct eth_priv_t *)dev->priv; 635a4d2adeeSKhoronzhuk, Ivan struct phy_device *phy_dev = eth_priv->phy_dev; 636fc9a8e8dSKaricheri, Muralidharan 637a4d2adeeSKhoronzhuk, Ivan genphy_update_link(phy_dev); 638a4d2adeeSKhoronzhuk, Ivan if (phy_dev->link == 0) 639fc9a8e8dSKaricheri, Muralidharan return -1; 640fc9a8e8dSKaricheri, Muralidharan 641fc9a8e8dSKaricheri, Muralidharan if (cpmac_drv_send((u32 *)packet, length, eth_priv->slave_port) != 0) 642fc9a8e8dSKaricheri, Muralidharan return ret_status; 643fc9a8e8dSKaricheri, Muralidharan 644fc9a8e8dSKaricheri, Muralidharan return length; 645fc9a8e8dSKaricheri, Muralidharan } 646fc9a8e8dSKaricheri, Muralidharan 647fc9a8e8dSKaricheri, Muralidharan /* 648fc9a8e8dSKaricheri, Muralidharan * This function handles receipt of a packet from the network 649fc9a8e8dSKaricheri, Muralidharan */ 650fc9a8e8dSKaricheri, Muralidharan static int keystone2_eth_rcv_packet(struct eth_device *dev) 651fc9a8e8dSKaricheri, Muralidharan { 652fc9a8e8dSKaricheri, Muralidharan void *hd; 653fc9a8e8dSKaricheri, Muralidharan int pkt_size; 654fc9a8e8dSKaricheri, Muralidharan u32 *pkt; 655fc9a8e8dSKaricheri, Muralidharan 6569ea9021aSKhoronzhuk, Ivan hd = ksnav_recv(&netcp_pktdma, &pkt, &pkt_size); 657fc9a8e8dSKaricheri, Muralidharan if (hd == NULL) 658fc9a8e8dSKaricheri, Muralidharan return 0; 659fc9a8e8dSKaricheri, Muralidharan 6601fd92db8SJoe Hershberger net_process_received_packet((uchar *)pkt, pkt_size); 661fc9a8e8dSKaricheri, Muralidharan 6629ea9021aSKhoronzhuk, Ivan ksnav_release_rxhd(&netcp_pktdma, hd); 663fc9a8e8dSKaricheri, Muralidharan 664fc9a8e8dSKaricheri, Muralidharan return pkt_size; 665fc9a8e8dSKaricheri, Muralidharan } 666fc9a8e8dSKaricheri, Muralidharan 6675031ca59SVitaly Andrianov #ifdef CONFIG_MCAST_TFTP 6685031ca59SVitaly Andrianov static int keystone2_eth_bcast_addr(struct eth_device *dev, u32 ip, u8 set) 6695031ca59SVitaly Andrianov { 6705031ca59SVitaly Andrianov return 0; 6715031ca59SVitaly Andrianov } 6725031ca59SVitaly Andrianov #endif 6735031ca59SVitaly Andrianov 674fc9a8e8dSKaricheri, Muralidharan /* 675fc9a8e8dSKaricheri, Muralidharan * This function initializes the EMAC hardware. 676fc9a8e8dSKaricheri, Muralidharan */ 677fc9a8e8dSKaricheri, Muralidharan int keystone2_emac_initialize(struct eth_priv_t *eth_priv) 678fc9a8e8dSKaricheri, Muralidharan { 679550c5ce6SKhoronzhuk, Ivan int res; 680fc9a8e8dSKaricheri, Muralidharan struct eth_device *dev; 6813fe93623SKhoronzhuk, Ivan struct phy_device *phy_dev; 6826599f369SMugunthan V N struct mdio_regs *adap_mdio = (struct mdio_regs *)EMAC_MDIO_BASE_ADDR; 683fc9a8e8dSKaricheri, Muralidharan 684fc9a8e8dSKaricheri, Muralidharan dev = malloc(sizeof(struct eth_device)); 685fc9a8e8dSKaricheri, Muralidharan if (dev == NULL) 686fc9a8e8dSKaricheri, Muralidharan return -1; 687fc9a8e8dSKaricheri, Muralidharan 688fc9a8e8dSKaricheri, Muralidharan memset(dev, 0, sizeof(struct eth_device)); 689fc9a8e8dSKaricheri, Muralidharan 690fc9a8e8dSKaricheri, Muralidharan strcpy(dev->name, eth_priv->int_name); 691fc9a8e8dSKaricheri, Muralidharan dev->priv = eth_priv; 692fc9a8e8dSKaricheri, Muralidharan 693fc9a8e8dSKaricheri, Muralidharan keystone2_eth_read_mac_addr(dev); 694fc9a8e8dSKaricheri, Muralidharan 695fc9a8e8dSKaricheri, Muralidharan dev->iobase = 0; 696fc9a8e8dSKaricheri, Muralidharan dev->init = keystone2_eth_open; 697fc9a8e8dSKaricheri, Muralidharan dev->halt = keystone2_eth_close; 698fc9a8e8dSKaricheri, Muralidharan dev->send = keystone2_eth_send_packet; 699fc9a8e8dSKaricheri, Muralidharan dev->recv = keystone2_eth_rcv_packet; 7005031ca59SVitaly Andrianov #ifdef CONFIG_MCAST_TFTP 7015031ca59SVitaly Andrianov dev->mcast = keystone2_eth_bcast_addr; 7025031ca59SVitaly Andrianov #endif 703fc9a8e8dSKaricheri, Muralidharan 704fc9a8e8dSKaricheri, Muralidharan eth_register(dev); 705fc9a8e8dSKaricheri, Muralidharan 706550c5ce6SKhoronzhuk, Ivan /* Register MDIO bus if it's not registered yet */ 707550c5ce6SKhoronzhuk, Ivan if (!mdio_bus) { 708550c5ce6SKhoronzhuk, Ivan mdio_bus = mdio_alloc(); 709550c5ce6SKhoronzhuk, Ivan mdio_bus->read = keystone2_mdio_read; 710550c5ce6SKhoronzhuk, Ivan mdio_bus->write = keystone2_mdio_write; 711550c5ce6SKhoronzhuk, Ivan mdio_bus->reset = keystone2_mdio_reset; 712550c5ce6SKhoronzhuk, Ivan mdio_bus->priv = (void *)EMAC_MDIO_BASE_ADDR; 713192bc694SBen Whitten strcpy(mdio_bus->name, "ethernet-mdio"); 714550c5ce6SKhoronzhuk, Ivan 715550c5ce6SKhoronzhuk, Ivan res = mdio_register(mdio_bus); 716550c5ce6SKhoronzhuk, Ivan if (res) 717550c5ce6SKhoronzhuk, Ivan return res; 718550c5ce6SKhoronzhuk, Ivan } 719550c5ce6SKhoronzhuk, Ivan 7204657a2d4SVitaly Andrianov #ifndef CONFIG_SOC_K2G 721312aca4eSVitaly Andrianov keystone2_net_serdes_setup(); 7224657a2d4SVitaly Andrianov #endif 723312aca4eSVitaly Andrianov 7243fe93623SKhoronzhuk, Ivan /* Create phy device and bind it with driver */ 7253fe93623SKhoronzhuk, Ivan #ifdef CONFIG_KSNET_MDIO_PHY_CONFIG_ENABLE 7263fe93623SKhoronzhuk, Ivan phy_dev = phy_connect(mdio_bus, eth_priv->phy_addr, 727bf7bd4e7SMugunthan V N dev, eth_priv->phy_if); 7283fe93623SKhoronzhuk, Ivan phy_config(phy_dev); 7293fe93623SKhoronzhuk, Ivan #else 7303fe93623SKhoronzhuk, Ivan phy_dev = phy_find_by_mask(mdio_bus, 1 << eth_priv->phy_addr, 731bf7bd4e7SMugunthan V N eth_priv->phy_if); 7323fe93623SKhoronzhuk, Ivan phy_dev->dev = dev; 7333fe93623SKhoronzhuk, Ivan #endif 7343fe93623SKhoronzhuk, Ivan eth_priv->phy_dev = phy_dev; 7353fe93623SKhoronzhuk, Ivan 736fc9a8e8dSKaricheri, Muralidharan return 0; 737fc9a8e8dSKaricheri, Muralidharan } 738fc9a8e8dSKaricheri, Muralidharan 7396599f369SMugunthan V N #else 74092a16c81SHao Zhang 7416599f369SMugunthan V N static int ks2_eth_start(struct udevice *dev) 742fc9a8e8dSKaricheri, Muralidharan { 7436599f369SMugunthan V N struct ks2_eth_priv *priv = dev_get_priv(dev); 74492a16c81SHao Zhang 7456599f369SMugunthan V N #ifdef CONFIG_SOC_K2G 7466599f369SMugunthan V N keystone_rgmii_config(priv->phydev); 7476599f369SMugunthan V N #else 7486599f369SMugunthan V N keystone_sgmii_config(priv->phydev, priv->slave_port - 1, 7496599f369SMugunthan V N priv->sgmii_link_type); 7503c61502aSKhoronzhuk, Ivan #endif 7513c61502aSKhoronzhuk, Ivan 7526599f369SMugunthan V N udelay(10000); 7536599f369SMugunthan V N 7546599f369SMugunthan V N /* On chip switch configuration */ 7556599f369SMugunthan V N ethss_config(target_get_switch_ctl(), SWITCH_MAX_PKT_SIZE); 7566599f369SMugunthan V N 7576599f369SMugunthan V N qm_init(); 7586599f369SMugunthan V N 7596599f369SMugunthan V N if (ksnav_init(priv->netcp_pktdma, &priv->net_rx_buffs)) { 7606599f369SMugunthan V N error("ksnav_init failed\n"); 7616599f369SMugunthan V N goto err_knav_init; 762fc9a8e8dSKaricheri, Muralidharan } 7636599f369SMugunthan V N 7646599f369SMugunthan V N /* 7656599f369SMugunthan V N * Streaming switch configuration. If not present this 7666599f369SMugunthan V N * statement is defined to void in target.h. 7676599f369SMugunthan V N * If present this is usually defined to a series of register writes 7686599f369SMugunthan V N */ 7696599f369SMugunthan V N hw_config_streaming_switch(); 7706599f369SMugunthan V N 7716599f369SMugunthan V N if (priv->has_mdio) { 772a61f6a55SMugunthan V N keystone2_mdio_reset(priv->mdio_bus); 773a61f6a55SMugunthan V N 7746599f369SMugunthan V N phy_startup(priv->phydev); 7756599f369SMugunthan V N if (priv->phydev->link == 0) { 7766599f369SMugunthan V N error("phy startup failed\n"); 7776599f369SMugunthan V N goto err_phy_start; 7786599f369SMugunthan V N } 7796599f369SMugunthan V N } 7806599f369SMugunthan V N 7816599f369SMugunthan V N emac_gigabit_enable(dev); 7826599f369SMugunthan V N 7836599f369SMugunthan V N ethss_start(); 7846599f369SMugunthan V N 7856599f369SMugunthan V N priv->emac_open = true; 7866599f369SMugunthan V N 7876599f369SMugunthan V N return 0; 7886599f369SMugunthan V N 7896599f369SMugunthan V N err_phy_start: 7906599f369SMugunthan V N ksnav_close(priv->netcp_pktdma); 7916599f369SMugunthan V N err_knav_init: 7926599f369SMugunthan V N qm_close(); 7936599f369SMugunthan V N 7946599f369SMugunthan V N return -EFAULT; 7956599f369SMugunthan V N } 7966599f369SMugunthan V N 7976599f369SMugunthan V N static int ks2_eth_send(struct udevice *dev, void *packet, int length) 7986599f369SMugunthan V N { 7996599f369SMugunthan V N struct ks2_eth_priv *priv = dev_get_priv(dev); 8006599f369SMugunthan V N 8016599f369SMugunthan V N genphy_update_link(priv->phydev); 8026599f369SMugunthan V N if (priv->phydev->link == 0) 8036599f369SMugunthan V N return -1; 8046599f369SMugunthan V N 8056599f369SMugunthan V N if (length < EMAC_MIN_ETHERNET_PKT_SIZE) 8066599f369SMugunthan V N length = EMAC_MIN_ETHERNET_PKT_SIZE; 8076599f369SMugunthan V N 8086599f369SMugunthan V N return ksnav_send(priv->netcp_pktdma, (u32 *)packet, 8096599f369SMugunthan V N length, (priv->slave_port) << 16); 8106599f369SMugunthan V N } 8116599f369SMugunthan V N 8126599f369SMugunthan V N static int ks2_eth_recv(struct udevice *dev, int flags, uchar **packetp) 8136599f369SMugunthan V N { 8146599f369SMugunthan V N struct ks2_eth_priv *priv = dev_get_priv(dev); 8156599f369SMugunthan V N int pkt_size; 8166599f369SMugunthan V N u32 *pkt = NULL; 8176599f369SMugunthan V N 8186599f369SMugunthan V N priv->hd = ksnav_recv(priv->netcp_pktdma, &pkt, &pkt_size); 8196599f369SMugunthan V N if (priv->hd == NULL) 8206599f369SMugunthan V N return -EAGAIN; 8216599f369SMugunthan V N 8226599f369SMugunthan V N *packetp = (uchar *)pkt; 8236599f369SMugunthan V N 8246599f369SMugunthan V N return pkt_size; 8256599f369SMugunthan V N } 8266599f369SMugunthan V N 8276599f369SMugunthan V N static int ks2_eth_free_pkt(struct udevice *dev, uchar *packet, 8286599f369SMugunthan V N int length) 8296599f369SMugunthan V N { 8306599f369SMugunthan V N struct ks2_eth_priv *priv = dev_get_priv(dev); 8316599f369SMugunthan V N 8326599f369SMugunthan V N ksnav_release_rxhd(priv->netcp_pktdma, priv->hd); 8336599f369SMugunthan V N 8346599f369SMugunthan V N return 0; 8356599f369SMugunthan V N } 8366599f369SMugunthan V N 8376599f369SMugunthan V N static void ks2_eth_stop(struct udevice *dev) 8386599f369SMugunthan V N { 8396599f369SMugunthan V N struct ks2_eth_priv *priv = dev_get_priv(dev); 8406599f369SMugunthan V N 8416599f369SMugunthan V N if (!priv->emac_open) 8426599f369SMugunthan V N return; 8436599f369SMugunthan V N ethss_stop(); 8446599f369SMugunthan V N 8456599f369SMugunthan V N ksnav_close(priv->netcp_pktdma); 8466599f369SMugunthan V N qm_close(); 8476599f369SMugunthan V N phy_shutdown(priv->phydev); 8486599f369SMugunthan V N priv->emac_open = false; 8496599f369SMugunthan V N } 8506599f369SMugunthan V N 8516599f369SMugunthan V N int ks2_eth_read_rom_hwaddr(struct udevice *dev) 8526599f369SMugunthan V N { 8536599f369SMugunthan V N struct ks2_eth_priv *priv = dev_get_priv(dev); 8546599f369SMugunthan V N struct eth_pdata *pdata = dev_get_platdata(dev); 8556599f369SMugunthan V N u32 maca = 0; 8566599f369SMugunthan V N u32 macb = 0; 8576599f369SMugunthan V N 8586599f369SMugunthan V N /* Read the e-fuse mac address */ 8596599f369SMugunthan V N if (priv->slave_port == 1) { 8606599f369SMugunthan V N maca = __raw_readl(MAC_ID_BASE_ADDR); 8616599f369SMugunthan V N macb = __raw_readl(MAC_ID_BASE_ADDR + 4); 8626599f369SMugunthan V N } 8636599f369SMugunthan V N 8646599f369SMugunthan V N pdata->enetaddr[0] = (macb >> 8) & 0xff; 8656599f369SMugunthan V N pdata->enetaddr[1] = (macb >> 0) & 0xff; 8666599f369SMugunthan V N pdata->enetaddr[2] = (maca >> 24) & 0xff; 8676599f369SMugunthan V N pdata->enetaddr[3] = (maca >> 16) & 0xff; 8686599f369SMugunthan V N pdata->enetaddr[4] = (maca >> 8) & 0xff; 8696599f369SMugunthan V N pdata->enetaddr[5] = (maca >> 0) & 0xff; 8706599f369SMugunthan V N 8716599f369SMugunthan V N return 0; 8726599f369SMugunthan V N } 8736599f369SMugunthan V N 8746599f369SMugunthan V N int ks2_eth_write_hwaddr(struct udevice *dev) 8756599f369SMugunthan V N { 8766599f369SMugunthan V N struct ks2_eth_priv *priv = dev_get_priv(dev); 8776599f369SMugunthan V N struct eth_pdata *pdata = dev_get_platdata(dev); 8786599f369SMugunthan V N 8796599f369SMugunthan V N writel(mac_hi(pdata->enetaddr), 8806599f369SMugunthan V N DEVICE_EMACSW_BASE(pdata->iobase, priv->slave_port - 1) + 8816599f369SMugunthan V N CPGMACSL_REG_SA_HI); 8826599f369SMugunthan V N writel(mac_lo(pdata->enetaddr), 8836599f369SMugunthan V N DEVICE_EMACSW_BASE(pdata->iobase, priv->slave_port - 1) + 8846599f369SMugunthan V N CPGMACSL_REG_SA_LO); 8856599f369SMugunthan V N 8866599f369SMugunthan V N return 0; 8876599f369SMugunthan V N } 8886599f369SMugunthan V N 8896599f369SMugunthan V N static int ks2_eth_probe(struct udevice *dev) 8906599f369SMugunthan V N { 8916599f369SMugunthan V N struct ks2_eth_priv *priv = dev_get_priv(dev); 8926599f369SMugunthan V N struct mii_dev *mdio_bus; 8936599f369SMugunthan V N int ret; 8946599f369SMugunthan V N 8956599f369SMugunthan V N priv->dev = dev; 8966599f369SMugunthan V N 8976599f369SMugunthan V N /* These clock enables has to be moved to common location */ 8986599f369SMugunthan V N if (cpu_is_k2g()) 8996599f369SMugunthan V N writel(KS2_ETHERNET_RGMII, KS2_ETHERNET_CFG); 9006599f369SMugunthan V N 9016599f369SMugunthan V N /* By default, select PA PLL clock as PA clock source */ 9026599f369SMugunthan V N #ifndef CONFIG_SOC_K2G 9036599f369SMugunthan V N if (psc_enable_module(KS2_LPSC_PA)) 9046599f369SMugunthan V N return -EACCES; 9056599f369SMugunthan V N #endif 9066599f369SMugunthan V N if (psc_enable_module(KS2_LPSC_CPGMAC)) 9076599f369SMugunthan V N return -EACCES; 9086599f369SMugunthan V N if (psc_enable_module(KS2_LPSC_CRYPTO)) 9096599f369SMugunthan V N return -EACCES; 9106599f369SMugunthan V N 9116599f369SMugunthan V N if (cpu_is_k2e() || cpu_is_k2l()) 9126599f369SMugunthan V N pll_pa_clk_sel(); 9136599f369SMugunthan V N 9146599f369SMugunthan V N 9151610a921SMugunthan V N priv->net_rx_buffs.buff_ptr = rx_buffs; 9161610a921SMugunthan V N priv->net_rx_buffs.num_buffs = RX_BUFF_NUMS; 9171610a921SMugunthan V N priv->net_rx_buffs.buff_len = RX_BUFF_LEN; 9186599f369SMugunthan V N 919a61f6a55SMugunthan V N if (priv->slave_port == 1) { 920a61f6a55SMugunthan V N /* 921a61f6a55SMugunthan V N * Register MDIO bus for slave 0 only, other slave have 922a61f6a55SMugunthan V N * to re-use the same 923a61f6a55SMugunthan V N */ 9246599f369SMugunthan V N mdio_bus = mdio_alloc(); 9256599f369SMugunthan V N if (!mdio_bus) { 9266599f369SMugunthan V N error("MDIO alloc failed\n"); 9276599f369SMugunthan V N return -ENOMEM; 9286599f369SMugunthan V N } 9296599f369SMugunthan V N priv->mdio_bus = mdio_bus; 9306599f369SMugunthan V N mdio_bus->read = keystone2_mdio_read; 9316599f369SMugunthan V N mdio_bus->write = keystone2_mdio_write; 9326599f369SMugunthan V N mdio_bus->reset = keystone2_mdio_reset; 9336599f369SMugunthan V N mdio_bus->priv = priv->mdio_base; 9346599f369SMugunthan V N sprintf(mdio_bus->name, "ethernet-mdio"); 9356599f369SMugunthan V N 9366599f369SMugunthan V N ret = mdio_register(mdio_bus); 9376599f369SMugunthan V N if (ret) { 9386599f369SMugunthan V N error("MDIO bus register failed\n"); 9396599f369SMugunthan V N return ret; 9406599f369SMugunthan V N } 941a61f6a55SMugunthan V N } else { 942a61f6a55SMugunthan V N /* Get the MDIO bus from slave 0 device */ 943a61f6a55SMugunthan V N struct ks2_eth_priv *parent_priv; 944a61f6a55SMugunthan V N 945a61f6a55SMugunthan V N parent_priv = dev_get_priv(dev->parent); 946a61f6a55SMugunthan V N priv->mdio_bus = parent_priv->mdio_bus; 947a61f6a55SMugunthan V N } 9486599f369SMugunthan V N 9496599f369SMugunthan V N #ifndef CONFIG_SOC_K2G 9506599f369SMugunthan V N keystone2_net_serdes_setup(); 9516599f369SMugunthan V N #endif 9526599f369SMugunthan V N 9536599f369SMugunthan V N priv->netcp_pktdma = &netcp_pktdma; 9546599f369SMugunthan V N 955a61f6a55SMugunthan V N if (priv->has_mdio) { 956a61f6a55SMugunthan V N priv->phydev = phy_connect(priv->mdio_bus, priv->phy_addr, 957a61f6a55SMugunthan V N dev, priv->phy_if); 9586599f369SMugunthan V N phy_config(priv->phydev); 959a61f6a55SMugunthan V N } 9606599f369SMugunthan V N 9616599f369SMugunthan V N return 0; 9626599f369SMugunthan V N } 9636599f369SMugunthan V N 9646599f369SMugunthan V N int ks2_eth_remove(struct udevice *dev) 9656599f369SMugunthan V N { 9666599f369SMugunthan V N struct ks2_eth_priv *priv = dev_get_priv(dev); 9676599f369SMugunthan V N 9686599f369SMugunthan V N free(priv->phydev); 9696599f369SMugunthan V N mdio_unregister(priv->mdio_bus); 9706599f369SMugunthan V N mdio_free(priv->mdio_bus); 9716599f369SMugunthan V N 9726599f369SMugunthan V N return 0; 9736599f369SMugunthan V N } 9746599f369SMugunthan V N 9756599f369SMugunthan V N static const struct eth_ops ks2_eth_ops = { 9766599f369SMugunthan V N .start = ks2_eth_start, 9776599f369SMugunthan V N .send = ks2_eth_send, 9786599f369SMugunthan V N .recv = ks2_eth_recv, 9796599f369SMugunthan V N .free_pkt = ks2_eth_free_pkt, 9806599f369SMugunthan V N .stop = ks2_eth_stop, 9816599f369SMugunthan V N .read_rom_hwaddr = ks2_eth_read_rom_hwaddr, 9826599f369SMugunthan V N .write_hwaddr = ks2_eth_write_hwaddr, 9836599f369SMugunthan V N }; 9846599f369SMugunthan V N 985a61f6a55SMugunthan V N static int ks2_eth_bind_slaves(struct udevice *dev, int gbe, int *gbe_0) 9866599f369SMugunthan V N { 9876599f369SMugunthan V N const void *fdt = gd->fdt_blob; 988a61f6a55SMugunthan V N struct udevice *sl_dev; 9896599f369SMugunthan V N int interfaces; 990a61f6a55SMugunthan V N int sec_slave; 991a61f6a55SMugunthan V N int slave; 992a61f6a55SMugunthan V N int ret; 993a61f6a55SMugunthan V N char *slave_name; 994a61f6a55SMugunthan V N 995a61f6a55SMugunthan V N interfaces = fdt_subnode_offset(fdt, gbe, "interfaces"); 996df87e6b1SSimon Glass fdt_for_each_subnode(slave, fdt, interfaces) { 997a61f6a55SMugunthan V N int slave_no; 998a61f6a55SMugunthan V N 999a61f6a55SMugunthan V N slave_no = fdtdec_get_int(fdt, slave, "slave-port", -ENOENT); 1000a61f6a55SMugunthan V N if (slave_no == -ENOENT) 1001a61f6a55SMugunthan V N continue; 1002a61f6a55SMugunthan V N 1003a61f6a55SMugunthan V N if (slave_no == 0) { 1004a61f6a55SMugunthan V N /* This is the current eth device */ 1005a61f6a55SMugunthan V N *gbe_0 = slave; 1006a61f6a55SMugunthan V N } else { 1007a61f6a55SMugunthan V N /* Slave devices to be registered */ 1008a61f6a55SMugunthan V N slave_name = malloc(20); 1009a61f6a55SMugunthan V N snprintf(slave_name, 20, "netcp@slave-%d", slave_no); 1010a61f6a55SMugunthan V N ret = device_bind_driver_to_node(dev, "eth_ks2_sl", 1011a61f6a55SMugunthan V N slave_name, slave, 1012a61f6a55SMugunthan V N &sl_dev); 1013a61f6a55SMugunthan V N if (ret) { 1014a61f6a55SMugunthan V N error("ks2_net - not able to bind slave interfaces\n"); 1015a61f6a55SMugunthan V N return ret; 1016a61f6a55SMugunthan V N } 1017a61f6a55SMugunthan V N } 1018a61f6a55SMugunthan V N } 1019a61f6a55SMugunthan V N 1020a61f6a55SMugunthan V N sec_slave = fdt_subnode_offset(fdt, gbe, "secondary-slave-ports"); 1021df87e6b1SSimon Glass fdt_for_each_subnode(slave, fdt, sec_slave) { 1022a61f6a55SMugunthan V N int slave_no; 1023a61f6a55SMugunthan V N 1024a61f6a55SMugunthan V N slave_no = fdtdec_get_int(fdt, slave, "slave-port", -ENOENT); 1025a61f6a55SMugunthan V N if (slave_no == -ENOENT) 1026a61f6a55SMugunthan V N continue; 1027a61f6a55SMugunthan V N 1028a61f6a55SMugunthan V N /* Slave devices to be registered */ 1029a61f6a55SMugunthan V N slave_name = malloc(20); 1030a61f6a55SMugunthan V N snprintf(slave_name, 20, "netcp@slave-%d", slave_no); 1031a61f6a55SMugunthan V N ret = device_bind_driver_to_node(dev, "eth_ks2_sl", slave_name, 1032a61f6a55SMugunthan V N slave, &sl_dev); 1033a61f6a55SMugunthan V N if (ret) { 1034a61f6a55SMugunthan V N error("ks2_net - not able to bind slave interfaces\n"); 1035a61f6a55SMugunthan V N return ret; 1036a61f6a55SMugunthan V N } 1037a61f6a55SMugunthan V N } 1038a61f6a55SMugunthan V N 1039a61f6a55SMugunthan V N return 0; 1040a61f6a55SMugunthan V N } 1041a61f6a55SMugunthan V N 1042a61f6a55SMugunthan V N static int ks2_eth_parse_slave_interface(int netcp, int slave, 1043a61f6a55SMugunthan V N struct ks2_eth_priv *priv, 1044a61f6a55SMugunthan V N struct eth_pdata *pdata) 1045a61f6a55SMugunthan V N { 1046a61f6a55SMugunthan V N const void *fdt = gd->fdt_blob; 10476599f369SMugunthan V N int mdio; 1048a61f6a55SMugunthan V N int phy; 1049a61f6a55SMugunthan V N int dma_count; 1050a61f6a55SMugunthan V N u32 dma_channel[8]; 10516599f369SMugunthan V N 1052a61f6a55SMugunthan V N priv->slave_port = fdtdec_get_int(fdt, slave, "slave-port", -1); 1053a61f6a55SMugunthan V N priv->net_rx_buffs.rx_flow = priv->slave_port * 8; 10546599f369SMugunthan V N 10556599f369SMugunthan V N /* U-Boot slave port number starts with 1 instead of 0 */ 10566599f369SMugunthan V N priv->slave_port += 1; 10576599f369SMugunthan V N 1058a61f6a55SMugunthan V N dma_count = fdtdec_get_int_array_count(fdt, netcp, 1059a61f6a55SMugunthan V N "ti,navigator-dmas", 1060a61f6a55SMugunthan V N dma_channel, 8); 1061a61f6a55SMugunthan V N 1062a61f6a55SMugunthan V N if (dma_count > (2 * priv->slave_port)) { 1063a61f6a55SMugunthan V N int dma_idx; 1064a61f6a55SMugunthan V N 1065a61f6a55SMugunthan V N dma_idx = priv->slave_port * 2 - 1; 1066a61f6a55SMugunthan V N priv->net_rx_buffs.rx_flow = dma_channel[dma_idx]; 1067a61f6a55SMugunthan V N } 1068a61f6a55SMugunthan V N 1069a61f6a55SMugunthan V N priv->link_type = fdtdec_get_int(fdt, slave, "link-interface", -1); 1070a61f6a55SMugunthan V N 1071a61f6a55SMugunthan V N phy = fdtdec_lookup_phandle(fdt, slave, "phy-handle"); 1072a61f6a55SMugunthan V N if (phy >= 0) { 10736599f369SMugunthan V N priv->phy_addr = fdtdec_get_int(fdt, phy, "reg", -1); 10746599f369SMugunthan V N 10756599f369SMugunthan V N mdio = fdt_parent_offset(fdt, phy); 10766599f369SMugunthan V N if (mdio < 0) { 10776599f369SMugunthan V N error("mdio dt not found\n"); 10786599f369SMugunthan V N return -ENODEV; 10796599f369SMugunthan V N } 10806599f369SMugunthan V N priv->mdio_base = (void *)fdtdec_get_addr(fdt, mdio, "reg"); 1081a61f6a55SMugunthan V N } 10826599f369SMugunthan V N 1083*1de40662SMugunthan V N if (priv->link_type == LINK_TYPE_SGMII_MAC_TO_PHY_MODE) { 10846599f369SMugunthan V N priv->phy_if = PHY_INTERFACE_MODE_SGMII; 10856599f369SMugunthan V N pdata->phy_interface = priv->phy_if; 10866599f369SMugunthan V N priv->sgmii_link_type = SGMII_LINK_MAC_PHY; 10876599f369SMugunthan V N priv->has_mdio = true; 1088*1de40662SMugunthan V N } else if (priv->link_type == LINK_TYPE_RGMII_LINK_MAC_PHY) { 1089*1de40662SMugunthan V N priv->phy_if = PHY_INTERFACE_MODE_RGMII; 1090*1de40662SMugunthan V N pdata->phy_interface = priv->phy_if; 1091*1de40662SMugunthan V N priv->has_mdio = true; 10926599f369SMugunthan V N } 10936599f369SMugunthan V N 1094a61f6a55SMugunthan V N return 0; 1095a61f6a55SMugunthan V N } 1096a61f6a55SMugunthan V N 1097a61f6a55SMugunthan V N static int ks2_sl_eth_ofdata_to_platdata(struct udevice *dev) 1098a61f6a55SMugunthan V N { 1099a61f6a55SMugunthan V N struct ks2_eth_priv *priv = dev_get_priv(dev); 1100a61f6a55SMugunthan V N struct eth_pdata *pdata = dev_get_platdata(dev); 1101a61f6a55SMugunthan V N const void *fdt = gd->fdt_blob; 1102a61f6a55SMugunthan V N int slave = dev->of_offset; 1103a61f6a55SMugunthan V N int interfaces; 1104a61f6a55SMugunthan V N int gbe; 1105a61f6a55SMugunthan V N int netcp_devices; 1106a61f6a55SMugunthan V N int netcp; 1107a61f6a55SMugunthan V N 1108a61f6a55SMugunthan V N interfaces = fdt_parent_offset(fdt, slave); 1109a61f6a55SMugunthan V N gbe = fdt_parent_offset(fdt, interfaces); 1110a61f6a55SMugunthan V N netcp_devices = fdt_parent_offset(fdt, gbe); 1111a61f6a55SMugunthan V N netcp = fdt_parent_offset(fdt, netcp_devices); 1112a61f6a55SMugunthan V N 1113a61f6a55SMugunthan V N ks2_eth_parse_slave_interface(netcp, slave, priv, pdata); 1114a61f6a55SMugunthan V N 1115a61f6a55SMugunthan V N pdata->iobase = fdtdec_get_addr(fdt, netcp, "reg"); 1116a61f6a55SMugunthan V N 1117a61f6a55SMugunthan V N return 0; 1118a61f6a55SMugunthan V N } 1119a61f6a55SMugunthan V N 1120a61f6a55SMugunthan V N static int ks2_eth_ofdata_to_platdata(struct udevice *dev) 1121a61f6a55SMugunthan V N { 1122a61f6a55SMugunthan V N struct ks2_eth_priv *priv = dev_get_priv(dev); 1123a61f6a55SMugunthan V N struct eth_pdata *pdata = dev_get_platdata(dev); 1124a61f6a55SMugunthan V N const void *fdt = gd->fdt_blob; 1125a61f6a55SMugunthan V N int gbe_0 = -ENODEV; 1126a61f6a55SMugunthan V N int netcp_devices; 1127a61f6a55SMugunthan V N int gbe; 1128a61f6a55SMugunthan V N 1129a61f6a55SMugunthan V N netcp_devices = fdt_subnode_offset(fdt, dev->of_offset, 1130a61f6a55SMugunthan V N "netcp-devices"); 1131a61f6a55SMugunthan V N gbe = fdt_subnode_offset(fdt, netcp_devices, "gbe"); 1132a61f6a55SMugunthan V N 1133a61f6a55SMugunthan V N ks2_eth_bind_slaves(dev, gbe, &gbe_0); 1134a61f6a55SMugunthan V N 1135a61f6a55SMugunthan V N ks2_eth_parse_slave_interface(dev->of_offset, gbe_0, priv, pdata); 1136a61f6a55SMugunthan V N 1137a61f6a55SMugunthan V N pdata->iobase = dev_get_addr(dev); 11386599f369SMugunthan V N 11396599f369SMugunthan V N return 0; 11406599f369SMugunthan V N } 11416599f369SMugunthan V N 11426599f369SMugunthan V N static const struct udevice_id ks2_eth_ids[] = { 11436599f369SMugunthan V N { .compatible = "ti,netcp-1.0" }, 11446599f369SMugunthan V N { } 11456599f369SMugunthan V N }; 11466599f369SMugunthan V N 1147a61f6a55SMugunthan V N U_BOOT_DRIVER(eth_ks2_slave) = { 1148a61f6a55SMugunthan V N .name = "eth_ks2_sl", 1149a61f6a55SMugunthan V N .id = UCLASS_ETH, 1150a61f6a55SMugunthan V N .ofdata_to_platdata = ks2_sl_eth_ofdata_to_platdata, 1151a61f6a55SMugunthan V N .probe = ks2_eth_probe, 1152a61f6a55SMugunthan V N .remove = ks2_eth_remove, 1153a61f6a55SMugunthan V N .ops = &ks2_eth_ops, 1154a61f6a55SMugunthan V N .priv_auto_alloc_size = sizeof(struct ks2_eth_priv), 1155a61f6a55SMugunthan V N .platdata_auto_alloc_size = sizeof(struct eth_pdata), 1156a61f6a55SMugunthan V N .flags = DM_FLAG_ALLOC_PRIV_DMA, 1157a61f6a55SMugunthan V N }; 11586599f369SMugunthan V N 11596599f369SMugunthan V N U_BOOT_DRIVER(eth_ks2) = { 11606599f369SMugunthan V N .name = "eth_ks2", 11616599f369SMugunthan V N .id = UCLASS_ETH, 11626599f369SMugunthan V N .of_match = ks2_eth_ids, 11636599f369SMugunthan V N .ofdata_to_platdata = ks2_eth_ofdata_to_platdata, 11646599f369SMugunthan V N .probe = ks2_eth_probe, 11656599f369SMugunthan V N .remove = ks2_eth_remove, 11666599f369SMugunthan V N .ops = &ks2_eth_ops, 11676599f369SMugunthan V N .priv_auto_alloc_size = sizeof(struct ks2_eth_priv), 11686599f369SMugunthan V N .platdata_auto_alloc_size = sizeof(struct eth_pdata), 11696599f369SMugunthan V N .flags = DM_FLAG_ALLOC_PRIV_DMA, 11706599f369SMugunthan V N }; 11714657a2d4SVitaly Andrianov #endif 1172