xref: /openbmc/linux/drivers/net/dsa/ocelot/felix.c (revision 56051948773eeb4224fbda88102e891d1ad5cefd)
1*56051948SVladimir Oltean // SPDX-License-Identifier: GPL-2.0
2*56051948SVladimir Oltean /* Copyright 2019 NXP Semiconductors
3*56051948SVladimir Oltean  */
4*56051948SVladimir Oltean #include <uapi/linux/if_bridge.h>
5*56051948SVladimir Oltean #include <soc/mscc/ocelot.h>
6*56051948SVladimir Oltean #include <linux/module.h>
7*56051948SVladimir Oltean #include <linux/pci.h>
8*56051948SVladimir Oltean #include <linux/of.h>
9*56051948SVladimir Oltean #include <net/dsa.h>
10*56051948SVladimir Oltean #include "felix.h"
11*56051948SVladimir Oltean 
12*56051948SVladimir Oltean static enum dsa_tag_protocol felix_get_tag_protocol(struct dsa_switch *ds,
13*56051948SVladimir Oltean 						    int port)
14*56051948SVladimir Oltean {
15*56051948SVladimir Oltean 	return DSA_TAG_PROTO_OCELOT;
16*56051948SVladimir Oltean }
17*56051948SVladimir Oltean 
18*56051948SVladimir Oltean static int felix_set_ageing_time(struct dsa_switch *ds,
19*56051948SVladimir Oltean 				 unsigned int ageing_time)
20*56051948SVladimir Oltean {
21*56051948SVladimir Oltean 	struct ocelot *ocelot = ds->priv;
22*56051948SVladimir Oltean 
23*56051948SVladimir Oltean 	ocelot_set_ageing_time(ocelot, ageing_time);
24*56051948SVladimir Oltean 
25*56051948SVladimir Oltean 	return 0;
26*56051948SVladimir Oltean }
27*56051948SVladimir Oltean 
28*56051948SVladimir Oltean static void felix_adjust_link(struct dsa_switch *ds, int port,
29*56051948SVladimir Oltean 			      struct phy_device *phydev)
30*56051948SVladimir Oltean {
31*56051948SVladimir Oltean 	struct ocelot *ocelot = ds->priv;
32*56051948SVladimir Oltean 
33*56051948SVladimir Oltean 	ocelot_adjust_link(ocelot, port, phydev);
34*56051948SVladimir Oltean }
35*56051948SVladimir Oltean 
36*56051948SVladimir Oltean static int felix_fdb_dump(struct dsa_switch *ds, int port,
37*56051948SVladimir Oltean 			  dsa_fdb_dump_cb_t *cb, void *data)
38*56051948SVladimir Oltean {
39*56051948SVladimir Oltean 	struct ocelot *ocelot = ds->priv;
40*56051948SVladimir Oltean 
41*56051948SVladimir Oltean 	return ocelot_fdb_dump(ocelot, port, cb, data);
42*56051948SVladimir Oltean }
43*56051948SVladimir Oltean 
44*56051948SVladimir Oltean static int felix_fdb_add(struct dsa_switch *ds, int port,
45*56051948SVladimir Oltean 			 const unsigned char *addr, u16 vid)
46*56051948SVladimir Oltean {
47*56051948SVladimir Oltean 	struct ocelot *ocelot = ds->priv;
48*56051948SVladimir Oltean 	bool vlan_aware;
49*56051948SVladimir Oltean 
50*56051948SVladimir Oltean 	vlan_aware = dsa_port_is_vlan_filtering(dsa_to_port(ds, port));
51*56051948SVladimir Oltean 
52*56051948SVladimir Oltean 	return ocelot_fdb_add(ocelot, port, addr, vid, vlan_aware);
53*56051948SVladimir Oltean }
54*56051948SVladimir Oltean 
55*56051948SVladimir Oltean static int felix_fdb_del(struct dsa_switch *ds, int port,
56*56051948SVladimir Oltean 			 const unsigned char *addr, u16 vid)
57*56051948SVladimir Oltean {
58*56051948SVladimir Oltean 	struct ocelot *ocelot = ds->priv;
59*56051948SVladimir Oltean 
60*56051948SVladimir Oltean 	return ocelot_fdb_del(ocelot, port, addr, vid);
61*56051948SVladimir Oltean }
62*56051948SVladimir Oltean 
63*56051948SVladimir Oltean static void felix_bridge_stp_state_set(struct dsa_switch *ds, int port,
64*56051948SVladimir Oltean 				       u8 state)
65*56051948SVladimir Oltean {
66*56051948SVladimir Oltean 	struct ocelot *ocelot = ds->priv;
67*56051948SVladimir Oltean 
68*56051948SVladimir Oltean 	return ocelot_bridge_stp_state_set(ocelot, port, state);
69*56051948SVladimir Oltean }
70*56051948SVladimir Oltean 
71*56051948SVladimir Oltean static int felix_bridge_join(struct dsa_switch *ds, int port,
72*56051948SVladimir Oltean 			     struct net_device *br)
73*56051948SVladimir Oltean {
74*56051948SVladimir Oltean 	struct ocelot *ocelot = ds->priv;
75*56051948SVladimir Oltean 
76*56051948SVladimir Oltean 	return ocelot_port_bridge_join(ocelot, port, br);
77*56051948SVladimir Oltean }
78*56051948SVladimir Oltean 
79*56051948SVladimir Oltean static void felix_bridge_leave(struct dsa_switch *ds, int port,
80*56051948SVladimir Oltean 			       struct net_device *br)
81*56051948SVladimir Oltean {
82*56051948SVladimir Oltean 	struct ocelot *ocelot = ds->priv;
83*56051948SVladimir Oltean 
84*56051948SVladimir Oltean 	ocelot_port_bridge_leave(ocelot, port, br);
85*56051948SVladimir Oltean }
86*56051948SVladimir Oltean 
87*56051948SVladimir Oltean /* This callback needs to be present */
88*56051948SVladimir Oltean static int felix_vlan_prepare(struct dsa_switch *ds, int port,
89*56051948SVladimir Oltean 			      const struct switchdev_obj_port_vlan *vlan)
90*56051948SVladimir Oltean {
91*56051948SVladimir Oltean 	return 0;
92*56051948SVladimir Oltean }
93*56051948SVladimir Oltean 
94*56051948SVladimir Oltean static int felix_vlan_filtering(struct dsa_switch *ds, int port, bool enabled)
95*56051948SVladimir Oltean {
96*56051948SVladimir Oltean 	struct ocelot *ocelot = ds->priv;
97*56051948SVladimir Oltean 
98*56051948SVladimir Oltean 	ocelot_port_vlan_filtering(ocelot, port, enabled);
99*56051948SVladimir Oltean 
100*56051948SVladimir Oltean 	return 0;
101*56051948SVladimir Oltean }
102*56051948SVladimir Oltean 
103*56051948SVladimir Oltean static void felix_vlan_add(struct dsa_switch *ds, int port,
104*56051948SVladimir Oltean 			   const struct switchdev_obj_port_vlan *vlan)
105*56051948SVladimir Oltean {
106*56051948SVladimir Oltean 	struct ocelot *ocelot = ds->priv;
107*56051948SVladimir Oltean 	u16 vid;
108*56051948SVladimir Oltean 	int err;
109*56051948SVladimir Oltean 
110*56051948SVladimir Oltean 	for (vid = vlan->vid_begin; vid <= vlan->vid_end; vid++) {
111*56051948SVladimir Oltean 		err = ocelot_vlan_add(ocelot, port, vid,
112*56051948SVladimir Oltean 				      vlan->flags & BRIDGE_VLAN_INFO_PVID,
113*56051948SVladimir Oltean 				      vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED);
114*56051948SVladimir Oltean 		if (err) {
115*56051948SVladimir Oltean 			dev_err(ds->dev, "Failed to add VLAN %d to port %d: %d\n",
116*56051948SVladimir Oltean 				vid, port, err);
117*56051948SVladimir Oltean 			return;
118*56051948SVladimir Oltean 		}
119*56051948SVladimir Oltean 	}
120*56051948SVladimir Oltean }
121*56051948SVladimir Oltean 
122*56051948SVladimir Oltean static int felix_vlan_del(struct dsa_switch *ds, int port,
123*56051948SVladimir Oltean 			  const struct switchdev_obj_port_vlan *vlan)
124*56051948SVladimir Oltean {
125*56051948SVladimir Oltean 	struct ocelot *ocelot = ds->priv;
126*56051948SVladimir Oltean 	u16 vid;
127*56051948SVladimir Oltean 	int err;
128*56051948SVladimir Oltean 
129*56051948SVladimir Oltean 	for (vid = vlan->vid_begin; vid <= vlan->vid_end; vid++) {
130*56051948SVladimir Oltean 		err = ocelot_vlan_del(ocelot, port, vid);
131*56051948SVladimir Oltean 		if (err) {
132*56051948SVladimir Oltean 			dev_err(ds->dev, "Failed to remove VLAN %d from port %d: %d\n",
133*56051948SVladimir Oltean 				vid, port, err);
134*56051948SVladimir Oltean 			return err;
135*56051948SVladimir Oltean 		}
136*56051948SVladimir Oltean 	}
137*56051948SVladimir Oltean 	return 0;
138*56051948SVladimir Oltean }
139*56051948SVladimir Oltean 
140*56051948SVladimir Oltean static int felix_port_enable(struct dsa_switch *ds, int port,
141*56051948SVladimir Oltean 			     struct phy_device *phy)
142*56051948SVladimir Oltean {
143*56051948SVladimir Oltean 	struct ocelot *ocelot = ds->priv;
144*56051948SVladimir Oltean 
145*56051948SVladimir Oltean 	ocelot_port_enable(ocelot, port, phy);
146*56051948SVladimir Oltean 
147*56051948SVladimir Oltean 	return 0;
148*56051948SVladimir Oltean }
149*56051948SVladimir Oltean 
150*56051948SVladimir Oltean static void felix_port_disable(struct dsa_switch *ds, int port)
151*56051948SVladimir Oltean {
152*56051948SVladimir Oltean 	struct ocelot *ocelot = ds->priv;
153*56051948SVladimir Oltean 
154*56051948SVladimir Oltean 	return ocelot_port_disable(ocelot, port);
155*56051948SVladimir Oltean }
156*56051948SVladimir Oltean 
157*56051948SVladimir Oltean static void felix_get_strings(struct dsa_switch *ds, int port,
158*56051948SVladimir Oltean 			      u32 stringset, u8 *data)
159*56051948SVladimir Oltean {
160*56051948SVladimir Oltean 	struct ocelot *ocelot = ds->priv;
161*56051948SVladimir Oltean 
162*56051948SVladimir Oltean 	return ocelot_get_strings(ocelot, port, stringset, data);
163*56051948SVladimir Oltean }
164*56051948SVladimir Oltean 
165*56051948SVladimir Oltean static void felix_get_ethtool_stats(struct dsa_switch *ds, int port, u64 *data)
166*56051948SVladimir Oltean {
167*56051948SVladimir Oltean 	struct ocelot *ocelot = ds->priv;
168*56051948SVladimir Oltean 
169*56051948SVladimir Oltean 	ocelot_get_ethtool_stats(ocelot, port, data);
170*56051948SVladimir Oltean }
171*56051948SVladimir Oltean 
172*56051948SVladimir Oltean static int felix_get_sset_count(struct dsa_switch *ds, int port, int sset)
173*56051948SVladimir Oltean {
174*56051948SVladimir Oltean 	struct ocelot *ocelot = ds->priv;
175*56051948SVladimir Oltean 
176*56051948SVladimir Oltean 	return ocelot_get_sset_count(ocelot, port, sset);
177*56051948SVladimir Oltean }
178*56051948SVladimir Oltean 
179*56051948SVladimir Oltean static int felix_get_ts_info(struct dsa_switch *ds, int port,
180*56051948SVladimir Oltean 			     struct ethtool_ts_info *info)
181*56051948SVladimir Oltean {
182*56051948SVladimir Oltean 	struct ocelot *ocelot = ds->priv;
183*56051948SVladimir Oltean 
184*56051948SVladimir Oltean 	return ocelot_get_ts_info(ocelot, port, info);
185*56051948SVladimir Oltean }
186*56051948SVladimir Oltean 
187*56051948SVladimir Oltean static int felix_init_structs(struct felix *felix, int num_phys_ports)
188*56051948SVladimir Oltean {
189*56051948SVladimir Oltean 	struct ocelot *ocelot = &felix->ocelot;
190*56051948SVladimir Oltean 	resource_size_t base;
191*56051948SVladimir Oltean 	int port, i, err;
192*56051948SVladimir Oltean 
193*56051948SVladimir Oltean 	ocelot->num_phys_ports = num_phys_ports;
194*56051948SVladimir Oltean 	ocelot->ports = devm_kcalloc(ocelot->dev, num_phys_ports,
195*56051948SVladimir Oltean 				     sizeof(struct ocelot_port *), GFP_KERNEL);
196*56051948SVladimir Oltean 	if (!ocelot->ports)
197*56051948SVladimir Oltean 		return -ENOMEM;
198*56051948SVladimir Oltean 
199*56051948SVladimir Oltean 	ocelot->map		= felix->info->map;
200*56051948SVladimir Oltean 	ocelot->stats_layout	= felix->info->stats_layout;
201*56051948SVladimir Oltean 	ocelot->num_stats	= felix->info->num_stats;
202*56051948SVladimir Oltean 	ocelot->shared_queue_sz	= felix->info->shared_queue_sz;
203*56051948SVladimir Oltean 	ocelot->ops		= felix->info->ops;
204*56051948SVladimir Oltean 
205*56051948SVladimir Oltean 	base = pci_resource_start(felix->pdev, felix->info->pci_bar);
206*56051948SVladimir Oltean 
207*56051948SVladimir Oltean 	for (i = 0; i < TARGET_MAX; i++) {
208*56051948SVladimir Oltean 		struct regmap *target;
209*56051948SVladimir Oltean 		struct resource *res;
210*56051948SVladimir Oltean 
211*56051948SVladimir Oltean 		if (!felix->info->target_io_res[i].name)
212*56051948SVladimir Oltean 			continue;
213*56051948SVladimir Oltean 
214*56051948SVladimir Oltean 		res = &felix->info->target_io_res[i];
215*56051948SVladimir Oltean 		res->flags = IORESOURCE_MEM;
216*56051948SVladimir Oltean 		res->start += base;
217*56051948SVladimir Oltean 		res->end += base;
218*56051948SVladimir Oltean 
219*56051948SVladimir Oltean 		target = ocelot_regmap_init(ocelot, res);
220*56051948SVladimir Oltean 		if (IS_ERR(target)) {
221*56051948SVladimir Oltean 			dev_err(ocelot->dev,
222*56051948SVladimir Oltean 				"Failed to map device memory space\n");
223*56051948SVladimir Oltean 			return PTR_ERR(target);
224*56051948SVladimir Oltean 		}
225*56051948SVladimir Oltean 
226*56051948SVladimir Oltean 		ocelot->targets[i] = target;
227*56051948SVladimir Oltean 	}
228*56051948SVladimir Oltean 
229*56051948SVladimir Oltean 	err = ocelot_regfields_init(ocelot, felix->info->regfields);
230*56051948SVladimir Oltean 	if (err) {
231*56051948SVladimir Oltean 		dev_err(ocelot->dev, "failed to init reg fields map\n");
232*56051948SVladimir Oltean 		return err;
233*56051948SVladimir Oltean 	}
234*56051948SVladimir Oltean 
235*56051948SVladimir Oltean 	for (port = 0; port < num_phys_ports; port++) {
236*56051948SVladimir Oltean 		struct ocelot_port *ocelot_port;
237*56051948SVladimir Oltean 		void __iomem *port_regs;
238*56051948SVladimir Oltean 		struct resource *res;
239*56051948SVladimir Oltean 
240*56051948SVladimir Oltean 		ocelot_port = devm_kzalloc(ocelot->dev,
241*56051948SVladimir Oltean 					   sizeof(struct ocelot_port),
242*56051948SVladimir Oltean 					   GFP_KERNEL);
243*56051948SVladimir Oltean 		if (!ocelot_port) {
244*56051948SVladimir Oltean 			dev_err(ocelot->dev,
245*56051948SVladimir Oltean 				"failed to allocate port memory\n");
246*56051948SVladimir Oltean 			return -ENOMEM;
247*56051948SVladimir Oltean 		}
248*56051948SVladimir Oltean 
249*56051948SVladimir Oltean 		res = &felix->info->port_io_res[port];
250*56051948SVladimir Oltean 		res->flags = IORESOURCE_MEM;
251*56051948SVladimir Oltean 		res->start += base;
252*56051948SVladimir Oltean 		res->end += base;
253*56051948SVladimir Oltean 
254*56051948SVladimir Oltean 		port_regs = devm_ioremap_resource(ocelot->dev, res);
255*56051948SVladimir Oltean 		if (IS_ERR(port_regs)) {
256*56051948SVladimir Oltean 			dev_err(ocelot->dev,
257*56051948SVladimir Oltean 				"failed to map registers for port %d\n", port);
258*56051948SVladimir Oltean 			return PTR_ERR(port_regs);
259*56051948SVladimir Oltean 		}
260*56051948SVladimir Oltean 
261*56051948SVladimir Oltean 		ocelot_port->ocelot = ocelot;
262*56051948SVladimir Oltean 		ocelot_port->regs = port_regs;
263*56051948SVladimir Oltean 		ocelot->ports[port] = ocelot_port;
264*56051948SVladimir Oltean 	}
265*56051948SVladimir Oltean 
266*56051948SVladimir Oltean 	return 0;
267*56051948SVladimir Oltean }
268*56051948SVladimir Oltean 
269*56051948SVladimir Oltean /* Hardware initialization done here so that we can allocate structures with
270*56051948SVladimir Oltean  * devm without fear of dsa_register_switch returning -EPROBE_DEFER and causing
271*56051948SVladimir Oltean  * us to allocate structures twice (leak memory) and map PCI memory twice
272*56051948SVladimir Oltean  * (which will not work).
273*56051948SVladimir Oltean  */
274*56051948SVladimir Oltean static int felix_setup(struct dsa_switch *ds)
275*56051948SVladimir Oltean {
276*56051948SVladimir Oltean 	struct ocelot *ocelot = ds->priv;
277*56051948SVladimir Oltean 	struct felix *felix = ocelot_to_felix(ocelot);
278*56051948SVladimir Oltean 	int port, err;
279*56051948SVladimir Oltean 
280*56051948SVladimir Oltean 	err = felix_init_structs(felix, ds->num_ports);
281*56051948SVladimir Oltean 	if (err)
282*56051948SVladimir Oltean 		return err;
283*56051948SVladimir Oltean 
284*56051948SVladimir Oltean 	ocelot_init(ocelot);
285*56051948SVladimir Oltean 
286*56051948SVladimir Oltean 	for (port = 0; port < ds->num_ports; port++) {
287*56051948SVladimir Oltean 		ocelot_init_port(ocelot, port);
288*56051948SVladimir Oltean 
289*56051948SVladimir Oltean 		if (port == dsa_upstream_port(ds, port))
290*56051948SVladimir Oltean 			ocelot_set_cpu_port(ocelot, port,
291*56051948SVladimir Oltean 					    OCELOT_TAG_PREFIX_NONE,
292*56051948SVladimir Oltean 					    OCELOT_TAG_PREFIX_LONG);
293*56051948SVladimir Oltean 	}
294*56051948SVladimir Oltean 
295*56051948SVladimir Oltean 	return 0;
296*56051948SVladimir Oltean }
297*56051948SVladimir Oltean 
298*56051948SVladimir Oltean static void felix_teardown(struct dsa_switch *ds)
299*56051948SVladimir Oltean {
300*56051948SVladimir Oltean 	struct ocelot *ocelot = ds->priv;
301*56051948SVladimir Oltean 
302*56051948SVladimir Oltean 	/* stop workqueue thread */
303*56051948SVladimir Oltean 	ocelot_deinit(ocelot);
304*56051948SVladimir Oltean }
305*56051948SVladimir Oltean 
306*56051948SVladimir Oltean static const struct dsa_switch_ops felix_switch_ops = {
307*56051948SVladimir Oltean 	.get_tag_protocol	= felix_get_tag_protocol,
308*56051948SVladimir Oltean 	.setup			= felix_setup,
309*56051948SVladimir Oltean 	.teardown		= felix_teardown,
310*56051948SVladimir Oltean 	.set_ageing_time	= felix_set_ageing_time,
311*56051948SVladimir Oltean 	.get_strings		= felix_get_strings,
312*56051948SVladimir Oltean 	.get_ethtool_stats	= felix_get_ethtool_stats,
313*56051948SVladimir Oltean 	.get_sset_count		= felix_get_sset_count,
314*56051948SVladimir Oltean 	.get_ts_info		= felix_get_ts_info,
315*56051948SVladimir Oltean 	.adjust_link		= felix_adjust_link,
316*56051948SVladimir Oltean 	.port_enable		= felix_port_enable,
317*56051948SVladimir Oltean 	.port_disable		= felix_port_disable,
318*56051948SVladimir Oltean 	.port_fdb_dump		= felix_fdb_dump,
319*56051948SVladimir Oltean 	.port_fdb_add		= felix_fdb_add,
320*56051948SVladimir Oltean 	.port_fdb_del		= felix_fdb_del,
321*56051948SVladimir Oltean 	.port_bridge_join	= felix_bridge_join,
322*56051948SVladimir Oltean 	.port_bridge_leave	= felix_bridge_leave,
323*56051948SVladimir Oltean 	.port_stp_state_set	= felix_bridge_stp_state_set,
324*56051948SVladimir Oltean 	.port_vlan_prepare	= felix_vlan_prepare,
325*56051948SVladimir Oltean 	.port_vlan_filtering	= felix_vlan_filtering,
326*56051948SVladimir Oltean 	.port_vlan_add		= felix_vlan_add,
327*56051948SVladimir Oltean 	.port_vlan_del		= felix_vlan_del,
328*56051948SVladimir Oltean };
329*56051948SVladimir Oltean 
330*56051948SVladimir Oltean static struct felix_info *felix_instance_tbl[] = {
331*56051948SVladimir Oltean 	[FELIX_INSTANCE_VSC9959] = &felix_info_vsc9959,
332*56051948SVladimir Oltean };
333*56051948SVladimir Oltean 
334*56051948SVladimir Oltean static int felix_pci_probe(struct pci_dev *pdev,
335*56051948SVladimir Oltean 			   const struct pci_device_id *id)
336*56051948SVladimir Oltean {
337*56051948SVladimir Oltean 	enum felix_instance instance = id->driver_data;
338*56051948SVladimir Oltean 	struct dsa_switch *ds;
339*56051948SVladimir Oltean 	struct ocelot *ocelot;
340*56051948SVladimir Oltean 	struct felix *felix;
341*56051948SVladimir Oltean 	int err;
342*56051948SVladimir Oltean 
343*56051948SVladimir Oltean 	err = pci_enable_device(pdev);
344*56051948SVladimir Oltean 	if (err) {
345*56051948SVladimir Oltean 		dev_err(&pdev->dev, "device enable failed\n");
346*56051948SVladimir Oltean 		goto err_pci_enable;
347*56051948SVladimir Oltean 	}
348*56051948SVladimir Oltean 
349*56051948SVladimir Oltean 	/* set up for high or low dma */
350*56051948SVladimir Oltean 	err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
351*56051948SVladimir Oltean 	if (err) {
352*56051948SVladimir Oltean 		err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
353*56051948SVladimir Oltean 		if (err) {
354*56051948SVladimir Oltean 			dev_err(&pdev->dev,
355*56051948SVladimir Oltean 				"DMA configuration failed: 0x%x\n", err);
356*56051948SVladimir Oltean 			goto err_dma;
357*56051948SVladimir Oltean 		}
358*56051948SVladimir Oltean 	}
359*56051948SVladimir Oltean 
360*56051948SVladimir Oltean 	felix = kzalloc(sizeof(struct felix), GFP_KERNEL);
361*56051948SVladimir Oltean 	if (!felix) {
362*56051948SVladimir Oltean 		err = -ENOMEM;
363*56051948SVladimir Oltean 		dev_err(&pdev->dev, "Failed to allocate driver memory\n");
364*56051948SVladimir Oltean 		goto err_alloc_felix;
365*56051948SVladimir Oltean 	}
366*56051948SVladimir Oltean 
367*56051948SVladimir Oltean 	pci_set_drvdata(pdev, felix);
368*56051948SVladimir Oltean 	ocelot = &felix->ocelot;
369*56051948SVladimir Oltean 	ocelot->dev = &pdev->dev;
370*56051948SVladimir Oltean 	felix->pdev = pdev;
371*56051948SVladimir Oltean 	felix->info = felix_instance_tbl[instance];
372*56051948SVladimir Oltean 
373*56051948SVladimir Oltean 	pci_set_master(pdev);
374*56051948SVladimir Oltean 
375*56051948SVladimir Oltean 	ds = kzalloc(sizeof(struct dsa_switch), GFP_KERNEL);
376*56051948SVladimir Oltean 	if (!ds) {
377*56051948SVladimir Oltean 		err = -ENOMEM;
378*56051948SVladimir Oltean 		dev_err(&pdev->dev, "Failed to allocate DSA switch\n");
379*56051948SVladimir Oltean 		goto err_alloc_ds;
380*56051948SVladimir Oltean 	}
381*56051948SVladimir Oltean 
382*56051948SVladimir Oltean 	ds->dev = &pdev->dev;
383*56051948SVladimir Oltean 	ds->num_ports = felix->info->num_ports;
384*56051948SVladimir Oltean 	ds->ops = &felix_switch_ops;
385*56051948SVladimir Oltean 	ds->priv = ocelot;
386*56051948SVladimir Oltean 	felix->ds = ds;
387*56051948SVladimir Oltean 
388*56051948SVladimir Oltean 	err = dsa_register_switch(ds);
389*56051948SVladimir Oltean 	if (err) {
390*56051948SVladimir Oltean 		dev_err(&pdev->dev, "Failed to register DSA switch: %d\n", err);
391*56051948SVladimir Oltean 		goto err_register_ds;
392*56051948SVladimir Oltean 	}
393*56051948SVladimir Oltean 
394*56051948SVladimir Oltean 	return 0;
395*56051948SVladimir Oltean 
396*56051948SVladimir Oltean err_register_ds:
397*56051948SVladimir Oltean 	kfree(ds);
398*56051948SVladimir Oltean err_alloc_ds:
399*56051948SVladimir Oltean err_alloc_felix:
400*56051948SVladimir Oltean 	kfree(felix);
401*56051948SVladimir Oltean err_dma:
402*56051948SVladimir Oltean 	pci_disable_device(pdev);
403*56051948SVladimir Oltean err_pci_enable:
404*56051948SVladimir Oltean 	return err;
405*56051948SVladimir Oltean }
406*56051948SVladimir Oltean 
407*56051948SVladimir Oltean static void felix_pci_remove(struct pci_dev *pdev)
408*56051948SVladimir Oltean {
409*56051948SVladimir Oltean 	struct felix *felix;
410*56051948SVladimir Oltean 
411*56051948SVladimir Oltean 	felix = pci_get_drvdata(pdev);
412*56051948SVladimir Oltean 
413*56051948SVladimir Oltean 	dsa_unregister_switch(felix->ds);
414*56051948SVladimir Oltean 
415*56051948SVladimir Oltean 	kfree(felix->ds);
416*56051948SVladimir Oltean 	kfree(felix);
417*56051948SVladimir Oltean 
418*56051948SVladimir Oltean 	pci_disable_device(pdev);
419*56051948SVladimir Oltean }
420*56051948SVladimir Oltean 
421*56051948SVladimir Oltean static struct pci_device_id felix_ids[] = {
422*56051948SVladimir Oltean 	{
423*56051948SVladimir Oltean 		/* NXP LS1028A */
424*56051948SVladimir Oltean 		PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, 0xEEF0),
425*56051948SVladimir Oltean 		.driver_data = FELIX_INSTANCE_VSC9959,
426*56051948SVladimir Oltean 	},
427*56051948SVladimir Oltean 	{ 0, }
428*56051948SVladimir Oltean };
429*56051948SVladimir Oltean MODULE_DEVICE_TABLE(pci, felix_ids);
430*56051948SVladimir Oltean 
431*56051948SVladimir Oltean static struct pci_driver felix_pci_driver = {
432*56051948SVladimir Oltean 	.name		= KBUILD_MODNAME,
433*56051948SVladimir Oltean 	.id_table	= felix_ids,
434*56051948SVladimir Oltean 	.probe		= felix_pci_probe,
435*56051948SVladimir Oltean 	.remove		= felix_pci_remove,
436*56051948SVladimir Oltean };
437*56051948SVladimir Oltean 
438*56051948SVladimir Oltean module_pci_driver(felix_pci_driver);
439*56051948SVladimir Oltean 
440*56051948SVladimir Oltean MODULE_DESCRIPTION("Felix Switch driver");
441*56051948SVladimir Oltean MODULE_LICENSE("GPL v2");
442