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