Root/target/linux/lantiq/files/arch/mips/lantiq/svip/switchip_setup.c

1/******************************************************************************
2     Copyright (c) 2007, Infineon Technologies. All rights reserved.
3
4                               No Warranty
5   Because the program is licensed free of charge, there is no warranty for
6   the program, to the extent permitted by applicable law. Except when
7   otherwise stated in writing the copyright holders and/or other parties
8   provide the program "as is" without warranty of any kind, either
9   expressed or implied, including, but not limited to, the implied
10   warranties of merchantability and fitness for a particular purpose. The
11   entire risk as to the quality and performance of the program is with
12   you. should the program prove defective, you assume the cost of all
13   necessary servicing, repair or correction.
14
15   In no event unless required by applicable law or agreed to in writing
16   will any copyright holder, or any other party who may modify and/or
17   redistribute the program as permitted above, be liable to you for
18   damages, including any general, special, incidental or consequential
19   damages arising out of the use or inability to use the program
20   (including but not limited to loss of data or data being rendered
21   inaccurate or losses sustained by you or third parties or a failure of
22   the program to operate with any other programs), even if such holder or
23   other party has been advised of the possibility of such damages.
24 ******************************************************************************
25   Module : switchip_setup.c
26   Date : 2007-11-09
27   Description : Basic setup of embedded ethernet switch "SwitchIP"
28   Remarks: andreas.schmidt@infineon.com
29
30 *****************************************************************************/
31
32/* TODO: get rid of #ifdef CONFIG_LANTIQ_MACH_EASY336 */
33
34#include <linux/kernel.h>
35#include <linux/module.h>
36#include <linux/version.h>
37#include <linux/init.h>
38#include <linux/delay.h>
39#include <linux/workqueue.h>
40#include <linux/time.h>
41
42#include <base_reg.h>
43#include <es_reg.h>
44#include <sys1_reg.h>
45#include <dma_reg.h>
46#include <lantiq_soc.h>
47
48static struct svip_reg_sys1 *const sys1 = (struct svip_reg_sys1 *)LTQ_SYS1_BASE;
49static struct svip_reg_es *const es = (struct svip_reg_es *)LTQ_ES_BASE;
50
51/* PHY Organizationally Unique Identifier (OUI) */
52#define PHY_OUI_PMC 0x00E004
53#define PHY_OUI_VITESSE 0x008083
54#define PHY_OUI_DEFAULT 0xFFFFFF
55
56unsigned short switchip_phy_read(unsigned int phyaddr, unsigned int regaddr);
57void switchip_phy_write(unsigned int phyaddr, unsigned int regaddr,
58            unsigned short data);
59
60static int phy_address[2] = {0, 1};
61static u32 phy_oui;
62static void switchip_mdio_poll_init(void);
63static void _switchip_mdio_poll(struct work_struct *work);
64
65/* struct workqueue_struct mdio_poll_task; */
66static struct workqueue_struct *mdio_poll_workqueue;
67DECLARE_DELAYED_WORK(mdio_poll_work, _switchip_mdio_poll);
68static int old_link_status[2] = {-1, -1};
69
70/**
71 * Autonegotiation check.
72 * This funtion checks for link changes. If a link change has occured it will
73 * update certain switch registers.
74 */
75static void _switchip_check_phy_status(int port)
76{
77    int new_link_status;
78    unsigned short reg1;
79
80    reg1 = switchip_phy_read(phy_address[port], 1);
81    if ((reg1 == 0xFFFF) || (reg1 == 0x0000))
82        return; /* no PHY connected */
83
84    new_link_status = reg1 & 4;
85    if (old_link_status[port] ^ new_link_status) {
86        /* link status change */
87        if (!new_link_status) {
88            if (port == 0)
89                es_w32_mask(LTQ_ES_P0_CTL_REG_FLP, 0, p0_ctl);
90            else
91                es_w32_mask(LTQ_ES_P0_CTL_REG_FLP, 0, p1_ctl);
92
93            /* read again; link bit is latched low! */
94            reg1 = switchip_phy_read(phy_address[port], 1);
95            new_link_status = reg1 & 4;
96        }
97
98        if (new_link_status) {
99            unsigned short reg0, reg4, reg5, reg9, reg10;
100            int phy_pause, phy_speed, phy_duplex;
101            int aneg_enable, aneg_cmpt;
102
103            reg0 = switchip_phy_read(phy_address[port], 0);
104            reg4 = switchip_phy_read(phy_address[port], 4);
105            aneg_enable = reg0 & 0x1000;
106            aneg_cmpt = reg1 & 0x20;
107
108            if (aneg_enable && aneg_cmpt) {
109                reg5 = switchip_phy_read(phy_address[port], 5);
110                switch (phy_oui) {
111#ifdef CONFIG_LANTIQ_MACH_EASY336
112                case PHY_OUI_PMC:
113                    /* PMC Sierra supports 1Gigabit FD,
114                     * only. On successful
115                     * auto-negotiation, we are sure this
116                     * is what the LP can. */
117                    phy_pause = ((reg4 & reg5) & 0x0080) >> 7;
118                    phy_speed = 2;
119                    phy_duplex = 1;
120                    break;
121#endif
122                case PHY_OUI_VITESSE:
123                case PHY_OUI_DEFAULT:
124                    reg9 = switchip_phy_read(phy_address[port], 9);
125                    reg10 = switchip_phy_read(phy_address[port], 10);
126
127                    /* Check if advertise and partner
128                     * agree on pause */
129                    phy_pause = ((reg4 & reg5) & 0x0400) >> 10;
130
131                    /* Find the best mode both partners
132                     * support
133                     * Priority: 1GB-FD, 1GB-HD, 100MB-FD,
134                     * 100MB-HD, 10MB-FD, 10MB-HD */
135                    phy_speed = ((((reg9<<2) & reg10)
136                              & 0x0c00) >> 6) |
137                        (((reg4 & reg5) & 0x01e0) >> 5);
138
139                    if (phy_speed >= 0x0020) {
140                        phy_speed = 2;
141                        phy_duplex = 1;
142                    } else if (phy_speed >= 0x0010) {
143                        phy_speed = 2;
144                        phy_duplex = 0;
145                    } else if (phy_speed >= 0x0008) {
146                        phy_speed = 1;
147                        phy_duplex = 1;
148                    } else if (phy_speed >= 0x0004) {
149                        phy_speed = 1;
150                        phy_duplex = 0;
151                    } else if (phy_speed >= 0x0002) {
152                        phy_speed = 0;
153                        phy_duplex = 1;
154                    } else {
155                        phy_speed = 0;
156                        phy_duplex = 0;
157                    }
158                    break;
159                default:
160                    phy_pause = (reg4 & 0x0400) >> 10;
161                    phy_speed = (reg0 & 0x40 ? 2 : (reg0 >> 13)&1);
162                    phy_duplex = (reg0 >> 8)&1;
163                    break;
164                }
165            } else {
166                /* parallel detection or fixed speed */
167                phy_pause = (reg4 & 0x0400) >> 10;
168                phy_speed = (reg0 & 0x40 ? 2 : (reg0 >> 13)&1);
169                phy_duplex = (reg0 >> 8)&1;
170            }
171
172            if (port == 0) {
173                es_w32_mask(LTQ_ES_RGMII_CTL_REG_P0SPD,
174                        LTQ_ES_RGMII_CTL_REG_P0SPD_VAL(phy_speed),
175                        rgmii_ctl);
176                es_w32_mask(LTQ_ES_RGMII_CTL_REG_P0DUP,
177                        LTQ_ES_RGMII_CTL_REG_P0DUP_VAL(phy_duplex),
178                        rgmii_ctl);
179                es_w32_mask(LTQ_ES_RGMII_CTL_REG_P0FCE,
180                        LTQ_ES_RGMII_CTL_REG_P0FCE_VAL(phy_pause),
181                        rgmii_ctl);
182
183                es_w32_mask(0, LTQ_ES_P0_CTL_REG_FLP, p0_ctl);
184            } else {
185                es_w32_mask(LTQ_ES_RGMII_CTL_REG_P1SPD,
186                        LTQ_ES_RGMII_CTL_REG_P1SPD_VAL(phy_speed),
187                        rgmii_ctl);
188                es_w32_mask(LTQ_ES_RGMII_CTL_REG_P1DUP,
189                        LTQ_ES_RGMII_CTL_REG_P1DUP_VAL(phy_duplex),
190                        rgmii_ctl);
191                es_w32_mask(LTQ_ES_RGMII_CTL_REG_P1FCE,
192                        LTQ_ES_RGMII_CTL_REG_P0FCE_VAL(phy_pause),
193                        rgmii_ctl);
194
195                es_w32_mask(1, LTQ_ES_P0_CTL_REG_FLP, p1_ctl);
196            }
197        }
198    }
199    old_link_status[port] = new_link_status;
200}
201
202static void _switchip_mdio_poll(struct work_struct *work)
203{
204    if (es_r32(sw_gctl0) & LTQ_ES_SW_GCTL0_REG_SE) {
205        _switchip_check_phy_status(0);
206        _switchip_check_phy_status(1);
207    }
208
209    queue_delayed_work(mdio_poll_workqueue, &mdio_poll_work, HZ/2);
210}
211
212static void switchip_mdio_poll_init(void)
213{
214    mdio_poll_workqueue = create_workqueue("SVIP MDIP poll");
215    INIT_DELAYED_WORK(&mdio_poll_work, _switchip_mdio_poll);
216
217    queue_delayed_work(mdio_poll_workqueue, &mdio_poll_work, HZ/2);
218
219}
220
221unsigned short switchip_phy_read(unsigned int phyaddr, unsigned int regaddr)
222{
223    /* TODO: protect MDIO access with semaphore */
224    es_w32(LTQ_ES_MDIO_CTL_REG_MBUSY
225           | LTQ_ES_MDIO_CTL_REG_OP_VAL(2) /* read operation */
226           | LTQ_ES_MDIO_CTL_REG_PHYAD_VAL(phyaddr)
227           | LTQ_ES_MDIO_CTL_REG_REGAD_VAL(regaddr), mdio_ctl);
228    while (es_r32(mdio_ctl) & LTQ_ES_MDIO_CTL_REG_MBUSY);
229
230    return es_r32(mdio_data) & 0xFFFF;
231}
232EXPORT_SYMBOL(switchip_phy_read);
233
234void switchip_phy_write(unsigned int phyaddr, unsigned int regaddr,
235            unsigned short data)
236{
237    /* TODO: protect MDIO access with semaphore */
238    es_w32(LTQ_ES_MDIO_CTL_REG_WD_VAL(data)
239           | LTQ_ES_MDIO_CTL_REG_MBUSY
240           | LTQ_ES_MDIO_CTL_REG_OP_VAL(1) /* write operation */
241           | LTQ_ES_MDIO_CTL_REG_PHYAD_VAL(phyaddr)
242           | LTQ_ES_MDIO_CTL_REG_REGAD_VAL(regaddr), mdio_ctl);
243    while (es_r32(mdio_ctl) & LTQ_ES_MDIO_CTL_REG_MBUSY);
244
245    return;
246}
247EXPORT_SYMBOL(switchip_phy_write);
248
249const static u32 switch_reset_offset_000[] = {
250    /*b8000000:*/ 0xffffffff, 0x00000001, 0x00000001, 0x00000003,
251    /*b8000010:*/ 0x04070001, 0x04070001, 0x04070001, 0xffffffff,
252    /*b8000020:*/ 0x00001be8, 0x00001be8, 0x00001be8, 0xffffffff,
253    /*b8000030:*/ 0x00000000, 0x00000000, 0x00080004, 0x00020001,
254    /*b8000040:*/ 0x00000000, 0x00000000, 0x00080004, 0x00020001,
255    /*b8000050:*/ 0x00000000, 0x00000000, 0x00080004, 0x00020001,
256    /*b8000060:*/ 0x00000000, 0x00000000, 0x00081000, 0x001f7777,
257    /*b8000070:*/ 0x00000000, 0x00000000, 0x0c00ac2b, 0x0000fa50,
258    /*b8000080:*/ 0x00001000, 0x00001800, 0x00000000, 0x00000000,
259    /*b8000090:*/ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
260    /*b80000a0:*/ 0x00000000, 0x00000050, 0x00000010, 0x00000000,
261    /*b80000b0:*/ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
262    /*b80000c0:*/ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
263    /*b80000d0:*/ 0xffffffff, 0x00000000, 0x00000000
264};
265const static u32 switch_reset_offset_100[] = {
266    /*b8000100:*/ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
267    /*b8000110:*/ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
268    /*b8000120:*/ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
269    /*b8000130:*/ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
270    /*b8000140:*/ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
271    /*b8000150:*/ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
272    /*b8000160:*/ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
273    /*b8000170:*/ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
274    /*b8000180:*/ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
275    /*b8000190:*/ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
276    /*b80001a0:*/ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
277    /*b80001b0:*/ 0x00000000, 0x00000000
278};
279
280/*
281 * Switch Reset.
282 */
283void switchip_reset(void)
284{
285    volatile unsigned int *reg;
286    volatile unsigned int rdreg;
287    int i;
288
289    sys1_w32(SYS1_CLKENR_ETHSW, clkenr);
290    asm("sync");
291
292    /* disable P0 */
293    es_w32_mask(0, LTQ_ES_P0_CTL_REG_SPS_VAL(1), p0_ctl);
294    /* disable P1 */
295    es_w32_mask(0, LTQ_ES_P0_CTL_REG_SPS_VAL(1), p1_ctl);
296    /* disable P2 */
297    es_w32_mask(0, LTQ_ES_P0_CTL_REG_SPS_VAL(1), p2_ctl);
298
299    /**************************************
300     * BEGIN: Procedure to clear MAC table
301     **************************************/
302    for (i = 0; i < 3; i++) {
303        int result;
304
305        /* check if access engine is available */
306        while (es_r32(adr_tb_st2) & LTQ_ES_ADR_TB_ST2_REG_BUSY);
307
308        /* initialise to first address */
309        es_w32(LTQ_ES_ADR_TB_CTL2_REG_CMD_VAL(3)
310               | LTQ_ES_ADR_TB_CTL2_REG_AC_VAL(0), adr_tb_ctl2);
311
312        /* wait while busy */
313        while (es_r32(adr_tb_st2) & LTQ_ES_ADR_TB_ST2_REG_BUSY);
314
315        /* setup the portmap */
316        es_w32_mask(0, LTQ_ES_ADR_TB_CTL1_REG_PMAP_VAL(1 << i),
317                adr_tb_ctl1);
318
319        do {
320            /* search for addresses by port */
321            es_w32(LTQ_ES_ADR_TB_CTL2_REG_CMD_VAL(2)
322                   | LTQ_ES_ADR_TB_CTL2_REG_AC_VAL(9), adr_tb_ctl2);
323
324            /* wait while busy */
325            while (es_r32(adr_tb_st2) & LTQ_ES_ADR_TB_ST2_REG_BUSY);
326
327            result = LTQ_ES_ADR_TB_ST2_REG_RSLT_GET(es_r32(adr_tb_st2));
328            if (result == 0x101) {
329                printk(KERN_ERR "%s, cmd error\n", __func__);
330                return;
331            }
332            /* if Command OK, address found... */
333            if (result == 0) {
334                unsigned char mac[6];
335
336                mac[5] = (es_r32(adr_tb_st0) >> 0) & 0xff;
337                mac[4] = (es_r32(adr_tb_st0) >> 8) & 0xff;
338                mac[3] = (es_r32(adr_tb_st0) >> 16) & 0xff;
339                mac[2] = (es_r32(adr_tb_st0) >> 24) & 0xff;
340                mac[1] = (es_r32(adr_tb_st1) >> 0) & 0xff;
341                mac[0] = (es_r32(adr_tb_st1) >> 8) & 0xff;
342
343                /* setup address */
344                es_w32((mac[5] << 0) |
345                       (mac[4] << 8) |
346                       (mac[3] << 16) |
347                       (mac[2] << 24), adr_tb_ctl0);
348                es_w32(LTQ_ES_ADR_TB_CTL1_REG_PMAP_VAL(1<<i) |
349                       LTQ_ES_ADR_TB_CTL1_REG_FID_VAL(0) |
350                       (mac[0] << 8) |
351                       (mac[1] << 0), adr_tb_ctl1);
352                /* erase address */
353
354                es_w32(LTQ_ES_ADR_TB_CTL2_REG_CMD_VAL(1) |
355                       LTQ_ES_ADR_TB_CTL2_REG_AC_VAL(15),
356                       adr_tb_ctl2);
357
358                /* wait, while busy */
359                while (es_r32(adr_tb_st2) &
360                       LTQ_ES_ADR_TB_ST2_REG_BUSY);
361            }
362        } while (result == 0);
363    }
364    /**************************************
365     * END: Procedure to clear MAC table
366     **************************************/
367
368    /* reset RMON counters */
369    es_w32(LTQ_ES_RMON_CTL_REG_BAS | LTQ_ES_RMON_CTL_REG_CAC_VAL(3),
370           rmon_ctl);
371
372    /* bring all registers to reset state */
373    reg = LTQ_ES_PS_REG;
374    for (i = 0; i < ARRAY_SIZE(switch_reset_offset_000); i++) {
375        if ((reg == LTQ_ES_PS_REG) ||
376            (reg >= LTQ_ES_ADR_TB_CTL0_REG &&
377             reg <= LTQ_ES_ADR_TB_ST2_REG))
378            continue;
379
380        if (switch_reset_offset_000[i] != 0xFFFFFFFF) {
381            /* write reset value to register */
382            *reg = switch_reset_offset_000[i];
383            /* read register value back */
384            rdreg = *reg;
385            if (reg == LTQ_ES_SW_GCTL1_REG)
386                rdreg &= ~LTQ_ES_SW_GCTL1_REG_BISTDN;
387            /* compare read value with written one */
388            if (rdreg != switch_reset_offset_000[i]) {
389                printk(KERN_ERR "%s,%d: reg %08x mismatch "
390                       "[has:%08x, expect:%08x]\n",
391                       __func__, __LINE__,
392                       (unsigned int)reg, rdreg,
393                       switch_reset_offset_000[i]);
394            }
395        }
396        reg++;
397    }
398
399    reg = LTQ_ES_VLAN_FLT0_REG;
400    for (i = 0; i < ARRAY_SIZE(switch_reset_offset_100); i++) {
401        *reg = switch_reset_offset_100[i];
402        rdreg = *reg;
403        if (rdreg != switch_reset_offset_100[i]) {
404            printk(KERN_ERR "%s,%d: reg %08x mismatch "
405                   "[has:%08x, expect:%08x]\n", __func__, __LINE__,
406                   (unsigned int)reg, rdreg,
407                   switch_reset_offset_100[i]);
408        }
409        reg++;
410    }
411}
412EXPORT_SYMBOL(switchip_reset);
413
414static u32 get_phy_oui(unsigned char phy_addr)
415{
416    u32 oui;
417    int i, bit, byte, shift, w;
418    u16 reg_id[2];
419
420    /* read PHY identifier registers 1 and 2 */
421    reg_id[0] = switchip_phy_read(phy_addr, 2);
422    reg_id[1] = switchip_phy_read(phy_addr, 3);
423
424    oui = 0;
425    w = 1;
426    shift = 7;
427    byte = 1;
428    for (i = 0, bit = 10; i <= 21; i++, bit++) {
429        oui |= ((reg_id[w] & (1<<bit)) ? 1 : 0) << shift;
430        if (!(shift % 8)) {
431            byte++;
432            if (byte == 2)
433                shift = 15;
434            else
435                shift = 21;
436        } else {
437            shift--;
438        }
439        if (w == 1 && bit == 15) {
440            bit = -1;
441            w = 0;
442        }
443    }
444    return oui;
445}
446
447/*
448 * Switch Initialization.
449 */
450int switchip_init(void)
451{
452    int eth_port, phy_present = 0;
453    u16 reg, mode;
454
455    sys1_w32(SYS1_CLKENR_ETHSW, clkenr);
456    asm("sync");
457
458    /* Enable Switch, if not already done so */
459    if ((es_r32(sw_gctl0) & LTQ_ES_SW_GCTL0_REG_SE) == 0)
460        es_w32_mask(0, LTQ_ES_SW_GCTL0_REG_SE, sw_gctl0);
461    /* Wait for completion of MBIST */
462    while (LTQ_ES_SW_GCTL1_REG_BISTDN_GET(es_r32(sw_gctl1)) == 0);
463
464    switchip_reset();
465
466    mode = LTQ_ES_RGMII_CTL_REG_IS_GET(es_r32(rgmii_ctl));
467    eth_port = (mode == 2 ? 1 : 0);
468
469    /* Set the primary port(port toward backplane) as sniffer port,
470       changing from P2 which is the reset setting */
471    es_w32_mask(LTQ_ES_SW_GCTL0_REG_SNIFFPN,
472            LTQ_ES_SW_GCTL0_REG_SNIFFPN_VAL(eth_port),
473            sw_gctl0);
474
475    /* Point MDIO state machine to invalid PHY addresses 8 and 9 */
476    es_w32_mask(0, LTQ_ES_SW_GCTL0_REG_PHYBA, sw_gctl0);
477
478    /* Add CRC for packets from DMA to PMAC.
479       Remove CRC for packets from PMAC to DMA. */
480    es_w32(LTQ_ES_PMAC_HD_CTL_RC | LTQ_ES_PMAC_HD_CTL_AC, pmac_hd_ctl);
481
482    phy_oui = get_phy_oui(0);
483    switch (phy_oui) {
484#ifdef CONFIG_LANTIQ_MACH_EASY336
485    case PHY_OUI_PMC:
486        phy_address[0] = (mode == 2 ? -1 : 2);
487        phy_address[1] = (mode == 2 ? 2 : -1);
488        break;
489#endif
490    case PHY_OUI_VITESSE:
491    default:
492        phy_oui = PHY_OUI_DEFAULT;
493        phy_address[0] = (mode == 2 ? 1 : 0);
494        phy_address[1] = (mode == 2 ? 0 : 1);
495        break;
496    }
497
498    /****** PORT 0 *****/
499    reg = switchip_phy_read(phy_address[0], 1);
500    if ((reg != 0x0000) && (reg != 0xffff)) {
501        /* PHY connected? */
502        phy_present |= 1;
503        /* Set Rx- and TxDelay in case of RGMII */
504        switch (mode) {
505        case 0: /* *RGMII,RGMII */
506        case 2: /* RGMII,*GMII */
507            /* program clock delay in PHY, not in SVIP */
508
509            es_w32_mask(LTQ_ES_RGMII_CTL_REG_P0RDLY, 0, rgmii_ctl);
510            es_w32_mask(LTQ_ES_RGMII_CTL_REG_P0TDLY, 0, rgmii_ctl);
511            if (phy_oui == PHY_OUI_VITESSE ||
512                phy_oui == PHY_OUI_DEFAULT) {
513                switchip_phy_write(phy_address[0], 31, 0x0001);
514                switchip_phy_write(phy_address[0], 28, 0xA000);
515                switchip_phy_write(phy_address[0], 31, 0x0000);
516            }
517        default:
518            break;
519        }
520        if (phy_oui == PHY_OUI_VITESSE ||
521            phy_oui == PHY_OUI_DEFAULT) {
522            /* Program PHY advertisements and
523             * restart auto-negotiation */
524            switchip_phy_write(phy_address[0], 4, 0x05E1);
525            switchip_phy_write(phy_address[0], 9, 0x0300);
526            switchip_phy_write(phy_address[0], 0, 0x3300);
527        } else {
528            reg = switchip_phy_read(phy_address[1], 0);
529            reg |= 0x1000; /* auto-negotiation enable */
530            switchip_phy_write(phy_address[1], 0, reg);
531            reg |= 0x0200; /* auto-negotiation restart */
532            switchip_phy_write(phy_address[1], 0, reg);
533        }
534    } else {
535        /* Force SWITCH link with highest capability:
536         * 100M FD for MII
537         * 1G FD for GMII/RGMII
538         */
539        switch (mode) {
540        case 1: /* *MII,MII */
541        case 3: /* *MII,RGMII */
542            es_w32_mask(0, LTQ_ES_RGMII_CTL_REG_P0SPD_VAL(1),
543                    rgmii_ctl);
544            es_w32_mask(0, LTQ_ES_RGMII_CTL_REG_P0DUP_VAL(1),
545                    rgmii_ctl);
546            break;
547        case 0: /* *RGMII,RGMII */
548        case 2: /* RGMII,*GMII */
549            es_w32_mask(0, LTQ_ES_RGMII_CTL_REG_P0SPD_VAL(2),
550                    rgmii_ctl);
551            es_w32_mask(0, LTQ_ES_RGMII_CTL_REG_P0DUP_VAL(1),
552                    rgmii_ctl);
553
554            es_w32_mask(LTQ_ES_RGMII_CTL_REG_P0RDLY, 0, rgmii_ctl);
555            es_w32_mask(0, LTQ_ES_RGMII_CTL_REG_P0TDLY_VAL(2),
556                    rgmii_ctl);
557            break;
558        }
559
560        es_w32_mask(0, LTQ_ES_P0_CTL_REG_FLP, p0_ctl);
561    }
562
563    /****** PORT 1 *****/
564    reg = switchip_phy_read(phy_address[1], 1);
565    if ((reg != 0x0000) && (reg != 0xffff)) {
566        /* PHY connected? */
567        phy_present |= 2;
568        /* Set Rx- and TxDelay in case of RGMII */
569        switch (mode) {
570        case 0: /* *RGMII,RGMII */
571        case 3: /* *MII,RGMII */
572            /* program clock delay in PHY, not in SVIP */
573
574            es_w32_mask(LTQ_ES_RGMII_CTL_REG_P1RDLY, 0, rgmii_ctl);
575            es_w32_mask(LTQ_ES_RGMII_CTL_REG_P1TDLY, 0, rgmii_ctl);
576            if (phy_oui == PHY_OUI_VITESSE ||
577                phy_oui == PHY_OUI_DEFAULT) {
578                switchip_phy_write(phy_address[1], 31, 0x0001);
579                switchip_phy_write(phy_address[1], 28, 0xA000);
580                switchip_phy_write(phy_address[1], 31, 0x0000);
581            }
582            break;
583        case 2: /* RGMII,*GMII */
584
585            es_w32_mask(0, LTQ_ES_RGMII_CTL_REG_P1SPD_VAL(2),
586                    rgmii_ctl);
587            es_w32_mask(0, LTQ_ES_RGMII_CTL_REG_P1DUP, rgmii_ctl);
588#ifdef CONFIG_LANTIQ_MACH_EASY336
589            if (phy_oui == PHY_OUI_PMC) {
590                switchip_phy_write(phy_address[1], 24, 0x0510);
591                switchip_phy_write(phy_address[1], 17, 0xA38C);
592                switchip_phy_write(phy_address[1], 17, 0xA384);
593            }
594#endif
595            break;
596        default:
597            break;
598        }
599        /* Program PHY advertisements and restart auto-negotiation */
600        if (phy_oui == PHY_OUI_VITESSE ||
601            phy_oui == PHY_OUI_DEFAULT) {
602            switchip_phy_write(phy_address[1], 4, 0x05E1);
603            switchip_phy_write(phy_address[1], 9, 0x0300);
604            switchip_phy_write(phy_address[1], 0, 0x3300);
605        } else {
606            reg = switchip_phy_read(phy_address[1], 0);
607            reg |= 0x1000; /* auto-negotiation enable */
608            switchip_phy_write(phy_address[1], 0, reg);
609            reg |= 0x0200; /* auto-negotiation restart */
610            switchip_phy_write(phy_address[1], 0, reg);
611        }
612    } else {
613        /* Force SWITCH link with highest capability:
614         * 100M FD for MII
615         * 1G FD for GMII/RGMII
616         */
617        switch (mode) {
618        case 1: /* *MII,MII */
619            es_w32_mask(0, LTQ_ES_RGMII_CTL_REG_P1SPD_VAL(1),
620                    rgmii_ctl);
621            es_w32_mask(0, LTQ_ES_RGMII_CTL_REG_P1DUP, rgmii_ctl);
622            break;
623        case 0: /* *RGMII,RGMII */
624        case 3: /* *MII,RGMII */
625            es_w32_mask(0, LTQ_ES_RGMII_CTL_REG_P1SPD_VAL(2),
626                    rgmii_ctl);
627            es_w32_mask(0, LTQ_ES_RGMII_CTL_REG_P1DUP, rgmii_ctl);
628            es_w32_mask(LTQ_ES_RGMII_CTL_REG_P1RDLY, 0, rgmii_ctl);
629            es_w32_mask(0, LTQ_ES_RGMII_CTL_REG_P1TDLY_VAL(2),
630                    rgmii_ctl);
631            break;
632        case 2: /* RGMII,*GMII */
633            es_w32_mask(0, LTQ_ES_RGMII_CTL_REG_P1SPD_VAL(2),
634                    rgmii_ctl);
635            es_w32_mask(0, LTQ_ES_RGMII_CTL_REG_P1DUP, rgmii_ctl);
636            break;
637        }
638        es_w32_mask(0, LTQ_ES_P0_CTL_REG_FLP, p0_ctl);
639    }
640
641    /*
642     * Allow unknown unicast/multicast and broadcasts
643     * on all ports.
644     */
645
646    es_w32_mask(0, LTQ_ES_SW_GCTL1_REG_UP_VAL(7), sw_gctl1);
647    es_w32_mask(0, LTQ_ES_SW_GCTL1_REG_BP_VAL(7), sw_gctl1);
648    es_w32_mask(0, LTQ_ES_SW_GCTL1_REG_MP_VAL(7), sw_gctl1);
649    es_w32_mask(0, LTQ_ES_SW_GCTL1_REG_RP_VAL(7), sw_gctl1);
650
651    /* Enable LAN port(s) */
652    if (eth_port == 0)
653        es_w32_mask(LTQ_ES_P0_CTL_REG_SPS, 0, p0_ctl);
654    else
655        es_w32_mask(LTQ_ES_P0_CTL_REG_SPS, 0, p1_ctl);
656    /* Enable CPU Port (Forwarding State) */
657    es_w32_mask(LTQ_ES_P0_CTL_REG_SPS, 0, p2_ctl);
658
659    if (phy_present)
660        switchip_mdio_poll_init();
661
662    return 0;
663}
664EXPORT_SYMBOL(switchip_init);
665
666device_initcall(switchip_init);
667

Archive Download this file



interactive