rtl8366rb.c revision 268093
1/*-
2 * Copyright (c) 2011-2012 Stefan Bethke.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * $FreeBSD: head/sys/dev/etherswitch/rtl8366/rtl8366rb.c 268093 2014-07-01 14:33:48Z loos $
27 */
28
29#include <sys/param.h>
30#include <sys/bus.h>
31#include <sys/errno.h>
32#include <sys/kernel.h>
33#include <sys/lock.h>
34#include <sys/malloc.h>
35#include <sys/module.h>
36#include <sys/mutex.h>
37#include <sys/socket.h>
38#include <sys/sockio.h>
39#include <sys/sysctl.h>
40#include <sys/systm.h>
41
42#include <net/if.h>
43#include <net/if_var.h>
44#include <net/ethernet.h>
45#include <net/if_media.h>
46#include <net/if_types.h>
47
48#include <machine/bus.h>
49#include <dev/iicbus/iic.h>
50#include <dev/iicbus/iiconf.h>
51#include <dev/iicbus/iicbus.h>
52#include <dev/mii/mii.h>
53#include <dev/mii/miivar.h>
54
55#include <dev/etherswitch/etherswitch.h>
56#include <dev/etherswitch/rtl8366/rtl8366rbvar.h>
57
58#include "iicbus_if.h"
59#include "miibus_if.h"
60#include "etherswitch_if.h"
61
62
63struct rtl8366rb_softc {
64	struct mtx	sc_mtx;		/* serialize access to softc */
65	int		smi_acquired;	/* serialize access to SMI/I2C bus */
66	struct mtx	callout_mtx;	/* serialize callout */
67	device_t	dev;
68	int		vid[RTL8366RB_NUM_VLANS];
69	char		*ifname[RTL8366RB_NUM_PHYS];
70	device_t	miibus[RTL8366RB_NUM_PHYS];
71	struct ifnet	*ifp[RTL8366RB_NUM_PHYS];
72	struct callout	callout_tick;
73};
74
75static etherswitch_info_t etherswitch_info = {
76	.es_nports =		RTL8366RB_NUM_PORTS,
77	.es_nvlangroups =	RTL8366RB_NUM_VLANS,
78	.es_name =			"Realtek RTL8366RB"
79};
80
81#define RTL_LOCK(_sc)	mtx_lock(&(_sc)->sc_mtx)
82#define RTL_UNLOCK(_sc)	mtx_unlock(&(_sc)->sc_mtx)
83#define RTL_LOCK_ASSERT(_sc, _what)	mtx_assert(&(_s)c->sc_mtx, (_what))
84#define RTL_TRYLOCK(_sc)	mtx_trylock(&(_sc)->sc_mtx)
85
86#define RTL_WAITOK	0
87#define	RTL_NOWAIT	1
88
89#define RTL_SMI_ACQUIRED	1
90#define RTL_SMI_ACQUIRED_ASSERT(_sc) \
91	KASSERT((_sc)->smi_acquired == RTL_SMI_ACQUIRED, ("smi must be acquired @%s", __FUNCTION__))
92
93#if defined(DEBUG)
94#define DPRINTF(dev, args...) device_printf(dev, args)
95#define DEVERR(dev, err, fmt, args...) do { \
96		if (err != 0) device_printf(dev, fmt, err, args); \
97	} while (0)
98#define DEBUG_INCRVAR(var)	do { \
99		var++; \
100	} while (0)
101
102static int callout_blocked = 0;
103static int iic_select_retries = 0;
104static int phy_access_retries = 0;
105static SYSCTL_NODE(_debug, OID_AUTO, rtl8366rb, CTLFLAG_RD, 0, "rtl8366rb");
106SYSCTL_INT(_debug_rtl8366rb, OID_AUTO, callout_blocked, CTLFLAG_RW, &callout_blocked, 0,
107	"number of times the callout couldn't acquire the bus");
108SYSCTL_INT(_debug_rtl8366rb, OID_AUTO, iic_select_retries, CTLFLAG_RW, &iic_select_retries, 0,
109	"number of times the I2C bus selection had to be retried");
110SYSCTL_INT(_debug_rtl8366rb, OID_AUTO, phy_access_retries, CTLFLAG_RW, &phy_access_retries, 0,
111	"number of times PHY register access had to be retried");
112#else
113#define DPRINTF(dev, args...)
114#define DEVERR(dev, err, fmt, args...)
115#define DEBUG_INCRVAR(var)
116#endif
117
118static int smi_probe(device_t dev);
119static int smi_read(device_t dev, uint16_t addr, uint16_t *data, int sleep);
120static int smi_write(device_t dev, uint16_t addr, uint16_t data, int sleep);
121static int smi_rmw(device_t dev, uint16_t addr, uint16_t mask, uint16_t data, int sleep);
122static void rtl8366rb_tick(void *arg);
123static int rtl8366rb_ifmedia_upd(struct ifnet *);
124static void rtl8366rb_ifmedia_sts(struct ifnet *, struct ifmediareq *);
125
126static void
127rtl8366rb_identify(driver_t *driver, device_t parent)
128{
129	device_t child;
130	struct iicbus_ivar *devi;
131
132	if (device_find_child(parent, "rtl8366rb", -1) == NULL) {
133		child = BUS_ADD_CHILD(parent, 0, "rtl8366rb", -1);
134		devi = IICBUS_IVAR(child);
135		devi->addr = RTL8366RB_IIC_ADDR;
136	}
137}
138
139static int
140rtl8366rb_probe(device_t dev)
141{
142	if (smi_probe(dev) != 0)
143		return (ENXIO);
144	device_set_desc(dev, "RTL8366RB Ethernet Switch Controller");
145	return (BUS_PROBE_DEFAULT);
146}
147
148static void
149rtl8366rb_init(device_t dev)
150{
151	/* Initialisation for TL-WR1043ND */
152	smi_rmw(dev, RTL8366RB_RCR,
153		RTL8366RB_RCR_HARD_RESET,
154		RTL8366RB_RCR_HARD_RESET, RTL_WAITOK);
155	DELAY(100000);
156	/* Enable 16 VLAN mode */
157	smi_rmw(dev, RTL8366RB_SGCR,
158		RTL8366RB_SGCR_EN_VLAN | RTL8366RB_SGCR_EN_VLAN_4KTB,
159		RTL8366RB_SGCR_EN_VLAN, RTL_WAITOK);
160	/* remove port 0 form VLAN 0 */
161	smi_rmw(dev, RTL8366RB_VMCR(RTL8366RB_VMCR_MU_REG, 0),
162		(1 << 0), 0, RTL_WAITOK);
163	/* add port 0 untagged and port 5 tagged to VLAN 1 */
164	smi_rmw(dev, RTL8366RB_VMCR(RTL8366RB_VMCR_MU_REG, 1),
165		((1 << 5 | 1 << 0) << RTL8366RB_VMCR_MU_MEMBER_SHIFT)
166			| ((1 << 5 | 1 << 0) << RTL8366RB_VMCR_MU_UNTAG_SHIFT),
167		((1 << 5 | 1 << 0) << RTL8366RB_VMCR_MU_MEMBER_SHIFT
168			| ((1 << 0) << RTL8366RB_VMCR_MU_UNTAG_SHIFT)),
169		RTL_WAITOK);
170	/* set PVLAN 1 for port 0 */
171	smi_rmw(dev, RTL8366RB_PVCR_REG(0),
172		RTL8366RB_PVCR_VAL(0, RTL8366RB_PVCR_PORT_MASK),
173		RTL8366RB_PVCR_VAL(0, 1), RTL_WAITOK);
174}
175
176static int
177rtl8366rb_attach(device_t dev)
178{
179	uint16_t rev = 0;
180	struct rtl8366rb_softc *sc;
181	char name[IFNAMSIZ];
182	int err = 0;
183	int i;
184
185	sc = device_get_softc(dev);
186	bzero(sc, sizeof(*sc));
187	sc->dev = dev;
188	mtx_init(&sc->sc_mtx, "rtl8366rb", NULL, MTX_DEF);
189	sc->smi_acquired = 0;
190	mtx_init(&sc->callout_mtx, "rtl8366rbcallout", NULL, MTX_DEF);
191
192	rtl8366rb_init(dev);
193	smi_read(dev, RTL8366RB_CVCR, &rev, RTL_WAITOK);
194	device_printf(dev, "rev. %d\n", rev & 0x000f);
195
196	/* attach miibus and phys */
197	/* PHYs need an interface, so we generate a dummy one */
198	for (i = 0; i < RTL8366RB_NUM_PHYS; i++) {
199		sc->ifp[i] = if_alloc(IFT_ETHER);
200		sc->ifp[i]->if_softc = sc;
201		sc->ifp[i]->if_flags |= IFF_UP | IFF_BROADCAST | IFF_DRV_RUNNING
202			| IFF_SIMPLEX;
203		snprintf(name, IFNAMSIZ, "%sport", device_get_nameunit(dev));
204		sc->ifname[i] = malloc(strlen(name)+1, M_DEVBUF, M_WAITOK);
205		bcopy(name, sc->ifname[i], strlen(name)+1);
206		if_initname(sc->ifp[i], sc->ifname[i], i);
207		err = mii_attach(dev, &sc->miibus[i], sc->ifp[i], rtl8366rb_ifmedia_upd, \
208			rtl8366rb_ifmedia_sts, BMSR_DEFCAPMASK, \
209			i, MII_OFFSET_ANY, 0);
210		if (err != 0) {
211			device_printf(dev, "attaching PHY %d failed\n", i);
212			return (err);
213		}
214	}
215
216	bus_generic_probe(dev);
217	bus_enumerate_hinted_children(dev);
218	err = bus_generic_attach(dev);
219	if (err != 0)
220		return (err);
221
222	callout_init_mtx(&sc->callout_tick, &sc->callout_mtx, 0);
223	rtl8366rb_tick(sc);
224
225	return (err);
226}
227
228static int
229rtl8366rb_detach(device_t dev)
230{
231	struct rtl8366rb_softc *sc = device_get_softc(dev);
232	int i;
233
234	for (i=0; i < RTL8366RB_NUM_PHYS; i++) {
235		if (sc->miibus[i])
236			device_delete_child(dev, sc->miibus[i]);
237		if (sc->ifp[i] != NULL)
238			if_free(sc->ifp[i]);
239		free(sc->ifname[i], M_DEVBUF);
240	}
241	bus_generic_detach(dev);
242	callout_drain(&sc->callout_tick);
243	mtx_destroy(&sc->callout_mtx);
244	mtx_destroy(&sc->sc_mtx);
245
246	return (0);
247}
248
249static void
250rtl8366rb_update_ifmedia(int portstatus, u_int *media_status, u_int *media_active)
251{
252	*media_active = IFM_ETHER;
253	*media_status = IFM_AVALID;
254	if ((portstatus & RTL8366RB_PLSR_LINK) != 0)
255		*media_status |= IFM_ACTIVE;
256	else {
257		*media_active |= IFM_NONE;
258		return;
259	}
260	switch (portstatus & RTL8366RB_PLSR_SPEED_MASK) {
261	case RTL8366RB_PLSR_SPEED_10:
262		*media_active |= IFM_10_T;
263		break;
264	case RTL8366RB_PLSR_SPEED_100:
265		*media_active |= IFM_100_TX;
266		break;
267	case RTL8366RB_PLSR_SPEED_1000:
268		*media_active |= IFM_1000_T;
269		break;
270	}
271	if ((portstatus & RTL8366RB_PLSR_FULLDUPLEX) == 0)
272		*media_active |= IFM_FDX;
273	else
274		*media_active |= IFM_HDX;
275	if ((portstatus & RTL8366RB_PLSR_TXPAUSE) != 0)
276		*media_active |= IFM_ETH_TXPAUSE;
277	if ((portstatus & RTL8366RB_PLSR_RXPAUSE) != 0)
278		*media_active |= IFM_ETH_RXPAUSE;
279}
280
281static void
282rtl833rb_miipollstat(struct rtl8366rb_softc *sc)
283{
284	int i;
285	struct mii_data *mii;
286	struct mii_softc *miisc;
287	uint16_t value;
288	int portstatus;
289
290	for (i = 0; i < RTL8366RB_NUM_PHYS; i++) {
291		mii = device_get_softc(sc->miibus[i]);
292		if ((i % 2) == 0) {
293			if (smi_read(sc->dev, RTL8366RB_PLSR_BASE + i/2, &value, RTL_NOWAIT) != 0) {
294				DEBUG_INCRVAR(callout_blocked);
295				return;
296			}
297			portstatus = value & 0xff;
298		} else {
299			portstatus = (value >> 8) & 0xff;
300		}
301		rtl8366rb_update_ifmedia(portstatus, &mii->mii_media_status, &mii->mii_media_active);
302		LIST_FOREACH(miisc, &mii->mii_phys, mii_list) {
303			if (IFM_INST(mii->mii_media.ifm_cur->ifm_media) != miisc->mii_inst)
304				continue;
305			mii_phy_update(miisc, MII_POLLSTAT);
306		}
307	}
308}
309
310static void
311rtl8366rb_tick(void *arg)
312{
313	struct rtl8366rb_softc *sc = arg;
314
315	rtl833rb_miipollstat(sc);
316	callout_reset(&sc->callout_tick, hz, rtl8366rb_tick, sc);
317}
318
319static int
320smi_probe(device_t dev)
321{
322	device_t iicbus, iicha;
323	int err, i;
324	uint16_t chipid;
325	char bytes[2];
326	int xferd;
327
328	bytes[0] = RTL8366RB_CIR & 0xff;
329	bytes[1] = (RTL8366RB_CIR >> 8) & 0xff;
330	iicbus = device_get_parent(dev);
331	iicha = device_get_parent(iicbus);
332	iicbus_reset(iicbus, IIC_FASTEST, RTL8366RB_IIC_ADDR, NULL);
333	for (i=3; i--; ) {
334		IICBUS_STOP(iicha);
335		/*
336		 * we go directly to the host adapter because iicbus.c
337		 * only issues a stop on a bus that was successfully started.
338		 */
339	}
340	err = iicbus_request_bus(iicbus, dev, IIC_WAIT);
341	if (err != 0)
342		goto out;
343	err = iicbus_start(iicbus, RTL8366RB_IIC_ADDR | RTL_IICBUS_READ, RTL_IICBUS_TIMEOUT);
344	if (err != 0)
345		goto out;
346	err = iicbus_write(iicbus, bytes, 2, &xferd, RTL_IICBUS_TIMEOUT);
347	if (err != 0)
348		goto out;
349	err = iicbus_read(iicbus, bytes, 2, &xferd, IIC_LAST_READ, 0);
350	if (err != 0)
351		goto out;
352	chipid = ((bytes[1] & 0xff) << 8) | (bytes[0] & 0xff);
353	DPRINTF(dev, "chip id 0x%04x\n", chipid);
354	if (chipid != RTL8366RB_CIR_ID8366RB)
355		err = ENXIO;
356out:
357	iicbus_stop(iicbus);
358	iicbus_release_bus(iicbus, dev);
359	return (err == 0 ? 0 : ENXIO);
360}
361
362static int
363smi_acquire(struct rtl8366rb_softc *sc, int sleep)
364{
365	int r = 0;
366	if (sleep == RTL_WAITOK)
367		RTL_LOCK(sc);
368	else
369		if (RTL_TRYLOCK(sc) == 0)
370			return (EWOULDBLOCK);
371	if (sc->smi_acquired == RTL_SMI_ACQUIRED)
372		r = EBUSY;
373	else {
374		r = iicbus_request_bus(device_get_parent(sc->dev), sc->dev, \
375			sleep == RTL_WAITOK ? IIC_WAIT : IIC_DONTWAIT);
376		if (r == 0)
377			sc->smi_acquired = RTL_SMI_ACQUIRED;
378	}
379	RTL_UNLOCK(sc);
380	return (r);
381}
382
383static int
384smi_release(struct rtl8366rb_softc *sc, int sleep)
385{
386	if (sleep == RTL_WAITOK)
387		RTL_LOCK(sc);
388	else
389		if (RTL_TRYLOCK(sc) == 0)
390			return (EWOULDBLOCK);
391	RTL_SMI_ACQUIRED_ASSERT(sc);
392	iicbus_release_bus(device_get_parent(sc->dev), sc->dev);
393	sc->smi_acquired = 0;
394	RTL_UNLOCK(sc);
395	return (0);
396}
397
398static int
399smi_select(device_t dev, int op, int sleep)
400{
401	int err, i;
402	device_t iicbus = device_get_parent(dev);
403	struct iicbus_ivar *devi = IICBUS_IVAR(dev);
404	int slave = devi->addr;
405
406	RTL_SMI_ACQUIRED_ASSERT((struct rtl8366rb_softc *)device_get_softc(dev));
407	/*
408	 * The chip does not use clock stretching when it is busy,
409	 * instead ignoring the command. Retry a few times.
410	 */
411	for (i = RTL_IICBUS_RETRIES; i--; ) {
412		err = iicbus_start(iicbus, slave | op, RTL_IICBUS_TIMEOUT);
413		if (err != IIC_ENOACK)
414			break;
415		if (sleep == RTL_WAITOK) {
416			DEBUG_INCRVAR(iic_select_retries);
417			pause("smi_select", RTL_IICBUS_RETRY_SLEEP);
418		} else
419			break;
420	}
421	return (err);
422}
423
424static int
425smi_read_locked(struct rtl8366rb_softc *sc, uint16_t addr, uint16_t *data, int sleep)
426{
427	int err;
428	device_t iicbus = device_get_parent(sc->dev);
429	char bytes[2];
430	int xferd;
431
432	RTL_SMI_ACQUIRED_ASSERT(sc);
433	bytes[0] = addr & 0xff;
434	bytes[1] = (addr >> 8) & 0xff;
435	err = smi_select(sc->dev, RTL_IICBUS_READ, sleep);
436	if (err != 0)
437		goto out;
438	err = iicbus_write(iicbus, bytes, 2, &xferd, RTL_IICBUS_TIMEOUT);
439	if (err != 0)
440		goto out;
441	err = iicbus_read(iicbus, bytes, 2, &xferd, IIC_LAST_READ, 0);
442	if (err != 0)
443		goto out;
444	*data = ((bytes[1] & 0xff) << 8) | (bytes[0] & 0xff);
445
446out:
447	iicbus_stop(iicbus);
448	return (err);
449}
450
451static int
452smi_write_locked(struct rtl8366rb_softc *sc, uint16_t addr, uint16_t data, int sleep)
453{
454	int err;
455	device_t iicbus = device_get_parent(sc->dev);
456	char bytes[4];
457	int xferd;
458
459	RTL_SMI_ACQUIRED_ASSERT(sc);
460	bytes[0] = addr & 0xff;
461	bytes[1] = (addr >> 8) & 0xff;
462	bytes[2] = data & 0xff;
463	bytes[3] = (data >> 8) & 0xff;
464
465	err = smi_select(sc->dev, RTL_IICBUS_WRITE, sleep);
466	if (err == 0)
467		err = iicbus_write(iicbus, bytes, 4, &xferd, RTL_IICBUS_TIMEOUT);
468	iicbus_stop(iicbus);
469
470	return (err);
471}
472
473static int
474smi_read(device_t dev, uint16_t addr, uint16_t *data, int sleep)
475{
476	struct rtl8366rb_softc *sc = device_get_softc(dev);
477	int err;
478
479	err = smi_acquire(sc, sleep);
480	if (err != 0)
481		return (EBUSY);
482	err = smi_read_locked(sc, addr, data, sleep);
483	smi_release(sc, sleep);
484	DEVERR(dev, err, "smi_read()=%d: addr=%04x\n", addr);
485	return (err == 0 ? 0 : EIO);
486}
487
488static int
489smi_write(device_t dev, uint16_t addr, uint16_t data, int sleep)
490{
491	struct rtl8366rb_softc *sc = device_get_softc(dev);
492	int err;
493
494	err = smi_acquire(sc, sleep);
495	if (err != 0)
496		return (EBUSY);
497	err = smi_write_locked(sc, addr, data, sleep);
498	smi_release(sc, sleep);
499	DEVERR(dev, err, "smi_write()=%d: addr=%04x\n", addr);
500	return (err == 0 ? 0 : EIO);
501}
502
503static int
504smi_rmw(device_t dev, uint16_t addr, uint16_t mask, uint16_t data, int sleep)
505{
506	struct rtl8366rb_softc *sc = device_get_softc(dev);
507	int err;
508	uint16_t oldv, newv;
509
510	err = smi_acquire(sc, sleep);
511	if (err != 0)
512		return (EBUSY);
513	if (err == 0) {
514		err = smi_read_locked(sc, addr, &oldv, sleep);
515		if (err == 0) {
516			newv = oldv & ~mask;
517			newv |= data & mask;
518			if (newv != oldv)
519				err = smi_write_locked(sc, addr, newv, sleep);
520		}
521	}
522	smi_release(sc, sleep);
523	DEVERR(dev, err, "smi_rmw()=%d: addr=%04x\n", addr);
524	return (err == 0 ? 0 : EIO);
525}
526
527static etherswitch_info_t *
528rtl_getinfo(device_t dev)
529{
530	return (&etherswitch_info);
531}
532
533static int
534rtl_readreg(device_t dev, int reg)
535{
536	uint16_t data = 0;
537
538	smi_read(dev, reg, &data, RTL_WAITOK);
539	return (data);
540}
541
542static int
543rtl_writereg(device_t dev, int reg, int value)
544{
545	return (smi_write(dev, reg, value, RTL_WAITOK));
546}
547
548static int
549rtl_getport(device_t dev, etherswitch_port_t *p)
550{
551	struct rtl8366rb_softc *sc;
552	struct ifmedia *ifm;
553	struct mii_data *mii;
554	struct ifmediareq *ifmr = &p->es_ifmr;
555	uint16_t v;
556	int err, vlangroup;
557
558	if (p->es_port < 0 || p->es_port >= RTL8366RB_NUM_PORTS)
559		return (ENXIO);
560	sc = device_get_softc(dev);
561	vlangroup = RTL8366RB_PVCR_GET(p->es_port,
562		rtl_readreg(dev, RTL8366RB_PVCR_REG(p->es_port)));
563	p->es_pvid = sc->vid[vlangroup];
564
565	if (p->es_port < RTL8366RB_NUM_PHYS) {
566		mii = device_get_softc(sc->miibus[p->es_port]);
567		ifm = &mii->mii_media;
568		err = ifmedia_ioctl(sc->ifp[p->es_port], &p->es_ifr, ifm, SIOCGIFMEDIA);
569		if (err)
570			return (err);
571	} else {
572		/* fill in fixed values for CPU port */
573		p->es_flags |= ETHERSWITCH_PORT_CPU;
574		ifmr->ifm_count = 0;
575		smi_read(dev, RTL8366RB_PLSR_BASE + (RTL8366RB_NUM_PHYS)/2, &v, RTL_WAITOK);
576		v = v >> (8 * ((RTL8366RB_NUM_PHYS) % 2));
577		rtl8366rb_update_ifmedia(v, &ifmr->ifm_status, &ifmr->ifm_active);
578		ifmr->ifm_current = ifmr->ifm_active;
579		ifmr->ifm_mask = 0;
580		ifmr->ifm_status = IFM_ACTIVE | IFM_AVALID;
581	}
582	return (0);
583}
584
585static int
586rtl_setport(device_t dev, etherswitch_port_t *p)
587{
588	int i, err, vlangroup;
589	struct rtl8366rb_softc *sc;
590	struct ifmedia *ifm;
591	struct mii_data *mii;
592
593	if (p->es_port < 0 || p->es_port >= RTL8366RB_NUM_PHYS)
594		return (ENXIO);
595	sc = device_get_softc(dev);
596	vlangroup = -1;
597	for (i = 0; i < RTL8366RB_NUM_VLANS; i++) {
598		if (sc->vid[i] == p->es_pvid) {
599			vlangroup = i;
600			break;
601		}
602	}
603	if (vlangroup == -1)
604		return (ENXIO);
605	err = smi_rmw(dev, RTL8366RB_PVCR_REG(p->es_port),
606		RTL8366RB_PVCR_VAL(p->es_port, RTL8366RB_PVCR_PORT_MASK),
607		RTL8366RB_PVCR_VAL(p->es_port, vlangroup), RTL_WAITOK);
608	if (err)
609		return (err);
610	if (p->es_port == RTL8366RB_CPU_PORT)
611		return (0);
612	mii = device_get_softc(sc->miibus[p->es_port]);
613	ifm = &mii->mii_media;
614	err = ifmedia_ioctl(sc->ifp[p->es_port], &p->es_ifr, ifm, SIOCSIFMEDIA);
615	return (err);
616}
617
618static int
619rtl_getvgroup(device_t dev, etherswitch_vlangroup_t *vg)
620{
621	uint16_t vmcr[3];
622	int i;
623
624	for (i=0; i<3; i++)
625		vmcr[i] = rtl_readreg(dev, RTL8366RB_VMCR(i, vg->es_vlangroup));
626
627	vg->es_vid = RTL8366RB_VMCR_VID(vmcr) | ETHERSWITCH_VID_VALID;
628	vg->es_member_ports = RTL8366RB_VMCR_MEMBER(vmcr);
629	vg->es_untagged_ports = RTL8366RB_VMCR_UNTAG(vmcr);
630	vg->es_fid = RTL8366RB_VMCR_FID(vmcr);
631	return (0);
632}
633
634static int
635rtl_setvgroup(device_t dev, etherswitch_vlangroup_t *vg)
636{
637	struct rtl8366rb_softc *sc;
638	int g = vg->es_vlangroup;
639
640	sc = device_get_softc(dev);
641	sc->vid[g] = vg->es_vid;
642	rtl_writereg(dev, RTL8366RB_VMCR(RTL8366RB_VMCR_DOT1Q_REG, g),
643		(vg->es_vid << RTL8366RB_VMCR_DOT1Q_VID_SHIFT) & RTL8366RB_VMCR_DOT1Q_VID_MASK);
644	rtl_writereg(dev, RTL8366RB_VMCR(RTL8366RB_VMCR_MU_REG, g),
645		((vg->es_member_ports << RTL8366RB_VMCR_MU_MEMBER_SHIFT) & RTL8366RB_VMCR_MU_MEMBER_MASK) |
646		((vg->es_untagged_ports << RTL8366RB_VMCR_MU_UNTAG_SHIFT) & RTL8366RB_VMCR_MU_UNTAG_MASK));
647	rtl_writereg(dev, RTL8366RB_VMCR(RTL8366RB_VMCR_FID_REG, g),
648		vg->es_fid);
649	return (0);
650}
651
652static int
653rtl_readphy(device_t dev, int phy, int reg)
654{
655	struct rtl8366rb_softc *sc = device_get_softc(dev);
656	uint16_t data = 0;
657	int err, i, sleep;
658
659	if (phy < 0 || phy >= RTL8366RB_NUM_PHYS)
660		return (ENXIO);
661	if (reg < 0 || reg >= RTL8366RB_NUM_PHY_REG)
662		return (ENXIO);
663	sleep = RTL_WAITOK;
664	err = smi_acquire(sc, sleep);
665	if (err != 0)
666		return (EBUSY);
667	for (i = RTL_IICBUS_RETRIES; i--; ) {
668		err = smi_write_locked(sc, RTL8366RB_PACR, RTL8366RB_PACR_READ, sleep);
669		if (err == 0)
670			err = smi_write_locked(sc, RTL8366RB_PHYREG(phy, 0, reg), 0, sleep);
671		if (err == 0) {
672			err = smi_read_locked(sc, RTL8366RB_PADR, &data, sleep);
673			break;
674		}
675		DEBUG_INCRVAR(phy_access_retries);
676		DPRINTF(dev, "rtl_readphy(): chip not responsive, retrying %d more times\n", i);
677		pause("rtl_readphy", RTL_IICBUS_RETRY_SLEEP);
678	}
679	smi_release(sc, sleep);
680	DEVERR(dev, err, "rtl_readphy()=%d: phy=%d.%02x\n", phy, reg);
681	return (data);
682}
683
684static int
685rtl_writephy(device_t dev, int phy, int reg, int data)
686{
687	struct rtl8366rb_softc *sc = device_get_softc(dev);
688	int err, i, sleep;
689
690	if (phy < 0 || phy >= RTL8366RB_NUM_PHYS)
691		return (ENXIO);
692	if (reg < 0 || reg >= RTL8366RB_NUM_PHY_REG)
693		return (ENXIO);
694	sleep = RTL_WAITOK;
695	err = smi_acquire(sc, sleep);
696	if (err != 0)
697		return (EBUSY);
698	for (i = RTL_IICBUS_RETRIES; i--; ) {
699		err = smi_write_locked(sc, RTL8366RB_PACR, RTL8366RB_PACR_WRITE, sleep);
700		if (err == 0)
701			err = smi_write_locked(sc, RTL8366RB_PHYREG(phy, 0, reg), data, sleep);
702		if (err == 0) {
703			break;
704		}
705		DEBUG_INCRVAR(phy_access_retries);
706		DPRINTF(dev, "rtl_writephy(): chip not responsive, retrying %d more tiems\n", i);
707		pause("rtl_writephy", RTL_IICBUS_RETRY_SLEEP);
708	}
709	smi_release(sc, sleep);
710	DEVERR(dev, err, "rtl_writephy()=%d: phy=%d.%02x\n", phy, reg);
711	return (err == 0 ? 0 : EIO);
712}
713
714static int
715rtl8366rb_ifmedia_upd(struct ifnet *ifp)
716{
717	struct rtl8366rb_softc *sc = ifp->if_softc;
718	struct mii_data *mii = device_get_softc(sc->miibus[ifp->if_dunit]);
719
720	mii_mediachg(mii);
721	return (0);
722}
723
724static void
725rtl8366rb_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
726{
727	struct rtl8366rb_softc *sc = ifp->if_softc;
728	struct mii_data *mii = device_get_softc(sc->miibus[ifp->if_dunit]);
729
730	mii_pollstat(mii);
731	ifmr->ifm_active = mii->mii_media_active;
732	ifmr->ifm_status = mii->mii_media_status;
733}
734
735
736static device_method_t rtl8366rb_methods[] = {
737	/* Device interface */
738	DEVMETHOD(device_identify,	rtl8366rb_identify),
739	DEVMETHOD(device_probe,		rtl8366rb_probe),
740	DEVMETHOD(device_attach,	rtl8366rb_attach),
741	DEVMETHOD(device_detach,	rtl8366rb_detach),
742
743	/* bus interface */
744	DEVMETHOD(bus_add_child,	device_add_child_ordered),
745
746	/* MII interface */
747	DEVMETHOD(miibus_readreg,	rtl_readphy),
748	DEVMETHOD(miibus_writereg,	rtl_writephy),
749
750	/* etherswitch interface */
751	DEVMETHOD(etherswitch_getinfo,	rtl_getinfo),
752	DEVMETHOD(etherswitch_readreg,	rtl_readreg),
753	DEVMETHOD(etherswitch_writereg,	rtl_writereg),
754	DEVMETHOD(etherswitch_readphyreg,	rtl_readphy),
755	DEVMETHOD(etherswitch_writephyreg,	rtl_writephy),
756	DEVMETHOD(etherswitch_getport,	rtl_getport),
757	DEVMETHOD(etherswitch_setport,	rtl_setport),
758	DEVMETHOD(etherswitch_getvgroup,	rtl_getvgroup),
759	DEVMETHOD(etherswitch_setvgroup,	rtl_setvgroup),
760
761	DEVMETHOD_END
762};
763
764DEFINE_CLASS_0(rtl8366rb, rtl8366rb_driver, rtl8366rb_methods,
765    sizeof(struct rtl8366rb_softc));
766static devclass_t rtl8366rb_devclass;
767
768DRIVER_MODULE(rtl8366rb, iicbus, rtl8366rb_driver, rtl8366rb_devclass, 0, 0);
769DRIVER_MODULE(miibus, rtl8366rb, miibus_driver, miibus_devclass, 0, 0);
770DRIVER_MODULE(etherswitch, rtl8366rb, etherswitch_driver, etherswitch_devclass, 0, 0);
771MODULE_VERSION(rtl8366rb, 1);
772MODULE_DEPEND(rtl8366rb, iicbus, 1, 1, 1); /* XXX which versions? */
773MODULE_DEPEND(rtl8366rb, miibus, 1, 1, 1); /* XXX which versions? */
774MODULE_DEPEND(rtl8366rb, etherswitch, 1, 1, 1); /* XXX which versions? */
775