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 { 596599f369SMugunthan V N LINK_TYPE_MAC_TO_MAC_AUTO = 0, 606599f369SMugunthan V N LINK_TYPE_MAC_TO_PHY_MODE = 1, 616599f369SMugunthan V N LINK_TYPE_MAC_TO_MAC_FORCED_MODE = 2, 626599f369SMugunthan V N LINK_TYPE_MAC_TO_FIBRE_MODE = 3, 636599f369SMugunthan V N LINK_TYPE_MAC_TO_PHY_NO_MDIO_MODE = 4, 646599f369SMugunthan V N LINK_TYPE_10G_MAC_TO_PHY_MODE = 10, 656599f369SMugunthan V N LINK_TYPE_10G_MAC_TO_MAC_FORCED_MODE = 11, 666599f369SMugunthan V N }; 67fc9a8e8dSKaricheri, Muralidharan 686599f369SMugunthan V N #define mac_hi(mac) (((mac)[0] << 0) | ((mac)[1] << 8) | \ 696599f369SMugunthan V N ((mac)[2] << 16) | ((mac)[3] << 24)) 706599f369SMugunthan V N #define mac_lo(mac) (((mac)[4] << 0) | ((mac)[5] << 8)) 71fc9a8e8dSKaricheri, Muralidharan 726599f369SMugunthan V N #ifdef CONFIG_KSNET_NETCP_V1_0 73fc9a8e8dSKaricheri, Muralidharan 746599f369SMugunthan V N #define EMAC_EMACSW_BASE_OFS 0x90800 756599f369SMugunthan V N #define EMAC_EMACSW_PORT_BASE_OFS (EMAC_EMACSW_BASE_OFS + 0x60) 766599f369SMugunthan V N 776599f369SMugunthan V N /* CPSW Switch slave registers */ 786599f369SMugunthan V N #define CPGMACSL_REG_SA_LO 0x10 796599f369SMugunthan V N #define CPGMACSL_REG_SA_HI 0x14 806599f369SMugunthan V N 816599f369SMugunthan V N #define DEVICE_EMACSW_BASE(base, x) ((base) + EMAC_EMACSW_PORT_BASE_OFS + \ 826599f369SMugunthan V N (x) * 0x30) 836599f369SMugunthan V N 846599f369SMugunthan V N #elif defined CONFIG_KSNET_NETCP_V1_5 856599f369SMugunthan V N 866599f369SMugunthan V N #define EMAC_EMACSW_PORT_BASE_OFS 0x222000 876599f369SMugunthan V N 886599f369SMugunthan V N /* CPSW Switch slave registers */ 896599f369SMugunthan V N #define CPGMACSL_REG_SA_LO 0x308 906599f369SMugunthan V N #define CPGMACSL_REG_SA_HI 0x30c 916599f369SMugunthan V N 926599f369SMugunthan V N #define DEVICE_EMACSW_BASE(base, x) ((base) + EMAC_EMACSW_PORT_BASE_OFS + \ 936599f369SMugunthan V N (x) * 0x1000) 946599f369SMugunthan V N 956599f369SMugunthan V N #endif 966599f369SMugunthan V N 976599f369SMugunthan V N 986599f369SMugunthan V N struct ks2_eth_priv { 996599f369SMugunthan V N struct udevice *dev; 1006599f369SMugunthan V N struct phy_device *phydev; 1016599f369SMugunthan V N struct mii_dev *mdio_bus; 1026599f369SMugunthan V N int phy_addr; 1036599f369SMugunthan V N phy_interface_t phy_if; 1046599f369SMugunthan V N int sgmii_link_type; 1056599f369SMugunthan V N void *mdio_base; 1066599f369SMugunthan V N struct rx_buff_desc net_rx_buffs; 1076599f369SMugunthan V N struct pktdma_cfg *netcp_pktdma; 1086599f369SMugunthan V N void *hd; 1096599f369SMugunthan V N int slave_port; 1106599f369SMugunthan V N enum link_type link_type; 1116599f369SMugunthan V N bool emac_open; 1126599f369SMugunthan V N bool has_mdio; 1136599f369SMugunthan V N }; 1146599f369SMugunthan V N #endif 115fc9a8e8dSKaricheri, Muralidharan 116550c5ce6SKhoronzhuk, Ivan /* MDIO */ 117550c5ce6SKhoronzhuk, Ivan 118550c5ce6SKhoronzhuk, Ivan static int keystone2_mdio_reset(struct mii_dev *bus) 119fc9a8e8dSKaricheri, Muralidharan { 120fc9a8e8dSKaricheri, Muralidharan u_int32_t clkdiv; 121550c5ce6SKhoronzhuk, Ivan struct mdio_regs *adap_mdio = bus->priv; 122fc9a8e8dSKaricheri, Muralidharan 123fc9a8e8dSKaricheri, Muralidharan clkdiv = (EMAC_MDIO_BUS_FREQ / EMAC_MDIO_CLOCK_FREQ) - 1; 124fc9a8e8dSKaricheri, Muralidharan 125550c5ce6SKhoronzhuk, Ivan writel((clkdiv & 0xffff) | MDIO_CONTROL_ENABLE | 126550c5ce6SKhoronzhuk, Ivan MDIO_CONTROL_FAULT | MDIO_CONTROL_FAULT_ENABLE, 127fc9a8e8dSKaricheri, Muralidharan &adap_mdio->control); 128fc9a8e8dSKaricheri, Muralidharan 129fc9a8e8dSKaricheri, Muralidharan while (readl(&adap_mdio->control) & MDIO_CONTROL_IDLE) 130fc9a8e8dSKaricheri, Muralidharan ; 131550c5ce6SKhoronzhuk, Ivan 132550c5ce6SKhoronzhuk, Ivan return 0; 133fc9a8e8dSKaricheri, Muralidharan } 134fc9a8e8dSKaricheri, Muralidharan 135550c5ce6SKhoronzhuk, Ivan /** 136550c5ce6SKhoronzhuk, Ivan * keystone2_mdio_read - read a PHY register via MDIO interface. 137550c5ce6SKhoronzhuk, Ivan * Blocks until operation is complete. 138550c5ce6SKhoronzhuk, Ivan */ 139550c5ce6SKhoronzhuk, Ivan static int keystone2_mdio_read(struct mii_dev *bus, 140550c5ce6SKhoronzhuk, Ivan int addr, int devad, int reg) 141fc9a8e8dSKaricheri, Muralidharan { 142fc9a8e8dSKaricheri, Muralidharan int tmp; 143550c5ce6SKhoronzhuk, Ivan struct mdio_regs *adap_mdio = bus->priv; 144fc9a8e8dSKaricheri, Muralidharan 145fc9a8e8dSKaricheri, Muralidharan while (readl(&adap_mdio->useraccess0) & MDIO_USERACCESS0_GO) 146fc9a8e8dSKaricheri, Muralidharan ; 147fc9a8e8dSKaricheri, Muralidharan 148550c5ce6SKhoronzhuk, Ivan writel(MDIO_USERACCESS0_GO | MDIO_USERACCESS0_WRITE_READ | 149550c5ce6SKhoronzhuk, Ivan ((reg & 0x1f) << 21) | ((addr & 0x1f) << 16), 150fc9a8e8dSKaricheri, Muralidharan &adap_mdio->useraccess0); 151fc9a8e8dSKaricheri, Muralidharan 152fc9a8e8dSKaricheri, Muralidharan /* Wait for command to complete */ 153fc9a8e8dSKaricheri, Muralidharan while ((tmp = readl(&adap_mdio->useraccess0)) & MDIO_USERACCESS0_GO) 154fc9a8e8dSKaricheri, Muralidharan ; 155fc9a8e8dSKaricheri, Muralidharan 156550c5ce6SKhoronzhuk, Ivan if (tmp & MDIO_USERACCESS0_ACK) 157550c5ce6SKhoronzhuk, Ivan return tmp & 0xffff; 158fc9a8e8dSKaricheri, Muralidharan 159fc9a8e8dSKaricheri, Muralidharan return -1; 160fc9a8e8dSKaricheri, Muralidharan } 161fc9a8e8dSKaricheri, Muralidharan 162550c5ce6SKhoronzhuk, Ivan /** 163550c5ce6SKhoronzhuk, Ivan * keystone2_mdio_write - write to a PHY register via MDIO interface. 164fc9a8e8dSKaricheri, Muralidharan * Blocks until operation is complete. 165fc9a8e8dSKaricheri, Muralidharan */ 166550c5ce6SKhoronzhuk, Ivan static int keystone2_mdio_write(struct mii_dev *bus, 167550c5ce6SKhoronzhuk, Ivan int addr, int devad, int reg, u16 val) 168fc9a8e8dSKaricheri, Muralidharan { 169550c5ce6SKhoronzhuk, Ivan struct mdio_regs *adap_mdio = bus->priv; 170550c5ce6SKhoronzhuk, Ivan 171fc9a8e8dSKaricheri, Muralidharan while (readl(&adap_mdio->useraccess0) & MDIO_USERACCESS0_GO) 172fc9a8e8dSKaricheri, Muralidharan ; 173fc9a8e8dSKaricheri, Muralidharan 174550c5ce6SKhoronzhuk, Ivan writel(MDIO_USERACCESS0_GO | MDIO_USERACCESS0_WRITE_WRITE | 175550c5ce6SKhoronzhuk, Ivan ((reg & 0x1f) << 21) | ((addr & 0x1f) << 16) | 176550c5ce6SKhoronzhuk, Ivan (val & 0xffff), &adap_mdio->useraccess0); 177fc9a8e8dSKaricheri, Muralidharan 178fc9a8e8dSKaricheri, Muralidharan /* Wait for command to complete */ 179fc9a8e8dSKaricheri, Muralidharan while (readl(&adap_mdio->useraccess0) & MDIO_USERACCESS0_GO) 180fc9a8e8dSKaricheri, Muralidharan ; 181fc9a8e8dSKaricheri, Muralidharan 182fc9a8e8dSKaricheri, Muralidharan return 0; 183fc9a8e8dSKaricheri, Muralidharan } 184fc9a8e8dSKaricheri, Muralidharan 1856599f369SMugunthan V N #ifndef CONFIG_DM_ETH 186fc9a8e8dSKaricheri, Muralidharan static void __attribute__((unused)) 187fc9a8e8dSKaricheri, Muralidharan keystone2_eth_gigabit_enable(struct eth_device *dev) 188fc9a8e8dSKaricheri, Muralidharan { 189fc9a8e8dSKaricheri, Muralidharan u_int16_t data; 190fc9a8e8dSKaricheri, Muralidharan struct eth_priv_t *eth_priv = (struct eth_priv_t *)dev->priv; 191fc9a8e8dSKaricheri, Muralidharan 192fc9a8e8dSKaricheri, Muralidharan if (sys_has_mdio) { 193550c5ce6SKhoronzhuk, Ivan data = keystone2_mdio_read(mdio_bus, eth_priv->phy_addr, 194550c5ce6SKhoronzhuk, Ivan MDIO_DEVAD_NONE, 0); 195550c5ce6SKhoronzhuk, Ivan /* speed selection MSB */ 196550c5ce6SKhoronzhuk, Ivan if (!(data & (1 << 6))) 197fc9a8e8dSKaricheri, Muralidharan return; 198fc9a8e8dSKaricheri, Muralidharan } 199fc9a8e8dSKaricheri, Muralidharan 200fc9a8e8dSKaricheri, Muralidharan /* 201fc9a8e8dSKaricheri, Muralidharan * Check if link detected is giga-bit 202fc9a8e8dSKaricheri, Muralidharan * If Gigabit mode detected, enable gigbit in MAC 203fc9a8e8dSKaricheri, Muralidharan */ 204b2cfe322SHao Zhang writel(readl(DEVICE_EMACSL_BASE(eth_priv->slave_port - 1) + 205b2cfe322SHao Zhang CPGMACSL_REG_CTL) | 206fc9a8e8dSKaricheri, Muralidharan EMAC_MACCONTROL_GIGFORCE | EMAC_MACCONTROL_GIGABIT_ENABLE, 207b2cfe322SHao Zhang DEVICE_EMACSL_BASE(eth_priv->slave_port - 1) + CPGMACSL_REG_CTL); 208fc9a8e8dSKaricheri, Muralidharan } 2096599f369SMugunthan V N #else 2106599f369SMugunthan V N static void __attribute__((unused)) 2116599f369SMugunthan V N keystone2_eth_gigabit_enable(struct udevice *dev) 2126599f369SMugunthan V N { 2136599f369SMugunthan V N struct ks2_eth_priv *priv = dev_get_priv(dev); 2146599f369SMugunthan V N u_int16_t data; 2156599f369SMugunthan V N 2166599f369SMugunthan V N if (priv->has_mdio) { 2176599f369SMugunthan V N data = keystone2_mdio_read(priv->mdio_bus, priv->phy_addr, 2186599f369SMugunthan V N MDIO_DEVAD_NONE, 0); 2196599f369SMugunthan V N /* speed selection MSB */ 2206599f369SMugunthan V N if (!(data & (1 << 6))) 2216599f369SMugunthan V N return; 2226599f369SMugunthan V N } 2236599f369SMugunthan V N 2246599f369SMugunthan V N /* 2256599f369SMugunthan V N * Check if link detected is giga-bit 2266599f369SMugunthan V N * If Gigabit mode detected, enable gigbit in MAC 2276599f369SMugunthan V N */ 2286599f369SMugunthan V N writel(readl(DEVICE_EMACSL_BASE(priv->slave_port - 1) + 2296599f369SMugunthan V N CPGMACSL_REG_CTL) | 2306599f369SMugunthan V N EMAC_MACCONTROL_GIGFORCE | EMAC_MACCONTROL_GIGABIT_ENABLE, 2316599f369SMugunthan V N DEVICE_EMACSL_BASE(priv->slave_port - 1) + CPGMACSL_REG_CTL); 2326599f369SMugunthan V N } 2336599f369SMugunthan V N #endif 234fc9a8e8dSKaricheri, Muralidharan 2354657a2d4SVitaly Andrianov #ifdef CONFIG_SOC_K2G 2364657a2d4SVitaly Andrianov int keystone_rgmii_config(struct phy_device *phy_dev) 2374657a2d4SVitaly Andrianov { 2384657a2d4SVitaly Andrianov unsigned int i, status; 2394657a2d4SVitaly Andrianov 2404657a2d4SVitaly Andrianov i = 0; 2414657a2d4SVitaly Andrianov do { 2424657a2d4SVitaly Andrianov if (i > SGMII_ANEG_TIMEOUT) { 2434657a2d4SVitaly Andrianov puts(" TIMEOUT !\n"); 2444657a2d4SVitaly Andrianov phy_dev->link = 0; 2454657a2d4SVitaly Andrianov return 0; 2464657a2d4SVitaly Andrianov } 2474657a2d4SVitaly Andrianov 2484657a2d4SVitaly Andrianov if (ctrlc()) { 2494657a2d4SVitaly Andrianov puts("user interrupt!\n"); 2504657a2d4SVitaly Andrianov phy_dev->link = 0; 2514657a2d4SVitaly Andrianov return -EINTR; 2524657a2d4SVitaly Andrianov } 2534657a2d4SVitaly Andrianov 2544657a2d4SVitaly Andrianov if ((i++ % 500) == 0) 2554657a2d4SVitaly Andrianov printf("."); 2564657a2d4SVitaly Andrianov 2574657a2d4SVitaly Andrianov udelay(1000); /* 1 ms */ 2584657a2d4SVitaly Andrianov status = readl(RGMII_STATUS_REG); 2594657a2d4SVitaly Andrianov } while (!(status & RGMII_REG_STATUS_LINK)); 2604657a2d4SVitaly Andrianov 2614657a2d4SVitaly Andrianov puts(" done\n"); 2624657a2d4SVitaly Andrianov 2634657a2d4SVitaly Andrianov return 0; 2644657a2d4SVitaly Andrianov } 2654657a2d4SVitaly Andrianov #else 266c05d05e7SKhoronzhuk, Ivan int keystone_sgmii_config(struct phy_device *phy_dev, int port, int interface) 267fc9a8e8dSKaricheri, Muralidharan { 268fc9a8e8dSKaricheri, Muralidharan unsigned int i, status, mask; 269fc9a8e8dSKaricheri, Muralidharan unsigned int mr_adv_ability, control; 270fc9a8e8dSKaricheri, Muralidharan 271fc9a8e8dSKaricheri, Muralidharan switch (interface) { 272fc9a8e8dSKaricheri, Muralidharan case SGMII_LINK_MAC_MAC_AUTONEG: 273fc9a8e8dSKaricheri, Muralidharan mr_adv_ability = (SGMII_REG_MR_ADV_ENABLE | 274fc9a8e8dSKaricheri, Muralidharan SGMII_REG_MR_ADV_LINK | 275fc9a8e8dSKaricheri, Muralidharan SGMII_REG_MR_ADV_FULL_DUPLEX | 276fc9a8e8dSKaricheri, Muralidharan SGMII_REG_MR_ADV_GIG_MODE); 277fc9a8e8dSKaricheri, Muralidharan control = (SGMII_REG_CONTROL_MASTER | 278fc9a8e8dSKaricheri, Muralidharan SGMII_REG_CONTROL_AUTONEG); 279fc9a8e8dSKaricheri, Muralidharan 280fc9a8e8dSKaricheri, Muralidharan break; 281fc9a8e8dSKaricheri, Muralidharan case SGMII_LINK_MAC_PHY: 282fc9a8e8dSKaricheri, Muralidharan case SGMII_LINK_MAC_PHY_FORCED: 283fc9a8e8dSKaricheri, Muralidharan mr_adv_ability = SGMII_REG_MR_ADV_ENABLE; 284fc9a8e8dSKaricheri, Muralidharan control = SGMII_REG_CONTROL_AUTONEG; 285fc9a8e8dSKaricheri, Muralidharan 286fc9a8e8dSKaricheri, Muralidharan break; 287fc9a8e8dSKaricheri, Muralidharan case SGMII_LINK_MAC_MAC_FORCED: 288fc9a8e8dSKaricheri, Muralidharan mr_adv_ability = (SGMII_REG_MR_ADV_ENABLE | 289fc9a8e8dSKaricheri, Muralidharan SGMII_REG_MR_ADV_LINK | 290fc9a8e8dSKaricheri, Muralidharan SGMII_REG_MR_ADV_FULL_DUPLEX | 291fc9a8e8dSKaricheri, Muralidharan SGMII_REG_MR_ADV_GIG_MODE); 292fc9a8e8dSKaricheri, Muralidharan control = SGMII_REG_CONTROL_MASTER; 293fc9a8e8dSKaricheri, Muralidharan 294fc9a8e8dSKaricheri, Muralidharan break; 295fc9a8e8dSKaricheri, Muralidharan case SGMII_LINK_MAC_FIBER: 296fc9a8e8dSKaricheri, Muralidharan mr_adv_ability = 0x20; 297fc9a8e8dSKaricheri, Muralidharan control = SGMII_REG_CONTROL_AUTONEG; 298fc9a8e8dSKaricheri, Muralidharan 299fc9a8e8dSKaricheri, Muralidharan break; 300fc9a8e8dSKaricheri, Muralidharan default: 301fc9a8e8dSKaricheri, Muralidharan mr_adv_ability = SGMII_REG_MR_ADV_ENABLE; 302fc9a8e8dSKaricheri, Muralidharan control = SGMII_REG_CONTROL_AUTONEG; 303fc9a8e8dSKaricheri, Muralidharan } 304fc9a8e8dSKaricheri, Muralidharan 305fc9a8e8dSKaricheri, Muralidharan __raw_writel(0, SGMII_CTL_REG(port)); 306fc9a8e8dSKaricheri, Muralidharan 307fc9a8e8dSKaricheri, Muralidharan /* 308fc9a8e8dSKaricheri, Muralidharan * Wait for the SerDes pll to lock, 309fc9a8e8dSKaricheri, Muralidharan * but don't trap if lock is never read 310fc9a8e8dSKaricheri, Muralidharan */ 311fc9a8e8dSKaricheri, Muralidharan for (i = 0; i < 1000; i++) { 312fc9a8e8dSKaricheri, Muralidharan udelay(2000); 313fc9a8e8dSKaricheri, Muralidharan status = __raw_readl(SGMII_STATUS_REG(port)); 314fc9a8e8dSKaricheri, Muralidharan if ((status & SGMII_REG_STATUS_LOCK) != 0) 315fc9a8e8dSKaricheri, Muralidharan break; 316fc9a8e8dSKaricheri, Muralidharan } 317fc9a8e8dSKaricheri, Muralidharan 318fc9a8e8dSKaricheri, Muralidharan __raw_writel(mr_adv_ability, SGMII_MRADV_REG(port)); 319fc9a8e8dSKaricheri, Muralidharan __raw_writel(control, SGMII_CTL_REG(port)); 320fc9a8e8dSKaricheri, Muralidharan 321fc9a8e8dSKaricheri, Muralidharan 322fc9a8e8dSKaricheri, Muralidharan mask = SGMII_REG_STATUS_LINK; 323fc9a8e8dSKaricheri, Muralidharan 324fc9a8e8dSKaricheri, Muralidharan if (control & SGMII_REG_CONTROL_AUTONEG) 325fc9a8e8dSKaricheri, Muralidharan mask |= SGMII_REG_STATUS_AUTONEG; 326fc9a8e8dSKaricheri, Muralidharan 327fc9a8e8dSKaricheri, Muralidharan status = __raw_readl(SGMII_STATUS_REG(port)); 328fc9a8e8dSKaricheri, Muralidharan if ((status & mask) == mask) 329c05d05e7SKhoronzhuk, Ivan return 0; 330c05d05e7SKhoronzhuk, Ivan 331c05d05e7SKhoronzhuk, Ivan printf("\n%s Waiting for SGMII auto negotiation to complete", 332c05d05e7SKhoronzhuk, Ivan phy_dev->dev->name); 333c05d05e7SKhoronzhuk, Ivan while ((status & mask) != mask) { 334c05d05e7SKhoronzhuk, Ivan /* 335c05d05e7SKhoronzhuk, Ivan * Timeout reached ? 336c05d05e7SKhoronzhuk, Ivan */ 337c05d05e7SKhoronzhuk, Ivan if (i > SGMII_ANEG_TIMEOUT) { 338c05d05e7SKhoronzhuk, Ivan puts(" TIMEOUT !\n"); 339c05d05e7SKhoronzhuk, Ivan phy_dev->link = 0; 340c05d05e7SKhoronzhuk, Ivan return 0; 341fc9a8e8dSKaricheri, Muralidharan } 342fc9a8e8dSKaricheri, Muralidharan 343c05d05e7SKhoronzhuk, Ivan if (ctrlc()) { 344c05d05e7SKhoronzhuk, Ivan puts("user interrupt!\n"); 345c05d05e7SKhoronzhuk, Ivan phy_dev->link = 0; 346c05d05e7SKhoronzhuk, Ivan return -EINTR; 347c05d05e7SKhoronzhuk, Ivan } 348c05d05e7SKhoronzhuk, Ivan 349c05d05e7SKhoronzhuk, Ivan if ((i++ % 500) == 0) 350c05d05e7SKhoronzhuk, Ivan printf("."); 351c05d05e7SKhoronzhuk, Ivan 352c05d05e7SKhoronzhuk, Ivan udelay(1000); /* 1 ms */ 353c05d05e7SKhoronzhuk, Ivan status = __raw_readl(SGMII_STATUS_REG(port)); 354c05d05e7SKhoronzhuk, Ivan } 355c05d05e7SKhoronzhuk, Ivan puts(" done\n"); 356c05d05e7SKhoronzhuk, Ivan 357fc9a8e8dSKaricheri, Muralidharan return 0; 358fc9a8e8dSKaricheri, Muralidharan } 3594657a2d4SVitaly Andrianov #endif 360fc9a8e8dSKaricheri, Muralidharan 361fc9a8e8dSKaricheri, Muralidharan int mac_sl_reset(u32 port) 362fc9a8e8dSKaricheri, Muralidharan { 363fc9a8e8dSKaricheri, Muralidharan u32 i, v; 364fc9a8e8dSKaricheri, Muralidharan 365fc9a8e8dSKaricheri, Muralidharan if (port >= DEVICE_N_GMACSL_PORTS) 366fc9a8e8dSKaricheri, Muralidharan return GMACSL_RET_INVALID_PORT; 367fc9a8e8dSKaricheri, Muralidharan 368fc9a8e8dSKaricheri, Muralidharan /* Set the soft reset bit */ 369e6c9428aSKhoronzhuk, Ivan writel(CPGMAC_REG_RESET_VAL_RESET, 370e6c9428aSKhoronzhuk, Ivan DEVICE_EMACSL_BASE(port) + CPGMACSL_REG_RESET); 371fc9a8e8dSKaricheri, Muralidharan 372fc9a8e8dSKaricheri, Muralidharan /* Wait for the bit to clear */ 373fc9a8e8dSKaricheri, Muralidharan for (i = 0; i < DEVICE_EMACSL_RESET_POLL_COUNT; i++) { 374e6c9428aSKhoronzhuk, Ivan v = readl(DEVICE_EMACSL_BASE(port) + CPGMACSL_REG_RESET); 375fc9a8e8dSKaricheri, Muralidharan if ((v & CPGMAC_REG_RESET_VAL_RESET_MASK) != 376fc9a8e8dSKaricheri, Muralidharan CPGMAC_REG_RESET_VAL_RESET) 377fc9a8e8dSKaricheri, Muralidharan return GMACSL_RET_OK; 378fc9a8e8dSKaricheri, Muralidharan } 379fc9a8e8dSKaricheri, Muralidharan 380fc9a8e8dSKaricheri, Muralidharan /* Timeout on the reset */ 381fc9a8e8dSKaricheri, Muralidharan return GMACSL_RET_WARN_RESET_INCOMPLETE; 382fc9a8e8dSKaricheri, Muralidharan } 383fc9a8e8dSKaricheri, Muralidharan 384fc9a8e8dSKaricheri, Muralidharan int mac_sl_config(u_int16_t port, struct mac_sl_cfg *cfg) 385fc9a8e8dSKaricheri, Muralidharan { 386fc9a8e8dSKaricheri, Muralidharan u32 v, i; 387fc9a8e8dSKaricheri, Muralidharan int ret = GMACSL_RET_OK; 388fc9a8e8dSKaricheri, Muralidharan 389fc9a8e8dSKaricheri, Muralidharan if (port >= DEVICE_N_GMACSL_PORTS) 390fc9a8e8dSKaricheri, Muralidharan return GMACSL_RET_INVALID_PORT; 391fc9a8e8dSKaricheri, Muralidharan 392fc9a8e8dSKaricheri, Muralidharan if (cfg->max_rx_len > CPGMAC_REG_MAXLEN_LEN) { 393fc9a8e8dSKaricheri, Muralidharan cfg->max_rx_len = CPGMAC_REG_MAXLEN_LEN; 394fc9a8e8dSKaricheri, Muralidharan ret = GMACSL_RET_WARN_MAXLEN_TOO_BIG; 395fc9a8e8dSKaricheri, Muralidharan } 396fc9a8e8dSKaricheri, Muralidharan 397fc9a8e8dSKaricheri, Muralidharan /* Must wait if the device is undergoing reset */ 398fc9a8e8dSKaricheri, Muralidharan for (i = 0; i < DEVICE_EMACSL_RESET_POLL_COUNT; i++) { 399e6c9428aSKhoronzhuk, Ivan v = readl(DEVICE_EMACSL_BASE(port) + CPGMACSL_REG_RESET); 400fc9a8e8dSKaricheri, Muralidharan if ((v & CPGMAC_REG_RESET_VAL_RESET_MASK) != 401fc9a8e8dSKaricheri, Muralidharan CPGMAC_REG_RESET_VAL_RESET) 402fc9a8e8dSKaricheri, Muralidharan break; 403fc9a8e8dSKaricheri, Muralidharan } 404fc9a8e8dSKaricheri, Muralidharan 405fc9a8e8dSKaricheri, Muralidharan if (i == DEVICE_EMACSL_RESET_POLL_COUNT) 406fc9a8e8dSKaricheri, Muralidharan return GMACSL_RET_CONFIG_FAIL_RESET_ACTIVE; 407fc9a8e8dSKaricheri, Muralidharan 408e6c9428aSKhoronzhuk, Ivan writel(cfg->max_rx_len, DEVICE_EMACSL_BASE(port) + CPGMACSL_REG_MAXLEN); 409e6c9428aSKhoronzhuk, Ivan writel(cfg->ctl, DEVICE_EMACSL_BASE(port) + CPGMACSL_REG_CTL); 410fc9a8e8dSKaricheri, Muralidharan 4114657a2d4SVitaly Andrianov #ifndef CONFIG_SOC_K2HK 412ff11c769SKhoronzhuk, Ivan /* Map RX packet flow priority to 0 */ 413ff11c769SKhoronzhuk, Ivan writel(0, DEVICE_EMACSL_BASE(port) + CPGMACSL_REG_RX_PRI_MAP); 414ff11c769SKhoronzhuk, Ivan #endif 415ff11c769SKhoronzhuk, Ivan 416fc9a8e8dSKaricheri, Muralidharan return ret; 417fc9a8e8dSKaricheri, Muralidharan } 418fc9a8e8dSKaricheri, Muralidharan 419fc9a8e8dSKaricheri, Muralidharan int ethss_config(u32 ctl, u32 max_pkt_size) 420fc9a8e8dSKaricheri, Muralidharan { 421fc9a8e8dSKaricheri, Muralidharan u32 i; 422fc9a8e8dSKaricheri, Muralidharan 423fc9a8e8dSKaricheri, Muralidharan /* Max length register */ 424e6c9428aSKhoronzhuk, Ivan writel(max_pkt_size, DEVICE_CPSW_BASE + CPSW_REG_MAXLEN); 425fc9a8e8dSKaricheri, Muralidharan 426fc9a8e8dSKaricheri, Muralidharan /* Control register */ 427e6c9428aSKhoronzhuk, Ivan writel(ctl, DEVICE_CPSW_BASE + CPSW_REG_CTL); 428fc9a8e8dSKaricheri, Muralidharan 429fc9a8e8dSKaricheri, Muralidharan /* All statistics enabled by default */ 430e6c9428aSKhoronzhuk, Ivan writel(CPSW_REG_VAL_STAT_ENABLE_ALL, 431e6c9428aSKhoronzhuk, Ivan DEVICE_CPSW_BASE + CPSW_REG_STAT_PORT_EN); 432fc9a8e8dSKaricheri, Muralidharan 433fc9a8e8dSKaricheri, Muralidharan /* Reset and enable the ALE */ 434e6c9428aSKhoronzhuk, Ivan writel(CPSW_REG_VAL_ALE_CTL_RESET_AND_ENABLE | 435e6c9428aSKhoronzhuk, Ivan CPSW_REG_VAL_ALE_CTL_BYPASS, 436e6c9428aSKhoronzhuk, Ivan DEVICE_CPSW_BASE + CPSW_REG_ALE_CONTROL); 437fc9a8e8dSKaricheri, Muralidharan 438fc9a8e8dSKaricheri, Muralidharan /* All ports put into forward mode */ 439fc9a8e8dSKaricheri, Muralidharan for (i = 0; i < DEVICE_CPSW_NUM_PORTS; i++) 440e6c9428aSKhoronzhuk, Ivan writel(CPSW_REG_VAL_PORTCTL_FORWARD_MODE, 441e6c9428aSKhoronzhuk, Ivan DEVICE_CPSW_BASE + CPSW_REG_ALE_PORTCTL(i)); 442fc9a8e8dSKaricheri, Muralidharan 443fc9a8e8dSKaricheri, Muralidharan return 0; 444fc9a8e8dSKaricheri, Muralidharan } 445fc9a8e8dSKaricheri, Muralidharan 446fc9a8e8dSKaricheri, Muralidharan int ethss_start(void) 447fc9a8e8dSKaricheri, Muralidharan { 448fc9a8e8dSKaricheri, Muralidharan int i; 449fc9a8e8dSKaricheri, Muralidharan struct mac_sl_cfg cfg; 450fc9a8e8dSKaricheri, Muralidharan 451fc9a8e8dSKaricheri, Muralidharan cfg.max_rx_len = MAX_SIZE_STREAM_BUFFER; 452fc9a8e8dSKaricheri, Muralidharan cfg.ctl = GMACSL_ENABLE | GMACSL_RX_ENABLE_EXT_CTL; 453fc9a8e8dSKaricheri, Muralidharan 454fc9a8e8dSKaricheri, Muralidharan for (i = 0; i < DEVICE_N_GMACSL_PORTS; i++) { 455fc9a8e8dSKaricheri, Muralidharan mac_sl_reset(i); 456fc9a8e8dSKaricheri, Muralidharan mac_sl_config(i, &cfg); 457fc9a8e8dSKaricheri, Muralidharan } 458fc9a8e8dSKaricheri, Muralidharan 459fc9a8e8dSKaricheri, Muralidharan return 0; 460fc9a8e8dSKaricheri, Muralidharan } 461fc9a8e8dSKaricheri, Muralidharan 462fc9a8e8dSKaricheri, Muralidharan int ethss_stop(void) 463fc9a8e8dSKaricheri, Muralidharan { 464fc9a8e8dSKaricheri, Muralidharan int i; 465fc9a8e8dSKaricheri, Muralidharan 466fc9a8e8dSKaricheri, Muralidharan for (i = 0; i < DEVICE_N_GMACSL_PORTS; i++) 467fc9a8e8dSKaricheri, Muralidharan mac_sl_reset(i); 468fc9a8e8dSKaricheri, Muralidharan 469fc9a8e8dSKaricheri, Muralidharan return 0; 470fc9a8e8dSKaricheri, Muralidharan } 471fc9a8e8dSKaricheri, Muralidharan 4726599f369SMugunthan V N struct ks2_serdes ks2_serdes_sgmii_156p25mhz = { 4736599f369SMugunthan V N .clk = SERDES_CLOCK_156P25M, 4746599f369SMugunthan V N .rate = SERDES_RATE_5G, 4756599f369SMugunthan V N .rate_mode = SERDES_QUARTER_RATE, 4766599f369SMugunthan V N .intf = SERDES_PHY_SGMII, 4776599f369SMugunthan V N .loopback = 0, 4786599f369SMugunthan V N }; 4796599f369SMugunthan V N 4806599f369SMugunthan V N #ifndef CONFIG_SOC_K2G 4816599f369SMugunthan V N static void keystone2_net_serdes_setup(void) 4826599f369SMugunthan V N { 4836599f369SMugunthan V N ks2_serdes_init(CONFIG_KSNET_SERDES_SGMII_BASE, 4846599f369SMugunthan V N &ks2_serdes_sgmii_156p25mhz, 4856599f369SMugunthan V N CONFIG_KSNET_SERDES_LANES_PER_SGMII); 4866599f369SMugunthan V N 4876599f369SMugunthan V N #if defined(CONFIG_SOC_K2E) || defined(CONFIG_SOC_K2L) 4886599f369SMugunthan V N ks2_serdes_init(CONFIG_KSNET_SERDES_SGMII2_BASE, 4896599f369SMugunthan V N &ks2_serdes_sgmii_156p25mhz, 4906599f369SMugunthan V N CONFIG_KSNET_SERDES_LANES_PER_SGMII); 4916599f369SMugunthan V N #endif 4926599f369SMugunthan V N 4936599f369SMugunthan V N /* wait till setup */ 4946599f369SMugunthan V N udelay(5000); 4956599f369SMugunthan V N } 4966599f369SMugunthan V N #endif 4976599f369SMugunthan V N 4986599f369SMugunthan V N #ifndef CONFIG_DM_ETH 4996599f369SMugunthan V N 5006599f369SMugunthan V N int keystone2_eth_read_mac_addr(struct eth_device *dev) 5016599f369SMugunthan V N { 5026599f369SMugunthan V N struct eth_priv_t *eth_priv; 5036599f369SMugunthan V N u32 maca = 0; 5046599f369SMugunthan V N u32 macb = 0; 5056599f369SMugunthan V N 5066599f369SMugunthan V N eth_priv = (struct eth_priv_t *)dev->priv; 5076599f369SMugunthan V N 5086599f369SMugunthan V N /* Read the e-fuse mac address */ 5096599f369SMugunthan V N if (eth_priv->slave_port == 1) { 5106599f369SMugunthan V N maca = __raw_readl(MAC_ID_BASE_ADDR); 5116599f369SMugunthan V N macb = __raw_readl(MAC_ID_BASE_ADDR + 4); 5126599f369SMugunthan V N } 5136599f369SMugunthan V N 5146599f369SMugunthan V N dev->enetaddr[0] = (macb >> 8) & 0xff; 5156599f369SMugunthan V N dev->enetaddr[1] = (macb >> 0) & 0xff; 5166599f369SMugunthan V N dev->enetaddr[2] = (maca >> 24) & 0xff; 5176599f369SMugunthan V N dev->enetaddr[3] = (maca >> 16) & 0xff; 5186599f369SMugunthan V N dev->enetaddr[4] = (maca >> 8) & 0xff; 5196599f369SMugunthan V N dev->enetaddr[5] = (maca >> 0) & 0xff; 5206599f369SMugunthan V N 5216599f369SMugunthan V N return 0; 5226599f369SMugunthan V N } 5236599f369SMugunthan V N 524fc9a8e8dSKaricheri, Muralidharan int32_t cpmac_drv_send(u32 *buffer, int num_bytes, int slave_port_num) 525fc9a8e8dSKaricheri, Muralidharan { 526fc9a8e8dSKaricheri, Muralidharan if (num_bytes < EMAC_MIN_ETHERNET_PKT_SIZE) 527fc9a8e8dSKaricheri, Muralidharan num_bytes = EMAC_MIN_ETHERNET_PKT_SIZE; 528fc9a8e8dSKaricheri, Muralidharan 5299ea9021aSKhoronzhuk, Ivan return ksnav_send(&netcp_pktdma, buffer, 5309ea9021aSKhoronzhuk, Ivan num_bytes, (slave_port_num) << 16); 531fc9a8e8dSKaricheri, Muralidharan } 532fc9a8e8dSKaricheri, Muralidharan 533fc9a8e8dSKaricheri, Muralidharan /* Eth device open */ 534fc9a8e8dSKaricheri, Muralidharan static int keystone2_eth_open(struct eth_device *dev, bd_t *bis) 535fc9a8e8dSKaricheri, Muralidharan { 536fc9a8e8dSKaricheri, Muralidharan struct eth_priv_t *eth_priv = (struct eth_priv_t *)dev->priv; 5373fe93623SKhoronzhuk, Ivan struct phy_device *phy_dev = eth_priv->phy_dev; 538fc9a8e8dSKaricheri, Muralidharan 539fc9a8e8dSKaricheri, Muralidharan debug("+ emac_open\n"); 540fc9a8e8dSKaricheri, Muralidharan 541fc9a8e8dSKaricheri, Muralidharan net_rx_buffs.rx_flow = eth_priv->rx_flow; 542fc9a8e8dSKaricheri, Muralidharan 543fc9a8e8dSKaricheri, Muralidharan sys_has_mdio = 544fc9a8e8dSKaricheri, Muralidharan (eth_priv->sgmii_link_type == SGMII_LINK_MAC_PHY) ? 1 : 0; 545fc9a8e8dSKaricheri, Muralidharan 5466c0fb41aSKhoronzhuk, Ivan if (sys_has_mdio) 5476c0fb41aSKhoronzhuk, Ivan keystone2_mdio_reset(mdio_bus); 5486c0fb41aSKhoronzhuk, Ivan 5494657a2d4SVitaly Andrianov #ifdef CONFIG_SOC_K2G 5504657a2d4SVitaly Andrianov keystone_rgmii_config(phy_dev); 5514657a2d4SVitaly Andrianov #else 552c05d05e7SKhoronzhuk, Ivan keystone_sgmii_config(phy_dev, eth_priv->slave_port - 1, 553fc9a8e8dSKaricheri, Muralidharan eth_priv->sgmii_link_type); 5544657a2d4SVitaly Andrianov #endif 555fc9a8e8dSKaricheri, Muralidharan 556fc9a8e8dSKaricheri, Muralidharan udelay(10000); 557fc9a8e8dSKaricheri, Muralidharan 558fc9a8e8dSKaricheri, Muralidharan /* On chip switch configuration */ 559fc9a8e8dSKaricheri, Muralidharan ethss_config(target_get_switch_ctl(), SWITCH_MAX_PKT_SIZE); 560fc9a8e8dSKaricheri, Muralidharan 561fc9a8e8dSKaricheri, Muralidharan /* TODO: add error handling code */ 562fc9a8e8dSKaricheri, Muralidharan if (qm_init()) { 563fc9a8e8dSKaricheri, Muralidharan printf("ERROR: qm_init()\n"); 564fc9a8e8dSKaricheri, Muralidharan return -1; 565fc9a8e8dSKaricheri, Muralidharan } 5669ea9021aSKhoronzhuk, Ivan if (ksnav_init(&netcp_pktdma, &net_rx_buffs)) { 567fc9a8e8dSKaricheri, Muralidharan qm_close(); 568fc9a8e8dSKaricheri, Muralidharan printf("ERROR: netcp_init()\n"); 569fc9a8e8dSKaricheri, Muralidharan return -1; 570fc9a8e8dSKaricheri, Muralidharan } 571fc9a8e8dSKaricheri, Muralidharan 572fc9a8e8dSKaricheri, Muralidharan /* 573fc9a8e8dSKaricheri, Muralidharan * Streaming switch configuration. If not present this 574fc9a8e8dSKaricheri, Muralidharan * statement is defined to void in target.h. 575fc9a8e8dSKaricheri, Muralidharan * If present this is usually defined to a series of register writes 576fc9a8e8dSKaricheri, Muralidharan */ 577fc9a8e8dSKaricheri, Muralidharan hw_config_streaming_switch(); 578fc9a8e8dSKaricheri, Muralidharan 579fc9a8e8dSKaricheri, Muralidharan if (sys_has_mdio) { 580550c5ce6SKhoronzhuk, Ivan keystone2_mdio_reset(mdio_bus); 581fc9a8e8dSKaricheri, Muralidharan 5823fe93623SKhoronzhuk, Ivan phy_startup(phy_dev); 5833fe93623SKhoronzhuk, Ivan if (phy_dev->link == 0) { 5849ea9021aSKhoronzhuk, Ivan ksnav_close(&netcp_pktdma); 585fc9a8e8dSKaricheri, Muralidharan qm_close(); 586fc9a8e8dSKaricheri, Muralidharan return -1; 587fc9a8e8dSKaricheri, Muralidharan } 588fc9a8e8dSKaricheri, Muralidharan } 589fc9a8e8dSKaricheri, Muralidharan 590fc9a8e8dSKaricheri, Muralidharan emac_gigabit_enable(dev); 591fc9a8e8dSKaricheri, Muralidharan 592fc9a8e8dSKaricheri, Muralidharan ethss_start(); 593fc9a8e8dSKaricheri, Muralidharan 594fc9a8e8dSKaricheri, Muralidharan debug("- emac_open\n"); 595fc9a8e8dSKaricheri, Muralidharan 596fc9a8e8dSKaricheri, Muralidharan emac_open = 1; 597fc9a8e8dSKaricheri, Muralidharan 598fc9a8e8dSKaricheri, Muralidharan return 0; 599fc9a8e8dSKaricheri, Muralidharan } 600fc9a8e8dSKaricheri, Muralidharan 601fc9a8e8dSKaricheri, Muralidharan /* Eth device close */ 602fc9a8e8dSKaricheri, Muralidharan void keystone2_eth_close(struct eth_device *dev) 603fc9a8e8dSKaricheri, Muralidharan { 6043fe93623SKhoronzhuk, Ivan struct eth_priv_t *eth_priv = (struct eth_priv_t *)dev->priv; 6053fe93623SKhoronzhuk, Ivan struct phy_device *phy_dev = eth_priv->phy_dev; 6063fe93623SKhoronzhuk, Ivan 607fc9a8e8dSKaricheri, Muralidharan debug("+ emac_close\n"); 608fc9a8e8dSKaricheri, Muralidharan 609fc9a8e8dSKaricheri, Muralidharan if (!emac_open) 610fc9a8e8dSKaricheri, Muralidharan return; 611fc9a8e8dSKaricheri, Muralidharan 612fc9a8e8dSKaricheri, Muralidharan ethss_stop(); 613fc9a8e8dSKaricheri, Muralidharan 6149ea9021aSKhoronzhuk, Ivan ksnav_close(&netcp_pktdma); 615fc9a8e8dSKaricheri, Muralidharan qm_close(); 6163fe93623SKhoronzhuk, Ivan phy_shutdown(phy_dev); 617fc9a8e8dSKaricheri, Muralidharan 618fc9a8e8dSKaricheri, Muralidharan emac_open = 0; 619fc9a8e8dSKaricheri, Muralidharan 620fc9a8e8dSKaricheri, Muralidharan debug("- emac_close\n"); 621fc9a8e8dSKaricheri, Muralidharan } 622fc9a8e8dSKaricheri, Muralidharan 623fc9a8e8dSKaricheri, Muralidharan /* 624fc9a8e8dSKaricheri, Muralidharan * This function sends a single packet on the network and returns 625fc9a8e8dSKaricheri, Muralidharan * positive number (number of bytes transmitted) or negative for error 626fc9a8e8dSKaricheri, Muralidharan */ 627fc9a8e8dSKaricheri, Muralidharan static int keystone2_eth_send_packet(struct eth_device *dev, 628fc9a8e8dSKaricheri, Muralidharan void *packet, int length) 629fc9a8e8dSKaricheri, Muralidharan { 630fc9a8e8dSKaricheri, Muralidharan int ret_status = -1; 631fc9a8e8dSKaricheri, Muralidharan struct eth_priv_t *eth_priv = (struct eth_priv_t *)dev->priv; 632a4d2adeeSKhoronzhuk, Ivan struct phy_device *phy_dev = eth_priv->phy_dev; 633fc9a8e8dSKaricheri, Muralidharan 634a4d2adeeSKhoronzhuk, Ivan genphy_update_link(phy_dev); 635a4d2adeeSKhoronzhuk, Ivan if (phy_dev->link == 0) 636fc9a8e8dSKaricheri, Muralidharan return -1; 637fc9a8e8dSKaricheri, Muralidharan 638fc9a8e8dSKaricheri, Muralidharan if (cpmac_drv_send((u32 *)packet, length, eth_priv->slave_port) != 0) 639fc9a8e8dSKaricheri, Muralidharan return ret_status; 640fc9a8e8dSKaricheri, Muralidharan 641fc9a8e8dSKaricheri, Muralidharan return length; 642fc9a8e8dSKaricheri, Muralidharan } 643fc9a8e8dSKaricheri, Muralidharan 644fc9a8e8dSKaricheri, Muralidharan /* 645fc9a8e8dSKaricheri, Muralidharan * This function handles receipt of a packet from the network 646fc9a8e8dSKaricheri, Muralidharan */ 647fc9a8e8dSKaricheri, Muralidharan static int keystone2_eth_rcv_packet(struct eth_device *dev) 648fc9a8e8dSKaricheri, Muralidharan { 649fc9a8e8dSKaricheri, Muralidharan void *hd; 650fc9a8e8dSKaricheri, Muralidharan int pkt_size; 651fc9a8e8dSKaricheri, Muralidharan u32 *pkt; 652fc9a8e8dSKaricheri, Muralidharan 6539ea9021aSKhoronzhuk, Ivan hd = ksnav_recv(&netcp_pktdma, &pkt, &pkt_size); 654fc9a8e8dSKaricheri, Muralidharan if (hd == NULL) 655fc9a8e8dSKaricheri, Muralidharan return 0; 656fc9a8e8dSKaricheri, Muralidharan 6571fd92db8SJoe Hershberger net_process_received_packet((uchar *)pkt, pkt_size); 658fc9a8e8dSKaricheri, Muralidharan 6599ea9021aSKhoronzhuk, Ivan ksnav_release_rxhd(&netcp_pktdma, hd); 660fc9a8e8dSKaricheri, Muralidharan 661fc9a8e8dSKaricheri, Muralidharan return pkt_size; 662fc9a8e8dSKaricheri, Muralidharan } 663fc9a8e8dSKaricheri, Muralidharan 6645031ca59SVitaly Andrianov #ifdef CONFIG_MCAST_TFTP 6655031ca59SVitaly Andrianov static int keystone2_eth_bcast_addr(struct eth_device *dev, u32 ip, u8 set) 6665031ca59SVitaly Andrianov { 6675031ca59SVitaly Andrianov return 0; 6685031ca59SVitaly Andrianov } 6695031ca59SVitaly Andrianov #endif 6705031ca59SVitaly Andrianov 671fc9a8e8dSKaricheri, Muralidharan /* 672fc9a8e8dSKaricheri, Muralidharan * This function initializes the EMAC hardware. 673fc9a8e8dSKaricheri, Muralidharan */ 674fc9a8e8dSKaricheri, Muralidharan int keystone2_emac_initialize(struct eth_priv_t *eth_priv) 675fc9a8e8dSKaricheri, Muralidharan { 676550c5ce6SKhoronzhuk, Ivan int res; 677fc9a8e8dSKaricheri, Muralidharan struct eth_device *dev; 6783fe93623SKhoronzhuk, Ivan struct phy_device *phy_dev; 6796599f369SMugunthan V N struct mdio_regs *adap_mdio = (struct mdio_regs *)EMAC_MDIO_BASE_ADDR; 680fc9a8e8dSKaricheri, Muralidharan 681fc9a8e8dSKaricheri, Muralidharan dev = malloc(sizeof(struct eth_device)); 682fc9a8e8dSKaricheri, Muralidharan if (dev == NULL) 683fc9a8e8dSKaricheri, Muralidharan return -1; 684fc9a8e8dSKaricheri, Muralidharan 685fc9a8e8dSKaricheri, Muralidharan memset(dev, 0, sizeof(struct eth_device)); 686fc9a8e8dSKaricheri, Muralidharan 687fc9a8e8dSKaricheri, Muralidharan strcpy(dev->name, eth_priv->int_name); 688fc9a8e8dSKaricheri, Muralidharan dev->priv = eth_priv; 689fc9a8e8dSKaricheri, Muralidharan 690fc9a8e8dSKaricheri, Muralidharan keystone2_eth_read_mac_addr(dev); 691fc9a8e8dSKaricheri, Muralidharan 692fc9a8e8dSKaricheri, Muralidharan dev->iobase = 0; 693fc9a8e8dSKaricheri, Muralidharan dev->init = keystone2_eth_open; 694fc9a8e8dSKaricheri, Muralidharan dev->halt = keystone2_eth_close; 695fc9a8e8dSKaricheri, Muralidharan dev->send = keystone2_eth_send_packet; 696fc9a8e8dSKaricheri, Muralidharan dev->recv = keystone2_eth_rcv_packet; 6975031ca59SVitaly Andrianov #ifdef CONFIG_MCAST_TFTP 6985031ca59SVitaly Andrianov dev->mcast = keystone2_eth_bcast_addr; 6995031ca59SVitaly Andrianov #endif 700fc9a8e8dSKaricheri, Muralidharan 701fc9a8e8dSKaricheri, Muralidharan eth_register(dev); 702fc9a8e8dSKaricheri, Muralidharan 703550c5ce6SKhoronzhuk, Ivan /* Register MDIO bus if it's not registered yet */ 704550c5ce6SKhoronzhuk, Ivan if (!mdio_bus) { 705550c5ce6SKhoronzhuk, Ivan mdio_bus = mdio_alloc(); 706550c5ce6SKhoronzhuk, Ivan mdio_bus->read = keystone2_mdio_read; 707550c5ce6SKhoronzhuk, Ivan mdio_bus->write = keystone2_mdio_write; 708550c5ce6SKhoronzhuk, Ivan mdio_bus->reset = keystone2_mdio_reset; 709550c5ce6SKhoronzhuk, Ivan mdio_bus->priv = (void *)EMAC_MDIO_BASE_ADDR; 710192bc694SBen Whitten strcpy(mdio_bus->name, "ethernet-mdio"); 711550c5ce6SKhoronzhuk, Ivan 712550c5ce6SKhoronzhuk, Ivan res = mdio_register(mdio_bus); 713550c5ce6SKhoronzhuk, Ivan if (res) 714550c5ce6SKhoronzhuk, Ivan return res; 715550c5ce6SKhoronzhuk, Ivan } 716550c5ce6SKhoronzhuk, Ivan 7174657a2d4SVitaly Andrianov #ifndef CONFIG_SOC_K2G 718312aca4eSVitaly Andrianov keystone2_net_serdes_setup(); 7194657a2d4SVitaly Andrianov #endif 720312aca4eSVitaly Andrianov 7213fe93623SKhoronzhuk, Ivan /* Create phy device and bind it with driver */ 7223fe93623SKhoronzhuk, Ivan #ifdef CONFIG_KSNET_MDIO_PHY_CONFIG_ENABLE 7233fe93623SKhoronzhuk, Ivan phy_dev = phy_connect(mdio_bus, eth_priv->phy_addr, 724bf7bd4e7SMugunthan V N dev, eth_priv->phy_if); 7253fe93623SKhoronzhuk, Ivan phy_config(phy_dev); 7263fe93623SKhoronzhuk, Ivan #else 7273fe93623SKhoronzhuk, Ivan phy_dev = phy_find_by_mask(mdio_bus, 1 << eth_priv->phy_addr, 728bf7bd4e7SMugunthan V N eth_priv->phy_if); 7293fe93623SKhoronzhuk, Ivan phy_dev->dev = dev; 7303fe93623SKhoronzhuk, Ivan #endif 7313fe93623SKhoronzhuk, Ivan eth_priv->phy_dev = phy_dev; 7323fe93623SKhoronzhuk, Ivan 733fc9a8e8dSKaricheri, Muralidharan return 0; 734fc9a8e8dSKaricheri, Muralidharan } 735fc9a8e8dSKaricheri, Muralidharan 7366599f369SMugunthan V N #else 73792a16c81SHao Zhang 7386599f369SMugunthan V N static int ks2_eth_start(struct udevice *dev) 739fc9a8e8dSKaricheri, Muralidharan { 7406599f369SMugunthan V N struct ks2_eth_priv *priv = dev_get_priv(dev); 74192a16c81SHao Zhang 7426599f369SMugunthan V N #ifdef CONFIG_SOC_K2G 7436599f369SMugunthan V N keystone_rgmii_config(priv->phydev); 7446599f369SMugunthan V N #else 7456599f369SMugunthan V N keystone_sgmii_config(priv->phydev, priv->slave_port - 1, 7466599f369SMugunthan V N priv->sgmii_link_type); 7473c61502aSKhoronzhuk, Ivan #endif 7483c61502aSKhoronzhuk, Ivan 7496599f369SMugunthan V N udelay(10000); 7506599f369SMugunthan V N 7516599f369SMugunthan V N /* On chip switch configuration */ 7526599f369SMugunthan V N ethss_config(target_get_switch_ctl(), SWITCH_MAX_PKT_SIZE); 7536599f369SMugunthan V N 7546599f369SMugunthan V N qm_init(); 7556599f369SMugunthan V N 7566599f369SMugunthan V N if (ksnav_init(priv->netcp_pktdma, &priv->net_rx_buffs)) { 7576599f369SMugunthan V N error("ksnav_init failed\n"); 7586599f369SMugunthan V N goto err_knav_init; 759fc9a8e8dSKaricheri, Muralidharan } 7606599f369SMugunthan V N 7616599f369SMugunthan V N /* 7626599f369SMugunthan V N * Streaming switch configuration. If not present this 7636599f369SMugunthan V N * statement is defined to void in target.h. 7646599f369SMugunthan V N * If present this is usually defined to a series of register writes 7656599f369SMugunthan V N */ 7666599f369SMugunthan V N hw_config_streaming_switch(); 7676599f369SMugunthan V N 7686599f369SMugunthan V N if (priv->has_mdio) { 769a61f6a55SMugunthan V N keystone2_mdio_reset(priv->mdio_bus); 770a61f6a55SMugunthan V N 7716599f369SMugunthan V N phy_startup(priv->phydev); 7726599f369SMugunthan V N if (priv->phydev->link == 0) { 7736599f369SMugunthan V N error("phy startup failed\n"); 7746599f369SMugunthan V N goto err_phy_start; 7756599f369SMugunthan V N } 7766599f369SMugunthan V N } 7776599f369SMugunthan V N 7786599f369SMugunthan V N emac_gigabit_enable(dev); 7796599f369SMugunthan V N 7806599f369SMugunthan V N ethss_start(); 7816599f369SMugunthan V N 7826599f369SMugunthan V N priv->emac_open = true; 7836599f369SMugunthan V N 7846599f369SMugunthan V N return 0; 7856599f369SMugunthan V N 7866599f369SMugunthan V N err_phy_start: 7876599f369SMugunthan V N ksnav_close(priv->netcp_pktdma); 7886599f369SMugunthan V N err_knav_init: 7896599f369SMugunthan V N qm_close(); 7906599f369SMugunthan V N 7916599f369SMugunthan V N return -EFAULT; 7926599f369SMugunthan V N } 7936599f369SMugunthan V N 7946599f369SMugunthan V N static int ks2_eth_send(struct udevice *dev, void *packet, int length) 7956599f369SMugunthan V N { 7966599f369SMugunthan V N struct ks2_eth_priv *priv = dev_get_priv(dev); 7976599f369SMugunthan V N 7986599f369SMugunthan V N genphy_update_link(priv->phydev); 7996599f369SMugunthan V N if (priv->phydev->link == 0) 8006599f369SMugunthan V N return -1; 8016599f369SMugunthan V N 8026599f369SMugunthan V N if (length < EMAC_MIN_ETHERNET_PKT_SIZE) 8036599f369SMugunthan V N length = EMAC_MIN_ETHERNET_PKT_SIZE; 8046599f369SMugunthan V N 8056599f369SMugunthan V N return ksnav_send(priv->netcp_pktdma, (u32 *)packet, 8066599f369SMugunthan V N length, (priv->slave_port) << 16); 8076599f369SMugunthan V N } 8086599f369SMugunthan V N 8096599f369SMugunthan V N static int ks2_eth_recv(struct udevice *dev, int flags, uchar **packetp) 8106599f369SMugunthan V N { 8116599f369SMugunthan V N struct ks2_eth_priv *priv = dev_get_priv(dev); 8126599f369SMugunthan V N int pkt_size; 8136599f369SMugunthan V N u32 *pkt = NULL; 8146599f369SMugunthan V N 8156599f369SMugunthan V N priv->hd = ksnav_recv(priv->netcp_pktdma, &pkt, &pkt_size); 8166599f369SMugunthan V N if (priv->hd == NULL) 8176599f369SMugunthan V N return -EAGAIN; 8186599f369SMugunthan V N 8196599f369SMugunthan V N *packetp = (uchar *)pkt; 8206599f369SMugunthan V N 8216599f369SMugunthan V N return pkt_size; 8226599f369SMugunthan V N } 8236599f369SMugunthan V N 8246599f369SMugunthan V N static int ks2_eth_free_pkt(struct udevice *dev, uchar *packet, 8256599f369SMugunthan V N int length) 8266599f369SMugunthan V N { 8276599f369SMugunthan V N struct ks2_eth_priv *priv = dev_get_priv(dev); 8286599f369SMugunthan V N 8296599f369SMugunthan V N ksnav_release_rxhd(priv->netcp_pktdma, priv->hd); 8306599f369SMugunthan V N 8316599f369SMugunthan V N return 0; 8326599f369SMugunthan V N } 8336599f369SMugunthan V N 8346599f369SMugunthan V N static void ks2_eth_stop(struct udevice *dev) 8356599f369SMugunthan V N { 8366599f369SMugunthan V N struct ks2_eth_priv *priv = dev_get_priv(dev); 8376599f369SMugunthan V N 8386599f369SMugunthan V N if (!priv->emac_open) 8396599f369SMugunthan V N return; 8406599f369SMugunthan V N ethss_stop(); 8416599f369SMugunthan V N 8426599f369SMugunthan V N ksnav_close(priv->netcp_pktdma); 8436599f369SMugunthan V N qm_close(); 8446599f369SMugunthan V N phy_shutdown(priv->phydev); 8456599f369SMugunthan V N priv->emac_open = false; 8466599f369SMugunthan V N } 8476599f369SMugunthan V N 8486599f369SMugunthan V N int ks2_eth_read_rom_hwaddr(struct udevice *dev) 8496599f369SMugunthan V N { 8506599f369SMugunthan V N struct ks2_eth_priv *priv = dev_get_priv(dev); 8516599f369SMugunthan V N struct eth_pdata *pdata = dev_get_platdata(dev); 8526599f369SMugunthan V N u32 maca = 0; 8536599f369SMugunthan V N u32 macb = 0; 8546599f369SMugunthan V N 8556599f369SMugunthan V N /* Read the e-fuse mac address */ 8566599f369SMugunthan V N if (priv->slave_port == 1) { 8576599f369SMugunthan V N maca = __raw_readl(MAC_ID_BASE_ADDR); 8586599f369SMugunthan V N macb = __raw_readl(MAC_ID_BASE_ADDR + 4); 8596599f369SMugunthan V N } 8606599f369SMugunthan V N 8616599f369SMugunthan V N pdata->enetaddr[0] = (macb >> 8) & 0xff; 8626599f369SMugunthan V N pdata->enetaddr[1] = (macb >> 0) & 0xff; 8636599f369SMugunthan V N pdata->enetaddr[2] = (maca >> 24) & 0xff; 8646599f369SMugunthan V N pdata->enetaddr[3] = (maca >> 16) & 0xff; 8656599f369SMugunthan V N pdata->enetaddr[4] = (maca >> 8) & 0xff; 8666599f369SMugunthan V N pdata->enetaddr[5] = (maca >> 0) & 0xff; 8676599f369SMugunthan V N 8686599f369SMugunthan V N return 0; 8696599f369SMugunthan V N } 8706599f369SMugunthan V N 8716599f369SMugunthan V N int ks2_eth_write_hwaddr(struct udevice *dev) 8726599f369SMugunthan V N { 8736599f369SMugunthan V N struct ks2_eth_priv *priv = dev_get_priv(dev); 8746599f369SMugunthan V N struct eth_pdata *pdata = dev_get_platdata(dev); 8756599f369SMugunthan V N 8766599f369SMugunthan V N writel(mac_hi(pdata->enetaddr), 8776599f369SMugunthan V N DEVICE_EMACSW_BASE(pdata->iobase, priv->slave_port - 1) + 8786599f369SMugunthan V N CPGMACSL_REG_SA_HI); 8796599f369SMugunthan V N writel(mac_lo(pdata->enetaddr), 8806599f369SMugunthan V N DEVICE_EMACSW_BASE(pdata->iobase, priv->slave_port - 1) + 8816599f369SMugunthan V N CPGMACSL_REG_SA_LO); 8826599f369SMugunthan V N 8836599f369SMugunthan V N return 0; 8846599f369SMugunthan V N } 8856599f369SMugunthan V N 8866599f369SMugunthan V N static int ks2_eth_probe(struct udevice *dev) 8876599f369SMugunthan V N { 8886599f369SMugunthan V N struct ks2_eth_priv *priv = dev_get_priv(dev); 8896599f369SMugunthan V N struct mii_dev *mdio_bus; 8906599f369SMugunthan V N int ret; 8916599f369SMugunthan V N 8926599f369SMugunthan V N priv->dev = dev; 8936599f369SMugunthan V N 8946599f369SMugunthan V N /* These clock enables has to be moved to common location */ 8956599f369SMugunthan V N if (cpu_is_k2g()) 8966599f369SMugunthan V N writel(KS2_ETHERNET_RGMII, KS2_ETHERNET_CFG); 8976599f369SMugunthan V N 8986599f369SMugunthan V N /* By default, select PA PLL clock as PA clock source */ 8996599f369SMugunthan V N #ifndef CONFIG_SOC_K2G 9006599f369SMugunthan V N if (psc_enable_module(KS2_LPSC_PA)) 9016599f369SMugunthan V N return -EACCES; 9026599f369SMugunthan V N #endif 9036599f369SMugunthan V N if (psc_enable_module(KS2_LPSC_CPGMAC)) 9046599f369SMugunthan V N return -EACCES; 9056599f369SMugunthan V N if (psc_enable_module(KS2_LPSC_CRYPTO)) 9066599f369SMugunthan V N return -EACCES; 9076599f369SMugunthan V N 9086599f369SMugunthan V N if (cpu_is_k2e() || cpu_is_k2l()) 9096599f369SMugunthan V N pll_pa_clk_sel(); 9106599f369SMugunthan V N 9116599f369SMugunthan V N 9121610a921SMugunthan V N priv->net_rx_buffs.buff_ptr = rx_buffs; 9131610a921SMugunthan V N priv->net_rx_buffs.num_buffs = RX_BUFF_NUMS; 9141610a921SMugunthan V N priv->net_rx_buffs.buff_len = RX_BUFF_LEN; 9156599f369SMugunthan V N 916a61f6a55SMugunthan V N if (priv->slave_port == 1) { 917a61f6a55SMugunthan V N /* 918a61f6a55SMugunthan V N * Register MDIO bus for slave 0 only, other slave have 919a61f6a55SMugunthan V N * to re-use the same 920a61f6a55SMugunthan V N */ 9216599f369SMugunthan V N mdio_bus = mdio_alloc(); 9226599f369SMugunthan V N if (!mdio_bus) { 9236599f369SMugunthan V N error("MDIO alloc failed\n"); 9246599f369SMugunthan V N return -ENOMEM; 9256599f369SMugunthan V N } 9266599f369SMugunthan V N priv->mdio_bus = mdio_bus; 9276599f369SMugunthan V N mdio_bus->read = keystone2_mdio_read; 9286599f369SMugunthan V N mdio_bus->write = keystone2_mdio_write; 9296599f369SMugunthan V N mdio_bus->reset = keystone2_mdio_reset; 9306599f369SMugunthan V N mdio_bus->priv = priv->mdio_base; 9316599f369SMugunthan V N sprintf(mdio_bus->name, "ethernet-mdio"); 9326599f369SMugunthan V N 9336599f369SMugunthan V N ret = mdio_register(mdio_bus); 9346599f369SMugunthan V N if (ret) { 9356599f369SMugunthan V N error("MDIO bus register failed\n"); 9366599f369SMugunthan V N return ret; 9376599f369SMugunthan V N } 938a61f6a55SMugunthan V N } else { 939a61f6a55SMugunthan V N /* Get the MDIO bus from slave 0 device */ 940a61f6a55SMugunthan V N struct ks2_eth_priv *parent_priv; 941a61f6a55SMugunthan V N 942a61f6a55SMugunthan V N parent_priv = dev_get_priv(dev->parent); 943a61f6a55SMugunthan V N priv->mdio_bus = parent_priv->mdio_bus; 944a61f6a55SMugunthan V N } 9456599f369SMugunthan V N 9466599f369SMugunthan V N #ifndef CONFIG_SOC_K2G 9476599f369SMugunthan V N keystone2_net_serdes_setup(); 9486599f369SMugunthan V N #endif 9496599f369SMugunthan V N 9506599f369SMugunthan V N priv->netcp_pktdma = &netcp_pktdma; 9516599f369SMugunthan V N 952a61f6a55SMugunthan V N if (priv->has_mdio) { 953a61f6a55SMugunthan V N priv->phydev = phy_connect(priv->mdio_bus, priv->phy_addr, 954a61f6a55SMugunthan V N dev, priv->phy_if); 9556599f369SMugunthan V N phy_config(priv->phydev); 956a61f6a55SMugunthan V N } 9576599f369SMugunthan V N 9586599f369SMugunthan V N return 0; 9596599f369SMugunthan V N } 9606599f369SMugunthan V N 9616599f369SMugunthan V N int ks2_eth_remove(struct udevice *dev) 9626599f369SMugunthan V N { 9636599f369SMugunthan V N struct ks2_eth_priv *priv = dev_get_priv(dev); 9646599f369SMugunthan V N 9656599f369SMugunthan V N free(priv->phydev); 9666599f369SMugunthan V N mdio_unregister(priv->mdio_bus); 9676599f369SMugunthan V N mdio_free(priv->mdio_bus); 9686599f369SMugunthan V N 9696599f369SMugunthan V N return 0; 9706599f369SMugunthan V N } 9716599f369SMugunthan V N 9726599f369SMugunthan V N static const struct eth_ops ks2_eth_ops = { 9736599f369SMugunthan V N .start = ks2_eth_start, 9746599f369SMugunthan V N .send = ks2_eth_send, 9756599f369SMugunthan V N .recv = ks2_eth_recv, 9766599f369SMugunthan V N .free_pkt = ks2_eth_free_pkt, 9776599f369SMugunthan V N .stop = ks2_eth_stop, 9786599f369SMugunthan V N .read_rom_hwaddr = ks2_eth_read_rom_hwaddr, 9796599f369SMugunthan V N .write_hwaddr = ks2_eth_write_hwaddr, 9806599f369SMugunthan V N }; 9816599f369SMugunthan V N 982a61f6a55SMugunthan V N static int ks2_eth_bind_slaves(struct udevice *dev, int gbe, int *gbe_0) 9836599f369SMugunthan V N { 9846599f369SMugunthan V N const void *fdt = gd->fdt_blob; 985a61f6a55SMugunthan V N struct udevice *sl_dev; 9866599f369SMugunthan V N int interfaces; 987a61f6a55SMugunthan V N int sec_slave; 988a61f6a55SMugunthan V N int slave; 989a61f6a55SMugunthan V N int ret; 990a61f6a55SMugunthan V N char *slave_name; 991a61f6a55SMugunthan V N 992a61f6a55SMugunthan V N interfaces = fdt_subnode_offset(fdt, gbe, "interfaces"); 993*df87e6b1SSimon Glass fdt_for_each_subnode(slave, fdt, interfaces) { 994a61f6a55SMugunthan V N int slave_no; 995a61f6a55SMugunthan V N 996a61f6a55SMugunthan V N slave_no = fdtdec_get_int(fdt, slave, "slave-port", -ENOENT); 997a61f6a55SMugunthan V N if (slave_no == -ENOENT) 998a61f6a55SMugunthan V N continue; 999a61f6a55SMugunthan V N 1000a61f6a55SMugunthan V N if (slave_no == 0) { 1001a61f6a55SMugunthan V N /* This is the current eth device */ 1002a61f6a55SMugunthan V N *gbe_0 = slave; 1003a61f6a55SMugunthan V N } else { 1004a61f6a55SMugunthan V N /* Slave devices to be registered */ 1005a61f6a55SMugunthan V N slave_name = malloc(20); 1006a61f6a55SMugunthan V N snprintf(slave_name, 20, "netcp@slave-%d", slave_no); 1007a61f6a55SMugunthan V N ret = device_bind_driver_to_node(dev, "eth_ks2_sl", 1008a61f6a55SMugunthan V N slave_name, slave, 1009a61f6a55SMugunthan V N &sl_dev); 1010a61f6a55SMugunthan V N if (ret) { 1011a61f6a55SMugunthan V N error("ks2_net - not able to bind slave interfaces\n"); 1012a61f6a55SMugunthan V N return ret; 1013a61f6a55SMugunthan V N } 1014a61f6a55SMugunthan V N } 1015a61f6a55SMugunthan V N } 1016a61f6a55SMugunthan V N 1017a61f6a55SMugunthan V N sec_slave = fdt_subnode_offset(fdt, gbe, "secondary-slave-ports"); 1018*df87e6b1SSimon Glass fdt_for_each_subnode(slave, fdt, sec_slave) { 1019a61f6a55SMugunthan V N int slave_no; 1020a61f6a55SMugunthan V N 1021a61f6a55SMugunthan V N slave_no = fdtdec_get_int(fdt, slave, "slave-port", -ENOENT); 1022a61f6a55SMugunthan V N if (slave_no == -ENOENT) 1023a61f6a55SMugunthan V N continue; 1024a61f6a55SMugunthan V N 1025a61f6a55SMugunthan V N /* Slave devices to be registered */ 1026a61f6a55SMugunthan V N slave_name = malloc(20); 1027a61f6a55SMugunthan V N snprintf(slave_name, 20, "netcp@slave-%d", slave_no); 1028a61f6a55SMugunthan V N ret = device_bind_driver_to_node(dev, "eth_ks2_sl", slave_name, 1029a61f6a55SMugunthan V N slave, &sl_dev); 1030a61f6a55SMugunthan V N if (ret) { 1031a61f6a55SMugunthan V N error("ks2_net - not able to bind slave interfaces\n"); 1032a61f6a55SMugunthan V N return ret; 1033a61f6a55SMugunthan V N } 1034a61f6a55SMugunthan V N } 1035a61f6a55SMugunthan V N 1036a61f6a55SMugunthan V N return 0; 1037a61f6a55SMugunthan V N } 1038a61f6a55SMugunthan V N 1039a61f6a55SMugunthan V N static int ks2_eth_parse_slave_interface(int netcp, int slave, 1040a61f6a55SMugunthan V N struct ks2_eth_priv *priv, 1041a61f6a55SMugunthan V N struct eth_pdata *pdata) 1042a61f6a55SMugunthan V N { 1043a61f6a55SMugunthan V N const void *fdt = gd->fdt_blob; 10446599f369SMugunthan V N int mdio; 1045a61f6a55SMugunthan V N int phy; 1046a61f6a55SMugunthan V N int dma_count; 1047a61f6a55SMugunthan V N u32 dma_channel[8]; 10486599f369SMugunthan V N 1049a61f6a55SMugunthan V N priv->slave_port = fdtdec_get_int(fdt, slave, "slave-port", -1); 1050a61f6a55SMugunthan V N priv->net_rx_buffs.rx_flow = priv->slave_port * 8; 10516599f369SMugunthan V N 10526599f369SMugunthan V N /* U-Boot slave port number starts with 1 instead of 0 */ 10536599f369SMugunthan V N priv->slave_port += 1; 10546599f369SMugunthan V N 1055a61f6a55SMugunthan V N dma_count = fdtdec_get_int_array_count(fdt, netcp, 1056a61f6a55SMugunthan V N "ti,navigator-dmas", 1057a61f6a55SMugunthan V N dma_channel, 8); 1058a61f6a55SMugunthan V N 1059a61f6a55SMugunthan V N if (dma_count > (2 * priv->slave_port)) { 1060a61f6a55SMugunthan V N int dma_idx; 1061a61f6a55SMugunthan V N 1062a61f6a55SMugunthan V N dma_idx = priv->slave_port * 2 - 1; 1063a61f6a55SMugunthan V N priv->net_rx_buffs.rx_flow = dma_channel[dma_idx]; 1064a61f6a55SMugunthan V N } 1065a61f6a55SMugunthan V N 1066a61f6a55SMugunthan V N priv->link_type = fdtdec_get_int(fdt, slave, "link-interface", -1); 1067a61f6a55SMugunthan V N 1068a61f6a55SMugunthan V N phy = fdtdec_lookup_phandle(fdt, slave, "phy-handle"); 1069a61f6a55SMugunthan V N if (phy >= 0) { 10706599f369SMugunthan V N priv->phy_addr = fdtdec_get_int(fdt, phy, "reg", -1); 10716599f369SMugunthan V N 10726599f369SMugunthan V N mdio = fdt_parent_offset(fdt, phy); 10736599f369SMugunthan V N if (mdio < 0) { 10746599f369SMugunthan V N error("mdio dt not found\n"); 10756599f369SMugunthan V N return -ENODEV; 10766599f369SMugunthan V N } 10776599f369SMugunthan V N priv->mdio_base = (void *)fdtdec_get_addr(fdt, mdio, "reg"); 1078a61f6a55SMugunthan V N } 10796599f369SMugunthan V N 10806599f369SMugunthan V N if (priv->link_type == LINK_TYPE_MAC_TO_PHY_MODE) { 10816599f369SMugunthan V N priv->phy_if = PHY_INTERFACE_MODE_SGMII; 10826599f369SMugunthan V N pdata->phy_interface = priv->phy_if; 10836599f369SMugunthan V N priv->sgmii_link_type = SGMII_LINK_MAC_PHY; 10846599f369SMugunthan V N priv->has_mdio = true; 10856599f369SMugunthan V N } 10866599f369SMugunthan V N 1087a61f6a55SMugunthan V N return 0; 1088a61f6a55SMugunthan V N } 1089a61f6a55SMugunthan V N 1090a61f6a55SMugunthan V N static int ks2_sl_eth_ofdata_to_platdata(struct udevice *dev) 1091a61f6a55SMugunthan V N { 1092a61f6a55SMugunthan V N struct ks2_eth_priv *priv = dev_get_priv(dev); 1093a61f6a55SMugunthan V N struct eth_pdata *pdata = dev_get_platdata(dev); 1094a61f6a55SMugunthan V N const void *fdt = gd->fdt_blob; 1095a61f6a55SMugunthan V N int slave = dev->of_offset; 1096a61f6a55SMugunthan V N int interfaces; 1097a61f6a55SMugunthan V N int gbe; 1098a61f6a55SMugunthan V N int netcp_devices; 1099a61f6a55SMugunthan V N int netcp; 1100a61f6a55SMugunthan V N 1101a61f6a55SMugunthan V N interfaces = fdt_parent_offset(fdt, slave); 1102a61f6a55SMugunthan V N gbe = fdt_parent_offset(fdt, interfaces); 1103a61f6a55SMugunthan V N netcp_devices = fdt_parent_offset(fdt, gbe); 1104a61f6a55SMugunthan V N netcp = fdt_parent_offset(fdt, netcp_devices); 1105a61f6a55SMugunthan V N 1106a61f6a55SMugunthan V N ks2_eth_parse_slave_interface(netcp, slave, priv, pdata); 1107a61f6a55SMugunthan V N 1108a61f6a55SMugunthan V N pdata->iobase = fdtdec_get_addr(fdt, netcp, "reg"); 1109a61f6a55SMugunthan V N 1110a61f6a55SMugunthan V N return 0; 1111a61f6a55SMugunthan V N } 1112a61f6a55SMugunthan V N 1113a61f6a55SMugunthan V N static int ks2_eth_ofdata_to_platdata(struct udevice *dev) 1114a61f6a55SMugunthan V N { 1115a61f6a55SMugunthan V N struct ks2_eth_priv *priv = dev_get_priv(dev); 1116a61f6a55SMugunthan V N struct eth_pdata *pdata = dev_get_platdata(dev); 1117a61f6a55SMugunthan V N const void *fdt = gd->fdt_blob; 1118a61f6a55SMugunthan V N int gbe_0 = -ENODEV; 1119a61f6a55SMugunthan V N int netcp_devices; 1120a61f6a55SMugunthan V N int gbe; 1121a61f6a55SMugunthan V N 1122a61f6a55SMugunthan V N netcp_devices = fdt_subnode_offset(fdt, dev->of_offset, 1123a61f6a55SMugunthan V N "netcp-devices"); 1124a61f6a55SMugunthan V N gbe = fdt_subnode_offset(fdt, netcp_devices, "gbe"); 1125a61f6a55SMugunthan V N 1126a61f6a55SMugunthan V N ks2_eth_bind_slaves(dev, gbe, &gbe_0); 1127a61f6a55SMugunthan V N 1128a61f6a55SMugunthan V N ks2_eth_parse_slave_interface(dev->of_offset, gbe_0, priv, pdata); 1129a61f6a55SMugunthan V N 1130a61f6a55SMugunthan V N pdata->iobase = dev_get_addr(dev); 11316599f369SMugunthan V N 11326599f369SMugunthan V N return 0; 11336599f369SMugunthan V N } 11346599f369SMugunthan V N 11356599f369SMugunthan V N static const struct udevice_id ks2_eth_ids[] = { 11366599f369SMugunthan V N { .compatible = "ti,netcp-1.0" }, 11376599f369SMugunthan V N { } 11386599f369SMugunthan V N }; 11396599f369SMugunthan V N 1140a61f6a55SMugunthan V N U_BOOT_DRIVER(eth_ks2_slave) = { 1141a61f6a55SMugunthan V N .name = "eth_ks2_sl", 1142a61f6a55SMugunthan V N .id = UCLASS_ETH, 1143a61f6a55SMugunthan V N .ofdata_to_platdata = ks2_sl_eth_ofdata_to_platdata, 1144a61f6a55SMugunthan V N .probe = ks2_eth_probe, 1145a61f6a55SMugunthan V N .remove = ks2_eth_remove, 1146a61f6a55SMugunthan V N .ops = &ks2_eth_ops, 1147a61f6a55SMugunthan V N .priv_auto_alloc_size = sizeof(struct ks2_eth_priv), 1148a61f6a55SMugunthan V N .platdata_auto_alloc_size = sizeof(struct eth_pdata), 1149a61f6a55SMugunthan V N .flags = DM_FLAG_ALLOC_PRIV_DMA, 1150a61f6a55SMugunthan V N }; 11516599f369SMugunthan V N 11526599f369SMugunthan V N U_BOOT_DRIVER(eth_ks2) = { 11536599f369SMugunthan V N .name = "eth_ks2", 11546599f369SMugunthan V N .id = UCLASS_ETH, 11556599f369SMugunthan V N .of_match = ks2_eth_ids, 11566599f369SMugunthan V N .ofdata_to_platdata = ks2_eth_ofdata_to_platdata, 11576599f369SMugunthan V N .probe = ks2_eth_probe, 11586599f369SMugunthan V N .remove = ks2_eth_remove, 11596599f369SMugunthan V N .ops = &ks2_eth_ops, 11606599f369SMugunthan V N .priv_auto_alloc_size = sizeof(struct ks2_eth_priv), 11616599f369SMugunthan V N .platdata_auto_alloc_size = sizeof(struct eth_pdata), 11626599f369SMugunthan V N .flags = DM_FLAG_ALLOC_PRIV_DMA, 11636599f369SMugunthan V N }; 11644657a2d4SVitaly Andrianov #endif 1165