xref: /openbmc/linux/drivers/net/dsa/sja1105/sja1105_main.c (revision 8aa9ebccae87621d997707e4f25e53fddd7e30e4)
1*8aa9ebccSVladimir Oltean // SPDX-License-Identifier: GPL-2.0
2*8aa9ebccSVladimir Oltean /* Copyright (c) 2018, Sensor-Technik Wiedemann GmbH
3*8aa9ebccSVladimir Oltean  * Copyright (c) 2018-2019, Vladimir Oltean <olteanv@gmail.com>
4*8aa9ebccSVladimir Oltean  */
5*8aa9ebccSVladimir Oltean 
6*8aa9ebccSVladimir Oltean #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
7*8aa9ebccSVladimir Oltean 
8*8aa9ebccSVladimir Oltean #include <linux/delay.h>
9*8aa9ebccSVladimir Oltean #include <linux/module.h>
10*8aa9ebccSVladimir Oltean #include <linux/printk.h>
11*8aa9ebccSVladimir Oltean #include <linux/spi/spi.h>
12*8aa9ebccSVladimir Oltean #include <linux/errno.h>
13*8aa9ebccSVladimir Oltean #include <linux/gpio/consumer.h>
14*8aa9ebccSVladimir Oltean #include <linux/of.h>
15*8aa9ebccSVladimir Oltean #include <linux/of_net.h>
16*8aa9ebccSVladimir Oltean #include <linux/of_mdio.h>
17*8aa9ebccSVladimir Oltean #include <linux/of_device.h>
18*8aa9ebccSVladimir Oltean #include <linux/netdev_features.h>
19*8aa9ebccSVladimir Oltean #include <linux/netdevice.h>
20*8aa9ebccSVladimir Oltean #include <linux/if_bridge.h>
21*8aa9ebccSVladimir Oltean #include <linux/if_ether.h>
22*8aa9ebccSVladimir Oltean #include "sja1105.h"
23*8aa9ebccSVladimir Oltean 
24*8aa9ebccSVladimir Oltean static void sja1105_hw_reset(struct gpio_desc *gpio, unsigned int pulse_len,
25*8aa9ebccSVladimir Oltean 			     unsigned int startup_delay)
26*8aa9ebccSVladimir Oltean {
27*8aa9ebccSVladimir Oltean 	gpiod_set_value_cansleep(gpio, 1);
28*8aa9ebccSVladimir Oltean 	/* Wait for minimum reset pulse length */
29*8aa9ebccSVladimir Oltean 	msleep(pulse_len);
30*8aa9ebccSVladimir Oltean 	gpiod_set_value_cansleep(gpio, 0);
31*8aa9ebccSVladimir Oltean 	/* Wait until chip is ready after reset */
32*8aa9ebccSVladimir Oltean 	msleep(startup_delay);
33*8aa9ebccSVladimir Oltean }
34*8aa9ebccSVladimir Oltean 
35*8aa9ebccSVladimir Oltean static void
36*8aa9ebccSVladimir Oltean sja1105_port_allow_traffic(struct sja1105_l2_forwarding_entry *l2_fwd,
37*8aa9ebccSVladimir Oltean 			   int from, int to, bool allow)
38*8aa9ebccSVladimir Oltean {
39*8aa9ebccSVladimir Oltean 	if (allow) {
40*8aa9ebccSVladimir Oltean 		l2_fwd[from].bc_domain  |= BIT(to);
41*8aa9ebccSVladimir Oltean 		l2_fwd[from].reach_port |= BIT(to);
42*8aa9ebccSVladimir Oltean 		l2_fwd[from].fl_domain  |= BIT(to);
43*8aa9ebccSVladimir Oltean 	} else {
44*8aa9ebccSVladimir Oltean 		l2_fwd[from].bc_domain  &= ~BIT(to);
45*8aa9ebccSVladimir Oltean 		l2_fwd[from].reach_port &= ~BIT(to);
46*8aa9ebccSVladimir Oltean 		l2_fwd[from].fl_domain  &= ~BIT(to);
47*8aa9ebccSVladimir Oltean 	}
48*8aa9ebccSVladimir Oltean }
49*8aa9ebccSVladimir Oltean 
50*8aa9ebccSVladimir Oltean /* Structure used to temporarily transport device tree
51*8aa9ebccSVladimir Oltean  * settings into sja1105_setup
52*8aa9ebccSVladimir Oltean  */
53*8aa9ebccSVladimir Oltean struct sja1105_dt_port {
54*8aa9ebccSVladimir Oltean 	phy_interface_t phy_mode;
55*8aa9ebccSVladimir Oltean 	sja1105_mii_role_t role;
56*8aa9ebccSVladimir Oltean };
57*8aa9ebccSVladimir Oltean 
58*8aa9ebccSVladimir Oltean static int sja1105_init_mac_settings(struct sja1105_private *priv)
59*8aa9ebccSVladimir Oltean {
60*8aa9ebccSVladimir Oltean 	struct sja1105_mac_config_entry default_mac = {
61*8aa9ebccSVladimir Oltean 		/* Enable all 8 priority queues on egress.
62*8aa9ebccSVladimir Oltean 		 * Every queue i holds top[i] - base[i] frames.
63*8aa9ebccSVladimir Oltean 		 * Sum of top[i] - base[i] is 511 (max hardware limit).
64*8aa9ebccSVladimir Oltean 		 */
65*8aa9ebccSVladimir Oltean 		.top  = {0x3F, 0x7F, 0xBF, 0xFF, 0x13F, 0x17F, 0x1BF, 0x1FF},
66*8aa9ebccSVladimir Oltean 		.base = {0x0, 0x40, 0x80, 0xC0, 0x100, 0x140, 0x180, 0x1C0},
67*8aa9ebccSVladimir Oltean 		.enabled = {true, true, true, true, true, true, true, true},
68*8aa9ebccSVladimir Oltean 		/* Keep standard IFG of 12 bytes on egress. */
69*8aa9ebccSVladimir Oltean 		.ifg = 0,
70*8aa9ebccSVladimir Oltean 		/* Always put the MAC speed in automatic mode, where it can be
71*8aa9ebccSVladimir Oltean 		 * retrieved from the PHY object through phylib and
72*8aa9ebccSVladimir Oltean 		 * sja1105_adjust_port_config.
73*8aa9ebccSVladimir Oltean 		 */
74*8aa9ebccSVladimir Oltean 		.speed = SJA1105_SPEED_AUTO,
75*8aa9ebccSVladimir Oltean 		/* No static correction for 1-step 1588 events */
76*8aa9ebccSVladimir Oltean 		.tp_delin = 0,
77*8aa9ebccSVladimir Oltean 		.tp_delout = 0,
78*8aa9ebccSVladimir Oltean 		/* Disable aging for critical TTEthernet traffic */
79*8aa9ebccSVladimir Oltean 		.maxage = 0xFF,
80*8aa9ebccSVladimir Oltean 		/* Internal VLAN (pvid) to apply to untagged ingress */
81*8aa9ebccSVladimir Oltean 		.vlanprio = 0,
82*8aa9ebccSVladimir Oltean 		.vlanid = 0,
83*8aa9ebccSVladimir Oltean 		.ing_mirr = false,
84*8aa9ebccSVladimir Oltean 		.egr_mirr = false,
85*8aa9ebccSVladimir Oltean 		/* Don't drop traffic with other EtherType than ETH_P_IP */
86*8aa9ebccSVladimir Oltean 		.drpnona664 = false,
87*8aa9ebccSVladimir Oltean 		/* Don't drop double-tagged traffic */
88*8aa9ebccSVladimir Oltean 		.drpdtag = false,
89*8aa9ebccSVladimir Oltean 		/* Don't drop untagged traffic */
90*8aa9ebccSVladimir Oltean 		.drpuntag = false,
91*8aa9ebccSVladimir Oltean 		/* Don't retag 802.1p (VID 0) traffic with the pvid */
92*8aa9ebccSVladimir Oltean 		.retag = false,
93*8aa9ebccSVladimir Oltean 		/* Enable learning and I/O on user ports by default. */
94*8aa9ebccSVladimir Oltean 		.dyn_learn = true,
95*8aa9ebccSVladimir Oltean 		.egress = false,
96*8aa9ebccSVladimir Oltean 		.ingress = false,
97*8aa9ebccSVladimir Oltean 	};
98*8aa9ebccSVladimir Oltean 	struct sja1105_mac_config_entry *mac;
99*8aa9ebccSVladimir Oltean 	struct sja1105_table *table;
100*8aa9ebccSVladimir Oltean 	int i;
101*8aa9ebccSVladimir Oltean 
102*8aa9ebccSVladimir Oltean 	table = &priv->static_config.tables[BLK_IDX_MAC_CONFIG];
103*8aa9ebccSVladimir Oltean 
104*8aa9ebccSVladimir Oltean 	/* Discard previous MAC Configuration Table */
105*8aa9ebccSVladimir Oltean 	if (table->entry_count) {
106*8aa9ebccSVladimir Oltean 		kfree(table->entries);
107*8aa9ebccSVladimir Oltean 		table->entry_count = 0;
108*8aa9ebccSVladimir Oltean 	}
109*8aa9ebccSVladimir Oltean 
110*8aa9ebccSVladimir Oltean 	table->entries = kcalloc(SJA1105_NUM_PORTS,
111*8aa9ebccSVladimir Oltean 				 table->ops->unpacked_entry_size, GFP_KERNEL);
112*8aa9ebccSVladimir Oltean 	if (!table->entries)
113*8aa9ebccSVladimir Oltean 		return -ENOMEM;
114*8aa9ebccSVladimir Oltean 
115*8aa9ebccSVladimir Oltean 	/* Override table based on phylib DT bindings */
116*8aa9ebccSVladimir Oltean 	table->entry_count = SJA1105_NUM_PORTS;
117*8aa9ebccSVladimir Oltean 
118*8aa9ebccSVladimir Oltean 	mac = table->entries;
119*8aa9ebccSVladimir Oltean 
120*8aa9ebccSVladimir Oltean 	for (i = 0; i < SJA1105_NUM_PORTS; i++)
121*8aa9ebccSVladimir Oltean 		mac[i] = default_mac;
122*8aa9ebccSVladimir Oltean 
123*8aa9ebccSVladimir Oltean 	return 0;
124*8aa9ebccSVladimir Oltean }
125*8aa9ebccSVladimir Oltean 
126*8aa9ebccSVladimir Oltean static int sja1105_init_mii_settings(struct sja1105_private *priv,
127*8aa9ebccSVladimir Oltean 				     struct sja1105_dt_port *ports)
128*8aa9ebccSVladimir Oltean {
129*8aa9ebccSVladimir Oltean 	struct device *dev = &priv->spidev->dev;
130*8aa9ebccSVladimir Oltean 	struct sja1105_xmii_params_entry *mii;
131*8aa9ebccSVladimir Oltean 	struct sja1105_table *table;
132*8aa9ebccSVladimir Oltean 	int i;
133*8aa9ebccSVladimir Oltean 
134*8aa9ebccSVladimir Oltean 	table = &priv->static_config.tables[BLK_IDX_XMII_PARAMS];
135*8aa9ebccSVladimir Oltean 
136*8aa9ebccSVladimir Oltean 	/* Discard previous xMII Mode Parameters Table */
137*8aa9ebccSVladimir Oltean 	if (table->entry_count) {
138*8aa9ebccSVladimir Oltean 		kfree(table->entries);
139*8aa9ebccSVladimir Oltean 		table->entry_count = 0;
140*8aa9ebccSVladimir Oltean 	}
141*8aa9ebccSVladimir Oltean 
142*8aa9ebccSVladimir Oltean 	table->entries = kcalloc(SJA1105_MAX_XMII_PARAMS_COUNT,
143*8aa9ebccSVladimir Oltean 				 table->ops->unpacked_entry_size, GFP_KERNEL);
144*8aa9ebccSVladimir Oltean 	if (!table->entries)
145*8aa9ebccSVladimir Oltean 		return -ENOMEM;
146*8aa9ebccSVladimir Oltean 
147*8aa9ebccSVladimir Oltean 	/* Override table based on phylib DT bindings */
148*8aa9ebccSVladimir Oltean 	table->entry_count = SJA1105_MAX_XMII_PARAMS_COUNT;
149*8aa9ebccSVladimir Oltean 
150*8aa9ebccSVladimir Oltean 	mii = table->entries;
151*8aa9ebccSVladimir Oltean 
152*8aa9ebccSVladimir Oltean 	for (i = 0; i < SJA1105_NUM_PORTS; i++) {
153*8aa9ebccSVladimir Oltean 		switch (ports[i].phy_mode) {
154*8aa9ebccSVladimir Oltean 		case PHY_INTERFACE_MODE_MII:
155*8aa9ebccSVladimir Oltean 			mii->xmii_mode[i] = XMII_MODE_MII;
156*8aa9ebccSVladimir Oltean 			break;
157*8aa9ebccSVladimir Oltean 		case PHY_INTERFACE_MODE_RMII:
158*8aa9ebccSVladimir Oltean 			mii->xmii_mode[i] = XMII_MODE_RMII;
159*8aa9ebccSVladimir Oltean 			break;
160*8aa9ebccSVladimir Oltean 		case PHY_INTERFACE_MODE_RGMII:
161*8aa9ebccSVladimir Oltean 		case PHY_INTERFACE_MODE_RGMII_ID:
162*8aa9ebccSVladimir Oltean 		case PHY_INTERFACE_MODE_RGMII_RXID:
163*8aa9ebccSVladimir Oltean 		case PHY_INTERFACE_MODE_RGMII_TXID:
164*8aa9ebccSVladimir Oltean 			mii->xmii_mode[i] = XMII_MODE_RGMII;
165*8aa9ebccSVladimir Oltean 			break;
166*8aa9ebccSVladimir Oltean 		default:
167*8aa9ebccSVladimir Oltean 			dev_err(dev, "Unsupported PHY mode %s!\n",
168*8aa9ebccSVladimir Oltean 				phy_modes(ports[i].phy_mode));
169*8aa9ebccSVladimir Oltean 		}
170*8aa9ebccSVladimir Oltean 
171*8aa9ebccSVladimir Oltean 		mii->phy_mac[i] = ports[i].role;
172*8aa9ebccSVladimir Oltean 	}
173*8aa9ebccSVladimir Oltean 	return 0;
174*8aa9ebccSVladimir Oltean }
175*8aa9ebccSVladimir Oltean 
176*8aa9ebccSVladimir Oltean static int sja1105_init_static_fdb(struct sja1105_private *priv)
177*8aa9ebccSVladimir Oltean {
178*8aa9ebccSVladimir Oltean 	struct sja1105_table *table;
179*8aa9ebccSVladimir Oltean 
180*8aa9ebccSVladimir Oltean 	table = &priv->static_config.tables[BLK_IDX_L2_LOOKUP];
181*8aa9ebccSVladimir Oltean 
182*8aa9ebccSVladimir Oltean 	if (table->entry_count) {
183*8aa9ebccSVladimir Oltean 		kfree(table->entries);
184*8aa9ebccSVladimir Oltean 		table->entry_count = 0;
185*8aa9ebccSVladimir Oltean 	}
186*8aa9ebccSVladimir Oltean 	return 0;
187*8aa9ebccSVladimir Oltean }
188*8aa9ebccSVladimir Oltean 
189*8aa9ebccSVladimir Oltean static int sja1105_init_l2_lookup_params(struct sja1105_private *priv)
190*8aa9ebccSVladimir Oltean {
191*8aa9ebccSVladimir Oltean 	struct sja1105_table *table;
192*8aa9ebccSVladimir Oltean 	struct sja1105_l2_lookup_params_entry default_l2_lookup_params = {
193*8aa9ebccSVladimir Oltean 		/* TODO Learned FDB entries are never forgotten */
194*8aa9ebccSVladimir Oltean 		.maxage = 0,
195*8aa9ebccSVladimir Oltean 		/* All entries within a FDB bin are available for learning */
196*8aa9ebccSVladimir Oltean 		.dyn_tbsz = SJA1105ET_FDB_BIN_SIZE,
197*8aa9ebccSVladimir Oltean 		/* 2^8 + 2^5 + 2^3 + 2^2 + 2^1 + 1 in Koopman notation */
198*8aa9ebccSVladimir Oltean 		.poly = 0x97,
199*8aa9ebccSVladimir Oltean 		/* This selects between Independent VLAN Learning (IVL) and
200*8aa9ebccSVladimir Oltean 		 * Shared VLAN Learning (SVL)
201*8aa9ebccSVladimir Oltean 		 */
202*8aa9ebccSVladimir Oltean 		.shared_learn = false,
203*8aa9ebccSVladimir Oltean 		/* Don't discard management traffic based on ENFPORT -
204*8aa9ebccSVladimir Oltean 		 * we don't perform SMAC port enforcement anyway, so
205*8aa9ebccSVladimir Oltean 		 * what we are setting here doesn't matter.
206*8aa9ebccSVladimir Oltean 		 */
207*8aa9ebccSVladimir Oltean 		.no_enf_hostprt = false,
208*8aa9ebccSVladimir Oltean 		/* Don't learn SMAC for mac_fltres1 and mac_fltres0.
209*8aa9ebccSVladimir Oltean 		 * Maybe correlate with no_linklocal_learn from bridge driver?
210*8aa9ebccSVladimir Oltean 		 */
211*8aa9ebccSVladimir Oltean 		.no_mgmt_learn = true,
212*8aa9ebccSVladimir Oltean 	};
213*8aa9ebccSVladimir Oltean 
214*8aa9ebccSVladimir Oltean 	table = &priv->static_config.tables[BLK_IDX_L2_LOOKUP_PARAMS];
215*8aa9ebccSVladimir Oltean 
216*8aa9ebccSVladimir Oltean 	if (table->entry_count) {
217*8aa9ebccSVladimir Oltean 		kfree(table->entries);
218*8aa9ebccSVladimir Oltean 		table->entry_count = 0;
219*8aa9ebccSVladimir Oltean 	}
220*8aa9ebccSVladimir Oltean 
221*8aa9ebccSVladimir Oltean 	table->entries = kcalloc(SJA1105_MAX_L2_LOOKUP_PARAMS_COUNT,
222*8aa9ebccSVladimir Oltean 				 table->ops->unpacked_entry_size, GFP_KERNEL);
223*8aa9ebccSVladimir Oltean 	if (!table->entries)
224*8aa9ebccSVladimir Oltean 		return -ENOMEM;
225*8aa9ebccSVladimir Oltean 
226*8aa9ebccSVladimir Oltean 	table->entry_count = SJA1105_MAX_L2_LOOKUP_PARAMS_COUNT;
227*8aa9ebccSVladimir Oltean 
228*8aa9ebccSVladimir Oltean 	/* This table only has a single entry */
229*8aa9ebccSVladimir Oltean 	((struct sja1105_l2_lookup_params_entry *)table->entries)[0] =
230*8aa9ebccSVladimir Oltean 				default_l2_lookup_params;
231*8aa9ebccSVladimir Oltean 
232*8aa9ebccSVladimir Oltean 	return 0;
233*8aa9ebccSVladimir Oltean }
234*8aa9ebccSVladimir Oltean 
235*8aa9ebccSVladimir Oltean static int sja1105_init_static_vlan(struct sja1105_private *priv)
236*8aa9ebccSVladimir Oltean {
237*8aa9ebccSVladimir Oltean 	struct sja1105_table *table;
238*8aa9ebccSVladimir Oltean 	struct sja1105_vlan_lookup_entry pvid = {
239*8aa9ebccSVladimir Oltean 		.ving_mirr = 0,
240*8aa9ebccSVladimir Oltean 		.vegr_mirr = 0,
241*8aa9ebccSVladimir Oltean 		.vmemb_port = 0,
242*8aa9ebccSVladimir Oltean 		.vlan_bc = 0,
243*8aa9ebccSVladimir Oltean 		.tag_port = 0,
244*8aa9ebccSVladimir Oltean 		.vlanid = 0,
245*8aa9ebccSVladimir Oltean 	};
246*8aa9ebccSVladimir Oltean 	int i;
247*8aa9ebccSVladimir Oltean 
248*8aa9ebccSVladimir Oltean 	table = &priv->static_config.tables[BLK_IDX_VLAN_LOOKUP];
249*8aa9ebccSVladimir Oltean 
250*8aa9ebccSVladimir Oltean 	/* The static VLAN table will only contain the initial pvid of 0.
251*8aa9ebccSVladimir Oltean 	 */
252*8aa9ebccSVladimir Oltean 	if (table->entry_count) {
253*8aa9ebccSVladimir Oltean 		kfree(table->entries);
254*8aa9ebccSVladimir Oltean 		table->entry_count = 0;
255*8aa9ebccSVladimir Oltean 	}
256*8aa9ebccSVladimir Oltean 
257*8aa9ebccSVladimir Oltean 	table->entries = kcalloc(1, table->ops->unpacked_entry_size,
258*8aa9ebccSVladimir Oltean 				 GFP_KERNEL);
259*8aa9ebccSVladimir Oltean 	if (!table->entries)
260*8aa9ebccSVladimir Oltean 		return -ENOMEM;
261*8aa9ebccSVladimir Oltean 
262*8aa9ebccSVladimir Oltean 	table->entry_count = 1;
263*8aa9ebccSVladimir Oltean 
264*8aa9ebccSVladimir Oltean 	/* VLAN ID 0: all DT-defined ports are members; no restrictions on
265*8aa9ebccSVladimir Oltean 	 * forwarding; always transmit priority-tagged frames as untagged.
266*8aa9ebccSVladimir Oltean 	 */
267*8aa9ebccSVladimir Oltean 	for (i = 0; i < SJA1105_NUM_PORTS; i++) {
268*8aa9ebccSVladimir Oltean 		pvid.vmemb_port |= BIT(i);
269*8aa9ebccSVladimir Oltean 		pvid.vlan_bc |= BIT(i);
270*8aa9ebccSVladimir Oltean 		pvid.tag_port &= ~BIT(i);
271*8aa9ebccSVladimir Oltean 	}
272*8aa9ebccSVladimir Oltean 
273*8aa9ebccSVladimir Oltean 	((struct sja1105_vlan_lookup_entry *)table->entries)[0] = pvid;
274*8aa9ebccSVladimir Oltean 	return 0;
275*8aa9ebccSVladimir Oltean }
276*8aa9ebccSVladimir Oltean 
277*8aa9ebccSVladimir Oltean static int sja1105_init_l2_forwarding(struct sja1105_private *priv)
278*8aa9ebccSVladimir Oltean {
279*8aa9ebccSVladimir Oltean 	struct sja1105_l2_forwarding_entry *l2fwd;
280*8aa9ebccSVladimir Oltean 	struct sja1105_table *table;
281*8aa9ebccSVladimir Oltean 	int i, j;
282*8aa9ebccSVladimir Oltean 
283*8aa9ebccSVladimir Oltean 	table = &priv->static_config.tables[BLK_IDX_L2_FORWARDING];
284*8aa9ebccSVladimir Oltean 
285*8aa9ebccSVladimir Oltean 	if (table->entry_count) {
286*8aa9ebccSVladimir Oltean 		kfree(table->entries);
287*8aa9ebccSVladimir Oltean 		table->entry_count = 0;
288*8aa9ebccSVladimir Oltean 	}
289*8aa9ebccSVladimir Oltean 
290*8aa9ebccSVladimir Oltean 	table->entries = kcalloc(SJA1105_MAX_L2_FORWARDING_COUNT,
291*8aa9ebccSVladimir Oltean 				 table->ops->unpacked_entry_size, GFP_KERNEL);
292*8aa9ebccSVladimir Oltean 	if (!table->entries)
293*8aa9ebccSVladimir Oltean 		return -ENOMEM;
294*8aa9ebccSVladimir Oltean 
295*8aa9ebccSVladimir Oltean 	table->entry_count = SJA1105_MAX_L2_FORWARDING_COUNT;
296*8aa9ebccSVladimir Oltean 
297*8aa9ebccSVladimir Oltean 	l2fwd = table->entries;
298*8aa9ebccSVladimir Oltean 
299*8aa9ebccSVladimir Oltean 	/* First 5 entries define the forwarding rules */
300*8aa9ebccSVladimir Oltean 	for (i = 0; i < SJA1105_NUM_PORTS; i++) {
301*8aa9ebccSVladimir Oltean 		unsigned int upstream = dsa_upstream_port(priv->ds, i);
302*8aa9ebccSVladimir Oltean 
303*8aa9ebccSVladimir Oltean 		for (j = 0; j < SJA1105_NUM_TC; j++)
304*8aa9ebccSVladimir Oltean 			l2fwd[i].vlan_pmap[j] = j;
305*8aa9ebccSVladimir Oltean 
306*8aa9ebccSVladimir Oltean 		if (i == upstream)
307*8aa9ebccSVladimir Oltean 			continue;
308*8aa9ebccSVladimir Oltean 
309*8aa9ebccSVladimir Oltean 		sja1105_port_allow_traffic(l2fwd, i, upstream, true);
310*8aa9ebccSVladimir Oltean 		sja1105_port_allow_traffic(l2fwd, upstream, i, true);
311*8aa9ebccSVladimir Oltean 	}
312*8aa9ebccSVladimir Oltean 	/* Next 8 entries define VLAN PCP mapping from ingress to egress.
313*8aa9ebccSVladimir Oltean 	 * Create a one-to-one mapping.
314*8aa9ebccSVladimir Oltean 	 */
315*8aa9ebccSVladimir Oltean 	for (i = 0; i < SJA1105_NUM_TC; i++)
316*8aa9ebccSVladimir Oltean 		for (j = 0; j < SJA1105_NUM_PORTS; j++)
317*8aa9ebccSVladimir Oltean 			l2fwd[SJA1105_NUM_PORTS + i].vlan_pmap[j] = i;
318*8aa9ebccSVladimir Oltean 
319*8aa9ebccSVladimir Oltean 	return 0;
320*8aa9ebccSVladimir Oltean }
321*8aa9ebccSVladimir Oltean 
322*8aa9ebccSVladimir Oltean static int sja1105_init_l2_forwarding_params(struct sja1105_private *priv)
323*8aa9ebccSVladimir Oltean {
324*8aa9ebccSVladimir Oltean 	struct sja1105_l2_forwarding_params_entry default_l2fwd_params = {
325*8aa9ebccSVladimir Oltean 		/* Disallow dynamic reconfiguration of vlan_pmap */
326*8aa9ebccSVladimir Oltean 		.max_dynp = 0,
327*8aa9ebccSVladimir Oltean 		/* Use a single memory partition for all ingress queues */
328*8aa9ebccSVladimir Oltean 		.part_spc = { SJA1105_MAX_FRAME_MEMORY, 0, 0, 0, 0, 0, 0, 0 },
329*8aa9ebccSVladimir Oltean 	};
330*8aa9ebccSVladimir Oltean 	struct sja1105_table *table;
331*8aa9ebccSVladimir Oltean 
332*8aa9ebccSVladimir Oltean 	table = &priv->static_config.tables[BLK_IDX_L2_FORWARDING_PARAMS];
333*8aa9ebccSVladimir Oltean 
334*8aa9ebccSVladimir Oltean 	if (table->entry_count) {
335*8aa9ebccSVladimir Oltean 		kfree(table->entries);
336*8aa9ebccSVladimir Oltean 		table->entry_count = 0;
337*8aa9ebccSVladimir Oltean 	}
338*8aa9ebccSVladimir Oltean 
339*8aa9ebccSVladimir Oltean 	table->entries = kcalloc(SJA1105_MAX_L2_FORWARDING_PARAMS_COUNT,
340*8aa9ebccSVladimir Oltean 				 table->ops->unpacked_entry_size, GFP_KERNEL);
341*8aa9ebccSVladimir Oltean 	if (!table->entries)
342*8aa9ebccSVladimir Oltean 		return -ENOMEM;
343*8aa9ebccSVladimir Oltean 
344*8aa9ebccSVladimir Oltean 	table->entry_count = SJA1105_MAX_L2_FORWARDING_PARAMS_COUNT;
345*8aa9ebccSVladimir Oltean 
346*8aa9ebccSVladimir Oltean 	/* This table only has a single entry */
347*8aa9ebccSVladimir Oltean 	((struct sja1105_l2_forwarding_params_entry *)table->entries)[0] =
348*8aa9ebccSVladimir Oltean 				default_l2fwd_params;
349*8aa9ebccSVladimir Oltean 
350*8aa9ebccSVladimir Oltean 	return 0;
351*8aa9ebccSVladimir Oltean }
352*8aa9ebccSVladimir Oltean 
353*8aa9ebccSVladimir Oltean static int sja1105_init_general_params(struct sja1105_private *priv)
354*8aa9ebccSVladimir Oltean {
355*8aa9ebccSVladimir Oltean 	struct sja1105_general_params_entry default_general_params = {
356*8aa9ebccSVladimir Oltean 		/* Disallow dynamic changing of the mirror port */
357*8aa9ebccSVladimir Oltean 		.mirr_ptacu = 0,
358*8aa9ebccSVladimir Oltean 		.switchid = priv->ds->index,
359*8aa9ebccSVladimir Oltean 		/* Priority queue for link-local frames trapped to CPU */
360*8aa9ebccSVladimir Oltean 		.hostprio = 0,
361*8aa9ebccSVladimir Oltean 		.mac_fltres1 = SJA1105_LINKLOCAL_FILTER_A,
362*8aa9ebccSVladimir Oltean 		.mac_flt1    = SJA1105_LINKLOCAL_FILTER_A_MASK,
363*8aa9ebccSVladimir Oltean 		.incl_srcpt1 = true,
364*8aa9ebccSVladimir Oltean 		.send_meta1  = false,
365*8aa9ebccSVladimir Oltean 		.mac_fltres0 = SJA1105_LINKLOCAL_FILTER_B,
366*8aa9ebccSVladimir Oltean 		.mac_flt0    = SJA1105_LINKLOCAL_FILTER_B_MASK,
367*8aa9ebccSVladimir Oltean 		.incl_srcpt0 = true,
368*8aa9ebccSVladimir Oltean 		.send_meta0  = false,
369*8aa9ebccSVladimir Oltean 		/* The destination for traffic matching mac_fltres1 and
370*8aa9ebccSVladimir Oltean 		 * mac_fltres0 on all ports except host_port. Such traffic
371*8aa9ebccSVladimir Oltean 		 * receieved on host_port itself would be dropped, except
372*8aa9ebccSVladimir Oltean 		 * by installing a temporary 'management route'
373*8aa9ebccSVladimir Oltean 		 */
374*8aa9ebccSVladimir Oltean 		.host_port = dsa_upstream_port(priv->ds, 0),
375*8aa9ebccSVladimir Oltean 		/* Same as host port */
376*8aa9ebccSVladimir Oltean 		.mirr_port = dsa_upstream_port(priv->ds, 0),
377*8aa9ebccSVladimir Oltean 		/* Link-local traffic received on casc_port will be forwarded
378*8aa9ebccSVladimir Oltean 		 * to host_port without embedding the source port and device ID
379*8aa9ebccSVladimir Oltean 		 * info in the destination MAC address (presumably because it
380*8aa9ebccSVladimir Oltean 		 * is a cascaded port and a downstream SJA switch already did
381*8aa9ebccSVladimir Oltean 		 * that). Default to an invalid port (to disable the feature)
382*8aa9ebccSVladimir Oltean 		 * and overwrite this if we find any DSA (cascaded) ports.
383*8aa9ebccSVladimir Oltean 		 */
384*8aa9ebccSVladimir Oltean 		.casc_port = SJA1105_NUM_PORTS,
385*8aa9ebccSVladimir Oltean 		/* No TTEthernet */
386*8aa9ebccSVladimir Oltean 		.vllupformat = 0,
387*8aa9ebccSVladimir Oltean 		.vlmarker = 0,
388*8aa9ebccSVladimir Oltean 		.vlmask = 0,
389*8aa9ebccSVladimir Oltean 		/* Only update correctionField for 1-step PTP (L2 transport) */
390*8aa9ebccSVladimir Oltean 		.ignore2stf = 0,
391*8aa9ebccSVladimir Oltean 		.tpid = ETH_P_8021Q,
392*8aa9ebccSVladimir Oltean 		.tpid2 = ETH_P_8021Q,
393*8aa9ebccSVladimir Oltean 	};
394*8aa9ebccSVladimir Oltean 	struct sja1105_table *table;
395*8aa9ebccSVladimir Oltean 	int i;
396*8aa9ebccSVladimir Oltean 
397*8aa9ebccSVladimir Oltean 	for (i = 0; i < SJA1105_NUM_PORTS; i++)
398*8aa9ebccSVladimir Oltean 		if (dsa_is_dsa_port(priv->ds, i))
399*8aa9ebccSVladimir Oltean 			default_general_params.casc_port = i;
400*8aa9ebccSVladimir Oltean 
401*8aa9ebccSVladimir Oltean 	table = &priv->static_config.tables[BLK_IDX_GENERAL_PARAMS];
402*8aa9ebccSVladimir Oltean 
403*8aa9ebccSVladimir Oltean 	if (table->entry_count) {
404*8aa9ebccSVladimir Oltean 		kfree(table->entries);
405*8aa9ebccSVladimir Oltean 		table->entry_count = 0;
406*8aa9ebccSVladimir Oltean 	}
407*8aa9ebccSVladimir Oltean 
408*8aa9ebccSVladimir Oltean 	table->entries = kcalloc(SJA1105_MAX_GENERAL_PARAMS_COUNT,
409*8aa9ebccSVladimir Oltean 				 table->ops->unpacked_entry_size, GFP_KERNEL);
410*8aa9ebccSVladimir Oltean 	if (!table->entries)
411*8aa9ebccSVladimir Oltean 		return -ENOMEM;
412*8aa9ebccSVladimir Oltean 
413*8aa9ebccSVladimir Oltean 	table->entry_count = SJA1105_MAX_GENERAL_PARAMS_COUNT;
414*8aa9ebccSVladimir Oltean 
415*8aa9ebccSVladimir Oltean 	/* This table only has a single entry */
416*8aa9ebccSVladimir Oltean 	((struct sja1105_general_params_entry *)table->entries)[0] =
417*8aa9ebccSVladimir Oltean 				default_general_params;
418*8aa9ebccSVladimir Oltean 
419*8aa9ebccSVladimir Oltean 	return 0;
420*8aa9ebccSVladimir Oltean }
421*8aa9ebccSVladimir Oltean 
422*8aa9ebccSVladimir Oltean #define SJA1105_RATE_MBPS(speed) (((speed) * 64000) / 1000)
423*8aa9ebccSVladimir Oltean 
424*8aa9ebccSVladimir Oltean static inline void
425*8aa9ebccSVladimir Oltean sja1105_setup_policer(struct sja1105_l2_policing_entry *policing,
426*8aa9ebccSVladimir Oltean 		      int index)
427*8aa9ebccSVladimir Oltean {
428*8aa9ebccSVladimir Oltean 	policing[index].sharindx = index;
429*8aa9ebccSVladimir Oltean 	policing[index].smax = 65535; /* Burst size in bytes */
430*8aa9ebccSVladimir Oltean 	policing[index].rate = SJA1105_RATE_MBPS(1000);
431*8aa9ebccSVladimir Oltean 	policing[index].maxlen = ETH_FRAME_LEN + VLAN_HLEN + ETH_FCS_LEN;
432*8aa9ebccSVladimir Oltean 	policing[index].partition = 0;
433*8aa9ebccSVladimir Oltean }
434*8aa9ebccSVladimir Oltean 
435*8aa9ebccSVladimir Oltean static int sja1105_init_l2_policing(struct sja1105_private *priv)
436*8aa9ebccSVladimir Oltean {
437*8aa9ebccSVladimir Oltean 	struct sja1105_l2_policing_entry *policing;
438*8aa9ebccSVladimir Oltean 	struct sja1105_table *table;
439*8aa9ebccSVladimir Oltean 	int i, j, k;
440*8aa9ebccSVladimir Oltean 
441*8aa9ebccSVladimir Oltean 	table = &priv->static_config.tables[BLK_IDX_L2_POLICING];
442*8aa9ebccSVladimir Oltean 
443*8aa9ebccSVladimir Oltean 	/* Discard previous L2 Policing Table */
444*8aa9ebccSVladimir Oltean 	if (table->entry_count) {
445*8aa9ebccSVladimir Oltean 		kfree(table->entries);
446*8aa9ebccSVladimir Oltean 		table->entry_count = 0;
447*8aa9ebccSVladimir Oltean 	}
448*8aa9ebccSVladimir Oltean 
449*8aa9ebccSVladimir Oltean 	table->entries = kcalloc(SJA1105_MAX_L2_POLICING_COUNT,
450*8aa9ebccSVladimir Oltean 				 table->ops->unpacked_entry_size, GFP_KERNEL);
451*8aa9ebccSVladimir Oltean 	if (!table->entries)
452*8aa9ebccSVladimir Oltean 		return -ENOMEM;
453*8aa9ebccSVladimir Oltean 
454*8aa9ebccSVladimir Oltean 	table->entry_count = SJA1105_MAX_L2_POLICING_COUNT;
455*8aa9ebccSVladimir Oltean 
456*8aa9ebccSVladimir Oltean 	policing = table->entries;
457*8aa9ebccSVladimir Oltean 
458*8aa9ebccSVladimir Oltean 	/* k sweeps through all unicast policers (0-39).
459*8aa9ebccSVladimir Oltean 	 * bcast sweeps through policers 40-44.
460*8aa9ebccSVladimir Oltean 	 */
461*8aa9ebccSVladimir Oltean 	for (i = 0, k = 0; i < SJA1105_NUM_PORTS; i++) {
462*8aa9ebccSVladimir Oltean 		int bcast = (SJA1105_NUM_PORTS * SJA1105_NUM_TC) + i;
463*8aa9ebccSVladimir Oltean 
464*8aa9ebccSVladimir Oltean 		for (j = 0; j < SJA1105_NUM_TC; j++, k++)
465*8aa9ebccSVladimir Oltean 			sja1105_setup_policer(policing, k);
466*8aa9ebccSVladimir Oltean 
467*8aa9ebccSVladimir Oltean 		/* Set up this port's policer for broadcast traffic */
468*8aa9ebccSVladimir Oltean 		sja1105_setup_policer(policing, bcast);
469*8aa9ebccSVladimir Oltean 	}
470*8aa9ebccSVladimir Oltean 	return 0;
471*8aa9ebccSVladimir Oltean }
472*8aa9ebccSVladimir Oltean 
473*8aa9ebccSVladimir Oltean static int sja1105_static_config_load(struct sja1105_private *priv,
474*8aa9ebccSVladimir Oltean 				      struct sja1105_dt_port *ports)
475*8aa9ebccSVladimir Oltean {
476*8aa9ebccSVladimir Oltean 	int rc;
477*8aa9ebccSVladimir Oltean 
478*8aa9ebccSVladimir Oltean 	sja1105_static_config_free(&priv->static_config);
479*8aa9ebccSVladimir Oltean 	rc = sja1105_static_config_init(&priv->static_config,
480*8aa9ebccSVladimir Oltean 					priv->info->static_ops,
481*8aa9ebccSVladimir Oltean 					priv->info->device_id);
482*8aa9ebccSVladimir Oltean 	if (rc)
483*8aa9ebccSVladimir Oltean 		return rc;
484*8aa9ebccSVladimir Oltean 
485*8aa9ebccSVladimir Oltean 	/* Build static configuration */
486*8aa9ebccSVladimir Oltean 	rc = sja1105_init_mac_settings(priv);
487*8aa9ebccSVladimir Oltean 	if (rc < 0)
488*8aa9ebccSVladimir Oltean 		return rc;
489*8aa9ebccSVladimir Oltean 	rc = sja1105_init_mii_settings(priv, ports);
490*8aa9ebccSVladimir Oltean 	if (rc < 0)
491*8aa9ebccSVladimir Oltean 		return rc;
492*8aa9ebccSVladimir Oltean 	rc = sja1105_init_static_fdb(priv);
493*8aa9ebccSVladimir Oltean 	if (rc < 0)
494*8aa9ebccSVladimir Oltean 		return rc;
495*8aa9ebccSVladimir Oltean 	rc = sja1105_init_static_vlan(priv);
496*8aa9ebccSVladimir Oltean 	if (rc < 0)
497*8aa9ebccSVladimir Oltean 		return rc;
498*8aa9ebccSVladimir Oltean 	rc = sja1105_init_l2_lookup_params(priv);
499*8aa9ebccSVladimir Oltean 	if (rc < 0)
500*8aa9ebccSVladimir Oltean 		return rc;
501*8aa9ebccSVladimir Oltean 	rc = sja1105_init_l2_forwarding(priv);
502*8aa9ebccSVladimir Oltean 	if (rc < 0)
503*8aa9ebccSVladimir Oltean 		return rc;
504*8aa9ebccSVladimir Oltean 	rc = sja1105_init_l2_forwarding_params(priv);
505*8aa9ebccSVladimir Oltean 	if (rc < 0)
506*8aa9ebccSVladimir Oltean 		return rc;
507*8aa9ebccSVladimir Oltean 	rc = sja1105_init_l2_policing(priv);
508*8aa9ebccSVladimir Oltean 	if (rc < 0)
509*8aa9ebccSVladimir Oltean 		return rc;
510*8aa9ebccSVladimir Oltean 	rc = sja1105_init_general_params(priv);
511*8aa9ebccSVladimir Oltean 	if (rc < 0)
512*8aa9ebccSVladimir Oltean 		return rc;
513*8aa9ebccSVladimir Oltean 
514*8aa9ebccSVladimir Oltean 	/* Send initial configuration to hardware via SPI */
515*8aa9ebccSVladimir Oltean 	return sja1105_static_config_upload(priv);
516*8aa9ebccSVladimir Oltean }
517*8aa9ebccSVladimir Oltean 
518*8aa9ebccSVladimir Oltean static int sja1105_parse_ports_node(struct sja1105_private *priv,
519*8aa9ebccSVladimir Oltean 				    struct sja1105_dt_port *ports,
520*8aa9ebccSVladimir Oltean 				    struct device_node *ports_node)
521*8aa9ebccSVladimir Oltean {
522*8aa9ebccSVladimir Oltean 	struct device *dev = &priv->spidev->dev;
523*8aa9ebccSVladimir Oltean 	struct device_node *child;
524*8aa9ebccSVladimir Oltean 
525*8aa9ebccSVladimir Oltean 	for_each_child_of_node(ports_node, child) {
526*8aa9ebccSVladimir Oltean 		struct device_node *phy_node;
527*8aa9ebccSVladimir Oltean 		int phy_mode;
528*8aa9ebccSVladimir Oltean 		u32 index;
529*8aa9ebccSVladimir Oltean 
530*8aa9ebccSVladimir Oltean 		/* Get switch port number from DT */
531*8aa9ebccSVladimir Oltean 		if (of_property_read_u32(child, "reg", &index) < 0) {
532*8aa9ebccSVladimir Oltean 			dev_err(dev, "Port number not defined in device tree "
533*8aa9ebccSVladimir Oltean 				"(property \"reg\")\n");
534*8aa9ebccSVladimir Oltean 			return -ENODEV;
535*8aa9ebccSVladimir Oltean 		}
536*8aa9ebccSVladimir Oltean 
537*8aa9ebccSVladimir Oltean 		/* Get PHY mode from DT */
538*8aa9ebccSVladimir Oltean 		phy_mode = of_get_phy_mode(child);
539*8aa9ebccSVladimir Oltean 		if (phy_mode < 0) {
540*8aa9ebccSVladimir Oltean 			dev_err(dev, "Failed to read phy-mode or "
541*8aa9ebccSVladimir Oltean 				"phy-interface-type property for port %d\n",
542*8aa9ebccSVladimir Oltean 				index);
543*8aa9ebccSVladimir Oltean 			return -ENODEV;
544*8aa9ebccSVladimir Oltean 		}
545*8aa9ebccSVladimir Oltean 		ports[index].phy_mode = phy_mode;
546*8aa9ebccSVladimir Oltean 
547*8aa9ebccSVladimir Oltean 		phy_node = of_parse_phandle(child, "phy-handle", 0);
548*8aa9ebccSVladimir Oltean 		if (!phy_node) {
549*8aa9ebccSVladimir Oltean 			if (!of_phy_is_fixed_link(child)) {
550*8aa9ebccSVladimir Oltean 				dev_err(dev, "phy-handle or fixed-link "
551*8aa9ebccSVladimir Oltean 					"properties missing!\n");
552*8aa9ebccSVladimir Oltean 				return -ENODEV;
553*8aa9ebccSVladimir Oltean 			}
554*8aa9ebccSVladimir Oltean 			/* phy-handle is missing, but fixed-link isn't.
555*8aa9ebccSVladimir Oltean 			 * So it's a fixed link. Default to PHY role.
556*8aa9ebccSVladimir Oltean 			 */
557*8aa9ebccSVladimir Oltean 			ports[index].role = XMII_PHY;
558*8aa9ebccSVladimir Oltean 		} else {
559*8aa9ebccSVladimir Oltean 			/* phy-handle present => put port in MAC role */
560*8aa9ebccSVladimir Oltean 			ports[index].role = XMII_MAC;
561*8aa9ebccSVladimir Oltean 			of_node_put(phy_node);
562*8aa9ebccSVladimir Oltean 		}
563*8aa9ebccSVladimir Oltean 
564*8aa9ebccSVladimir Oltean 		/* The MAC/PHY role can be overridden with explicit bindings */
565*8aa9ebccSVladimir Oltean 		if (of_property_read_bool(child, "sja1105,role-mac"))
566*8aa9ebccSVladimir Oltean 			ports[index].role = XMII_MAC;
567*8aa9ebccSVladimir Oltean 		else if (of_property_read_bool(child, "sja1105,role-phy"))
568*8aa9ebccSVladimir Oltean 			ports[index].role = XMII_PHY;
569*8aa9ebccSVladimir Oltean 	}
570*8aa9ebccSVladimir Oltean 
571*8aa9ebccSVladimir Oltean 	return 0;
572*8aa9ebccSVladimir Oltean }
573*8aa9ebccSVladimir Oltean 
574*8aa9ebccSVladimir Oltean static int sja1105_parse_dt(struct sja1105_private *priv,
575*8aa9ebccSVladimir Oltean 			    struct sja1105_dt_port *ports)
576*8aa9ebccSVladimir Oltean {
577*8aa9ebccSVladimir Oltean 	struct device *dev = &priv->spidev->dev;
578*8aa9ebccSVladimir Oltean 	struct device_node *switch_node = dev->of_node;
579*8aa9ebccSVladimir Oltean 	struct device_node *ports_node;
580*8aa9ebccSVladimir Oltean 	int rc;
581*8aa9ebccSVladimir Oltean 
582*8aa9ebccSVladimir Oltean 	ports_node = of_get_child_by_name(switch_node, "ports");
583*8aa9ebccSVladimir Oltean 	if (!ports_node) {
584*8aa9ebccSVladimir Oltean 		dev_err(dev, "Incorrect bindings: absent \"ports\" node\n");
585*8aa9ebccSVladimir Oltean 		return -ENODEV;
586*8aa9ebccSVladimir Oltean 	}
587*8aa9ebccSVladimir Oltean 
588*8aa9ebccSVladimir Oltean 	rc = sja1105_parse_ports_node(priv, ports, ports_node);
589*8aa9ebccSVladimir Oltean 	of_node_put(ports_node);
590*8aa9ebccSVladimir Oltean 
591*8aa9ebccSVladimir Oltean 	return rc;
592*8aa9ebccSVladimir Oltean }
593*8aa9ebccSVladimir Oltean 
594*8aa9ebccSVladimir Oltean /* Convert back and forth MAC speed from Mbps to SJA1105 encoding */
595*8aa9ebccSVladimir Oltean static int sja1105_speed[] = {
596*8aa9ebccSVladimir Oltean 	[SJA1105_SPEED_AUTO]     = 0,
597*8aa9ebccSVladimir Oltean 	[SJA1105_SPEED_10MBPS]   = 10,
598*8aa9ebccSVladimir Oltean 	[SJA1105_SPEED_100MBPS]  = 100,
599*8aa9ebccSVladimir Oltean 	[SJA1105_SPEED_1000MBPS] = 1000,
600*8aa9ebccSVladimir Oltean };
601*8aa9ebccSVladimir Oltean 
602*8aa9ebccSVladimir Oltean static sja1105_speed_t sja1105_get_speed_cfg(unsigned int speed_mbps)
603*8aa9ebccSVladimir Oltean {
604*8aa9ebccSVladimir Oltean 	int i;
605*8aa9ebccSVladimir Oltean 
606*8aa9ebccSVladimir Oltean 	for (i = SJA1105_SPEED_AUTO; i <= SJA1105_SPEED_1000MBPS; i++)
607*8aa9ebccSVladimir Oltean 		if (sja1105_speed[i] == speed_mbps)
608*8aa9ebccSVladimir Oltean 			return i;
609*8aa9ebccSVladimir Oltean 	return -EINVAL;
610*8aa9ebccSVladimir Oltean }
611*8aa9ebccSVladimir Oltean 
612*8aa9ebccSVladimir Oltean /* Set link speed and enable/disable traffic I/O in the MAC configuration
613*8aa9ebccSVladimir Oltean  * for a specific port.
614*8aa9ebccSVladimir Oltean  *
615*8aa9ebccSVladimir Oltean  * @speed_mbps: If 0, leave the speed unchanged, else adapt MAC to PHY speed.
616*8aa9ebccSVladimir Oltean  * @enabled: Manage Rx and Tx settings for this port. Overrides the static
617*8aa9ebccSVladimir Oltean  *	     configuration settings.
618*8aa9ebccSVladimir Oltean  */
619*8aa9ebccSVladimir Oltean static int sja1105_adjust_port_config(struct sja1105_private *priv, int port,
620*8aa9ebccSVladimir Oltean 				      int speed_mbps, bool enabled)
621*8aa9ebccSVladimir Oltean {
622*8aa9ebccSVladimir Oltean 	struct sja1105_xmii_params_entry *mii;
623*8aa9ebccSVladimir Oltean 	struct sja1105_mac_config_entry *mac;
624*8aa9ebccSVladimir Oltean 	struct device *dev = priv->ds->dev;
625*8aa9ebccSVladimir Oltean 	sja1105_phy_interface_t phy_mode;
626*8aa9ebccSVladimir Oltean 	sja1105_speed_t speed;
627*8aa9ebccSVladimir Oltean 	int rc;
628*8aa9ebccSVladimir Oltean 
629*8aa9ebccSVladimir Oltean 	mii = priv->static_config.tables[BLK_IDX_XMII_PARAMS].entries;
630*8aa9ebccSVladimir Oltean 	mac = priv->static_config.tables[BLK_IDX_MAC_CONFIG].entries;
631*8aa9ebccSVladimir Oltean 
632*8aa9ebccSVladimir Oltean 	speed = sja1105_get_speed_cfg(speed_mbps);
633*8aa9ebccSVladimir Oltean 	if (speed_mbps && speed < 0) {
634*8aa9ebccSVladimir Oltean 		dev_err(dev, "Invalid speed %iMbps\n", speed_mbps);
635*8aa9ebccSVladimir Oltean 		return -EINVAL;
636*8aa9ebccSVladimir Oltean 	}
637*8aa9ebccSVladimir Oltean 
638*8aa9ebccSVladimir Oltean 	/* If requested, overwrite SJA1105_SPEED_AUTO from the static MAC
639*8aa9ebccSVladimir Oltean 	 * configuration table, since this will be used for the clocking setup,
640*8aa9ebccSVladimir Oltean 	 * and we no longer need to store it in the static config (already told
641*8aa9ebccSVladimir Oltean 	 * hardware we want auto during upload phase).
642*8aa9ebccSVladimir Oltean 	 */
643*8aa9ebccSVladimir Oltean 	if (speed_mbps)
644*8aa9ebccSVladimir Oltean 		mac[port].speed = speed;
645*8aa9ebccSVladimir Oltean 	else
646*8aa9ebccSVladimir Oltean 		mac[port].speed = SJA1105_SPEED_AUTO;
647*8aa9ebccSVladimir Oltean 
648*8aa9ebccSVladimir Oltean 	/* On P/Q/R/S, one can read from the device via the MAC reconfiguration
649*8aa9ebccSVladimir Oltean 	 * tables. On E/T, MAC reconfig tables are not readable, only writable.
650*8aa9ebccSVladimir Oltean 	 * We have to *know* what the MAC looks like.  For the sake of keeping
651*8aa9ebccSVladimir Oltean 	 * the code common, we'll use the static configuration tables as a
652*8aa9ebccSVladimir Oltean 	 * reasonable approximation for both E/T and P/Q/R/S.
653*8aa9ebccSVladimir Oltean 	 */
654*8aa9ebccSVladimir Oltean 	mac[port].ingress = enabled;
655*8aa9ebccSVladimir Oltean 	mac[port].egress  = enabled;
656*8aa9ebccSVladimir Oltean 
657*8aa9ebccSVladimir Oltean 	/* Write to the dynamic reconfiguration tables */
658*8aa9ebccSVladimir Oltean 	rc = sja1105_dynamic_config_write(priv, BLK_IDX_MAC_CONFIG,
659*8aa9ebccSVladimir Oltean 					  port, &mac[port], true);
660*8aa9ebccSVladimir Oltean 	if (rc < 0) {
661*8aa9ebccSVladimir Oltean 		dev_err(dev, "Failed to write MAC config: %d\n", rc);
662*8aa9ebccSVladimir Oltean 		return rc;
663*8aa9ebccSVladimir Oltean 	}
664*8aa9ebccSVladimir Oltean 
665*8aa9ebccSVladimir Oltean 	/* Reconfigure the PLLs for the RGMII interfaces (required 125 MHz at
666*8aa9ebccSVladimir Oltean 	 * gigabit, 25 MHz at 100 Mbps and 2.5 MHz at 10 Mbps). For MII and
667*8aa9ebccSVladimir Oltean 	 * RMII no change of the clock setup is required. Actually, changing
668*8aa9ebccSVladimir Oltean 	 * the clock setup does interrupt the clock signal for a certain time
669*8aa9ebccSVladimir Oltean 	 * which causes trouble for all PHYs relying on this signal.
670*8aa9ebccSVladimir Oltean 	 */
671*8aa9ebccSVladimir Oltean 	if (!enabled)
672*8aa9ebccSVladimir Oltean 		return 0;
673*8aa9ebccSVladimir Oltean 
674*8aa9ebccSVladimir Oltean 	phy_mode = mii->xmii_mode[port];
675*8aa9ebccSVladimir Oltean 	if (phy_mode != XMII_MODE_RGMII)
676*8aa9ebccSVladimir Oltean 		return 0;
677*8aa9ebccSVladimir Oltean 
678*8aa9ebccSVladimir Oltean 	return sja1105_clocking_setup_port(priv, port);
679*8aa9ebccSVladimir Oltean }
680*8aa9ebccSVladimir Oltean 
681*8aa9ebccSVladimir Oltean static void sja1105_adjust_link(struct dsa_switch *ds, int port,
682*8aa9ebccSVladimir Oltean 				struct phy_device *phydev)
683*8aa9ebccSVladimir Oltean {
684*8aa9ebccSVladimir Oltean 	struct sja1105_private *priv = ds->priv;
685*8aa9ebccSVladimir Oltean 
686*8aa9ebccSVladimir Oltean 	if (!phydev->link)
687*8aa9ebccSVladimir Oltean 		sja1105_adjust_port_config(priv, port, 0, false);
688*8aa9ebccSVladimir Oltean 	else
689*8aa9ebccSVladimir Oltean 		sja1105_adjust_port_config(priv, port, phydev->speed, true);
690*8aa9ebccSVladimir Oltean }
691*8aa9ebccSVladimir Oltean 
692*8aa9ebccSVladimir Oltean static int sja1105_bridge_member(struct dsa_switch *ds, int port,
693*8aa9ebccSVladimir Oltean 				 struct net_device *br, bool member)
694*8aa9ebccSVladimir Oltean {
695*8aa9ebccSVladimir Oltean 	struct sja1105_l2_forwarding_entry *l2_fwd;
696*8aa9ebccSVladimir Oltean 	struct sja1105_private *priv = ds->priv;
697*8aa9ebccSVladimir Oltean 	int i, rc;
698*8aa9ebccSVladimir Oltean 
699*8aa9ebccSVladimir Oltean 	l2_fwd = priv->static_config.tables[BLK_IDX_L2_FORWARDING].entries;
700*8aa9ebccSVladimir Oltean 
701*8aa9ebccSVladimir Oltean 	for (i = 0; i < SJA1105_NUM_PORTS; i++) {
702*8aa9ebccSVladimir Oltean 		/* Add this port to the forwarding matrix of the
703*8aa9ebccSVladimir Oltean 		 * other ports in the same bridge, and viceversa.
704*8aa9ebccSVladimir Oltean 		 */
705*8aa9ebccSVladimir Oltean 		if (!dsa_is_user_port(ds, i))
706*8aa9ebccSVladimir Oltean 			continue;
707*8aa9ebccSVladimir Oltean 		/* For the ports already under the bridge, only one thing needs
708*8aa9ebccSVladimir Oltean 		 * to be done, and that is to add this port to their
709*8aa9ebccSVladimir Oltean 		 * reachability domain. So we can perform the SPI write for
710*8aa9ebccSVladimir Oltean 		 * them immediately. However, for this port itself (the one
711*8aa9ebccSVladimir Oltean 		 * that is new to the bridge), we need to add all other ports
712*8aa9ebccSVladimir Oltean 		 * to its reachability domain. So we do that incrementally in
713*8aa9ebccSVladimir Oltean 		 * this loop, and perform the SPI write only at the end, once
714*8aa9ebccSVladimir Oltean 		 * the domain contains all other bridge ports.
715*8aa9ebccSVladimir Oltean 		 */
716*8aa9ebccSVladimir Oltean 		if (i == port)
717*8aa9ebccSVladimir Oltean 			continue;
718*8aa9ebccSVladimir Oltean 		if (dsa_to_port(ds, i)->bridge_dev != br)
719*8aa9ebccSVladimir Oltean 			continue;
720*8aa9ebccSVladimir Oltean 		sja1105_port_allow_traffic(l2_fwd, i, port, member);
721*8aa9ebccSVladimir Oltean 		sja1105_port_allow_traffic(l2_fwd, port, i, member);
722*8aa9ebccSVladimir Oltean 
723*8aa9ebccSVladimir Oltean 		rc = sja1105_dynamic_config_write(priv, BLK_IDX_L2_FORWARDING,
724*8aa9ebccSVladimir Oltean 						  i, &l2_fwd[i], true);
725*8aa9ebccSVladimir Oltean 		if (rc < 0)
726*8aa9ebccSVladimir Oltean 			return rc;
727*8aa9ebccSVladimir Oltean 	}
728*8aa9ebccSVladimir Oltean 
729*8aa9ebccSVladimir Oltean 	return sja1105_dynamic_config_write(priv, BLK_IDX_L2_FORWARDING,
730*8aa9ebccSVladimir Oltean 					    port, &l2_fwd[port], true);
731*8aa9ebccSVladimir Oltean }
732*8aa9ebccSVladimir Oltean 
733*8aa9ebccSVladimir Oltean static int sja1105_bridge_join(struct dsa_switch *ds, int port,
734*8aa9ebccSVladimir Oltean 			       struct net_device *br)
735*8aa9ebccSVladimir Oltean {
736*8aa9ebccSVladimir Oltean 	return sja1105_bridge_member(ds, port, br, true);
737*8aa9ebccSVladimir Oltean }
738*8aa9ebccSVladimir Oltean 
739*8aa9ebccSVladimir Oltean static void sja1105_bridge_leave(struct dsa_switch *ds, int port,
740*8aa9ebccSVladimir Oltean 				 struct net_device *br)
741*8aa9ebccSVladimir Oltean {
742*8aa9ebccSVladimir Oltean 	sja1105_bridge_member(ds, port, br, false);
743*8aa9ebccSVladimir Oltean }
744*8aa9ebccSVladimir Oltean 
745*8aa9ebccSVladimir Oltean static enum dsa_tag_protocol
746*8aa9ebccSVladimir Oltean sja1105_get_tag_protocol(struct dsa_switch *ds, int port)
747*8aa9ebccSVladimir Oltean {
748*8aa9ebccSVladimir Oltean 	return DSA_TAG_PROTO_NONE;
749*8aa9ebccSVladimir Oltean }
750*8aa9ebccSVladimir Oltean 
751*8aa9ebccSVladimir Oltean /* The programming model for the SJA1105 switch is "all-at-once" via static
752*8aa9ebccSVladimir Oltean  * configuration tables. Some of these can be dynamically modified at runtime,
753*8aa9ebccSVladimir Oltean  * but not the xMII mode parameters table.
754*8aa9ebccSVladimir Oltean  * Furthermode, some PHYs may not have crystals for generating their clocks
755*8aa9ebccSVladimir Oltean  * (e.g. RMII). Instead, their 50MHz clock is supplied via the SJA1105 port's
756*8aa9ebccSVladimir Oltean  * ref_clk pin. So port clocking needs to be initialized early, before
757*8aa9ebccSVladimir Oltean  * connecting to PHYs is attempted, otherwise they won't respond through MDIO.
758*8aa9ebccSVladimir Oltean  * Setting correct PHY link speed does not matter now.
759*8aa9ebccSVladimir Oltean  * But dsa_slave_phy_setup is called later than sja1105_setup, so the PHY
760*8aa9ebccSVladimir Oltean  * bindings are not yet parsed by DSA core. We need to parse early so that we
761*8aa9ebccSVladimir Oltean  * can populate the xMII mode parameters table.
762*8aa9ebccSVladimir Oltean  */
763*8aa9ebccSVladimir Oltean static int sja1105_setup(struct dsa_switch *ds)
764*8aa9ebccSVladimir Oltean {
765*8aa9ebccSVladimir Oltean 	struct sja1105_dt_port ports[SJA1105_NUM_PORTS];
766*8aa9ebccSVladimir Oltean 	struct sja1105_private *priv = ds->priv;
767*8aa9ebccSVladimir Oltean 	int rc;
768*8aa9ebccSVladimir Oltean 
769*8aa9ebccSVladimir Oltean 	rc = sja1105_parse_dt(priv, ports);
770*8aa9ebccSVladimir Oltean 	if (rc < 0) {
771*8aa9ebccSVladimir Oltean 		dev_err(ds->dev, "Failed to parse DT: %d\n", rc);
772*8aa9ebccSVladimir Oltean 		return rc;
773*8aa9ebccSVladimir Oltean 	}
774*8aa9ebccSVladimir Oltean 	/* Create and send configuration down to device */
775*8aa9ebccSVladimir Oltean 	rc = sja1105_static_config_load(priv, ports);
776*8aa9ebccSVladimir Oltean 	if (rc < 0) {
777*8aa9ebccSVladimir Oltean 		dev_err(ds->dev, "Failed to load static config: %d\n", rc);
778*8aa9ebccSVladimir Oltean 		return rc;
779*8aa9ebccSVladimir Oltean 	}
780*8aa9ebccSVladimir Oltean 	/* Configure the CGU (PHY link modes and speeds) */
781*8aa9ebccSVladimir Oltean 	rc = sja1105_clocking_setup(priv);
782*8aa9ebccSVladimir Oltean 	if (rc < 0) {
783*8aa9ebccSVladimir Oltean 		dev_err(ds->dev, "Failed to configure MII clocking: %d\n", rc);
784*8aa9ebccSVladimir Oltean 		return rc;
785*8aa9ebccSVladimir Oltean 	}
786*8aa9ebccSVladimir Oltean 
787*8aa9ebccSVladimir Oltean 	return 0;
788*8aa9ebccSVladimir Oltean }
789*8aa9ebccSVladimir Oltean 
790*8aa9ebccSVladimir Oltean static const struct dsa_switch_ops sja1105_switch_ops = {
791*8aa9ebccSVladimir Oltean 	.get_tag_protocol	= sja1105_get_tag_protocol,
792*8aa9ebccSVladimir Oltean 	.setup			= sja1105_setup,
793*8aa9ebccSVladimir Oltean 	.adjust_link		= sja1105_adjust_link,
794*8aa9ebccSVladimir Oltean 	.port_bridge_join	= sja1105_bridge_join,
795*8aa9ebccSVladimir Oltean 	.port_bridge_leave	= sja1105_bridge_leave,
796*8aa9ebccSVladimir Oltean };
797*8aa9ebccSVladimir Oltean 
798*8aa9ebccSVladimir Oltean static int sja1105_check_device_id(struct sja1105_private *priv)
799*8aa9ebccSVladimir Oltean {
800*8aa9ebccSVladimir Oltean 	const struct sja1105_regs *regs = priv->info->regs;
801*8aa9ebccSVladimir Oltean 	u8 prod_id[SJA1105_SIZE_DEVICE_ID] = {0};
802*8aa9ebccSVladimir Oltean 	struct device *dev = &priv->spidev->dev;
803*8aa9ebccSVladimir Oltean 	u64 device_id;
804*8aa9ebccSVladimir Oltean 	u64 part_no;
805*8aa9ebccSVladimir Oltean 	int rc;
806*8aa9ebccSVladimir Oltean 
807*8aa9ebccSVladimir Oltean 	rc = sja1105_spi_send_int(priv, SPI_READ, regs->device_id,
808*8aa9ebccSVladimir Oltean 				  &device_id, SJA1105_SIZE_DEVICE_ID);
809*8aa9ebccSVladimir Oltean 	if (rc < 0)
810*8aa9ebccSVladimir Oltean 		return rc;
811*8aa9ebccSVladimir Oltean 
812*8aa9ebccSVladimir Oltean 	if (device_id != priv->info->device_id) {
813*8aa9ebccSVladimir Oltean 		dev_err(dev, "Expected device ID 0x%llx but read 0x%llx\n",
814*8aa9ebccSVladimir Oltean 			priv->info->device_id, device_id);
815*8aa9ebccSVladimir Oltean 		return -ENODEV;
816*8aa9ebccSVladimir Oltean 	}
817*8aa9ebccSVladimir Oltean 
818*8aa9ebccSVladimir Oltean 	rc = sja1105_spi_send_packed_buf(priv, SPI_READ, regs->prod_id,
819*8aa9ebccSVladimir Oltean 					 prod_id, SJA1105_SIZE_DEVICE_ID);
820*8aa9ebccSVladimir Oltean 	if (rc < 0)
821*8aa9ebccSVladimir Oltean 		return rc;
822*8aa9ebccSVladimir Oltean 
823*8aa9ebccSVladimir Oltean 	sja1105_unpack(prod_id, &part_no, 19, 4, SJA1105_SIZE_DEVICE_ID);
824*8aa9ebccSVladimir Oltean 
825*8aa9ebccSVladimir Oltean 	if (part_no != priv->info->part_no) {
826*8aa9ebccSVladimir Oltean 		dev_err(dev, "Expected part number 0x%llx but read 0x%llx\n",
827*8aa9ebccSVladimir Oltean 			priv->info->part_no, part_no);
828*8aa9ebccSVladimir Oltean 		return -ENODEV;
829*8aa9ebccSVladimir Oltean 	}
830*8aa9ebccSVladimir Oltean 
831*8aa9ebccSVladimir Oltean 	return 0;
832*8aa9ebccSVladimir Oltean }
833*8aa9ebccSVladimir Oltean 
834*8aa9ebccSVladimir Oltean static int sja1105_probe(struct spi_device *spi)
835*8aa9ebccSVladimir Oltean {
836*8aa9ebccSVladimir Oltean 	struct device *dev = &spi->dev;
837*8aa9ebccSVladimir Oltean 	struct sja1105_private *priv;
838*8aa9ebccSVladimir Oltean 	struct dsa_switch *ds;
839*8aa9ebccSVladimir Oltean 	int rc;
840*8aa9ebccSVladimir Oltean 
841*8aa9ebccSVladimir Oltean 	if (!dev->of_node) {
842*8aa9ebccSVladimir Oltean 		dev_err(dev, "No DTS bindings for SJA1105 driver\n");
843*8aa9ebccSVladimir Oltean 		return -EINVAL;
844*8aa9ebccSVladimir Oltean 	}
845*8aa9ebccSVladimir Oltean 
846*8aa9ebccSVladimir Oltean 	priv = devm_kzalloc(dev, sizeof(struct sja1105_private), GFP_KERNEL);
847*8aa9ebccSVladimir Oltean 	if (!priv)
848*8aa9ebccSVladimir Oltean 		return -ENOMEM;
849*8aa9ebccSVladimir Oltean 
850*8aa9ebccSVladimir Oltean 	/* Configure the optional reset pin and bring up switch */
851*8aa9ebccSVladimir Oltean 	priv->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
852*8aa9ebccSVladimir Oltean 	if (IS_ERR(priv->reset_gpio))
853*8aa9ebccSVladimir Oltean 		dev_dbg(dev, "reset-gpios not defined, ignoring\n");
854*8aa9ebccSVladimir Oltean 	else
855*8aa9ebccSVladimir Oltean 		sja1105_hw_reset(priv->reset_gpio, 1, 1);
856*8aa9ebccSVladimir Oltean 
857*8aa9ebccSVladimir Oltean 	/* Populate our driver private structure (priv) based on
858*8aa9ebccSVladimir Oltean 	 * the device tree node that was probed (spi)
859*8aa9ebccSVladimir Oltean 	 */
860*8aa9ebccSVladimir Oltean 	priv->spidev = spi;
861*8aa9ebccSVladimir Oltean 	spi_set_drvdata(spi, priv);
862*8aa9ebccSVladimir Oltean 
863*8aa9ebccSVladimir Oltean 	/* Configure the SPI bus */
864*8aa9ebccSVladimir Oltean 	spi->bits_per_word = 8;
865*8aa9ebccSVladimir Oltean 	rc = spi_setup(spi);
866*8aa9ebccSVladimir Oltean 	if (rc < 0) {
867*8aa9ebccSVladimir Oltean 		dev_err(dev, "Could not init SPI\n");
868*8aa9ebccSVladimir Oltean 		return rc;
869*8aa9ebccSVladimir Oltean 	}
870*8aa9ebccSVladimir Oltean 
871*8aa9ebccSVladimir Oltean 	priv->info = of_device_get_match_data(dev);
872*8aa9ebccSVladimir Oltean 
873*8aa9ebccSVladimir Oltean 	/* Detect hardware device */
874*8aa9ebccSVladimir Oltean 	rc = sja1105_check_device_id(priv);
875*8aa9ebccSVladimir Oltean 	if (rc < 0) {
876*8aa9ebccSVladimir Oltean 		dev_err(dev, "Device ID check failed: %d\n", rc);
877*8aa9ebccSVladimir Oltean 		return rc;
878*8aa9ebccSVladimir Oltean 	}
879*8aa9ebccSVladimir Oltean 
880*8aa9ebccSVladimir Oltean 	dev_info(dev, "Probed switch chip: %s\n", priv->info->name);
881*8aa9ebccSVladimir Oltean 
882*8aa9ebccSVladimir Oltean 	ds = dsa_switch_alloc(dev, SJA1105_NUM_PORTS);
883*8aa9ebccSVladimir Oltean 	if (!ds)
884*8aa9ebccSVladimir Oltean 		return -ENOMEM;
885*8aa9ebccSVladimir Oltean 
886*8aa9ebccSVladimir Oltean 	ds->ops = &sja1105_switch_ops;
887*8aa9ebccSVladimir Oltean 	ds->priv = priv;
888*8aa9ebccSVladimir Oltean 	priv->ds = ds;
889*8aa9ebccSVladimir Oltean 
890*8aa9ebccSVladimir Oltean 	return dsa_register_switch(priv->ds);
891*8aa9ebccSVladimir Oltean }
892*8aa9ebccSVladimir Oltean 
893*8aa9ebccSVladimir Oltean static int sja1105_remove(struct spi_device *spi)
894*8aa9ebccSVladimir Oltean {
895*8aa9ebccSVladimir Oltean 	struct sja1105_private *priv = spi_get_drvdata(spi);
896*8aa9ebccSVladimir Oltean 
897*8aa9ebccSVladimir Oltean 	dsa_unregister_switch(priv->ds);
898*8aa9ebccSVladimir Oltean 	sja1105_static_config_free(&priv->static_config);
899*8aa9ebccSVladimir Oltean 	return 0;
900*8aa9ebccSVladimir Oltean }
901*8aa9ebccSVladimir Oltean 
902*8aa9ebccSVladimir Oltean static const struct of_device_id sja1105_dt_ids[] = {
903*8aa9ebccSVladimir Oltean 	{ .compatible = "nxp,sja1105e", .data = &sja1105e_info },
904*8aa9ebccSVladimir Oltean 	{ .compatible = "nxp,sja1105t", .data = &sja1105t_info },
905*8aa9ebccSVladimir Oltean 	{ .compatible = "nxp,sja1105p", .data = &sja1105p_info },
906*8aa9ebccSVladimir Oltean 	{ .compatible = "nxp,sja1105q", .data = &sja1105q_info },
907*8aa9ebccSVladimir Oltean 	{ .compatible = "nxp,sja1105r", .data = &sja1105r_info },
908*8aa9ebccSVladimir Oltean 	{ .compatible = "nxp,sja1105s", .data = &sja1105s_info },
909*8aa9ebccSVladimir Oltean 	{ /* sentinel */ },
910*8aa9ebccSVladimir Oltean };
911*8aa9ebccSVladimir Oltean MODULE_DEVICE_TABLE(of, sja1105_dt_ids);
912*8aa9ebccSVladimir Oltean 
913*8aa9ebccSVladimir Oltean static struct spi_driver sja1105_driver = {
914*8aa9ebccSVladimir Oltean 	.driver = {
915*8aa9ebccSVladimir Oltean 		.name  = "sja1105",
916*8aa9ebccSVladimir Oltean 		.owner = THIS_MODULE,
917*8aa9ebccSVladimir Oltean 		.of_match_table = of_match_ptr(sja1105_dt_ids),
918*8aa9ebccSVladimir Oltean 	},
919*8aa9ebccSVladimir Oltean 	.probe  = sja1105_probe,
920*8aa9ebccSVladimir Oltean 	.remove = sja1105_remove,
921*8aa9ebccSVladimir Oltean };
922*8aa9ebccSVladimir Oltean 
923*8aa9ebccSVladimir Oltean module_spi_driver(sja1105_driver);
924*8aa9ebccSVladimir Oltean 
925*8aa9ebccSVladimir Oltean MODULE_AUTHOR("Vladimir Oltean <olteanv@gmail.com>");
926*8aa9ebccSVladimir Oltean MODULE_AUTHOR("Georg Waibel <georg.waibel@sensor-technik.de>");
927*8aa9ebccSVladimir Oltean MODULE_DESCRIPTION("SJA1105 Driver");
928*8aa9ebccSVladimir Oltean MODULE_LICENSE("GPL v2");
929