Changeset e73f8a17 in rtems


Ignore:
Timestamp:
Jun 11, 2009, 8:03:14 PM (10 years ago)
Author:
Joel Sherrill <joel.sherrill@…>
Branches:
4.10, 4.11, master
Children:
9e06eb1
Parents:
34e64879
Message:

2009-06-11 Joel Sherrill <joel.sherrill@…>

  • network/network.c: Attempt to support csb637 PHY.
Location:
c/src/lib/libbsp/arm/csb337
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • c/src/lib/libbsp/arm/csb337/ChangeLog

    r34e64879 re73f8a17  
     12009-06-11      Joel Sherrill <joel.sherrill@OARcorp.com>
     2
     3        * network/network.c: Attempt to support csb637 PHY.
     4
    152009-06-04      Xi Yang <hiyangxi@gmail.com>
    26
  • c/src/lib/libbsp/arm/csb337/network/network.c

    r34e64879 re73f8a17  
    3333
    3434#include <irq.h>
    35 
    36 
    37 /* interrupt stuff */
    38 #define EMAC_INT_PRIORITY       0       /* lowest priority */
    39 
    40 /*  RTEMS event used by interrupt handler to start receive daemon. */
    41 #define START_RECEIVE_EVENT  RTEMS_EVENT_1
    42 
    43 /* RTEMS event used to start transmit daemon. */
    44 #define START_TRANSMIT_EVENT    RTEMS_EVENT_2
     35#include <bspopts.h>
     36
     37#if csb637
     38  /* Bit defines for the PHY Status Register #1 (phy address 0x01) */
     39  /* 1 = PHY able to perform 100BASE-T4 */
     40  #define PHY_STAT_100BASE_T4     BIT15
     41  /* 1 = PHY able to perform full-duplex 100BASE-X */
     42  #define PHY_STAT_100BASE_X_FDX  BIT14
     43  /* 1 = PHY able to perform half-duplex 100BASE-X */
     44  #define PHY_STAT_100BASE_X_HDX  BIT13
     45  /* 1 = PHY able to operate at 10 Mbps in full-duplex mode */
     46  #define PHY_STAT_10BASE_FDX     BIT12
     47  /* 1 = PHY able to operate at 10 Mbps in half-duplex mode */
     48  #define PHY_STAT_10BASE_HDX     BIT11
     49  /* 1 = PHY will accept management frames with preamble suppressed */
     50  #define PHY_STAT_MF_PREAMBLE    BIT6
     51  /* 1 = Auto-negotiation complete */
     52  #define PHY_STAT_AUTO_NEG_DONE  BIT5
     53  /* 1 = Remote fault condition detected */
     54  #define PHY_STAT_REM_FLT        BIT4
     55  /* 1 = PHY is able to perform Auto-Negotiation */
     56  #define PHY_STAT_AUTO_NEG_ABLE  BIT3
     57  /* 1 = Link is up */
     58  #define PHY_STAT_LINK_UP        BIT2
     59  /* 1 = Jabber condition detected */
     60  #define PHY_STAT_JABBER         BIT1
     61  /* 1 = Extended register capabilities */
     62  #define PHY_STAT_EXT_REG        BIT0
     63
     64  /* Bit defines for the Auxillary Mode 3 register */
     65  #define PHY_AUX_MODE2_TRAFFIC_LED   BIT6
     66#endif
     67
     68  /* interrupt stuff */
     69  #define EMAC_INT_PRIORITY       0       /* lowest priority */
     70
     71  /*  RTEMS event used by interrupt handler to start receive daemon. */
     72  #define START_RECEIVE_EVENT  RTEMS_EVENT_1
     73
     74  /* RTEMS event used to start transmit daemon. */
     75  #define START_TRANSMIT_EVENT    RTEMS_EVENT_2
    4576
    4677rtems_isr at91rm9200_emac_isr(rtems_vector_number vector);
     
    5182/* Replace the first value with the clock's interrupt name. */
    5283rtems_irq_connect_data at91rm9200_emac_isr_data = {
    53     AT91RM9200_INT_EMAC,   
     84    AT91RM9200_INT_EMAC,
    5485    (rtems_irq_hdl)at91rm9200_emac_isr,
    5586    at91rm9200_emac_isr_on,
     
    99130     */
    100131    struct arpcom                    arpcom;
    101    
     132
    102133    /*
    103134     * Interrupt vector
    104135     */
    105136    rtems_vector_number             vector;
    106    
     137
    107138    /*
    108139     *  Indicates configuration
    109140     */
    110141    int                             acceptBroadcast;
    111    
     142
    112143    /*
    113144     * Task waiting for interrupts
     
    115146    rtems_id                        rxDaemonTid;
    116147    rtems_id                        txDaemonTid;
    117    
     148
    118149    /*
    119150     * current receive header
     
    133164    unsigned long                   rxBadCRC;
    134165    unsigned long                   rxCollision;
    135    
     166
    136167    unsigned long                   txInterrupts;
    137168    unsigned long                   txSingleCollision;
     
    157188
    158189/* function prototypes */
    159 int rtems_at91rm9200_emac_attach (struct rtems_bsdnet_ifconfig *config, 
     190int rtems_at91rm9200_emac_attach (struct rtems_bsdnet_ifconfig *config,
    160191                                  void *chip);
    161192void at91rm9200_emac_init(void *arg);
     
    167198void at91rm9200_emac_rxDaemon(void *arg);
    168199void at91rm9200_emac_stats (at91rm9200_emac_softc_t *sc);
    169 static int at91rm9200_emac_ioctl (struct ifnet *ifp, 
    170                                   ioctl_command_t command, 
     200static int at91rm9200_emac_ioctl (struct ifnet *ifp,
     201                                  ioctl_command_t command,
    171202                                  caddr_t data);
     203
     204
     205/*
     206 * phyread(): Read the PHY
     207 */
     208uint32_t phyread(uint8_t reg)
     209{
     210  EMAC_REG(EMAC_MAN) = (0x01 << 30  /* Start of Frame Delimiter */
     211            | 0x02 << 28            /* Operation, 0x01 = Write, 0x02 = Read */
     212            | 0x00 << 23            /* Phy Number, 0 as we only have one */
     213            | reg << 18             /* Phy Register */
     214            | 0x02 << 16);          /* must be 0x02 for turn around field */
     215
     216  /* wait for phy read to complete (was udelay(5000)) */
     217  rtems_task_wake_after(1);
     218
     219  #if EMAC_DBG
     220    printk(
     221      "EMAC: Phy 0, Reg %d, Read 0x%04lx.\n",
     222       reg,
     223       (EMAC_REG(EMAC_MAN) & 0xffff)
     224    );
     225  #endif
     226
     227  return EMAC_REG(EMAC_MAN) & 0xffff;
     228}
     229
     230/*
     231 * phywrite(): Write the PHY
     232 */
     233void phywrite(uint8_t reg, uint16_t data)
     234{
     235  EMAC_REG(EMAC_MAN) = (0x01 << 30 /* Start of Frame Delimiter */
     236             | 0x01 << 28          /* Operation, 0x01 = Write, 0x02 = Read */
     237             | 0x00 << 23          /* Phy Number, BCM5221 is address 0 */
     238             | reg << 18           /* Phy Register */
     239             | 0x02 << 16          /* must be 0x02 for turn around field */
     240             | data);
     241  #if EMAC_DBG
     242    printf("EMAC: Phy 0, Reg %d, Write 0x%04x.\n", reg, data);
     243  #endif
     244
     245  /* wait for phy write to complete (was udelay(5000)) */
     246  rtems_task_wake_after(1);
     247}
    172248
    173249
     
    182258    char *unitname;
    183259    void *p;
    184    
     260
    185261    /* an array of receive buffer descriptors -- avoid type punned warning */
    186262    p = (void *)&at91rm9200_emac_rxbuf_hdrs;
     
    197273    if ((unitnumber = rtems_bsdnet_parse_driver_name (config, &unitname)) < 0)
    198274        return 0;
    199    
     275
    200276    /*
    201277     * Is driver free?
     
    210286        return 0;
    211287    }
    212    
     288
    213289    /*
    214290     *  zero out the control structure
    215291     */
    216    
     292
    217293    memset( &softc, 0, sizeof(softc) );
    218    
    219    
     294
     295
    220296    /* get the MAC address from the chip */
    221297    softc.arpcom.ac_enaddr[0] = (EMAC_REG(EMAC_SA1L) >> 0) & 0xff;
     
    226302    softc.arpcom.ac_enaddr[5] = (EMAC_REG(EMAC_SA1H) >> 8) & 0xff;
    227303
     304    #if 0
     305      printk( "MAC=%02x:%02x:%02x:%02x:%02x:%02x\n",
     306        softc.arpcom.ac_enaddr[0],
     307        softc.arpcom.ac_enaddr[1],
     308        softc.arpcom.ac_enaddr[2],
     309        softc.arpcom.ac_enaddr[3],
     310        softc.arpcom.ac_enaddr[4],
     311        softc.arpcom.ac_enaddr[5]
     312      );
     313    #endif
     314
    228315    if (config->mtu) {
    229316        mtu = config->mtu;
     
    233320
    234321    softc.acceptBroadcast = !config->ignore_broadcast;
    235    
     322
    236323    /*
    237324     * Set up network interface values
     
    249336        ifp->if_snd.ifq_maxlen = ifqmaxlen;
    250337    }
    251    
     338
    252339    softc.rx_buf_idx = 0;
    253340
     
    262349void at91rm9200_emac_init(void *arg)
    263350{
    264     at91rm9200_emac_softc_t     *sc = arg;     
     351    at91rm9200_emac_softc_t     *sc = arg;
    265352    struct ifnet *ifp = &sc->arpcom.ac_if;
    266    
    267     /* 
    268      *This is for stuff that only gets done once (at91rm9200_emac_init() 
    269      * gets called multiple times 
     353
     354    /*
     355     *This is for stuff that only gets done once (at91rm9200_emac_init()
     356     * gets called multiple times
    270357     */
    271358    if (sc->txDaemonTid == 0) {
    272359        /* Set up EMAC hardware */
    273360        at91rm9200_emac_init_hw(sc);
    274        
     361
    275362        /*      Start driver tasks */
    276         sc->rxDaemonTid = rtems_bsdnet_newproc("ENrx", 
    277                                                4096, 
    278                                                at91rm9200_emac_rxDaemon, 
     363        sc->rxDaemonTid = rtems_bsdnet_newproc("ENrx",
     364                                               4096,
     365                                               at91rm9200_emac_rxDaemon,
    279366                                               sc);
    280         sc->txDaemonTid = rtems_bsdnet_newproc("ENtx", 
    281                                                4096, 
    282                                                at91rm9200_emac_txDaemon, 
     367        sc->txDaemonTid = rtems_bsdnet_newproc("ENtx",
     368                                               4096,
     369                                               at91rm9200_emac_txDaemon,
    283370                                               sc);
    284371    } /* if txDaemonTid */
    285    
     372
    286373    /* set our priority in the AIC */
    287374    AIC_SMR_REG(AIC_SMR_EMAC) = AIC_SMR_PRIOR(EMAC_INT_PRIORITY);
    288    
     375
    289376    /* install the interrupt handler */
    290377    BSP_install_rtems_irq_handler(&at91rm9200_emac_isr_data);
    291    
     378
    292379    /* EMAC doesn't support promiscuous, so ignore requests */
    293380    if (ifp->if_flags & IFF_PROMISC) {
     
    300387     */
    301388    ifp->if_flags |= IFF_RUNNING;
    302    
     389
    303390    /* Enable TX/RX and clear the statistics counters */
    304391    EMAC_REG(EMAC_CTL) = (EMAC_CTL_TE | EMAC_CTL_RE | EMAC_CTL_CSR);
    305    
     392
    306393    /* clear any pending interrupts */
    307394    EMAC_REG(EMAC_TSR) = 0xffffffff;
    308395    EMAC_REG(EMAC_RSR) = 0xffffffff;
    309    
     396
    310397} /* at91rm9200_emac_init() */
    311398
     
    343430                          BIT18 |   /* rx collistion */
    344431                          BIT19 );  /* rx clock   */
    345                          
     432
    346433
    347434    /* Enable the clock to the EMAC */
     
    355442
    356443    /* last one needs the wrapbit set as well  */
    357     rxbuf_hdrs[i].address = ((unsigned long)(&rxbuf[i * RX_BUFFER_SIZE]) | 
     444    rxbuf_hdrs[i].address = ((unsigned long)(&rxbuf[i * RX_BUFFER_SIZE]) |
    358445                             RXBUF_ADD_WRAP);
    359446    rxbuf_hdrs[i].status = 0x00000000;
    360    
     447
    361448    /* point to our receive buffer queue */
    362449    EMAC_REG(EMAC_RBQP) = (unsigned long)rxbuf_hdrs;
    363    
     450
    364451    /* clear any left over status bits */
    365452    EMAC_REG(EMAC_RSR)  &= ~(EMAC_RSR_OVR | EMAC_RSR_REC | EMAC_RSR_BNA);
    366    
     453
    367454    /* set the MII clock divder to MCK/64 */
    368455    EMAC_REG(EMAC_CFG) &= EMAC_CFG_CLK_MASK;
    369456    EMAC_REG(EMAC_CFG) = (EMAC_CFG_CLK_64 | EMAC_CFG_BIG | EMAC_CFG_FD);
    370    
     457
    371458    /* enable the MII interface */
    372459    EMAC_REG(EMAC_CTL) = EMAC_CTL_MPE;
    373    
     460
    374461    /* Set PHY LED2 to combined Link/Activity and enable pulse stretching */
     462    #if csb637
     463     /* Set PHY LED modes.  Traffic Meter Mode for ACTLED
     464      * Set Bit 6 - Traffic Mode on
     465      */
     466     phywrite(0x1b, PHY_AUX_MODE2_TRAFFIC_LED);
     467    #else
     468      /* must be csb337 */
     469      phywrite( 18, 0x0d0a );
     470    #endif
     471
     472    #if 0
    375473    EMAC_REG(EMAC_MAN) = (0x01 << 30 |   /* Start of Frame Delimiter */
    376474                          0x01 << 28 |   /* Operation, 0x01 = Write */
     
    379477                          0x02 << 16 |   /* must be 0x02 */
    380478                          0x0D0A);       /* Write data (0x0000 if read) */
    381    
     479   #endif
     480
    382481} /* at91rm9200_emac_init_hw() */
    383482
     
    385484{
    386485    at91rm9200_emac_softc_t *sc = ifp->if_softc;
    387    
     486
    388487    rtems_event_send(sc->txDaemonTid, START_TRANSMIT_EVENT);
    389488    ifp->if_flags |= IFF_OACTIVE;
     
    393492{
    394493    struct ifnet *ifp = &sc->arpcom.ac_if;
    395    
     494
    396495    ifp->if_flags &= ~IFF_RUNNING;
    397    
     496
    398497    /*
    399498     * Stop the transmitter and receiver.
     
    411510    struct mbuf *m;
    412511    rtems_event_set events;
    413    
     512
    414513    for (;;)
    415514    {
    416515        /* turn on TX interrupt, then wait for one */
    417516        EMAC_REG(EMAC_IER) = EMAC_INT_TCOM;     /* Transmit complete */
    418        
     517
    419518        rtems_bsdnet_event_receive(
    420519            START_TRANSMIT_EVENT,
     
    422521            RTEMS_NO_TIMEOUT,
    423522            &events);
    424        
     523
    425524        /* Send packets till queue is empty */
    426525        for (;;)
     
    443542    delay_cnt = 0;
    444543    /* printf("at91rm9200_emac_sendpacket %p\n", m); */
    445    
     544
    446545    /* Wait for EMAC Transmit Queue to become available. */
    447546    while (((EMAC_REG(EMAC_TSR) & EMAC_TSR_COMP) == 0) &&
    448547           ((EMAC_REG(EMAC_TSR) & EMAC_TSR_TXIDLE) == 0))
    449        
     548
    450549    {
    451550        delay_cnt++;
     
    453552        continue;
    454553    }
    455    
     554
    456555    /* copy the mbuf chain into the transmit buffer */
    457     l = m;     
     556    l = m;
    458557    while (l != NULL) {
    459         memcpy(((char *)txbuf + pkt_offset),  /* offset into pkt for mbuf */ 
    460                (char *)mtod(l, void *),       /* cast to void */ 
     558        memcpy(((char *)txbuf + pkt_offset),  /* offset into pkt for mbuf */
     559               (char *)mtod(l, void *),       /* cast to void */
    461560               l->m_len);                     /* length of this mbuf */
    462        
     561
    463562        pkt_offset += l->m_len;               /* update offset */
    464         l = l->m_next;                        /* get next mbuf, if any */     
    465     }
    466    
     563        l = l->m_next;                        /* get next mbuf, if any */
     564    }
     565
    467566    /* free the mbuf chain we just copied */
    468567    m_freem(m);
    469    
     568
    470569    /* clear any pending status */
    471570    EMAC_REG(EMAC_TSR) = (EMAC_TSR_OVR | EMAC_TSR_COL | EMAC_TSR_RLE
    472                           | EMAC_TSR_COMP | EMAC_TSR_UND); 
    473    
     571                          | EMAC_TSR_COMP | EMAC_TSR_UND);
     572
    474573    /* tell the EMAC about our buffer */
    475574    EMAC_REG(EMAC_TAR) = (unsigned long)txbuf;
     
    487586    rtems_event_set events;
    488587    int pktlen;
    489    
     588
    490589    /* Input packet handling loop */
    491590    for (;;) {
     
    494593                              EMAC_INT_RBNA |   /* Receive buf not available */
    495594                              EMAC_INT_ROVR);   /* Receive overrun */
    496        
     595
    497596        rtems_bsdnet_event_receive(
    498597            START_RECEIVE_EVENT,
     
    500599            RTEMS_NO_TIMEOUT,
    501600            &events);
    502        
     601
    503602        if (EMAC_REG(EMAC_RSR) & EMAC_RSR_BNA) {
    504603            printf("1: EMAC_BNA\n");
     
    511610        /* clear the receive status as we do not use it anyway */
    512611        EMAC_REG(EMAC_RSR) = (EMAC_RSR_REC | EMAC_RSR_OVR | EMAC_RSR_BNA);
    513        
     612
    514613        /* scan the buffer descriptors looking for any with data in them */
    515614        while (rxbuf_hdrs[sc->rx_buf_idx].address & RXBUF_ADD_OWNED) {
    516615            pktlen = rxbuf_hdrs[sc->rx_buf_idx].status & RXBUF_STAT_LEN_MASK;
    517            
     616
    518617            /* get an mbuf this packet */
    519618            MGETHDR(m, M_WAIT, MT_DATA);
    520            
     619
    521620            /* now get a cluster pointed to by the mbuf */
    522621            /* since an mbuf by itself is too small */
    523622            MCLGET(m, M_WAIT);
    524            
     623
    525624            /* set the type of mbuf to ifp (ethernet I/F) */
    526625            m->m_pkthdr.rcvif = ifp;
    527626            m->m_nextpkt = 0;
    528            
    529             /* copy the packet into the cluster pointed to by the mbuf */   
     627
     628            /* copy the packet into the cluster pointed to by the mbuf */
    530629            memcpy((char *)m->m_ext.ext_buf,
    531630                   (char *)(rxbuf_hdrs[sc->rx_buf_idx].address & 0xfffffffc),
    532631                   pktlen);
    533            
     632
    534633            /* Release the buffer ASAP back to the EMAC */
    535634            rxbuf_hdrs[sc->rx_buf_idx].address &= ~RXBUF_ADD_OWNED;
    536            
     635
    537636            /* set the length of the mbuf */
    538637            m->m_len = pktlen - (sizeof(struct ether_header) + 4);
    539638            m->m_pkthdr.len = m->m_len;
    540            
     639
    541640            /* strip off the ethernet header from the mbuf */
    542641            /* but save the pointer to it */
     
    549648                sc->rx_buf_idx = 0;
    550649            }
    551            
     650
    552651            /* give all this stuff to the stack */
    553652            ether_input(ifp, eh, m);
    554            
     653
    555654        } /* while ADD_OWNED = 0 */
    556655
     
    564663
    565664    } /* for (;;) */
    566 } /* at91rm9200_emac_rxDaemon() */ 
     665} /* at91rm9200_emac_rxDaemon() */
    567666
    568667
     
    577676    printf ("        Collision:%-8lu",          sc->rxCollision);
    578677    printf ("           Missed:%-8lu\n",                sc->rxMissed);
    579    
     678
    580679    printf (    "    Tx Interrupts:%-8lu",      sc->txInterrupts);
    581680    printf (  "           Deferred:%-8lu",      sc->txDeferred);
     
    600699                          EMAC_INT_ROVR | /* Receive overrun */
    601700                          EMAC_INT_ABT);  /* Abort on DMA transfer */
    602    
     701
    603702    return;
    604703}
     
    612711}
    613712
    614 /* Tests to see if at91rm9200_emac interrupts are enabled, and 
     713/* Tests to see if at91rm9200_emac interrupts are enabled, and
    615714 * returns non-0 if so.
    616715 * If interrupt is not enabled, returns 0.
     
    627726    at91rm9200_emac_softc_t *sc = ifp->if_softc;
    628727    int error = 0;
    629    
     728
    630729    switch (command) {
    631730    case SIOCGIFADDR:
     
    633732        ether_ioctl (ifp, command, data);
    634733        break;
    635        
     734
    636735    case SIOCSIFFLAGS:
    637736        switch (ifp->if_flags & (IFF_UP | IFF_RUNNING))
     
    640739            at91rm9200_emac_stop (sc);
    641740            break;
    642            
     741
    643742        case IFF_UP:
    644743            at91rm9200_emac_init (sc);
    645744            break;
    646            
     745
    647746        case IFF_UP | IFF_RUNNING:
    648747            at91rm9200_emac_stop (sc);
    649748            at91rm9200_emac_init (sc);
    650749            break;
    651            
     750
    652751        default:
    653752            break;
    654753        } /* switch (if_flags) */
    655754        break;
    656        
     755
    657756    case SIO_RTEMS_SHOW_STATS:
    658757        at91rm9200_emac_stats (sc);
    659758        break;
    660        
     759
    661760        /*
    662761         * FIXME: All sorts of multicast commands need to be added here!
     
    673772{
    674773    unsigned long status32;
    675    
     774
    676775    /* get the ISR status and determine RX or TX */
    677776    status32 = EMAC_REG(EMAC_ISR);
    678    
     777
    679778    if (status32 & EMAC_INT_ABT) {
    680779        EMAC_REG(EMAC_IDR) = EMAC_INT_ABT; /* disable it */
    681780        rtems_panic("AT91RM9200 Ethernet MAC has received an Abort.\n");
    682781    }
    683    
     782
    684783    if (status32 & (EMAC_INT_RCOM |    /* Receive complete */
    685784                    EMAC_INT_RBNA |    /* Receive buffer not available */
    686785                    EMAC_INT_ROVR)) {  /* Receive overrun */
    687        
     786
    688787        /* disable the RX interrupts */
    689788        EMAC_REG(EMAC_IDR) = (EMAC_INT_RCOM |  /* Receive complete */
    690789                              EMAC_INT_RBNA |  /* Receive buf not available */
    691790                              EMAC_INT_ROVR);  /* Receive overrun */
    692        
     791
    693792        rtems_event_send (softc.rxDaemonTid, START_RECEIVE_EVENT);
    694     }   
     793    }
    695794
    696795    if (status32 & EMAC_INT_TCOM) {      /* Transmit buffer register empty */
    697        
     796
    698797        /* disable the TX interrupts */
    699798        EMAC_REG(EMAC_IDR) = EMAC_INT_TCOM;
    700        
     799
    701800        rtems_event_send (softc.txDaemonTid, START_TRANSMIT_EVENT);
    702     }   
    703 }
    704 
     801    }
     802}
     803
Note: See TracChangeset for help on using the changeset viewer.