1/*
2 * net/dsa/mv88e6xxx.c - Marvell 88e6xxx switch chip support
3 * Copyright (c) 2008 Marvell Semiconductor
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 */
10
11#include <linux/list.h>
12#include <linux/module.h>
13#include <linux/netdevice.h>
14#include <linux/phy.h>
15#include <net/dsa.h>
16#include "mv88e6xxx.h"
17
18/*
19 * If the switch's ADDR[4:0] strap pins are strapped to zero, it will
20 * use all 32 SMI bus addresses on its SMI bus, and all switch registers
21 * will be directly accessible on some {device address,register address}
22 * pair.  If the ADDR[4:0] pins are not strapped to zero, the switch
23 * will only respond to SMI transactions to that specific address, and
24 * an indirect addressing mechanism needs to be used to access its
25 * registers.
26 */
27static int mv88e6xxx_reg_wait_ready(struct mii_bus *bus, int sw_addr)
28{
29	int ret;
30	int i;
31
32	for (i = 0; i < 16; i++) {
33		ret = mdiobus_read(bus, sw_addr, 0);
34		if (ret < 0)
35			return ret;
36
37		if ((ret & 0x8000) == 0)
38			return 0;
39	}
40
41	return -ETIMEDOUT;
42}
43
44int __mv88e6xxx_reg_read(struct mii_bus *bus, int sw_addr, int addr, int reg)
45{
46	int ret;
47
48	if (sw_addr == 0)
49		return mdiobus_read(bus, addr, reg);
50
51	/*
52	 * Wait for the bus to become free.
53	 */
54	ret = mv88e6xxx_reg_wait_ready(bus, sw_addr);
55	if (ret < 0)
56		return ret;
57
58	/*
59	 * Transmit the read command.
60	 */
61	ret = mdiobus_write(bus, sw_addr, 0, 0x9800 | (addr << 5) | reg);
62	if (ret < 0)
63		return ret;
64
65	/*
66	 * Wait for the read command to complete.
67	 */
68	ret = mv88e6xxx_reg_wait_ready(bus, sw_addr);
69	if (ret < 0)
70		return ret;
71
72	/*
73	 * Read the data.
74	 */
75	ret = mdiobus_read(bus, sw_addr, 1);
76	if (ret < 0)
77		return ret;
78
79	return ret & 0xffff;
80}
81
82int mv88e6xxx_reg_read(struct dsa_switch *ds, int addr, int reg)
83{
84	struct mv88e6xxx_priv_state *ps = (void *)(ds + 1);
85	int ret;
86
87	mutex_lock(&ps->smi_mutex);
88	ret = __mv88e6xxx_reg_read(ds->master_mii_bus,
89				   ds->pd->sw_addr, addr, reg);
90	mutex_unlock(&ps->smi_mutex);
91
92	return ret;
93}
94
95int __mv88e6xxx_reg_write(struct mii_bus *bus, int sw_addr, int addr,
96			  int reg, u16 val)
97{
98	int ret;
99
100	if (sw_addr == 0)
101		return mdiobus_write(bus, addr, reg, val);
102
103	/*
104	 * Wait for the bus to become free.
105	 */
106	ret = mv88e6xxx_reg_wait_ready(bus, sw_addr);
107	if (ret < 0)
108		return ret;
109
110	/*
111	 * Transmit the data to write.
112	 */
113	ret = mdiobus_write(bus, sw_addr, 1, val);
114	if (ret < 0)
115		return ret;
116
117	/*
118	 * Transmit the write command.
119	 */
120	ret = mdiobus_write(bus, sw_addr, 0, 0x9400 | (addr << 5) | reg);
121	if (ret < 0)
122		return ret;
123
124	/*
125	 * Wait for the write command to complete.
126	 */
127	ret = mv88e6xxx_reg_wait_ready(bus, sw_addr);
128	if (ret < 0)
129		return ret;
130
131	return 0;
132}
133
134int mv88e6xxx_reg_write(struct dsa_switch *ds, int addr, int reg, u16 val)
135{
136	struct mv88e6xxx_priv_state *ps = (void *)(ds + 1);
137	int ret;
138
139	mutex_lock(&ps->smi_mutex);
140	ret = __mv88e6xxx_reg_write(ds->master_mii_bus,
141				    ds->pd->sw_addr, addr, reg, val);
142	mutex_unlock(&ps->smi_mutex);
143
144	return ret;
145}
146
147int mv88e6xxx_config_prio(struct dsa_switch *ds)
148{
149	/*
150	 * Configure the IP ToS mapping registers.
151	 */
152	REG_WRITE(REG_GLOBAL, 0x10, 0x0000);
153	REG_WRITE(REG_GLOBAL, 0x11, 0x0000);
154	REG_WRITE(REG_GLOBAL, 0x12, 0x5555);
155	REG_WRITE(REG_GLOBAL, 0x13, 0x5555);
156	REG_WRITE(REG_GLOBAL, 0x14, 0xaaaa);
157	REG_WRITE(REG_GLOBAL, 0x15, 0xaaaa);
158	REG_WRITE(REG_GLOBAL, 0x16, 0xffff);
159	REG_WRITE(REG_GLOBAL, 0x17, 0xffff);
160
161	/*
162	 * Configure the IEEE 802.1p priority mapping register.
163	 */
164	REG_WRITE(REG_GLOBAL, 0x18, 0xfa41);
165
166	return 0;
167}
168
169int mv88e6xxx_set_addr_direct(struct dsa_switch *ds, u8 *addr)
170{
171	REG_WRITE(REG_GLOBAL, 0x01, (addr[0] << 8) | addr[1]);
172	REG_WRITE(REG_GLOBAL, 0x02, (addr[2] << 8) | addr[3]);
173	REG_WRITE(REG_GLOBAL, 0x03, (addr[4] << 8) | addr[5]);
174
175	return 0;
176}
177
178int mv88e6xxx_set_addr_indirect(struct dsa_switch *ds, u8 *addr)
179{
180	int i;
181	int ret;
182
183	for (i = 0; i < 6; i++) {
184		int j;
185
186		/*
187		 * Write the MAC address byte.
188		 */
189		REG_WRITE(REG_GLOBAL2, 0x0d, 0x8000 | (i << 8) | addr[i]);
190
191		/*
192		 * Wait for the write to complete.
193		 */
194		for (j = 0; j < 16; j++) {
195			ret = REG_READ(REG_GLOBAL2, 0x0d);
196			if ((ret & 0x8000) == 0)
197				break;
198		}
199		if (j == 16)
200			return -ETIMEDOUT;
201	}
202
203	return 0;
204}
205
206int mv88e6xxx_phy_read(struct dsa_switch *ds, int addr, int regnum)
207{
208	if (addr >= 0)
209		return mv88e6xxx_reg_read(ds, addr, regnum);
210	return 0xffff;
211}
212
213int mv88e6xxx_phy_write(struct dsa_switch *ds, int addr, int regnum, u16 val)
214{
215	if (addr >= 0)
216		return mv88e6xxx_reg_write(ds, addr, regnum, val);
217	return 0;
218}
219
220#ifdef CONFIG_NET_DSA_MV88E6XXX_NEED_PPU
221static int mv88e6xxx_ppu_disable(struct dsa_switch *ds)
222{
223	int ret;
224	int i;
225
226	ret = REG_READ(REG_GLOBAL, 0x04);
227	REG_WRITE(REG_GLOBAL, 0x04, ret & ~0x4000);
228
229	for (i = 0; i < 1000; i++) {
230	        ret = REG_READ(REG_GLOBAL, 0x00);
231	        msleep(1);
232	        if ((ret & 0xc000) != 0xc000)
233	                return 0;
234	}
235
236	return -ETIMEDOUT;
237}
238
239static int mv88e6xxx_ppu_enable(struct dsa_switch *ds)
240{
241	int ret;
242	int i;
243
244	ret = REG_READ(REG_GLOBAL, 0x04);
245	REG_WRITE(REG_GLOBAL, 0x04, ret | 0x4000);
246
247	for (i = 0; i < 1000; i++) {
248	        ret = REG_READ(REG_GLOBAL, 0x00);
249	        msleep(1);
250	        if ((ret & 0xc000) == 0xc000)
251	                return 0;
252	}
253
254	return -ETIMEDOUT;
255}
256
257static void mv88e6xxx_ppu_reenable_work(struct work_struct *ugly)
258{
259	struct mv88e6xxx_priv_state *ps;
260
261	ps = container_of(ugly, struct mv88e6xxx_priv_state, ppu_work);
262	if (mutex_trylock(&ps->ppu_mutex)) {
263	        struct dsa_switch *ds = ((struct dsa_switch *)ps) - 1;
264
265	        if (mv88e6xxx_ppu_enable(ds) == 0)
266	                ps->ppu_disabled = 0;
267	        mutex_unlock(&ps->ppu_mutex);
268	}
269}
270
271static void mv88e6xxx_ppu_reenable_timer(unsigned long _ps)
272{
273	struct mv88e6xxx_priv_state *ps = (void *)_ps;
274
275	schedule_work(&ps->ppu_work);
276}
277
278static int mv88e6xxx_ppu_access_get(struct dsa_switch *ds)
279{
280	struct mv88e6xxx_priv_state *ps = (void *)(ds + 1);
281	int ret;
282
283	mutex_lock(&ps->ppu_mutex);
284
285	/*
286	 * If the PHY polling unit is enabled, disable it so that
287	 * we can access the PHY registers.  If it was already
288	 * disabled, cancel the timer that is going to re-enable
289	 * it.
290	 */
291	if (!ps->ppu_disabled) {
292	        ret = mv88e6xxx_ppu_disable(ds);
293	        if (ret < 0) {
294	                mutex_unlock(&ps->ppu_mutex);
295	                return ret;
296	        }
297	        ps->ppu_disabled = 1;
298	} else {
299	        del_timer(&ps->ppu_timer);
300	        ret = 0;
301	}
302
303	return ret;
304}
305
306static void mv88e6xxx_ppu_access_put(struct dsa_switch *ds)
307{
308	struct mv88e6xxx_priv_state *ps = (void *)(ds + 1);
309
310	/*
311	 * Schedule a timer to re-enable the PHY polling unit.
312	 */
313	mod_timer(&ps->ppu_timer, jiffies + msecs_to_jiffies(10));
314	mutex_unlock(&ps->ppu_mutex);
315}
316
317void mv88e6xxx_ppu_state_init(struct dsa_switch *ds)
318{
319	struct mv88e6xxx_priv_state *ps = (void *)(ds + 1);
320
321	mutex_init(&ps->ppu_mutex);
322	INIT_WORK(&ps->ppu_work, mv88e6xxx_ppu_reenable_work);
323	init_timer(&ps->ppu_timer);
324	ps->ppu_timer.data = (unsigned long)ps;
325	ps->ppu_timer.function = mv88e6xxx_ppu_reenable_timer;
326}
327
328int mv88e6xxx_phy_read_ppu(struct dsa_switch *ds, int addr, int regnum)
329{
330	int ret;
331
332	ret = mv88e6xxx_ppu_access_get(ds);
333	if (ret >= 0) {
334	        ret = mv88e6xxx_reg_read(ds, addr, regnum);
335	        mv88e6xxx_ppu_access_put(ds);
336	}
337
338	return ret;
339}
340
341int mv88e6xxx_phy_write_ppu(struct dsa_switch *ds, int addr,
342			    int regnum, u16 val)
343{
344	int ret;
345
346	ret = mv88e6xxx_ppu_access_get(ds);
347	if (ret >= 0) {
348	        ret = mv88e6xxx_reg_write(ds, addr, regnum, val);
349	        mv88e6xxx_ppu_access_put(ds);
350	}
351
352	return ret;
353}
354#endif
355
356void mv88e6xxx_poll_link(struct dsa_switch *ds)
357{
358	int i;
359
360	for (i = 0; i < DSA_MAX_PORTS; i++) {
361		struct net_device *dev;
362		int uninitialized_var(port_status);
363		int link;
364		int speed;
365		int duplex;
366		int fc;
367
368		dev = ds->ports[i];
369		if (dev == NULL)
370			continue;
371
372		link = 0;
373		if (dev->flags & IFF_UP) {
374			port_status = mv88e6xxx_reg_read(ds, REG_PORT(i), 0x00);
375			if (port_status < 0)
376				continue;
377
378			link = !!(port_status & 0x0800);
379		}
380
381		if (!link) {
382			if (netif_carrier_ok(dev)) {
383				printk(KERN_INFO "%s: link down\n", dev->name);
384				netif_carrier_off(dev);
385			}
386			continue;
387		}
388
389		switch (port_status & 0x0300) {
390		case 0x0000:
391			speed = 10;
392			break;
393		case 0x0100:
394			speed = 100;
395			break;
396		case 0x0200:
397			speed = 1000;
398			break;
399		default:
400			speed = -1;
401			break;
402		}
403		duplex = (port_status & 0x0400) ? 1 : 0;
404		fc = (port_status & 0x8000) ? 1 : 0;
405
406		if (!netif_carrier_ok(dev)) {
407			printk(KERN_INFO "%s: link up, %d Mb/s, %s duplex, "
408					 "flow control %sabled\n", dev->name,
409					 speed, duplex ? "full" : "half",
410					 fc ? "en" : "dis");
411			netif_carrier_on(dev);
412		}
413	}
414}
415
416static int mv88e6xxx_stats_wait(struct dsa_switch *ds)
417{
418	int ret;
419	int i;
420
421	for (i = 0; i < 10; i++) {
422		ret = REG_READ(REG_GLOBAL, 0x1d);
423		if ((ret & 0x8000) == 0)
424			return 0;
425	}
426
427	return -ETIMEDOUT;
428}
429
430static int mv88e6xxx_stats_snapshot(struct dsa_switch *ds, int port)
431{
432	int ret;
433
434	/*
435	 * Snapshot the hardware statistics counters for this port.
436	 */
437	REG_WRITE(REG_GLOBAL, 0x1d, 0xdc00 | port);
438
439	/*
440	 * Wait for the snapshotting to complete.
441	 */
442	ret = mv88e6xxx_stats_wait(ds);
443	if (ret < 0)
444		return ret;
445
446	return 0;
447}
448
449static void mv88e6xxx_stats_read(struct dsa_switch *ds, int stat, u32 *val)
450{
451	u32 _val;
452	int ret;
453
454	*val = 0;
455
456	ret = mv88e6xxx_reg_write(ds, REG_GLOBAL, 0x1d, 0xcc00 | stat);
457	if (ret < 0)
458		return;
459
460	ret = mv88e6xxx_stats_wait(ds);
461	if (ret < 0)
462		return;
463
464	ret = mv88e6xxx_reg_read(ds, REG_GLOBAL, 0x1e);
465	if (ret < 0)
466		return;
467
468	_val = ret << 16;
469
470	ret = mv88e6xxx_reg_read(ds, REG_GLOBAL, 0x1f);
471	if (ret < 0)
472		return;
473
474	*val = _val | ret;
475}
476
477void mv88e6xxx_get_strings(struct dsa_switch *ds,
478			   int nr_stats, struct mv88e6xxx_hw_stat *stats,
479			   int port, uint8_t *data)
480{
481	int i;
482
483	for (i = 0; i < nr_stats; i++) {
484		memcpy(data + i * ETH_GSTRING_LEN,
485		       stats[i].string, ETH_GSTRING_LEN);
486	}
487}
488
489void mv88e6xxx_get_ethtool_stats(struct dsa_switch *ds,
490				 int nr_stats, struct mv88e6xxx_hw_stat *stats,
491				 int port, uint64_t *data)
492{
493	struct mv88e6xxx_priv_state *ps = (void *)(ds + 1);
494	int ret;
495	int i;
496
497	mutex_lock(&ps->stats_mutex);
498
499	ret = mv88e6xxx_stats_snapshot(ds, port);
500	if (ret < 0) {
501		mutex_unlock(&ps->stats_mutex);
502		return;
503	}
504
505	/*
506	 * Read each of the counters.
507	 */
508	for (i = 0; i < nr_stats; i++) {
509		struct mv88e6xxx_hw_stat *s = stats + i;
510		u32 low;
511		u32 high;
512
513		mv88e6xxx_stats_read(ds, s->reg, &low);
514		if (s->sizeof_stat == 8)
515			mv88e6xxx_stats_read(ds, s->reg + 1, &high);
516		else
517			high = 0;
518
519		data[i] = (((u64)high) << 32) | low;
520	}
521
522	mutex_unlock(&ps->stats_mutex);
523}
524
525static int __init mv88e6xxx_init(void)
526{
527#if IS_ENABLED(CONFIG_NET_DSA_MV88E6131)
528	register_switch_driver(&mv88e6131_switch_driver);
529#endif
530#if IS_ENABLED(CONFIG_NET_DSA_MV88E6123_61_65)
531	register_switch_driver(&mv88e6123_61_65_switch_driver);
532#endif
533	return 0;
534}
535module_init(mv88e6xxx_init);
536
537static void __exit mv88e6xxx_cleanup(void)
538{
539#if IS_ENABLED(CONFIG_NET_DSA_MV88E6123_61_65)
540	unregister_switch_driver(&mv88e6123_61_65_switch_driver);
541#endif
542#if IS_ENABLED(CONFIG_NET_DSA_MV88E6131)
543	unregister_switch_driver(&mv88e6131_switch_driver);
544#endif
545}
546module_exit(mv88e6xxx_cleanup);
547
548MODULE_AUTHOR("Lennert Buytenhek <buytenh@wantstofly.org>");
549MODULE_DESCRIPTION("Driver for Marvell 88E6XXX ethernet switch chips");
550MODULE_LICENSE("GPL");
551