blob: 1f4b07b77de245912bd4a0242b2314fae55bddba [file] [log] [blame]
Florian Fainelli967dd822016-06-09 18:23:53 -07001/*
2 * B53 common definitions
3 *
4 * Copyright (C) 2011-2013 Jonas Gorski <jogo@openwrt.org>
5 *
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19#ifndef __B53_PRIV_H
20#define __B53_PRIV_H
21
22#include <linux/kernel.h>
23#include <linux/mutex.h>
24#include <linux/phy.h>
Florian Fainelli4b92ea82017-01-05 11:08:58 -080025#include <linux/etherdevice.h>
Florian Fainelli967dd822016-06-09 18:23:53 -070026#include <net/dsa.h>
27
Florian Fainelli1da6df82016-06-09 18:23:55 -070028#include "b53_regs.h"
29
Florian Fainelli967dd822016-06-09 18:23:53 -070030struct b53_device;
Florian Fainelliff39c2d2016-06-09 18:23:56 -070031struct net_device;
Florian Fainelli967dd822016-06-09 18:23:53 -070032
33struct b53_io_ops {
34 int (*read8)(struct b53_device *dev, u8 page, u8 reg, u8 *value);
35 int (*read16)(struct b53_device *dev, u8 page, u8 reg, u16 *value);
36 int (*read32)(struct b53_device *dev, u8 page, u8 reg, u32 *value);
37 int (*read48)(struct b53_device *dev, u8 page, u8 reg, u64 *value);
38 int (*read64)(struct b53_device *dev, u8 page, u8 reg, u64 *value);
39 int (*write8)(struct b53_device *dev, u8 page, u8 reg, u8 value);
40 int (*write16)(struct b53_device *dev, u8 page, u8 reg, u16 value);
41 int (*write32)(struct b53_device *dev, u8 page, u8 reg, u32 value);
42 int (*write48)(struct b53_device *dev, u8 page, u8 reg, u64 value);
43 int (*write64)(struct b53_device *dev, u8 page, u8 reg, u64 value);
44 int (*phy_read16)(struct b53_device *dev, int addr, int reg, u16 *value);
45 int (*phy_write16)(struct b53_device *dev, int addr, int reg, u16 value);
46};
47
48enum {
49 BCM5325_DEVICE_ID = 0x25,
50 BCM5365_DEVICE_ID = 0x65,
51 BCM5395_DEVICE_ID = 0x95,
52 BCM5397_DEVICE_ID = 0x97,
53 BCM5398_DEVICE_ID = 0x98,
54 BCM53115_DEVICE_ID = 0x53115,
55 BCM53125_DEVICE_ID = 0x53125,
56 BCM53128_DEVICE_ID = 0x53128,
57 BCM63XX_DEVICE_ID = 0x6300,
58 BCM53010_DEVICE_ID = 0x53010,
59 BCM53011_DEVICE_ID = 0x53011,
60 BCM53012_DEVICE_ID = 0x53012,
61 BCM53018_DEVICE_ID = 0x53018,
62 BCM53019_DEVICE_ID = 0x53019,
Florian Fainelli991a36b2016-07-08 11:39:13 -070063 BCM58XX_DEVICE_ID = 0x5800,
Florian Fainelli130401d2016-08-26 12:18:30 -070064 BCM7445_DEVICE_ID = 0x7445,
Florian Fainelli967dd822016-06-09 18:23:53 -070065};
66
67#define B53_N_PORTS 9
68#define B53_N_PORTS_25 6
69
70struct b53_port {
Florian Fainelliff39c2d2016-06-09 18:23:56 -070071 u16 vlan_ctl_mask;
72 struct net_device *bridge_dev;
Florian Fainelli967dd822016-06-09 18:23:53 -070073};
74
Florian Fainellia2482d22016-06-09 18:23:57 -070075struct b53_vlan {
76 u16 members;
77 u16 untag;
78 bool valid;
79};
80
Florian Fainelli967dd822016-06-09 18:23:53 -070081struct b53_device {
82 struct dsa_switch *ds;
83 struct b53_platform_data *pdata;
84 const char *name;
85
86 struct mutex reg_mutex;
87 struct mutex stats_mutex;
88 const struct b53_io_ops *ops;
89
90 /* chip specific data */
91 u32 chip_id;
92 u8 core_rev;
93 u8 vta_regs[3];
94 u8 duplex_reg;
95 u8 jumbo_pm_reg;
96 u8 jumbo_size_reg;
97 int reset_gpio;
Florian Fainelli1da6df82016-06-09 18:23:55 -070098 u8 num_arl_entries;
Florian Fainelli967dd822016-06-09 18:23:53 -070099
100 /* used ports mask */
101 u16 enabled_ports;
102 unsigned int cpu_port;
103
104 /* connect specific data */
105 u8 current_page;
106 struct device *dev;
107
108 /* Master MDIO bus we got probed from */
109 struct mii_bus *bus;
110
Florian Fainelli967dd822016-06-09 18:23:53 -0700111 void *priv;
112
113 /* run time configuration */
Florian Fainellia2482d22016-06-09 18:23:57 -0700114 bool enable_jumbo;
115
Florian Fainelli967dd822016-06-09 18:23:53 -0700116 unsigned int num_vlans;
Florian Fainellia2482d22016-06-09 18:23:57 -0700117 struct b53_vlan *vlans;
Florian Fainelli967dd822016-06-09 18:23:53 -0700118 unsigned int num_ports;
119 struct b53_port *ports;
120};
121
122#define b53_for_each_port(dev, i) \
123 for (i = 0; i < B53_N_PORTS; i++) \
124 if (dev->enabled_ports & BIT(i))
125
126
127static inline int is5325(struct b53_device *dev)
128{
129 return dev->chip_id == BCM5325_DEVICE_ID;
130}
131
132static inline int is5365(struct b53_device *dev)
133{
134#ifdef CONFIG_BCM47XX
135 return dev->chip_id == BCM5365_DEVICE_ID;
136#else
137 return 0;
138#endif
139}
140
141static inline int is5397_98(struct b53_device *dev)
142{
143 return dev->chip_id == BCM5397_DEVICE_ID ||
144 dev->chip_id == BCM5398_DEVICE_ID;
145}
146
147static inline int is539x(struct b53_device *dev)
148{
149 return dev->chip_id == BCM5395_DEVICE_ID ||
150 dev->chip_id == BCM5397_DEVICE_ID ||
151 dev->chip_id == BCM5398_DEVICE_ID;
152}
153
154static inline int is531x5(struct b53_device *dev)
155{
156 return dev->chip_id == BCM53115_DEVICE_ID ||
157 dev->chip_id == BCM53125_DEVICE_ID ||
158 dev->chip_id == BCM53128_DEVICE_ID;
159}
160
161static inline int is63xx(struct b53_device *dev)
162{
163#ifdef CONFIG_BCM63XX
164 return dev->chip_id == BCM63XX_DEVICE_ID;
165#else
166 return 0;
167#endif
168}
169
170static inline int is5301x(struct b53_device *dev)
171{
172 return dev->chip_id == BCM53010_DEVICE_ID ||
173 dev->chip_id == BCM53011_DEVICE_ID ||
174 dev->chip_id == BCM53012_DEVICE_ID ||
175 dev->chip_id == BCM53018_DEVICE_ID ||
176 dev->chip_id == BCM53019_DEVICE_ID;
177}
178
Florian Fainellibde5d132016-08-26 12:18:31 -0700179static inline int is58xx(struct b53_device *dev)
180{
181 return dev->chip_id == BCM58XX_DEVICE_ID ||
182 dev->chip_id == BCM7445_DEVICE_ID;
183}
184
Florian Fainelli967dd822016-06-09 18:23:53 -0700185#define B53_CPU_PORT_25 5
186#define B53_CPU_PORT 8
187
188static inline int is_cpu_port(struct b53_device *dev, int port)
189{
190 return dev->cpu_port;
191}
192
Julia Lawall0dff88d2016-08-09 19:09:45 +0200193struct b53_device *b53_switch_alloc(struct device *base,
194 const struct b53_io_ops *ops,
Florian Fainelli967dd822016-06-09 18:23:53 -0700195 void *priv);
196
197int b53_switch_detect(struct b53_device *dev);
198
199int b53_switch_register(struct b53_device *dev);
200
201static inline void b53_switch_remove(struct b53_device *dev)
202{
203 dsa_unregister_switch(dev->ds);
204}
205
206static inline int b53_read8(struct b53_device *dev, u8 page, u8 reg, u8 *val)
207{
208 int ret;
209
210 mutex_lock(&dev->reg_mutex);
211 ret = dev->ops->read8(dev, page, reg, val);
212 mutex_unlock(&dev->reg_mutex);
213
214 return ret;
215}
216
217static inline int b53_read16(struct b53_device *dev, u8 page, u8 reg, u16 *val)
218{
219 int ret;
220
221 mutex_lock(&dev->reg_mutex);
222 ret = dev->ops->read16(dev, page, reg, val);
223 mutex_unlock(&dev->reg_mutex);
224
225 return ret;
226}
227
228static inline int b53_read32(struct b53_device *dev, u8 page, u8 reg, u32 *val)
229{
230 int ret;
231
232 mutex_lock(&dev->reg_mutex);
233 ret = dev->ops->read32(dev, page, reg, val);
234 mutex_unlock(&dev->reg_mutex);
235
236 return ret;
237}
238
239static inline int b53_read48(struct b53_device *dev, u8 page, u8 reg, u64 *val)
240{
241 int ret;
242
243 mutex_lock(&dev->reg_mutex);
244 ret = dev->ops->read48(dev, page, reg, val);
245 mutex_unlock(&dev->reg_mutex);
246
247 return ret;
248}
249
250static inline int b53_read64(struct b53_device *dev, u8 page, u8 reg, u64 *val)
251{
252 int ret;
253
254 mutex_lock(&dev->reg_mutex);
255 ret = dev->ops->read64(dev, page, reg, val);
256 mutex_unlock(&dev->reg_mutex);
257
258 return ret;
259}
260
261static inline int b53_write8(struct b53_device *dev, u8 page, u8 reg, u8 value)
262{
263 int ret;
264
265 mutex_lock(&dev->reg_mutex);
266 ret = dev->ops->write8(dev, page, reg, value);
267 mutex_unlock(&dev->reg_mutex);
268
269 return ret;
270}
271
272static inline int b53_write16(struct b53_device *dev, u8 page, u8 reg,
273 u16 value)
274{
275 int ret;
276
277 mutex_lock(&dev->reg_mutex);
278 ret = dev->ops->write16(dev, page, reg, value);
279 mutex_unlock(&dev->reg_mutex);
280
281 return ret;
282}
283
284static inline int b53_write32(struct b53_device *dev, u8 page, u8 reg,
285 u32 value)
286{
287 int ret;
288
289 mutex_lock(&dev->reg_mutex);
290 ret = dev->ops->write32(dev, page, reg, value);
291 mutex_unlock(&dev->reg_mutex);
292
293 return ret;
294}
295
296static inline int b53_write48(struct b53_device *dev, u8 page, u8 reg,
297 u64 value)
298{
299 int ret;
300
301 mutex_lock(&dev->reg_mutex);
302 ret = dev->ops->write48(dev, page, reg, value);
303 mutex_unlock(&dev->reg_mutex);
304
305 return ret;
306}
307
308static inline int b53_write64(struct b53_device *dev, u8 page, u8 reg,
309 u64 value)
310{
311 int ret;
312
313 mutex_lock(&dev->reg_mutex);
314 ret = dev->ops->write64(dev, page, reg, value);
315 mutex_unlock(&dev->reg_mutex);
316
317 return ret;
318}
319
Florian Fainelli1da6df82016-06-09 18:23:55 -0700320struct b53_arl_entry {
321 u8 port;
322 u8 mac[ETH_ALEN];
323 u16 vid;
324 u8 is_valid:1;
325 u8 is_age:1;
326 u8 is_static:1;
327};
328
Florian Fainelli1da6df82016-06-09 18:23:55 -0700329static inline void b53_arl_to_entry(struct b53_arl_entry *ent,
330 u64 mac_vid, u32 fwd_entry)
331{
332 memset(ent, 0, sizeof(*ent));
333 ent->port = fwd_entry & ARLTBL_DATA_PORT_ID_MASK;
334 ent->is_valid = !!(fwd_entry & ARLTBL_VALID);
335 ent->is_age = !!(fwd_entry & ARLTBL_AGE);
336 ent->is_static = !!(fwd_entry & ARLTBL_STATIC);
Florian Fainelli4b92ea82017-01-05 11:08:58 -0800337 u64_to_ether_addr(mac_vid, ent->mac);
Florian Fainelli1da6df82016-06-09 18:23:55 -0700338 ent->vid = mac_vid >> ARLTBL_VID_S;
339}
340
341static inline void b53_arl_from_entry(u64 *mac_vid, u32 *fwd_entry,
342 const struct b53_arl_entry *ent)
343{
Florian Fainelli4b92ea82017-01-05 11:08:58 -0800344 *mac_vid = ether_addr_to_u64(ent->mac);
Florian Fainelli1da6df82016-06-09 18:23:55 -0700345 *mac_vid |= (u64)(ent->vid & ARLTBL_VID_MASK) << ARLTBL_VID_S;
346 *fwd_entry = ent->port & ARLTBL_DATA_PORT_ID_MASK;
347 if (ent->is_valid)
348 *fwd_entry |= ARLTBL_VALID;
349 if (ent->is_static)
350 *fwd_entry |= ARLTBL_STATIC;
351 if (ent->is_age)
352 *fwd_entry |= ARLTBL_AGE;
353}
354
Florian Fainelli967dd822016-06-09 18:23:53 -0700355#ifdef CONFIG_BCM47XX
356
Florian Fainelli967dd822016-06-09 18:23:53 -0700357#include <linux/bcm47xx_nvram.h>
358#include <bcm47xx_board.h>
359static inline int b53_switch_get_reset_gpio(struct b53_device *dev)
360{
361 enum bcm47xx_board board = bcm47xx_board_get();
362
363 switch (board) {
364 case BCM47XX_BOARD_LINKSYS_WRT300NV11:
365 case BCM47XX_BOARD_LINKSYS_WRT310NV1:
366 return 8;
367 default:
368 return bcm47xx_nvram_gpio_pin("robo_reset");
369 }
370}
371#else
372static inline int b53_switch_get_reset_gpio(struct b53_device *dev)
373{
374 return -ENOENT;
375}
376#endif
377#endif