xref: /linux/drivers/net/phy/icplus.c (revision 9f7d35d9f7a184ffb591b090b2cbf63d2d599c02)
1 /*
2  * Driver for ICPlus PHYs
3  *
4  * Copyright (c) 2007 Freescale Semiconductor, Inc.
5  *
6  * This program is free software; you can redistribute  it and/or modify it
7  * under  the terms of  the GNU General  Public License as published by the
8  * Free Software Foundation;  either version 2 of the  License, or (at your
9  * option) any later version.
10  *
11  */
12 #include <linux/kernel.h>
13 #include <linux/string.h>
14 #include <linux/errno.h>
15 #include <linux/unistd.h>
16 #include <linux/interrupt.h>
17 #include <linux/init.h>
18 #include <linux/delay.h>
19 #include <linux/netdevice.h>
20 #include <linux/etherdevice.h>
21 #include <linux/skbuff.h>
22 #include <linux/spinlock.h>
23 #include <linux/mm.h>
24 #include <linux/module.h>
25 #include <linux/mii.h>
26 #include <linux/ethtool.h>
27 #include <linux/phy.h>
28 #include <linux/property.h>
29 
30 #include <asm/io.h>
31 #include <asm/irq.h>
32 #include <linux/uaccess.h>
33 
34 MODULE_DESCRIPTION("ICPlus IP175C/IP101A/IP101G/IC1001 PHY drivers");
35 MODULE_AUTHOR("Michael Barkowski");
36 MODULE_LICENSE("GPL");
37 
38 /* IP101A/G - IP1001 */
39 #define IP10XX_SPEC_CTRL_STATUS		16	/* Spec. Control Register */
40 #define IP1001_RXPHASE_SEL		BIT(0)	/* Add delay on RX_CLK */
41 #define IP1001_TXPHASE_SEL		BIT(1)	/* Add delay on TX_CLK */
42 #define IP1001_SPEC_CTRL_STATUS_2	20	/* IP1001 Spec. Control Reg 2 */
43 #define IP1001_APS_ON			11	/* IP1001 APS Mode  bit */
44 #define IP101A_G_APS_ON			BIT(1)	/* IP101A/G APS Mode bit */
45 #define IP101A_G_IRQ_CONF_STATUS	0x11	/* Conf Info IRQ & Status Reg */
46 #define	IP101A_G_IRQ_PIN_USED		BIT(15) /* INTR pin used */
47 #define IP101A_G_IRQ_ALL_MASK		BIT(11) /* IRQ's inactive */
48 #define IP101A_G_IRQ_SPEED_CHANGE	BIT(2)
49 #define IP101A_G_IRQ_DUPLEX_CHANGE	BIT(1)
50 #define IP101A_G_IRQ_LINK_CHANGE	BIT(0)
51 
52 #define IP101G_DIGITAL_IO_SPEC_CTRL			0x1d
53 #define IP101G_DIGITAL_IO_SPEC_CTRL_SEL_INTR32		BIT(2)
54 
55 /* The 32-pin IP101GR package can re-configure the mode of the RXER/INTR_32 pin
56  * (pin number 21). The hardware default is RXER (receive error) mode. But it
57  * can be configured to interrupt mode manually.
58  */
59 enum ip101gr_sel_intr32 {
60 	IP101GR_SEL_INTR32_KEEP,
61 	IP101GR_SEL_INTR32_INTR,
62 	IP101GR_SEL_INTR32_RXER,
63 };
64 
65 struct ip101a_g_phy_priv {
66 	enum ip101gr_sel_intr32 sel_intr32;
67 };
68 
69 static int ip175c_config_init(struct phy_device *phydev)
70 {
71 	int err, i;
72 	static int full_reset_performed;
73 
74 	if (full_reset_performed == 0) {
75 
76 		/* master reset */
77 		err = mdiobus_write(phydev->mdio.bus, 30, 0, 0x175c);
78 		if (err < 0)
79 			return err;
80 
81 		/* ensure no bus delays overlap reset period */
82 		err = mdiobus_read(phydev->mdio.bus, 30, 0);
83 
84 		/* data sheet specifies reset period is 2 msec */
85 		mdelay(2);
86 
87 		/* enable IP175C mode */
88 		err = mdiobus_write(phydev->mdio.bus, 29, 31, 0x175c);
89 		if (err < 0)
90 			return err;
91 
92 		/* Set MII0 speed and duplex (in PHY mode) */
93 		err = mdiobus_write(phydev->mdio.bus, 29, 22, 0x420);
94 		if (err < 0)
95 			return err;
96 
97 		/* reset switch ports */
98 		for (i = 0; i < 5; i++) {
99 			err = mdiobus_write(phydev->mdio.bus, i,
100 					    MII_BMCR, BMCR_RESET);
101 			if (err < 0)
102 				return err;
103 		}
104 
105 		for (i = 0; i < 5; i++)
106 			err = mdiobus_read(phydev->mdio.bus, i, MII_BMCR);
107 
108 		mdelay(2);
109 
110 		full_reset_performed = 1;
111 	}
112 
113 	if (phydev->mdio.addr != 4) {
114 		phydev->state = PHY_RUNNING;
115 		phydev->speed = SPEED_100;
116 		phydev->duplex = DUPLEX_FULL;
117 		phydev->link = 1;
118 		netif_carrier_on(phydev->attached_dev);
119 	}
120 
121 	return 0;
122 }
123 
124 static int ip1xx_reset(struct phy_device *phydev)
125 {
126 	int bmcr;
127 
128 	/* Software Reset PHY */
129 	bmcr = phy_read(phydev, MII_BMCR);
130 	if (bmcr < 0)
131 		return bmcr;
132 	bmcr |= BMCR_RESET;
133 	bmcr = phy_write(phydev, MII_BMCR, bmcr);
134 	if (bmcr < 0)
135 		return bmcr;
136 
137 	do {
138 		bmcr = phy_read(phydev, MII_BMCR);
139 		if (bmcr < 0)
140 			return bmcr;
141 	} while (bmcr & BMCR_RESET);
142 
143 	return 0;
144 }
145 
146 static int ip1001_config_init(struct phy_device *phydev)
147 {
148 	int c;
149 
150 	c = ip1xx_reset(phydev);
151 	if (c < 0)
152 		return c;
153 
154 	/* Enable Auto Power Saving mode */
155 	c = phy_read(phydev, IP1001_SPEC_CTRL_STATUS_2);
156 	if (c < 0)
157 		return c;
158 	c |= IP1001_APS_ON;
159 	c = phy_write(phydev, IP1001_SPEC_CTRL_STATUS_2, c);
160 	if (c < 0)
161 		return c;
162 
163 	if (phy_interface_is_rgmii(phydev)) {
164 
165 		c = phy_read(phydev, IP10XX_SPEC_CTRL_STATUS);
166 		if (c < 0)
167 			return c;
168 
169 		c &= ~(IP1001_RXPHASE_SEL | IP1001_TXPHASE_SEL);
170 
171 		if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)
172 			c |= (IP1001_RXPHASE_SEL | IP1001_TXPHASE_SEL);
173 		else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID)
174 			c |= IP1001_RXPHASE_SEL;
175 		else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)
176 			c |= IP1001_TXPHASE_SEL;
177 
178 		c = phy_write(phydev, IP10XX_SPEC_CTRL_STATUS, c);
179 		if (c < 0)
180 			return c;
181 	}
182 
183 	return 0;
184 }
185 
186 static int ip175c_read_status(struct phy_device *phydev)
187 {
188 	if (phydev->mdio.addr == 4) /* WAN port */
189 		genphy_read_status(phydev);
190 	else
191 		/* Don't need to read status for switch ports */
192 		phydev->irq = PHY_IGNORE_INTERRUPT;
193 
194 	return 0;
195 }
196 
197 static int ip175c_config_aneg(struct phy_device *phydev)
198 {
199 	if (phydev->mdio.addr == 4) /* WAN port */
200 		genphy_config_aneg(phydev);
201 
202 	return 0;
203 }
204 
205 static int ip101a_g_probe(struct phy_device *phydev)
206 {
207 	struct device *dev = &phydev->mdio.dev;
208 	struct ip101a_g_phy_priv *priv;
209 
210 	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
211 	if (!priv)
212 		return -ENOMEM;
213 
214 	/* Both functions (RX error and interrupt status) are sharing the same
215 	 * pin on the 32-pin IP101GR, so this is an exclusive choice.
216 	 */
217 	if (device_property_read_bool(dev, "icplus,select-rx-error") &&
218 	    device_property_read_bool(dev, "icplus,select-interrupt")) {
219 		dev_err(dev,
220 			"RXER and INTR mode cannot be selected together\n");
221 		return -EINVAL;
222 	}
223 
224 	if (device_property_read_bool(dev, "icplus,select-rx-error"))
225 		priv->sel_intr32 = IP101GR_SEL_INTR32_RXER;
226 	else if (device_property_read_bool(dev, "icplus,select-interrupt"))
227 		priv->sel_intr32 = IP101GR_SEL_INTR32_INTR;
228 	else
229 		priv->sel_intr32 = IP101GR_SEL_INTR32_KEEP;
230 
231 	phydev->priv = priv;
232 
233 	return 0;
234 }
235 
236 static int ip101a_g_config_init(struct phy_device *phydev)
237 {
238 	struct ip101a_g_phy_priv *priv = phydev->priv;
239 	int err, c;
240 
241 	c = ip1xx_reset(phydev);
242 	if (c < 0)
243 		return c;
244 
245 	/* configure the RXER/INTR_32 pin of the 32-pin IP101GR if needed: */
246 	switch (priv->sel_intr32) {
247 	case IP101GR_SEL_INTR32_RXER:
248 		err = phy_modify(phydev, IP101G_DIGITAL_IO_SPEC_CTRL,
249 				 IP101G_DIGITAL_IO_SPEC_CTRL_SEL_INTR32, 0);
250 		if (err < 0)
251 			return err;
252 		break;
253 
254 	case IP101GR_SEL_INTR32_INTR:
255 		err = phy_modify(phydev, IP101G_DIGITAL_IO_SPEC_CTRL,
256 				 IP101G_DIGITAL_IO_SPEC_CTRL_SEL_INTR32,
257 				 IP101G_DIGITAL_IO_SPEC_CTRL_SEL_INTR32);
258 		if (err < 0)
259 			return err;
260 		break;
261 
262 	default:
263 		/* Don't touch IP101G_DIGITAL_IO_SPEC_CTRL because it's not
264 		 * documented on IP101A and it's not clear whether this would
265 		 * cause problems.
266 		 * For the 32-pin IP101GR we simply keep the SEL_INTR32
267 		 * configuration as set by the bootloader when not configured
268 		 * to one of the special functions.
269 		 */
270 		break;
271 	}
272 
273 	/* Enable Auto Power Saving mode */
274 	c = phy_read(phydev, IP10XX_SPEC_CTRL_STATUS);
275 	c |= IP101A_G_APS_ON;
276 
277 	return phy_write(phydev, IP10XX_SPEC_CTRL_STATUS, c);
278 }
279 
280 static int ip101a_g_config_intr(struct phy_device *phydev)
281 {
282 	u16 val;
283 
284 	if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
285 		/* INTR pin used: Speed/link/duplex will cause an interrupt */
286 		val = IP101A_G_IRQ_PIN_USED;
287 	else
288 		val = IP101A_G_IRQ_ALL_MASK;
289 
290 	return phy_write(phydev, IP101A_G_IRQ_CONF_STATUS, val);
291 }
292 
293 static int ip101a_g_did_interrupt(struct phy_device *phydev)
294 {
295 	int val = phy_read(phydev, IP101A_G_IRQ_CONF_STATUS);
296 
297 	if (val < 0)
298 		return 0;
299 
300 	return val & (IP101A_G_IRQ_SPEED_CHANGE |
301 		      IP101A_G_IRQ_DUPLEX_CHANGE |
302 		      IP101A_G_IRQ_LINK_CHANGE);
303 }
304 
305 static int ip101a_g_ack_interrupt(struct phy_device *phydev)
306 {
307 	int err = phy_read(phydev, IP101A_G_IRQ_CONF_STATUS);
308 	if (err < 0)
309 		return err;
310 
311 	return 0;
312 }
313 
314 static struct phy_driver icplus_driver[] = {
315 {
316 	.phy_id		= 0x02430d80,
317 	.name		= "ICPlus IP175C",
318 	.phy_id_mask	= 0x0ffffff0,
319 	.features	= PHY_BASIC_FEATURES,
320 	.config_init	= &ip175c_config_init,
321 	.config_aneg	= &ip175c_config_aneg,
322 	.read_status	= &ip175c_read_status,
323 	.suspend	= genphy_suspend,
324 	.resume		= genphy_resume,
325 }, {
326 	.phy_id		= 0x02430d90,
327 	.name		= "ICPlus IP1001",
328 	.phy_id_mask	= 0x0ffffff0,
329 	.features	= PHY_GBIT_FEATURES,
330 	.config_init	= &ip1001_config_init,
331 	.suspend	= genphy_suspend,
332 	.resume		= genphy_resume,
333 }, {
334 	.phy_id		= 0x02430c54,
335 	.name		= "ICPlus IP101A/G",
336 	.phy_id_mask	= 0x0ffffff0,
337 	.features	= PHY_BASIC_FEATURES,
338 	.probe		= ip101a_g_probe,
339 	.config_intr	= ip101a_g_config_intr,
340 	.did_interrupt	= ip101a_g_did_interrupt,
341 	.ack_interrupt	= ip101a_g_ack_interrupt,
342 	.config_init	= &ip101a_g_config_init,
343 	.suspend	= genphy_suspend,
344 	.resume		= genphy_resume,
345 } };
346 
347 module_phy_driver(icplus_driver);
348 
349 static struct mdio_device_id __maybe_unused icplus_tbl[] = {
350 	{ 0x02430d80, 0x0ffffff0 },
351 	{ 0x02430d90, 0x0ffffff0 },
352 	{ 0x02430c54, 0x0ffffff0 },
353 	{ }
354 };
355 
356 MODULE_DEVICE_TABLE(mdio, icplus_tbl);
357