[U-Boot] [U-boot] [Patch v4 0/4] keystone2: serdes: add seredes driver

This patch series adds serdes driver, moving it from keystone_net driver.
Based on "[U-boot] [Patch v2 0/5] keystone2: generalize keystone_net driver usage" http://u-boot.10912.n7.nabble.com/U-boot-Patch-v2-0-5-keystone2-generalize- keystone-net-driver-usage-td190624.html
v4..v3: - soc: keystone_serdes: create a separate SGMII SerDes driver squashed with "soc: add soc specific drivers directory"
v3..v1: just rebase.
Hao Zhang (2): soc: keystone_serdes: enhance to use cmu/comlane/lane specific configurations soc: keystone_serdes: generalize to be used by other sub systems
Ivan Khoronzhuk (2): soc: keystone_serdes: create a separate SGMII SerDes driver soc: keystone_serdes: generalize configuration mechanism
arch/arm/include/asm/arch-keystone/hardware-k2hk.h | 3 + arch/arm/include/asm/arch-keystone/hardware.h | 3 + arch/arm/include/asm/ti-common/keystone_serdes.h | 55 ++++++ drivers/Makefile | 2 + drivers/net/keystone_net.c | 154 ++------------- drivers/soc/Makefile | 5 + drivers/soc/keystone/Makefile | 1 + drivers/soc/keystone/keystone_serdes.c | 210 +++++++++++++++++++++ include/configs/k2hk_evm.h | 3 + include/configs/ks2_evm.h | 6 +- 10 files changed, 303 insertions(+), 139 deletions(-) create mode 100644 arch/arm/include/asm/ti-common/keystone_serdes.h create mode 100644 drivers/soc/Makefile create mode 100644 drivers/soc/keystone/Makefile create mode 100644 drivers/soc/keystone/keystone_serdes.c

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 hzhang@ti.com Signed-off-by: Ivan Khoronzhuk ivan.khoronzhuk@ti.com --- arch/arm/include/asm/ti-common/keystone_serdes.h | 15 +++ drivers/Makefile | 2 + drivers/net/keystone_net.c | 143 +---------------------- drivers/soc/Makefile | 5 + drivers/soc/keystone/Makefile | 1 + drivers/soc/keystone/keystone_serdes.c | 127 ++++++++++++++++++++ include/configs/k2hk_evm.h | 3 + 7 files changed, 158 insertions(+), 138 deletions(-) create mode 100644 arch/arm/include/asm/ti-common/keystone_serdes.h create mode 100644 drivers/soc/Makefile create mode 100644 drivers/soc/keystone/Makefile create mode 100644 drivers/soc/keystone/keystone_serdes.c
diff --git a/arch/arm/include/asm/ti-common/keystone_serdes.h b/arch/arm/include/asm/ti-common/keystone_serdes.h new file mode 100644 index 0000000..2e12b05 --- /dev/null +++ b/arch/arm/include/asm/ti-common/keystone_serdes.h @@ -0,0 +1,15 @@ +/* + * Texas Instruments Keystone SerDes driver + * + * (C) Copyright 2014 + * Texas Instruments Incorporated, <www.ti.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __TI_KEYSTONE_SERDES_H__ +#define __TI_KEYSTONE_SERDES_H__ + +void ks2_serdes_sgmii_156p25mhz_setup(void); + +#endif /* __TI_KEYSTONE_SERDES_H__ */ diff --git a/drivers/Makefile b/drivers/Makefile index b22b109..fc9b630 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -16,3 +16,5 @@ obj-y += watchdog/ obj-$(CONFIG_QE) += qe/ obj-y += memory/ obj-y += pwm/ +# SOC specific infrastructure drivers. +obj-y += soc/ 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 <malloc.h> #include <asm/ti-common/keystone_nav.h> #include <asm/ti-common/keystone_net.h> +#include <asm/ti-common/keystone_serdes.h>
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(); } diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile new file mode 100644 index 0000000..3d4baa5 --- /dev/null +++ b/drivers/soc/Makefile @@ -0,0 +1,5 @@ +# +# Makefile for the U-boot SOC specific device drivers. +# + +obj-$(CONFIG_ARCH_KEYSTONE) += keystone/ diff --git a/drivers/soc/keystone/Makefile b/drivers/soc/keystone/Makefile new file mode 100644 index 0000000..c000eca --- /dev/null +++ b/drivers/soc/keystone/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_TI_KEYSTONE_SERDES) += keystone_serdes.o diff --git a/drivers/soc/keystone/keystone_serdes.c b/drivers/soc/keystone/keystone_serdes.c new file mode 100644 index 0000000..dc4e78d --- /dev/null +++ b/drivers/soc/keystone/keystone_serdes.c @@ -0,0 +1,127 @@ +/* + * TI serdes driver for keystone2. + * + * (C) Copyright 2014 + * Texas Instruments Incorporated, <www.ti.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> + +void ks2_serdes_sgmii_156p25mhz_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); +} diff --git a/include/configs/k2hk_evm.h b/include/configs/k2hk_evm.h index 45bd72d..034cbfd 100644 --- a/include/configs/k2hk_evm.h +++ b/include/configs/k2hk_evm.h @@ -41,4 +41,7 @@ #define CONFIG_KSNET_NETCP_V1_0 #define CONFIG_KSNET_CPSW_NUM_PORTS 5
+/* SerDes */ +#define CONFIG_TI_KEYSTONE_SERDES + #endif /* __CONFIG_K2HK_EVM_H */

On Wed, Oct 22, 2014 at 05:18:21PM +0300, Khoronzhuk, Ivan wrote:
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 hzhang@ti.com Signed-off-by: Ivan Khoronzhuk ivan.khoronzhuk@ti.com
Applied to u-boot-ti/master, thanks!

From: Hao Zhang hzhang@ti.com
Enhance the driver to use cmu/comlane/lane specific configurations instead of 1 big array of configuration.
Signed-off-by: Hao Zhang hzhang@ti.com Signed-off-by: Ivan Khoronzhuk ivan.khoronzhuk@ti.com --- arch/arm/include/asm/arch-keystone/hardware-k2hk.h | 3 + arch/arm/include/asm/arch-keystone/hardware.h | 3 + drivers/soc/keystone/keystone_serdes.c | 166 +++++++++++---------- include/configs/ks2_evm.h | 4 + 4 files changed, 94 insertions(+), 82 deletions(-)
diff --git a/arch/arm/include/asm/arch-keystone/hardware-k2hk.h b/arch/arm/include/asm/arch-keystone/hardware-k2hk.h index 706b21d..28de3f5 100644 --- a/arch/arm/include/asm/arch-keystone/hardware-k2hk.h +++ b/arch/arm/include/asm/arch-keystone/hardware-k2hk.h @@ -79,6 +79,9 @@ #define KS2_DDR3B_EMIF_DATA_BASE 0x60000000 #define KS2_DDR3B_DDRPHYC 0x02328000
+/* SGMII SerDes */ +#define KS2_LANES_PER_SGMII_SERDES 4 + /* Number of DSP cores */ #define KS2_NUM_DSPS 8
diff --git a/arch/arm/include/asm/arch-keystone/hardware.h b/arch/arm/include/asm/arch-keystone/hardware.h index 0441b29..6e2e939 100644 --- a/arch/arm/include/asm/arch-keystone/hardware.h +++ b/arch/arm/include/asm/arch-keystone/hardware.h @@ -177,6 +177,9 @@ typedef volatile unsigned int *dv_reg_p;
#define KS2_MAC_ID_BASE_ADDR (KS2_DEVICE_STATE_CTRL_BASE + 0x110)
+/* SGMII SerDes */ +#define KS2_SGMII_SERDES_BASE 0x0232a000 + #ifdef CONFIG_SOC_K2HK #include <asm/arch/hardware-k2hk.h> #endif diff --git a/drivers/soc/keystone/keystone_serdes.c b/drivers/soc/keystone/keystone_serdes.c index dc4e78d..3632c22 100644 --- a/drivers/soc/keystone/keystone_serdes.c +++ b/drivers/soc/keystone/keystone_serdes.c @@ -9,92 +9,94 @@
#include <common.h>
+#define SERDES_LANE_REGS(x) (0x0200 + (0x200 * (x))) + +struct serdes_cfg { + u32 ofs; + u32 val; + u32 mask; +}; + +static struct serdes_cfg cfg_cmu_156p25m_5g[] = { + {0x0000, 0x00800000, 0xffff0000}, + {0x0014, 0x00008282, 0x0000ffff}, + {0x0060, 0x00142438, 0x00ffffff}, + {0x0064, 0x00c3c700, 0x00ffff00}, + {0x0078, 0x0000c000, 0x0000ff00} +}; + +static struct serdes_cfg cfg_comlane_156p25m_5g[] = { + {0x0a00, 0x00000800, 0x0000ff00}, + {0x0a08, 0x38a20000, 0xffff0000}, + {0x0a30, 0x008a8a00, 0x00ffff00}, + {0x0a84, 0x00000600, 0x0000ff00}, + {0x0a94, 0x10000000, 0xff000000}, + {0x0aa0, 0x81000000, 0xff000000}, + {0x0abc, 0xff000000, 0xff000000}, + {0x0ac0, 0x0000008b, 0x000000ff}, + {0x0b08, 0x583f0000, 0xffff0000}, + {0x0b0c, 0x0000004e, 0x000000ff} +}; + +static struct serdes_cfg cfg_lane_156p25mhz_5g[] = { + {0x0004, 0x38000080, 0xff0000ff}, + {0x0008, 0x00000000, 0x000000ff}, + {0x000c, 0x02000000, 0xff000000}, + {0x0010, 0x1b000000, 0xff000000}, + {0x0014, 0x00006fb8, 0x0000ffff}, + {0x0018, 0x758000e4, 0xffff00ff}, + {0x00ac, 0x00004400, 0x0000ff00}, + {0x002c, 0x00100800, 0x00ffff00}, + {0x0080, 0x00820082, 0x00ff00ff}, + {0x0084, 0x1d0f0385, 0xffffffff} + +}; + +static inline void ks2_serdes_rmw(u32 addr, u32 value, u32 mask) +{ + writel(((readl(addr) & (~mask)) | (value & mask)), addr); +} + +static void ks2_serdes_cfg_setup(u32 base, struct serdes_cfg *cfg, u32 size) +{ + u32 i; + + for (i = 0; i < size; i++) + ks2_serdes_rmw(base + cfg[i].ofs, cfg[i].val, cfg[i].mask); +} + +static void ks2_serdes_lane_config(u32 base, struct serdes_cfg *cfg_lane, + u32 size, u32 lane) +{ + u32 i; + + for (i = 0; i < size; i++) + ks2_serdes_rmw(base + cfg_lane[i].ofs + SERDES_LANE_REGS(lane), + cfg_lane[i].val, cfg_lane[i].mask); +} + +static int ks2_serdes_init_156p25m_5g(u32 base, u32 num_lanes) +{ + u32 i; + + ks2_serdes_cfg_setup(base, cfg_cmu_156p25m_5g, + ARRAY_SIZE(cfg_cmu_156p25m_5g)); + ks2_serdes_cfg_setup(base, cfg_comlane_156p25m_5g, + ARRAY_SIZE(cfg_comlane_156p25m_5g)); + + for (i = 0; i < num_lanes; i++) + ks2_serdes_lane_config(base, cfg_lane_156p25mhz_5g, + ARRAY_SIZE(cfg_lane_156p25mhz_5g), i); + + return 0; +} + void ks2_serdes_sgmii_156p25mhz_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); + ks2_serdes_init_156p25m_5g(CONFIG_KS2_SERDES_SGMII_BASE, + CONFIG_KS2_SERDES_LANES_PER_SGMII);
/*Bring SerDes out of Reset if SerDes is Shutdown & is in Reset Mode*/ clrbits_le32(0x0232a010, 1 << 28); diff --git a/include/configs/ks2_evm.h b/include/configs/ks2_evm.h index 01e2201..6900d75 100644 --- a/include/configs/ks2_evm.h +++ b/include/configs/ks2_evm.h @@ -321,4 +321,8 @@ which is NOT applicable for DDR ECC test */ #define CONFIG_MAX_UBOOT_MEM_SIZE (4 << 20) /* 4 MiB */
+/* SGMII SerDes */ +#define CONFIG_KS2_SERDES_SGMII_BASE KS2_SGMII_SERDES_BASE +#define CONFIG_KS2_SERDES_LANES_PER_SGMII KS2_LANES_PER_SGMII_SERDES + #endif /* __CONFIG_KS2_EVM_H */

On Wed, Oct 22, 2014 at 05:18:22PM +0300, Khoronzhuk, Ivan wrote:
From: Hao Zhang hzhang@ti.com
Enhance the driver to use cmu/comlane/lane specific configurations instead of 1 big array of configuration.
Signed-off-by: Hao Zhang hzhang@ti.com Signed-off-by: Ivan Khoronzhuk ivan.khoronzhuk@ti.com
Applied to u-boot-ti/master, thanks!

From: Hao Zhang hzhang@ti.com
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 hzhang@ti.com Signed-off-by: Ivan Khoronzhuk ivan.khoronzhuk@ti.com --- arch/arm/include/asm/ti-common/keystone_serdes.h | 42 +++++++- drivers/net/keystone_net.c | 15 ++- drivers/soc/keystone/keystone_serdes.c | 131 +++++++++++++++++------ include/configs/ks2_evm.h | 10 +- 4 files changed, 156 insertions(+), 42 deletions(-)
diff --git a/arch/arm/include/asm/ti-common/keystone_serdes.h b/arch/arm/include/asm/ti-common/keystone_serdes.h index 2e12b05..2e92411 100644 --- a/arch/arm/include/asm/ti-common/keystone_serdes.h +++ b/arch/arm/include/asm/ti-common/keystone_serdes.h @@ -10,6 +10,46 @@ #ifndef __TI_KEYSTONE_SERDES_H__ #define __TI_KEYSTONE_SERDES_H__
-void ks2_serdes_sgmii_156p25mhz_setup(void); +/* SERDES Reference clock */ +enum ks2_serdes_clock { + SERDES_CLOCK_100M, /* 100 MHz */ + SERDES_CLOCK_122P88M, /* 122.88 MHz */ + SERDES_CLOCK_125M, /* 125 MHz */ + SERDES_CLOCK_156P25M, /* 156.25 MHz */ + SERDES_CLOCK_312P5M, /* 312.5 MHz */ +}; + +/* SERDES Lane Baud Rate */ +enum ks2_serdes_rate { + SERDES_RATE_4P9152G, /* 4.9152 GBaud */ + SERDES_RATE_5G, /* 5 GBaud */ + SERDES_RATE_6P144G, /* 6.144 GBaud */ + SERDES_RATE_6P25G, /* 6.25 GBaud */ + SERDES_RATE_10p3125g, /* 10.3215 GBaud */ + SERDES_RATE_12p5g, /* 12.5 GBaud */ +}; + +/* SERDES Lane Rate Mode */ +enum ks2_serdes_rate_mode { + SERDES_FULL_RATE, + SERDES_HALF_RATE, + SERDES_QUARTER_RATE, +}; + +/* SERDES PHY TYPE */ +enum ks2_serdes_interface { + SERDES_PHY_SGMII, + SERDES_PHY_PCSR, /* XGE SERDES */ +}; + +struct ks2_serdes { + enum ks2_serdes_clock clk; + enum ks2_serdes_rate rate; + enum ks2_serdes_rate_mode rate_mode; + enum ks2_serdes_interface intf; + u32 loopback; +}; + +int ks2_serdes_init(u32 base, struct ks2_serdes *serdes, u32 num_lanes);
#endif /* __TI_KEYSTONE_SERDES_H__ */ 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); } diff --git a/drivers/soc/keystone/keystone_serdes.c b/drivers/soc/keystone/keystone_serdes.c index 3632c22..84ed9ba 100644 --- a/drivers/soc/keystone/keystone_serdes.c +++ b/drivers/soc/keystone/keystone_serdes.c @@ -7,9 +7,27 @@ * SPDX-License-Identifier: GPL-2.0+ */
+#include <errno.h> #include <common.h> +#include <asm/ti-common/keystone_serdes.h>
+#define SERDES_CMU_REGS(x) (0x0000 + (0x0c00 * (x))) #define SERDES_LANE_REGS(x) (0x0200 + (0x200 * (x))) +#define SERDES_COMLANE_REGS 0x0a00 +#define SERDES_WIZ_REGS 0x1fc0 + +#define SERDES_CMU_REG_000(x) (SERDES_CMU_REGS(x) + 0x000) +#define SERDES_CMU_REG_010(x) (SERDES_CMU_REGS(x) + 0x010) +#define SERDES_COMLANE_REG_000 (SERDES_COMLANE_REGS + 0x000) +#define SERDES_LANE_REG_000(x) (SERDES_LANE_REGS(x) + 0x000) +#define SERDES_LANE_REG_028(x) (SERDES_LANE_REGS(x) + 0x028) +#define SERDES_LANE_CTL_STATUS_REG(x) (SERDES_WIZ_REGS + 0x0020 + (4 * (x))) +#define SERDES_PLL_CTL_REG (SERDES_WIZ_REGS + 0x0034) + +#define SERDES_RESET BIT(28) +#define SERDES_LANE_RESET BIT(29) +#define SERDES_LANE_LOOPBACK BIT(30) +#define SERDES_LANE_EN_VAL(x, y, z) (x[y] | (z << 26) | (z << 10))
struct serdes_cfg { u32 ofs; @@ -17,6 +35,18 @@ struct serdes_cfg { u32 mask; };
+/* SERDES PHY lane enable configuration value, indexed by PHY interface */ +static u32 serdes_cfg_lane_enable[] = { + 0xf000f0c0, /* SGMII */ + 0xf0e9f038, /* PCSR */ +}; + +/* SERDES PHY PLL enable configuration value, indexed by PHY interface */ +static u32 serdes_cfg_pll_enable[] = { + 0xe0000000, /* SGMII */ + 0xee000000, /* PCSR */ +}; + static struct serdes_cfg cfg_cmu_156p25m_5g[] = { {0x0000, 0x00800000, 0xffff0000}, {0x0014, 0x00008282, 0x0000ffff}, @@ -91,39 +121,72 @@ static int ks2_serdes_init_156p25m_5g(u32 base, u32 num_lanes) return 0; }
-void ks2_serdes_sgmii_156p25mhz_setup(void) +static void ks2_serdes_cmu_comlane_enable(u32 base, struct ks2_serdes *serdes) +{ + /* Bring SerDes out of Reset */ + ks2_serdes_rmw(base + SERDES_CMU_REG_010(0), 0x0, SERDES_RESET); + if (serdes->intf == SERDES_PHY_PCSR) + ks2_serdes_rmw(base + SERDES_CMU_REG_010(1), 0x0, SERDES_RESET); + + /* Enable CMU and COMLANE */ + ks2_serdes_rmw(base + SERDES_CMU_REG_000(0), 0x03, 0x000000ff); + if (serdes->intf == SERDES_PHY_PCSR) + ks2_serdes_rmw(base + SERDES_CMU_REG_000(1), 0x03, 0x000000ff); + + ks2_serdes_rmw(base + SERDES_COMLANE_REG_000, 0x5f, 0x000000ff); +} + +static void ks2_serdes_pll_enable(u32 base, struct ks2_serdes *serdes) +{ + writel(serdes_cfg_pll_enable[serdes->intf], + base + SERDES_PLL_CTL_REG); +} + +static void ks2_serdes_lane_reset(u32 base, u32 reset, u32 lane) { - unsigned int cnt; - - ks2_serdes_init_156p25m_5g(CONFIG_KS2_SERDES_SGMII_BASE, - CONFIG_KS2_SERDES_LANES_PER_SGMII); - - /*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); + if (reset) + ks2_serdes_rmw(base + SERDES_LANE_REG_028(lane), + 0x1, SERDES_LANE_RESET); + else + ks2_serdes_rmw(base + SERDES_LANE_REG_028(lane), + 0x0, SERDES_LANE_RESET); +} + +static void ks2_serdes_lane_enable(u32 base, + struct ks2_serdes *serdes, u32 lane) +{ + /* Bring lane out of reset */ + ks2_serdes_lane_reset(base, 0, lane); + + writel(SERDES_LANE_EN_VAL(serdes_cfg_lane_enable, serdes->intf, + serdes->rate_mode), + base + SERDES_LANE_CTL_STATUS_REG(lane)); + + /* Set NES bit if Loopback Enabled */ + if (serdes->loopback) + ks2_serdes_rmw(base + SERDES_LANE_REG_000(lane), + 0x1, SERDES_LANE_LOOPBACK); +} + +int ks2_serdes_init(u32 base, struct ks2_serdes *serdes, u32 num_lanes) +{ + int i; + int ret = 0; + + /* The driver currently supports 5GBaud rate with ref clock 156.25MHz */ + if (serdes->clk == SERDES_CLOCK_156P25M) + if (serdes->rate == SERDES_RATE_5G) + ret = ks2_serdes_init_156p25m_5g(base, num_lanes); + else + return -EINVAL; + else + return -EINVAL; + + ks2_serdes_cmu_comlane_enable(base, serdes); + for (i = 0; i < num_lanes; i++) + ks2_serdes_lane_enable(base, serdes, i); + + ks2_serdes_pll_enable(base, serdes); + + return ret; } diff --git a/include/configs/ks2_evm.h b/include/configs/ks2_evm.h index 6900d75..7fbb648 100644 --- a/include/configs/ks2_evm.h +++ b/include/configs/ks2_evm.h @@ -136,8 +136,10 @@ #define CONFIG_KSNAV_NETCP_PDMA_TX_SND_QUEUE KS2_NETCP_PDMA_TX_SND_QUEUE
/* Keystone net */ -#define CONFIG_KSNET_MAC_ID_BASE KS2_MAC_ID_BASE_ADDR -#define CONFIG_KSNET_NETCP_BASE KS2_NETCP_BASE +#define CONFIG_KSNET_MAC_ID_BASE KS2_MAC_ID_BASE_ADDR +#define CONFIG_KSNET_NETCP_BASE KS2_NETCP_BASE +#define CONFIG_KSNET_SERDES_SGMII_BASE KS2_SGMII_SERDES_BASE +#define CONFIG_KSNET_SERDES_LANES_PER_SGMII KS2_LANES_PER_SGMII_SERDES
/* AEMIF */ #define CONFIG_TI_AEMIF @@ -321,8 +323,4 @@ which is NOT applicable for DDR ECC test */ #define CONFIG_MAX_UBOOT_MEM_SIZE (4 << 20) /* 4 MiB */
-/* SGMII SerDes */ -#define CONFIG_KS2_SERDES_SGMII_BASE KS2_SGMII_SERDES_BASE -#define CONFIG_KS2_SERDES_LANES_PER_SGMII KS2_LANES_PER_SGMII_SERDES - #endif /* __CONFIG_KS2_EVM_H */

On Wed, Oct 22, 2014 at 05:18:23PM +0300, Khoronzhuk, Ivan wrote:
From: Hao Zhang hzhang@ti.com
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 hzhang@ti.com Signed-off-by: Ivan Khoronzhuk ivan.khoronzhuk@ti.com
Applied to u-boot-ti/master, thanks!

The cmu, comlane, lane configuration mechanism are similar for sub systems as well such as PCI or sRIO, but they have different values based on input clock and output bus rate. According to this compact driver to simplify adding different configuration settings based on clock and rate.
Signed-off-by: Ivan Khoronzhuk ivan.khoronzhuk@ti.com --- drivers/soc/keystone/keystone_serdes.c | 112 +++++++++++++++++++-------------- 1 file changed, 65 insertions(+), 47 deletions(-)
diff --git a/drivers/soc/keystone/keystone_serdes.c b/drivers/soc/keystone/keystone_serdes.c index 84ed9ba..dd5eac9 100644 --- a/drivers/soc/keystone/keystone_serdes.c +++ b/drivers/soc/keystone/keystone_serdes.c @@ -29,12 +29,24 @@ #define SERDES_LANE_LOOPBACK BIT(30) #define SERDES_LANE_EN_VAL(x, y, z) (x[y] | (z << 26) | (z << 10))
+#define SERDES_CMU_CFG_NUM 5 +#define SERDES_COMLANE_CFG_NUM 10 +#define SERDES_LANE_CFG_NUM 10 + struct serdes_cfg { u32 ofs; u32 val; u32 mask; };
+struct cfg_entry { + enum ks2_serdes_clock clk; + enum ks2_serdes_rate rate; + struct serdes_cfg cmu[SERDES_CMU_CFG_NUM]; + struct serdes_cfg comlane[SERDES_COMLANE_CFG_NUM]; + struct serdes_cfg lane[SERDES_LANE_CFG_NUM]; +}; + /* SERDES PHY lane enable configuration value, indexed by PHY interface */ static u32 serdes_cfg_lane_enable[] = { 0xf000f0c0, /* SGMII */ @@ -47,39 +59,46 @@ static u32 serdes_cfg_pll_enable[] = { 0xee000000, /* PCSR */ };
-static struct serdes_cfg cfg_cmu_156p25m_5g[] = { - {0x0000, 0x00800000, 0xffff0000}, - {0x0014, 0x00008282, 0x0000ffff}, - {0x0060, 0x00142438, 0x00ffffff}, - {0x0064, 0x00c3c700, 0x00ffff00}, - {0x0078, 0x0000c000, 0x0000ff00} -}; - -static struct serdes_cfg cfg_comlane_156p25m_5g[] = { - {0x0a00, 0x00000800, 0x0000ff00}, - {0x0a08, 0x38a20000, 0xffff0000}, - {0x0a30, 0x008a8a00, 0x00ffff00}, - {0x0a84, 0x00000600, 0x0000ff00}, - {0x0a94, 0x10000000, 0xff000000}, - {0x0aa0, 0x81000000, 0xff000000}, - {0x0abc, 0xff000000, 0xff000000}, - {0x0ac0, 0x0000008b, 0x000000ff}, - {0x0b08, 0x583f0000, 0xffff0000}, - {0x0b0c, 0x0000004e, 0x000000ff} -}; - -static struct serdes_cfg cfg_lane_156p25mhz_5g[] = { - {0x0004, 0x38000080, 0xff0000ff}, - {0x0008, 0x00000000, 0x000000ff}, - {0x000c, 0x02000000, 0xff000000}, - {0x0010, 0x1b000000, 0xff000000}, - {0x0014, 0x00006fb8, 0x0000ffff}, - {0x0018, 0x758000e4, 0xffff00ff}, - {0x00ac, 0x00004400, 0x0000ff00}, - {0x002c, 0x00100800, 0x00ffff00}, - {0x0080, 0x00820082, 0x00ff00ff}, - {0x0084, 0x1d0f0385, 0xffffffff} - +/** + * Array to hold all possible serdes configurations. + * Combination for 5 clock settings and 6 baud rates. + */ +static struct cfg_entry cfgs[] = { + { + .clk = SERDES_CLOCK_156P25M, + .rate = SERDES_RATE_5G, + .cmu = { + {0x0000, 0x00800000, 0xffff0000}, + {0x0014, 0x00008282, 0x0000ffff}, + {0x0060, 0x00142438, 0x00ffffff}, + {0x0064, 0x00c3c700, 0x00ffff00}, + {0x0078, 0x0000c000, 0x0000ff00} + }, + .comlane = { + {0x0a00, 0x00000800, 0x0000ff00}, + {0x0a08, 0x38a20000, 0xffff0000}, + {0x0a30, 0x008a8a00, 0x00ffff00}, + {0x0a84, 0x00000600, 0x0000ff00}, + {0x0a94, 0x10000000, 0xff000000}, + {0x0aa0, 0x81000000, 0xff000000}, + {0x0abc, 0xff000000, 0xff000000}, + {0x0ac0, 0x0000008b, 0x000000ff}, + {0x0b08, 0x583f0000, 0xffff0000}, + {0x0b0c, 0x0000004e, 0x000000ff} + }, + .lane = { + {0x0004, 0x38000080, 0xff0000ff}, + {0x0008, 0x00000000, 0x000000ff}, + {0x000c, 0x02000000, 0xff000000}, + {0x0010, 0x1b000000, 0xff000000}, + {0x0014, 0x00006fb8, 0x0000ffff}, + {0x0018, 0x758000e4, 0xffff00ff}, + {0x00ac, 0x00004400, 0x0000ff00}, + {0x002c, 0x00100800, 0x00ffff00}, + {0x0080, 0x00820082, 0x00ff00ff}, + {0x0084, 0x1d0f0385, 0xffffffff} + }, + }, };
static inline void ks2_serdes_rmw(u32 addr, u32 value, u32 mask) @@ -105,18 +124,15 @@ static void ks2_serdes_lane_config(u32 base, struct serdes_cfg *cfg_lane, cfg_lane[i].val, cfg_lane[i].mask); }
-static int ks2_serdes_init_156p25m_5g(u32 base, u32 num_lanes) +static int ks2_serdes_init_cfg(u32 base, struct cfg_entry *cfg, u32 num_lanes) { u32 i;
- ks2_serdes_cfg_setup(base, cfg_cmu_156p25m_5g, - ARRAY_SIZE(cfg_cmu_156p25m_5g)); - ks2_serdes_cfg_setup(base, cfg_comlane_156p25m_5g, - ARRAY_SIZE(cfg_comlane_156p25m_5g)); + ks2_serdes_cfg_setup(base, cfg->cmu, SERDES_CMU_CFG_NUM); + ks2_serdes_cfg_setup(base, cfg->comlane, SERDES_COMLANE_CFG_NUM);
for (i = 0; i < num_lanes; i++) - ks2_serdes_lane_config(base, cfg_lane_156p25mhz_5g, - ARRAY_SIZE(cfg_lane_156p25mhz_5g), i); + ks2_serdes_lane_config(base, cfg->lane, SERDES_LANE_CFG_NUM, i);
return 0; } @@ -173,14 +189,16 @@ int ks2_serdes_init(u32 base, struct ks2_serdes *serdes, u32 num_lanes) int i; int ret = 0;
- /* The driver currently supports 5GBaud rate with ref clock 156.25MHz */ - if (serdes->clk == SERDES_CLOCK_156P25M) - if (serdes->rate == SERDES_RATE_5G) - ret = ks2_serdes_init_156p25m_5g(base, num_lanes); - else - return -EINVAL; - else + for (i = 0; i < ARRAY_SIZE(cfgs); i++) + if (serdes->clk == cfgs[i].clk && serdes->rate == cfgs[i].rate) + break; + + if (i >= ARRAY_SIZE(cfgs)) { + puts("Cannot find keystone SerDes configuration"); return -EINVAL; + } + + ks2_serdes_init_cfg(base, &cfgs[i], num_lanes);
ks2_serdes_cmu_comlane_enable(base, serdes); for (i = 0; i < num_lanes; i++)

On Wed, Oct 22, 2014 at 05:18:24PM +0300, Khoronzhuk, Ivan wrote:
The cmu, comlane, lane configuration mechanism are similar for sub systems as well such as PCI or sRIO, but they have different values based on input clock and output bus rate. According to this compact driver to simplify adding different configuration settings based on clock and rate.
Signed-off-by: Ivan Khoronzhuk ivan.khoronzhuk@ti.com
Applied to u-boot-ti/master, thanks!
participants (2)
-
Ivan Khoronzhuk
-
Tom Rini