Skip to content
Snippets Groups Projects
Commit be71a179 authored by rick's avatar rick
Browse files

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: default avatarrick <rick@andestech.com>
parent 4c780287
No related branches found
No related tags found
No related merge requests found
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
aliases { aliases {
uart0 = &serial0; uart0 = &serial0;
ethernet0 = &mac0;
} ; } ;
chosen { chosen {
...@@ -55,6 +56,12 @@ ...@@ -55,6 +56,12 @@
clock-frequency = <30000000>; clock-frequency = <30000000>;
}; };
mac0: mac@e0100000 {
compatible = "andestech,atmac100";
reg = <0xe0100000 0x1000>;
interrupts = <25 4>;
};
nor@0,0 { nor@0,0 {
compatible = "cfi-flash"; compatible = "cfi-flash";
reg = <0x88000000 0x1000>; reg = <0x88000000 0x1000>;
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
aliases { aliases {
uart0 = &serial0; uart0 = &serial0;
ethernet0 = &mac0;
} ; } ;
chosen { chosen {
...@@ -54,4 +55,9 @@ ...@@ -54,4 +55,9 @@
clock-frequency = <15000000>; clock-frequency = <15000000>;
}; };
mac0: mac@90900000 {
compatible = "andestech,atmac100";
reg = <0x90900000 0x1000>;
interrupts = <25 4>;
};
}; };
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
*/ */
#include <common.h> #include <common.h>
#if defined(CONFIG_FTMAC100) #if defined(CONFIG_FTMAC100) && !defined(CONFIG_DM_ETH)
#include <netdev.h> #include <netdev.h>
#endif #endif
#include <linux/io.h> #include <linux/io.h>
...@@ -56,7 +56,7 @@ int dram_init_banksize(void) ...@@ -56,7 +56,7 @@ int dram_init_banksize(void)
return 0; return 0;
} }
#if defined(CONFIG_FTMAC100) #if defined(CONFIG_FTMAC100) && !defined(CONFIG_DM_ETH)
int board_eth_init(bd_t *bd) int board_eth_init(bd_t *bd)
{ {
return ftmac100_initialize(bd); return ftmac100_initialize(bd);
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
*/ */
#include <common.h> #include <common.h>
#if defined(CONFIG_FTMAC100) #if defined(CONFIG_FTMAC100) && !defined(CONFIG_DM_ETH)
#include <netdev.h> #include <netdev.h>
#endif #endif
#include <linux/io.h> #include <linux/io.h>
...@@ -62,7 +62,7 @@ int dram_init_banksize(void) ...@@ -62,7 +62,7 @@ int dram_init_banksize(void)
return 0; return 0;
} }
#if defined(CONFIG_FTMAC100) #if defined(CONFIG_FTMAC100) && !defined(CONFIG_DM_ETH)
int board_eth_init(bd_t *bd) int board_eth_init(bd_t *bd)
{ {
return ftmac100_initialize(bd); return ftmac100_initialize(bd);
......
...@@ -16,9 +16,12 @@ CONFIG_MMC=y ...@@ -16,9 +16,12 @@ CONFIG_MMC=y
CONFIG_MTD_NOR_FLASH=y CONFIG_MTD_NOR_FLASH=y
CONFIG_BAUDRATE=38400 CONFIG_BAUDRATE=38400
CONFIG_OF_CONTROL=y CONFIG_OF_CONTROL=y
CONFIG_NET_RANDOM_ETHADDR=y
CONFIG_DM=y CONFIG_DM=y
CONFIG_MTD=y CONFIG_MTD=y
CONFIG_CFI_FLASH=y CONFIG_CFI_FLASH=y
CONFIG_DM_ETH=y
CONFIG_FTMAC100=y
CONFIG_DM_SERIAL=y CONFIG_DM_SERIAL=y
CONFIG_SYS_NS16550=y CONFIG_SYS_NS16550=y
CONFIG_TIMER=y CONFIG_TIMER=y
......
...@@ -16,7 +16,10 @@ CONFIG_MMC=y ...@@ -16,7 +16,10 @@ CONFIG_MMC=y
CONFIG_MTD_NOR_FLASH=y CONFIG_MTD_NOR_FLASH=y
CONFIG_BAUDRATE=38400 CONFIG_BAUDRATE=38400
CONFIG_OF_CONTROL=y CONFIG_OF_CONTROL=y
CONFIG_NET_RANDOM_ETHADDR=y
CONFIG_DM=y CONFIG_DM=y
CONFIG_DM_ETH=y
CONFIG_FTMAC100=y
CONFIG_DM_SERIAL=y CONFIG_DM_SERIAL=y
CONFIG_SYS_NS16550=y CONFIG_SYS_NS16550=y
CONFIG_TIMER=y CONFIG_TIMER=y
......
...@@ -225,4 +225,9 @@ config GMAC_ROCKCHIP ...@@ -225,4 +225,9 @@ config GMAC_ROCKCHIP
This driver provides Rockchip SoCs network support based on the This driver provides Rockchip SoCs network support based on the
Synopsys Designware driver. Synopsys Designware driver.
config FTMAC100
bool "Ftmac100 Ethernet Support"
help
This MAC is present in Andestech SoCs.
endif # NETDEVICES endif # NETDEVICES
...@@ -11,24 +11,29 @@ ...@@ -11,24 +11,29 @@
#include <common.h> #include <common.h>
#include <malloc.h> #include <malloc.h>
#include <net.h> #include <net.h>
#include <asm/io.h> #include <linux/io.h>
#include "ftmac100.h" #include "ftmac100.h"
#ifdef CONFIG_DM_ETH
#include <dm.h>
DECLARE_GLOBAL_DATA_PTR;
#endif
#define ETH_ZLEN 60 #define ETH_ZLEN 60
struct ftmac100_data { struct ftmac100_data {
struct ftmac100_txdes txdes[1]; struct ftmac100_txdes txdes[1];
struct ftmac100_rxdes rxdes[PKTBUFSRX]; struct ftmac100_rxdes rxdes[PKTBUFSRX];
int rx_index; int rx_index;
const char *name;
phys_addr_t iobase;
}; };
/* /*
* Reset MAC * 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__); debug ("%s()\n", __func__);
...@@ -41,9 +46,10 @@ static void ftmac100_reset (struct eth_device *dev) ...@@ -41,9 +46,10 @@ static void ftmac100_reset (struct eth_device *dev)
/* /*
* Set MAC address * 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 maddr = mac[0] << 8 | mac[1];
unsigned int laddr = mac[2] << 24 | mac[3] << 16 | mac[4] << 8 | mac[5]; 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) ...@@ -53,29 +59,22 @@ static void ftmac100_set_mac (struct eth_device *dev, const unsigned char *mac)
writel (laddr, &ftmac100->mac_ladr); 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__); debug ("%s()\n", __func__);
writel (0, &ftmac100->maccr); 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 *ftmac100 = (struct ftmac100 *)priv->iobase;
struct ftmac100_data *priv = dev->priv;
struct ftmac100_txdes *txdes = priv->txdes; struct ftmac100_txdes *txdes = priv->txdes;
struct ftmac100_rxdes *rxdes = priv->rxdes; struct ftmac100_rxdes *rxdes = priv->rxdes;
unsigned int maccr; unsigned int maccr;
...@@ -83,11 +82,11 @@ static int ftmac100_init (struct eth_device *dev, bd_t *bd) ...@@ -83,11 +82,11 @@ static int ftmac100_init (struct eth_device *dev, bd_t *bd)
debug ("%s()\n", __func__); debug ("%s()\n", __func__);
ftmac100_reset (dev); ftmac100_reset(priv);
/* set the ethernet address */ /* set the ethernet address */
ftmac100_set_mac(priv, enetaddr);
ftmac100_set_mac_from_env (dev);
/* disable all interrupts */ /* disable all interrupts */
...@@ -136,25 +135,37 @@ static int ftmac100_init (struct eth_device *dev, bd_t *bd) ...@@ -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; struct ftmac100_rxdes *curr_des;
unsigned short rxlen; unsigned short rxlen;
curr_des = &priv->rxdes[priv->rx_index]; curr_des = &priv->rxdes[priv->rx_index];
if (curr_des->rxdes0 & FTMAC100_RXDES0_RXDMA_OWN) if (curr_des->rxdes0 & FTMAC100_RXDES0_RXDMA_OWN)
return -1; return 0;
if (curr_des->rxdes0 & (FTMAC100_RXDES0_RX_ERR | if (curr_des->rxdes0 & (FTMAC100_RXDES0_RX_ERR |
FTMAC100_RXDES0_CRC_ERR | FTMAC100_RXDES0_CRC_ERR |
FTMAC100_RXDES0_FTL | FTMAC100_RXDES0_FTL |
FTMAC100_RXDES0_RUNT | FTMAC100_RXDES0_RUNT |
FTMAC100_RXDES0_RX_ODD_NB)) { FTMAC100_RXDES0_RX_ODD_NB)) {
return -1; return 0;
} }
rxlen = FTMAC100_RXDES0_RFL (curr_des->rxdes0); rxlen = FTMAC100_RXDES0_RFL (curr_des->rxdes0);
...@@ -162,26 +173,15 @@ static int ftmac100_recv (struct eth_device *dev) ...@@ -162,26 +173,15 @@ static int ftmac100_recv (struct eth_device *dev)
debug ("%s(): RX buffer %d, %x received\n", debug ("%s(): RX buffer %d, %x received\n",
__func__, priv->rx_index, rxlen); __func__, priv->rx_index, rxlen);
/* pass the packet up to the protocol layers. */ return rxlen;
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;
} }
/* /*
* Send a data block via Ethernet * 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 *ftmac100 = (struct ftmac100 *)priv->iobase;
struct ftmac100_data *priv = dev->priv;
struct ftmac100_txdes *curr_des = priv->txdes; struct ftmac100_txdes *curr_des = priv->txdes;
ulong start; ulong start;
...@@ -224,25 +224,69 @@ static int ftmac100_send(struct eth_device *dev, void *packet, int length) ...@@ -224,25 +224,69 @@ static int ftmac100_send(struct eth_device *dev, void *packet, int length)
return 0; 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) int ftmac100_initialize (bd_t *bd)
{ {
struct eth_device *dev; struct eth_device *dev;
struct ftmac100_data *priv; struct ftmac100_data *priv;
dev = malloc (sizeof *dev); dev = malloc (sizeof *dev);
if (!dev) { if (!dev) {
printf ("%s(): failed to allocate dev\n", __func__); printf ("%s(): failed to allocate dev\n", __func__);
goto out; goto out;
} }
/* Transmit and receive descriptors should align to 16 bytes */ /* Transmit and receive descriptors should align to 16 bytes */
priv = memalign (16, sizeof (struct ftmac100_data)); priv = memalign (16, sizeof (struct ftmac100_data));
if (!priv) { if (!priv) {
printf ("%s(): failed to allocate priv\n", __func__); printf ("%s(): failed to allocate priv\n", __func__);
goto free_dev; goto free_dev;
} }
memset (dev, 0, sizeof (*dev)); memset (dev, 0, sizeof (*dev));
memset (priv, 0, sizeof (*priv)); memset (priv, 0, sizeof (*priv));
...@@ -253,7 +297,7 @@ int ftmac100_initialize (bd_t *bd) ...@@ -253,7 +297,7 @@ int ftmac100_initialize (bd_t *bd)
dev->send = ftmac100_send; dev->send = ftmac100_send;
dev->recv = ftmac100_recv; dev->recv = ftmac100_recv;
dev->priv = priv; dev->priv = priv;
priv->iobase = dev->iobase;
eth_register (dev); eth_register (dev);
return 1; return 1;
...@@ -263,3 +307,135 @@ free_dev: ...@@ -263,3 +307,135 @@ free_dev:
out: out:
return 0; 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 @@ ...@@ -89,11 +89,6 @@
#endif #endif
#define CONFIG_SYS_NS16550_CLK ((18432000 * 20) / 25) /* AG101P */ #define CONFIG_SYS_NS16550_CLK ((18432000 * 20) / 25) /* AG101P */
/*
* Ethernet
*/
#define CONFIG_FTMAC100
/* /*
* SD (MMC) controller * SD (MMC) controller
*/ */
......
...@@ -95,11 +95,6 @@ ...@@ -95,11 +95,6 @@
#endif #endif
#define CONFIG_SYS_NS16550_CLK ((18432000 * 20) / 25) /* AG101P */ #define CONFIG_SYS_NS16550_CLK ((18432000 * 20) / 25) /* AG101P */
/*
* Ethernet
*/
#define CONFIG_FTMAC100
/* /*
* SD (MMC) controller * SD (MMC) controller
*/ */
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment