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@adaptrum.com> for Adaptrum, Inc.
10  */
11 #include <common.h>
12 #include <dm.h>
13 #include <errno.h>
14 #include <micrel.h>
15 #include <phy.h>
16 
17 /*
18  * KSZ9021 - KSZ9031 common
19  */
20 
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)
26 
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
31 
32 #define CTRL1000_PREFER_MASTER		(1 << 10)
33 #define CTRL1000_CONFIG_MASTER		(1 << 11)
34 #define CTRL1000_MANUAL_CONFIG		(1 << 12)
35 
36 /* KSZ9031 PHY Registers */
37 #define MII_KSZ9031_MMD_ACCES_CTRL	0x0d
38 #define MII_KSZ9031_MMD_REG_DATA	0x0e
39 
40 static int ksz90xx_startup(struct phy_device *phydev)
41 {
42 	unsigned phy_ctl;
43 	int ret;
44 
45 	ret = genphy_update_link(phydev);
46 	if (ret)
47 		return ret;
48 
49 	phy_ctl = phy_read(phydev, MDIO_DEVAD_NONE, MII_KSZ90xx_PHY_CTL);
50 
51 	if (phy_ctl & MIIM_KSZ90xx_PHYCTL_DUPLEX)
52 		phydev->duplex = DUPLEX_FULL;
53 	else
54 		phydev->duplex = DUPLEX_HALF;
55 
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;
62 	return 0;
63 }
64 
65 /* Common OF config bits for KSZ9021 and KSZ9031 */
66 #ifdef CONFIG_DM_ETH
67 struct ksz90x1_reg_field {
68 	const char	*name;
69 	const u8	size;	/* Size of the bitfield, in bits */
70 	const u8	off;	/* Offset from bit 0 */
71 	const u8	dflt;	/* Default value */
72 };
73 
74 struct ksz90x1_ofcfg {
75 	const u16			reg;
76 	const u16			devad;
77 	const struct ksz90x1_reg_field	*grp;
78 	const u16			grpsz;
79 };
80 
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 }
84 };
85 
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 },
89 };
90 
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 },
94 };
95 
96 static const struct ksz90x1_reg_field ksz9031_ctl_grp[] = {
97 	{ "txen-skew-ps", 4, 0, 0x7 }, { "rxdv-skew-ps", 4, 4, 0x7 }
98 };
99 
100 static const struct ksz90x1_reg_field ksz9031_clk_grp[] = {
101 	{ "rxc-skew-ps", 5, 0, 0xf }, { "txc-skew-ps", 5, 5, 0xf }
102 };
103 
104 static int ksz90x1_of_config_group(struct phy_device *phydev,
105 				   struct ksz90x1_ofcfg *ofcfg)
106 {
107 	struct udevice *dev = phydev->dev;
108 	struct phy_driver *drv = phydev->drv;
109 	const int ps_to_regval = 60;
110 	int val[4];
111 	int i, changed = 0, offset, max;
112 	u16 regval = 0;
113 
114 	if (!drv || !drv->writeext)
115 		return -EOPNOTSUPP;
116 
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;
120 		if (val[i] == -1) {
121 			/* Default register value for KSZ9021 */
122 			regval |= ofcfg->grp[i].dflt << offset;
123 		} else {
124 			changed = 1;	/* Value was changed in OF */
125 			/* Calculate the register value and fix corner cases */
126 			if (val[i] > ps_to_regval * 0xf) {
127 				max = (1 << ofcfg->grp[i].size) - 1;
128 				regval |= max << offset;
129 			} else {
130 				regval |= (val[i] / ps_to_regval) << offset;
131 			}
132 		}
133 	}
134 
135 	if (!changed)
136 		return 0;
137 
138 	return drv->writeext(phydev, 0, ofcfg->devad, ofcfg->reg, regval);
139 }
140 
141 static int ksz9021_of_config(struct phy_device *phydev)
142 {
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 },
147 	};
148 	int i, ret = 0;
149 
150 	for (i = 0; i < ARRAY_SIZE(ofcfg); i++) {
151 		ret = ksz90x1_of_config_group(phydev, &(ofcfg[i]));
152 		if (ret)
153 			return ret;
154 	}
155 
156 	return 0;
157 }
158 
159 static int ksz9031_of_config(struct phy_device *phydev)
160 {
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 },
166 	};
167 	int i, ret = 0;
168 
169 	for (i = 0; i < ARRAY_SIZE(ofcfg); i++) {
170 		ret = ksz90x1_of_config_group(phydev, &(ofcfg[i]));
171 		if (ret)
172 			return ret;
173 	}
174 
175 	return 0;
176 }
177 
178 static int ksz9031_center_flp_timing(struct phy_device *phydev)
179 {
180 	struct phy_driver *drv = phydev->drv;
181 	int ret = 0;
182 
183 	if (!drv || !drv->writeext)
184 		return -EOPNOTSUPP;
185 
186 	ret = drv->writeext(phydev, 0, 0, MII_KSZ9031_FLP_BURST_TX_LO, 0x1A80);
187 	if (ret)
188 		return ret;
189 
190 	ret = drv->writeext(phydev, 0, 0, MII_KSZ9031_FLP_BURST_TX_HI, 0x6);
191 	return ret;
192 }
193 
194 #else /* !CONFIG_DM_ETH */
195 static int ksz9021_of_config(struct phy_device *phydev)
196 {
197 	return 0;
198 }
199 
200 static int ksz9031_of_config(struct phy_device *phydev)
201 {
202 	return 0;
203 }
204 
205 static int ksz9031_center_flp_timing(struct phy_device *phydev)
206 {
207 	return 0;
208 }
209 #endif
210 
211 /*
212  * KSZ9021
213  */
214 int ksz9021_phy_extended_write(struct phy_device *phydev, int regnum, u16 val)
215 {
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);
221 }
222 
223 int ksz9021_phy_extended_read(struct phy_device *phydev, int regnum)
224 {
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);
228 }
229 
230 
231 static int ksz9021_phy_extread(struct phy_device *phydev, int addr, int devaddr,
232 			       int regnum)
233 {
234 	return ksz9021_phy_extended_read(phydev, regnum);
235 }
236 
237 static int ksz9021_phy_extwrite(struct phy_device *phydev, int addr,
238 				int devaddr, int regnum, u16 val)
239 {
240 	return ksz9021_phy_extended_write(phydev, regnum, val);
241 }
242 
243 static int ksz9021_config(struct phy_device *phydev)
244 {
245 	unsigned ctrl1000 = 0;
246 	const unsigned master = CTRL1000_PREFER_MASTER |
247 	CTRL1000_CONFIG_MASTER | CTRL1000_MANUAL_CONFIG;
248 	unsigned features = phydev->drv->features;
249 	int ret;
250 
251 	ret = ksz9021_of_config(phydev);
252 	if (ret)
253 		return ret;
254 
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);
268 	return 0;
269 }
270 
271 static struct phy_driver ksz9021_driver = {
272 	.name = "Micrel ksz9021",
273 	.uid  = 0x221610,
274 	.mask = 0xfffff0,
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,
281 };
282 
283 /*
284  * KSZ9031
285  */
286 int ksz9031_phy_extended_write(struct phy_device *phydev,
287 			       int devaddr, int regnum, u16 mode, u16 val)
288 {
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);
295 	/*setup mode*/
296 	phy_write(phydev, MDIO_DEVAD_NONE,
297 		  MII_KSZ9031_MMD_ACCES_CTRL, (mode | devaddr));
298 	/*write the value*/
299 	return	phy_write(phydev, MDIO_DEVAD_NONE,
300 			  MII_KSZ9031_MMD_REG_DATA, val);
301 }
302 
303 int ksz9031_phy_extended_read(struct phy_device *phydev, int devaddr,
304 			      int regnum, u16 mode)
305 {
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);
313 }
314 
315 static int ksz9031_phy_extread(struct phy_device *phydev, int addr, int devaddr,
316 			       int regnum)
317 {
318 	return ksz9031_phy_extended_read(phydev, devaddr, regnum,
319 					 MII_KSZ9031_MOD_DATA_NO_POST_INC);
320 }
321 
322 static int ksz9031_phy_extwrite(struct phy_device *phydev, int addr,
323 				int devaddr, int regnum, u16 val)
324 {
325 	return ksz9031_phy_extended_write(phydev, devaddr, regnum,
326 					  MII_KSZ9031_MOD_DATA_POST_INC_RW, val);
327 }
328 
329 static int ksz9031_config(struct phy_device *phydev)
330 {
331 	int ret;
332 
333 	ret = ksz9031_of_config(phydev);
334 	if (ret)
335 		return ret;
336 	ret = ksz9031_center_flp_timing(phydev);
337 	if (ret)
338 		return ret;
339 
340 	/* add an option to disable the gigabit feature of this PHY */
341 	if (env_get("disable_giga")) {
342 		unsigned features;
343 		unsigned bmcr;
344 
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;
350 
351 		/* disable speed 1000 in Basic Control Register */
352 		bmcr = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR);
353 		bmcr &= ~(1 << 6);
354 		phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, bmcr);
355 
356 		/* disable speed 1000 in 1000Base-T Control Register */
357 		phy_write(phydev, MDIO_DEVAD_NONE, MII_CTRL1000, 0);
358 
359 		/* start autoneg */
360 		genphy_config_aneg(phydev);
361 		genphy_restart_aneg(phydev);
362 
363 		return 0;
364 	}
365 
366 	return genphy_config(phydev);
367 }
368 
369 static struct phy_driver ksz9031_driver = {
370 	.name = "Micrel ksz9031",
371 	.uid  = 0x221620,
372 	.mask = 0xfffff0,
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,
379 };
380 
381 int phy_micrel_ksz90x1_init(void)
382 {
383 	phy_register(&ksz9021_driver);
384 	phy_register(&ksz9031_driver);
385 	return 0;
386 }
387