191da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek/*
291da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek * include/net/dsa.h - Driver for Distributed Switch Architecture switch chips
3e84665c9cb4db963393fafad6fefe5efdd7e4a09Lennert Buytenhek * Copyright (c) 2008-2009 Marvell Semiconductor
491da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek *
591da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek * This program is free software; you can redistribute it and/or modify
691da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek * it under the terms of the GNU General Public License as published by
791da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek * the Free Software Foundation; either version 2 of the License, or
891da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek * (at your option) any later version.
991da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek */
1091da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek
1191da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek#ifndef __LINUX_NET_DSA_H
1291da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek#define __LINUX_NET_DSA_H
1391da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek
14ea1f51beff4ddd0234c59a125290aeb355cf62b2Axel Lin#include <linux/if_ether.h>
15c8f0b86996c88081095124d16b869e8d8a1c02c5Ben Hutchings#include <linux/list.h>
16cf50dcc24f82a6dc2bce523eec2a979eb1b106e2Ben Hutchings#include <linux/timer.h>
17cf50dcc24f82a6dc2bce523eec2a979eb1b106e2Ben Hutchings#include <linux/workqueue.h>
18cf50dcc24f82a6dc2bce523eec2a979eb1b106e2Ben Hutchings
19e84665c9cb4db963393fafad6fefe5efdd7e4a09Lennert Buytenhek#define DSA_MAX_SWITCHES	4
20e84665c9cb4db963393fafad6fefe5efdd7e4a09Lennert Buytenhek#define DSA_MAX_PORTS		12
21e84665c9cb4db963393fafad6fefe5efdd7e4a09Lennert Buytenhek
22e84665c9cb4db963393fafad6fefe5efdd7e4a09Lennert Buytenhekstruct dsa_chip_data {
23e84665c9cb4db963393fafad6fefe5efdd7e4a09Lennert Buytenhek	/*
24e84665c9cb4db963393fafad6fefe5efdd7e4a09Lennert Buytenhek	 * How to access the switch configuration registers.
25e84665c9cb4db963393fafad6fefe5efdd7e4a09Lennert Buytenhek	 */
26e84665c9cb4db963393fafad6fefe5efdd7e4a09Lennert Buytenhek	struct device	*mii_bus;
27e84665c9cb4db963393fafad6fefe5efdd7e4a09Lennert Buytenhek	int		sw_addr;
28e84665c9cb4db963393fafad6fefe5efdd7e4a09Lennert Buytenhek
29e84665c9cb4db963393fafad6fefe5efdd7e4a09Lennert Buytenhek	/*
30e84665c9cb4db963393fafad6fefe5efdd7e4a09Lennert Buytenhek	 * The names of the switch's ports.  Use "cpu" to
31e84665c9cb4db963393fafad6fefe5efdd7e4a09Lennert Buytenhek	 * designate the switch port that the cpu is connected to,
32e84665c9cb4db963393fafad6fefe5efdd7e4a09Lennert Buytenhek	 * "dsa" to indicate that this port is a DSA link to
33e84665c9cb4db963393fafad6fefe5efdd7e4a09Lennert Buytenhek	 * another switch, NULL to indicate the port is unused,
34e84665c9cb4db963393fafad6fefe5efdd7e4a09Lennert Buytenhek	 * or any other string to indicate this is a physical port.
35e84665c9cb4db963393fafad6fefe5efdd7e4a09Lennert Buytenhek	 */
36e84665c9cb4db963393fafad6fefe5efdd7e4a09Lennert Buytenhek	char		*port_names[DSA_MAX_PORTS];
37e84665c9cb4db963393fafad6fefe5efdd7e4a09Lennert Buytenhek
38e84665c9cb4db963393fafad6fefe5efdd7e4a09Lennert Buytenhek	/*
39e84665c9cb4db963393fafad6fefe5efdd7e4a09Lennert Buytenhek	 * An array (with nr_chips elements) of which element [a]
40e84665c9cb4db963393fafad6fefe5efdd7e4a09Lennert Buytenhek	 * indicates which port on this switch should be used to
41e84665c9cb4db963393fafad6fefe5efdd7e4a09Lennert Buytenhek	 * send packets to that are destined for switch a.  Can be
42e84665c9cb4db963393fafad6fefe5efdd7e4a09Lennert Buytenhek	 * NULL if there is only one switch chip.
43e84665c9cb4db963393fafad6fefe5efdd7e4a09Lennert Buytenhek	 */
44e84665c9cb4db963393fafad6fefe5efdd7e4a09Lennert Buytenhek	s8		*rtable;
45e84665c9cb4db963393fafad6fefe5efdd7e4a09Lennert Buytenhek};
4691da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek
4791da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhekstruct dsa_platform_data {
4891da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	/*
4991da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	 * Reference to a Linux network interface that connects
50e84665c9cb4db963393fafad6fefe5efdd7e4a09Lennert Buytenhek	 * to the root switch chip of the tree.
5191da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	 */
5291da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	struct device	*netdev;
5391da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek
5491da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	/*
55e84665c9cb4db963393fafad6fefe5efdd7e4a09Lennert Buytenhek	 * Info structs describing each of the switch chips
56e84665c9cb4db963393fafad6fefe5efdd7e4a09Lennert Buytenhek	 * connected via this network interface.
5791da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek	 */
58e84665c9cb4db963393fafad6fefe5efdd7e4a09Lennert Buytenhek	int		nr_chips;
59e84665c9cb4db963393fafad6fefe5efdd7e4a09Lennert Buytenhek	struct dsa_chip_data	*chip;
6091da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek};
6191da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek
62cf50dcc24f82a6dc2bce523eec2a979eb1b106e2Ben Hutchingsstruct dsa_switch_tree {
63cf50dcc24f82a6dc2bce523eec2a979eb1b106e2Ben Hutchings	/*
64cf50dcc24f82a6dc2bce523eec2a979eb1b106e2Ben Hutchings	 * Configuration data for the platform device that owns
65cf50dcc24f82a6dc2bce523eec2a979eb1b106e2Ben Hutchings	 * this dsa switch tree instance.
66cf50dcc24f82a6dc2bce523eec2a979eb1b106e2Ben Hutchings	 */
67cf50dcc24f82a6dc2bce523eec2a979eb1b106e2Ben Hutchings	struct dsa_platform_data	*pd;
68cf50dcc24f82a6dc2bce523eec2a979eb1b106e2Ben Hutchings
69cf50dcc24f82a6dc2bce523eec2a979eb1b106e2Ben Hutchings	/*
70cf50dcc24f82a6dc2bce523eec2a979eb1b106e2Ben Hutchings	 * Reference to network device to use, and which tagging
71cf50dcc24f82a6dc2bce523eec2a979eb1b106e2Ben Hutchings	 * protocol to use.
72cf50dcc24f82a6dc2bce523eec2a979eb1b106e2Ben Hutchings	 */
73cf50dcc24f82a6dc2bce523eec2a979eb1b106e2Ben Hutchings	struct net_device	*master_netdev;
74cf50dcc24f82a6dc2bce523eec2a979eb1b106e2Ben Hutchings	__be16			tag_protocol;
75cf50dcc24f82a6dc2bce523eec2a979eb1b106e2Ben Hutchings
76cf50dcc24f82a6dc2bce523eec2a979eb1b106e2Ben Hutchings	/*
77cf50dcc24f82a6dc2bce523eec2a979eb1b106e2Ben Hutchings	 * The switch and port to which the CPU is attached.
78cf50dcc24f82a6dc2bce523eec2a979eb1b106e2Ben Hutchings	 */
79cf50dcc24f82a6dc2bce523eec2a979eb1b106e2Ben Hutchings	s8			cpu_switch;
80cf50dcc24f82a6dc2bce523eec2a979eb1b106e2Ben Hutchings	s8			cpu_port;
81cf50dcc24f82a6dc2bce523eec2a979eb1b106e2Ben Hutchings
82cf50dcc24f82a6dc2bce523eec2a979eb1b106e2Ben Hutchings	/*
83cf50dcc24f82a6dc2bce523eec2a979eb1b106e2Ben Hutchings	 * Link state polling.
84cf50dcc24f82a6dc2bce523eec2a979eb1b106e2Ben Hutchings	 */
85cf50dcc24f82a6dc2bce523eec2a979eb1b106e2Ben Hutchings	int			link_poll_needed;
86cf50dcc24f82a6dc2bce523eec2a979eb1b106e2Ben Hutchings	struct work_struct	link_poll_work;
87cf50dcc24f82a6dc2bce523eec2a979eb1b106e2Ben Hutchings	struct timer_list	link_poll_timer;
88cf50dcc24f82a6dc2bce523eec2a979eb1b106e2Ben Hutchings
89cf50dcc24f82a6dc2bce523eec2a979eb1b106e2Ben Hutchings	/*
90cf50dcc24f82a6dc2bce523eec2a979eb1b106e2Ben Hutchings	 * Data for the individual switch chips.
91cf50dcc24f82a6dc2bce523eec2a979eb1b106e2Ben Hutchings	 */
92cf50dcc24f82a6dc2bce523eec2a979eb1b106e2Ben Hutchings	struct dsa_switch	*ds[DSA_MAX_SWITCHES];
93cf50dcc24f82a6dc2bce523eec2a979eb1b106e2Ben Hutchings};
94cf50dcc24f82a6dc2bce523eec2a979eb1b106e2Ben Hutchings
95c8f0b86996c88081095124d16b869e8d8a1c02c5Ben Hutchingsstruct dsa_switch {
96c8f0b86996c88081095124d16b869e8d8a1c02c5Ben Hutchings	/*
97c8f0b86996c88081095124d16b869e8d8a1c02c5Ben Hutchings	 * Parent switch tree, and switch index.
98c8f0b86996c88081095124d16b869e8d8a1c02c5Ben Hutchings	 */
99c8f0b86996c88081095124d16b869e8d8a1c02c5Ben Hutchings	struct dsa_switch_tree	*dst;
100c8f0b86996c88081095124d16b869e8d8a1c02c5Ben Hutchings	int			index;
101c8f0b86996c88081095124d16b869e8d8a1c02c5Ben Hutchings
102c8f0b86996c88081095124d16b869e8d8a1c02c5Ben Hutchings	/*
103c8f0b86996c88081095124d16b869e8d8a1c02c5Ben Hutchings	 * Configuration data for this switch.
104c8f0b86996c88081095124d16b869e8d8a1c02c5Ben Hutchings	 */
105c8f0b86996c88081095124d16b869e8d8a1c02c5Ben Hutchings	struct dsa_chip_data	*pd;
106c8f0b86996c88081095124d16b869e8d8a1c02c5Ben Hutchings
107c8f0b86996c88081095124d16b869e8d8a1c02c5Ben Hutchings	/*
108c8f0b86996c88081095124d16b869e8d8a1c02c5Ben Hutchings	 * The used switch driver.
109c8f0b86996c88081095124d16b869e8d8a1c02c5Ben Hutchings	 */
110c8f0b86996c88081095124d16b869e8d8a1c02c5Ben Hutchings	struct dsa_switch_driver	*drv;
111c8f0b86996c88081095124d16b869e8d8a1c02c5Ben Hutchings
112c8f0b86996c88081095124d16b869e8d8a1c02c5Ben Hutchings	/*
113c8f0b86996c88081095124d16b869e8d8a1c02c5Ben Hutchings	 * Reference to mii bus to use.
114c8f0b86996c88081095124d16b869e8d8a1c02c5Ben Hutchings	 */
115c8f0b86996c88081095124d16b869e8d8a1c02c5Ben Hutchings	struct mii_bus		*master_mii_bus;
116c8f0b86996c88081095124d16b869e8d8a1c02c5Ben Hutchings
117c8f0b86996c88081095124d16b869e8d8a1c02c5Ben Hutchings	/*
118c8f0b86996c88081095124d16b869e8d8a1c02c5Ben Hutchings	 * Slave mii_bus and devices for the individual ports.
119c8f0b86996c88081095124d16b869e8d8a1c02c5Ben Hutchings	 */
120c8f0b86996c88081095124d16b869e8d8a1c02c5Ben Hutchings	u32			dsa_port_mask;
121c8f0b86996c88081095124d16b869e8d8a1c02c5Ben Hutchings	u32			phys_port_mask;
122c8f0b86996c88081095124d16b869e8d8a1c02c5Ben Hutchings	struct mii_bus		*slave_mii_bus;
123c8f0b86996c88081095124d16b869e8d8a1c02c5Ben Hutchings	struct net_device	*ports[DSA_MAX_PORTS];
124c8f0b86996c88081095124d16b869e8d8a1c02c5Ben Hutchings};
125c8f0b86996c88081095124d16b869e8d8a1c02c5Ben Hutchings
126c8f0b86996c88081095124d16b869e8d8a1c02c5Ben Hutchingsstatic inline bool dsa_is_cpu_port(struct dsa_switch *ds, int p)
127c8f0b86996c88081095124d16b869e8d8a1c02c5Ben Hutchings{
128c8f0b86996c88081095124d16b869e8d8a1c02c5Ben Hutchings	return !!(ds->index == ds->dst->cpu_switch && p == ds->dst->cpu_port);
129c8f0b86996c88081095124d16b869e8d8a1c02c5Ben Hutchings}
130c8f0b86996c88081095124d16b869e8d8a1c02c5Ben Hutchings
131c8f0b86996c88081095124d16b869e8d8a1c02c5Ben Hutchingsstatic inline u8 dsa_upstream_port(struct dsa_switch *ds)
132c8f0b86996c88081095124d16b869e8d8a1c02c5Ben Hutchings{
133c8f0b86996c88081095124d16b869e8d8a1c02c5Ben Hutchings	struct dsa_switch_tree *dst = ds->dst;
134c8f0b86996c88081095124d16b869e8d8a1c02c5Ben Hutchings
135c8f0b86996c88081095124d16b869e8d8a1c02c5Ben Hutchings	/*
136c8f0b86996c88081095124d16b869e8d8a1c02c5Ben Hutchings	 * If this is the root switch (i.e. the switch that connects
137c8f0b86996c88081095124d16b869e8d8a1c02c5Ben Hutchings	 * to the CPU), return the cpu port number on this switch.
138c8f0b86996c88081095124d16b869e8d8a1c02c5Ben Hutchings	 * Else return the (DSA) port number that connects to the
139c8f0b86996c88081095124d16b869e8d8a1c02c5Ben Hutchings	 * switch that is one hop closer to the cpu.
140c8f0b86996c88081095124d16b869e8d8a1c02c5Ben Hutchings	 */
141c8f0b86996c88081095124d16b869e8d8a1c02c5Ben Hutchings	if (dst->cpu_switch == ds->index)
142c8f0b86996c88081095124d16b869e8d8a1c02c5Ben Hutchings		return dst->cpu_port;
143c8f0b86996c88081095124d16b869e8d8a1c02c5Ben Hutchings	else
144c8f0b86996c88081095124d16b869e8d8a1c02c5Ben Hutchings		return ds->pd->rtable[dst->cpu_switch];
145c8f0b86996c88081095124d16b869e8d8a1c02c5Ben Hutchings}
146c8f0b86996c88081095124d16b869e8d8a1c02c5Ben Hutchings
147c8f0b86996c88081095124d16b869e8d8a1c02c5Ben Hutchingsstruct dsa_switch_driver {
148c8f0b86996c88081095124d16b869e8d8a1c02c5Ben Hutchings	struct list_head	list;
149c8f0b86996c88081095124d16b869e8d8a1c02c5Ben Hutchings
150c8f0b86996c88081095124d16b869e8d8a1c02c5Ben Hutchings	__be16			tag_protocol;
151c8f0b86996c88081095124d16b869e8d8a1c02c5Ben Hutchings	int			priv_size;
152c8f0b86996c88081095124d16b869e8d8a1c02c5Ben Hutchings
153c8f0b86996c88081095124d16b869e8d8a1c02c5Ben Hutchings	/*
154c8f0b86996c88081095124d16b869e8d8a1c02c5Ben Hutchings	 * Probing and setup.
155c8f0b86996c88081095124d16b869e8d8a1c02c5Ben Hutchings	 */
156c8f0b86996c88081095124d16b869e8d8a1c02c5Ben Hutchings	char	*(*probe)(struct mii_bus *bus, int sw_addr);
157c8f0b86996c88081095124d16b869e8d8a1c02c5Ben Hutchings	int	(*setup)(struct dsa_switch *ds);
158c8f0b86996c88081095124d16b869e8d8a1c02c5Ben Hutchings	int	(*set_addr)(struct dsa_switch *ds, u8 *addr);
159c8f0b86996c88081095124d16b869e8d8a1c02c5Ben Hutchings
160c8f0b86996c88081095124d16b869e8d8a1c02c5Ben Hutchings	/*
161c8f0b86996c88081095124d16b869e8d8a1c02c5Ben Hutchings	 * Access to the switch's PHY registers.
162c8f0b86996c88081095124d16b869e8d8a1c02c5Ben Hutchings	 */
163c8f0b86996c88081095124d16b869e8d8a1c02c5Ben Hutchings	int	(*phy_read)(struct dsa_switch *ds, int port, int regnum);
164c8f0b86996c88081095124d16b869e8d8a1c02c5Ben Hutchings	int	(*phy_write)(struct dsa_switch *ds, int port,
165c8f0b86996c88081095124d16b869e8d8a1c02c5Ben Hutchings			     int regnum, u16 val);
166c8f0b86996c88081095124d16b869e8d8a1c02c5Ben Hutchings
167c8f0b86996c88081095124d16b869e8d8a1c02c5Ben Hutchings	/*
168c8f0b86996c88081095124d16b869e8d8a1c02c5Ben Hutchings	 * Link state polling and IRQ handling.
169c8f0b86996c88081095124d16b869e8d8a1c02c5Ben Hutchings	 */
170c8f0b86996c88081095124d16b869e8d8a1c02c5Ben Hutchings	void	(*poll_link)(struct dsa_switch *ds);
171c8f0b86996c88081095124d16b869e8d8a1c02c5Ben Hutchings
172c8f0b86996c88081095124d16b869e8d8a1c02c5Ben Hutchings	/*
173c8f0b86996c88081095124d16b869e8d8a1c02c5Ben Hutchings	 * ethtool hardware statistics.
174c8f0b86996c88081095124d16b869e8d8a1c02c5Ben Hutchings	 */
175c8f0b86996c88081095124d16b869e8d8a1c02c5Ben Hutchings	void	(*get_strings)(struct dsa_switch *ds, int port, uint8_t *data);
176c8f0b86996c88081095124d16b869e8d8a1c02c5Ben Hutchings	void	(*get_ethtool_stats)(struct dsa_switch *ds,
177c8f0b86996c88081095124d16b869e8d8a1c02c5Ben Hutchings				     int port, uint64_t *data);
178c8f0b86996c88081095124d16b869e8d8a1c02c5Ben Hutchings	int	(*get_sset_count)(struct dsa_switch *ds);
179c8f0b86996c88081095124d16b869e8d8a1c02c5Ben Hutchings};
180c8f0b86996c88081095124d16b869e8d8a1c02c5Ben Hutchings
181c8f0b86996c88081095124d16b869e8d8a1c02c5Ben Hutchingsvoid register_switch_driver(struct dsa_switch_driver *type);
182c8f0b86996c88081095124d16b869e8d8a1c02c5Ben Hutchingsvoid unregister_switch_driver(struct dsa_switch_driver *type);
183c8f0b86996c88081095124d16b869e8d8a1c02c5Ben Hutchings
184cf50dcc24f82a6dc2bce523eec2a979eb1b106e2Ben Hutchings/*
185cf50dcc24f82a6dc2bce523eec2a979eb1b106e2Ben Hutchings * The original DSA tag format and some other tag formats have no
186cf50dcc24f82a6dc2bce523eec2a979eb1b106e2Ben Hutchings * ethertype, which means that we need to add a little hack to the
187cf50dcc24f82a6dc2bce523eec2a979eb1b106e2Ben Hutchings * networking receive path to make sure that received frames get
188cf50dcc24f82a6dc2bce523eec2a979eb1b106e2Ben Hutchings * the right ->protocol assigned to them when one of those tag
189cf50dcc24f82a6dc2bce523eec2a979eb1b106e2Ben Hutchings * formats is in use.
190cf50dcc24f82a6dc2bce523eec2a979eb1b106e2Ben Hutchings */
191cf50dcc24f82a6dc2bce523eec2a979eb1b106e2Ben Hutchingsstatic inline bool dsa_uses_dsa_tags(struct dsa_switch_tree *dst)
192cf50dcc24f82a6dc2bce523eec2a979eb1b106e2Ben Hutchings{
193cf50dcc24f82a6dc2bce523eec2a979eb1b106e2Ben Hutchings	return !!(dst->tag_protocol == htons(ETH_P_DSA));
194cf50dcc24f82a6dc2bce523eec2a979eb1b106e2Ben Hutchings}
195cf85d08fdf4548ee46657ccfb7f9949a85145db5Lennert Buytenhek
196cf50dcc24f82a6dc2bce523eec2a979eb1b106e2Ben Hutchingsstatic inline bool dsa_uses_trailer_tags(struct dsa_switch_tree *dst)
197cf50dcc24f82a6dc2bce523eec2a979eb1b106e2Ben Hutchings{
198cf50dcc24f82a6dc2bce523eec2a979eb1b106e2Ben Hutchings	return !!(dst->tag_protocol == htons(ETH_P_TRAILER));
199cf50dcc24f82a6dc2bce523eec2a979eb1b106e2Ben Hutchings}
20091da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek
20191da11f870f00a3322b81c73042291d7f0be5a17Lennert Buytenhek#endif
202