1 #include <linux/ioport.h>
2 #include <linux/switch.h>
4 #include <rt305x_regs.h>
5 #include <rt305x_esw_platform.h>
8 * HW limitations for this switch:
9 * - No large frame support (PKT_MAX_LEN at most 1536)
10 * - Can't have untagged vlan and tagged vlan on one port at the same time,
11 * though this might be possible using the undocumented PPE.
14 #define RT305X_ESW_REG_FCT0 0x08
15 #define RT305X_ESW_REG_PFC1 0x14
16 #define RT305X_ESW_REG_ATS 0x24
17 #define RT305X_ESW_REG_ATS0 0x28
18 #define RT305X_ESW_REG_ATS1 0x2c
19 #define RT305X_ESW_REG_ATS2 0x30
20 #define RT305X_ESW_REG_PVIDC(_n) (0x40 + 4 * (_n))
21 #define RT305X_ESW_REG_VLANI(_n) (0x50 + 4 * (_n))
22 #define RT305X_ESW_REG_VMSC(_n) (0x70 + 4 * (_n))
23 #define RT305X_ESW_REG_POA 0x80
24 #define RT305X_ESW_REG_FPA 0x84
25 #define RT305X_ESW_REG_SOCPC 0x8c
26 #define RT305X_ESW_REG_POC0 0x90
27 #define RT305X_ESW_REG_POC1 0x94
28 #define RT305X_ESW_REG_POC2 0x98
29 #define RT305X_ESW_REG_SGC 0x9c
30 #define RT305X_ESW_REG_STRT 0xa0
31 #define RT305X_ESW_REG_PCR0 0xc0
32 #define RT305X_ESW_REG_PCR1 0xc4
33 #define RT305X_ESW_REG_FPA2 0xc8
34 #define RT305X_ESW_REG_FCT2 0xcc
35 #define RT305X_ESW_REG_SGC2 0xe4
36 #define RT305X_ESW_REG_P0LED 0xa4
37 #define RT305X_ESW_REG_P1LED 0xa8
38 #define RT305X_ESW_REG_P2LED 0xac
39 #define RT305X_ESW_REG_P3LED 0xb0
40 #define RT305X_ESW_REG_P4LED 0xb4
41 #define RT305X_ESW_REG_P0PC 0xe8
42 #define RT305X_ESW_REG_P1PC 0xec
43 #define RT305X_ESW_REG_P2PC 0xf0
44 #define RT305X_ESW_REG_P3PC 0xf4
45 #define RT305X_ESW_REG_P4PC 0xf8
46 #define RT305X_ESW_REG_P5PC 0xfc
48 #define RT305X_ESW_LED_LINK 0
49 #define RT305X_ESW_LED_100M 1
50 #define RT305X_ESW_LED_DUPLEX 2
51 #define RT305X_ESW_LED_ACTIVITY 3
52 #define RT305X_ESW_LED_COLLISION 4
53 #define RT305X_ESW_LED_LINKACT 5
54 #define RT305X_ESW_LED_DUPLCOLL 6
55 #define RT305X_ESW_LED_10MACT 7
56 #define RT305X_ESW_LED_100MACT 8
57 /* Additional led states not in datasheet: */
58 #define RT305X_ESW_LED_BLINK 10
59 #define RT305X_ESW_LED_ON 12
61 #define RT305X_ESW_LINK_S 25
62 #define RT305X_ESW_DUPLEX_S 9
63 #define RT305X_ESW_SPD_S 0
65 #define RT305X_ESW_PCR0_WT_NWAY_DATA_S 16
66 #define RT305X_ESW_PCR0_WT_PHY_CMD BIT(13)
67 #define RT305X_ESW_PCR0_CPU_PHY_REG_S 8
69 #define RT305X_ESW_PCR1_WT_DONE BIT(0)
71 #define RT305X_ESW_ATS_TIMEOUT (5 * HZ)
72 #define RT305X_ESW_PHY_TIMEOUT (5 * HZ)
74 #define RT305X_ESW_PVIDC_PVID_M 0xfff
75 #define RT305X_ESW_PVIDC_PVID_S 12
77 #define RT305X_ESW_VLANI_VID_M 0xfff
78 #define RT305X_ESW_VLANI_VID_S 12
80 #define RT305X_ESW_VMSC_MSC_M 0xff
81 #define RT305X_ESW_VMSC_MSC_S 8
83 #define RT305X_ESW_SOCPC_DISUN2CPU_S 0
84 #define RT305X_ESW_SOCPC_DISMC2CPU_S 8
85 #define RT305X_ESW_SOCPC_DISBC2CPU_S 16
86 #define RT305X_ESW_SOCPC_CRC_PADDING BIT(25)
88 #define RT305X_ESW_POC0_EN_BP_S 0
89 #define RT305X_ESW_POC0_EN_FC_S 8
90 #define RT305X_ESW_POC0_DIS_RMC2CPU_S 16
91 #define RT305X_ESW_POC0_DIS_PORT_M 0x7f
92 #define RT305X_ESW_POC0_DIS_PORT_S 23
94 #define RT305X_ESW_POC2_UNTAG_EN_M 0xff
95 #define RT305X_ESW_POC2_UNTAG_EN_S 0
96 #define RT305X_ESW_POC2_ENAGING_S 8
97 #define RT305X_ESW_POC2_DIS_UC_PAUSE_S 16
99 #define RT305X_ESW_SGC2_DOUBLE_TAG_M 0x7f
100 #define RT305X_ESW_SGC2_DOUBLE_TAG_S 0
101 #define RT305X_ESW_SGC2_LAN_PMAP_M 0x3f
102 #define RT305X_ESW_SGC2_LAN_PMAP_S 24
104 #define RT305X_ESW_PFC1_EN_VLAN_M 0xff
105 #define RT305X_ESW_PFC1_EN_VLAN_S 16
106 #define RT305X_ESW_PFC1_EN_TOS_S 24
108 #define RT305X_ESW_VLAN_NONE 0xfff
110 #define RT305X_ESW_PORT0 0
111 #define RT305X_ESW_PORT1 1
112 #define RT305X_ESW_PORT2 2
113 #define RT305X_ESW_PORT3 3
114 #define RT305X_ESW_PORT4 4
115 #define RT305X_ESW_PORT5 5
116 #define RT305X_ESW_PORT6 6
118 #define RT305X_ESW_PORTS_NONE 0
120 #define RT305X_ESW_PMAP_LLLLLL 0x3f
121 #define RT305X_ESW_PMAP_LLLLWL 0x2f
122 #define RT305X_ESW_PMAP_WLLLLL 0x3e
124 #define RT305X_ESW_PORTS_INTERNAL \
125 (BIT(RT305X_ESW_PORT0) | BIT(RT305X_ESW_PORT1) | \
126 BIT(RT305X_ESW_PORT2) | BIT(RT305X_ESW_PORT3) | \
127 BIT(RT305X_ESW_PORT4))
129 #define RT305X_ESW_PORTS_NOCPU \
130 (RT305X_ESW_PORTS_INTERNAL | BIT(RT305X_ESW_PORT5))
132 #define RT305X_ESW_PORTS_CPU BIT(RT305X_ESW_PORT6)
134 #define RT305X_ESW_PORTS_ALL \
135 (RT305X_ESW_PORTS_NOCPU | RT305X_ESW_PORTS_CPU)
137 #define RT305X_ESW_NUM_VLANS 16
138 #define RT305X_ESW_NUM_VIDS 4096
139 #define RT305X_ESW_NUM_PORTS 7
140 #define RT305X_ESW_NUM_LANWAN 6
141 #define RT305X_ESW_NUM_LEDS 5
144 /* Global attributes. */
145 RT305X_ESW_ATTR_ENABLE_VLAN
,
146 RT305X_ESW_ATTR_ALT_VLAN_DISABLE
,
147 /* Port attributes. */
148 RT305X_ESW_ATTR_PORT_DISABLE
,
149 RT305X_ESW_ATTR_PORT_DOUBLETAG
,
150 RT305X_ESW_ATTR_PORT_UNTAG
,
151 RT305X_ESW_ATTR_PORT_LED
,
152 RT305X_ESW_ATTR_PORT_LAN
,
153 RT305X_ESW_ATTR_PORT_RECV_BAD
,
154 RT305X_ESW_ATTR_PORT_RECV_GOOD
,
157 struct rt305x_esw_port
{
165 struct rt305x_esw_vlan
{
172 struct rt305x_esw_platform_data
*pdata
;
173 /* Protects against concurrent register rmw operations. */
174 spinlock_t reg_rw_lock
;
176 struct switch_dev swdev
;
177 bool global_vlan_enable
;
178 bool alt_vlan_disable
;
179 struct rt305x_esw_vlan vlans
[RT305X_ESW_NUM_VLANS
];
180 struct rt305x_esw_port ports
[RT305X_ESW_NUM_PORTS
];
185 rt305x_esw_wr(struct rt305x_esw
*esw
, u32 val
, unsigned reg
)
187 __raw_writel(val
, esw
->base
+ reg
);
191 rt305x_esw_rr(struct rt305x_esw
*esw
, unsigned reg
)
193 return __raw_readl(esw
->base
+ reg
);
197 rt305x_esw_rmw_raw(struct rt305x_esw
*esw
, unsigned reg
, unsigned long mask
,
202 t
= __raw_readl(esw
->base
+ reg
) & ~mask
;
203 __raw_writel(t
| val
, esw
->base
+ reg
);
207 rt305x_esw_rmw(struct rt305x_esw
*esw
, unsigned reg
, unsigned long mask
,
212 spin_lock_irqsave(&esw
->reg_rw_lock
, flags
);
213 rt305x_esw_rmw_raw(esw
, reg
, mask
, val
);
214 spin_unlock_irqrestore(&esw
->reg_rw_lock
, flags
);
218 rt305x_mii_write(struct rt305x_esw
*esw
, u32 phy_addr
, u32 phy_register
,
221 unsigned long t_start
= jiffies
;
225 if (!(rt305x_esw_rr(esw
, RT305X_ESW_REG_PCR1
) &
226 RT305X_ESW_PCR1_WT_DONE
))
228 if (time_after(jiffies
, t_start
+ RT305X_ESW_PHY_TIMEOUT
)) {
234 write_data
&= 0xffff;
236 (write_data
<< RT305X_ESW_PCR0_WT_NWAY_DATA_S
) |
237 (phy_register
<< RT305X_ESW_PCR0_CPU_PHY_REG_S
) |
238 (phy_addr
) | RT305X_ESW_PCR0_WT_PHY_CMD
,
239 RT305X_ESW_REG_PCR0
);
243 if (rt305x_esw_rr(esw
, RT305X_ESW_REG_PCR1
) &
244 RT305X_ESW_PCR1_WT_DONE
)
247 if (time_after(jiffies
, t_start
+ RT305X_ESW_PHY_TIMEOUT
)) {
254 printk(KERN_ERR
"ramips_eth: MDIO timeout\n");
259 rt305x_esw_get_vlan_id(struct rt305x_esw
*esw
, unsigned vlan
)
264 s
= RT305X_ESW_VLANI_VID_S
* (vlan
% 2);
265 val
= rt305x_esw_rr(esw
, RT305X_ESW_REG_VLANI(vlan
/ 2));
266 val
= (val
>> s
) & RT305X_ESW_VLANI_VID_M
;
272 rt305x_esw_set_vlan_id(struct rt305x_esw
*esw
, unsigned vlan
, unsigned vid
)
276 s
= RT305X_ESW_VLANI_VID_S
* (vlan
% 2);
278 RT305X_ESW_REG_VLANI(vlan
/ 2),
279 RT305X_ESW_VLANI_VID_M
<< s
,
280 (vid
& RT305X_ESW_VLANI_VID_M
) << s
);
284 rt305x_esw_get_pvid(struct rt305x_esw
*esw
, unsigned port
)
288 s
= RT305X_ESW_PVIDC_PVID_S
* (port
% 2);
289 val
= rt305x_esw_rr(esw
, RT305X_ESW_REG_PVIDC(port
/ 2));
290 return (val
>> s
) & RT305X_ESW_PVIDC_PVID_M
;
294 rt305x_esw_set_pvid(struct rt305x_esw
*esw
, unsigned port
, unsigned pvid
)
298 s
= RT305X_ESW_PVIDC_PVID_S
* (port
% 2);
300 RT305X_ESW_REG_PVIDC(port
/ 2),
301 RT305X_ESW_PVIDC_PVID_M
<< s
,
302 (pvid
& RT305X_ESW_PVIDC_PVID_M
) << s
);
306 rt305x_esw_get_vmsc(struct rt305x_esw
*esw
, unsigned vlan
)
310 s
= RT305X_ESW_VMSC_MSC_S
* (vlan
% 4);
311 val
= rt305x_esw_rr(esw
, RT305X_ESW_REG_VMSC(vlan
/ 4));
312 val
= (val
>> s
) & RT305X_ESW_VMSC_MSC_M
;
318 rt305x_esw_set_vmsc(struct rt305x_esw
*esw
, unsigned vlan
, unsigned msc
)
322 s
= RT305X_ESW_VMSC_MSC_S
* (vlan
% 4);
324 RT305X_ESW_REG_VMSC(vlan
/ 4),
325 RT305X_ESW_VMSC_MSC_M
<< s
,
326 (msc
& RT305X_ESW_VMSC_MSC_M
) << s
);
330 rt305x_esw_apply_config(struct switch_dev
*dev
);
333 rt305x_esw_hw_init(struct rt305x_esw
*esw
)
336 u8 port_map
= RT305X_ESW_PMAP_LLLLLL
;
338 /* vodoo from original driver */
339 rt305x_esw_wr(esw
, 0xC8A07850, RT305X_ESW_REG_FCT0
);
340 rt305x_esw_wr(esw
, 0x00000000, RT305X_ESW_REG_SGC2
);
341 /* Port priority 1 for all ports, vlan enabled. */
342 rt305x_esw_wr(esw
, 0x00005555 |
343 (RT305X_ESW_PORTS_ALL
<< RT305X_ESW_PFC1_EN_VLAN_S
),
344 RT305X_ESW_REG_PFC1
);
346 /* Enable Back Pressure, and Flow Control */
348 ((RT305X_ESW_PORTS_ALL
<< RT305X_ESW_POC0_EN_BP_S
) |
349 (RT305X_ESW_PORTS_ALL
<< RT305X_ESW_POC0_EN_FC_S
)),
350 RT305X_ESW_REG_POC0
);
352 /* Enable Aging, and VLAN TAG removal */
354 ((RT305X_ESW_PORTS_ALL
<< RT305X_ESW_POC2_ENAGING_S
) |
355 (RT305X_ESW_PORTS_NOCPU
<< RT305X_ESW_POC2_UNTAG_EN_S
)),
356 RT305X_ESW_REG_POC2
);
358 rt305x_esw_wr(esw
, esw
->pdata
->reg_initval_fct2
, RT305X_ESW_REG_FCT2
);
361 * 300s aging timer, max packet len 1536, broadcast storm prevention
362 * disabled, disable collision abort, mac xor48 hash, 10 packet back
363 * pressure jam, GMII disable was_transmit, back pressure disabled,
364 * 30ms led flash, unmatched IGMP as broadcast, rmc tb fault to all
367 rt305x_esw_wr(esw
, 0x0008a301, RT305X_ESW_REG_SGC
);
369 /* Setup SoC Port control register */
371 (RT305X_ESW_SOCPC_CRC_PADDING
|
372 (RT305X_ESW_PORTS_CPU
<< RT305X_ESW_SOCPC_DISUN2CPU_S
) |
373 (RT305X_ESW_PORTS_CPU
<< RT305X_ESW_SOCPC_DISMC2CPU_S
) |
374 (RT305X_ESW_PORTS_CPU
<< RT305X_ESW_SOCPC_DISBC2CPU_S
)),
375 RT305X_ESW_REG_SOCPC
);
377 rt305x_esw_wr(esw
, esw
->pdata
->reg_initval_fpa2
, RT305X_ESW_REG_FPA2
);
378 rt305x_esw_wr(esw
, 0x00000000, RT305X_ESW_REG_FPA
);
380 /* Force Link/Activity on ports */
381 rt305x_esw_wr(esw
, 0x00000005, RT305X_ESW_REG_P0LED
);
382 rt305x_esw_wr(esw
, 0x00000005, RT305X_ESW_REG_P1LED
);
383 rt305x_esw_wr(esw
, 0x00000005, RT305X_ESW_REG_P2LED
);
384 rt305x_esw_wr(esw
, 0x00000005, RT305X_ESW_REG_P3LED
);
385 rt305x_esw_wr(esw
, 0x00000005, RT305X_ESW_REG_P4LED
);
387 rt305x_mii_write(esw
, 0, 31, 0x8000);
388 for (i
= 0; i
< 5; i
++) {
389 /* TX10 waveform coefficient */
390 rt305x_mii_write(esw
, i
, 0, 0x3100);
391 /* TX10 waveform coefficient */
392 rt305x_mii_write(esw
, i
, 26, 0x1601);
393 /* TX100/TX10 AD/DA current bias */
394 rt305x_mii_write(esw
, i
, 29, 0x7058);
395 /* TX100 slew rate control */
396 rt305x_mii_write(esw
, i
, 30, 0x0018);
400 /* select global register */
401 rt305x_mii_write(esw
, 0, 31, 0x0);
402 /* tune TP_IDL tail and head waveform */
403 rt305x_mii_write(esw
, 0, 22, 0x052f);
404 /* set TX10 signal amplitude threshold to minimum */
405 rt305x_mii_write(esw
, 0, 17, 0x0fe0);
406 /* set squelch amplitude to higher threshold */
407 rt305x_mii_write(esw
, 0, 18, 0x40ba);
408 /* longer TP_IDL tail length */
409 rt305x_mii_write(esw
, 0, 14, 0x65);
410 /* select local register */
411 rt305x_mii_write(esw
, 0, 31, 0x8000);
413 switch (esw
->pdata
->vlan_config
) {
414 case RT305X_ESW_VLAN_CONFIG_NONE
:
415 port_map
= RT305X_ESW_PMAP_LLLLLL
;
417 case RT305X_ESW_VLAN_CONFIG_LLLLW
:
418 port_map
= RT305X_ESW_PMAP_LLLLWL
;
420 case RT305X_ESW_VLAN_CONFIG_WLLLL
:
421 port_map
= RT305X_ESW_PMAP_WLLLLL
;
428 * Unused HW feature, but still nice to be consistent here...
429 * This is also exported to userspace ('lan' attribute) so it's
430 * conveniently usable to decide which ports go into the wan vlan by
433 rt305x_esw_rmw(esw
, RT305X_ESW_REG_SGC2
,
434 RT305X_ESW_SGC2_LAN_PMAP_M
<< RT305X_ESW_SGC2_LAN_PMAP_S
,
435 port_map
<< RT305X_ESW_SGC2_LAN_PMAP_S
);
437 /* Apply the empty config. */
438 rt305x_esw_apply_config(&esw
->swdev
);
442 rt305x_esw_apply_config(struct switch_dev
*dev
)
444 struct rt305x_esw
*esw
= container_of(dev
, struct rt305x_esw
, swdev
);
451 for (i
= 0; i
< RT305X_ESW_NUM_VLANS
; i
++) {
453 if (esw
->global_vlan_enable
) {
454 vid
= esw
->vlans
[i
].vid
;
455 vmsc
= esw
->vlans
[i
].ports
;
457 vid
= RT305X_ESW_VLAN_NONE
;
458 vmsc
= RT305X_ESW_PORTS_NONE
;
460 rt305x_esw_set_vlan_id(esw
, i
, vid
);
461 rt305x_esw_set_vmsc(esw
, i
, vmsc
);
464 for (i
= 0; i
< RT305X_ESW_NUM_PORTS
; i
++) {
466 disable
|= esw
->ports
[i
].disable
<< i
;
467 if (esw
->global_vlan_enable
) {
468 doubletag
|= esw
->ports
[i
].doubletag
<< i
;
470 untag
|= esw
->ports
[i
].untag
<< i
;
471 pvid
= esw
->ports
[i
].pvid
;
473 int x
= esw
->alt_vlan_disable
? 1 : 0;
479 rt305x_esw_set_pvid(esw
, i
, pvid
);
480 if (i
< RT305X_ESW_NUM_LEDS
)
481 rt305x_esw_wr(esw
, esw
->ports
[i
].led
,
482 RT305X_ESW_REG_P0LED
+ 4*i
);
485 rt305x_esw_rmw(esw
, RT305X_ESW_REG_POC0
,
486 RT305X_ESW_POC0_DIS_PORT_M
<< RT305X_ESW_POC0_DIS_PORT_S
,
487 disable
<< RT305X_ESW_POC0_DIS_PORT_S
);
488 rt305x_esw_rmw(esw
, RT305X_ESW_REG_SGC2
,
489 (RT305X_ESW_SGC2_DOUBLE_TAG_M
<<
490 RT305X_ESW_SGC2_DOUBLE_TAG_S
),
491 doubletag
<< RT305X_ESW_SGC2_DOUBLE_TAG_S
);
492 rt305x_esw_rmw(esw
, RT305X_ESW_REG_PFC1
,
493 RT305X_ESW_PFC1_EN_VLAN_M
<< RT305X_ESW_PFC1_EN_VLAN_S
,
494 en_vlan
<< RT305X_ESW_PFC1_EN_VLAN_S
);
495 rt305x_esw_rmw(esw
, RT305X_ESW_REG_POC2
,
496 RT305X_ESW_POC2_UNTAG_EN_M
<< RT305X_ESW_POC2_UNTAG_EN_S
,
497 untag
<< RT305X_ESW_POC2_UNTAG_EN_S
);
499 if (!esw
->global_vlan_enable
) {
501 * Still need to put all ports into vlan 0 or they'll be
503 * NOTE: vlan 0 is special, no vlan tag is prepended
505 rt305x_esw_set_vlan_id(esw
, 0, 0);
506 rt305x_esw_set_vmsc(esw
, 0, RT305X_ESW_PORTS_ALL
);
513 rt305x_esw_reset_switch(struct switch_dev
*dev
)
515 struct rt305x_esw
*esw
= container_of(dev
, struct rt305x_esw
, swdev
);
516 esw
->global_vlan_enable
= 0;
517 memset(esw
->ports
, 0, sizeof(esw
->ports
));
518 memset(esw
->vlans
, 0, sizeof(esw
->vlans
));
519 rt305x_esw_hw_init(esw
);
525 rt305x_esw_get_vlan_enable(struct switch_dev
*dev
,
526 const struct switch_attr
*attr
,
527 struct switch_val
*val
)
529 struct rt305x_esw
*esw
= container_of(dev
, struct rt305x_esw
, swdev
);
531 val
->value
.i
= esw
->global_vlan_enable
;
537 rt305x_esw_set_vlan_enable(struct switch_dev
*dev
,
538 const struct switch_attr
*attr
,
539 struct switch_val
*val
)
541 struct rt305x_esw
*esw
= container_of(dev
, struct rt305x_esw
, swdev
);
543 esw
->global_vlan_enable
= val
->value
.i
!= 0;
549 rt305x_esw_get_alt_vlan_disable(struct switch_dev
*dev
,
550 const struct switch_attr
*attr
,
551 struct switch_val
*val
)
553 struct rt305x_esw
*esw
= container_of(dev
, struct rt305x_esw
, swdev
);
555 val
->value
.i
= esw
->alt_vlan_disable
;
561 rt305x_esw_set_alt_vlan_disable(struct switch_dev
*dev
,
562 const struct switch_attr
*attr
,
563 struct switch_val
*val
)
565 struct rt305x_esw
*esw
= container_of(dev
, struct rt305x_esw
, swdev
);
567 esw
->alt_vlan_disable
= val
->value
.i
!= 0;
573 rt305x_esw_get_port_link(struct switch_dev
*dev
,
575 struct switch_port_link
*link
)
577 struct rt305x_esw
*esw
= container_of(dev
, struct rt305x_esw
, swdev
);
580 if (port
< 0 || port
>= RT305X_ESW_NUM_PORTS
)
583 poa
= rt305x_esw_rr(esw
, RT305X_ESW_REG_POA
) >> port
;
585 link
->link
= (poa
>> RT305X_ESW_LINK_S
) & 1;
586 link
->duplex
= (poa
>> RT305X_ESW_DUPLEX_S
) & 1;
587 if (port
< RT305X_ESW_NUM_LEDS
) {
588 speed
= (poa
>> RT305X_ESW_SPD_S
) & 1;
590 if (port
== RT305X_ESW_NUM_PORTS
- 1)
592 speed
= (poa
>> RT305X_ESW_SPD_S
) & 3;
596 link
->speed
= SWITCH_PORT_SPEED_10
;
599 link
->speed
= SWITCH_PORT_SPEED_100
;
602 case 3: /* forced gige speed can be 2 or 3 */
603 link
->speed
= SWITCH_PORT_SPEED_1000
;
606 link
->speed
= SWITCH_PORT_SPEED_UNKNOWN
;
614 rt305x_esw_get_port_bool(struct switch_dev
*dev
,
615 const struct switch_attr
*attr
,
616 struct switch_val
*val
)
618 struct rt305x_esw
*esw
= container_of(dev
, struct rt305x_esw
, swdev
);
619 int idx
= val
->port_vlan
;
622 if (idx
< 0 || idx
>= RT305X_ESW_NUM_PORTS
)
626 case RT305X_ESW_ATTR_PORT_DISABLE
:
627 reg
= RT305X_ESW_REG_POC0
;
628 shift
= RT305X_ESW_POC0_DIS_PORT_S
;
630 case RT305X_ESW_ATTR_PORT_DOUBLETAG
:
631 reg
= RT305X_ESW_REG_SGC2
;
632 shift
= RT305X_ESW_SGC2_DOUBLE_TAG_S
;
634 case RT305X_ESW_ATTR_PORT_UNTAG
:
635 reg
= RT305X_ESW_REG_POC2
;
636 shift
= RT305X_ESW_POC2_UNTAG_EN_S
;
638 case RT305X_ESW_ATTR_PORT_LAN
:
639 reg
= RT305X_ESW_REG_SGC2
;
640 shift
= RT305X_ESW_SGC2_LAN_PMAP_S
;
641 if (idx
>= RT305X_ESW_NUM_LANWAN
)
648 x
= rt305x_esw_rr(esw
, reg
);
649 val
->value
.i
= (x
>> (idx
+ shift
)) & 1;
655 rt305x_esw_set_port_bool(struct switch_dev
*dev
,
656 const struct switch_attr
*attr
,
657 struct switch_val
*val
)
659 struct rt305x_esw
*esw
= container_of(dev
, struct rt305x_esw
, swdev
);
660 int idx
= val
->port_vlan
;
662 if (idx
< 0 || idx
>= RT305X_ESW_NUM_PORTS
||
663 val
->value
.i
< 0 || val
->value
.i
> 1)
667 case RT305X_ESW_ATTR_PORT_DISABLE
:
668 esw
->ports
[idx
].disable
= val
->value
.i
;
670 case RT305X_ESW_ATTR_PORT_DOUBLETAG
:
671 esw
->ports
[idx
].doubletag
= val
->value
.i
;
673 case RT305X_ESW_ATTR_PORT_UNTAG
:
674 esw
->ports
[idx
].untag
= val
->value
.i
;
684 rt305x_esw_get_port_recv_badgood(struct switch_dev
*dev
,
685 const struct switch_attr
*attr
,
686 struct switch_val
*val
)
688 struct rt305x_esw
*esw
= container_of(dev
, struct rt305x_esw
, swdev
);
689 int idx
= val
->port_vlan
;
690 int shift
= attr
->id
== RT305X_ESW_ATTR_PORT_RECV_GOOD
? 0 : 16;
692 if (idx
< 0 || idx
>= RT305X_ESW_NUM_LANWAN
)
695 val
->value
.i
= rt305x_esw_rr(esw
, RT305X_ESW_REG_P0PC
+ 4*idx
) >> shift
;
701 rt305x_esw_get_port_led(struct switch_dev
*dev
,
702 const struct switch_attr
*attr
,
703 struct switch_val
*val
)
705 struct rt305x_esw
*esw
= container_of(dev
, struct rt305x_esw
, swdev
);
706 int idx
= val
->port_vlan
;
708 if (idx
< 0 || idx
>= RT305X_ESW_NUM_PORTS
||
709 idx
>= RT305X_ESW_NUM_LEDS
)
712 val
->value
.i
= rt305x_esw_rr(esw
, RT305X_ESW_REG_P0LED
+ 4*idx
);
718 rt305x_esw_set_port_led(struct switch_dev
*dev
,
719 const struct switch_attr
*attr
,
720 struct switch_val
*val
)
722 struct rt305x_esw
*esw
= container_of(dev
, struct rt305x_esw
, swdev
);
723 int idx
= val
->port_vlan
;
725 if (idx
< 0 || idx
>= RT305X_ESW_NUM_LEDS
)
728 esw
->ports
[idx
].led
= val
->value
.i
;
734 rt305x_esw_get_port_pvid(struct switch_dev
*dev
, int port
, int *val
)
736 struct rt305x_esw
*esw
= container_of(dev
, struct rt305x_esw
, swdev
);
738 if (port
>= RT305X_ESW_NUM_PORTS
)
741 *val
= rt305x_esw_get_pvid(esw
, port
);
747 rt305x_esw_set_port_pvid(struct switch_dev
*dev
, int port
, int val
)
749 struct rt305x_esw
*esw
= container_of(dev
, struct rt305x_esw
, swdev
);
751 if (port
>= RT305X_ESW_NUM_PORTS
)
754 esw
->ports
[port
].pvid
= val
;
760 rt305x_esw_get_vlan_ports(struct switch_dev
*dev
, struct switch_val
*val
)
762 struct rt305x_esw
*esw
= container_of(dev
, struct rt305x_esw
, swdev
);
769 if (val
->port_vlan
< 0 || val
->port_vlan
>= RT305X_ESW_NUM_VIDS
)
773 for (i
= 0; i
< RT305X_ESW_NUM_VLANS
; i
++) {
774 if (rt305x_esw_get_vlan_id(esw
, i
) == val
->port_vlan
&&
775 rt305x_esw_get_vmsc(esw
, i
) != RT305X_ESW_PORTS_NONE
) {
784 vmsc
= rt305x_esw_get_vmsc(esw
, vlan_idx
);
785 poc2
= rt305x_esw_rr(esw
, RT305X_ESW_REG_POC2
);
787 for (i
= 0; i
< RT305X_ESW_NUM_PORTS
; i
++) {
788 struct switch_port
*p
;
789 int port_mask
= 1 << i
;
791 if (!(vmsc
& port_mask
))
794 p
= &val
->value
.ports
[val
->len
++];
796 if (poc2
& (port_mask
<< RT305X_ESW_POC2_UNTAG_EN_S
))
799 p
->flags
= 1 << SWITCH_PORT_FLAG_TAGGED
;
806 rt305x_esw_set_vlan_ports(struct switch_dev
*dev
, struct switch_val
*val
)
808 struct rt305x_esw
*esw
= container_of(dev
, struct rt305x_esw
, swdev
);
813 if (val
->port_vlan
< 0 || val
->port_vlan
>= RT305X_ESW_NUM_VIDS
||
814 val
->len
> RT305X_ESW_NUM_PORTS
)
817 /* one of the already defined vlans? */
818 for (i
= 0; i
< RT305X_ESW_NUM_VLANS
; i
++) {
819 if (esw
->vlans
[i
].vid
== val
->port_vlan
&&
820 esw
->vlans
[i
].ports
!= RT305X_ESW_PORTS_NONE
) {
826 /* select a free slot */
827 for (i
= 0; vlan_idx
== -1 && i
< RT305X_ESW_NUM_VLANS
; i
++) {
828 if (esw
->vlans
[i
].ports
== RT305X_ESW_PORTS_NONE
)
832 /* bail if all slots are in use */
836 ports
= RT305X_ESW_PORTS_NONE
;
837 for (i
= 0; i
< val
->len
; i
++) {
838 struct switch_port
*p
= &val
->value
.ports
[i
];
839 int port_mask
= 1 << p
->id
;
840 bool untagged
= !(p
->flags
& (1 << SWITCH_PORT_FLAG_TAGGED
));
842 if (p
->id
>= RT305X_ESW_NUM_PORTS
)
846 esw
->ports
[p
->id
].untag
= untagged
;
848 esw
->vlans
[vlan_idx
].ports
= ports
;
849 if (ports
== RT305X_ESW_PORTS_NONE
)
850 esw
->vlans
[vlan_idx
].vid
= RT305X_ESW_VLAN_NONE
;
852 esw
->vlans
[vlan_idx
].vid
= val
->port_vlan
;
857 static const struct switch_attr rt305x_esw_global
[] = {
859 .type
= SWITCH_TYPE_INT
,
860 .name
= "enable_vlan",
861 .description
= "VLAN mode (1:enabled)",
863 .id
= RT305X_ESW_ATTR_ENABLE_VLAN
,
864 .get
= rt305x_esw_get_vlan_enable
,
865 .set
= rt305x_esw_set_vlan_enable
,
868 .type
= SWITCH_TYPE_INT
,
869 .name
= "alternate_vlan_disable",
870 .description
= "Use en_vlan instead of doubletag to disable"
873 .id
= RT305X_ESW_ATTR_ALT_VLAN_DISABLE
,
874 .get
= rt305x_esw_get_alt_vlan_disable
,
875 .set
= rt305x_esw_set_alt_vlan_disable
,
879 static const struct switch_attr rt305x_esw_port
[] = {
881 .type
= SWITCH_TYPE_INT
,
883 .description
= "Port state (1:disabled)",
885 .id
= RT305X_ESW_ATTR_PORT_DISABLE
,
886 .get
= rt305x_esw_get_port_bool
,
887 .set
= rt305x_esw_set_port_bool
,
890 .type
= SWITCH_TYPE_INT
,
892 .description
= "Double tagging for incoming vlan packets "
895 .id
= RT305X_ESW_ATTR_PORT_DOUBLETAG
,
896 .get
= rt305x_esw_get_port_bool
,
897 .set
= rt305x_esw_set_port_bool
,
900 .type
= SWITCH_TYPE_INT
,
902 .description
= "Untag (1:strip outgoing vlan tag)",
904 .id
= RT305X_ESW_ATTR_PORT_UNTAG
,
905 .get
= rt305x_esw_get_port_bool
,
906 .set
= rt305x_esw_set_port_bool
,
909 .type
= SWITCH_TYPE_INT
,
911 .description
= "LED mode (0:link, 1:100m, 2:duplex, 3:activity,"
912 " 4:collision, 5:linkact, 6:duplcoll, 7:10mact,"
913 " 8:100mact, 10:blink, 12:on)",
915 .id
= RT305X_ESW_ATTR_PORT_LED
,
916 .get
= rt305x_esw_get_port_led
,
917 .set
= rt305x_esw_set_port_led
,
920 .type
= SWITCH_TYPE_INT
,
922 .description
= "HW port group (0:wan, 1:lan)",
924 .id
= RT305X_ESW_ATTR_PORT_LAN
,
925 .get
= rt305x_esw_get_port_bool
,
928 .type
= SWITCH_TYPE_INT
,
930 .description
= "Receive bad packet counter",
931 .id
= RT305X_ESW_ATTR_PORT_RECV_BAD
,
932 .get
= rt305x_esw_get_port_recv_badgood
,
935 .type
= SWITCH_TYPE_INT
,
937 .description
= "Receive good packet counter",
938 .id
= RT305X_ESW_ATTR_PORT_RECV_GOOD
,
939 .get
= rt305x_esw_get_port_recv_badgood
,
943 static const struct switch_attr rt305x_esw_vlan
[] = {
946 static const struct switch_dev_ops rt305x_esw_ops
= {
948 .attr
= rt305x_esw_global
,
949 .n_attr
= ARRAY_SIZE(rt305x_esw_global
),
952 .attr
= rt305x_esw_port
,
953 .n_attr
= ARRAY_SIZE(rt305x_esw_port
),
956 .attr
= rt305x_esw_vlan
,
957 .n_attr
= ARRAY_SIZE(rt305x_esw_vlan
),
959 .get_vlan_ports
= rt305x_esw_get_vlan_ports
,
960 .set_vlan_ports
= rt305x_esw_set_vlan_ports
,
961 .get_port_pvid
= rt305x_esw_get_port_pvid
,
962 .set_port_pvid
= rt305x_esw_set_port_pvid
,
963 .get_port_link
= rt305x_esw_get_port_link
,
964 .apply_config
= rt305x_esw_apply_config
,
965 .reset_switch
= rt305x_esw_reset_switch
,
969 rt305x_esw_probe(struct platform_device
*pdev
)
971 struct rt305x_esw_platform_data
*pdata
;
972 struct rt305x_esw
*esw
;
973 struct switch_dev
*swdev
;
974 struct resource
*res
;
977 pdata
= pdev
->dev
.platform_data
;
981 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
983 dev_err(&pdev
->dev
, "no memory resource found\n");
987 esw
= kzalloc(sizeof(struct rt305x_esw
), GFP_KERNEL
);
989 dev_err(&pdev
->dev
, "no memory for private data\n");
993 esw
->base
= ioremap(res
->start
, resource_size(res
));
995 dev_err(&pdev
->dev
, "ioremap failed\n");
1000 swdev
= &esw
->swdev
;
1001 swdev
->name
= "rt305x-esw";
1002 swdev
->alias
= "rt305x";
1003 swdev
->cpu_port
= RT305X_ESW_PORT6
;
1004 swdev
->ports
= RT305X_ESW_NUM_PORTS
;
1005 swdev
->vlans
= RT305X_ESW_NUM_VIDS
;
1006 swdev
->ops
= &rt305x_esw_ops
;
1008 err
= register_switch(swdev
, NULL
);
1010 dev_err(&pdev
->dev
, "register_switch failed\n");
1014 platform_set_drvdata(pdev
, esw
);
1017 spin_lock_init(&esw
->reg_rw_lock
);
1018 rt305x_esw_hw_init(esw
);
1030 rt305x_esw_remove(struct platform_device
*pdev
)
1032 struct rt305x_esw
*esw
;
1034 esw
= platform_get_drvdata(pdev
);
1036 unregister_switch(&esw
->swdev
);
1037 platform_set_drvdata(pdev
, NULL
);
1045 static struct platform_driver rt305x_esw_driver
= {
1046 .probe
= rt305x_esw_probe
,
1047 .remove
= rt305x_esw_remove
,
1049 .name
= "rt305x-esw",
1050 .owner
= THIS_MODULE
,
1055 rt305x_esw_init(void)
1057 return platform_driver_register(&rt305x_esw_driver
);
1061 rt305x_esw_exit(void)
1063 platform_driver_unregister(&rt305x_esw_driver
);