1 // SPDX-License-Identifier: GPL-2.0+
5 * Copyright 2010-2011 Freescale Semiconductor, Inc.
7 * (C) 2012 NetModule AG, David Andrey, added KSZ9031
8 * (C) Copyright 2017 Adaptrum, Inc.
9 * Written by Alexandru Gagniuc <alex.g@adaptrum.com> for Adaptrum, Inc.
18 * KSZ9021 - KSZ9031 common
21 #define MII_KSZ90xx_PHY_CTL 0x1f
22 #define MIIM_KSZ90xx_PHYCTL_1000 (1 << 6)
23 #define MIIM_KSZ90xx_PHYCTL_100 (1 << 5)
24 #define MIIM_KSZ90xx_PHYCTL_10 (1 << 4)
25 #define MIIM_KSZ90xx_PHYCTL_DUPLEX (1 << 3)
27 /* KSZ9021 PHY Registers */
28 #define MII_KSZ9021_EXTENDED_CTRL 0x0b
29 #define MII_KSZ9021_EXTENDED_DATAW 0x0c
30 #define MII_KSZ9021_EXTENDED_DATAR 0x0d
32 #define CTRL1000_PREFER_MASTER (1 << 10)
33 #define CTRL1000_CONFIG_MASTER (1 << 11)
34 #define CTRL1000_MANUAL_CONFIG (1 << 12)
36 /* KSZ9031 PHY Registers */
37 #define MII_KSZ9031_MMD_ACCES_CTRL 0x0d
38 #define MII_KSZ9031_MMD_REG_DATA 0x0e
40 static int ksz90xx_startup(struct phy_device *phydev)
45 ret = genphy_update_link(phydev);
49 phy_ctl = phy_read(phydev, MDIO_DEVAD_NONE, MII_KSZ90xx_PHY_CTL);
51 if (phy_ctl & MIIM_KSZ90xx_PHYCTL_DUPLEX)
52 phydev->duplex = DUPLEX_FULL;
54 phydev->duplex = DUPLEX_HALF;
56 if (phy_ctl & MIIM_KSZ90xx_PHYCTL_1000)
57 phydev->speed = SPEED_1000;
58 else if (phy_ctl & MIIM_KSZ90xx_PHYCTL_100)
59 phydev->speed = SPEED_100;
60 else if (phy_ctl & MIIM_KSZ90xx_PHYCTL_10)
61 phydev->speed = SPEED_10;
65 /* Common OF config bits for KSZ9021 and KSZ9031 */
67 struct ksz90x1_reg_field {
69 const u8 size; /* Size of the bitfield, in bits */
70 const u8 off; /* Offset from bit 0 */
71 const u8 dflt; /* Default value */
74 struct ksz90x1_ofcfg {
77 const struct ksz90x1_reg_field *grp;
81 static const struct ksz90x1_reg_field ksz90x1_rxd_grp[] = {
82 { "rxd0-skew-ps", 4, 0, 0x7 }, { "rxd1-skew-ps", 4, 4, 0x7 },
83 { "rxd2-skew-ps", 4, 8, 0x7 }, { "rxd3-skew-ps", 4, 12, 0x7 }
86 static const struct ksz90x1_reg_field ksz90x1_txd_grp[] = {
87 { "txd0-skew-ps", 4, 0, 0x7 }, { "txd1-skew-ps", 4, 4, 0x7 },
88 { "txd2-skew-ps", 4, 8, 0x7 }, { "txd3-skew-ps", 4, 12, 0x7 },
91 static const struct ksz90x1_reg_field ksz9021_clk_grp[] = {
92 { "txen-skew-ps", 4, 0, 0x7 }, { "txc-skew-ps", 4, 4, 0x7 },
93 { "rxdv-skew-ps", 4, 8, 0x7 }, { "rxc-skew-ps", 4, 12, 0x7 },
96 static const struct ksz90x1_reg_field ksz9031_ctl_grp[] = {
97 { "txen-skew-ps", 4, 0, 0x7 }, { "rxdv-skew-ps", 4, 4, 0x7 }
100 static const struct ksz90x1_reg_field ksz9031_clk_grp[] = {
101 { "rxc-skew-ps", 5, 0, 0xf }, { "txc-skew-ps", 5, 5, 0xf }
104 static int ksz90x1_of_config_group(struct phy_device *phydev,
105 struct ksz90x1_ofcfg *ofcfg)
107 struct udevice *dev = phydev->dev;
108 struct phy_driver *drv = phydev->drv;
109 const int ps_to_regval = 60;
111 int i, changed = 0, offset, max;
114 if (!drv || !drv->writeext)
117 for (i = 0; i < ofcfg->grpsz; i++) {
118 val[i] = dev_read_u32_default(dev, ofcfg->grp[i].name, ~0);
119 offset = ofcfg->grp[i].off;
121 /* Default register value for KSZ9021 */
122 regval |= ofcfg->grp[i].dflt << offset;
124 changed = 1; /* Value was changed in OF */
125 /* Calculate the register value and fix corner cases */
126 max = (1 << ofcfg->grp[i].size) - 1;
127 if (val[i] > ps_to_regval * max) {
128 regval |= max << offset;
130 regval |= (val[i] / ps_to_regval) << offset;
138 return drv->writeext(phydev, 0, ofcfg->devad, ofcfg->reg, regval);
141 static int ksz9021_of_config(struct phy_device *phydev)
143 struct ksz90x1_ofcfg ofcfg[] = {
144 { MII_KSZ9021_EXT_RGMII_RX_DATA_SKEW, 0, ksz90x1_rxd_grp, 4 },
145 { MII_KSZ9021_EXT_RGMII_TX_DATA_SKEW, 0, ksz90x1_txd_grp, 4 },
146 { MII_KSZ9021_EXT_RGMII_CLOCK_SKEW, 0, ksz9021_clk_grp, 4 },
150 for (i = 0; i < ARRAY_SIZE(ofcfg); i++) {
151 ret = ksz90x1_of_config_group(phydev, &(ofcfg[i]));
159 static int ksz9031_of_config(struct phy_device *phydev)
161 struct ksz90x1_ofcfg ofcfg[] = {
162 { MII_KSZ9031_EXT_RGMII_CTRL_SIG_SKEW, 2, ksz9031_ctl_grp, 2 },
163 { MII_KSZ9031_EXT_RGMII_RX_DATA_SKEW, 2, ksz90x1_rxd_grp, 4 },
164 { MII_KSZ9031_EXT_RGMII_TX_DATA_SKEW, 2, ksz90x1_txd_grp, 4 },
165 { MII_KSZ9031_EXT_RGMII_CLOCK_SKEW, 2, ksz9031_clk_grp, 2 },
169 for (i = 0; i < ARRAY_SIZE(ofcfg); i++) {
170 ret = ksz90x1_of_config_group(phydev, &(ofcfg[i]));
178 static int ksz9031_center_flp_timing(struct phy_device *phydev)
180 struct phy_driver *drv = phydev->drv;
183 if (!drv || !drv->writeext)
186 ret = drv->writeext(phydev, 0, 0, MII_KSZ9031_FLP_BURST_TX_LO, 0x1A80);
190 ret = drv->writeext(phydev, 0, 0, MII_KSZ9031_FLP_BURST_TX_HI, 0x6);
194 #else /* !CONFIG_DM_ETH */
195 static int ksz9021_of_config(struct phy_device *phydev)
200 static int ksz9031_of_config(struct phy_device *phydev)
205 static int ksz9031_center_flp_timing(struct phy_device *phydev)
214 int ksz9021_phy_extended_write(struct phy_device *phydev, int regnum, u16 val)
216 /* extended registers */
217 phy_write(phydev, MDIO_DEVAD_NONE,
218 MII_KSZ9021_EXTENDED_CTRL, regnum | 0x8000);
219 return phy_write(phydev, MDIO_DEVAD_NONE,
220 MII_KSZ9021_EXTENDED_DATAW, val);
223 int ksz9021_phy_extended_read(struct phy_device *phydev, int regnum)
225 /* extended registers */
226 phy_write(phydev, MDIO_DEVAD_NONE, MII_KSZ9021_EXTENDED_CTRL, regnum);
227 return phy_read(phydev, MDIO_DEVAD_NONE, MII_KSZ9021_EXTENDED_DATAR);
231 static int ksz9021_phy_extread(struct phy_device *phydev, int addr, int devaddr,
234 return ksz9021_phy_extended_read(phydev, regnum);
237 static int ksz9021_phy_extwrite(struct phy_device *phydev, int addr,
238 int devaddr, int regnum, u16 val)
240 return ksz9021_phy_extended_write(phydev, regnum, val);
243 static int ksz9021_config(struct phy_device *phydev)
245 unsigned ctrl1000 = 0;
246 const unsigned master = CTRL1000_PREFER_MASTER |
247 CTRL1000_CONFIG_MASTER | CTRL1000_MANUAL_CONFIG;
248 unsigned features = phydev->drv->features;
251 ret = ksz9021_of_config(phydev);
255 if (env_get("disable_giga"))
256 features &= ~(SUPPORTED_1000baseT_Half |
257 SUPPORTED_1000baseT_Full);
258 /* force master mode for 1000BaseT due to chip errata */
259 if (features & SUPPORTED_1000baseT_Half)
260 ctrl1000 |= ADVERTISE_1000HALF | master;
261 if (features & SUPPORTED_1000baseT_Full)
262 ctrl1000 |= ADVERTISE_1000FULL | master;
263 phydev->advertising = features;
264 phydev->supported = features;
265 phy_write(phydev, MDIO_DEVAD_NONE, MII_CTRL1000, ctrl1000);
266 genphy_config_aneg(phydev);
267 genphy_restart_aneg(phydev);
271 static struct phy_driver ksz9021_driver = {
272 .name = "Micrel ksz9021",
275 .features = PHY_GBIT_FEATURES,
276 .config = &ksz9021_config,
277 .startup = &ksz90xx_startup,
278 .shutdown = &genphy_shutdown,
279 .writeext = &ksz9021_phy_extwrite,
280 .readext = &ksz9021_phy_extread,
286 int ksz9031_phy_extended_write(struct phy_device *phydev,
287 int devaddr, int regnum, u16 mode, u16 val)
289 /*select register addr for mmd*/
290 phy_write(phydev, MDIO_DEVAD_NONE,
291 MII_KSZ9031_MMD_ACCES_CTRL, devaddr);
292 /*select register for mmd*/
293 phy_write(phydev, MDIO_DEVAD_NONE,
294 MII_KSZ9031_MMD_REG_DATA, regnum);
296 phy_write(phydev, MDIO_DEVAD_NONE,
297 MII_KSZ9031_MMD_ACCES_CTRL, (mode | devaddr));
299 return phy_write(phydev, MDIO_DEVAD_NONE,
300 MII_KSZ9031_MMD_REG_DATA, val);
303 int ksz9031_phy_extended_read(struct phy_device *phydev, int devaddr,
304 int regnum, u16 mode)
306 phy_write(phydev, MDIO_DEVAD_NONE,
307 MII_KSZ9031_MMD_ACCES_CTRL, devaddr);
308 phy_write(phydev, MDIO_DEVAD_NONE,
309 MII_KSZ9031_MMD_REG_DATA, regnum);
310 phy_write(phydev, MDIO_DEVAD_NONE,
311 MII_KSZ9031_MMD_ACCES_CTRL, (devaddr | mode));
312 return phy_read(phydev, MDIO_DEVAD_NONE, MII_KSZ9031_MMD_REG_DATA);
315 static int ksz9031_phy_extread(struct phy_device *phydev, int addr, int devaddr,
318 return ksz9031_phy_extended_read(phydev, devaddr, regnum,
319 MII_KSZ9031_MOD_DATA_NO_POST_INC);
322 static int ksz9031_phy_extwrite(struct phy_device *phydev, int addr,
323 int devaddr, int regnum, u16 val)
325 return ksz9031_phy_extended_write(phydev, devaddr, regnum,
326 MII_KSZ9031_MOD_DATA_POST_INC_RW, val);
329 static int ksz9031_config(struct phy_device *phydev)
333 ret = ksz9031_of_config(phydev);
336 ret = ksz9031_center_flp_timing(phydev);
340 /* add an option to disable the gigabit feature of this PHY */
341 if (env_get("disable_giga")) {
345 /* disable speed 1000 in features supported by the PHY */
346 features = phydev->drv->features;
347 features &= ~(SUPPORTED_1000baseT_Half |
348 SUPPORTED_1000baseT_Full);
349 phydev->advertising = phydev->supported = features;
351 /* disable speed 1000 in Basic Control Register */
352 bmcr = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR);
354 phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, bmcr);
356 /* disable speed 1000 in 1000Base-T Control Register */
357 phy_write(phydev, MDIO_DEVAD_NONE, MII_CTRL1000, 0);
360 genphy_config_aneg(phydev);
361 genphy_restart_aneg(phydev);
366 return genphy_config(phydev);
369 static struct phy_driver ksz9031_driver = {
370 .name = "Micrel ksz9031",
373 .features = PHY_GBIT_FEATURES,
374 .config = &ksz9031_config,
375 .startup = &ksz90xx_startup,
376 .shutdown = &genphy_shutdown,
377 .writeext = &ksz9031_phy_extwrite,
378 .readext = &ksz9031_phy_extread,
381 int phy_micrel_ksz90x1_init(void)
383 phy_register(&ksz9021_driver);
384 phy_register(&ksz9031_driver);