Root/target/linux/ramips/files/drivers/net/ethernet/ramips/ramips_esw.c

1#include <linux/ioport.h>
2
3#include <rt305x_regs.h>
4#include <rt305x_esw_platform.h>
5
6#define RT305X_ESW_REG_FCT0 0x08
7#define RT305X_ESW_REG_PFC1 0x14
8#define RT305X_ESW_REG_PVIDC(_n) (0x40 + 4 * (_n))
9#define RT305X_ESW_REG_VLANI(_n) (0x50 + 4 * (_n))
10#define RT305X_ESW_REG_VMSC(_n) (0x70 + 4 * (_n))
11#define RT305X_ESW_REG_FPA 0x84
12#define RT305X_ESW_REG_SOCPC 0x8c
13#define RT305X_ESW_REG_POC1 0x90
14#define RT305X_ESW_REG_POC2 0x94
15#define RT305X_ESW_REG_POC3 0x98
16#define RT305X_ESW_REG_SGC 0x9c
17#define RT305X_ESW_REG_PCR0 0xc0
18#define RT305X_ESW_REG_PCR1 0xc4
19#define RT305X_ESW_REG_FPA2 0xc8
20#define RT305X_ESW_REG_FCT2 0xcc
21#define RT305X_ESW_REG_SGC2 0xe4
22#define RT305X_ESW_REG_P0LED 0xa4
23#define RT305X_ESW_REG_P1LED 0xa8
24#define RT305X_ESW_REG_P2LED 0xac
25#define RT305X_ESW_REG_P3LED 0xb0
26#define RT305X_ESW_REG_P4LED 0xb4
27
28#define RT305X_ESW_PCR0_WT_NWAY_DATA_S 16
29#define RT305X_ESW_PCR0_WT_PHY_CMD BIT(13)
30#define RT305X_ESW_PCR0_CPU_PHY_REG_S 8
31
32#define RT305X_ESW_PCR1_WT_DONE BIT(0)
33
34#define RT305X_ESW_PHY_TIMEOUT (5 * HZ)
35
36#define RT305X_ESW_PVIDC_PVID_M 0xfff
37#define RT305X_ESW_PVIDC_PVID_S 12
38
39#define RT305X_ESW_VLANI_VID_M 0xfff
40#define RT305X_ESW_VLANI_VID_S 12
41
42#define RT305X_ESW_VMSC_MSC_M 0xff
43#define RT305X_ESW_VMSC_MSC_S 8
44
45#define RT305X_ESW_SOCPC_DISUN2CPU_S 0
46#define RT305X_ESW_SOCPC_DISMC2CPU_S 8
47#define RT305X_ESW_SOCPC_DISBC2CPU_S 16
48#define RT305X_ESW_SOCPC_CRC_PADDING BIT(25)
49
50#define RT305X_ESW_POC1_EN_BP_S 0
51#define RT305X_ESW_POC1_EN_FC_S 8
52#define RT305X_ESW_POC1_DIS_RMC2CPU_S 16
53#define RT305X_ESW_POC1_DIS_PORT_S 23
54
55#define RT305X_ESW_POC3_UNTAG_EN_S 0
56#define RT305X_ESW_POC3_ENAGING_S 8
57#define RT305X_ESW_POC3_DIS_UC_PAUSE_S 16
58
59#define RT305X_ESW_PORT0 0
60#define RT305X_ESW_PORT1 1
61#define RT305X_ESW_PORT2 2
62#define RT305X_ESW_PORT3 3
63#define RT305X_ESW_PORT4 4
64#define RT305X_ESW_PORT5 5
65#define RT305X_ESW_PORT6 6
66
67#define RT305X_ESW_PORTS_INTERNAL \
68        (BIT(RT305X_ESW_PORT0) | BIT(RT305X_ESW_PORT1) | \
69         BIT(RT305X_ESW_PORT2) | BIT(RT305X_ESW_PORT3) | \
70         BIT(RT305X_ESW_PORT4))
71
72#define RT305X_ESW_PORTS_NOCPU \
73        (RT305X_ESW_PORTS_INTERNAL | BIT(RT305X_ESW_PORT5))
74
75#define RT305X_ESW_PORTS_CPU BIT(RT305X_ESW_PORT6)
76
77#define RT305X_ESW_PORTS_ALL \
78        (RT305X_ESW_PORTS_NOCPU | RT305X_ESW_PORTS_CPU)
79
80#define RT305X_ESW_NUM_VLANS 16
81#define RT305X_ESW_NUM_PORTS 7
82
83struct rt305x_esw {
84    void __iomem *base;
85    struct rt305x_esw_platform_data *pdata;
86    spinlock_t reg_rw_lock;
87};
88
89static inline void
90rt305x_esw_wr(struct rt305x_esw *esw, u32 val, unsigned reg)
91{
92    __raw_writel(val, esw->base + reg);
93}
94
95static inline u32
96rt305x_esw_rr(struct rt305x_esw *esw, unsigned reg)
97{
98    return __raw_readl(esw->base + reg);
99}
100
101static inline void
102rt305x_esw_rmw_raw(struct rt305x_esw *esw, unsigned reg, unsigned long mask,
103           unsigned long val)
104{
105    unsigned long t;
106
107    t = __raw_readl(esw->base + reg) & ~mask;
108    __raw_writel(t | val, esw->base + reg);
109}
110
111static void
112rt305x_esw_rmw(struct rt305x_esw *esw, unsigned reg, unsigned long mask,
113           unsigned long val)
114{
115    unsigned long flags;
116
117    spin_lock_irqsave(&esw->reg_rw_lock, flags);
118    rt305x_esw_rmw_raw(esw, reg, mask, val);
119    spin_unlock_irqrestore(&esw->reg_rw_lock, flags);
120}
121
122static u32
123rt305x_mii_write(struct rt305x_esw *esw, u32 phy_addr, u32 phy_register,
124         u32 write_data)
125{
126    unsigned long t_start = jiffies;
127    int ret = 0;
128
129    while (1) {
130        if (!(rt305x_esw_rr(esw, RT305X_ESW_REG_PCR1) &
131              RT305X_ESW_PCR1_WT_DONE))
132            break;
133        if (time_after(jiffies, t_start + RT305X_ESW_PHY_TIMEOUT)) {
134            ret = 1;
135            goto out;
136        }
137    }
138
139    write_data &= 0xffff;
140    rt305x_esw_wr(esw,
141              (write_data << RT305X_ESW_PCR0_WT_NWAY_DATA_S) |
142              (phy_register << RT305X_ESW_PCR0_CPU_PHY_REG_S) |
143              (phy_addr) | RT305X_ESW_PCR0_WT_PHY_CMD,
144              RT305X_ESW_REG_PCR0);
145
146    t_start = jiffies;
147    while (1) {
148        if (rt305x_esw_rr(esw, RT305X_ESW_REG_PCR1) &
149            RT305X_ESW_PCR1_WT_DONE)
150            break;
151
152        if (time_after(jiffies, t_start + RT305X_ESW_PHY_TIMEOUT)) {
153            ret = 1;
154            break;
155        }
156    }
157out:
158    if (ret)
159        printk(KERN_ERR "ramips_eth: MDIO timeout\n");
160    return ret;
161}
162
163static void
164rt305x_esw_set_vlan_id(struct rt305x_esw *esw, unsigned vlan, unsigned vid)
165{
166    unsigned s;
167
168    s = RT305X_ESW_VLANI_VID_S * (vlan % 2);
169    rt305x_esw_rmw(esw,
170               RT305X_ESW_REG_VLANI(vlan / 2),
171               RT305X_ESW_VLANI_VID_M << s,
172               (vid & RT305X_ESW_VLANI_VID_M) << s);
173}
174
175static void
176rt305x_esw_set_pvid(struct rt305x_esw *esw, unsigned port, unsigned pvid)
177{
178    unsigned s;
179
180    s = RT305X_ESW_PVIDC_PVID_S * (port % 2);
181    rt305x_esw_rmw(esw,
182               RT305X_ESW_REG_PVIDC(port / 2),
183               RT305X_ESW_PVIDC_PVID_M << s,
184               (pvid & RT305X_ESW_PVIDC_PVID_M) << s);
185}
186
187static void
188rt305x_esw_set_vmsc(struct rt305x_esw *esw, unsigned vlan, unsigned msc)
189{
190    unsigned s;
191
192    s = RT305X_ESW_VMSC_MSC_S * (vlan % 4);
193    rt305x_esw_rmw(esw,
194               RT305X_ESW_REG_VMSC(vlan / 4),
195               RT305X_ESW_VMSC_MSC_M << s,
196               (msc & RT305X_ESW_VMSC_MSC_M) << s);
197}
198
199static void
200rt305x_esw_hw_init(struct rt305x_esw *esw)
201{
202    int i;
203
204    /* vodoo from original driver */
205    rt305x_esw_wr(esw, 0xC8A07850, RT305X_ESW_REG_FCT0);
206    rt305x_esw_wr(esw, 0x00000000, RT305X_ESW_REG_SGC2);
207    rt305x_esw_wr(esw, 0x00405555, RT305X_ESW_REG_PFC1);
208
209    /* Enable Back Pressure, and Flow Control */
210    rt305x_esw_wr(esw,
211              ((RT305X_ESW_PORTS_ALL << RT305X_ESW_POC1_EN_BP_S) |
212               (RT305X_ESW_PORTS_ALL << RT305X_ESW_POC1_EN_FC_S)),
213              RT305X_ESW_REG_POC1);
214
215    /* Enable Aging, and VLAN TAG removal */
216    rt305x_esw_wr(esw,
217              ((RT305X_ESW_PORTS_ALL << RT305X_ESW_POC3_ENAGING_S) |
218               (RT305X_ESW_PORTS_NOCPU << RT305X_ESW_POC3_UNTAG_EN_S)),
219              RT305X_ESW_REG_POC3);
220
221    rt305x_esw_wr(esw, esw->pdata->reg_initval_fct2, RT305X_ESW_REG_FCT2);
222    rt305x_esw_wr(esw, 0x0008a301, RT305X_ESW_REG_SGC);
223
224    /* Setup SoC Port control register */
225    rt305x_esw_wr(esw,
226              (RT305X_ESW_SOCPC_CRC_PADDING |
227               (RT305X_ESW_PORTS_CPU << RT305X_ESW_SOCPC_DISUN2CPU_S) |
228               (RT305X_ESW_PORTS_CPU << RT305X_ESW_SOCPC_DISMC2CPU_S) |
229               (RT305X_ESW_PORTS_CPU << RT305X_ESW_SOCPC_DISBC2CPU_S)),
230              RT305X_ESW_REG_SOCPC);
231
232    rt305x_esw_wr(esw, esw->pdata->reg_initval_fpa2, RT305X_ESW_REG_FPA2);
233    rt305x_esw_wr(esw, 0x00000000, RT305X_ESW_REG_FPA);
234
235    /* Force Link/Activity on ports */
236    rt305x_esw_wr(esw, 0x00000005, RT305X_ESW_REG_P0LED);
237    rt305x_esw_wr(esw, 0x00000005, RT305X_ESW_REG_P1LED);
238    rt305x_esw_wr(esw, 0x00000005, RT305X_ESW_REG_P2LED);
239    rt305x_esw_wr(esw, 0x00000005, RT305X_ESW_REG_P3LED);
240    rt305x_esw_wr(esw, 0x00000005, RT305X_ESW_REG_P4LED);
241
242    rt305x_mii_write(esw, 0, 31, 0x8000);
243    for (i = 0; i < 5; i++) {
244        /* TX10 waveform coefficient */
245        rt305x_mii_write(esw, i, 0, 0x3100);
246        /* TX10 waveform coefficient */
247        rt305x_mii_write(esw, i, 26, 0x1601);
248        /* TX100/TX10 AD/DA current bias */
249        rt305x_mii_write(esw, i, 29, 0x7058);
250        /* TX100 slew rate control */
251        rt305x_mii_write(esw, i, 30, 0x0018);
252    }
253
254    /* PHY IOT */
255    /* select global register */
256    rt305x_mii_write(esw, 0, 31, 0x0);
257    /* tune TP_IDL tail and head waveform */
258    rt305x_mii_write(esw, 0, 22, 0x052f);
259    /* set TX10 signal amplitude threshold to minimum */
260    rt305x_mii_write(esw, 0, 17, 0x0fe0);
261    /* set squelch amplitude to higher threshold */
262    rt305x_mii_write(esw, 0, 18, 0x40ba);
263    /* longer TP_IDL tail length */
264    rt305x_mii_write(esw, 0, 14, 0x65);
265    /* select local register */
266    rt305x_mii_write(esw, 0, 31, 0x8000);
267
268    for (i = 0; i < RT305X_ESW_NUM_VLANS; i++) {
269        rt305x_esw_set_vlan_id(esw, i, 0);
270        rt305x_esw_set_vmsc(esw, i, 0);
271    }
272
273    for (i = 0; i < RT305X_ESW_NUM_PORTS; i++)
274        rt305x_esw_set_pvid(esw, i, 1);
275
276    switch (esw->pdata->vlan_config) {
277    case RT305X_ESW_VLAN_CONFIG_NONE:
278        break;
279
280    case RT305X_ESW_VLAN_CONFIG_BYPASS:
281        /* Pass all vlan tags to all ports */
282        for (i = 0; i < RT305X_ESW_NUM_VLANS; i++) {
283            rt305x_esw_set_vlan_id(esw, i, i+1);
284            rt305x_esw_set_vmsc(esw, i, RT305X_ESW_PORTS_ALL);
285        }
286        /* Disable VLAN TAG removal, keep aging on. */
287        rt305x_esw_wr(esw,
288                  RT305X_ESW_PORTS_ALL << RT305X_ESW_POC3_ENAGING_S,
289                  RT305X_ESW_REG_POC3);
290        break;
291
292    case RT305X_ESW_VLAN_CONFIG_LLLLW:
293        rt305x_esw_set_vlan_id(esw, 0, 1);
294        rt305x_esw_set_vlan_id(esw, 1, 2);
295        rt305x_esw_set_pvid(esw, RT305X_ESW_PORT4, 2);
296
297        rt305x_esw_set_vmsc(esw, 0,
298                BIT(RT305X_ESW_PORT0) | BIT(RT305X_ESW_PORT1) |
299                BIT(RT305X_ESW_PORT2) | BIT(RT305X_ESW_PORT3) |
300                BIT(RT305X_ESW_PORT6));
301        rt305x_esw_set_vmsc(esw, 1,
302                BIT(RT305X_ESW_PORT4) | BIT(RT305X_ESW_PORT6));
303        break;
304
305    case RT305X_ESW_VLAN_CONFIG_WLLLL:
306        rt305x_esw_set_vlan_id(esw, 0, 1);
307        rt305x_esw_set_vlan_id(esw, 1, 2);
308        rt305x_esw_set_pvid(esw, RT305X_ESW_PORT0, 2);
309
310        rt305x_esw_set_vmsc(esw, 0,
311                BIT(RT305X_ESW_PORT1) | BIT(RT305X_ESW_PORT2) |
312                BIT(RT305X_ESW_PORT3) | BIT(RT305X_ESW_PORT4) |
313                BIT(RT305X_ESW_PORT6));
314        rt305x_esw_set_vmsc(esw, 1,
315                BIT(RT305X_ESW_PORT0) | BIT(RT305X_ESW_PORT6));
316        break;
317
318    default:
319        BUG();
320    }
321}
322
323static int
324rt305x_esw_probe(struct platform_device *pdev)
325{
326    struct rt305x_esw_platform_data *pdata;
327    struct rt305x_esw *esw;
328    struct resource *res;
329    int err;
330
331    pdata = pdev->dev.platform_data;
332    if (!pdata)
333        return -EINVAL;
334
335    res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
336    if (!res) {
337        dev_err(&pdev->dev, "no memory resource found\n");
338        return -ENOMEM;
339    }
340
341    esw = kzalloc(sizeof(struct rt305x_esw), GFP_KERNEL);
342    if (!esw) {
343        dev_err(&pdev->dev, "no memory for private data\n");
344        return -ENOMEM;
345    }
346
347    esw->base = ioremap(res->start, resource_size(res));
348    if (!esw->base) {
349        dev_err(&pdev->dev, "ioremap failed\n");
350        err = -ENOMEM;
351        goto free_esw;
352    }
353
354    platform_set_drvdata(pdev, esw);
355
356    esw->pdata = pdata;
357    spin_lock_init(&esw->reg_rw_lock);
358    rt305x_esw_hw_init(esw);
359
360    return 0;
361
362free_esw:
363    kfree(esw);
364    return err;
365}
366
367static int
368rt305x_esw_remove(struct platform_device *pdev)
369{
370    struct rt305x_esw *esw;
371
372    esw = platform_get_drvdata(pdev);
373    if (esw) {
374        platform_set_drvdata(pdev, NULL);
375        iounmap(esw->base);
376        kfree(esw);
377    }
378
379    return 0;
380}
381
382static struct platform_driver rt305x_esw_driver = {
383    .probe = rt305x_esw_probe,
384    .remove = rt305x_esw_remove,
385    .driver = {
386        .name = "rt305x-esw",
387        .owner = THIS_MODULE,
388    },
389};
390
391static int __init
392rt305x_esw_init(void)
393{
394    return platform_driver_register(&rt305x_esw_driver);
395}
396
397static void
398rt305x_esw_exit(void)
399{
400    platform_driver_unregister(&rt305x_esw_driver);
401}
402

Archive Download this file



interactive