* sh_eth.c - Driver for Renesas ethernet controler.
*
* Copyright (C) 2008, 2011 Renesas Solutions Corp.
* sh_eth.c - Driver for Renesas ethernet controler.
*
* Copyright (C) 2008, 2011 Renesas Solutions Corp.
-#ifdef CONFIG_SH_ETHER_CACHE_WRITEBACK
-#define flush_cache_wback(addr, len) \
- flush_dcache_range((u32)addr, (u32)(addr + len - 1))
+#if defined(CONFIG_SH_ETHER_CACHE_WRITEBACK) && !defined(CONFIG_SYS_DCACHE_OFF)
+#define flush_cache_wback(addr, len) \
+ flush_dcache_range((u32)addr, (u32)(addr + len - 1))
+#if defined(CONFIG_SH_ETHER_CACHE_INVALIDATE) && defined(CONFIG_ARM)
+#define invalidate_cache(addr, len) \
+ { \
+ u32 line_size = CONFIG_SH_ETHER_ALIGNE_SIZE; \
+ u32 start, end; \
+ \
+ start = (u32)addr; \
+ end = start + len; \
+ start &= ~(line_size - 1); \
+ end = ((end + line_size - 1) & ~(line_size - 1)); \
+ \
+ invalidate_dcache_range(start, end); \
+ }
+#else
+#define invalidate_cache(...)
+#endif
+
/* Restart the transmitter if disabled */
if (!(sh_eth_read(eth, EDTRR) & EDTRR_TRNS))
sh_eth_write(eth, EDTRR_TRNS, EDTRR);
/* Wait until packet is transmitted */
timeout = TIMEOUT_CNT;
/* Restart the transmitter if disabled */
if (!(sh_eth_read(eth, EDTRR) & EDTRR_TRNS))
sh_eth_write(eth, EDTRR_TRNS, EDTRR);
/* Wait until packet is transmitted */
timeout = TIMEOUT_CNT;
if (!(port_info->rx_desc_cur->rd0 & RD_RACT)) {
/* Check for errors */
if (!(port_info->rx_desc_cur->rd0 & RD_RFE)) {
len = port_info->rx_desc_cur->rd1 & 0xffff;
packet = (uchar *)
ADDR_TO_P2(port_info->rx_desc_cur->rd2);
if (!(port_info->rx_desc_cur->rd0 & RD_RACT)) {
/* Check for errors */
if (!(port_info->rx_desc_cur->rd0 & RD_RFE)) {
len = port_info->rx_desc_cur->rd1 & 0xffff;
packet = (uchar *)
ADDR_TO_P2(port_info->rx_desc_cur->rd2);
- NetReceive(packet, len);
+ invalidate_cache(packet, len);
+ net_process_received_packet(packet, len);
/* Point to the next descriptor */
port_info->rx_desc_cur++;
if (port_info->rx_desc_cur >=
/* Point to the next descriptor */
port_info->rx_desc_cur++;
if (port_info->rx_desc_cur >=
/* Perform a software reset and wait for it to complete */
sh_eth_write(eth, EDMR_SRST, EDMR);
/* Perform a software reset and wait for it to complete */
sh_eth_write(eth, EDMR_SRST, EDMR);
static int sh_eth_tx_desc_init(struct sh_eth_dev *eth)
{
int port = eth->port, i, ret = 0;
static int sh_eth_tx_desc_init(struct sh_eth_dev *eth)
{
int port = eth->port, i, ret = 0;
- port_info->tx_desc_malloc = malloc(NUM_TX_DESC *
- sizeof(struct tx_desc_s) +
- TX_DESC_SIZE - 1);
- if (!port_info->tx_desc_malloc) {
- printf(SHETHER_NAME ": malloc failed\n");
+ port_info->tx_desc_alloc =
+ memalign(sizeof(struct tx_desc_s), alloc_desc_size);
+ if (!port_info->tx_desc_alloc) {
+ printf(SHETHER_NAME ": memalign failed\n");
- tmp_addr = (u32) (((int)port_info->tx_desc_malloc + TX_DESC_SIZE - 1) &
- ~(TX_DESC_SIZE - 1));
- flush_cache_wback(tmp_addr, NUM_TX_DESC * sizeof(struct tx_desc_s));
+ flush_cache_wback((u32)port_info->tx_desc_alloc, alloc_desc_size);
+
/* Point the controller to the tx descriptor list. Must use physical
addresses */
sh_eth_write(eth, ADDR_TO_PHY(port_info->tx_desc_base), TDLAR);
/* Point the controller to the tx descriptor list. Must use physical
addresses */
sh_eth_write(eth, ADDR_TO_PHY(port_info->tx_desc_base), TDLAR);
sh_eth_write(eth, ADDR_TO_PHY(port_info->tx_desc_base), TDFAR);
sh_eth_write(eth, ADDR_TO_PHY(cur_tx_desc), TDFXR);
sh_eth_write(eth, 0x01, TDFFR);/* Last discriptor bit */
sh_eth_write(eth, ADDR_TO_PHY(port_info->tx_desc_base), TDFAR);
sh_eth_write(eth, ADDR_TO_PHY(cur_tx_desc), TDFXR);
sh_eth_write(eth, 0x01, TDFFR);/* Last discriptor bit */
static int sh_eth_rx_desc_init(struct sh_eth_dev *eth)
{
int port = eth->port, i , ret = 0;
static int sh_eth_rx_desc_init(struct sh_eth_dev *eth)
{
int port = eth->port, i , ret = 0;
- port_info->rx_desc_malloc = malloc(NUM_RX_DESC *
- sizeof(struct rx_desc_s) +
- RX_DESC_SIZE - 1);
- if (!port_info->rx_desc_malloc) {
- printf(SHETHER_NAME ": malloc failed\n");
+ port_info->rx_desc_alloc =
+ memalign(sizeof(struct rx_desc_s), alloc_desc_size);
+ if (!port_info->rx_desc_alloc) {
+ printf(SHETHER_NAME ": memalign failed\n");
- tmp_addr = (u32) (((int)port_info->rx_desc_malloc + RX_DESC_SIZE - 1) &
- ~(RX_DESC_SIZE - 1));
- flush_cache_wback(tmp_addr, NUM_RX_DESC * sizeof(struct rx_desc_s));
+ flush_cache_wback(port_info->rx_desc_alloc, alloc_desc_size);
+
- port_info->rx_buf_malloc = malloc(NUM_RX_DESC * MAX_BUF_SIZE + 31);
- if (!port_info->rx_buf_malloc) {
- printf(SHETHER_NAME ": malloc failed\n");
+ port_info->rx_buf_alloc =
+ memalign(RX_BUF_ALIGNE_SIZE, NUM_RX_DESC * MAX_BUF_SIZE);
+ if (!port_info->rx_buf_alloc) {
+ printf(SHETHER_NAME ": alloc failed\n");
/* Initialize all descriptors */
for (cur_rx_desc = port_info->rx_desc_base,
/* Initialize all descriptors */
for (cur_rx_desc = port_info->rx_desc_base,
/* Point the controller to the rx descriptor list */
sh_eth_write(eth, ADDR_TO_PHY(port_info->rx_desc_base), RDLAR);
/* Point the controller to the rx descriptor list */
sh_eth_write(eth, ADDR_TO_PHY(port_info->rx_desc_base), RDLAR);
sh_eth_write(eth, ADDR_TO_PHY(port_info->rx_desc_base), RDFAR);
sh_eth_write(eth, ADDR_TO_PHY(cur_rx_desc), RDFXR);
sh_eth_write(eth, RDFFR_RDLF, RDFFR);
sh_eth_write(eth, ADDR_TO_PHY(port_info->rx_desc_base), RDFAR);
sh_eth_write(eth, ADDR_TO_PHY(cur_rx_desc), RDFXR);
sh_eth_write(eth, RDFFR_RDLF, RDFFR);
- if (port_info->tx_desc_malloc) {
- free(port_info->tx_desc_malloc);
- port_info->tx_desc_malloc = NULL;
+ if (port_info->tx_desc_alloc) {
+ free(port_info->tx_desc_alloc);
+ port_info->tx_desc_alloc = NULL;
- if (port_info->rx_desc_malloc) {
- free(port_info->rx_desc_malloc);
- port_info->rx_desc_malloc = NULL;
+ if (port_info->rx_desc_alloc) {
+ free(port_info->rx_desc_alloc);
+ port_info->rx_desc_alloc = NULL;
- if (port_info->rx_buf_malloc) {
- free(port_info->rx_buf_malloc);
- port_info->rx_buf_malloc = NULL;
+ if (port_info->rx_buf_alloc) {
+ free(port_info->rx_buf_alloc);
+ port_info->rx_buf_alloc = NULL;
- sh_eth_write(eth, (sh_eth_read(eth, EDMR) & ~EMDR_DESC_R) | EDMR_EL,
- EDMR);
+ sh_eth_write(eth, (sh_eth_read(eth, EDMR) & ~EMDR_DESC_R) |
+ (EMDR_DESC | EDMR_EL), EDMR);
+
sh_eth_write(eth, 0, EESIPR);
sh_eth_write(eth, 0, TRSCER);
sh_eth_write(eth, 0, TFTR);
sh_eth_write(eth, (FIFO_SIZE_T | FIFO_SIZE_R), FDR);
sh_eth_write(eth, RMCR_RST, RMCR);
sh_eth_write(eth, 0, EESIPR);
sh_eth_write(eth, 0, TRSCER);
sh_eth_write(eth, 0, TFTR);
sh_eth_write(eth, (FIFO_SIZE_T | FIFO_SIZE_R), FDR);
sh_eth_write(eth, RMCR_RST, RMCR);
sh_eth_write(eth, 0, RPADIR);
#endif
sh_eth_write(eth, (FIFO_F_D_RFF | FIFO_F_D_RFD), FCFTR);
sh_eth_write(eth, 0, RPADIR);
#endif
sh_eth_write(eth, (FIFO_F_D_RFF | FIFO_F_D_RFD), FCFTR);
sh_eth_write(eth, RFLR_RFL_MIN, RFLR);
#if defined(SH_ETH_TYPE_GETHER)
sh_eth_write(eth, 0, PIPR);
sh_eth_write(eth, RFLR_RFL_MIN, RFLR);
#if defined(SH_ETH_TYPE_GETHER)
sh_eth_write(eth, 0, PIPR);
sh_eth_write(eth, APR_AP, APR);
sh_eth_write(eth, MPR_MP, MPR);
sh_eth_write(eth, TPAUSER_TPAUSE, TPAUSER);
sh_eth_write(eth, APR_AP, APR);
sh_eth_write(eth, MPR_MP, MPR);
sh_eth_write(eth, TPAUSER_TPAUSE, TPAUSER);
#if defined(CONFIG_CPU_SH7734) || defined(CONFIG_R8A7740)
sh_eth_write(eth, CONFIG_SH_ETHER_SH7734_MII, RMII_MII);
#if defined(CONFIG_CPU_SH7734) || defined(CONFIG_R8A7740)
sh_eth_write(eth, CONFIG_SH_ETHER_SH7734_MII, RMII_MII);
+#elif defined(CONFIG_R8A7790) || defined(CONFIG_R8A7791) || \
+ defined(CONFIG_R8A7793) || defined(CONFIG_R8A7794)
+ sh_eth_write(eth, sh_eth_read(eth, RMIIMR) | 0x1, RMIIMR);
sh_eth_write(eth, GECMR_100B, GECMR);
#elif defined(CONFIG_CPU_SH7757) || defined(CONFIG_CPU_SH7752)
sh_eth_write(eth, 1, RTRATE);
sh_eth_write(eth, GECMR_100B, GECMR);
#elif defined(CONFIG_CPU_SH7757) || defined(CONFIG_CPU_SH7752)
sh_eth_write(eth, 1, RTRATE);
- memset(dev, 0, sizeof(struct eth_device));
- memset(eth, 0, sizeof(struct sh_eth_dev));
+ memset(dev, 0, sizeof(struct eth_device));
+ memset(eth, 0, sizeof(struct sh_eth_dev));
- dev->priv = (void *)eth;
- dev->iobase = 0;
- dev->init = sh_eth_init;
- dev->halt = sh_eth_halt;
- dev->send = sh_eth_send;
- dev->recv = sh_eth_recv;
- eth->port_info[eth->port].dev = dev;
+ dev->priv = (void *)eth;
+ dev->iobase = 0;
+ dev->init = sh_eth_init;
+ dev->halt = sh_eth_halt;
+ dev->send = sh_eth_send;
+ dev->recv = sh_eth_recv;
+ eth->port_info[eth->port].dev = dev;
bb_miiphy_buses[0].priv = eth;
miiphy_register(dev->name, bb_miiphy_read, bb_miiphy_write);
bb_miiphy_buses[0].priv = eth;
miiphy_register(dev->name, bb_miiphy_read, bb_miiphy_write);