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:
rick 2017-05-23 13:48:27 +08:00
parent 4c78028737
commit be71a179bd
10 changed files with 251 additions and 61 deletions

View file

@ -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>;

View file

@ -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>;
};
};

View file

@ -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);

View file

@ -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);

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -89,11 +89,6 @@
#endif
#define CONFIG_SYS_NS16550_CLK ((18432000 * 20) / 25) /* AG101P */
/*
* Ethernet
*/
#define CONFIG_FTMAC100
/*
* SD (MMC) controller
*/

View file

@ -95,11 +95,6 @@
#endif
#define CONFIG_SYS_NS16550_CLK ((18432000 * 20) / 25) /* AG101P */
/*
* Ethernet
*/
#define CONFIG_FTMAC100
/*
* SD (MMC) controller
*/