diff options
-rw-r--r-- | .gitlab-ci.yml | 23 | ||||
-rw-r--r-- | board/toradex/apalis_imx6/apalis_imx6.c | 91 | ||||
-rw-r--r-- | board/toradex/colibri-imx6ull/colibri_imx6ull.c | 2 | ||||
-rw-r--r-- | board/toradex/common/tdx-cfg-block.c | 4 | ||||
-rw-r--r-- | configs/apalis_imx6_defconfig | 2 | ||||
-rw-r--r-- | configs/apalis_imx6_nospl_com_defconfig | 2 | ||||
-rw-r--r-- | configs/apalis_imx6_nospl_it_defconfig | 2 | ||||
-rw-r--r-- | configs/apalis_imx6_tezi_defconfig | 2 | ||||
-rw-r--r-- | drivers/net/phy/Makefile | 1 | ||||
-rw-r--r-- | drivers/net/phy/micrel_ksz90x1.c | 402 | ||||
-rw-r--r-- | drivers/net/phy/phy.c | 3 | ||||
-rw-r--r-- | include/configs/apalis_imx6.h | 3 | ||||
-rw-r--r-- | include/micrel.h | 13 | ||||
-rw-r--r-- | include/phy.h | 1 | ||||
-rw-r--r-- | scripts/config_whitelist.txt | 1 |
15 files changed, 530 insertions, 22 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000000..801016b5f5 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,23 @@ +variables: +# uncomment for the pipeline debug purpose +# CI_DEBUG_TRACE: "true" + CI_IMAGE: gitlab.int.toradex.com:4567/philippe.schenker/linux-toradex/ci-kernel-builder:latest + DOCKER_HOST: tcp://docker:2375 + DOCKER_DRIVER: overlay2 + DOCKER_TLS_CERTDIR: "" + +stages: + - build-uboot + +build_u-boot: + stage: build-uboot + image: $CI_IMAGE + variables: + GIT_STRATEGY: fetch + GIT_DEPTH: "1" + script: | + tools/buildman/buildman toradex || ret=$? + if [[ $ret -ne 0 && $ret -ne 129 ]]; then + tools/buildman/buildman -sdeP ${BUILDMAN}; + exit $ret; + fi; diff --git a/board/toradex/apalis_imx6/apalis_imx6.c b/board/toradex/apalis_imx6/apalis_imx6.c index b2bb875789..f5f51fcda8 100644 --- a/board/toradex/apalis_imx6/apalis_imx6.c +++ b/board/toradex/apalis_imx6/apalis_imx6.c @@ -208,22 +208,79 @@ iomux_v3_cfg_t const usdhc3_pads[] = { int mx6_rgmii_rework(struct phy_device *phydev) { - /* control data pad skew - devaddr = 0x02, register = 0x04 */ - ksz9031_phy_extended_write(phydev, 0x02, - MII_KSZ9031_EXT_RGMII_CTRL_SIG_SKEW, - MII_KSZ9031_MOD_DATA_NO_POST_INC, 0x0000); - /* rx data pad skew - devaddr = 0x02, register = 0x05 */ - ksz9031_phy_extended_write(phydev, 0x02, - MII_KSZ9031_EXT_RGMII_RX_DATA_SKEW, - MII_KSZ9031_MOD_DATA_NO_POST_INC, 0x0000); - /* tx data pad skew - devaddr = 0x02, register = 0x05 */ - ksz9031_phy_extended_write(phydev, 0x02, - MII_KSZ9031_EXT_RGMII_TX_DATA_SKEW, - MII_KSZ9031_MOD_DATA_NO_POST_INC, 0x0000); - /* gtx and rx clock pad skew - devaddr = 0x02, register = 0x08 */ - ksz9031_phy_extended_write(phydev, 0x02, - MII_KSZ9031_EXT_RGMII_CLOCK_SKEW, - MII_KSZ9031_MOD_DATA_NO_POST_INC, 0x03FF); + int tmp; + + switch (ksz9xx1_phy_get_id(phydev) & MII_KSZ9x31_SILICON_REV_MASK) { + case PHY_ID_KSZ9131: + /* read rxc dll control - devaddr = 0x02, register = 0x4c */ + tmp = ksz9031_phy_extended_read(phydev, 0x02, + MII_KSZ9131_EXT_RGMII_2NS_SKEW_RXDLL, + MII_KSZ9031_MOD_DATA_NO_POST_INC); + /* disable rxdll bypass (enable 2ns skew delay on RXC) */ + tmp &= ~MII_KSZ9131_RXTXDLL_BYPASS; + /* rxc data pad skew 2ns - devaddr = 0x02, register = 0x4c */ + ksz9031_phy_extended_write(phydev, 0x02, + MII_KSZ9131_EXT_RGMII_2NS_SKEW_RXDLL, + MII_KSZ9031_MOD_DATA_NO_POST_INC, + tmp); + /* read txc dll control - devaddr = 0x02, register = 0x4d */ + tmp = ksz9031_phy_extended_read(phydev, 0x02, + MII_KSZ9131_EXT_RGMII_2NS_SKEW_TXDLL, + MII_KSZ9031_MOD_DATA_NO_POST_INC); + /* disable rxdll bypass (enable 2ns skew delay on TXC) */ + tmp &= ~MII_KSZ9131_RXTXDLL_BYPASS; + /* txc data pad skew 2ns - devaddr = 0x02, register = 0x4d */ + ksz9031_phy_extended_write(phydev, 0x02, + MII_KSZ9131_EXT_RGMII_2NS_SKEW_TXDLL, + MII_KSZ9031_MOD_DATA_NO_POST_INC, + tmp); + + /* control data pad skew - devaddr = 0x02, register = 0x04 */ + ksz9031_phy_extended_write(phydev, 0x02, + MII_KSZ9031_EXT_RGMII_CTRL_SIG_SKEW, + MII_KSZ9031_MOD_DATA_NO_POST_INC, + 0x007d); + /* rx data pad skew - devaddr = 0x02, register = 0x05 */ + ksz9031_phy_extended_write(phydev, 0x02, + MII_KSZ9031_EXT_RGMII_RX_DATA_SKEW, + MII_KSZ9031_MOD_DATA_NO_POST_INC, + 0x7777); + /* tx data pad skew - devaddr = 0x02, register = 0x05 */ + ksz9031_phy_extended_write(phydev, 0x02, + MII_KSZ9031_EXT_RGMII_TX_DATA_SKEW, + MII_KSZ9031_MOD_DATA_NO_POST_INC, + 0xdddd); + /* gtx and rx clock pad skew - devaddr = 0x02,register = 0x08 */ + ksz9031_phy_extended_write(phydev, 0x02, + MII_KSZ9031_EXT_RGMII_CLOCK_SKEW, + MII_KSZ9031_MOD_DATA_NO_POST_INC, + 0x0007); + break; + case PHY_ID_KSZ9031: + default: + /* control data pad skew - devaddr = 0x02, register = 0x04 */ + ksz9031_phy_extended_write(phydev, 0x02, + MII_KSZ9031_EXT_RGMII_CTRL_SIG_SKEW, + MII_KSZ9031_MOD_DATA_NO_POST_INC, + 0x0000); + /* rx data pad skew - devaddr = 0x02, register = 0x05 */ + ksz9031_phy_extended_write(phydev, 0x02, + MII_KSZ9031_EXT_RGMII_RX_DATA_SKEW, + MII_KSZ9031_MOD_DATA_NO_POST_INC, + 0x0000); + /* tx data pad skew - devaddr = 0x02, register = 0x05 */ + ksz9031_phy_extended_write(phydev, 0x02, + MII_KSZ9031_EXT_RGMII_TX_DATA_SKEW, + MII_KSZ9031_MOD_DATA_NO_POST_INC, + 0x0000); + /* gtx and rx clock pad skew - devaddr = 0x02,register = 0x08 */ + ksz9031_phy_extended_write(phydev, 0x02, + MII_KSZ9031_EXT_RGMII_CLOCK_SKEW, + MII_KSZ9031_MOD_DATA_NO_POST_INC, + 0x03FF); + break; + } + return 0; } @@ -480,8 +537,6 @@ int board_mmc_init(bd_t *bis) int board_phy_config(struct phy_device *phydev) { - ksz9031_center_flp_timing(phydev); - mx6_rgmii_rework(phydev); if (phydev->drv->config) phydev->drv->config(phydev); diff --git a/board/toradex/colibri-imx6ull/colibri_imx6ull.c b/board/toradex/colibri-imx6ull/colibri_imx6ull.c index 5c28fafbca..4c175ceb30 100644 --- a/board/toradex/colibri-imx6ull/colibri_imx6ull.c +++ b/board/toradex/colibri-imx6ull/colibri_imx6ull.c @@ -121,7 +121,7 @@ static iomux_v3_cfg_t const lcd_pads[] = { MX6_PAD_LCD_CLK__LCDIF_CLK | MUX_PAD_CTRL(LCD_PAD_CTRL), MX6_PAD_LCD_ENABLE__LCDIF_ENABLE | MUX_PAD_CTRL(LCD_PAD_CTRL), MX6_PAD_LCD_HSYNC__LCDIF_HSYNC | MUX_PAD_CTRL(LCD_PAD_CTRL), - MX6_PAD_LCD_CLK__LCDIF_CLK | MUX_PAD_CTRL(LCD_PAD_CTRL), + MX6_PAD_LCD_VSYNC__LCDIF_VSYNC | MUX_PAD_CTRL(LCD_PAD_CTRL), MX6_PAD_LCD_DATA00__LCDIF_DATA00 | MUX_PAD_CTRL(LCD_PAD_CTRL), MX6_PAD_LCD_DATA01__LCDIF_DATA01 | MUX_PAD_CTRL(LCD_PAD_CTRL), MX6_PAD_LCD_DATA02__LCDIF_DATA02 | MUX_PAD_CTRL(LCD_PAD_CTRL), diff --git a/board/toradex/common/tdx-cfg-block.c b/board/toradex/common/tdx-cfg-block.c index 68ec51f3ec..aff3dd4d32 100644 --- a/board/toradex/common/tdx-cfg-block.c +++ b/board/toradex/common/tdx-cfg-block.c @@ -421,6 +421,8 @@ static int get_cfgblock_interactive(void) static int get_cfgblock_barcode(char *barcode) { + char revision[3] = {barcode[6], barcode[7], '\0'}; + if (strlen(barcode) < 16) { printf("Argument too short, barcode is 16 chars long\n"); return -1; @@ -429,7 +431,7 @@ static int get_cfgblock_barcode(char *barcode) /* Get hardware information from the first 8 digits */ tdx_hw_tag.ver_major = barcode[4] - '0'; tdx_hw_tag.ver_minor = barcode[5] - '0'; - tdx_hw_tag.ver_assembly = barcode[7] - '0'; + tdx_hw_tag.ver_assembly = simple_strtoul(revision, NULL, 10); barcode[4] = '\0'; tdx_hw_tag.prodid = simple_strtoul(barcode, NULL, 10); diff --git a/configs/apalis_imx6_defconfig b/configs/apalis_imx6_defconfig index bfd8cc0138..138c2ec575 100644 --- a/configs/apalis_imx6_defconfig +++ b/configs/apalis_imx6_defconfig @@ -55,3 +55,5 @@ CONFIG_G_DNL_PRODUCT_NUM=0x4000 CONFIG_OF_LIBFDT=y CONFIG_OF_LIBFDT_OVERLAY=y # CONFIG_EFI_LOADER is not set +CONFIG_PHY_MICREL=n +CONFIG_PHY_MICREL_KSZ90X1=y diff --git a/configs/apalis_imx6_nospl_com_defconfig b/configs/apalis_imx6_nospl_com_defconfig index 0dcb6fcf74..7e87f38f66 100644 --- a/configs/apalis_imx6_nospl_com_defconfig +++ b/configs/apalis_imx6_nospl_com_defconfig @@ -42,3 +42,5 @@ CONFIG_G_DNL_PRODUCT_NUM=0x4000 CONFIG_OF_LIBFDT=y CONFIG_OF_LIBFDT_OVERLAY=y # CONFIG_EFI_LOADER is not set +CONFIG_PHY_MICREL=n +CONFIG_PHY_MICREL_KSZ90X1=y diff --git a/configs/apalis_imx6_nospl_it_defconfig b/configs/apalis_imx6_nospl_it_defconfig index 3846f37152..cfd22c6cdd 100644 --- a/configs/apalis_imx6_nospl_it_defconfig +++ b/configs/apalis_imx6_nospl_it_defconfig @@ -42,3 +42,5 @@ CONFIG_G_DNL_PRODUCT_NUM=0x4000 CONFIG_OF_LIBFDT=y CONFIG_OF_LIBFDT_OVERLAY=y # CONFIG_EFI_LOADER is not set +CONFIG_PHY_MICREL=n +CONFIG_PHY_MICREL_KSZ90X1=y diff --git a/configs/apalis_imx6_tezi_defconfig b/configs/apalis_imx6_tezi_defconfig index 80e8e1e1c1..ef0f02226d 100644 --- a/configs/apalis_imx6_tezi_defconfig +++ b/configs/apalis_imx6_tezi_defconfig @@ -54,3 +54,5 @@ CONFIG_G_DNL_PRODUCT_NUM=0x4000 CONFIG_OF_LIBFDT=y CONFIG_OF_LIBFDT_OVERLAY=y # CONFIG_EFI_LOADER is not set +CONFIG_PHY_MICREL=n +CONFIG_PHY_MICREL_KSZ90X1=y diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile index 1e299b97b9..dacc07485c 100644 --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile @@ -20,6 +20,7 @@ obj-$(CONFIG_PHY_ET1011C) += et1011c.o obj-$(CONFIG_PHY_LXT) += lxt.o obj-$(CONFIG_PHY_MARVELL) += marvell.o obj-$(CONFIG_PHY_MICREL) += micrel.o +obj-$(CONFIG_PHY_MICREL_KSZ90X1) += micrel_ksz90x1.o obj-$(CONFIG_PHY_NATSEMI) += natsemi.o obj-$(CONFIG_PHY_REALTEK) += realtek.o obj-$(CONFIG_PHY_SMSC) += smsc.o diff --git a/drivers/net/phy/micrel_ksz90x1.c b/drivers/net/phy/micrel_ksz90x1.c new file mode 100644 index 0000000000..5ab7ed7edc --- /dev/null +++ b/drivers/net/phy/micrel_ksz90x1.c @@ -0,0 +1,402 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Micrel PHY drivers + * + * Copyright 2010-2011 Freescale Semiconductor, Inc. + * author Andy Fleming + * (C) 2012 NetModule AG, David Andrey, added KSZ9031 + * (C) Copyright 2017 Adaptrum, Inc. + * Written by Alexandru Gagniuc <alex.g@adaptrum.com> for Adaptrum, Inc. + */ +#include <common.h> +#include <dm.h> +#include <errno.h> +#include <micrel.h> +#include <phy.h> + +/* + * KSZ9021 - KSZ9031 common + */ + +#define MII_KSZ90xx_PHY_CTL 0x1f +#define MIIM_KSZ90xx_PHYCTL_1000 (1 << 6) +#define MIIM_KSZ90xx_PHYCTL_100 (1 << 5) +#define MIIM_KSZ90xx_PHYCTL_10 (1 << 4) +#define MIIM_KSZ90xx_PHYCTL_DUPLEX (1 << 3) + +/* KSZ9021 PHY Registers */ +#define MII_KSZ9021_EXTENDED_CTRL 0x0b +#define MII_KSZ9021_EXTENDED_DATAW 0x0c +#define MII_KSZ9021_EXTENDED_DATAR 0x0d + +#define CTRL1000_PREFER_MASTER (1 << 10) +#define CTRL1000_CONFIG_MASTER (1 << 11) +#define CTRL1000_MANUAL_CONFIG (1 << 12) + +#define KSZ9021_PS_TO_REG 120 + +/* KSZ9031 PHY Registers */ +#define MII_KSZ9031_MMD_ACCES_CTRL 0x0d +#define MII_KSZ9031_MMD_REG_DATA 0x0e + +#define KSZ9031_PS_TO_REG 60 + +static int ksz90xx_startup(struct phy_device *phydev) +{ + unsigned phy_ctl; + int ret; + + ret = genphy_update_link(phydev); + if (ret) + return ret; + + phy_ctl = phy_read(phydev, MDIO_DEVAD_NONE, MII_KSZ90xx_PHY_CTL); + + if (phy_ctl & MIIM_KSZ90xx_PHYCTL_DUPLEX) + phydev->duplex = DUPLEX_FULL; + else + phydev->duplex = DUPLEX_HALF; + + if (phy_ctl & MIIM_KSZ90xx_PHYCTL_1000) + phydev->speed = SPEED_1000; + else if (phy_ctl & MIIM_KSZ90xx_PHYCTL_100) + phydev->speed = SPEED_100; + else if (phy_ctl & MIIM_KSZ90xx_PHYCTL_10) + phydev->speed = SPEED_10; + return 0; +} + +/* Common OF config bits for KSZ9021 and KSZ9031 */ +#ifdef CONFIG_DM_ETH +struct ksz90x1_reg_field { + const char *name; + const u8 size; /* Size of the bitfield, in bits */ + const u8 off; /* Offset from bit 0 */ + const u8 dflt; /* Default value */ +}; + +struct ksz90x1_ofcfg { + const u16 reg; + const u16 devad; + const struct ksz90x1_reg_field *grp; + const u16 grpsz; +}; + +static const struct ksz90x1_reg_field ksz90x1_rxd_grp[] = { + { "rxd0-skew-ps", 4, 0, 0x7 }, { "rxd1-skew-ps", 4, 4, 0x7 }, + { "rxd2-skew-ps", 4, 8, 0x7 }, { "rxd3-skew-ps", 4, 12, 0x7 } +}; + +static const struct ksz90x1_reg_field ksz90x1_txd_grp[] = { + { "txd0-skew-ps", 4, 0, 0x7 }, { "txd1-skew-ps", 4, 4, 0x7 }, + { "txd2-skew-ps", 4, 8, 0x7 }, { "txd3-skew-ps", 4, 12, 0x7 }, +}; + +static const struct ksz90x1_reg_field ksz9021_clk_grp[] = { + { "txen-skew-ps", 4, 0, 0x7 }, { "txc-skew-ps", 4, 4, 0x7 }, + { "rxdv-skew-ps", 4, 8, 0x7 }, { "rxc-skew-ps", 4, 12, 0x7 }, +}; + +static const struct ksz90x1_reg_field ksz9031_ctl_grp[] = { + { "txen-skew-ps", 4, 0, 0x7 }, { "rxdv-skew-ps", 4, 4, 0x7 } +}; + +static const struct ksz90x1_reg_field ksz9031_clk_grp[] = { + { "rxc-skew-ps", 5, 0, 0xf }, { "txc-skew-ps", 5, 5, 0xf } +}; + +static int ksz90x1_of_config_group(struct phy_device *phydev, + struct ksz90x1_ofcfg *ofcfg, + int ps_to_regval) +{ + struct udevice *dev = phydev->dev; + struct phy_driver *drv = phydev->drv; + int val[4]; + int i, changed = 0, offset, max; + u16 regval = 0; + ofnode node; + + if (!drv || !drv->writeext) + return -EOPNOTSUPP; + + /* Look for a PHY node under the Ethernet node */ + node = dev_read_subnode(dev, "ethernet-phy"); + if (!ofnode_valid(node)) { + /* No node found, look in the Ethernet node */ + node = dev_ofnode(dev); + } + + for (i = 0; i < ofcfg->grpsz; i++) { + val[i] = ofnode_read_u32_default(node, ofcfg->grp[i].name, ~0); + offset = ofcfg->grp[i].off; + if (val[i] == -1) { + /* Default register value for KSZ9021 */ + regval |= ofcfg->grp[i].dflt << offset; + } else { + changed = 1; /* Value was changed in OF */ + /* Calculate the register value and fix corner cases */ + max = (1 << ofcfg->grp[i].size) - 1; + if (val[i] > ps_to_regval * max) { + regval |= max << offset; + } else { + regval |= (val[i] / ps_to_regval) << offset; + } + } + } + + if (!changed) + return 0; + + return drv->writeext(phydev, 0, ofcfg->devad, ofcfg->reg, regval); +} + +static int ksz9021_of_config(struct phy_device *phydev) +{ + struct ksz90x1_ofcfg ofcfg[] = { + { MII_KSZ9021_EXT_RGMII_RX_DATA_SKEW, 0, ksz90x1_rxd_grp, 4 }, + { MII_KSZ9021_EXT_RGMII_TX_DATA_SKEW, 0, ksz90x1_txd_grp, 4 }, + { MII_KSZ9021_EXT_RGMII_CLOCK_SKEW, 0, ksz9021_clk_grp, 4 }, + }; + int i, ret = 0; + + for (i = 0; i < ARRAY_SIZE(ofcfg); i++) { + ret = ksz90x1_of_config_group(phydev, &ofcfg[i], + KSZ9021_PS_TO_REG); + if (ret) + return ret; + } + + return 0; +} + +static int ksz9031_of_config(struct phy_device *phydev) +{ + struct ksz90x1_ofcfg ofcfg[] = { + { MII_KSZ9031_EXT_RGMII_CTRL_SIG_SKEW, 2, ksz9031_ctl_grp, 2 }, + { MII_KSZ9031_EXT_RGMII_RX_DATA_SKEW, 2, ksz90x1_rxd_grp, 4 }, + { MII_KSZ9031_EXT_RGMII_TX_DATA_SKEW, 2, ksz90x1_txd_grp, 4 }, + { MII_KSZ9031_EXT_RGMII_CLOCK_SKEW, 2, ksz9031_clk_grp, 2 }, + }; + int i, ret = 0; + + for (i = 0; i < ARRAY_SIZE(ofcfg); i++) { + ret = ksz90x1_of_config_group(phydev, &ofcfg[i], + KSZ9031_PS_TO_REG); + if (ret) + return ret; + } + + return 0; +} + +static int ksz9031_center_flp_timing(struct phy_device *phydev) +{ + struct phy_driver *drv = phydev->drv; + int ret = 0; + + if (!drv || !drv->writeext) + return -EOPNOTSUPP; + + ret = drv->writeext(phydev, 0, 0, MII_KSZ9031_FLP_BURST_TX_LO, 0x1A80); + if (ret) + return ret; + + ret = drv->writeext(phydev, 0, 0, MII_KSZ9031_FLP_BURST_TX_HI, 0x6); + return ret; +} + +#else /* !CONFIG_DM_ETH */ +static int ksz9021_of_config(struct phy_device *phydev) +{ + return 0; +} + +static int ksz9031_of_config(struct phy_device *phydev) +{ + return 0; +} + +static int ksz9031_center_flp_timing(struct phy_device *phydev) +{ + return 0; +} +#endif + +/* + * KSZ9021 + */ +int ksz9021_phy_extended_write(struct phy_device *phydev, int regnum, u16 val) +{ + /* extended registers */ + phy_write(phydev, MDIO_DEVAD_NONE, + MII_KSZ9021_EXTENDED_CTRL, regnum | 0x8000); + return phy_write(phydev, MDIO_DEVAD_NONE, + MII_KSZ9021_EXTENDED_DATAW, val); +} + +int ksz9021_phy_extended_read(struct phy_device *phydev, int regnum) +{ + /* extended registers */ + phy_write(phydev, MDIO_DEVAD_NONE, MII_KSZ9021_EXTENDED_CTRL, regnum); + return phy_read(phydev, MDIO_DEVAD_NONE, MII_KSZ9021_EXTENDED_DATAR); +} + + +static int ksz9021_phy_extread(struct phy_device *phydev, int addr, int devaddr, + int regnum) +{ + return ksz9021_phy_extended_read(phydev, regnum); +} + +static int ksz9021_phy_extwrite(struct phy_device *phydev, int addr, + int devaddr, int regnum, u16 val) +{ + return ksz9021_phy_extended_write(phydev, regnum, val); +} + +static int ksz9021_config(struct phy_device *phydev) +{ + unsigned ctrl1000 = 0; + const unsigned master = CTRL1000_PREFER_MASTER | + CTRL1000_CONFIG_MASTER | CTRL1000_MANUAL_CONFIG; + unsigned features = phydev->drv->features; + int ret; + + ret = ksz9021_of_config(phydev); + if (ret) + return ret; + + /* force master mode for 1000BaseT due to chip errata */ + if (features & SUPPORTED_1000baseT_Half) + ctrl1000 |= ADVERTISE_1000HALF | master; + if (features & SUPPORTED_1000baseT_Full) + ctrl1000 |= ADVERTISE_1000FULL | master; + phydev->advertising = features; + phydev->supported = features; + phy_write(phydev, MDIO_DEVAD_NONE, MII_CTRL1000, ctrl1000); + genphy_config_aneg(phydev); + genphy_restart_aneg(phydev); + return 0; +} + +static struct phy_driver ksz9021_driver = { + .name = "Micrel ksz9021", + .uid = 0x221610, + .mask = 0xfffffe, + .features = PHY_GBIT_FEATURES, + .config = &ksz9021_config, + .startup = &ksz90xx_startup, + .shutdown = &genphy_shutdown, + .writeext = &ksz9021_phy_extwrite, + .readext = &ksz9021_phy_extread, +}; + +/* + * KSZ9031 + */ +int ksz9031_phy_extended_write(struct phy_device *phydev, + int devaddr, int regnum, u16 mode, u16 val) +{ + /*select register addr for mmd*/ + phy_write(phydev, MDIO_DEVAD_NONE, + MII_KSZ9031_MMD_ACCES_CTRL, devaddr); + /*select register for mmd*/ + phy_write(phydev, MDIO_DEVAD_NONE, + MII_KSZ9031_MMD_REG_DATA, regnum); + /*setup mode*/ + phy_write(phydev, MDIO_DEVAD_NONE, + MII_KSZ9031_MMD_ACCES_CTRL, (mode | devaddr)); + /*write the value*/ + return phy_write(phydev, MDIO_DEVAD_NONE, + MII_KSZ9031_MMD_REG_DATA, val); +} + +int ksz9031_phy_extended_read(struct phy_device *phydev, int devaddr, + int regnum, u16 mode) +{ + phy_write(phydev, MDIO_DEVAD_NONE, + MII_KSZ9031_MMD_ACCES_CTRL, devaddr); + phy_write(phydev, MDIO_DEVAD_NONE, + MII_KSZ9031_MMD_REG_DATA, regnum); + phy_write(phydev, MDIO_DEVAD_NONE, + MII_KSZ9031_MMD_ACCES_CTRL, (devaddr | mode)); + return phy_read(phydev, MDIO_DEVAD_NONE, MII_KSZ9031_MMD_REG_DATA); +} + +static int ksz9031_phy_extread(struct phy_device *phydev, int addr, int devaddr, + int regnum) +{ + return ksz9031_phy_extended_read(phydev, devaddr, regnum, + MII_KSZ9031_MOD_DATA_NO_POST_INC); +} + +static int ksz9031_phy_extwrite(struct phy_device *phydev, int addr, + int devaddr, int regnum, u16 val) +{ + return ksz9031_phy_extended_write(phydev, devaddr, regnum, + MII_KSZ9031_MOD_DATA_POST_INC_RW, val); +} + +static int ksz9031_config(struct phy_device *phydev) +{ + int ret; + + ret = ksz9031_of_config(phydev); + if (ret) + return ret; + ret = ksz9031_center_flp_timing(phydev); + if (ret) + return ret; + + return genphy_config(phydev); +} + +static struct phy_driver ksz9031_driver = { + .name = "Micrel ksz9031", + .uid = PHY_ID_KSZ9031, + .mask = MII_KSZ9x31_SILICON_REV_MASK, + .features = PHY_GBIT_FEATURES, + .config = &ksz9031_config, + .startup = &ksz90xx_startup, + .shutdown = &genphy_shutdown, + .writeext = &ksz9031_phy_extwrite, + .readext = &ksz9031_phy_extread, +}; + +/* + * KSZ9131 + */ +static int ksz9131_config(struct phy_device *phydev) +{ + /* TBD: Implement Skew values for dts */ + return genphy_config(phydev); +} + +static struct phy_driver ksz9131_driver = { + .name = "Micrel ksz9031", + .uid = PHY_ID_KSZ9131, + .mask = MII_KSZ9x31_SILICON_REV_MASK, + .features = PHY_GBIT_FEATURES, + .config = &ksz9131_config, + .startup = &ksz90xx_startup, + .shutdown = &genphy_shutdown, + .writeext = &ksz9031_phy_extwrite, + .readext = &ksz9031_phy_extread, +}; + +int ksz9xx1_phy_get_id(struct phy_device *phydev) +{ + unsigned int phyid; + + get_phy_id(phydev->bus, phydev->addr, MDIO_DEVAD_NONE, &phyid); + + return phyid; +} + +int phy_micrel_ksz90x1_init(void) +{ + phy_register(&ksz9021_driver); + phy_register(&ksz9031_driver); + phy_register(&ksz9131_driver); + return 0; +} diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index 80bdfb6d9d..2d9122469f 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -491,6 +491,9 @@ int phy_init(void) #ifdef CONFIG_PHY_MICREL phy_micrel_init(); #endif +#ifdef CONFIG_PHY_MICREL_KSZ90X1 + phy_micrel_ksz90x1_init(); +#endif #ifdef CONFIG_PHY_NATSEMI phy_natsemi_init(); #endif diff --git a/include/configs/apalis_imx6.h b/include/configs/apalis_imx6.h index 4b2e519ab9..0058b6ad35 100644 --- a/include/configs/apalis_imx6.h +++ b/include/configs/apalis_imx6.h @@ -103,8 +103,7 @@ #define CONFIG_ETHPRIME "FEC" #define CONFIG_FEC_MXC_PHYADDR 6 #define CONFIG_PHYLIB -#define CONFIG_PHY_MICREL -#define CONFIG_PHY_MICREL_KSZ9031 +#define CONFIG_PHY_MICREL_KSZ90X1 #define CONFIG_IP_DEFRAG #define CONFIG_TFTP_BLOCKSIZE 4096 #define CONFIG_TFTP_TSIZE diff --git a/include/micrel.h b/include/micrel.h index 783dc634e2..a03b8dd7b9 100644 --- a/include/micrel.h +++ b/include/micrel.h @@ -23,6 +23,16 @@ #define MII_KSZ9031_FLP_BURST_TX_LO 0x3 #define MII_KSZ9031_FLP_BURST_TX_HI 0x4 +#define MII_KSZ9x31_SILICON_REV_MASK 0xfffff0 + +#define MII_KSZ9131_RXTXDLL_BYPASS BIT(12) +#define MII_KSZ9131_EXT_RGMII_2NS_SKEW_RXDLL 0x4c +#define MII_KSZ9131_EXT_RGMII_2NS_SKEW_TXDLL 0x4d + +#define PHY_ID_KSZ9031 0x00221620 +#define PHY_ID_KSZ9131 0x00221640 + + /* Registers */ #define MMD_ACCESS_CONTROL 0xd #define MMD_ACCESS_REG_DATA 0xe @@ -35,6 +45,9 @@ int ksz9031_phy_extended_write(struct phy_device *phydev, int devaddr, int regnum, u16 mode, u16 val); int ksz9031_phy_extended_read(struct phy_device *phydev, int devaddr, int regnum, u16 mode); +int ksz9xx1_phy_get_id(struct phy_device *phydev); +#ifndef CONFIG_PHY_MICREL_KSZ90X1 int ksz9031_center_flp_timing(struct phy_device *phydev); +#endif #endif diff --git a/include/phy.h b/include/phy.h index 268d9a1823..283a61406f 100644 --- a/include/phy.h +++ b/include/phy.h @@ -259,6 +259,7 @@ int phy_et1011c_init(void); int phy_lxt_init(void); int phy_marvell_init(void); int phy_micrel_init(void); +int phy_micrel_ksz90x1_init(void); int phy_natsemi_init(void); int phy_realtek_init(void); int phy_smsc_init(void); diff --git a/scripts/config_whitelist.txt b/scripts/config_whitelist.txt index 724fcfc426..63fd60a76a 100644 --- a/scripts/config_whitelist.txt +++ b/scripts/config_whitelist.txt @@ -3556,6 +3556,7 @@ CONFIG_PHY_MAX_ADDR CONFIG_PHY_MICREL CONFIG_PHY_MICREL_KSZ9021 CONFIG_PHY_MICREL_KSZ9031 +CONFIG_PHY_MICREL_KSZ90X1 CONFIG_PHY_MODE_NEED_CHANGE CONFIG_PHY_NATSEMI CONFIG_PHY_REALTEK |