1 //==========================================================================
5 // Ethernet device driver for SMSC LAN92XX compatible controllers
7 //==========================================================================
8 //==========================================================================
10 //#####DESCRIPTIONBEGIN####
12 // Author(s): Fred Fan
16 // Description: Driver for SMSC LAN92xx ethernet controller
20 //####DESCRIPTIONEND####
22 //==========================================================================
23 #include <pkgconf/system.h>
24 #include <pkgconf/io_eth_drivers.h>
26 #include <cyg/infra/cyg_type.h>
27 #include <cyg/hal/hal_arch.h>
28 #include <cyg/hal/hal_intr.h>
29 #include <cyg/hal/hal_diag.h>
30 #include <cyg/infra/cyg_ass.h>
31 #include <cyg/infra/diag.h>
32 #include <cyg/hal/drv_api.h>
33 #include <cyg/io/eth/netdev.h>
34 #include <cyg/io/eth/eth_drv.h>
35 #include <cyg/io/smsc_lan92xx.h>
39 #include <pkgconf/net.h>
40 #include <cyg/kernel/kapi.h>
41 #include <net/if.h> /* Needed for struct ifnet */
44 //#define LAN92XX_DEBUG
46 #define PDEBUG(fmt, args...) diag_printf(fmt, ##args)
48 #define PDEBUG(fmt, args...)
49 #endif /*LAN92XX_DEBUG*/
52 #include CYGDAT_DEVS_ETH_SMSC_LAN92XX_INL
55 #define LAN_92XX_DRV_VER "1.1"
57 #define MAX_RX_NUM (CYGNUM_IO_ETH_DRIVERS_NUM_PKT - 1)
58 static smsc_lan92xx_id_t smsc_lan92xx_id_table[] =
60 {0x117A, 0x0000, "SMSC LAN9217"},
61 {0x9220, 0x0000, "SMSC LAN9220"},
65 static int lan92xx_eeprom_present = 1;
67 static smsc_lan92xx_t lan92xx_dev;
69 lan92xx_set_mac_addr(struct eth_drv_sc *sc, unsigned char *enaddr);
70 static void lan92xx_soft_reset(struct eth_drv_sc *sc);
71 static inline unsigned int
72 lan92xx_mac_read(struct eth_drv_sc *sc, unsigned char reg);
74 lan92xx_mac_write(struct eth_drv_sc *sc, unsigned char reg, unsigned long val);
75 static inline unsigned int
76 lan92xx_mii_read(struct eth_drv_sc *sc, unsigned char addr);
78 lan92xx_mii_write(struct eth_drv_sc *sc, unsigned char addr, unsigned int val);
81 * This function set the value of PHY registers by MII interface
84 lan92xx_start(struct eth_drv_sc *sc, unsigned char *enaddr, int flags)
87 smsc_lan92xx_t *pdev = (smsc_lan92xx_t *)(sc->driver_private);
89 lan92xx_set_mac_addr(sc, enaddr);
93 val = lan92xx_mac_read(sc, MAC_MAC_CR)& (~0x800);
95 lan92xx_mac_write(sc, MAC_MAC_CR, val);
96 val = lan92xx_mac_read(sc, MAC_MAC_CR);
100 * This function pauses the FEC controller.
103 lan92xx_stop(struct eth_drv_sc *sc)
107 val = lan92xx_mac_read(sc, MAC_MAC_CR);
108 val &= ~(0x0000000C);
109 lan92xx_mac_write(sc, MAC_MAC_CR, val);
113 lan92xx_control(struct eth_drv_sc *sc, unsigned long key, void *data, int data_length)
115 /*TODO:: Add support */
116 PDEBUG("%s: key=0x%x, data=0x%x, data_len=0x%x\n",
117 __FUNCTION__, key, (unsigned long)data, (unsigned long)data_length);
122 * This function checks the status of FEC control.
125 lan92xx_can_send(struct eth_drv_sc *sc)
127 smsc_lan92xx_t *pdev = (smsc_lan92xx_t *)(sc->driver_private);
129 if (!(pdev->status & PHY_LINK_ON)) return 0;
130 if (pdev->tx_busy) return 0;
136 * This function transmits a frame.
139 lan92xx_send(struct eth_drv_sc *sc, struct eth_drv_sg *sg_list, int sg_len, int total, unsigned long key)
141 int i, j, len, freespace;
142 unsigned int tx_cmd1, tx_cmd2, data, *pdata;
143 smsc_lan92xx_t *pdev = (smsc_lan92xx_t *)(sc->driver_private);
144 freespace = LAN92XX_REG_READ(LAN92XX_TX_FIFO_INF) & 0xFFFF;
146 if (freespace < total + 16 ) {
147 sc->funs->eth_drv->tx_done(sc, key, -1);
150 for (i = 0; i < sg_len; i++) {
151 len = (sg_list[i].len + 3) >> 2;
152 if (i == (sg_len - 1))
159 tx_cmd1 |= sg_list[i].len;
160 tx_cmd2 = (total << 16) + total;
161 LAN92XX_REG_WRITE(LAN92XX_TX_DATA, tx_cmd1);
163 LAN92XX_REG_WRITE(LAN92XX_TX_DATA, tx_cmd2);
164 pdata = (unsigned int *)sg_list[i].buf;
166 for (j=0; j<len; j++) {
168 LAN92XX_REG_WRITE(LAN92XX_TX_DATA, data);
169 for (data=0; data<2; data++) {
182 lan92xx_drop_packet(struct eth_drv_sc *sc, int count)
186 LAN92XX_REG_WRITE(LAN92XX_RX_DP_CTRL, 0x80000000);
187 while (LAN92XX_REG_READ(LAN92XX_RX_DP_CTRL) & 0x80000000) {
191 data = LAN92XX_REG_READ(LAN92XX_RX_DATA);
196 * This function receives ready Frame in DB.
199 lan92xx_recv(struct eth_drv_sc *sc, struct eth_drv_sg *sg_list, int sg_len)
201 unsigned int i, rlen;
202 unsigned int *pdata = (unsigned int *)(sg_list->buf);
204 rlen = (sg_list->len + 3) >> 2;
205 if ((void *)(sg_list->buf) == NULL) {
209 for (i = 0; i < rlen; i++) {
210 *(pdata++) = LAN92XX_REG_READ(LAN92XX_RX_DATA);
214 lan92xx_drop_packet(sc, rlen);
218 lan92xx_deliver(struct eth_drv_sc *sc)
220 /*TODO::When redboot support thread ,
221 * the polling function will be called at here
227 lan92xx_link_status(struct eth_drv_sc *sc)
230 smsc_lan92xx_t *pdev = (smsc_lan92xx_t *)(sc->driver_private);
231 val = lan92xx_mii_read(sc, PHY_ISR);
233 val = lan92xx_mii_read(sc, PHY_BSR);
234 if (val != pdev->status) {
236 val = lan92xx_mac_read(sc, MAC_MAC_CR) & (~0x802F0800);
237 if ( IS_DUPLEX(pdev->status)) {
240 lan92xx_mac_write(sc, MAC_MAC_CR, val);
245 * This function checks the event of FEC controller
248 lan92xx_poll(struct eth_drv_sc *sc)
250 unsigned int val, reg;
252 smsc_lan92xx_t *pdev = (smsc_lan92xx_t *)(sc->driver_private);
254 reg = LAN92XX_REG_READ(LAN92XX_INT_STS);
255 LAN92XX_REG_WRITE(LAN92XX_INT_STS, reg);
257 //diag_printf("INT_STS: %x\n", reg);
259 lan92xx_link_status(sc);
263 diag_printf("%s:: TX or RX error [0x%x]\n", __FUNCTION__, reg);
264 lan92xx_soft_reset(sc);
269 reg = LAN92XX_REG_READ(LAN92XX_RX_FIFO_INF);
270 if (!(reg & 0xFF0000))
272 reg = LAN92XX_REG_READ(LAN92XX_RX_STATUS1);
274 if (reg & 0x4000909A) {
275 val = (reg >> 16) & 0x3FFF;
276 val = (val + 3) >> 2;
277 lan92xx_drop_packet(sc, val);
279 val = (reg >> 16) & 0x3FFF;
280 sc->funs->eth_drv->recv(sc, val);
284 if ( rx_num >= MAX_RX_NUM) break;
288 reg = LAN92XX_REG_READ(LAN92XX_TX_FIFO_INF);
289 if (!(reg & 0xFF0000)) break;
291 if (!LAN92XX_REG_READ(LAN92XX_TX_STATUS2)) {
292 diag_printf("***FIFO %x, wrong status =%x: int_sts=%x\n",
293 reg, LAN92XX_REG_READ(LAN92XX_TX_STATUS2),
294 LAN92XX_REG_READ(LAN92XX_INT_STS));
297 reg = LAN92XX_REG_READ(LAN92XX_TX_STATUS1);
299 sc->funs->eth_drv->tx_done(sc, pdev->tx_key, -1);
301 sc->funs->eth_drv->tx_done(sc, pdev->tx_key, 0);
308 lan92xx_int_vector(struct eth_drv_sc *sc)
310 PDEBUG("%s::\n", __FUNCTION__);
313 * get FEC interrupt number
318 static smsc_lan92xx_id_t *lan92xx_probe(unsigned long id)
320 smsc_lan92xx_id_t *p = smsc_lan92xx_id_table;
329 static inline unsigned int
330 lan92xx_mac_read(struct eth_drv_sc *sc, unsigned char reg)
334 if (LAN92XX_REG_READ(LAN92XX_MAC_CMD) & 0x80000000) {
335 diag_printf("Error: %d. MAC is busy\n", __LINE__);
339 cmd = 0xC0000000 | (reg & 0xFF);
340 LAN92XX_REG_WRITE(LAN92XX_MAC_CMD, cmd);
342 /* Workaround for hardware read-after-write */
343 LAN92XX_REG_READ(LAN92XX_BYTE_TEST);
345 while (LAN92XX_REG_READ(LAN92XX_MAC_CMD) & 0x80000000);
347 return LAN92XX_REG_READ(LAN92XX_MAC_DATA);
351 lan92xx_mac_write(struct eth_drv_sc *sc, unsigned char reg, unsigned long val)
355 if (LAN92XX_REG_READ(LAN92XX_MAC_CMD) & 0x80000000) {
356 diag_printf("Error: %d. MAC is busy\n", __LINE__);
360 LAN92XX_REG_WRITE(LAN92XX_MAC_DATA, val);
361 cmd = 0x80000000 | (reg & 0xFF);
362 LAN92XX_REG_WRITE(LAN92XX_MAC_CMD, cmd);
364 /* Workaround for hardware read-after-write */
365 LAN92XX_REG_READ(LAN92XX_BYTE_TEST);
367 while (LAN92XX_REG_READ(LAN92XX_MAC_CMD) & 0x80000000);
371 lan92xx_set_mac_addr(struct eth_drv_sc *sc, unsigned char *enaddr)
375 val = (val << 8) | enaddr[2];
376 val = (val << 8) | enaddr[1];
377 val = (val << 8) | enaddr[0];
378 lan92xx_mac_write(sc, MAC_ADDRL, val);
380 val = lan92xx_mac_read(sc, MAC_ADDRH) >> 16;
381 val = (val << 8) | enaddr[5];
382 val = (val << 8) | enaddr[4];
383 lan92xx_mac_write(sc, MAC_ADDRH, val);
386 static inline unsigned int
387 lan92xx_mii_read(struct eth_drv_sc *sc, unsigned char addr)
391 cmd = (0x1 << 11 ) | (addr << 6) | 1;
392 lan92xx_mac_write(sc, MAC_MII_ACC, cmd);
393 while (lan92xx_mac_read(sc, MAC_MII_ACC) & 1);
395 return lan92xx_mac_read(sc, MAC_MII_DATA)&0xFFFF;
399 lan92xx_mii_write(struct eth_drv_sc *sc, unsigned char addr, unsigned int val)
403 cmd = (0x1 << 11 ) | (addr << 6) | 3;
404 lan92xx_mac_write(sc, MAC_MII_DATA, val);
405 lan92xx_mac_read(sc, MAC_MII_DATA);
406 lan92xx_mac_write(sc, MAC_MII_ACC, cmd);
408 while (lan92xx_mac_read(sc, MAC_MII_ACC) & 1);
411 static int lan92xx_phy_init(struct eth_drv_sc *sc)
414 smsc_lan92xx_t *pdev = (smsc_lan92xx_t *)(sc->driver_private);
416 lan92xx_mii_write(sc, PHY_BCR, 0x8000);
418 while (lan92xx_mii_read(sc, PHY_BCR) & 0x8000);
420 for (val = 0; val < 2500; val++)
423 val = lan92xx_mii_read(sc, PHY_ANAR);
425 lan92xx_mii_write(sc, PHY_ANAR, val);
426 lan92xx_mii_write(sc, PHY_SMR, 0x00E1);
427 lan92xx_mii_write(sc, PHY_SCSI, 0x400B);
428 lan92xx_mii_write(sc, PHY_IMR, 0x00F0);
429 lan92xx_mii_write(sc, PHY_BCR, 0x1200);
431 while ((lan92xx_mii_read(sc, PHY_BCR) & 0x200));
433 pdev->status = lan92xx_mii_read(sc, PHY_BSR);
438 static int lan92xx_mac_init(struct eth_drv_sc *sc)
440 static int mac_init = 0;
442 smsc_lan92xx_t *pdev = (smsc_lan92xx_t *)(sc->driver_private);
444 val = lan92xx_mac_read(sc, MAC_MAC_CR) & (~0x802F0800);
445 if (IS_DUPLEX(pdev->status)) {
448 lan92xx_mac_write(sc, MAC_MAC_CR, val);
450 lan92xx_mac_write(sc, MAC_HASHH, 0);
451 lan92xx_mac_write(sc, MAC_HASHL, 0);
458 #if CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT
459 if (!_board_provide_eth0_esa(pdev->mac_addr))
462 // make sure EPC not busy
463 while ((val = LAN92XX_REG_READ(LAN92XX_E2P_CMD)) & E2P_CMD_BUSY);
465 if (val & E2P_CMD_TIMEOUT) {
466 lan92xx_eeprom_present = 0;
467 diag_printf("LAN9217: NO EEPROM\n");
471 if (!(LAN92XX_REG_READ(LAN92XX_E2P_CMD) & E2P_CMD_LOADED)) {
472 diag_printf("LAN9217:EEPROM is empty\n");
474 val = lan92xx_mac_read(sc, MAC_ADDRH);
475 pdev->mac_addr[5] = (val >> 8) & 0xFF;
476 pdev->mac_addr[4] = val&0xFF;
477 val = lan92xx_mac_read(sc, MAC_ADDRL);
478 pdev->mac_addr[3] = (val >> 24) & 0xFF;
479 pdev->mac_addr[2] = (val >> 16) & 0xFF;
480 pdev->mac_addr[1] = (val >> 8) & 0xFF;
481 pdev->mac_addr[0] = val & 0xFF;
487 * This function reset LAN9219 .
490 lan92xx_soft_reset(struct eth_drv_sc *sc)
492 unsigned int timeout = MAC_TIMEOUT;
494 LAN92XX_REG_WRITE(LAN92XX_HW_CFG, 1);
495 while ((LAN92XX_REG_READ(LAN92XX_HW_CFG) & 1) && (--timeout)) {
496 hal_delay_us(MAC_TICKET);
500 diag_printf("LAN92XX: Reset fail \n");
504 LAN92XX_REG_WRITE(LAN92XX_INT_EN, 0);
505 LAN92XX_REG_WRITE(LAN92XX_HW_CFG, 0x150000);
506 LAN92XX_REG_WRITE(LAN92XX_AFC_CFG, 0x6E3740);
507 LAN92XX_REG_WRITE(LAN92XX_TX_CFG, 0x2);
509 timeout = MAC_TIMEOUT;
511 while ((LAN92XX_REG_READ(LAN92XX_E2P_CMD) & 0x80000000) && (--timeout)) {
512 hal_delay_us(MAC_TICKET);
515 LAN92XX_REG_WRITE(LAN92XX_GPIO_CFG, 0x70070000);
516 LAN92XX_REG_WRITE(LAN92XX_INT_STS, 0xFFFFFFFF);
517 lan92xx_mac_init(sc);
521 * This function initializes the LAN92xx driver.
522 * It is called by net_init in net module of RedBoot during RedBoot init
525 lan92xx_init(struct cyg_netdevtab_entry *tab)
527 unsigned int reg, timeout;
528 smsc_lan92xx_id_t *id;
529 struct eth_drv_sc *sc = tab ? tab->device_instance : NULL;
530 smsc_lan92xx_t *pdev = (smsc_lan92xx_t *)(sc->driver_private);
532 diag_printf("\nLAN92xx Driver version %s\n", LAN_92XX_DRV_VER);
534 diag_printf("LAN92xx:: Driver don't attach with device\n");
537 reg = LAN92XX_REG_READ(LAN92XX_ID_REV);
538 id = lan92xx_probe(reg >> 16);
540 diag_printf("%s: ID = 0x%x REV = 0x%x\n", id->id_name, id->id, id->ver);
542 diag_printf("LAN92XX: unknow chip ID = %x\n", reg);
546 timeout = MAC_TIMEOUT;
547 while ((!(LAN92XX_REG_READ(LAN92XX_PMT_CTRL) & 1)) && (--timeout)) {
548 hal_delay_us(MAC_TICKET);
551 diag_printf("LAN92XX: is not ready to access\n");
555 lan92xx_phy_init(sc);
557 lan92xx_soft_reset(sc);
558 (sc->funs->eth_drv->init)(sc, pdev->mac_addr);
563 * Global variable which defines the LAN92xx driver,
565 ETH_DRV_SC(lan92xx_sc,
566 &lan92xx_dev, // Driver specific data
567 CYGDAT_DEVS_ETH_ARM_MXCBOARD_ETH0_NAME,
574 lan92xx_deliver, // "pseudoDSR" called from fast net thread
575 lan92xx_poll, // poll function, encapsulates ISR and DSR
579 * Global variable which defines the FEC device
581 NETDEVTAB_ENTRY(lan92xx_netdev,
582 "lan92xx_" CYGDAT_DEVS_ETH_ARM_MXCBOARD_ETH0_NAME,
586 // Low level function to issue a command to the eeprom controller.
587 // return 0 on success and -1 on failure
589 _lan92xx_e2p_do_cmd(unsigned int cmd)
592 LAN92XX_REG_WRITE(LAN92XX_E2P_CMD, cmd);
593 while ((v = LAN92XX_REG_READ(LAN92XX_E2P_CMD)) & E2P_CMD_BUSY);
594 if (v & E2P_CMD_TIMEOUT) {
595 diag_printf("%s:: EEPROM timeout\n", __FUNCTION__);
596 // clear the timeout status bit
597 LAN92XX_REG_WRITE(LAN92XX_E2P_CMD, E2P_CMD_TIMEOUT);
598 while ((v = LAN92XX_REG_READ(LAN92XX_E2P_CMD)) & E2P_CMD_BUSY);
604 // for all the 7 EEPROM operations
605 // return 0 on success and -1 on failure
607 lan92xx_e2p_op(enum epc_cmd cmd, unsigned char addr, unsigned char *data)
611 if (_lan92xx_e2p_do_cmd(E2P_CMD(cmd, addr)) != 0)
613 *data = (unsigned char)LAN92XX_REG_READ(LAN92XX_E2P_DATA);
618 LAN92XX_REG_WRITE(LAN92XX_E2P_DATA, *data);
624 if (_lan92xx_e2p_do_cmd(E2P_CMD(cmd, addr)) != 0)
630 static void setMac(int argc, char *argv[])
633 unsigned char data[7];
636 if (!lan92xx_eeprom_present) {
637 diag_printf("NO EEPROM present\n\n");
642 for (i = 0; i < 7 ; i++) {
643 if (lan92xx_e2p_op(E2P_CMD_READ, i, &data[i]) != 0) {
644 diag_printf("read MAC %d address fail\n\n", i);
649 if (data[0] != E2P_CONTEXT_ID) {
650 diag_printf("Warning: Unprogrammed MAC address: 0x%x\n", data[0]);
654 diag_printf("MAC address: ");
655 diag_printf("0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x\n\n",
656 data[1], data[2], data[3],
657 data[4], data[5], data[6]);
662 diag_printf("Error: Wrong argument\n");
666 data[0] = E2P_CONTEXT_ID;
667 for (i = 1; i < 7; i++) {
668 if (!parse_num(*(&argv[1]), &temp, &argv[1], ":")) {
669 diag_printf("Error: failed to parse command: %d\n", __LINE__);
673 diag_printf("Error: invalid valie: 0x%x\n", (unsigned int)temp);
679 // enable erase/write
680 if (lan92xx_e2p_op(E2P_CMD_EWEN, 0, data) != 0) {
681 diag_printf("%s:: Enable write/erase fail\n", __FUNCTION__);
684 for (i = 0; i < 7; i++) {
685 if (lan92xx_e2p_op(E2P_CMD_ERASE, i, &data[i]) != 0 ||
686 lan92xx_e2p_op(E2P_CMD_WRITE, i, &data[i]) != 0) {
687 diag_printf("Error: failed to program eeprom at %d\n", i);
692 // disable erase/write
693 if (lan92xx_e2p_op(E2P_CMD_EWDS, 0, data) != 0) {
694 diag_printf("%s:: Enable write/erase fail\n", __FUNCTION__);
698 RedBoot_cmd("setmac",
699 "Set Ethernet MAC address in EEPROM",
700 "[0x##:0x##:0x##:0x##:0x##:0x##]",