Home | History | Annotate | Download | only in phy
      1 // SPDX-License-Identifier: GPL-2.0+
      2 /*
      3  * Micrel PHY drivers
      4  *
      5  * Copyright 2010-2011 Freescale Semiconductor, Inc.
      6  * author Andy Fleming
      7  * (C) 2012 NetModule AG, David Andrey, added KSZ9031
      8  * (C) Copyright 2017 Adaptrum, Inc.
      9  * Written by Alexandru Gagniuc <alex.g (at) adaptrum.com> for Adaptrum, Inc.
     10  */
     11 
     12 #include <config.h>
     13 #include <common.h>
     14 #include <dm.h>
     15 #include <errno.h>
     16 #include <micrel.h>
     17 #include <phy.h>
     18 
     19 /*
     20  * KSZ9021 - KSZ9031 common
     21  */
     22 
     23 #define MII_KSZ90xx_PHY_CTL		0x1f
     24 #define MIIM_KSZ90xx_PHYCTL_1000	(1 << 6)
     25 #define MIIM_KSZ90xx_PHYCTL_100		(1 << 5)
     26 #define MIIM_KSZ90xx_PHYCTL_10		(1 << 4)
     27 #define MIIM_KSZ90xx_PHYCTL_DUPLEX	(1 << 3)
     28 
     29 /* KSZ9021 PHY Registers */
     30 #define MII_KSZ9021_EXTENDED_CTRL	0x0b
     31 #define MII_KSZ9021_EXTENDED_DATAW	0x0c
     32 #define MII_KSZ9021_EXTENDED_DATAR	0x0d
     33 
     34 #define CTRL1000_PREFER_MASTER		(1 << 10)
     35 #define CTRL1000_CONFIG_MASTER		(1 << 11)
     36 #define CTRL1000_MANUAL_CONFIG		(1 << 12)
     37 
     38 /* KSZ9031 PHY Registers */
     39 #define MII_KSZ9031_MMD_ACCES_CTRL	0x0d
     40 #define MII_KSZ9031_MMD_REG_DATA	0x0e
     41 
     42 static int ksz90xx_startup(struct phy_device *phydev)
     43 {
     44 	unsigned phy_ctl;
     45 	int ret;
     46 
     47 	ret = genphy_update_link(phydev);
     48 	if (ret)
     49 		return ret;
     50 
     51 	phy_ctl = phy_read(phydev, MDIO_DEVAD_NONE, MII_KSZ90xx_PHY_CTL);
     52 
     53 	if (phy_ctl & MIIM_KSZ90xx_PHYCTL_DUPLEX)
     54 		phydev->duplex = DUPLEX_FULL;
     55 	else
     56 		phydev->duplex = DUPLEX_HALF;
     57 
     58 	if (phy_ctl & MIIM_KSZ90xx_PHYCTL_1000)
     59 		phydev->speed = SPEED_1000;
     60 	else if (phy_ctl & MIIM_KSZ90xx_PHYCTL_100)
     61 		phydev->speed = SPEED_100;
     62 	else if (phy_ctl & MIIM_KSZ90xx_PHYCTL_10)
     63 		phydev->speed = SPEED_10;
     64 	return 0;
     65 }
     66 
     67 /* Common OF config bits for KSZ9021 and KSZ9031 */
     68 #ifdef CONFIG_DM_ETH
     69 struct ksz90x1_reg_field {
     70 	const char	*name;
     71 	const u8	size;	/* Size of the bitfield, in bits */
     72 	const u8	off;	/* Offset from bit 0 */
     73 	const u8	dflt;	/* Default value */
     74 };
     75 
     76 struct ksz90x1_ofcfg {
     77 	const u16			reg;
     78 	const u16			devad;
     79 	const struct ksz90x1_reg_field	*grp;
     80 	const u16			grpsz;
     81 };
     82 
     83 static const struct ksz90x1_reg_field ksz90x1_rxd_grp[] = {
     84 	{ "rxd0-skew-ps", 4, 0, 0x7 }, { "rxd1-skew-ps", 4, 4, 0x7 },
     85 	{ "rxd2-skew-ps", 4, 8, 0x7 }, { "rxd3-skew-ps", 4, 12, 0x7 }
     86 };
     87 
     88 static const struct ksz90x1_reg_field ksz90x1_txd_grp[] = {
     89 	{ "txd0-skew-ps", 4, 0, 0x7 }, { "txd1-skew-ps", 4, 4, 0x7 },
     90 	{ "txd2-skew-ps", 4, 8, 0x7 }, { "txd3-skew-ps", 4, 12, 0x7 },
     91 };
     92 
     93 static const struct ksz90x1_reg_field ksz9021_clk_grp[] = {
     94 	{ "txen-skew-ps", 4, 0, 0x7 }, { "txc-skew-ps", 4, 4, 0x7 },
     95 	{ "rxdv-skew-ps", 4, 8, 0x7 }, { "rxc-skew-ps", 4, 12, 0x7 },
     96 };
     97 
     98 static const struct ksz90x1_reg_field ksz9031_ctl_grp[] = {
     99 	{ "txen-skew-ps", 4, 0, 0x7 }, { "rxdv-skew-ps", 4, 4, 0x7 }
    100 };
    101 
    102 static const struct ksz90x1_reg_field ksz9031_clk_grp[] = {
    103 	{ "rxc-skew-ps", 5, 0, 0xf }, { "txc-skew-ps", 5, 5, 0xf }
    104 };
    105 
    106 static int ksz90x1_of_config_group(struct phy_device *phydev,
    107 				   struct ksz90x1_ofcfg *ofcfg)
    108 {
    109 	struct udevice *dev = phydev->dev;
    110 	struct phy_driver *drv = phydev->drv;
    111 	const int ps_to_regval = 60;
    112 	int val[4];
    113 	int i, changed = 0, offset, max;
    114 	u16 regval = 0;
    115 
    116 	if (!drv || !drv->writeext)
    117 		return -EOPNOTSUPP;
    118 
    119 	for (i = 0; i < ofcfg->grpsz; i++) {
    120 		val[i] = dev_read_u32_default(dev, ofcfg->grp[i].name, ~0);
    121 		offset = ofcfg->grp[i].off;
    122 		if (val[i] == -1) {
    123 			/* Default register value for KSZ9021 */
    124 			regval |= ofcfg->grp[i].dflt << offset;
    125 		} else {
    126 			changed = 1;	/* Value was changed in OF */
    127 			/* Calculate the register value and fix corner cases */
    128 			if (val[i] > ps_to_regval * 0xf) {
    129 				max = (1 << ofcfg->grp[i].size) - 1;
    130 				regval |= max << offset;
    131 			} else {
    132 				regval |= (val[i] / ps_to_regval) << offset;
    133 			}
    134 		}
    135 	}
    136 
    137 	if (!changed)
    138 		return 0;
    139 
    140 	return drv->writeext(phydev, 0, ofcfg->devad, ofcfg->reg, regval);
    141 }
    142 
    143 static int ksz9021_of_config(struct phy_device *phydev)
    144 {
    145 	struct ksz90x1_ofcfg ofcfg[] = {
    146 		{ MII_KSZ9021_EXT_RGMII_RX_DATA_SKEW, 0, ksz90x1_rxd_grp, 4 },
    147 		{ MII_KSZ9021_EXT_RGMII_TX_DATA_SKEW, 0, ksz90x1_txd_grp, 4 },
    148 		{ MII_KSZ9021_EXT_RGMII_CLOCK_SKEW, 0, ksz9021_clk_grp, 4 },
    149 	};
    150 	int i, ret = 0;
    151 
    152 	for (i = 0; i < ARRAY_SIZE(ofcfg); i++) {
    153 		ret = ksz90x1_of_config_group(phydev, &(ofcfg[i]));
    154 		if (ret)
    155 			return ret;
    156 	}
    157 
    158 	return 0;
    159 }
    160 
    161 static int ksz9031_of_config(struct phy_device *phydev)
    162 {
    163 	struct ksz90x1_ofcfg ofcfg[] = {
    164 		{ MII_KSZ9031_EXT_RGMII_CTRL_SIG_SKEW, 2, ksz9031_ctl_grp, 2 },
    165 		{ MII_KSZ9031_EXT_RGMII_RX_DATA_SKEW, 2, ksz90x1_rxd_grp, 4 },
    166 		{ MII_KSZ9031_EXT_RGMII_TX_DATA_SKEW, 2, ksz90x1_txd_grp, 4 },
    167 		{ MII_KSZ9031_EXT_RGMII_CLOCK_SKEW, 2, ksz9031_clk_grp, 2 },
    168 	};
    169 	int i, ret = 0;
    170 
    171 	for (i = 0; i < ARRAY_SIZE(ofcfg); i++) {
    172 		ret = ksz90x1_of_config_group(phydev, &(ofcfg[i]));
    173 		if (ret)
    174 			return ret;
    175 	}
    176 
    177 	return 0;
    178 }
    179 
    180 static int ksz9031_center_flp_timing(struct phy_device *phydev)
    181 {
    182 	struct phy_driver *drv = phydev->drv;
    183 	int ret = 0;
    184 
    185 	if (!drv || !drv->writeext)
    186 		return -EOPNOTSUPP;
    187 
    188 	ret = drv->writeext(phydev, 0, 0, MII_KSZ9031_FLP_BURST_TX_LO, 0x1A80);
    189 	if (ret)
    190 		return ret;
    191 
    192 	ret = drv->writeext(phydev, 0, 0, MII_KSZ9031_FLP_BURST_TX_HI, 0x6);
    193 	return ret;
    194 }
    195 
    196 #else /* !CONFIG_DM_ETH */
    197 static int ksz9021_of_config(struct phy_device *phydev)
    198 {
    199 	return 0;
    200 }
    201 
    202 static int ksz9031_of_config(struct phy_device *phydev)
    203 {
    204 	return 0;
    205 }
    206 
    207 static int ksz9031_center_flp_timing(struct phy_device *phydev)
    208 {
    209 	return 0;
    210 }
    211 #endif
    212 
    213 /*
    214  * KSZ9021
    215  */
    216 int ksz9021_phy_extended_write(struct phy_device *phydev, int regnum, u16 val)
    217 {
    218 	/* extended registers */
    219 	phy_write(phydev, MDIO_DEVAD_NONE,
    220 		  MII_KSZ9021_EXTENDED_CTRL, regnum | 0x8000);
    221 	return phy_write(phydev, MDIO_DEVAD_NONE,
    222 			 MII_KSZ9021_EXTENDED_DATAW, val);
    223 }
    224 
    225 int ksz9021_phy_extended_read(struct phy_device *phydev, int regnum)
    226 {
    227 	/* extended registers */
    228 	phy_write(phydev, MDIO_DEVAD_NONE, MII_KSZ9021_EXTENDED_CTRL, regnum);
    229 	return phy_read(phydev, MDIO_DEVAD_NONE, MII_KSZ9021_EXTENDED_DATAR);
    230 }
    231 
    232 
    233 static int ksz9021_phy_extread(struct phy_device *phydev, int addr, int devaddr,
    234 			       int regnum)
    235 {
    236 	return ksz9021_phy_extended_read(phydev, regnum);
    237 }
    238 
    239 static int ksz9021_phy_extwrite(struct phy_device *phydev, int addr,
    240 				int devaddr, int regnum, u16 val)
    241 {
    242 	return ksz9021_phy_extended_write(phydev, regnum, val);
    243 }
    244 
    245 static int ksz9021_config(struct phy_device *phydev)
    246 {
    247 	unsigned ctrl1000 = 0;
    248 	const unsigned master = CTRL1000_PREFER_MASTER |
    249 	CTRL1000_CONFIG_MASTER | CTRL1000_MANUAL_CONFIG;
    250 	unsigned features = phydev->drv->features;
    251 	int ret;
    252 
    253 	ret = ksz9021_of_config(phydev);
    254 	if (ret)
    255 		return ret;
    256 
    257 	if (env_get("disable_giga"))
    258 		features &= ~(SUPPORTED_1000baseT_Half |
    259 		SUPPORTED_1000baseT_Full);
    260 	/* force master mode for 1000BaseT due to chip errata */
    261 	if (features & SUPPORTED_1000baseT_Half)
    262 		ctrl1000 |= ADVERTISE_1000HALF | master;
    263 	if (features & SUPPORTED_1000baseT_Full)
    264 		ctrl1000 |= ADVERTISE_1000FULL | master;
    265 	phydev->advertising = features;
    266 	phydev->supported = features;
    267 	phy_write(phydev, MDIO_DEVAD_NONE, MII_CTRL1000, ctrl1000);
    268 	genphy_config_aneg(phydev);
    269 	genphy_restart_aneg(phydev);
    270 	return 0;
    271 }
    272 
    273 static struct phy_driver ksz9021_driver = {
    274 	.name = "Micrel ksz9021",
    275 	.uid  = 0x221610,
    276 	.mask = 0xfffff0,
    277 	.features = PHY_GBIT_FEATURES,
    278 	.config = &ksz9021_config,
    279 	.startup = &ksz90xx_startup,
    280 	.shutdown = &genphy_shutdown,
    281 	.writeext = &ksz9021_phy_extwrite,
    282 	.readext = &ksz9021_phy_extread,
    283 };
    284 
    285 /*
    286  * KSZ9031
    287  */
    288 int ksz9031_phy_extended_write(struct phy_device *phydev,
    289 			       int devaddr, int regnum, u16 mode, u16 val)
    290 {
    291 	/*select register addr for mmd*/
    292 	phy_write(phydev, MDIO_DEVAD_NONE,
    293 		  MII_KSZ9031_MMD_ACCES_CTRL, devaddr);
    294 	/*select register for mmd*/
    295 	phy_write(phydev, MDIO_DEVAD_NONE,
    296 		  MII_KSZ9031_MMD_REG_DATA, regnum);
    297 	/*setup mode*/
    298 	phy_write(phydev, MDIO_DEVAD_NONE,
    299 		  MII_KSZ9031_MMD_ACCES_CTRL, (mode | devaddr));
    300 	/*write the value*/
    301 	return	phy_write(phydev, MDIO_DEVAD_NONE,
    302 			  MII_KSZ9031_MMD_REG_DATA, val);
    303 }
    304 
    305 int ksz9031_phy_extended_read(struct phy_device *phydev, int devaddr,
    306 			      int regnum, u16 mode)
    307 {
    308 	phy_write(phydev, MDIO_DEVAD_NONE,
    309 		  MII_KSZ9031_MMD_ACCES_CTRL, devaddr);
    310 	phy_write(phydev, MDIO_DEVAD_NONE,
    311 		  MII_KSZ9031_MMD_REG_DATA, regnum);
    312 	phy_write(phydev, MDIO_DEVAD_NONE,
    313 		  MII_KSZ9031_MMD_ACCES_CTRL, (devaddr | mode));
    314 	return phy_read(phydev, MDIO_DEVAD_NONE, MII_KSZ9031_MMD_REG_DATA);
    315 }
    316 
    317 static int ksz9031_phy_extread(struct phy_device *phydev, int addr, int devaddr,
    318 			       int regnum)
    319 {
    320 	return ksz9031_phy_extended_read(phydev, devaddr, regnum,
    321 					 MII_KSZ9031_MOD_DATA_NO_POST_INC);
    322 }
    323 
    324 static int ksz9031_phy_extwrite(struct phy_device *phydev, int addr,
    325 				int devaddr, int regnum, u16 val)
    326 {
    327 	return ksz9031_phy_extended_write(phydev, devaddr, regnum,
    328 					  MII_KSZ9031_MOD_DATA_POST_INC_RW, val);
    329 }
    330 
    331 static int ksz9031_config(struct phy_device *phydev)
    332 {
    333 	int ret;
    334 
    335 	ret = ksz9031_of_config(phydev);
    336 	if (ret)
    337 		return ret;
    338 	ret = ksz9031_center_flp_timing(phydev);
    339 	if (ret)
    340 		return ret;
    341 
    342 	/* add an option to disable the gigabit feature of this PHY */
    343 	if (env_get("disable_giga")) {
    344 		unsigned features;
    345 		unsigned bmcr;
    346 
    347 		/* disable speed 1000 in features supported by the PHY */
    348 		features = phydev->drv->features;
    349 		features &= ~(SUPPORTED_1000baseT_Half |
    350 				SUPPORTED_1000baseT_Full);
    351 		phydev->advertising = phydev->supported = features;
    352 
    353 		/* disable speed 1000 in Basic Control Register */
    354 		bmcr = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR);
    355 		bmcr &= ~(1 << 6);
    356 		phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, bmcr);
    357 
    358 		/* disable speed 1000 in 1000Base-T Control Register */
    359 		phy_write(phydev, MDIO_DEVAD_NONE, MII_CTRL1000, 0);
    360 
    361 		/* start autoneg */
    362 		genphy_config_aneg(phydev);
    363 		genphy_restart_aneg(phydev);
    364 
    365 		return 0;
    366 	}
    367 
    368 	return genphy_config(phydev);
    369 }
    370 
    371 static struct phy_driver ksz9031_driver = {
    372 	.name = "Micrel ksz9031",
    373 	.uid  = 0x221620,
    374 	.mask = 0xfffff0,
    375 	.features = PHY_GBIT_FEATURES,
    376 	.config   = &ksz9031_config,
    377 	.startup  = &ksz90xx_startup,
    378 	.shutdown = &genphy_shutdown,
    379 	.writeext = &ksz9031_phy_extwrite,
    380 	.readext = &ksz9031_phy_extread,
    381 };
    382 
    383 int phy_micrel_ksz90x1_init(void)
    384 {
    385 	phy_register(&ksz9021_driver);
    386 	phy_register(&ksz9031_driver);
    387 	return 0;
    388 }
    389