1 #include <linux/ioport.h>
2 #include <linux/switch.h>
5 #include <rt305x_regs.h>
6 #include <rt305x_esw_platform.h>
9 * HW limitations for this switch:
10 * - No large frame support (PKT_MAX_LEN at most 1536)
11 * - Can't have untagged vlan and tagged vlan on one port at the same time,
12 * though this might be possible using the undocumented PPE.
15 #define RT305X_ESW_REG_FCT0 0x08
16 #define RT305X_ESW_REG_PFC1 0x14
17 #define RT305X_ESW_REG_ATS 0x24
18 #define RT305X_ESW_REG_ATS0 0x28
19 #define RT305X_ESW_REG_ATS1 0x2c
20 #define RT305X_ESW_REG_ATS2 0x30
21 #define RT305X_ESW_REG_PVIDC(_n) (0x40 + 4 * (_n))
22 #define RT305X_ESW_REG_VLANI(_n) (0x50 + 4 * (_n))
23 #define RT305X_ESW_REG_VMSC(_n) (0x70 + 4 * (_n))
24 #define RT305X_ESW_REG_POA 0x80
25 #define RT305X_ESW_REG_FPA 0x84
26 #define RT305X_ESW_REG_SOCPC 0x8c
27 #define RT305X_ESW_REG_POC0 0x90
28 #define RT305X_ESW_REG_POC1 0x94
29 #define RT305X_ESW_REG_POC2 0x98
30 #define RT305X_ESW_REG_SGC 0x9c
31 #define RT305X_ESW_REG_STRT 0xa0
32 #define RT305X_ESW_REG_PCR0 0xc0
33 #define RT305X_ESW_REG_PCR1 0xc4
34 #define RT305X_ESW_REG_FPA2 0xc8
35 #define RT305X_ESW_REG_FCT2 0xcc
36 #define RT305X_ESW_REG_SGC2 0xe4
37 #define RT305X_ESW_REG_P0LED 0xa4
38 #define RT305X_ESW_REG_P1LED 0xa8
39 #define RT305X_ESW_REG_P2LED 0xac
40 #define RT305X_ESW_REG_P3LED 0xb0
41 #define RT305X_ESW_REG_P4LED 0xb4
42 #define RT305X_ESW_REG_P0PC 0xe8
43 #define RT305X_ESW_REG_P1PC 0xec
44 #define RT305X_ESW_REG_P2PC 0xf0
45 #define RT305X_ESW_REG_P3PC 0xf4
46 #define RT305X_ESW_REG_P4PC 0xf8
47 #define RT305X_ESW_REG_P5PC 0xfc
49 #define RT305X_ESW_LED_LINK 0
50 #define RT305X_ESW_LED_100M 1
51 #define RT305X_ESW_LED_DUPLEX 2
52 #define RT305X_ESW_LED_ACTIVITY 3
53 #define RT305X_ESW_LED_COLLISION 4
54 #define RT305X_ESW_LED_LINKACT 5
55 #define RT305X_ESW_LED_DUPLCOLL 6
56 #define RT305X_ESW_LED_10MACT 7
57 #define RT305X_ESW_LED_100MACT 8
58 /* Additional led states not in datasheet: */
59 #define RT305X_ESW_LED_BLINK 10
60 #define RT305X_ESW_LED_ON 12
62 #define RT305X_ESW_LINK_S 25
63 #define RT305X_ESW_DUPLEX_S 9
64 #define RT305X_ESW_SPD_S 0
66 #define RT305X_ESW_PCR0_WT_NWAY_DATA_S 16
67 #define RT305X_ESW_PCR0_WT_PHY_CMD BIT(13)
68 #define RT305X_ESW_PCR0_CPU_PHY_REG_S 8
70 #define RT305X_ESW_PCR1_WT_DONE BIT(0)
72 #define RT305X_ESW_ATS_TIMEOUT (5 * HZ)
73 #define RT305X_ESW_PHY_TIMEOUT (5 * HZ)
75 #define RT305X_ESW_PVIDC_PVID_M 0xfff
76 #define RT305X_ESW_PVIDC_PVID_S 12
78 #define RT305X_ESW_VLANI_VID_M 0xfff
79 #define RT305X_ESW_VLANI_VID_S 12
81 #define RT305X_ESW_VMSC_MSC_M 0xff
82 #define RT305X_ESW_VMSC_MSC_S 8
84 #define RT305X_ESW_SOCPC_DISUN2CPU_S 0
85 #define RT305X_ESW_SOCPC_DISMC2CPU_S 8
86 #define RT305X_ESW_SOCPC_DISBC2CPU_S 16
87 #define RT305X_ESW_SOCPC_CRC_PADDING BIT(25)
89 #define RT305X_ESW_POC0_EN_BP_S 0
90 #define RT305X_ESW_POC0_EN_FC_S 8
91 #define RT305X_ESW_POC0_DIS_RMC2CPU_S 16
92 #define RT305X_ESW_POC0_DIS_PORT_M 0x7f
93 #define RT305X_ESW_POC0_DIS_PORT_S 23
95 #define RT305X_ESW_POC2_UNTAG_EN_M 0xff
96 #define RT305X_ESW_POC2_UNTAG_EN_S 0
97 #define RT305X_ESW_POC2_ENAGING_S 8
98 #define RT305X_ESW_POC2_DIS_UC_PAUSE_S 16
100 #define RT305X_ESW_SGC2_DOUBLE_TAG_M 0x7f
101 #define RT305X_ESW_SGC2_DOUBLE_TAG_S 0
102 #define RT305X_ESW_SGC2_LAN_PMAP_M 0x3f
103 #define RT305X_ESW_SGC2_LAN_PMAP_S 24
105 #define RT305X_ESW_PFC1_EN_VLAN_M 0xff
106 #define RT305X_ESW_PFC1_EN_VLAN_S 16
107 #define RT305X_ESW_PFC1_EN_TOS_S 24
109 #define RT305X_ESW_VLAN_NONE 0xfff
111 #define RT305X_ESW_PORT0 0
112 #define RT305X_ESW_PORT1 1
113 #define RT305X_ESW_PORT2 2
114 #define RT305X_ESW_PORT3 3
115 #define RT305X_ESW_PORT4 4
116 #define RT305X_ESW_PORT5 5
117 #define RT305X_ESW_PORT6 6
119 #define RT305X_ESW_PORTS_NONE 0
121 #define RT305X_ESW_PMAP_LLLLLL 0x3f
122 #define RT305X_ESW_PMAP_LLLLWL 0x2f
123 #define RT305X_ESW_PMAP_WLLLLL 0x3e
125 #define RT305X_ESW_PORTS_INTERNAL \
126 (BIT(RT305X_ESW_PORT0) | BIT(RT305X_ESW_PORT1) | \
127 BIT(RT305X_ESW_PORT2) | BIT(RT305X_ESW_PORT3) | \
128 BIT(RT305X_ESW_PORT4))
130 #define RT305X_ESW_PORTS_NOCPU \
131 (RT305X_ESW_PORTS_INTERNAL | BIT(RT305X_ESW_PORT5))
133 #define RT305X_ESW_PORTS_CPU BIT(RT305X_ESW_PORT6)
135 #define RT305X_ESW_PORTS_ALL \
136 (RT305X_ESW_PORTS_NOCPU | RT305X_ESW_PORTS_CPU)
138 #define RT305X_ESW_NUM_VLANS 16
139 #define RT305X_ESW_NUM_VIDS 4096
140 #define RT305X_ESW_NUM_PORTS 7
141 #define RT305X_ESW_NUM_LANWAN 6
142 #define RT305X_ESW_NUM_LEDS 5
145 /* Global attributes. */
146 RT305X_ESW_ATTR_ENABLE_VLAN
,
147 RT305X_ESW_ATTR_ALT_VLAN_DISABLE
,
148 /* Port attributes. */
149 RT305X_ESW_ATTR_PORT_DISABLE
,
150 RT305X_ESW_ATTR_PORT_DOUBLETAG
,
151 RT305X_ESW_ATTR_PORT_UNTAG
,
152 RT305X_ESW_ATTR_PORT_LED
,
153 RT305X_ESW_ATTR_PORT_LAN
,
154 RT305X_ESW_ATTR_PORT_RECV_BAD
,
155 RT305X_ESW_ATTR_PORT_RECV_GOOD
,
158 struct rt305x_esw_port
{
166 struct rt305x_esw_vlan
{
173 struct rt305x_esw_platform_data
*pdata
;
174 /* Protects against concurrent register rmw operations. */
175 spinlock_t reg_rw_lock
;
177 struct switch_dev swdev
;
178 bool global_vlan_enable
;
179 bool alt_vlan_disable
;
180 struct rt305x_esw_vlan vlans
[RT305X_ESW_NUM_VLANS
];
181 struct rt305x_esw_port ports
[RT305X_ESW_NUM_PORTS
];
186 rt305x_esw_wr(struct rt305x_esw
*esw
, u32 val
, unsigned reg
)
188 __raw_writel(val
, esw
->base
+ reg
);
192 rt305x_esw_rr(struct rt305x_esw
*esw
, unsigned reg
)
194 return __raw_readl(esw
->base
+ reg
);
198 rt305x_esw_rmw_raw(struct rt305x_esw
*esw
, unsigned reg
, unsigned long mask
,
203 t
= __raw_readl(esw
->base
+ reg
) & ~mask
;
204 __raw_writel(t
| val
, esw
->base
+ reg
);
208 rt305x_esw_rmw(struct rt305x_esw
*esw
, unsigned reg
, unsigned long mask
,
213 spin_lock_irqsave(&esw
->reg_rw_lock
, flags
);
214 rt305x_esw_rmw_raw(esw
, reg
, mask
, val
);
215 spin_unlock_irqrestore(&esw
->reg_rw_lock
, flags
);
219 rt305x_mii_write(struct rt305x_esw
*esw
, u32 phy_addr
, u32 phy_register
,
222 unsigned long t_start
= jiffies
;
226 if (!(rt305x_esw_rr(esw
, RT305X_ESW_REG_PCR1
) &
227 RT305X_ESW_PCR1_WT_DONE
))
229 if (time_after(jiffies
, t_start
+ RT305X_ESW_PHY_TIMEOUT
)) {
235 write_data
&= 0xffff;
237 (write_data
<< RT305X_ESW_PCR0_WT_NWAY_DATA_S
) |
238 (phy_register
<< RT305X_ESW_PCR0_CPU_PHY_REG_S
) |
239 (phy_addr
) | RT305X_ESW_PCR0_WT_PHY_CMD
,
240 RT305X_ESW_REG_PCR0
);
244 if (rt305x_esw_rr(esw
, RT305X_ESW_REG_PCR1
) &
245 RT305X_ESW_PCR1_WT_DONE
)
248 if (time_after(jiffies
, t_start
+ RT305X_ESW_PHY_TIMEOUT
)) {
255 printk(KERN_ERR
"ramips_eth: MDIO timeout\n");
260 rt305x_esw_get_vlan_id(struct rt305x_esw
*esw
, unsigned vlan
)
265 s
= RT305X_ESW_VLANI_VID_S
* (vlan
% 2);
266 val
= rt305x_esw_rr(esw
, RT305X_ESW_REG_VLANI(vlan
/ 2));
267 val
= (val
>> s
) & RT305X_ESW_VLANI_VID_M
;
273 rt305x_esw_set_vlan_id(struct rt305x_esw
*esw
, unsigned vlan
, unsigned vid
)
277 s
= RT305X_ESW_VLANI_VID_S
* (vlan
% 2);
279 RT305X_ESW_REG_VLANI(vlan
/ 2),
280 RT305X_ESW_VLANI_VID_M
<< s
,
281 (vid
& RT305X_ESW_VLANI_VID_M
) << s
);
285 rt305x_esw_get_pvid(struct rt305x_esw
*esw
, unsigned port
)
289 s
= RT305X_ESW_PVIDC_PVID_S
* (port
% 2);
290 val
= rt305x_esw_rr(esw
, RT305X_ESW_REG_PVIDC(port
/ 2));
291 return (val
>> s
) & RT305X_ESW_PVIDC_PVID_M
;
295 rt305x_esw_set_pvid(struct rt305x_esw
*esw
, unsigned port
, unsigned pvid
)
299 s
= RT305X_ESW_PVIDC_PVID_S
* (port
% 2);
301 RT305X_ESW_REG_PVIDC(port
/ 2),
302 RT305X_ESW_PVIDC_PVID_M
<< s
,
303 (pvid
& RT305X_ESW_PVIDC_PVID_M
) << s
);
307 rt305x_esw_get_vmsc(struct rt305x_esw
*esw
, unsigned vlan
)
311 s
= RT305X_ESW_VMSC_MSC_S
* (vlan
% 4);
312 val
= rt305x_esw_rr(esw
, RT305X_ESW_REG_VMSC(vlan
/ 4));
313 val
= (val
>> s
) & RT305X_ESW_VMSC_MSC_M
;
319 rt305x_esw_set_vmsc(struct rt305x_esw
*esw
, unsigned vlan
, unsigned msc
)
323 s
= RT305X_ESW_VMSC_MSC_S
* (vlan
% 4);
325 RT305X_ESW_REG_VMSC(vlan
/ 4),
326 RT305X_ESW_VMSC_MSC_M
<< s
,
327 (msc
& RT305X_ESW_VMSC_MSC_M
) << s
);
331 rt305x_esw_get_port_disable(struct rt305x_esw
*esw
)
334 reg
= rt305x_esw_rr(esw
, RT305X_ESW_REG_POC0
);
335 return (reg
>> RT305X_ESW_POC0_DIS_PORT_S
) &
336 RT305X_ESW_POC0_DIS_PORT_M
;
340 rt305x_esw_set_port_disable(struct rt305x_esw
*esw
, unsigned disable_mask
)
343 unsigned enable_mask
;
347 old_mask
= rt305x_esw_get_port_disable(esw
);
348 changed
= old_mask
^ disable_mask
;
349 enable_mask
= old_mask
& disable_mask
;
351 /* enable before writing to MII */
352 rt305x_esw_rmw(esw
, RT305X_ESW_REG_POC0
,
353 (RT305X_ESW_POC0_DIS_PORT_M
<<
354 RT305X_ESW_POC0_DIS_PORT_S
),
355 enable_mask
<< RT305X_ESW_POC0_DIS_PORT_S
);
357 for (i
= 0; i
< RT305X_ESW_NUM_LEDS
; i
++) {
358 if (!(changed
& (1 << i
)))
360 if (disable_mask
& (1 << i
)) {
362 rt305x_mii_write(esw
, i
, MII_BMCR
,
366 rt305x_mii_write(esw
, i
, MII_BMCR
,
374 /* disable after writing to MII */
375 rt305x_esw_rmw(esw
, RT305X_ESW_REG_POC0
,
376 (RT305X_ESW_POC0_DIS_PORT_M
<<
377 RT305X_ESW_POC0_DIS_PORT_S
),
378 disable_mask
<< RT305X_ESW_POC0_DIS_PORT_S
);
382 rt305x_esw_apply_config(struct switch_dev
*dev
);
385 rt305x_esw_hw_init(struct rt305x_esw
*esw
)
389 u8 port_map
= RT305X_ESW_PMAP_LLLLLL
;
391 /* vodoo from original driver */
392 rt305x_esw_wr(esw
, 0xC8A07850, RT305X_ESW_REG_FCT0
);
393 rt305x_esw_wr(esw
, 0x00000000, RT305X_ESW_REG_SGC2
);
394 /* Port priority 1 for all ports, vlan enabled. */
395 rt305x_esw_wr(esw
, 0x00005555 |
396 (RT305X_ESW_PORTS_ALL
<< RT305X_ESW_PFC1_EN_VLAN_S
),
397 RT305X_ESW_REG_PFC1
);
399 /* Enable Back Pressure, and Flow Control */
401 ((RT305X_ESW_PORTS_ALL
<< RT305X_ESW_POC0_EN_BP_S
) |
402 (RT305X_ESW_PORTS_ALL
<< RT305X_ESW_POC0_EN_FC_S
)),
403 RT305X_ESW_REG_POC0
);
405 /* Enable Aging, and VLAN TAG removal */
407 ((RT305X_ESW_PORTS_ALL
<< RT305X_ESW_POC2_ENAGING_S
) |
408 (RT305X_ESW_PORTS_NOCPU
<< RT305X_ESW_POC2_UNTAG_EN_S
)),
409 RT305X_ESW_REG_POC2
);
411 rt305x_esw_wr(esw
, esw
->pdata
->reg_initval_fct2
, RT305X_ESW_REG_FCT2
);
414 * 300s aging timer, max packet len 1536, broadcast storm prevention
415 * disabled, disable collision abort, mac xor48 hash, 10 packet back
416 * pressure jam, GMII disable was_transmit, back pressure disabled,
417 * 30ms led flash, unmatched IGMP as broadcast, rmc tb fault to all
420 rt305x_esw_wr(esw
, 0x0008a301, RT305X_ESW_REG_SGC
);
422 /* Setup SoC Port control register */
424 (RT305X_ESW_SOCPC_CRC_PADDING
|
425 (RT305X_ESW_PORTS_CPU
<< RT305X_ESW_SOCPC_DISUN2CPU_S
) |
426 (RT305X_ESW_PORTS_CPU
<< RT305X_ESW_SOCPC_DISMC2CPU_S
) |
427 (RT305X_ESW_PORTS_CPU
<< RT305X_ESW_SOCPC_DISBC2CPU_S
)),
428 RT305X_ESW_REG_SOCPC
);
430 rt305x_esw_wr(esw
, esw
->pdata
->reg_initval_fpa2
, RT305X_ESW_REG_FPA2
);
431 rt305x_esw_wr(esw
, 0x00000000, RT305X_ESW_REG_FPA
);
433 /* Force Link/Activity on ports */
434 rt305x_esw_wr(esw
, 0x00000005, RT305X_ESW_REG_P0LED
);
435 rt305x_esw_wr(esw
, 0x00000005, RT305X_ESW_REG_P1LED
);
436 rt305x_esw_wr(esw
, 0x00000005, RT305X_ESW_REG_P2LED
);
437 rt305x_esw_wr(esw
, 0x00000005, RT305X_ESW_REG_P3LED
);
438 rt305x_esw_wr(esw
, 0x00000005, RT305X_ESW_REG_P4LED
);
440 /* Copy disabled port configuration from bootloader setup */
441 port_disable
= rt305x_esw_get_port_disable(esw
);
442 for (i
= 0; i
< 6; i
++)
443 esw
->ports
[i
].disable
= (port_disable
& (1 << i
)) != 0;
445 rt305x_mii_write(esw
, 0, 31, 0x8000);
446 for (i
= 0; i
< 5; i
++) {
447 if (esw
->ports
[i
].disable
) {
448 rt305x_mii_write(esw
, i
, MII_BMCR
, BMCR_PDOWN
);
450 rt305x_mii_write(esw
, i
, MII_BMCR
,
455 /* TX10 waveform coefficient */
456 rt305x_mii_write(esw
, i
, 26, 0x1601);
457 /* TX100/TX10 AD/DA current bias */
458 rt305x_mii_write(esw
, i
, 29, 0x7058);
459 /* TX100 slew rate control */
460 rt305x_mii_write(esw
, i
, 30, 0x0018);
464 /* select global register */
465 rt305x_mii_write(esw
, 0, 31, 0x0);
466 /* tune TP_IDL tail and head waveform */
467 rt305x_mii_write(esw
, 0, 22, 0x052f);
468 /* set TX10 signal amplitude threshold to minimum */
469 rt305x_mii_write(esw
, 0, 17, 0x0fe0);
470 /* set squelch amplitude to higher threshold */
471 rt305x_mii_write(esw
, 0, 18, 0x40ba);
472 /* longer TP_IDL tail length */
473 rt305x_mii_write(esw
, 0, 14, 0x65);
474 /* select local register */
475 rt305x_mii_write(esw
, 0, 31, 0x8000);
477 switch (esw
->pdata
->vlan_config
) {
478 case RT305X_ESW_VLAN_CONFIG_NONE
:
479 port_map
= RT305X_ESW_PMAP_LLLLLL
;
481 case RT305X_ESW_VLAN_CONFIG_LLLLW
:
482 port_map
= RT305X_ESW_PMAP_LLLLWL
;
484 case RT305X_ESW_VLAN_CONFIG_WLLLL
:
485 port_map
= RT305X_ESW_PMAP_WLLLLL
;
492 * Unused HW feature, but still nice to be consistent here...
493 * This is also exported to userspace ('lan' attribute) so it's
494 * conveniently usable to decide which ports go into the wan vlan by
497 rt305x_esw_rmw(esw
, RT305X_ESW_REG_SGC2
,
498 RT305X_ESW_SGC2_LAN_PMAP_M
<< RT305X_ESW_SGC2_LAN_PMAP_S
,
499 port_map
<< RT305X_ESW_SGC2_LAN_PMAP_S
);
501 /* Apply the empty config. */
502 rt305x_esw_apply_config(&esw
->swdev
);
506 rt305x_esw_apply_config(struct switch_dev
*dev
)
508 struct rt305x_esw
*esw
= container_of(dev
, struct rt305x_esw
, swdev
);
515 for (i
= 0; i
< RT305X_ESW_NUM_VLANS
; i
++) {
517 if (esw
->global_vlan_enable
) {
518 vid
= esw
->vlans
[i
].vid
;
519 vmsc
= esw
->vlans
[i
].ports
;
521 vid
= RT305X_ESW_VLAN_NONE
;
522 vmsc
= RT305X_ESW_PORTS_NONE
;
524 rt305x_esw_set_vlan_id(esw
, i
, vid
);
525 rt305x_esw_set_vmsc(esw
, i
, vmsc
);
528 for (i
= 0; i
< RT305X_ESW_NUM_PORTS
; i
++) {
530 disable
|= esw
->ports
[i
].disable
<< i
;
531 if (esw
->global_vlan_enable
) {
532 doubletag
|= esw
->ports
[i
].doubletag
<< i
;
534 untag
|= esw
->ports
[i
].untag
<< i
;
535 pvid
= esw
->ports
[i
].pvid
;
537 int x
= esw
->alt_vlan_disable
? 1 : 0;
543 rt305x_esw_set_pvid(esw
, i
, pvid
);
544 if (i
< RT305X_ESW_NUM_LEDS
)
545 rt305x_esw_wr(esw
, esw
->ports
[i
].led
,
546 RT305X_ESW_REG_P0LED
+ 4*i
);
549 rt305x_esw_set_port_disable(esw
, disable
);
550 rt305x_esw_rmw(esw
, RT305X_ESW_REG_SGC2
,
551 (RT305X_ESW_SGC2_DOUBLE_TAG_M
<<
552 RT305X_ESW_SGC2_DOUBLE_TAG_S
),
553 doubletag
<< RT305X_ESW_SGC2_DOUBLE_TAG_S
);
554 rt305x_esw_rmw(esw
, RT305X_ESW_REG_PFC1
,
555 RT305X_ESW_PFC1_EN_VLAN_M
<< RT305X_ESW_PFC1_EN_VLAN_S
,
556 en_vlan
<< RT305X_ESW_PFC1_EN_VLAN_S
);
557 rt305x_esw_rmw(esw
, RT305X_ESW_REG_POC2
,
558 RT305X_ESW_POC2_UNTAG_EN_M
<< RT305X_ESW_POC2_UNTAG_EN_S
,
559 untag
<< RT305X_ESW_POC2_UNTAG_EN_S
);
561 if (!esw
->global_vlan_enable
) {
563 * Still need to put all ports into vlan 0 or they'll be
565 * NOTE: vlan 0 is special, no vlan tag is prepended
567 rt305x_esw_set_vlan_id(esw
, 0, 0);
568 rt305x_esw_set_vmsc(esw
, 0, RT305X_ESW_PORTS_ALL
);
575 rt305x_esw_reset_switch(struct switch_dev
*dev
)
577 struct rt305x_esw
*esw
= container_of(dev
, struct rt305x_esw
, swdev
);
578 esw
->global_vlan_enable
= 0;
579 memset(esw
->ports
, 0, sizeof(esw
->ports
));
580 memset(esw
->vlans
, 0, sizeof(esw
->vlans
));
581 rt305x_esw_hw_init(esw
);
587 rt305x_esw_get_vlan_enable(struct switch_dev
*dev
,
588 const struct switch_attr
*attr
,
589 struct switch_val
*val
)
591 struct rt305x_esw
*esw
= container_of(dev
, struct rt305x_esw
, swdev
);
593 val
->value
.i
= esw
->global_vlan_enable
;
599 rt305x_esw_set_vlan_enable(struct switch_dev
*dev
,
600 const struct switch_attr
*attr
,
601 struct switch_val
*val
)
603 struct rt305x_esw
*esw
= container_of(dev
, struct rt305x_esw
, swdev
);
605 esw
->global_vlan_enable
= val
->value
.i
!= 0;
611 rt305x_esw_get_alt_vlan_disable(struct switch_dev
*dev
,
612 const struct switch_attr
*attr
,
613 struct switch_val
*val
)
615 struct rt305x_esw
*esw
= container_of(dev
, struct rt305x_esw
, swdev
);
617 val
->value
.i
= esw
->alt_vlan_disable
;
623 rt305x_esw_set_alt_vlan_disable(struct switch_dev
*dev
,
624 const struct switch_attr
*attr
,
625 struct switch_val
*val
)
627 struct rt305x_esw
*esw
= container_of(dev
, struct rt305x_esw
, swdev
);
629 esw
->alt_vlan_disable
= val
->value
.i
!= 0;
635 rt305x_esw_get_port_link(struct switch_dev
*dev
,
637 struct switch_port_link
*link
)
639 struct rt305x_esw
*esw
= container_of(dev
, struct rt305x_esw
, swdev
);
642 if (port
< 0 || port
>= RT305X_ESW_NUM_PORTS
)
645 poa
= rt305x_esw_rr(esw
, RT305X_ESW_REG_POA
) >> port
;
647 link
->link
= (poa
>> RT305X_ESW_LINK_S
) & 1;
648 link
->duplex
= (poa
>> RT305X_ESW_DUPLEX_S
) & 1;
649 if (port
< RT305X_ESW_NUM_LEDS
) {
650 speed
= (poa
>> RT305X_ESW_SPD_S
) & 1;
652 if (port
== RT305X_ESW_NUM_PORTS
- 1)
654 speed
= (poa
>> RT305X_ESW_SPD_S
) & 3;
658 link
->speed
= SWITCH_PORT_SPEED_10
;
661 link
->speed
= SWITCH_PORT_SPEED_100
;
664 case 3: /* forced gige speed can be 2 or 3 */
665 link
->speed
= SWITCH_PORT_SPEED_1000
;
668 link
->speed
= SWITCH_PORT_SPEED_UNKNOWN
;
676 rt305x_esw_get_port_bool(struct switch_dev
*dev
,
677 const struct switch_attr
*attr
,
678 struct switch_val
*val
)
680 struct rt305x_esw
*esw
= container_of(dev
, struct rt305x_esw
, swdev
);
681 int idx
= val
->port_vlan
;
684 if (idx
< 0 || idx
>= RT305X_ESW_NUM_PORTS
)
688 case RT305X_ESW_ATTR_PORT_DISABLE
:
689 reg
= RT305X_ESW_REG_POC0
;
690 shift
= RT305X_ESW_POC0_DIS_PORT_S
;
692 case RT305X_ESW_ATTR_PORT_DOUBLETAG
:
693 reg
= RT305X_ESW_REG_SGC2
;
694 shift
= RT305X_ESW_SGC2_DOUBLE_TAG_S
;
696 case RT305X_ESW_ATTR_PORT_UNTAG
:
697 reg
= RT305X_ESW_REG_POC2
;
698 shift
= RT305X_ESW_POC2_UNTAG_EN_S
;
700 case RT305X_ESW_ATTR_PORT_LAN
:
701 reg
= RT305X_ESW_REG_SGC2
;
702 shift
= RT305X_ESW_SGC2_LAN_PMAP_S
;
703 if (idx
>= RT305X_ESW_NUM_LANWAN
)
710 x
= rt305x_esw_rr(esw
, reg
);
711 val
->value
.i
= (x
>> (idx
+ shift
)) & 1;
717 rt305x_esw_set_port_bool(struct switch_dev
*dev
,
718 const struct switch_attr
*attr
,
719 struct switch_val
*val
)
721 struct rt305x_esw
*esw
= container_of(dev
, struct rt305x_esw
, swdev
);
722 int idx
= val
->port_vlan
;
724 if (idx
< 0 || idx
>= RT305X_ESW_NUM_PORTS
||
725 val
->value
.i
< 0 || val
->value
.i
> 1)
729 case RT305X_ESW_ATTR_PORT_DISABLE
:
730 esw
->ports
[idx
].disable
= val
->value
.i
;
732 case RT305X_ESW_ATTR_PORT_DOUBLETAG
:
733 esw
->ports
[idx
].doubletag
= val
->value
.i
;
735 case RT305X_ESW_ATTR_PORT_UNTAG
:
736 esw
->ports
[idx
].untag
= val
->value
.i
;
746 rt305x_esw_get_port_recv_badgood(struct switch_dev
*dev
,
747 const struct switch_attr
*attr
,
748 struct switch_val
*val
)
750 struct rt305x_esw
*esw
= container_of(dev
, struct rt305x_esw
, swdev
);
751 int idx
= val
->port_vlan
;
752 int shift
= attr
->id
== RT305X_ESW_ATTR_PORT_RECV_GOOD
? 0 : 16;
754 if (idx
< 0 || idx
>= RT305X_ESW_NUM_LANWAN
)
757 val
->value
.i
= rt305x_esw_rr(esw
, RT305X_ESW_REG_P0PC
+ 4*idx
) >> shift
;
763 rt305x_esw_get_port_led(struct switch_dev
*dev
,
764 const struct switch_attr
*attr
,
765 struct switch_val
*val
)
767 struct rt305x_esw
*esw
= container_of(dev
, struct rt305x_esw
, swdev
);
768 int idx
= val
->port_vlan
;
770 if (idx
< 0 || idx
>= RT305X_ESW_NUM_PORTS
||
771 idx
>= RT305X_ESW_NUM_LEDS
)
774 val
->value
.i
= rt305x_esw_rr(esw
, RT305X_ESW_REG_P0LED
+ 4*idx
);
780 rt305x_esw_set_port_led(struct switch_dev
*dev
,
781 const struct switch_attr
*attr
,
782 struct switch_val
*val
)
784 struct rt305x_esw
*esw
= container_of(dev
, struct rt305x_esw
, swdev
);
785 int idx
= val
->port_vlan
;
787 if (idx
< 0 || idx
>= RT305X_ESW_NUM_LEDS
)
790 esw
->ports
[idx
].led
= val
->value
.i
;
796 rt305x_esw_get_port_pvid(struct switch_dev
*dev
, int port
, int *val
)
798 struct rt305x_esw
*esw
= container_of(dev
, struct rt305x_esw
, swdev
);
800 if (port
>= RT305X_ESW_NUM_PORTS
)
803 *val
= rt305x_esw_get_pvid(esw
, port
);
809 rt305x_esw_set_port_pvid(struct switch_dev
*dev
, int port
, int val
)
811 struct rt305x_esw
*esw
= container_of(dev
, struct rt305x_esw
, swdev
);
813 if (port
>= RT305X_ESW_NUM_PORTS
)
816 esw
->ports
[port
].pvid
= val
;
822 rt305x_esw_get_vlan_ports(struct switch_dev
*dev
, struct switch_val
*val
)
824 struct rt305x_esw
*esw
= container_of(dev
, struct rt305x_esw
, swdev
);
831 if (val
->port_vlan
< 0 || val
->port_vlan
>= RT305X_ESW_NUM_VIDS
)
835 for (i
= 0; i
< RT305X_ESW_NUM_VLANS
; i
++) {
836 if (rt305x_esw_get_vlan_id(esw
, i
) == val
->port_vlan
&&
837 rt305x_esw_get_vmsc(esw
, i
) != RT305X_ESW_PORTS_NONE
) {
846 vmsc
= rt305x_esw_get_vmsc(esw
, vlan_idx
);
847 poc2
= rt305x_esw_rr(esw
, RT305X_ESW_REG_POC2
);
849 for (i
= 0; i
< RT305X_ESW_NUM_PORTS
; i
++) {
850 struct switch_port
*p
;
851 int port_mask
= 1 << i
;
853 if (!(vmsc
& port_mask
))
856 p
= &val
->value
.ports
[val
->len
++];
858 if (poc2
& (port_mask
<< RT305X_ESW_POC2_UNTAG_EN_S
))
861 p
->flags
= 1 << SWITCH_PORT_FLAG_TAGGED
;
868 rt305x_esw_set_vlan_ports(struct switch_dev
*dev
, struct switch_val
*val
)
870 struct rt305x_esw
*esw
= container_of(dev
, struct rt305x_esw
, swdev
);
875 if (val
->port_vlan
< 0 || val
->port_vlan
>= RT305X_ESW_NUM_VIDS
||
876 val
->len
> RT305X_ESW_NUM_PORTS
)
879 /* one of the already defined vlans? */
880 for (i
= 0; i
< RT305X_ESW_NUM_VLANS
; i
++) {
881 if (esw
->vlans
[i
].vid
== val
->port_vlan
&&
882 esw
->vlans
[i
].ports
!= RT305X_ESW_PORTS_NONE
) {
888 /* select a free slot */
889 for (i
= 0; vlan_idx
== -1 && i
< RT305X_ESW_NUM_VLANS
; i
++) {
890 if (esw
->vlans
[i
].ports
== RT305X_ESW_PORTS_NONE
)
894 /* bail if all slots are in use */
898 ports
= RT305X_ESW_PORTS_NONE
;
899 for (i
= 0; i
< val
->len
; i
++) {
900 struct switch_port
*p
= &val
->value
.ports
[i
];
901 int port_mask
= 1 << p
->id
;
902 bool untagged
= !(p
->flags
& (1 << SWITCH_PORT_FLAG_TAGGED
));
904 if (p
->id
>= RT305X_ESW_NUM_PORTS
)
908 esw
->ports
[p
->id
].untag
= untagged
;
910 esw
->vlans
[vlan_idx
].ports
= ports
;
911 if (ports
== RT305X_ESW_PORTS_NONE
)
912 esw
->vlans
[vlan_idx
].vid
= RT305X_ESW_VLAN_NONE
;
914 esw
->vlans
[vlan_idx
].vid
= val
->port_vlan
;
919 static const struct switch_attr rt305x_esw_global
[] = {
921 .type
= SWITCH_TYPE_INT
,
922 .name
= "enable_vlan",
923 .description
= "VLAN mode (1:enabled)",
925 .id
= RT305X_ESW_ATTR_ENABLE_VLAN
,
926 .get
= rt305x_esw_get_vlan_enable
,
927 .set
= rt305x_esw_set_vlan_enable
,
930 .type
= SWITCH_TYPE_INT
,
931 .name
= "alternate_vlan_disable",
932 .description
= "Use en_vlan instead of doubletag to disable"
935 .id
= RT305X_ESW_ATTR_ALT_VLAN_DISABLE
,
936 .get
= rt305x_esw_get_alt_vlan_disable
,
937 .set
= rt305x_esw_set_alt_vlan_disable
,
941 static const struct switch_attr rt305x_esw_port
[] = {
943 .type
= SWITCH_TYPE_INT
,
945 .description
= "Port state (1:disabled)",
947 .id
= RT305X_ESW_ATTR_PORT_DISABLE
,
948 .get
= rt305x_esw_get_port_bool
,
949 .set
= rt305x_esw_set_port_bool
,
952 .type
= SWITCH_TYPE_INT
,
954 .description
= "Double tagging for incoming vlan packets "
957 .id
= RT305X_ESW_ATTR_PORT_DOUBLETAG
,
958 .get
= rt305x_esw_get_port_bool
,
959 .set
= rt305x_esw_set_port_bool
,
962 .type
= SWITCH_TYPE_INT
,
964 .description
= "Untag (1:strip outgoing vlan tag)",
966 .id
= RT305X_ESW_ATTR_PORT_UNTAG
,
967 .get
= rt305x_esw_get_port_bool
,
968 .set
= rt305x_esw_set_port_bool
,
971 .type
= SWITCH_TYPE_INT
,
973 .description
= "LED mode (0:link, 1:100m, 2:duplex, 3:activity,"
974 " 4:collision, 5:linkact, 6:duplcoll, 7:10mact,"
975 " 8:100mact, 10:blink, 12:on)",
977 .id
= RT305X_ESW_ATTR_PORT_LED
,
978 .get
= rt305x_esw_get_port_led
,
979 .set
= rt305x_esw_set_port_led
,
982 .type
= SWITCH_TYPE_INT
,
984 .description
= "HW port group (0:wan, 1:lan)",
986 .id
= RT305X_ESW_ATTR_PORT_LAN
,
987 .get
= rt305x_esw_get_port_bool
,
990 .type
= SWITCH_TYPE_INT
,
992 .description
= "Receive bad packet counter",
993 .id
= RT305X_ESW_ATTR_PORT_RECV_BAD
,
994 .get
= rt305x_esw_get_port_recv_badgood
,
997 .type
= SWITCH_TYPE_INT
,
999 .description
= "Receive good packet counter",
1000 .id
= RT305X_ESW_ATTR_PORT_RECV_GOOD
,
1001 .get
= rt305x_esw_get_port_recv_badgood
,
1005 static const struct switch_attr rt305x_esw_vlan
[] = {
1008 static const struct switch_dev_ops rt305x_esw_ops
= {
1010 .attr
= rt305x_esw_global
,
1011 .n_attr
= ARRAY_SIZE(rt305x_esw_global
),
1014 .attr
= rt305x_esw_port
,
1015 .n_attr
= ARRAY_SIZE(rt305x_esw_port
),
1018 .attr
= rt305x_esw_vlan
,
1019 .n_attr
= ARRAY_SIZE(rt305x_esw_vlan
),
1021 .get_vlan_ports
= rt305x_esw_get_vlan_ports
,
1022 .set_vlan_ports
= rt305x_esw_set_vlan_ports
,
1023 .get_port_pvid
= rt305x_esw_get_port_pvid
,
1024 .set_port_pvid
= rt305x_esw_set_port_pvid
,
1025 .get_port_link
= rt305x_esw_get_port_link
,
1026 .apply_config
= rt305x_esw_apply_config
,
1027 .reset_switch
= rt305x_esw_reset_switch
,
1031 rt305x_esw_probe(struct platform_device
*pdev
)
1033 struct rt305x_esw_platform_data
*pdata
;
1034 struct rt305x_esw
*esw
;
1035 struct switch_dev
*swdev
;
1036 struct resource
*res
;
1039 pdata
= pdev
->dev
.platform_data
;
1043 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
1045 dev_err(&pdev
->dev
, "no memory resource found\n");
1049 esw
= kzalloc(sizeof(struct rt305x_esw
), GFP_KERNEL
);
1051 dev_err(&pdev
->dev
, "no memory for private data\n");
1055 esw
->base
= ioremap(res
->start
, resource_size(res
));
1057 dev_err(&pdev
->dev
, "ioremap failed\n");
1062 swdev
= &esw
->swdev
;
1063 swdev
->name
= "rt305x-esw";
1064 swdev
->alias
= "rt305x";
1065 swdev
->cpu_port
= RT305X_ESW_PORT6
;
1066 swdev
->ports
= RT305X_ESW_NUM_PORTS
;
1067 swdev
->vlans
= RT305X_ESW_NUM_VIDS
;
1068 swdev
->ops
= &rt305x_esw_ops
;
1070 err
= register_switch(swdev
, NULL
);
1072 dev_err(&pdev
->dev
, "register_switch failed\n");
1076 platform_set_drvdata(pdev
, esw
);
1079 spin_lock_init(&esw
->reg_rw_lock
);
1080 rt305x_esw_hw_init(esw
);
1092 rt305x_esw_remove(struct platform_device
*pdev
)
1094 struct rt305x_esw
*esw
;
1096 esw
= platform_get_drvdata(pdev
);
1098 unregister_switch(&esw
->swdev
);
1099 platform_set_drvdata(pdev
, NULL
);
1107 static struct platform_driver rt305x_esw_driver
= {
1108 .probe
= rt305x_esw_probe
,
1109 .remove
= rt305x_esw_remove
,
1111 .name
= "rt305x-esw",
1112 .owner
= THIS_MODULE
,
1117 rt305x_esw_init(void)
1119 return platform_driver_register(&rt305x_esw_driver
);
1123 rt305x_esw_exit(void)
1125 platform_driver_unregister(&rt305x_esw_driver
);