123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221 |
- /*
- * File : emac_drv.c
- * i.MX6 EMAC Ethernet driver
- * COPYRIGHT (C) 2015, Shanghai Real-Thread Electronic Technology Co.,Ltd
- *
- * Change Logs:
- * Date Author Notes
- * 2015-07-15 Bernard The first version
- */
- #include <rtthread.h>
- #include <netif/ethernetif.h>
- #include <soc_memory_map.h>
- #include <stdint.h>
- #include <enet/enet.h>
- #include <lwipopts.h>
- #include "emac_drv.h"
- #define MAX_ADDR_LEN 6
- #define IMX_EMAC_DEVICE(eth) (struct emac_device*)(eth)
- struct emac_device
- {
- /* inherit from Ethernet device */
- struct eth_device parent;
- imx_enet_priv_t enet_priv;
- /* interface address info. */
- rt_uint8_t dev_addr[MAX_ADDR_LEN]; /* MAC address */
- };
- static struct emac_device _emac;
- #define ENET_PHY_ADDR 1
- extern int imx_enet_mii_type(imx_enet_priv_t * dev, enum imx_mii_type mii_type);
- extern void imx_enet_iomux(void);
- extern void imx_enet_phy_reset(void);
- static unsigned char s_pkt_send[2048];
- static unsigned char s_pkt_recv[2048];
- void init_enet(struct emac_device* emac)
- {
- // setup iomux for ENET
- imx_enet_iomux();
- imx_enet_phy_reset();
- // init enet0
- imx_enet_init(&emac->enet_priv, ENET_BASE_ADDR, ENET_PHY_ADDR);
- imx_enet_mii_type(&emac->enet_priv, RGMII);
- // init phy0.
- imx_enet_phy_init(&emac->enet_priv);
- // Check PHY link status.
- if (!(emac->enet_priv.status & ENET_STATUS_LINK_ON))
- {
- rt_kprintf("ENET link status check fail\n");
- }
- imx_enet_start(&emac->enet_priv, emac->dev_addr);
- }
- void imx_enet_isr(int vector, void *param)
- {
- unsigned int value = 0;
- imx_enet_priv_t * dev = &(_emac.enet_priv);
- volatile hw_enet_t *enet_reg = dev->enet_reg;
- value = enet_reg->EIR.U;
- enet_reg->EIR.U = value & (~ENET_EVENT_MII);
- if (value & ENET_EVENT_TX_ERR)
- {
- dev->tx_busy = 0;
- }
- else if (value & ENET_EVENT_TX)
- {
- dev->tx_busy = 0;
- }
- if (value & ENET_EVENT_RX)
- {
- eth_device_ready(&(_emac.parent));
- }
- if (value & ENET_EVENT_HBERR)
- {
- // printf("WARNGING[POLL]: Hearbeat error!\n");
- }
- if (value & ENET_EVENT_EBERR)
- {
- // printf("WARNING[POLL]: Ethernet Bus Error!\n");
- }
- }
- static rt_err_t imx_emac_init(rt_device_t dev)
- {
- struct emac_device *emac;
- emac = IMX_EMAC_DEVICE(dev);
- /* initialize enet */
- init_enet(emac);
- return RT_EOK;
- }
- static rt_err_t imx_emac_open(rt_device_t dev, rt_uint16_t oflag)
- {
- return RT_EOK;
- }
- static rt_err_t imx_emac_close(rt_device_t dev)
- {
- return RT_EOK;
- }
- static rt_size_t imx_emac_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size)
- {
- rt_set_errno(-RT_ENOSYS);
- return 0;
- }
- static rt_size_t imx_emac_write (rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size)
- {
- rt_set_errno(-RT_ENOSYS);
- return 0;
- }
- static rt_err_t imx_emac_control(rt_device_t dev, int cmd, void *args)
- {
- struct emac_device *emac;
- emac = IMX_EMAC_DEVICE(dev);
- RT_ASSERT(emac != RT_NULL);
- switch(cmd)
- {
- case NIOCTL_GADDR:
- /* get MAC address */
- if(args) rt_memcpy(args, emac->dev_addr, 6);
- else return -RT_ERROR;
- break;
- default :
- break;
- }
- return RT_EOK;
- }
- /* Ethernet device interface */
- /* transmit packet. */
- rt_err_t imx_emac_tx(rt_device_t dev, struct pbuf* p)
- {
- rt_err_t result = RT_EOK;
- struct emac_device *emac;
- emac = IMX_EMAC_DEVICE(dev);
- RT_ASSERT(emac != RT_NULL);
- /* copy pbuf to a whole ETH frame */
- pbuf_copy_partial(p, s_pkt_send, p->tot_len, 0);
- /* send to the enet */
- imx_enet_send(&emac->enet_priv, s_pkt_send, p->tot_len, 1);
- return result;
- }
- /* reception packet. */
- struct pbuf *imx_emac_rx(rt_device_t dev)
- {
- int len;
- struct pbuf* p = RT_NULL;
- struct emac_device *emac;
- emac = IMX_EMAC_DEVICE(dev);
- RT_ASSERT(emac != RT_NULL);
- imx_enet_recv(&emac->enet_priv, s_pkt_recv, &len);
- if (len > 0)
- {
- /* We allocate a pbuf chain of pbufs from the pool. */
- p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
- if (p != RT_NULL)
- {
- pbuf_take(p, s_pkt_recv, len);
- }
- }
- return p;
- }
- int imx_emac_hw_init(void)
- {
- /* test MAC address */
- _emac.dev_addr[0] = 0x00;
- _emac.dev_addr[1] = 0x11;
- _emac.dev_addr[2] = 0x22;
- _emac.dev_addr[3] = 0x33;
- _emac.dev_addr[4] = 0x44;
- _emac.dev_addr[5] = 0x55;
- _emac.parent.parent.init = imx_emac_init;
- _emac.parent.parent.open = imx_emac_open;
- _emac.parent.parent.close = imx_emac_close;
- _emac.parent.parent.read = imx_emac_read;
- _emac.parent.parent.write = imx_emac_write;
- _emac.parent.parent.control = imx_emac_control;
- _emac.parent.parent.user_data = RT_NULL;
- _emac.parent.eth_rx = imx_emac_rx;
- _emac.parent.eth_tx = imx_emac_tx;
- /* register ETH device */
- eth_device_init(&(_emac.parent), "e0");
- return 0;
- }
- INIT_DEVICE_EXPORT(imx_emac_hw_init);
|