add emac driver for at91sam9260

git-svn-id: https://rt-thread.googlecode.com/svn/trunk@1384 bbd45198-f89e-11dd-88c7-29a3b14d5316
This commit is contained in:
luohui2320@gmail.com 2011-04-21 14:30:15 +00:00
parent ea009132a2
commit fd963d847a
5 changed files with 1208 additions and 1 deletions

686
bsp/at91sam9260/macb.c Executable file
View File

@ -0,0 +1,686 @@
/*
* File : macb.c
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006, RT-Thread Develop Team
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rt-thread.org/license/LICENSE
*
* Change Logs:
* Date Author Notes
* 2011-03-18 weety first version
*/
#include <rtthread.h>
#include <netif/ethernetif.h>
#include "lwipopts.h"
#include <at91sam926x.h>
#include "macb.h"
#define CONFIG_RMII
#define MACB_RX_BUFFER_SIZE 4096*4
#define MACB_RX_RING_SIZE (MACB_RX_BUFFER_SIZE / 128)
#define MACB_TX_RING_SIZE 16
#define MACB_TX_TIMEOUT 1000
#define MACB_AUTONEG_TIMEOUT 5000000
#define MACB_LINK_TIMEOUT 500000
struct macb_dma_desc {
rt_uint32_t addr;
rt_uint32_t ctrl;
};
#define RXADDR_USED 0x00000001
#define RXADDR_WRAP 0x00000002
#define RXBUF_FRMLEN_MASK 0x00000fff
#define RXBUF_FRAME_START 0x00004000
#define RXBUF_FRAME_END 0x00008000
#define RXBUF_TYPEID_MATCH 0x00400000
#define RXBUF_ADDR4_MATCH 0x00800000
#define RXBUF_ADDR3_MATCH 0x01000000
#define RXBUF_ADDR2_MATCH 0x02000000
#define RXBUF_ADDR1_MATCH 0x04000000
#define RXBUF_BROADCAST 0x80000000
#define TXBUF_FRMLEN_MASK 0x000007ff
#define TXBUF_FRAME_END 0x00008000
#define TXBUF_NOCRC 0x00010000
#define TXBUF_EXHAUSTED 0x08000000
#define TXBUF_UNDERRUN 0x10000000
#define TXBUF_MAXRETRY 0x20000000
#define TXBUF_WRAP 0x40000000
#define TXBUF_USED 0x80000000
#define MACB_RX_INT_FLAGS (MACB_BIT(RCOMP) | MACB_BIT(RXUBR) \
| MACB_BIT(ISR_ROVR))
#define MAX_ADDR_LEN 6
struct rt_macb_eth
{
/* inherit from ethernet device */
struct eth_device parent;
void *regs;
unsigned int rx_tail;
unsigned int tx_head;
unsigned int tx_tail;
void *rx_buffer;
void *tx_buffer;
struct macb_dma_desc *rx_ring;
struct macb_dma_desc *tx_ring;
unsigned long rx_buffer_dma;
unsigned long rx_ring_dma;
unsigned long tx_ring_dma;
/* interface address info. */
rt_uint8_t dev_addr[MAX_ADDR_LEN]; /* hw address */
unsigned short phy_addr;
};
static struct rt_macb_eth macb_device;
static struct rt_semaphore sem_ack, sem_lock;
static void udelay(rt_uint32_t us)
{
rt_uint32_t len;
for (;us > 0; us --)
for (len = 0; len < 10; len++ );
}
static void rt_macb_isr(int irq)
{
struct rt_macb_eth *macb = &macb_device;
rt_device_t dev = &(macb->parent.parent);
rt_uint32_t status, rsr, tsr;
//rt_kprintf("%s:irq enter\n", __func__);
status = macb_readl(macb, ISR);
while (status) {
if (status & MACB_RX_INT_FLAGS) {
//rt_kprintf("macb recv isr\n");
//macb_writel(macb, IDR, MACB_RX_INT_FLAGS);
rsr = macb_readl(macb, RSR);
macb_writel(macb, RSR, rsr);
/* a frame has been received */
eth_device_ready(&(macb_device.parent));
}
if (status & (MACB_BIT(TCOMP) | MACB_BIT(ISR_TUND) |
MACB_BIT(ISR_RLE)))
{
//rt_kprintf("macb tx complete\n");
tsr = macb_readl(macb, TSR);
macb_writel(macb, TSR, tsr);
/* One packet sent complete */
rt_sem_release(&sem_ack);
}
//macb_tx(bp);
/*
* Link change detection isn't possible with RMII, so we'll
* add that if/when we get our hands on a full-blown MII PHY.
*/
if (status & MACB_BIT(HRESP)) {
/*
* TODO: Reset the hardware, and maybe move the printk
* to a lower-priority context as well (work queue?)
*/
rt_kprintf("%s: DMA bus error: HRESP not OK\n",
dev->parent.name);
}
status = macb_readl(macb, ISR);
}
}
static void macb_mdio_write(struct rt_macb_eth *macb, rt_uint8_t reg, rt_uint16_t value)
{
unsigned long netctl;
unsigned long netstat;
unsigned long frame;
netctl = macb_readl(macb, NCR);
netctl |= MACB_BIT(MPE);
macb_writel(macb, NCR, netctl);
frame = (MACB_BF(SOF, 1)
| MACB_BF(RW, 1)
| MACB_BF(PHYA, macb->phy_addr)
| MACB_BF(REGA, reg)
| MACB_BF(CODE, 2)
| MACB_BF(DATA, value));
macb_writel(macb, MAN, frame);
do {
netstat = macb_readl(macb, NSR);
} while (!(netstat & MACB_BIT(IDLE)));
netctl = macb_readl(macb, NCR);
netctl &= ~MACB_BIT(MPE);
macb_writel(macb, NCR, netctl);
}
static rt_uint16_t macb_mdio_read(struct rt_macb_eth *macb, rt_uint8_t reg)
{
unsigned long netctl;
unsigned long netstat;
unsigned long frame;
netctl = macb_readl(macb, NCR);
netctl |= MACB_BIT(MPE);
macb_writel(macb, NCR, netctl);
frame = (MACB_BF(SOF, 1)
| MACB_BF(RW, 2)
| MACB_BF(PHYA, macb->phy_addr)
| MACB_BF(REGA, reg)
| MACB_BF(CODE, 2));
macb_writel(macb, MAN, frame);
do {
netstat = macb_readl(macb, NSR);
} while (!(netstat & MACB_BIT(IDLE)));
frame = macb_readl(macb, MAN);
netctl = macb_readl(macb, NCR);
netctl &= ~MACB_BIT(MPE);
macb_writel(macb, NCR, netctl);
return MACB_BFEXT(DATA, frame);
}
static void macb_phy_reset(rt_device_t dev)
{
struct rt_macb_eth *macb = dev->user_data;;
int i;
rt_uint16_t status, adv;
adv = ADVERTISE_CSMA | ADVERTISE_ALL;
macb_mdio_write(macb, MII_ADVERTISE, adv);
rt_kprintf("%s: Starting autonegotiation...\n", dev->parent.name);
macb_mdio_write(macb, MII_BMCR, (BMCR_ANENABLE
| BMCR_ANRESTART));
for (i = 0; i < MACB_AUTONEG_TIMEOUT / 100; i++) {
status = macb_mdio_read(macb, MII_BMSR);
if (status & BMSR_ANEGCOMPLETE)
break;
udelay(100);
}
if (status & BMSR_ANEGCOMPLETE)
rt_kprintf("%s: Autonegotiation complete\n", dev->parent.name);
else
rt_kprintf("%s: Autonegotiation timed out (status=0x%04x)\n",
dev->parent.name, status);
}
static int macb_phy_init(rt_device_t dev)
{
//struct eth_device *netdev = &macb->netdev;
struct rt_macb_eth *macb = dev->user_data;
rt_uint32_t ncfgr;
rt_uint16_t phy_id, status, adv, lpa;
int media, speed, duplex;
int i;
/* Check if the PHY is up to snuff... */
phy_id = macb_mdio_read(macb, MII_PHYSID1);
if (phy_id == 0xffff) {
rt_kprintf("%s: No PHY present\n", dev->parent.name);
return 0;
}
status = macb_mdio_read(macb, MII_BMSR);
if (!(status & BMSR_LSTATUS)) {
/* Try to re-negotiate if we don't have link already. */
macb_phy_reset(dev);
for (i = 0; i < MACB_LINK_TIMEOUT / 100; i++) { //modified by luohui@2009-11-27 CFG_MACB_AUTONEG_TIMEOUT
status = macb_mdio_read(macb, MII_BMSR);
if (status & BMSR_LSTATUS)
break;
udelay(100);
}
}
if (!(status & BMSR_LSTATUS)) {
rt_kprintf("%s: link down (status: 0x%04x)\n",
dev->parent.name, status);
return 0;
} else {
adv = macb_mdio_read(macb, MII_ADVERTISE);
lpa = macb_mdio_read(macb, MII_LPA);
media = mii_nway_result(lpa & adv);
speed = (media & (ADVERTISE_100FULL | ADVERTISE_100HALF)
? 1 : 0);
duplex = (media & ADVERTISE_FULL) ? 1 : 0;
rt_kprintf("%s: link up, %sMbps %s-duplex (lpa: 0x%04x)\n",
dev->parent.name,
speed ? "100" : "10",
duplex ? "full" : "half",
lpa);
ncfgr = macb_readl(macb, NCFGR);
ncfgr &= ~(MACB_BIT(SPD) | MACB_BIT(FD));
if (speed)
ncfgr |= MACB_BIT(SPD);
if (duplex)
ncfgr |= MACB_BIT(FD);
macb_writel(macb, NCFGR, ncfgr);
return 1;
}
}
/* RT-Thread Device Interface */
/* initialize the interface */
static rt_err_t rt_macb_init(rt_device_t dev)
{
struct rt_macb_eth *macb = dev->user_data;
unsigned long paddr;
rt_uint32_t hwaddr_bottom;
rt_uint16_t hwaddr_top;
int i;
/*
* macb_halt should have been called at some point before now,
* so we'll assume the controller is idle.
*/
/* initialize DMA descriptors */
paddr = macb->rx_buffer_dma;
for (i = 0; i < MACB_RX_RING_SIZE; i++) {
if (i == (MACB_RX_RING_SIZE - 1))
paddr |= RXADDR_WRAP;
macb->rx_ring[i].addr = paddr;
macb->rx_ring[i].ctrl = 0;
paddr += 128;
}
for (i = 0; i < MACB_TX_RING_SIZE; i++) {
macb->tx_ring[i].addr = 0;
if (i == (MACB_TX_RING_SIZE - 1))
macb->tx_ring[i].ctrl = TXBUF_USED | TXBUF_WRAP;
else
macb->tx_ring[i].ctrl = TXBUF_USED;
}
macb->rx_tail = macb->tx_head = macb->tx_tail = 0;
macb_writel(macb, RBQP, macb->rx_ring_dma);
macb_writel(macb, TBQP, macb->tx_ring_dma);
/* set hardware address */
//hwaddr_bottom = cpu_to_le32(*((u32 *)netdev->enetaddr));
hwaddr_bottom = (*((rt_uint32_t *)macb->dev_addr));
macb_writel(macb, SA1B, hwaddr_bottom);
//hwaddr_top = cpu_to_le16(*((u16 *)(netdev->enetaddr + 4)));
hwaddr_top = (*((rt_uint16_t *)(macb->dev_addr + 4)));
macb_writel(macb, SA1T, hwaddr_top);
/* choose RMII or MII mode. This depends on the board */
#ifdef CONFIG_RMII
#if defined(CONFIG_AVR32)
macb_writel(macb, USRIO, 0);
#else
macb_writel(macb, USRIO, MACB_BIT(RMII) | MACB_BIT(CLKEN));
#endif
#else
#if defined(CONFIG_AVR32)
macb_writel(macb, USRIO, MACB_BIT(MII));
#else
macb_writel(macb, USRIO, MACB_BIT(CLKEN));
#endif
#endif /* CONFIG_RMII */
if (!macb_phy_init(dev))
return -RT_ERROR;
/* Enable TX and RX */
macb_writel(macb, NCR, MACB_BIT(TE) | MACB_BIT(RE) | MACB_BIT(MPE));
/* Enable interrupts */
macb_writel(macb, IER, (MACB_BIT(RCOMP)
| MACB_BIT(RXUBR)
| MACB_BIT(ISR_TUND)
| MACB_BIT(ISR_RLE)
| MACB_BIT(TXERR)
| MACB_BIT(TCOMP)
| MACB_BIT(ISR_ROVR)
| MACB_BIT(HRESP)));
/* instal interrupt */
rt_hw_interrupt_install(AT91SAM9260_ID_EMAC, rt_macb_isr, RT_NULL);
rt_hw_interrupt_umask(AT91SAM9260_ID_EMAC);
return RT_EOK;
}
static rt_err_t rt_macb_open(rt_device_t dev, rt_uint16_t oflag)
{
return RT_EOK;
}
static rt_err_t rt_macb_close(rt_device_t dev)
{
return RT_EOK;
}
static rt_size_t rt_macb_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 rt_macb_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 rt_macb_control(rt_device_t dev, rt_uint8_t cmd, void *args)
{
switch(cmd)
{
case NIOCTL_GADDR:
/* get mac address */
if(args) rt_memcpy(args, macb_device.dev_addr, 6);
else return -RT_ERROR;
break;
default :
break;
}
return RT_EOK;
}
/* ethernet device interface */
/* transmit packet. */
rt_err_t rt_macb_tx( rt_device_t dev, struct pbuf* p)
{
struct rt_macb_eth *macb = dev->user_data;
struct pbuf* q;
rt_uint32_t len;
rt_uint8_t* bufptr, *buf = RT_NULL;
unsigned long paddr, ctrl;
unsigned int tx_head = macb->tx_head;
int i;
/* lock macb device */
rt_sem_take(&sem_lock, RT_WAITING_FOREVER);
//rt_kprintf("macb tx enter, packetlen=%d\n", p->tot_len);
buf = rt_malloc(p->tot_len);
if (!buf) {
rt_kprintf("%s:alloc buf failed\n", __func__);
return NULL;
}
bufptr = buf;
for (q = p; q != NULL; q = q->next)
{
//len = q->len;
//paddr = (unsigned long)q->payload;
memcpy(bufptr, q->payload, q->len);
bufptr += q->len;
/* write data to device */
/*ctrl = len & TXBUF_FRMLEN_MASK;
ctrl |= TXBUF_FRAME_END;
if (tx_head == (MACB_TX_RING_SIZE - 1)) {
ctrl |= TXBUF_WRAP;
macb->tx_head = 0;
} else
macb->tx_head++;
macb->tx_ring[tx_head].ctrl = ctrl;
macb->tx_ring[tx_head].addr = paddr;
macb_writel(macb, NCR, MACB_BIT(TE) | MACB_BIT(RE) | MACB_BIT(TSTART));*/
/*
* I guess this is necessary because the networking core may
* re-use the transmit buffer as soon as we return...
*/
}
ctrl = p->tot_len & TXBUF_FRMLEN_MASK;
ctrl |= TXBUF_FRAME_END;
if (tx_head == (MACB_TX_RING_SIZE - 1)) {
ctrl |= TXBUF_WRAP;
macb->tx_head = 0;
} else
macb->tx_head++;
macb->tx_ring[tx_head].ctrl = ctrl;
macb->tx_ring[tx_head].addr = (rt_uint32_t)buf;
macb_writel(macb, NCR, MACB_BIT(TE) | MACB_BIT(RE) | MACB_BIT(TSTART));
//rt_uint32_t netcr = macb_readl(macb, NCR); //e0: DMA bus error: HRESP not OK
//rt_kprintf("NCR = 0x%08x\n");
//macb_writel(macb, NCR, netcr | MACB_BIT(TE) | MACB_BIT(RE) | MACB_BIT(TSTART));
/* unlock macb device */
rt_sem_release(&sem_lock);
/* wait ack */
rt_sem_take(&sem_ack, RT_WAITING_FOREVER);
rt_free(buf);
buf == RT_NULL;
return RT_EOK;
}
static void reclaim_rx_buffers(struct rt_macb_eth *macb,
unsigned int new_tail)
{
unsigned int i;
i = macb->rx_tail;
while (i > new_tail) {
macb->rx_ring[i].addr &= ~RXADDR_USED;
i++;
if (i > MACB_RX_RING_SIZE)
i = 0;
}
while (i < new_tail) {
macb->rx_ring[i].addr &= ~RXADDR_USED;
i++;
}
//barrier();
macb->rx_tail = new_tail;
}
/* reception packet. */
struct pbuf *rt_macb_rx(rt_device_t dev)
{
struct rt_macb_eth *macb = dev->user_data;
struct pbuf* p = RT_NULL;
rt_uint32_t len;
unsigned int rx_tail = macb->rx_tail;
void *buffer;
//int length;
int wrapped = 0;
rt_uint32_t status;
//rt_uint8_t* data;
struct pbuf* q;
rt_uint8_t *buf = RT_NULL;
//rt_kprintf("macb rx enter\n");
/* lock macb device */
rt_sem_take(&sem_lock, RT_WAITING_FOREVER);
//rt_kprintf("macb rx enter2\n");
for (;;) {
if (!(macb->rx_ring[rx_tail].addr & RXADDR_USED))
break;
status = macb->rx_ring[rx_tail].ctrl;
if (status & RXBUF_FRAME_START) {
if (rx_tail != macb->rx_tail)
reclaim_rx_buffers(macb, rx_tail);
wrapped = 0;
}
if (status & RXBUF_FRAME_END) {
buffer = macb->rx_buffer + 128 * macb->rx_tail;
len = status & RXBUF_FRMLEN_MASK;
//rt_kprintf("%s:recv %d bytes\n", __func__, len);
p = pbuf_alloc(PBUF_LINK, len, PBUF_RAM);
if (!p)
{
rt_kprintf("alloc pbuf failed\n");
break;
}
if (wrapped) {
unsigned int headlen, taillen;
buf = rt_malloc(len);
if (!buf)
{
rt_kprintf("%s:alloc memory failed\n", __func__);
pbuf_free(p);
p = RT_NULL;
break;
}
headlen = 128 * (MACB_RX_RING_SIZE
- macb->rx_tail);
taillen = len - headlen;
memcpy((void *)buf,
buffer, headlen);
memcpy((void *)buf + headlen,
macb->rx_buffer, taillen);
buffer = (void *)buf;
for (q = p; q != RT_NULL; q= q->next)
{
/* read data from device */
memcpy((void *)q->payload, buffer, q->len);
buffer += q->len;
}
rt_free(buf);
buf = RT_NULL;
} else {
for (q = p; q != RT_NULL; q= q->next)
{
/* read data from device */
memcpy((void *)q->payload, buffer, q->len);
buffer += q->len;
}
}
//NetReceive(buffer, length);
/* allocate buffer */
if (++rx_tail >= MACB_RX_RING_SIZE)
rx_tail = 0;
reclaim_rx_buffers(macb, rx_tail);
break;
} else {
if (++rx_tail >= MACB_RX_RING_SIZE) {
wrapped = 1;
rx_tail = 0;
}
}
}
/* unlock macb device */
rt_sem_release(&sem_lock);
return p;
}
void macb_gpio_init()
{
/* Pins used for MII and RMII */
at91_sys_write(AT91_PIOA + PIO_PDR, (1 << 19)|(1 << 17)|(1 << 14)|(1 << 15)|(1 << 18)|(1 << 16)|(1 << 12)|(1 << 13)|(1 << 21)|(1 << 20));
at91_sys_write(AT91_PIOA + PIO_ASR, (1 << 19)|(1 << 17)|(1 << 14)|(1 << 15)|(1 << 18)|(1 << 16)|(1 << 12)|(1 << 13)|(1 << 21)|(1 << 20));
}
void macb_initialize()
{
struct rt_macb_eth *macb = &macb_device;
unsigned long macb_hz;
rt_uint32_t ncfgr;
macb->rx_buffer = rt_malloc(MACB_RX_BUFFER_SIZE);
macb->rx_ring = rt_malloc(MACB_RX_RING_SIZE * sizeof(struct macb_dma_desc));
macb->tx_ring = rt_malloc(MACB_TX_RING_SIZE * sizeof(struct macb_dma_desc));
macb->rx_buffer_dma = (unsigned long)macb->rx_buffer;
macb->rx_ring_dma = (unsigned long)macb->rx_ring;
macb->tx_ring_dma = (unsigned long)macb->tx_ring;
macb->regs = (void *)AT91SAM9260_BASE_EMAC;
macb->phy_addr = 0x00;
/*
* Do some basic initialization so that we at least can talk
* to the PHY
*/
macb_hz = clk_get_rate(clk_get("mck"));
if (macb_hz < 20000000)
ncfgr = MACB_BF(CLK, MACB_CLK_DIV8);
else if (macb_hz < 40000000)
ncfgr = MACB_BF(CLK, MACB_CLK_DIV16);
else if (macb_hz < 80000000)
ncfgr = MACB_BF(CLK, MACB_CLK_DIV32);
else
ncfgr = MACB_BF(CLK, MACB_CLK_DIV64);
macb_writel(macb, NCFGR, ncfgr);
}
void rt_hw_macb_init()
{
at91_sys_write(AT91_PMC + AT91_PMC_PCER, 1 << AT91SAM9260_ID_EMAC); //enable macb clock
macb_gpio_init();
macb_initialize();
rt_sem_init(&sem_ack, "tx_ack", 1, RT_IPC_FLAG_FIFO);
rt_sem_init(&sem_lock, "eth_lock", 1, RT_IPC_FLAG_FIFO);
macb_device.dev_addr[0] = 0x00;
macb_device.dev_addr[1] = 0x60;
macb_device.dev_addr[2] = 0x6E;
macb_device.dev_addr[3] = 0x11;
macb_device.dev_addr[4] = 0x22;
macb_device.dev_addr[5] = 0x33;
macb_device.parent.parent.init = rt_macb_init;
macb_device.parent.parent.open = rt_macb_open;
macb_device.parent.parent.close = rt_macb_close;
macb_device.parent.parent.read = rt_macb_read;
macb_device.parent.parent.write = rt_macb_write;
macb_device.parent.parent.control = rt_macb_control;
macb_device.parent.parent.user_data = &macb_device;
macb_device.parent.eth_rx = rt_macb_rx;
macb_device.parent.eth_tx = rt_macb_tx;
eth_device_init(&(macb_device.parent), "e0");
//eth_system_device_init();
//set_if("192.168.1.30", "192.168.1.1", "255.255.255.0");
/* instal interrupt */
//rt_hw_interrupt_install(AT91SAM9260_ID_EMAC, rt_macb_isr, RT_NULL);
//rt_hw_interrupt_umask(AT91SAM9260_ID_EMAC);
}

335
bsp/at91sam9260/macb.h Executable file
View File

@ -0,0 +1,335 @@
/*
* File : macb.h
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006, RT-Thread Develop Team
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rt-thread.org/license/LICENSE
*
* Change Logs:
* Date Author Notes
* 2011-03-18 weety first version
*/
#ifndef _MACB_H
#define _MACB_H
#include <mii.h>
/* MACB register offsets */
#define MACB_NCR 0x0000
#define MACB_NCFGR 0x0004
#define MACB_NSR 0x0008
#define MACB_TSR 0x0014
#define MACB_RBQP 0x0018
#define MACB_TBQP 0x001c
#define MACB_RSR 0x0020
#define MACB_ISR 0x0024
#define MACB_IER 0x0028
#define MACB_IDR 0x002c
#define MACB_IMR 0x0030
#define MACB_MAN 0x0034
#define MACB_PTR 0x0038
#define MACB_PFR 0x003c
#define MACB_FTO 0x0040
#define MACB_SCF 0x0044
#define MACB_MCF 0x0048
#define MACB_FRO 0x004c
#define MACB_FCSE 0x0050
#define MACB_ALE 0x0054
#define MACB_DTF 0x0058
#define MACB_LCOL 0x005c
#define MACB_EXCOL 0x0060
#define MACB_TUND 0x0064
#define MACB_CSE 0x0068
#define MACB_RRE 0x006c
#define MACB_ROVR 0x0070
#define MACB_RSE 0x0074
#define MACB_ELE 0x0078
#define MACB_RJA 0x007c
#define MACB_USF 0x0080
#define MACB_STE 0x0084
#define MACB_RLE 0x0088
#define MACB_TPF 0x008c
#define MACB_HRB 0x0090
#define MACB_HRT 0x0094
#define MACB_SA1B 0x0098
#define MACB_SA1T 0x009c
#define MACB_SA2B 0x00a0
#define MACB_SA2T 0x00a4
#define MACB_SA3B 0x00a8
#define MACB_SA3T 0x00ac
#define MACB_SA4B 0x00b0
#define MACB_SA4T 0x00b4
#define MACB_TID 0x00b8
#define MACB_TPQ 0x00bc
#define MACB_USRIO 0x00c0
#define MACB_WOL 0x00c4
/* Bitfields in NCR */
#define MACB_LB_OFFSET 0
#define MACB_LB_SIZE 1
#define MACB_LLB_OFFSET 1
#define MACB_LLB_SIZE 1
#define MACB_RE_OFFSET 2
#define MACB_RE_SIZE 1
#define MACB_TE_OFFSET 3
#define MACB_TE_SIZE 1
#define MACB_MPE_OFFSET 4
#define MACB_MPE_SIZE 1
#define MACB_CLRSTAT_OFFSET 5
#define MACB_CLRSTAT_SIZE 1
#define MACB_INCSTAT_OFFSET 6
#define MACB_INCSTAT_SIZE 1
#define MACB_WESTAT_OFFSET 7
#define MACB_WESTAT_SIZE 1
#define MACB_BP_OFFSET 8
#define MACB_BP_SIZE 1
#define MACB_TSTART_OFFSET 9
#define MACB_TSTART_SIZE 1
#define MACB_THALT_OFFSET 10
#define MACB_THALT_SIZE 1
#define MACB_NCR_TPF_OFFSET 11
#define MACB_NCR_TPF_SIZE 1
#define MACB_TZQ_OFFSET 12
#define MACB_TZQ_SIZE 1
/* Bitfields in NCFGR */
#define MACB_SPD_OFFSET 0
#define MACB_SPD_SIZE 1
#define MACB_FD_OFFSET 1
#define MACB_FD_SIZE 1
#define MACB_BIT_RATE_OFFSET 2
#define MACB_BIT_RATE_SIZE 1
#define MACB_JFRAME_OFFSET 3
#define MACB_JFRAME_SIZE 1
#define MACB_CAF_OFFSET 4
#define MACB_CAF_SIZE 1
#define MACB_NBC_OFFSET 5
#define MACB_NBC_SIZE 1
#define MACB_NCFGR_MTI_OFFSET 6
#define MACB_NCFGR_MTI_SIZE 1
#define MACB_UNI_OFFSET 7
#define MACB_UNI_SIZE 1
#define MACB_BIG_OFFSET 8
#define MACB_BIG_SIZE 1
#define MACB_EAE_OFFSET 9
#define MACB_EAE_SIZE 1
#define MACB_CLK_OFFSET 10
#define MACB_CLK_SIZE 2
#define MACB_RTY_OFFSET 12
#define MACB_RTY_SIZE 1
#define MACB_PAE_OFFSET 13
#define MACB_PAE_SIZE 1
#define MACB_RBOF_OFFSET 14
#define MACB_RBOF_SIZE 2
#define MACB_RLCE_OFFSET 16
#define MACB_RLCE_SIZE 1
#define MACB_DRFCS_OFFSET 17
#define MACB_DRFCS_SIZE 1
#define MACB_EFRHD_OFFSET 18
#define MACB_EFRHD_SIZE 1
#define MACB_IRXFCS_OFFSET 19
#define MACB_IRXFCS_SIZE 1
/* Bitfields in NSR */
#define MACB_NSR_LINK_OFFSET 0
#define MACB_NSR_LINK_SIZE 1
#define MACB_MDIO_OFFSET 1
#define MACB_MDIO_SIZE 1
#define MACB_IDLE_OFFSET 2
#define MACB_IDLE_SIZE 1
/* Bitfields in TSR */
#define MACB_UBR_OFFSET 0
#define MACB_UBR_SIZE 1
#define MACB_COL_OFFSET 1
#define MACB_COL_SIZE 1
#define MACB_TSR_RLE_OFFSET 2
#define MACB_TSR_RLE_SIZE 1
#define MACB_TGO_OFFSET 3
#define MACB_TGO_SIZE 1
#define MACB_BEX_OFFSET 4
#define MACB_BEX_SIZE 1
#define MACB_COMP_OFFSET 5
#define MACB_COMP_SIZE 1
#define MACB_UND_OFFSET 6
#define MACB_UND_SIZE 1
/* Bitfields in RSR */
#define MACB_BNA_OFFSET 0
#define MACB_BNA_SIZE 1
#define MACB_REC_OFFSET 1
#define MACB_REC_SIZE 1
#define MACB_OVR_OFFSET 2
#define MACB_OVR_SIZE 1
/* Bitfields in ISR/IER/IDR/IMR */
#define MACB_MFD_OFFSET 0
#define MACB_MFD_SIZE 1
#define MACB_RCOMP_OFFSET 1
#define MACB_RCOMP_SIZE 1
#define MACB_RXUBR_OFFSET 2
#define MACB_RXUBR_SIZE 1
#define MACB_TXUBR_OFFSET 3
#define MACB_TXUBR_SIZE 1
#define MACB_ISR_TUND_OFFSET 4
#define MACB_ISR_TUND_SIZE 1
#define MACB_ISR_RLE_OFFSET 5
#define MACB_ISR_RLE_SIZE 1
#define MACB_TXERR_OFFSET 6
#define MACB_TXERR_SIZE 1
#define MACB_TCOMP_OFFSET 7
#define MACB_TCOMP_SIZE 1
#define MACB_ISR_LINK_OFFSET 9
#define MACB_ISR_LINK_SIZE 1
#define MACB_ISR_ROVR_OFFSET 10
#define MACB_ISR_ROVR_SIZE 1
#define MACB_HRESP_OFFSET 11
#define MACB_HRESP_SIZE 1
#define MACB_PFR_OFFSET 12
#define MACB_PFR_SIZE 1
#define MACB_PTZ_OFFSET 13
#define MACB_PTZ_SIZE 1
/* Bitfields in MAN */
#define MACB_DATA_OFFSET 0
#define MACB_DATA_SIZE 16
#define MACB_CODE_OFFSET 16
#define MACB_CODE_SIZE 2
#define MACB_REGA_OFFSET 18
#define MACB_REGA_SIZE 5
#define MACB_PHYA_OFFSET 23
#define MACB_PHYA_SIZE 5
#define MACB_RW_OFFSET 28
#define MACB_RW_SIZE 2
#define MACB_SOF_OFFSET 30
#define MACB_SOF_SIZE 2
/* Bitfields in USRIO (AVR32) */
#define MACB_MII_OFFSET 0
#define MACB_MII_SIZE 1
#define MACB_EAM_OFFSET 1
#define MACB_EAM_SIZE 1
#define MACB_TX_PAUSE_OFFSET 2
#define MACB_TX_PAUSE_SIZE 1
#define MACB_TX_PAUSE_ZERO_OFFSET 3
#define MACB_TX_PAUSE_ZERO_SIZE 1
/* Bitfields in USRIO (AT91) */
#define MACB_RMII_OFFSET 0
#define MACB_RMII_SIZE 1
#define MACB_CLKEN_OFFSET 1
#define MACB_CLKEN_SIZE 1
/* Bitfields in WOL */
#define MACB_IP_OFFSET 0
#define MACB_IP_SIZE 16
#define MACB_MAG_OFFSET 16
#define MACB_MAG_SIZE 1
#define MACB_ARP_OFFSET 17
#define MACB_ARP_SIZE 1
#define MACB_SA1_OFFSET 18
#define MACB_SA1_SIZE 1
#define MACB_WOL_MTI_OFFSET 19
#define MACB_WOL_MTI_SIZE 1
/* Constants for CLK */
#define MACB_CLK_DIV8 0
#define MACB_CLK_DIV16 1
#define MACB_CLK_DIV32 2
#define MACB_CLK_DIV64 3
/* Constants for MAN register */
#define MACB_MAN_SOF 1
#define MACB_MAN_WRITE 1
#define MACB_MAN_READ 2
#define MACB_MAN_CODE 2
/* Bit manipulation macros */
#define MACB_BIT(name) \
(1 << MACB_##name##_OFFSET)
#define MACB_BF(name,value) \
(((value) & ((1 << MACB_##name##_SIZE) - 1)) \
<< MACB_##name##_OFFSET)
#define MACB_BFEXT(name,value)\
(((value) >> MACB_##name##_OFFSET) \
& ((1 << MACB_##name##_SIZE) - 1))
#define MACB_BFINS(name,value,old) \
(((old) & ~(((1 << MACB_##name##_SIZE) - 1) \
<< MACB_##name##_OFFSET)) \
| MACB_BF(name,value))
/* Register access macros */
#define macb_readl(port,reg) \
readl((port)->regs + MACB_##reg)
#define macb_writel(port,reg,value) \
writel((value), (port)->regs + MACB_##reg)
struct dma_desc {
rt_uint32_t addr;
rt_uint32_t ctrl;
};
/* DMA descriptor bitfields */
#define MACB_RX_USED_OFFSET 0
#define MACB_RX_USED_SIZE 1
#define MACB_RX_WRAP_OFFSET 1
#define MACB_RX_WRAP_SIZE 1
#define MACB_RX_WADDR_OFFSET 2
#define MACB_RX_WADDR_SIZE 30
#define MACB_RX_FRMLEN_OFFSET 0
#define MACB_RX_FRMLEN_SIZE 12
#define MACB_RX_OFFSET_OFFSET 12
#define MACB_RX_OFFSET_SIZE 2
#define MACB_RX_SOF_OFFSET 14
#define MACB_RX_SOF_SIZE 1
#define MACB_RX_EOF_OFFSET 15
#define MACB_RX_EOF_SIZE 1
#define MACB_RX_CFI_OFFSET 16
#define MACB_RX_CFI_SIZE 1
#define MACB_RX_VLAN_PRI_OFFSET 17
#define MACB_RX_VLAN_PRI_SIZE 3
#define MACB_RX_PRI_TAG_OFFSET 20
#define MACB_RX_PRI_TAG_SIZE 1
#define MACB_RX_VLAN_TAG_OFFSET 21
#define MACB_RX_VLAN_TAG_SIZE 1
#define MACB_RX_TYPEID_MATCH_OFFSET 22
#define MACB_RX_TYPEID_MATCH_SIZE 1
#define MACB_RX_SA4_MATCH_OFFSET 23
#define MACB_RX_SA4_MATCH_SIZE 1
#define MACB_RX_SA3_MATCH_OFFSET 24
#define MACB_RX_SA3_MATCH_SIZE 1
#define MACB_RX_SA2_MATCH_OFFSET 25
#define MACB_RX_SA2_MATCH_SIZE 1
#define MACB_RX_SA1_MATCH_OFFSET 26
#define MACB_RX_SA1_MATCH_SIZE 1
#define MACB_RX_EXT_MATCH_OFFSET 28
#define MACB_RX_EXT_MATCH_SIZE 1
#define MACB_RX_UHASH_MATCH_OFFSET 29
#define MACB_RX_UHASH_MATCH_SIZE 1
#define MACB_RX_MHASH_MATCH_OFFSET 30
#define MACB_RX_MHASH_MATCH_SIZE 1
#define MACB_RX_BROADCAST_OFFSET 31
#define MACB_RX_BROADCAST_SIZE 1
#define MACB_TX_FRMLEN_OFFSET 0
#define MACB_TX_FRMLEN_SIZE 11
#define MACB_TX_LAST_OFFSET 15
#define MACB_TX_LAST_SIZE 1
#define MACB_TX_NOCRC_OFFSET 16
#define MACB_TX_NOCRC_SIZE 1
#define MACB_TX_BUF_EXHAUSTED_OFFSET 27
#define MACB_TX_BUF_EXHAUSTED_SIZE 1
#define MACB_TX_UNDERRUN_OFFSET 28
#define MACB_TX_UNDERRUN_SIZE 1
#define MACB_TX_ERROR_OFFSET 29
#define MACB_TX_ERROR_SIZE 1
#define MACB_TX_WRAP_OFFSET 30
#define MACB_TX_WRAP_SIZE 1
#define MACB_TX_USED_OFFSET 31
#define MACB_TX_USED_SIZE 1
#endif /* _MACB_H */

181
bsp/at91sam9260/mii.h Normal file
View File

@ -0,0 +1,181 @@
/*
* File : mii.h
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006, RT-Thread Develop Team
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rt-thread.org/license/LICENSE
*
* Change Logs:
* Date Author Notes
* 2011-03-18 weety first version
*/
#ifndef __MII_H__
#define __MII_H__
/* Generic MII registers. */
#define MII_BMCR 0x00 /* Basic mode control register */
#define MII_BMSR 0x01 /* Basic mode status register */
#define MII_PHYSID1 0x02 /* PHYS ID 1 */
#define MII_PHYSID2 0x03 /* PHYS ID 2 */
#define MII_ADVERTISE 0x04 /* Advertisement control reg */
#define MII_LPA 0x05 /* Link partner ability reg */
#define MII_EXPANSION 0x06 /* Expansion register */
#define MII_CTRL1000 0x09 /* 1000BASE-T control */
#define MII_STAT1000 0x0a /* 1000BASE-T status */
#define MII_ESTATUS 0x0f /* Extended Status */
#define MII_DCOUNTER 0x12 /* Disconnect counter */
#define MII_FCSCOUNTER 0x13 /* False carrier counter */
#define MII_NWAYTEST 0x14 /* N-way auto-neg test reg */
#define MII_RERRCOUNTER 0x15 /* Receive error counter */
#define MII_SREVISION 0x16 /* Silicon revision */
#define MII_RESV1 0x17 /* Reserved... */
#define MII_LBRERROR 0x18 /* Lpback, rx, bypass error */
#define MII_PHYADDR 0x19 /* PHY address */
#define MII_RESV2 0x1a /* Reserved... */
#define MII_TPISTATUS 0x1b /* TPI status for 10mbps */
#define MII_NCONFIG 0x1c /* Network interface config */
/* Basic mode control register. */
#define BMCR_RESV 0x003f /* Unused... */
#define BMCR_SPEED1000 0x0040 /* MSB of Speed (1000) */
#define BMCR_CTST 0x0080 /* Collision test */
#define BMCR_FULLDPLX 0x0100 /* Full duplex */
#define BMCR_ANRESTART 0x0200 /* Auto negotiation restart */
#define BMCR_ISOLATE 0x0400 /* Disconnect DP83840 from MII */
#define BMCR_PDOWN 0x0800 /* Powerdown the DP83840 */
#define BMCR_ANENABLE 0x1000 /* Enable auto negotiation */
#define BMCR_SPEED100 0x2000 /* Select 100Mbps */
#define BMCR_LOOPBACK 0x4000 /* TXD loopback bits */
#define BMCR_RESET 0x8000 /* Reset the DP83840 */
/* Basic mode status register. */
#define BMSR_ERCAP 0x0001 /* Ext-reg capability */
#define BMSR_JCD 0x0002 /* Jabber detected */
#define BMSR_LSTATUS 0x0004 /* Link status */
#define BMSR_ANEGCAPABLE 0x0008 /* Able to do auto-negotiation */
#define BMSR_RFAULT 0x0010 /* Remote fault detected */
#define BMSR_ANEGCOMPLETE 0x0020 /* Auto-negotiation complete */
#define BMSR_RESV 0x00c0 /* Unused... */
#define BMSR_ESTATEN 0x0100 /* Extended Status in R15 */
#define BMSR_100HALF2 0x0200 /* Can do 100BASE-T2 HDX */
#define BMSR_100FULL2 0x0400 /* Can do 100BASE-T2 FDX */
#define BMSR_10HALF 0x0800 /* Can do 10mbps, half-duplex */
#define BMSR_10FULL 0x1000 /* Can do 10mbps, full-duplex */
#define BMSR_100HALF 0x2000 /* Can do 100mbps, half-duplex */
#define BMSR_100FULL 0x4000 /* Can do 100mbps, full-duplex */
#define BMSR_100BASE4 0x8000 /* Can do 100mbps, 4k packets */
/* Advertisement control register. */
#define ADVERTISE_SLCT 0x001f /* Selector bits */
#define ADVERTISE_CSMA 0x0001 /* Only selector supported */
#define ADVERTISE_10HALF 0x0020 /* Try for 10mbps half-duplex */
#define ADVERTISE_1000XFULL 0x0020 /* Try for 1000BASE-X full-duplex */
#define ADVERTISE_10FULL 0x0040 /* Try for 10mbps full-duplex */
#define ADVERTISE_1000XHALF 0x0040 /* Try for 1000BASE-X half-duplex */
#define ADVERTISE_100HALF 0x0080 /* Try for 100mbps half-duplex */
#define ADVERTISE_1000XPAUSE 0x0080 /* Try for 1000BASE-X pause */
#define ADVERTISE_100FULL 0x0100 /* Try for 100mbps full-duplex */
#define ADVERTISE_1000XPSE_ASYM 0x0100 /* Try for 1000BASE-X asym pause */
#define ADVERTISE_100BASE4 0x0200 /* Try for 100mbps 4k packets */
#define ADVERTISE_PAUSE_CAP 0x0400 /* Try for pause */
#define ADVERTISE_PAUSE_ASYM 0x0800 /* Try for asymetric pause */
#define ADVERTISE_RESV 0x1000 /* Unused... */
#define ADVERTISE_RFAULT 0x2000 /* Say we can detect faults */
#define ADVERTISE_LPACK 0x4000 /* Ack link partners response */
#define ADVERTISE_NPAGE 0x8000 /* Next page bit */
#define ADVERTISE_FULL (ADVERTISE_100FULL | ADVERTISE_10FULL | \
ADVERTISE_CSMA)
#define ADVERTISE_ALL (ADVERTISE_10HALF | ADVERTISE_10FULL | \
ADVERTISE_100HALF | ADVERTISE_100FULL)
/* Link partner ability register. */
#define LPA_SLCT 0x001f /* Same as advertise selector */
#define LPA_10HALF 0x0020 /* Can do 10mbps half-duplex */
#define LPA_1000XFULL 0x0020 /* Can do 1000BASE-X full-duplex */
#define LPA_10FULL 0x0040 /* Can do 10mbps full-duplex */
#define LPA_1000XHALF 0x0040 /* Can do 1000BASE-X half-duplex */
#define LPA_100HALF 0x0080 /* Can do 100mbps half-duplex */
#define LPA_1000XPAUSE 0x0080 /* Can do 1000BASE-X pause */
#define LPA_100FULL 0x0100 /* Can do 100mbps full-duplex */
#define LPA_1000XPAUSE_ASYM 0x0100 /* Can do 1000BASE-X pause asym*/
#define LPA_100BASE4 0x0200 /* Can do 100mbps 4k packets */
#define LPA_PAUSE_CAP 0x0400 /* Can pause */
#define LPA_PAUSE_ASYM 0x0800 /* Can pause asymetrically */
#define LPA_RESV 0x1000 /* Unused... */
#define LPA_RFAULT 0x2000 /* Link partner faulted */
#define LPA_LPACK 0x4000 /* Link partner acked us */
#define LPA_NPAGE 0x8000 /* Next page bit */
#define LPA_DUPLEX (LPA_10FULL | LPA_100FULL)
#define LPA_100 (LPA_100FULL | LPA_100HALF | LPA_100BASE4)
/* Expansion register for auto-negotiation. */
#define EXPANSION_NWAY 0x0001 /* Can do N-way auto-nego */
#define EXPANSION_LCWP 0x0002 /* Got new RX page code word */
#define EXPANSION_ENABLENPAGE 0x0004 /* This enables npage words */
#define EXPANSION_NPCAPABLE 0x0008 /* Link partner supports npage */
#define EXPANSION_MFAULTS 0x0010 /* Multiple faults detected */
#define EXPANSION_RESV 0xffe0 /* Unused... */
#define ESTATUS_1000_TFULL 0x2000 /* Can do 1000BT Full */
#define ESTATUS_1000_THALF 0x1000 /* Can do 1000BT Half */
/* N-way test register. */
#define NWAYTEST_RESV1 0x00ff /* Unused... */
#define NWAYTEST_LOOPBACK 0x0100 /* Enable loopback for N-way */
#define NWAYTEST_RESV2 0xfe00 /* Unused... */
/* 1000BASE-T Control register */
#define ADVERTISE_1000FULL 0x0200 /* Advertise 1000BASE-T full duplex */
#define ADVERTISE_1000HALF 0x0100 /* Advertise 1000BASE-T half duplex */
/* 1000BASE-T Status register */
#define LPA_1000LOCALRXOK 0x2000 /* Link partner local receiver status */
#define LPA_1000REMRXOK 0x1000 /* Link partner remote receiver status */
#define LPA_1000FULL 0x0800 /* Link partner 1000BASE-T full duplex */
#define LPA_1000HALF 0x0400 /* Link partner 1000BASE-T half duplex */
/* Flow control flags */
#define FLOW_CTRL_TX 0x01
#define FLOW_CTRL_RX 0x02
/**
* mii_nway_result
* @negotiated: value of MII ANAR and'd with ANLPAR
*
* Given a set of MII abilities, check each bit and returns the
* currently supported media, in the priority order defined by
* IEEE 802.3u. We use LPA_xxx constants but note this is not the
* value of LPA solely, as described above.
*
* The one exception to IEEE 802.3u is that 100baseT4 is placed
* between 100T-full and 100T-half. If your phy does not support
* 100T4 this is fine. If your phy places 100T4 elsewhere in the
* priority order, you will need to roll your own function.
*/
static inline unsigned int mii_nway_result (unsigned int negotiated)
{
unsigned int ret;
if (negotiated & LPA_100FULL)
ret = LPA_100FULL;
else if (negotiated & LPA_100BASE4)
ret = LPA_100BASE4;
else if (negotiated & LPA_100HALF)
ret = LPA_100HALF;
else if (negotiated & LPA_10FULL)
ret = LPA_10FULL;
else
ret = LPA_10HALF;
return ret;
}
#endif /* __MII_H__ */

View File

@ -120,7 +120,7 @@
/* SECTION: lwip, a lightweight TCP/IP protocol stack */
/* Using lightweight TCP/IP protocol stack */
//#define RT_USING_LWIP
#define RT_USING_LWIP
#define RT_LWIP_DNS
/* Trace LwIP protocol */

View File

@ -116,7 +116,12 @@ void rtthread_startup(void)
#endif
#ifdef RT_USING_LWIP
/* register ethernetif device */
eth_system_device_init();
rt_hw_macb_init();
/* init lwip system */
lwip_sys_init();
rt_kprintf("TCP/IP initialized!\n");
#endif
/*init all registed devices */