mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-10 15:14:43 +00:00
nds32: eth: Support ftmac100 DM.
Support Andestech eth ftmac100 device tree flow on AG101P/AE3XX platform. Verification: Boot linux kernel via dhcp and bootm ok. NDS32 # setenv bootm_size 0x2000000;setenv fdt_high 0x1f00000; NDS32 # dhcp 0x600000 10.0.4.97:boomimage-310y-ae300-spi.bin BOOTP broadcast 1 BOOTP broadcast 2 BOOTP broadcast 3 BOOTP broadcast 4 DHCP client bound to address 10.0.4.178 (4899 ms) Using mac@e0100000 device TFTP from server 10.0.4.97; our IP address is 10.0.4.178 Filename 'boomimage-310y-ae300-spi.bin'. Load address: 0x600000 Loading: ################################################################# ################################################################# ################################################################# ... ... ################################### 233.4 KiB/s done Bytes transferred = 13872076 (d3abcc hex) NDS32 # dhcp 0x2000000 10.0.4.97:ae300.dtb BOOTP broadcast 1 BOOTP broadcast 2 BOOTP broadcast 3 BOOTP broadcast 4 DHCP client bound to address 10.0.4.178 (4592 ms) Using mac@e0100000 device TFTP from server 10.0.4.97; our IP address is 10.0.4.178 Filename 'ae300.dtb'. Load address: 0x2000000 Loading: # 82 KiB/s done Bytes transferred = 2378 (94a hex) NDS32 # bootm 0x600000 - 0x2000000 Image Name: Created: 2017-03-22 6:52:03 UTC Image Type: NDS32 Linux Kernel Image (uncompressed) Data Size: 13872012 Bytes = 13.2 MiB Load Address: 0000c000 Entry Point: 0000c000 Verifying Checksum ... OK Booting using the fdt blob at 0x2000000 Loading Kernel Image ... OK Loading Device Tree to 01efc000, end 01eff949 ... OK Linux version 3.10.102-20375-gb0034c1-dirty (rick@app09) (gcc version 4.9.3 (2016-07-06_nds32le-linux-glibc-v3_experimental) ) #293 PREEMPT Wed Mar 22 14:49:28 CST 2017 CPU: NDS32 N13, AndesCore ID(wb), CPU_VER 0x0d11103f(id 13, rev 17, cfg 4159) ... ... Signed-off-by: rick <rick@andestech.com>
This commit is contained in:
parent
4c78028737
commit
be71a179bd
10 changed files with 251 additions and 61 deletions
|
@ -7,6 +7,7 @@
|
|||
|
||||
aliases {
|
||||
uart0 = &serial0;
|
||||
ethernet0 = &mac0;
|
||||
} ;
|
||||
|
||||
chosen {
|
||||
|
@ -55,6 +56,12 @@
|
|||
clock-frequency = <30000000>;
|
||||
};
|
||||
|
||||
mac0: mac@e0100000 {
|
||||
compatible = "andestech,atmac100";
|
||||
reg = <0xe0100000 0x1000>;
|
||||
interrupts = <25 4>;
|
||||
};
|
||||
|
||||
nor@0,0 {
|
||||
compatible = "cfi-flash";
|
||||
reg = <0x88000000 0x1000>;
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
aliases {
|
||||
uart0 = &serial0;
|
||||
ethernet0 = &mac0;
|
||||
} ;
|
||||
|
||||
chosen {
|
||||
|
@ -54,4 +55,9 @@
|
|||
clock-frequency = <15000000>;
|
||||
};
|
||||
|
||||
mac0: mac@90900000 {
|
||||
compatible = "andestech,atmac100";
|
||||
reg = <0x90900000 0x1000>;
|
||||
interrupts = <25 4>;
|
||||
};
|
||||
};
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
*/
|
||||
|
||||
#include <common.h>
|
||||
#if defined(CONFIG_FTMAC100)
|
||||
#if defined(CONFIG_FTMAC100) && !defined(CONFIG_DM_ETH)
|
||||
#include <netdev.h>
|
||||
#endif
|
||||
#include <linux/io.h>
|
||||
|
@ -56,7 +56,7 @@ int dram_init_banksize(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_FTMAC100)
|
||||
#if defined(CONFIG_FTMAC100) && !defined(CONFIG_DM_ETH)
|
||||
int board_eth_init(bd_t *bd)
|
||||
{
|
||||
return ftmac100_initialize(bd);
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
*/
|
||||
|
||||
#include <common.h>
|
||||
#if defined(CONFIG_FTMAC100)
|
||||
#if defined(CONFIG_FTMAC100) && !defined(CONFIG_DM_ETH)
|
||||
#include <netdev.h>
|
||||
#endif
|
||||
#include <linux/io.h>
|
||||
|
@ -62,7 +62,7 @@ int dram_init_banksize(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_FTMAC100)
|
||||
#if defined(CONFIG_FTMAC100) && !defined(CONFIG_DM_ETH)
|
||||
int board_eth_init(bd_t *bd)
|
||||
{
|
||||
return ftmac100_initialize(bd);
|
||||
|
|
|
@ -16,9 +16,12 @@ CONFIG_MMC=y
|
|||
CONFIG_MTD_NOR_FLASH=y
|
||||
CONFIG_BAUDRATE=38400
|
||||
CONFIG_OF_CONTROL=y
|
||||
CONFIG_NET_RANDOM_ETHADDR=y
|
||||
CONFIG_DM=y
|
||||
CONFIG_MTD=y
|
||||
CONFIG_CFI_FLASH=y
|
||||
CONFIG_DM_ETH=y
|
||||
CONFIG_FTMAC100=y
|
||||
CONFIG_DM_SERIAL=y
|
||||
CONFIG_SYS_NS16550=y
|
||||
CONFIG_TIMER=y
|
||||
|
|
|
@ -16,7 +16,10 @@ CONFIG_MMC=y
|
|||
CONFIG_MTD_NOR_FLASH=y
|
||||
CONFIG_BAUDRATE=38400
|
||||
CONFIG_OF_CONTROL=y
|
||||
CONFIG_NET_RANDOM_ETHADDR=y
|
||||
CONFIG_DM=y
|
||||
CONFIG_DM_ETH=y
|
||||
CONFIG_FTMAC100=y
|
||||
CONFIG_DM_SERIAL=y
|
||||
CONFIG_SYS_NS16550=y
|
||||
CONFIG_TIMER=y
|
||||
|
|
|
@ -225,4 +225,9 @@ config GMAC_ROCKCHIP
|
|||
This driver provides Rockchip SoCs network support based on the
|
||||
Synopsys Designware driver.
|
||||
|
||||
config FTMAC100
|
||||
bool "Ftmac100 Ethernet Support"
|
||||
help
|
||||
This MAC is present in Andestech SoCs.
|
||||
|
||||
endif # NETDEVICES
|
||||
|
|
|
@ -11,24 +11,29 @@
|
|||
#include <common.h>
|
||||
#include <malloc.h>
|
||||
#include <net.h>
|
||||
#include <asm/io.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
#include "ftmac100.h"
|
||||
|
||||
#ifdef CONFIG_DM_ETH
|
||||
#include <dm.h>
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
#endif
|
||||
#define ETH_ZLEN 60
|
||||
|
||||
struct ftmac100_data {
|
||||
struct ftmac100_txdes txdes[1];
|
||||
struct ftmac100_rxdes rxdes[PKTBUFSRX];
|
||||
int rx_index;
|
||||
const char *name;
|
||||
phys_addr_t iobase;
|
||||
};
|
||||
|
||||
/*
|
||||
* Reset MAC
|
||||
*/
|
||||
static void ftmac100_reset (struct eth_device *dev)
|
||||
static void ftmac100_reset(struct ftmac100_data *priv)
|
||||
{
|
||||
struct ftmac100 *ftmac100 = (struct ftmac100 *)dev->iobase;
|
||||
struct ftmac100 *ftmac100 = (struct ftmac100 *)priv->iobase;
|
||||
|
||||
debug ("%s()\n", __func__);
|
||||
|
||||
|
@ -41,9 +46,10 @@ static void ftmac100_reset (struct eth_device *dev)
|
|||
/*
|
||||
* Set MAC address
|
||||
*/
|
||||
static void ftmac100_set_mac (struct eth_device *dev, const unsigned char *mac)
|
||||
static void ftmac100_set_mac(struct ftmac100_data *priv ,
|
||||
const unsigned char *mac)
|
||||
{
|
||||
struct ftmac100 *ftmac100 = (struct ftmac100 *)dev->iobase;
|
||||
struct ftmac100 *ftmac100 = (struct ftmac100 *)priv->iobase;
|
||||
unsigned int maddr = mac[0] << 8 | mac[1];
|
||||
unsigned int laddr = mac[2] << 24 | mac[3] << 16 | mac[4] << 8 | mac[5];
|
||||
|
||||
|
@ -53,29 +59,22 @@ static void ftmac100_set_mac (struct eth_device *dev, const unsigned char *mac)
|
|||
writel (laddr, &ftmac100->mac_ladr);
|
||||
}
|
||||
|
||||
static void ftmac100_set_mac_from_env (struct eth_device *dev)
|
||||
{
|
||||
eth_getenv_enetaddr ("ethaddr", dev->enetaddr);
|
||||
|
||||
ftmac100_set_mac (dev, dev->enetaddr);
|
||||
}
|
||||
|
||||
/*
|
||||
* disable transmitter, receiver
|
||||
* Disable MAC
|
||||
*/
|
||||
static void ftmac100_halt (struct eth_device *dev)
|
||||
static void _ftmac100_halt(struct ftmac100_data *priv)
|
||||
{
|
||||
struct ftmac100 *ftmac100 = (struct ftmac100 *)dev->iobase;
|
||||
|
||||
struct ftmac100 *ftmac100 = (struct ftmac100 *)priv->iobase;
|
||||
debug ("%s()\n", __func__);
|
||||
|
||||
writel (0, &ftmac100->maccr);
|
||||
}
|
||||
|
||||
static int ftmac100_init (struct eth_device *dev, bd_t *bd)
|
||||
/*
|
||||
* Initialize MAC
|
||||
*/
|
||||
static int _ftmac100_init(struct ftmac100_data *priv, unsigned char enetaddr[6])
|
||||
{
|
||||
struct ftmac100 *ftmac100 = (struct ftmac100 *)dev->iobase;
|
||||
struct ftmac100_data *priv = dev->priv;
|
||||
struct ftmac100 *ftmac100 = (struct ftmac100 *)priv->iobase;
|
||||
struct ftmac100_txdes *txdes = priv->txdes;
|
||||
struct ftmac100_rxdes *rxdes = priv->rxdes;
|
||||
unsigned int maccr;
|
||||
|
@ -83,11 +82,11 @@ static int ftmac100_init (struct eth_device *dev, bd_t *bd)
|
|||
|
||||
debug ("%s()\n", __func__);
|
||||
|
||||
ftmac100_reset (dev);
|
||||
ftmac100_reset(priv);
|
||||
|
||||
/* set the ethernet address */
|
||||
ftmac100_set_mac(priv, enetaddr);
|
||||
|
||||
ftmac100_set_mac_from_env (dev);
|
||||
|
||||
/* disable all interrupts */
|
||||
|
||||
|
@ -136,25 +135,37 @@ static int ftmac100_init (struct eth_device *dev, bd_t *bd)
|
|||
}
|
||||
|
||||
/*
|
||||
* Get a data block via Ethernet
|
||||
* Free receiving buffer
|
||||
*/
|
||||
static int ftmac100_recv (struct eth_device *dev)
|
||||
static int _ftmac100_free_pkt(struct ftmac100_data *priv)
|
||||
{
|
||||
struct ftmac100_rxdes *curr_des;
|
||||
curr_des = &priv->rxdes[priv->rx_index];
|
||||
/* release buffer to DMA */
|
||||
curr_des->rxdes0 |= FTMAC100_RXDES0_RXDMA_OWN;
|
||||
priv->rx_index = (priv->rx_index + 1) % PKTBUFSRX;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Receive a data block via Ethernet
|
||||
*/
|
||||
static int __ftmac100_recv(struct ftmac100_data *priv)
|
||||
{
|
||||
struct ftmac100_data *priv = dev->priv;
|
||||
struct ftmac100_rxdes *curr_des;
|
||||
unsigned short rxlen;
|
||||
|
||||
curr_des = &priv->rxdes[priv->rx_index];
|
||||
|
||||
if (curr_des->rxdes0 & FTMAC100_RXDES0_RXDMA_OWN)
|
||||
return -1;
|
||||
return 0;
|
||||
|
||||
if (curr_des->rxdes0 & (FTMAC100_RXDES0_RX_ERR |
|
||||
FTMAC100_RXDES0_CRC_ERR |
|
||||
FTMAC100_RXDES0_FTL |
|
||||
FTMAC100_RXDES0_RUNT |
|
||||
FTMAC100_RXDES0_RX_ODD_NB)) {
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
rxlen = FTMAC100_RXDES0_RFL (curr_des->rxdes0);
|
||||
|
@ -162,26 +173,15 @@ static int ftmac100_recv (struct eth_device *dev)
|
|||
debug ("%s(): RX buffer %d, %x received\n",
|
||||
__func__, priv->rx_index, rxlen);
|
||||
|
||||
/* pass the packet up to the protocol layers. */
|
||||
|
||||
net_process_received_packet((void *)curr_des->rxdes2, rxlen);
|
||||
|
||||
/* release buffer to DMA */
|
||||
|
||||
curr_des->rxdes0 |= FTMAC100_RXDES0_RXDMA_OWN;
|
||||
|
||||
priv->rx_index = (priv->rx_index + 1) % PKTBUFSRX;
|
||||
|
||||
return 0;
|
||||
return rxlen;
|
||||
}
|
||||
|
||||
/*
|
||||
* Send a data block via Ethernet
|
||||
*/
|
||||
static int ftmac100_send(struct eth_device *dev, void *packet, int length)
|
||||
static int _ftmac100_send(struct ftmac100_data *priv, void *packet, int length)
|
||||
{
|
||||
struct ftmac100 *ftmac100 = (struct ftmac100 *)dev->iobase;
|
||||
struct ftmac100_data *priv = dev->priv;
|
||||
struct ftmac100 *ftmac100 = (struct ftmac100 *)priv->iobase;
|
||||
struct ftmac100_txdes *curr_des = priv->txdes;
|
||||
ulong start;
|
||||
|
||||
|
@ -224,25 +224,69 @@ static int ftmac100_send(struct eth_device *dev, void *packet, int length)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_DM_ETH
|
||||
/*
|
||||
* disable transmitter, receiver
|
||||
*/
|
||||
static void ftmac100_halt(struct eth_device *dev)
|
||||
{
|
||||
struct ftmac100_data *priv = dev->priv;
|
||||
return _ftmac100_halt(priv);
|
||||
}
|
||||
|
||||
static int ftmac100_init(struct eth_device *dev, bd_t *bd)
|
||||
{
|
||||
struct ftmac100_data *priv = dev->priv;
|
||||
return _ftmac100_init(priv , dev->enetaddr);
|
||||
}
|
||||
|
||||
static int _ftmac100_recv(struct ftmac100_data *priv)
|
||||
{
|
||||
struct ftmac100_rxdes *curr_des;
|
||||
unsigned short len;
|
||||
curr_des = &priv->rxdes[priv->rx_index];
|
||||
len = __ftmac100_recv(priv);
|
||||
if (len) {
|
||||
/* pass the packet up to the protocol layers. */
|
||||
net_process_received_packet((void *)curr_des->rxdes2, len);
|
||||
_ftmac100_free_pkt(priv);
|
||||
}
|
||||
return len ? 1 : 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get a data block via Ethernet
|
||||
*/
|
||||
static int ftmac100_recv(struct eth_device *dev)
|
||||
{
|
||||
struct ftmac100_data *priv = dev->priv;
|
||||
return _ftmac100_recv(priv);
|
||||
}
|
||||
|
||||
/*
|
||||
* Send a data block via Ethernet
|
||||
*/
|
||||
static int ftmac100_send(struct eth_device *dev, void *packet, int length)
|
||||
{
|
||||
struct ftmac100_data *priv = dev->priv;
|
||||
return _ftmac100_send(priv , packet , length);
|
||||
}
|
||||
|
||||
int ftmac100_initialize (bd_t *bd)
|
||||
{
|
||||
struct eth_device *dev;
|
||||
struct ftmac100_data *priv;
|
||||
|
||||
dev = malloc (sizeof *dev);
|
||||
if (!dev) {
|
||||
printf ("%s(): failed to allocate dev\n", __func__);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Transmit and receive descriptors should align to 16 bytes */
|
||||
|
||||
priv = memalign (16, sizeof (struct ftmac100_data));
|
||||
if (!priv) {
|
||||
printf ("%s(): failed to allocate priv\n", __func__);
|
||||
goto free_dev;
|
||||
}
|
||||
|
||||
memset (dev, 0, sizeof (*dev));
|
||||
memset (priv, 0, sizeof (*priv));
|
||||
|
||||
|
@ -253,7 +297,7 @@ int ftmac100_initialize (bd_t *bd)
|
|||
dev->send = ftmac100_send;
|
||||
dev->recv = ftmac100_recv;
|
||||
dev->priv = priv;
|
||||
|
||||
priv->iobase = dev->iobase;
|
||||
eth_register (dev);
|
||||
|
||||
return 1;
|
||||
|
@ -263,3 +307,135 @@ free_dev:
|
|||
out:
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_DM_ETH
|
||||
static int ftmac100_start(struct udevice *dev)
|
||||
{
|
||||
struct eth_pdata *plat = dev_get_platdata(dev);
|
||||
struct ftmac100_data *priv = dev_get_priv(dev);
|
||||
|
||||
return _ftmac100_init(priv, plat->enetaddr);
|
||||
}
|
||||
|
||||
static void ftmac100_stop(struct udevice *dev)
|
||||
{
|
||||
struct ftmac100_data *priv = dev_get_priv(dev);
|
||||
_ftmac100_halt(priv);
|
||||
}
|
||||
|
||||
static int ftmac100_send(struct udevice *dev, void *packet, int length)
|
||||
{
|
||||
struct ftmac100_data *priv = dev_get_priv(dev);
|
||||
int ret;
|
||||
ret = _ftmac100_send(priv , packet , length);
|
||||
return ret ? 0 : -ETIMEDOUT;
|
||||
}
|
||||
|
||||
static int ftmac100_recv(struct udevice *dev, int flags, uchar **packetp)
|
||||
{
|
||||
struct ftmac100_data *priv = dev_get_priv(dev);
|
||||
struct ftmac100_rxdes *curr_des;
|
||||
curr_des = &priv->rxdes[priv->rx_index];
|
||||
int len;
|
||||
len = __ftmac100_recv(priv);
|
||||
if (len)
|
||||
*packetp = (void *)curr_des->rxdes2;
|
||||
|
||||
return len ? len : -EAGAIN;
|
||||
}
|
||||
|
||||
static int ftmac100_free_pkt(struct udevice *dev, uchar *packet, int length)
|
||||
{
|
||||
struct ftmac100_data *priv = dev_get_priv(dev);
|
||||
_ftmac100_free_pkt(priv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ftmac100_read_rom_hwaddr(struct udevice *dev)
|
||||
{
|
||||
struct eth_pdata *pdata = dev_get_platdata(dev);
|
||||
eth_getenv_enetaddr("ethaddr", pdata->enetaddr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char *dtbmacaddr(u32 ifno)
|
||||
{
|
||||
int node, len;
|
||||
char enet[16];
|
||||
const char *mac;
|
||||
const char *path;
|
||||
if (gd->fdt_blob == NULL) {
|
||||
printf("%s: don't have a valid gd->fdt_blob!\n", __func__);
|
||||
return NULL;
|
||||
}
|
||||
node = fdt_path_offset(gd->fdt_blob, "/aliases");
|
||||
if (node < 0)
|
||||
return NULL;
|
||||
|
||||
sprintf(enet, "ethernet%d", ifno);
|
||||
path = fdt_getprop(gd->fdt_blob, node, enet, NULL);
|
||||
if (!path) {
|
||||
printf("no alias for %s\n", enet);
|
||||
return NULL;
|
||||
}
|
||||
node = fdt_path_offset(gd->fdt_blob, path);
|
||||
mac = fdt_getprop(gd->fdt_blob, node, "mac-address", &len);
|
||||
if (mac && is_valid_ethaddr((u8 *)mac))
|
||||
return mac;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int ftmac100_ofdata_to_platdata(struct udevice *dev)
|
||||
{
|
||||
struct ftmac100_data *priv = dev_get_priv(dev);
|
||||
struct eth_pdata *pdata = dev_get_platdata(dev);
|
||||
const char *mac;
|
||||
pdata->iobase = dev_get_addr(dev);
|
||||
priv->iobase = pdata->iobase;
|
||||
mac = dtbmacaddr(0);
|
||||
if (mac)
|
||||
memcpy(pdata->enetaddr , mac , 6);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ftmac100_probe(struct udevice *dev)
|
||||
{
|
||||
struct ftmac100_data *priv = dev_get_priv(dev);
|
||||
priv->name = dev->name;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ftmac100_bind(struct udevice *dev)
|
||||
{
|
||||
return device_set_name(dev, dev->name);
|
||||
}
|
||||
|
||||
static const struct eth_ops ftmac100_ops = {
|
||||
.start = ftmac100_start,
|
||||
.send = ftmac100_send,
|
||||
.recv = ftmac100_recv,
|
||||
.stop = ftmac100_stop,
|
||||
.free_pkt = ftmac100_free_pkt,
|
||||
};
|
||||
|
||||
static const struct udevice_id ftmac100_ids[] = {
|
||||
{ .compatible = "andestech,atmac100" },
|
||||
{ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(ftmac100) = {
|
||||
.name = "nds32_mac",
|
||||
.id = UCLASS_ETH,
|
||||
.of_match = ftmac100_ids,
|
||||
.bind = ftmac100_bind,
|
||||
.ofdata_to_platdata = ftmac100_ofdata_to_platdata,
|
||||
.probe = ftmac100_probe,
|
||||
.ops = &ftmac100_ops,
|
||||
.priv_auto_alloc_size = sizeof(struct ftmac100_data),
|
||||
.platdata_auto_alloc_size = sizeof(struct eth_pdata),
|
||||
.flags = DM_FLAG_ALLOC_PRIV_DMA,
|
||||
};
|
||||
#endif
|
||||
|
|
|
@ -89,11 +89,6 @@
|
|||
#endif
|
||||
#define CONFIG_SYS_NS16550_CLK ((18432000 * 20) / 25) /* AG101P */
|
||||
|
||||
/*
|
||||
* Ethernet
|
||||
*/
|
||||
#define CONFIG_FTMAC100
|
||||
|
||||
/*
|
||||
* SD (MMC) controller
|
||||
*/
|
||||
|
|
|
@ -95,11 +95,6 @@
|
|||
#endif
|
||||
#define CONFIG_SYS_NS16550_CLK ((18432000 * 20) / 25) /* AG101P */
|
||||
|
||||
/*
|
||||
* Ethernet
|
||||
*/
|
||||
#define CONFIG_FTMAC100
|
||||
|
||||
/*
|
||||
* SD (MMC) controller
|
||||
*/
|
||||
|
|
Loading…
Reference in a new issue