ip175d.c revision 250386
1214152Sed/*-
2214152Sed * Copyright (c) 2013 Luiz Otavio O Souza.
3214152Sed * Copyright (c) 2011-2012 Stefan Bethke.
4214152Sed * Copyright (c) 2012 Adrian Chadd.
5222656Sed * Copyright (C) 2008 Patrick Horn.
6222656Sed * Copyright (C) 2008, 2010 Martin Mares.
7214152Sed * All rights reserved.
8214152Sed *
9214152Sed * Redistribution and use in source and binary forms, with or without
10214152Sed * modification, are permitted provided that the following conditions
11214152Sed * are met:
12214152Sed * 1. Redistributions of source code must retain the above copyright
13214152Sed *    notice, this list of conditions and the following disclaimer.
14214152Sed * 2. Redistributions in binary form must reproduce the above copyright
15214152Sed *    notice, this list of conditions and the following disclaimer in the
16214152Sed *    documentation and/or other materials provided with the distribution.
17214152Sed *
18214152Sed * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19229135Sed * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20229135Sed * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21229135Sed * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22214152Sed * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23229135Sed * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24214152Sed * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25229135Sed * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26229135Sed * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27229135Sed * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28245642Sandrew * SUCH DAMAGE.
29245642Sandrew *
30245642Sandrew * $FreeBSD: head/sys/dev/etherswitch/ip17x/ip175d.c 250386 2013-05-08 20:58:41Z adrian $
31245642Sandrew */
32245642Sandrew
33245642Sandrew#include <sys/param.h>
34245642Sandrew#include <sys/bus.h>
35245642Sandrew#include <sys/kernel.h>
36245642Sandrew#include <sys/lock.h>
37214152Sed#include <sys/mutex.h>
38229135Sed#include <sys/systm.h>
39229135Sed#include <sys/socket.h>
40214152Sed
41214152Sed#include <net/if.h>
42229135Sed
43229135Sed#include <dev/mii/mii.h>
44229135Sed
45229135Sed#include <dev/etherswitch/etherswitch.h>
46229135Sed#include <dev/etherswitch/ip17x/ip17x_phy.h>
47214152Sed#include <dev/etherswitch/ip17x/ip17x_reg.h>
48229135Sed#include <dev/etherswitch/ip17x/ip17x_var.h>
49229135Sed#include <dev/etherswitch/ip17x/ip17x_vlans.h>
50214152Sed#include <dev/etherswitch/ip17x/ip175d.h>
51229135Sed
52229135Sed/*
53214152Sed * IP175D specific functions.
54230021Sed */
55230021Sed
56230021Sed/*
57230021Sed * Reset the switch to default state.
58230021Sed */
59230021Sedstatic int
60230021Sedip175d_reset(struct ip17x_softc *sc)
61230021Sed{
62230021Sed
63230021Sed	/* Reset all the switch settings. */
64230021Sed	ip17x_writephy(sc->sc_dev, IP175D_RESET_PHY, IP175D_RESET_REG, 0x175d);
65230021Sed	DELAY(2);
66230021Sed
67230021Sed	/* Disable the special tagging mode. */
68230021Sed	ip17x_updatephy(sc->sc_dev, 21, 22, 0x3, 0x0);
69230021Sed
70230021Sed	/* Set 802.1q protocol type. */
71230021Sed	ip17x_writephy(sc->sc_dev, 22, 3, 0x8100);
72230021Sed
73230021Sed	return (0);
74214152Sed}
75
76/*
77 * Set the Switch configuration.
78 */
79static int
80ip175d_hw_setup(struct ip17x_softc *sc)
81{
82	struct ip17x_vlan *v;
83	uint32_t ports[IP17X_MAX_VLANS];
84	uint32_t addtag[IP17X_MAX_VLANS];
85	uint32_t striptag[IP17X_MAX_VLANS];
86	uint32_t vlan_mask;
87	int i, j;
88
89	vlan_mask = 0;
90	for (i = 0; i < IP17X_MAX_VLANS; i++) {
91
92		ports[i] = 0;
93		addtag[i] = 0;
94		striptag[i] = 0;
95
96		v = &sc->vlan[i];
97		if (v->vlanid == 0 || sc->vlan_mode == 0) {
98			/* Vlangroup disabled.  Reset the filter. */
99			ip17x_writephy(sc->sc_dev, 22, 14 + i, i + 1);
100			ports[i] = 0x3f;
101			continue;
102		}
103
104		vlan_mask |= (1 << i);
105		ports[i] = v->ports;
106
107		/* Setup the filter, write the VLAN id. */
108		ip17x_writephy(sc->sc_dev, 22, 14 + i, v->vlanid);
109
110		for (j = 0; j < MII_NPHY; j++) {
111			if ((ports[i] & (1 << j)) == 0)
112				continue;
113			if (sc->addtag & (1 << j))
114				addtag[i] |= (1 << j);
115			if (sc->striptag & (1 << j))
116				striptag[i] |= (1 << j);
117		}
118	}
119
120	/* Write the port masks, tag adds and removals. */
121	for (i = 0; i < IP17X_MAX_VLANS / 2; i++) {
122		ip17x_writephy(sc->sc_dev, 23, i,
123		    ports[2 * i] | (ports[2 * i + 1] << 8));
124		ip17x_writephy(sc->sc_dev, 23, i + 8,
125		    addtag[2 * i] | (addtag[2 * i + 1] << 8));
126		ip17x_writephy(sc->sc_dev, 23, i + 16,
127		    striptag[2 * i] | (striptag[2 * i + 1] << 8));
128	}
129
130	/* Write the in use vlan mask. */
131	ip17x_writephy(sc->sc_dev, 22, 10, vlan_mask);
132
133	/* Write the PVID of each port. */
134	for (i = 0; i < sc->numports; i++)
135		ip17x_writephy(sc->sc_dev, 22, 4 + i, sc->pvid[i]);
136
137	return (0);
138}
139
140/*
141 * Set the switch VLAN mode.
142 */
143static int
144ip175d_set_vlan_mode(struct ip17x_softc *sc, uint32_t mode)
145{
146
147	switch (mode) {
148	case ETHERSWITCH_VLAN_DOT1Q:
149		/*
150		 * VLAN classification rules: tag-based VLANs,
151		 * use VID to classify, drop packets that cannot
152		 * be classified.
153		 */
154		ip17x_updatephy(sc->sc_dev, 22, 0, 0x3fff, 0x003f);
155		sc->vlan_mode = mode;
156		break;
157	case ETHERSWITCH_VLAN_PORT:
158		sc->vlan_mode = mode;
159		/* fallthrough */
160	default:
161		/*
162		 * VLAN classification rules: everything off &
163		 * clear table.
164		 */
165		ip17x_updatephy(sc->sc_dev, 22, 0, 0xbfff, 0x8000);
166		sc->vlan_mode = 0;
167		break;
168	};
169
170	if (sc->vlan_mode != 0) {
171		/*
172		 * Ingress rules: CFI=1 dropped, null VID is untagged, VID=1 passed,
173		 * VID=0xfff discarded, admin both tagged and untagged, ingress
174		 * filters enabled.
175		 */
176		ip17x_updatephy(sc->sc_dev, 22, 1, 0x0fff, 0x0c3f);
177
178		/* Egress rules: IGMP processing off, keep VLAN header off. */
179		ip17x_updatephy(sc->sc_dev, 22, 2, 0x0fff, 0x0000);
180	} else {
181		ip17x_updatephy(sc->sc_dev, 22, 1, 0x0fff, 0x043f);
182		ip17x_updatephy(sc->sc_dev, 22, 2, 0x0fff, 0x0020);
183	}
184
185	/* Reset vlans. */
186	ip17x_reset_vlans(sc, sc->vlan_mode);
187
188	/* Update switch configuration. */
189	ip175d_hw_setup(sc);
190
191	return (0);
192}
193
194/*
195 * Get the switch VLAN mode.
196 */
197static int
198ip175d_get_vlan_mode(struct ip17x_softc *sc)
199{
200
201	return (sc->vlan_mode);
202}
203
204void
205ip175d_attach(struct ip17x_softc *sc)
206{
207
208	sc->hal.ip17x_reset = ip175d_reset;
209	sc->hal.ip17x_hw_setup = ip175d_hw_setup;
210	sc->hal.ip17x_get_vlan_mode = ip175d_get_vlan_mode;
211	sc->hal.ip17x_set_vlan_mode = ip175d_set_vlan_mode;
212
213	/* Defaults for IP175C. */
214	sc->cpuport = IP175X_CPU_PORT;
215	sc->numports = IP175X_NUM_PORTS;
216	sc->info.es_vlan_caps = ETHERSWITCH_VLAN_DOT1Q;
217
218	device_printf(sc->sc_dev, "type: IP175D\n");
219}
220