From ef4547176d0fa4d43d060a58c0c902add7fe0aed Mon Sep 17 00:00:00 2001 From: "Khoronzhuk, Ivan" Date: Fri, 5 Sep 2014 19:02:47 +0300 Subject: dma: keystone_nav: move keystone_nav driver to driver/dma/ The keystone_nav is used by drivers/net/keystone_net.c driver to send and receive packets, but currently it's placed at keystone arch sources. So it should be in the drivers directory also. It's separate driver that can be used for sending and receiving pktdma packets by others drivers also. This patch just move this driver to appropriate directory and doesn't add any functional changes. Acked-by: Murali Karicheri Signed-off-by: Ivan Khoronzhuk --- drivers/net/keystone_net.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/keystone_net.c b/drivers/net/keystone_net.c index d22b722..1cfe654 100644 --- a/drivers/net/keystone_net.c +++ b/drivers/net/keystone_net.c @@ -14,7 +14,7 @@ #include #include #include -#include +#include unsigned int emac_dbg; -- cgit v1.1 From 9ea9021ac466f5ccc8b6238cbce37428bb58f887 Mon Sep 17 00:00:00 2001 From: "Khoronzhuk, Ivan" Date: Fri, 5 Sep 2014 19:02:48 +0300 Subject: dma: keystone_nav: generalize driver usage The keystone_nav driver is general driver intended to be used for working with queue manager and pktdma for different IPs like NETCP, AIF, FFTC, etc. So the it's API shouldn't be named like it works only with one of them, it should be general names. The names with prefix like netcp_* rather do for drivers/net/keystone_net.c driver. So it's good to generalize this driver to be used for different IP's and delete confusion with real NETCP driver. The current netcp_* functions of keystone navigator can be used for other settings of pktdma, not only for NETCP. The API of this driver is used by the keystone_net driver to work with NETCP, so net driver also should be corrected. For convenience collect pkdma configurations in drivers/dma/keystone_nav_cfg.c. Acked-by: Vitaly Andrianov Signed-off-by: Ivan Khoronzhuk --- drivers/net/keystone_net.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/keystone_net.c b/drivers/net/keystone_net.c index 1cfe654..66532ee 100644 --- a/drivers/net/keystone_net.c +++ b/drivers/net/keystone_net.c @@ -393,7 +393,8 @@ int32_t cpmac_drv_send(u32 *buffer, int num_bytes, int slave_port_num) if (num_bytes < EMAC_MIN_ETHERNET_PKT_SIZE) num_bytes = EMAC_MIN_ETHERNET_PKT_SIZE; - return netcp_send(buffer, num_bytes, (slave_port_num) << 16); + return ksnav_send(&netcp_pktdma, buffer, + num_bytes, (slave_port_num) << 16); } /* Eth device open */ @@ -431,7 +432,7 @@ static int keystone2_eth_open(struct eth_device *dev, bd_t *bis) printf("ERROR: qm_init()\n"); return -1; } - if (netcp_init(&net_rx_buffs)) { + if (ksnav_init(&netcp_pktdma, &net_rx_buffs)) { qm_close(); printf("ERROR: netcp_init()\n"); return -1; @@ -456,7 +457,7 @@ static int keystone2_eth_open(struct eth_device *dev, bd_t *bis) link = keystone_get_link_status(dev); if (link == 0) { - netcp_close(); + ksnav_close(&netcp_pktdma); qm_close(); return -1; } @@ -483,7 +484,7 @@ void keystone2_eth_close(struct eth_device *dev) ethss_stop(); - netcp_close(); + ksnav_close(&netcp_pktdma); qm_close(); emac_open = 0; @@ -530,13 +531,13 @@ static int keystone2_eth_rcv_packet(struct eth_device *dev) int pkt_size; u32 *pkt; - hd = netcp_recv(&pkt, &pkt_size); + hd = ksnav_recv(&netcp_pktdma, &pkt, &pkt_size); if (hd == NULL) return 0; NetReceive((uchar *)pkt, pkt_size); - netcp_release_rxhd(hd); + ksnav_release_rxhd(&netcp_pktdma, hd); return pkt_size; } -- cgit v1.1 From b2cfe32278478dbf4b08a06f8d48436fc3d4ae7e Mon Sep 17 00:00:00 2001 From: Hao Zhang Date: Mon, 29 Sep 2014 22:17:20 +0300 Subject: net: keystone_net: remove SoC specific emac_regs structure This patch removes K2HK SOC specifc emac_regs structure, it uses soc specific register offset to keep the network driver common across all the Keystone II EVMs. Acked-by: Murali Karicheri Signed-off-by: Hao Zhang Signed-off-by: Ivan Khoronzhuk --- drivers/net/keystone_net.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/keystone_net.c b/drivers/net/keystone_net.c index 66532ee..4abde57 100644 --- a/drivers/net/keystone_net.c +++ b/drivers/net/keystone_net.c @@ -45,8 +45,6 @@ static void keystone2_eth_mdio_enable(void); static int gen_get_link_speed(int phy_addr); /* EMAC Addresses */ -static volatile struct emac_regs *adap_emac = - (struct emac_regs *)EMAC_EMACSL_BASE_ADDR; static volatile struct mdio_regs *adap_mdio = (struct mdio_regs *)EMAC_MDIO_BASE_ADDR; @@ -169,10 +167,10 @@ static void __attribute__((unused)) * Check if link detected is giga-bit * If Gigabit mode detected, enable gigbit in MAC */ - writel(readl(&(adap_emac[eth_priv->slave_port - 1].maccontrol)) | + writel(readl(DEVICE_EMACSL_BASE(eth_priv->slave_port - 1) + + CPGMACSL_REG_CTL) | EMAC_MACCONTROL_GIGFORCE | EMAC_MACCONTROL_GIGABIT_ENABLE, - &(adap_emac[eth_priv->slave_port - 1].maccontrol)) - ; + DEVICE_EMACSL_BASE(eth_priv->slave_port - 1) + CPGMACSL_REG_CTL); } int keystone_sgmii_link_status(int port) -- cgit v1.1 From 0935cac6855626f9de6af9583a30b6463e8bab95 Mon Sep 17 00:00:00 2001 From: "Khoronzhuk, Ivan" Date: Mon, 29 Sep 2014 22:17:22 +0300 Subject: net: keystone_net: move header file from arch to ti-common The header file for the driver should be in correct place. So move it to "arch/arm/include/asm/ti-common/keystone_net.h" and correct driver's external dependencies. At the same time align and correct some definitions. Acked-by: Murali Karicheri Signed-off-by: Ivan Khoronzhuk --- drivers/net/keystone_net.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/keystone_net.c b/drivers/net/keystone_net.c index 4abde57..edd2bb0 100644 --- a/drivers/net/keystone_net.c +++ b/drivers/net/keystone_net.c @@ -12,9 +12,9 @@ #include #include #include -#include #include #include +#include unsigned int emac_dbg; -- cgit v1.1 From 497e9e03216bae505a8f06808975d0c4865622f2 Mon Sep 17 00:00:00 2001 From: "Khoronzhuk, Ivan" Date: Mon, 29 Sep 2014 22:17:24 +0300 Subject: net: keystone_net: remove redundant code from keystone_net.c Remove unused tx_send_loop variable. Removes duplicated get_link_status() call from the keystone2_eth_send_packet(). The emac_gigabit_enable() is called at opening Ethernet and there is no need to enable it on sending each packet. So remove that call from keystone2_eth_send_packet() as well. The calling of power/clock up functions are mostly the responsibility of SoC/board code, so move these functions to appropriate place. Signed-off-by: Ivan Khoronzhuk --- drivers/net/keystone_net.c | 17 ----------------- 1 file changed, 17 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/keystone_net.c b/drivers/net/keystone_net.c index edd2bb0..33197f9 100644 --- a/drivers/net/keystone_net.c +++ b/drivers/net/keystone_net.c @@ -12,12 +12,9 @@ #include #include #include -#include #include #include -unsigned int emac_dbg; - unsigned int emac_open; static unsigned int sys_has_mdio = 1; @@ -409,9 +406,6 @@ static int keystone2_eth_open(struct eth_device *dev, bd_t *bis) sys_has_mdio = (eth_priv->sgmii_link_type == SGMII_LINK_MAC_PHY) ? 1 : 0; - psc_enable_module(KS2_LPSC_PA); - psc_enable_module(KS2_LPSC_CPGMAC); - sgmii_serdes_setup_156p25mhz(); if (sys_has_mdio) @@ -490,8 +484,6 @@ void keystone2_eth_close(struct eth_device *dev) debug("- emac_close\n"); } -static int tx_send_loop; - /* * This function sends a single packet on the network and returns * positive number (number of bytes transmitted) or negative for error @@ -502,21 +494,12 @@ static int keystone2_eth_send_packet(struct eth_device *dev, int ret_status = -1; struct eth_priv_t *eth_priv = (struct eth_priv_t *)dev->priv; - tx_send_loop = 0; - if (keystone_get_link_status(dev) == 0) return -1; - emac_gigabit_enable(dev); - if (cpmac_drv_send((u32 *)packet, length, eth_priv->slave_port) != 0) return ret_status; - if (keystone_get_link_status(dev) == 0) - return -1; - - emac_gigabit_enable(dev); - return length; } -- cgit v1.1 From a43febde4452f254621c0c95d452c89ad498e959 Mon Sep 17 00:00:00 2001 From: "Khoronzhuk, Ivan" Date: Wed, 22 Oct 2014 17:18:21 +0300 Subject: soc: keystone_serdes: create a separate SGMII SerDes driver This patch split the Keystone II SGMII SerDes related code from Ethernet driver and create a separate SGMII SerDes driver. The SerDes driver can be used by others keystone subsystems like PCI, sRIO, so move it to driver/soc/keystone directory. Add soc specific drivers directory like in the Linux kernel. It is going to be used by keysotone soc specific drivers. Signed-off-by: Hao Zhang Signed-off-by: Ivan Khoronzhuk --- drivers/net/keystone_net.c | 143 ++------------------------------------------- 1 file changed, 5 insertions(+), 138 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/keystone_net.c b/drivers/net/keystone_net.c index 33197f9..63f3361 100644 --- a/drivers/net/keystone_net.c +++ b/drivers/net/keystone_net.c @@ -14,6 +14,7 @@ #include #include #include +#include unsigned int emac_open; static unsigned int sys_has_mdio = 1; @@ -38,6 +39,7 @@ struct rx_buff_desc net_rx_buffs = { }; static void keystone2_eth_mdio_enable(void); +static void keystone2_net_serdes_setup(void); static int gen_get_link_speed(int phy_addr); @@ -406,7 +408,7 @@ static int keystone2_eth_open(struct eth_device *dev, bd_t *bis) sys_has_mdio = (eth_priv->sgmii_link_type == SGMII_LINK_MAC_PHY) ? 1 : 0; - sgmii_serdes_setup_156p25mhz(); + keystone2_net_serdes_setup(); if (sys_has_mdio) keystone2_eth_mdio_enable(); @@ -552,142 +554,7 @@ int keystone2_emac_initialize(struct eth_priv_t *eth_priv) return 0; } -void sgmii_serdes_setup_156p25mhz(void) +static void keystone2_net_serdes_setup(void) { - unsigned int cnt; - - /* - * configure Serializer/Deserializer (SerDes) hardware. SerDes IP - * hardware vendor published only register addresses and their values - * to be used for configuring SerDes. So had to use hardcoded values - * below. - */ - clrsetbits_le32(0x0232a000, 0xffff0000, 0x00800000); - clrsetbits_le32(0x0232a014, 0x0000ffff, 0x00008282); - clrsetbits_le32(0x0232a060, 0x00ffffff, 0x00142438); - clrsetbits_le32(0x0232a064, 0x00ffff00, 0x00c3c700); - clrsetbits_le32(0x0232a078, 0x0000ff00, 0x0000c000); - - clrsetbits_le32(0x0232a204, 0xff0000ff, 0x38000080); - clrsetbits_le32(0x0232a208, 0x000000ff, 0x00000000); - clrsetbits_le32(0x0232a20c, 0xff000000, 0x02000000); - clrsetbits_le32(0x0232a210, 0xff000000, 0x1b000000); - clrsetbits_le32(0x0232a214, 0x0000ffff, 0x00006fb8); - clrsetbits_le32(0x0232a218, 0xffff00ff, 0x758000e4); - clrsetbits_le32(0x0232a2ac, 0x0000ff00, 0x00004400); - clrsetbits_le32(0x0232a22c, 0x00ffff00, 0x00200800); - clrsetbits_le32(0x0232a280, 0x00ff00ff, 0x00820082); - clrsetbits_le32(0x0232a284, 0xffffffff, 0x1d0f0385); - - clrsetbits_le32(0x0232a404, 0xff0000ff, 0x38000080); - clrsetbits_le32(0x0232a408, 0x000000ff, 0x00000000); - clrsetbits_le32(0x0232a40c, 0xff000000, 0x02000000); - clrsetbits_le32(0x0232a410, 0xff000000, 0x1b000000); - clrsetbits_le32(0x0232a414, 0x0000ffff, 0x00006fb8); - clrsetbits_le32(0x0232a418, 0xffff00ff, 0x758000e4); - clrsetbits_le32(0x0232a4ac, 0x0000ff00, 0x00004400); - clrsetbits_le32(0x0232a42c, 0x00ffff00, 0x00200800); - clrsetbits_le32(0x0232a480, 0x00ff00ff, 0x00820082); - clrsetbits_le32(0x0232a484, 0xffffffff, 0x1d0f0385); - - clrsetbits_le32(0x0232a604, 0xff0000ff, 0x38000080); - clrsetbits_le32(0x0232a608, 0x000000ff, 0x00000000); - clrsetbits_le32(0x0232a60c, 0xff000000, 0x02000000); - clrsetbits_le32(0x0232a610, 0xff000000, 0x1b000000); - clrsetbits_le32(0x0232a614, 0x0000ffff, 0x00006fb8); - clrsetbits_le32(0x0232a618, 0xffff00ff, 0x758000e4); - clrsetbits_le32(0x0232a6ac, 0x0000ff00, 0x00004400); - clrsetbits_le32(0x0232a62c, 0x00ffff00, 0x00200800); - clrsetbits_le32(0x0232a680, 0x00ff00ff, 0x00820082); - clrsetbits_le32(0x0232a684, 0xffffffff, 0x1d0f0385); - - clrsetbits_le32(0x0232a804, 0xff0000ff, 0x38000080); - clrsetbits_le32(0x0232a808, 0x000000ff, 0x00000000); - clrsetbits_le32(0x0232a80c, 0xff000000, 0x02000000); - clrsetbits_le32(0x0232a810, 0xff000000, 0x1b000000); - clrsetbits_le32(0x0232a814, 0x0000ffff, 0x00006fb8); - clrsetbits_le32(0x0232a818, 0xffff00ff, 0x758000e4); - clrsetbits_le32(0x0232a8ac, 0x0000ff00, 0x00004400); - clrsetbits_le32(0x0232a82c, 0x00ffff00, 0x00200800); - clrsetbits_le32(0x0232a880, 0x00ff00ff, 0x00820082); - clrsetbits_le32(0x0232a884, 0xffffffff, 0x1d0f0385); - - clrsetbits_le32(0x0232aa00, 0x0000ff00, 0x00000800); - clrsetbits_le32(0x0232aa08, 0xffff0000, 0x38a20000); - clrsetbits_le32(0x0232aa30, 0x00ffff00, 0x008a8a00); - clrsetbits_le32(0x0232aa84, 0x0000ff00, 0x00000600); - clrsetbits_le32(0x0232aa94, 0xff000000, 0x10000000); - clrsetbits_le32(0x0232aaa0, 0xff000000, 0x81000000); - clrsetbits_le32(0x0232aabc, 0xff000000, 0xff000000); - clrsetbits_le32(0x0232aac0, 0x000000ff, 0x0000008b); - clrsetbits_le32(0x0232ab08, 0xffff0000, 0x583f0000); - clrsetbits_le32(0x0232ab0c, 0x000000ff, 0x0000004e); - clrsetbits_le32(0x0232a000, 0x000000ff, 0x00000003); - clrsetbits_le32(0x0232aa00, 0x000000ff, 0x0000005f); - - clrsetbits_le32(0x0232aa48, 0x00ffff00, 0x00fd8c00); - clrsetbits_le32(0x0232aa54, 0x00ffffff, 0x002fec72); - clrsetbits_le32(0x0232aa58, 0xffffff00, 0x00f92100); - clrsetbits_le32(0x0232aa5c, 0xffffffff, 0x00040060); - clrsetbits_le32(0x0232aa60, 0xffffffff, 0x00008000); - clrsetbits_le32(0x0232aa64, 0xffffffff, 0x0c581220); - clrsetbits_le32(0x0232aa68, 0xffffffff, 0xe13b0602); - clrsetbits_le32(0x0232aa6c, 0xffffffff, 0xb8074cc1); - clrsetbits_le32(0x0232aa70, 0xffffffff, 0x3f02e989); - clrsetbits_le32(0x0232aa74, 0x000000ff, 0x00000001); - clrsetbits_le32(0x0232ab20, 0x00ff0000, 0x00370000); - clrsetbits_le32(0x0232ab1c, 0xff000000, 0x37000000); - clrsetbits_le32(0x0232ab20, 0x000000ff, 0x0000005d); - - /*Bring SerDes out of Reset if SerDes is Shutdown & is in Reset Mode*/ - clrbits_le32(0x0232a010, 1 << 28); - - /* Enable TX and RX via the LANExCTL_STS 0x0000 + x*4 */ - clrbits_le32(0x0232a228, 1 << 29); - writel(0xF800F8C0, 0x0232bfe0); - clrbits_le32(0x0232a428, 1 << 29); - writel(0xF800F8C0, 0x0232bfe4); - clrbits_le32(0x0232a628, 1 << 29); - writel(0xF800F8C0, 0x0232bfe8); - clrbits_le32(0x0232a828, 1 << 29); - writel(0xF800F8C0, 0x0232bfec); - - /*Enable pll via the pll_ctrl 0x0014*/ - writel(0xe0000000, 0x0232bff4) - ; - - /*Waiting for SGMII Serdes PLL lock.*/ - for (cnt = 10000; cnt > 0 && ((readl(0x02090114) & 0x10) == 0); cnt--) - ; - - for (cnt = 10000; cnt > 0 && ((readl(0x02090214) & 0x10) == 0); cnt--) - ; - - for (cnt = 10000; cnt > 0 && ((readl(0x02090414) & 0x10) == 0); cnt--) - ; - - for (cnt = 10000; cnt > 0 && ((readl(0x02090514) & 0x10) == 0); cnt--) - ; - - udelay(45000); -} - -void sgmii_serdes_shutdown(void) -{ - /* - * shutdown SerDes hardware. SerDes hardware vendor published only - * register addresses and their values. So had to use hardcoded - * values below. - */ - clrbits_le32(0x0232bfe0, 3 << 29 | 3 << 13); - setbits_le32(0x02320228, 1 << 29); - clrbits_le32(0x0232bfe4, 3 << 29 | 3 << 13); - setbits_le32(0x02320428, 1 << 29); - clrbits_le32(0x0232bfe8, 3 << 29 | 3 << 13); - setbits_le32(0x02320628, 1 << 29); - clrbits_le32(0x0232bfec, 3 << 29 | 3 << 13); - setbits_le32(0x02320828, 1 << 29); - - clrbits_le32(0x02320034, 3 << 29); - setbits_le32(0x02320010, 1 << 28); + ks2_serdes_sgmii_156p25mhz_setup(); } -- cgit v1.1 From 92a16c81f5c5b43779520dbc7278f3d7cfb24684 Mon Sep 17 00:00:00 2001 From: Hao Zhang Date: Wed, 22 Oct 2014 17:18:23 +0300 Subject: soc: keystone_serdes: generalize to be used by other sub systems SerDes driver is used by other sub systems like PCI, sRIO etc. So modify it to be more general. The SerDes driver provides common API's that can also be extended for other peripherals SerDes configurations. Signed-off-by: Hao Zhang Signed-off-by: Ivan Khoronzhuk --- drivers/net/keystone_net.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/keystone_net.c b/drivers/net/keystone_net.c index 63f3361..8a45fbd 100644 --- a/drivers/net/keystone_net.c +++ b/drivers/net/keystone_net.c @@ -554,7 +554,20 @@ int keystone2_emac_initialize(struct eth_priv_t *eth_priv) return 0; } +struct ks2_serdes ks2_serdes_sgmii_156p25mhz = { + .clk = SERDES_CLOCK_156P25M, + .rate = SERDES_RATE_5G, + .rate_mode = SERDES_QUARTER_RATE, + .intf = SERDES_PHY_SGMII, + .loopback = 0, +}; + static void keystone2_net_serdes_setup(void) { - ks2_serdes_sgmii_156p25mhz_setup(); + ks2_serdes_init(CONFIG_KSNET_SERDES_SGMII_BASE, + &ks2_serdes_sgmii_156p25mhz, + CONFIG_KSNET_SERDES_LANES_PER_SGMII); + + /* wait till setup */ + udelay(5000); } -- cgit v1.1 From adc9a79f3f7c6d79f32048598f4d18cf0f48180f Mon Sep 17 00:00:00 2001 From: "Khoronzhuk, Ivan" Date: Fri, 17 Oct 2014 20:44:32 +0300 Subject: net: phy: print a number of phy that is not found In case when several Ethernet ports are supported it's convenient to see the number of phy that is not found. Acked-by: Vitaly Andrianov Signed-off-by: Ivan Khoronzhuk --- drivers/net/phy/phy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index 1d6c14f..99b0b83 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -648,7 +648,7 @@ static struct phy_device *get_phy_device_by_mask(struct mii_dev *bus, if (phydev) return phydev; } - printf("Phy not found\n"); + printf("Phy %d not found\n", ffs(phy_mask) - 1); return phy_device_create(bus, ffs(phy_mask) - 1, 0xffffffff, interface); } -- cgit v1.1 From 1920e905efcd528b43535e0b19f6b433d321fa76 Mon Sep 17 00:00:00 2001 From: "Khoronzhuk, Ivan" Date: Fri, 17 Oct 2014 20:44:33 +0300 Subject: net: keystone_net: use mdio_reset function Don't use mdio_enable twice while eth open. Also rename it to keystone2_mdio_reset as more appropriate name. Acked-by: Vitaly Andrianov Signed-off-by: Ivan Khoronzhuk --- drivers/net/keystone_net.c | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/keystone_net.c b/drivers/net/keystone_net.c index 8a45fbd..3f9650c 100644 --- a/drivers/net/keystone_net.c +++ b/drivers/net/keystone_net.c @@ -38,7 +38,6 @@ struct rx_buff_desc net_rx_buffs = { .rx_flow = 22, }; -static void keystone2_eth_mdio_enable(void); static void keystone2_net_serdes_setup(void); static int gen_get_link_speed(int phy_addr); @@ -71,7 +70,7 @@ int keystone2_eth_read_mac_addr(struct eth_device *dev) return 0; } -static void keystone2_eth_mdio_enable(void) +static void keystone2_mdio_reset(void) { u_int32_t clkdiv; @@ -397,7 +396,6 @@ int32_t cpmac_drv_send(u32 *buffer, int num_bytes, int slave_port_num) /* Eth device open */ static int keystone2_eth_open(struct eth_device *dev, bd_t *bis) { - u_int32_t clkdiv; int link; struct eth_priv_t *eth_priv = (struct eth_priv_t *)dev->priv; @@ -410,9 +408,6 @@ static int keystone2_eth_open(struct eth_device *dev, bd_t *bis) keystone2_net_serdes_setup(); - if (sys_has_mdio) - keystone2_eth_mdio_enable(); - keystone_sgmii_config(eth_priv->slave_port - 1, eth_priv->sgmii_link_type); @@ -440,14 +435,7 @@ static int keystone2_eth_open(struct eth_device *dev, bd_t *bis) hw_config_streaming_switch(); if (sys_has_mdio) { - /* Init MDIO & get link state */ - clkdiv = (EMAC_MDIO_BUS_FREQ / EMAC_MDIO_CLOCK_FREQ) - 1; - writel((clkdiv & 0xff) | MDIO_CONTROL_ENABLE | - MDIO_CONTROL_FAULT, &adap_mdio->control) - ; - - /* We need to wait for MDIO to start */ - udelay(1000); + keystone2_mdio_reset(); link = keystone_get_link_status(dev); if (link == 0) { -- cgit v1.1 From 550c5ce6f5b16e67f9af4c170efb91f1e342bafa Mon Sep 17 00:00:00 2001 From: "Khoronzhuk, Ivan" Date: Fri, 17 Oct 2014 20:44:34 +0300 Subject: net: keystone_net: register MDIO bus Currently MDIO framework is not used to configure Ethernet PHY. As result some of already implemented functions are duplicated. So register MDIO bus in order to use it. On that stage it's just registered, it'll be used as we start to use PHY framework. Use mdio bus read/write/reset functions in the driver. Acked-by: Vitaly Andrianov Signed-off-by: Ivan Khoronzhuk --- drivers/net/keystone_net.c | 93 +++++++++++++++++++++++++++------------------- 1 file changed, 55 insertions(+), 38 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/keystone_net.c b/drivers/net/keystone_net.c index 3f9650c..265530a 100644 --- a/drivers/net/keystone_net.c +++ b/drivers/net/keystone_net.c @@ -17,6 +17,7 @@ #include unsigned int emac_open; +static struct mii_dev *mdio_bus; static unsigned int sys_has_mdio = 1; #ifdef KEYSTONE2_EMAC_GIG_ENABLE @@ -42,10 +43,6 @@ static void keystone2_net_serdes_setup(void); static int gen_get_link_speed(int phy_addr); -/* EMAC Addresses */ -static volatile struct mdio_regs *adap_mdio = - (struct mdio_regs *)EMAC_MDIO_BASE_ADDR; - int keystone2_eth_read_mac_addr(struct eth_device *dev) { struct eth_priv_t *eth_priv; @@ -70,64 +67,67 @@ int keystone2_eth_read_mac_addr(struct eth_device *dev) return 0; } -static void keystone2_mdio_reset(void) +/* MDIO */ + +static int keystone2_mdio_reset(struct mii_dev *bus) { - u_int32_t clkdiv; + u_int32_t clkdiv; + struct mdio_regs *adap_mdio = bus->priv; clkdiv = (EMAC_MDIO_BUS_FREQ / EMAC_MDIO_CLOCK_FREQ) - 1; - writel((clkdiv & 0xffff) | - MDIO_CONTROL_ENABLE | - MDIO_CONTROL_FAULT | - MDIO_CONTROL_FAULT_ENABLE, + writel((clkdiv & 0xffff) | MDIO_CONTROL_ENABLE | + MDIO_CONTROL_FAULT | MDIO_CONTROL_FAULT_ENABLE, &adap_mdio->control); while (readl(&adap_mdio->control) & MDIO_CONTROL_IDLE) ; + + return 0; } -/* Read a PHY register via MDIO inteface. Returns 1 on success, 0 otherwise */ -int keystone2_eth_phy_read(u_int8_t phy_addr, u_int8_t reg_num, u_int16_t *data) +/** + * keystone2_mdio_read - read a PHY register via MDIO interface. + * Blocks until operation is complete. + */ +static int keystone2_mdio_read(struct mii_dev *bus, + int addr, int devad, int reg) { - int tmp; + int tmp; + struct mdio_regs *adap_mdio = bus->priv; while (readl(&adap_mdio->useraccess0) & MDIO_USERACCESS0_GO) ; - writel(MDIO_USERACCESS0_GO | - MDIO_USERACCESS0_WRITE_READ | - ((reg_num & 0x1f) << 21) | - ((phy_addr & 0x1f) << 16), + writel(MDIO_USERACCESS0_GO | MDIO_USERACCESS0_WRITE_READ | + ((reg & 0x1f) << 21) | ((addr & 0x1f) << 16), &adap_mdio->useraccess0); /* Wait for command to complete */ while ((tmp = readl(&adap_mdio->useraccess0)) & MDIO_USERACCESS0_GO) ; - if (tmp & MDIO_USERACCESS0_ACK) { - *data = tmp & 0xffff; - return 0; - } + if (tmp & MDIO_USERACCESS0_ACK) + return tmp & 0xffff; - *data = -1; return -1; } -/* - * Write to a PHY register via MDIO inteface. +/** + * keystone2_mdio_write - write to a PHY register via MDIO interface. * Blocks until operation is complete. */ -int keystone2_eth_phy_write(u_int8_t phy_addr, u_int8_t reg_num, u_int16_t data) +static int keystone2_mdio_write(struct mii_dev *bus, + int addr, int devad, int reg, u16 val) { + struct mdio_regs *adap_mdio = bus->priv; + while (readl(&adap_mdio->useraccess0) & MDIO_USERACCESS0_GO) ; - writel(MDIO_USERACCESS0_GO | - MDIO_USERACCESS0_WRITE_WRITE | - ((reg_num & 0x1f) << 21) | - ((phy_addr & 0x1f) << 16) | - (data & 0xffff), - &adap_mdio->useraccess0); + writel(MDIO_USERACCESS0_GO | MDIO_USERACCESS0_WRITE_WRITE | + ((reg & 0x1f) << 21) | ((addr & 0x1f) << 16) | + (val & 0xffff), &adap_mdio->useraccess0); /* Wait for command to complete */ while (readl(&adap_mdio->useraccess0) & MDIO_USERACCESS0_GO) @@ -139,12 +139,12 @@ int keystone2_eth_phy_write(u_int8_t phy_addr, u_int8_t reg_num, u_int16_t data) /* PHY functions for a generic PHY */ static int gen_get_link_speed(int phy_addr) { - u_int16_t tmp; + u_int16_t tmp; - if ((!keystone2_eth_phy_read(phy_addr, MII_STATUS_REG, &tmp)) && - (tmp & 0x04)) { + tmp = mdio_bus->read(mdio_bus, phy_addr, + MDIO_DEVAD_NONE, MII_STATUS_REG); + if (tmp & 0x04) return 0; - } return -1; } @@ -156,8 +156,10 @@ static void __attribute__((unused)) struct eth_priv_t *eth_priv = (struct eth_priv_t *)dev->priv; if (sys_has_mdio) { - if (keystone2_eth_phy_read(eth_priv->phy_addr, 0, &data) || - !(data & (1 << 6))) /* speed selection MSB */ + data = keystone2_mdio_read(mdio_bus, eth_priv->phy_addr, + MDIO_DEVAD_NONE, 0); + /* speed selection MSB */ + if (!(data & (1 << 6))) return; } @@ -435,7 +437,7 @@ static int keystone2_eth_open(struct eth_device *dev, bd_t *bis) hw_config_streaming_switch(); if (sys_has_mdio) { - keystone2_mdio_reset(); + keystone2_mdio_reset(mdio_bus); link = keystone_get_link_status(dev); if (link == 0) { @@ -518,6 +520,7 @@ static int keystone2_eth_rcv_packet(struct eth_device *dev) */ int keystone2_emac_initialize(struct eth_priv_t *eth_priv) { + int res; struct eth_device *dev; dev = malloc(sizeof(struct eth_device)); @@ -539,6 +542,20 @@ int keystone2_emac_initialize(struct eth_priv_t *eth_priv) eth_register(dev); + /* Register MDIO bus if it's not registered yet */ + if (!mdio_bus) { + mdio_bus = mdio_alloc(); + mdio_bus->read = keystone2_mdio_read; + mdio_bus->write = keystone2_mdio_write; + mdio_bus->reset = keystone2_mdio_reset; + mdio_bus->priv = (void *)EMAC_MDIO_BASE_ADDR; + sprintf(mdio_bus->name, "ethernet-mdio"); + + res = mdio_register(mdio_bus); + if (res) + return res; + } + return 0; } -- cgit v1.1 From 3fe93623cc5f5c5373fe0c0b7fe331f8800f4350 Mon Sep 17 00:00:00 2001 From: "Khoronzhuk, Ivan" Date: Fri, 17 Oct 2014 20:44:35 +0300 Subject: net: keystone_net: register eth PHYs on MDIO bus As MDIO bus has been added we can register PHYs with it. After registration, the PHY driver will be probed according to the hardware on board. Startup PHY at the ethernet open. Use phy_startup() instead of keystone_get_link_status() when eth open, as it verifies PHY link inside and SGMII link is checked before. For K2HK evm PHY configuration at init was absent, so don't enable phy config at init for k2hk evm. Acked-by: Vitaly Andrianov Signed-off-by: Ivan Khoronzhuk --- drivers/net/keystone_net.c | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/keystone_net.c b/drivers/net/keystone_net.c index 265530a..fa8e1ef 100644 --- a/drivers/net/keystone_net.c +++ b/drivers/net/keystone_net.c @@ -10,6 +10,7 @@ #include #include +#include #include #include #include @@ -398,8 +399,8 @@ int32_t cpmac_drv_send(u32 *buffer, int num_bytes, int slave_port_num) /* Eth device open */ static int keystone2_eth_open(struct eth_device *dev, bd_t *bis) { - int link; struct eth_priv_t *eth_priv = (struct eth_priv_t *)dev->priv; + struct phy_device *phy_dev = eth_priv->phy_dev; debug("+ emac_open\n"); @@ -439,8 +440,8 @@ static int keystone2_eth_open(struct eth_device *dev, bd_t *bis) if (sys_has_mdio) { keystone2_mdio_reset(mdio_bus); - link = keystone_get_link_status(dev); - if (link == 0) { + phy_startup(phy_dev); + if (phy_dev->link == 0) { ksnav_close(&netcp_pktdma); qm_close(); return -1; @@ -461,6 +462,9 @@ static int keystone2_eth_open(struct eth_device *dev, bd_t *bis) /* Eth device close */ void keystone2_eth_close(struct eth_device *dev) { + struct eth_priv_t *eth_priv = (struct eth_priv_t *)dev->priv; + struct phy_device *phy_dev = eth_priv->phy_dev; + debug("+ emac_close\n"); if (!emac_open) @@ -470,6 +474,7 @@ void keystone2_eth_close(struct eth_device *dev) ksnav_close(&netcp_pktdma); qm_close(); + phy_shutdown(phy_dev); emac_open = 0; @@ -522,6 +527,7 @@ int keystone2_emac_initialize(struct eth_priv_t *eth_priv) { int res; struct eth_device *dev; + struct phy_device *phy_dev; dev = malloc(sizeof(struct eth_device)); if (dev == NULL) @@ -556,6 +562,18 @@ int keystone2_emac_initialize(struct eth_priv_t *eth_priv) return res; } + /* Create phy device and bind it with driver */ +#ifdef CONFIG_KSNET_MDIO_PHY_CONFIG_ENABLE + phy_dev = phy_connect(mdio_bus, eth_priv->phy_addr, + dev, PHY_INTERFACE_MODE_SGMII); + phy_config(phy_dev); +#else + phy_dev = phy_find_by_mask(mdio_bus, 1 << eth_priv->phy_addr, + PHY_INTERFACE_MODE_SGMII); + phy_dev->dev = dev; +#endif + eth_priv->phy_dev = phy_dev; + return 0; } -- cgit v1.1 From a4d2adee110d1534705d84c573a41e6d7877f0d7 Mon Sep 17 00:00:00 2001 From: "Khoronzhuk, Ivan" Date: Fri, 17 Oct 2014 20:44:36 +0300 Subject: net: keystone_net: use general get link function The phy framework has function to get link, so use it instead of own implementation. There is no reason to check SGMII link while sending each packet, phy link is enough. Check SGMII link only while ethernet open. Acked-by: Vitaly Andrianov Signed-off-by: Ivan Khoronzhuk --- drivers/net/keystone_net.c | 50 +++++----------------------------------------- 1 file changed, 5 insertions(+), 45 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/keystone_net.c b/drivers/net/keystone_net.c index fa8e1ef..13a1778 100644 --- a/drivers/net/keystone_net.c +++ b/drivers/net/keystone_net.c @@ -42,8 +42,6 @@ struct rx_buff_desc net_rx_buffs = { static void keystone2_net_serdes_setup(void); -static int gen_get_link_speed(int phy_addr); - int keystone2_eth_read_mac_addr(struct eth_device *dev) { struct eth_priv_t *eth_priv; @@ -137,19 +135,6 @@ static int keystone2_mdio_write(struct mii_dev *bus, return 0; } -/* PHY functions for a generic PHY */ -static int gen_get_link_speed(int phy_addr) -{ - u_int16_t tmp; - - tmp = mdio_bus->read(mdio_bus, phy_addr, - MDIO_DEVAD_NONE, MII_STATUS_REG); - if (tmp & 0x04) - return 0; - - return -1; -} - static void __attribute__((unused)) keystone2_eth_gigabit_enable(struct eth_device *dev) { @@ -180,35 +165,8 @@ int keystone_sgmii_link_status(int port) status = __raw_readl(SGMII_STATUS_REG(port)); - return status & SGMII_REG_STATUS_LINK; -} - - -int keystone_get_link_status(struct eth_device *dev) -{ - struct eth_priv_t *eth_priv = (struct eth_priv_t *)dev->priv; - int sgmii_link; - int link_state = 0; -#if CONFIG_GET_LINK_STATUS_ATTEMPTS > 1 - int j; - - for (j = 0; (j < CONFIG_GET_LINK_STATUS_ATTEMPTS) && (link_state == 0); - j++) { -#endif - sgmii_link = - keystone_sgmii_link_status(eth_priv->slave_port - 1); - - if (sgmii_link) { - link_state = 1; - - if (eth_priv->sgmii_link_type == SGMII_LINK_MAC_PHY) - if (gen_get_link_speed(eth_priv->phy_addr)) - link_state = 0; - } -#if CONFIG_GET_LINK_STATUS_ATTEMPTS > 1 - } -#endif - return link_state; + return (status & SGMII_REG_STATUS_LOCK) && + (status & SGMII_REG_STATUS_LINK); } int keystone_sgmii_config(int port, int interface) @@ -490,8 +448,10 @@ static int keystone2_eth_send_packet(struct eth_device *dev, { int ret_status = -1; struct eth_priv_t *eth_priv = (struct eth_priv_t *)dev->priv; + struct phy_device *phy_dev = eth_priv->phy_dev; - if (keystone_get_link_status(dev) == 0) + genphy_update_link(phy_dev); + if (phy_dev->link == 0) return -1; if (cpmac_drv_send((u32 *)packet, length, eth_priv->slave_port) != 0) -- cgit v1.1 From 3c61502aad85e8b25b75e349dfd5a5a7eee22301 Mon Sep 17 00:00:00 2001 From: "Khoronzhuk, Ivan" Date: Fri, 17 Oct 2014 21:01:13 +0300 Subject: net: keystone_serdes: add keystone K2E SoC support Keystone2 Edison SoC uses the same keystone SerDes driver. This patch adds support for K2E SoCs. Acked-by: Vitaly Andrianov Acked-by: Murali Karicheri Signed-off-by: Ivan Khoronzhuk --- drivers/net/keystone_net.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/keystone_net.c b/drivers/net/keystone_net.c index 13a1778..43c263e 100644 --- a/drivers/net/keystone_net.c +++ b/drivers/net/keystone_net.c @@ -551,6 +551,12 @@ static void keystone2_net_serdes_setup(void) &ks2_serdes_sgmii_156p25mhz, CONFIG_KSNET_SERDES_LANES_PER_SGMII); +#ifdef CONFIG_SOC_K2E + ks2_serdes_init(CONFIG_KSNET_SERDES_SGMII2_BASE, + &ks2_serdes_sgmii_156p25mhz, + CONFIG_KSNET_SERDES_LANES_PER_SGMII); +#endif + /* wait till setup */ udelay(5000); } -- cgit v1.1 From ff11c7697cee84d03e8020cc6198554550cd3ea2 Mon Sep 17 00:00:00 2001 From: "Khoronzhuk, Ivan" Date: Fri, 17 Oct 2014 21:01:14 +0300 Subject: net: keystone_net: add Keystone2 K2E SoC support The Keystone2 Edison SoC uses the same keystone net driver. This patch adds opportunity to use it by K2E SoCs. Acked-by: Vitaly Andrianov Acked-by: Murali Karicheri Signed-off-by: Ivan Khoronzhuk --- drivers/net/keystone_net.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/keystone_net.c b/drivers/net/keystone_net.c index 43c263e..1186188 100644 --- a/drivers/net/keystone_net.c +++ b/drivers/net/keystone_net.c @@ -289,6 +289,11 @@ int mac_sl_config(u_int16_t port, struct mac_sl_cfg *cfg) writel(cfg->max_rx_len, DEVICE_EMACSL_BASE(port) + CPGMACSL_REG_MAXLEN); writel(cfg->ctl, DEVICE_EMACSL_BASE(port) + CPGMACSL_REG_CTL); +#ifdef CONFIG_K2E_EVM + /* Map RX packet flow priority to 0 */ + writel(0, DEVICE_EMACSL_BASE(port) + CPGMACSL_REG_RX_PRI_MAP); +#endif + return ret; } -- cgit v1.1 From c05d05e7202b01a1b461c78ba6c5b06545621620 Mon Sep 17 00:00:00 2001 From: "Khoronzhuk, Ivan" Date: Fri, 17 Oct 2014 21:01:15 +0300 Subject: net: keystone_net: increase PHY auto negotiate time The new Marvel PHY (88E1514) used on K2L/K2E EVM requires longer time to auto negotiate with SoC's SGMII port. It can take about 3 sec to up the PHY after reset, so add code to expose sgmii auto negotiation waiting process. Acked-by: Vitaly Andrianov Signed-off-by: Ivan Khoronzhuk --- drivers/net/keystone_net.c | 36 +++++++++++++++++++++++++++++++----- 1 file changed, 31 insertions(+), 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/keystone_net.c b/drivers/net/keystone_net.c index 1186188..c8681d0 100644 --- a/drivers/net/keystone_net.c +++ b/drivers/net/keystone_net.c @@ -11,6 +11,7 @@ #include #include +#include #include #include #include @@ -30,6 +31,7 @@ static unsigned int sys_has_mdio = 1; #define RX_BUFF_NUMS 24 #define RX_BUFF_LEN 1520 #define MAX_SIZE_STREAM_BUFFER RX_BUFF_LEN +#define SGMII_ANEG_TIMEOUT 4000 static u8 rx_buffs[RX_BUFF_NUMS * RX_BUFF_LEN] __aligned(16); @@ -169,7 +171,7 @@ int keystone_sgmii_link_status(int port) (status & SGMII_REG_STATUS_LINK); } -int keystone_sgmii_config(int port, int interface) +int keystone_sgmii_config(struct phy_device *phy_dev, int port, int interface) { unsigned int i, status, mask; unsigned int mr_adv_ability, control; @@ -230,11 +232,35 @@ int keystone_sgmii_config(int port, int interface) if (control & SGMII_REG_CONTROL_AUTONEG) mask |= SGMII_REG_STATUS_AUTONEG; - for (i = 0; i < 1000; i++) { + status = __raw_readl(SGMII_STATUS_REG(port)); + if ((status & mask) == mask) + return 0; + + printf("\n%s Waiting for SGMII auto negotiation to complete", + phy_dev->dev->name); + while ((status & mask) != mask) { + /* + * Timeout reached ? + */ + if (i > SGMII_ANEG_TIMEOUT) { + puts(" TIMEOUT !\n"); + phy_dev->link = 0; + return 0; + } + + if (ctrlc()) { + puts("user interrupt!\n"); + phy_dev->link = 0; + return -EINTR; + } + + if ((i++ % 500) == 0) + printf("."); + + udelay(1000); /* 1 ms */ status = __raw_readl(SGMII_STATUS_REG(port)); - if ((status & mask) == mask) - break; } + puts(" done\n"); return 0; } @@ -374,7 +400,7 @@ static int keystone2_eth_open(struct eth_device *dev, bd_t *bis) keystone2_net_serdes_setup(); - keystone_sgmii_config(eth_priv->slave_port - 1, + keystone_sgmii_config(phy_dev, eth_priv->slave_port - 1, eth_priv->sgmii_link_type); udelay(10000); -- cgit v1.1