diff options
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/Makefile | 1 | ||||
-rw-r--r-- | drivers/net/fsl_mc/Makefile | 8 | ||||
-rw-r--r-- | drivers/net/fsl_mc/mc.c | 266 | ||||
-rw-r--r-- | drivers/net/macb.c | 113 | ||||
-rw-r--r-- | drivers/net/phy/phy.c | 4 | ||||
-rw-r--r-- | drivers/net/sh_eth.c | 45 | ||||
-rw-r--r-- | drivers/net/sh_eth.h | 92 |
7 files changed, 460 insertions, 69 deletions
diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 6005f7e..6226cb2 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -64,3 +64,4 @@ obj-$(CONFIG_XILINX_EMACLITE) += xilinx_emaclite.o obj-$(CONFIG_XILINX_LL_TEMAC) += xilinx_ll_temac.o xilinx_ll_temac_mdio.o \ xilinx_ll_temac_fifo.o xilinx_ll_temac_sdma.o obj-$(CONFIG_ZYNQ_GEM) += zynq_gem.o +obj-$(CONFIG_FSL_MC_ENET) += fsl_mc/ diff --git a/drivers/net/fsl_mc/Makefile b/drivers/net/fsl_mc/Makefile new file mode 100644 index 0000000..4834086 --- /dev/null +++ b/drivers/net/fsl_mc/Makefile @@ -0,0 +1,8 @@ +# +# Copyright 2014 Freescale Semiconductor, Inc. +# +# SPDX-License-Identifier: GPL-2.0+ +# + +# Layerscape MC driver +obj-y += mc.o diff --git a/drivers/net/fsl_mc/mc.c b/drivers/net/fsl_mc/mc.c new file mode 100644 index 0000000..df84568 --- /dev/null +++ b/drivers/net/fsl_mc/mc.c @@ -0,0 +1,266 @@ +/* + * Copyright (C) 2014 Freescale Semiconductor + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#include <errno.h> +#include <asm/io.h> +#include <fsl_mc.h> + +DECLARE_GLOBAL_DATA_PTR; +static int mc_boot_status; + +/** + * Copying MC firmware or DPL image to DDR + */ +static int mc_copy_image(const char *title, + u64 image_addr, u32 image_size, u64 mc_ram_addr) +{ + debug("%s copied to address %p\n", title, (void *)mc_ram_addr); + memcpy((void *)mc_ram_addr, (void *)image_addr, image_size); + return 0; +} + +/** + * MC firmware FIT image parser checks if the image is in FIT + * format, verifies integrity of the image and calculates + * raw image address and size values. + * Returns 0 if success and 1 if any of the above mentioned + * task fail. + **/ + +int parse_mc_firmware_fit_image(const void **raw_image_addr, + size_t *raw_image_size) +{ + int format; + void *fit_hdr; + int node_offset; + const void *data; + size_t size; + const char *uname = "firmware"; + + /* Check if the image is in NOR flash*/ +#ifdef CONFIG_SYS_LS_MC_FW_IN_NOR + fit_hdr = (void *)CONFIG_SYS_LS_MC_FW_ADDR; +#else +#error "No CONFIG_SYS_LS_MC_FW_IN_xxx defined" +#endif + + /* Check if Image is in FIT format */ + format = genimg_get_format(fit_hdr); + + if (format != IMAGE_FORMAT_FIT) { + debug("Not a FIT image\n"); + return 1; + } + + if (!fit_check_format(fit_hdr)) { + debug("Bad FIT image format\n"); + return 1; + } + + node_offset = fit_image_get_node(fit_hdr, uname); + + if (node_offset < 0) { + debug("Can not find %s subimage\n", uname); + return 1; + } + + /* Verify MC firmware image */ + if (!(fit_image_verify(fit_hdr, node_offset))) { + debug("Bad MC firmware hash"); + return 1; + } + + /* Get address and size of raw image */ + fit_image_get_data(fit_hdr, node_offset, &data, &size); + + *raw_image_addr = data; + *raw_image_size = size; + + return 0; +} + +int mc_init(bd_t *bis) +{ + int error = 0; + int timeout = 200000; + struct mc_ccsr_registers __iomem *mc_ccsr_regs = MC_CCSR_BASE_ADDR; + u64 mc_ram_addr; + u64 mc_dpl_offset; + u32 reg_gsr; + u32 mc_fw_boot_status; + void *fdt_hdr; + int dpl_size; + const void *raw_image_addr; + size_t raw_image_size = 0; + + BUILD_BUG_ON(CONFIG_SYS_LS_MC_FW_LENGTH % 4 != 0); + + /* + * The MC private DRAM block was already carved at the end of DRAM + * by board_init_f() using CONFIG_SYS_MEM_TOP_HIDE: + */ + if (gd->bd->bi_dram[1].start) { + mc_ram_addr = + gd->bd->bi_dram[1].start + gd->bd->bi_dram[1].size; + } else { + mc_ram_addr = + gd->bd->bi_dram[0].start + gd->bd->bi_dram[0].size; + } + + /* + * Management Complex cores should be held at reset out of POR. + * U-boot should be the first software to touch MC. To be safe, + * we reset all cores again by setting GCR1 to 0. It doesn't do + * anything if they are held at reset. After we setup the firmware + * we kick off MC by deasserting the reset bit for core 0, and + * deasserting the reset bits for Command Portal Managers. + * The stop bits are not touched here. They are used to stop the + * cores when they are active. Setting stop bits doesn't stop the + * cores from fetching instructions when they are released from + * reset. + */ + out_le32(&mc_ccsr_regs->reg_gcr1, 0); + dmb(); + + error = parse_mc_firmware_fit_image(&raw_image_addr, &raw_image_size); + if (error != 0) + goto out; + /* + * Load the MC FW at the beginning of the MC private DRAM block: + */ + mc_copy_image( + "MC Firmware", + (u64)raw_image_addr, + raw_image_size, + mc_ram_addr); + + /* + * Calculate offset in the MC private DRAM block at which the MC DPL + * blob is to be placed: + */ +#ifdef CONFIG_SYS_LS_MC_DRAM_DPL_OFFSET + BUILD_BUG_ON( + (CONFIG_SYS_LS_MC_DRAM_DPL_OFFSET & 0x3) != 0 || + CONFIG_SYS_LS_MC_DRAM_DPL_OFFSET > 0xffffffff); + + mc_dpl_offset = CONFIG_SYS_LS_MC_DRAM_DPL_OFFSET; +#else + mc_dpl_offset = mc_get_dram_block_size() - + roundup(CONFIG_SYS_LS_MC_DPL_LENGTH, 4096); + + if ((mc_dpl_offset & 0x3) != 0 || mc_dpl_offset > 0xffffffff) { + printf("%s: Invalid MC DPL offset: %llu\n", + __func__, mc_dpl_offset); + error = -EINVAL; + goto out; + } +#endif + + /* Check if DPL image is in NOR flash */ +#ifdef CONFIG_SYS_LS_MC_DPL_IN_NOR + fdt_hdr = (void *)CONFIG_SYS_LS_MC_DPL_ADDR; +#else +#error "No CONFIG_SYS_LS_MC_DPL_IN_xxx defined" +#endif + + dpl_size = fdt_totalsize(fdt_hdr); + + /* + * Load the MC DPL blob at the far end of the MC private DRAM block: + */ + mc_copy_image( + "MC DPL blob", + (u64)fdt_hdr, + dpl_size, + mc_ram_addr + mc_dpl_offset); + + debug("mc_ccsr_regs %p\n", mc_ccsr_regs); + + /* + * Tell MC where the MC Firmware image was loaded in DDR: + */ + out_le32(&mc_ccsr_regs->reg_mcfbalr, (u32)mc_ram_addr); + out_le32(&mc_ccsr_regs->reg_mcfbahr, (u32)((u64)mc_ram_addr >> 32)); + out_le32(&mc_ccsr_regs->reg_mcfapr, MCFAPR_BYPASS_ICID_MASK); + + /* + * Tell MC where the DPL blob was loaded in DDR, by indicating + * its offset relative to the beginning of the DDR block + * allocated to the MC firmware. The MC firmware is responsible + * for checking that there is no overlap between the DPL blob + * and the runtime heap and stack of the MC firmware itself. + * + * NOTE: bits [31:2] of this offset need to be stored in bits [29:0] of + * the GSR MC CCSR register. So, this offset is assumed to be 4-byte + * aligned. + * Care must be taken not to write 1s into bits 31 and 30 of the GSR in + * this case as the SoC COP or PIC will be signaled. + */ + out_le32(&mc_ccsr_regs->reg_gsr, (u32)(mc_dpl_offset >> 2)); + + /* + * Deassert reset and release MC core 0 to run + */ + out_le32(&mc_ccsr_regs->reg_gcr1, GCR1_P1_DE_RST | GCR1_M_ALL_DE_RST); + dmb(); + debug("Polling mc_ccsr_regs->reg_gsr ...\n"); + + for (;;) { + reg_gsr = in_le32(&mc_ccsr_regs->reg_gsr); + mc_fw_boot_status = (reg_gsr & GSR_FS_MASK); + if (mc_fw_boot_status & 0x1) + break; + + udelay(1000); /* throttle polling */ + if (timeout-- <= 0) + break; + } + + if (timeout <= 0) { + printf("%s: timeout booting management complex firmware\n", + __func__); + + /* TODO: Get an error status from an MC CCSR register */ + error = -ETIMEDOUT; + goto out; + } + + printf("Management complex booted (boot status: %#x)\n", + mc_fw_boot_status); + + if (mc_fw_boot_status != 0x1) { + /* + * TODO: Identify critical errors from the GSR register's FS + * field and for those errors, set error to -ENODEV or other + * appropriate errno, so that the status property is set to + * failure in the fsl,dprc device tree node. + */ + } + +out: + if (error != 0) + mc_boot_status = -error; + else + mc_boot_status = 0; + + return error; +} + +int get_mc_boot_status(void) +{ + return mc_boot_status; +} + +/** + * Return the actual size of the MC private DRAM block. + * + * NOTE: For now this function always returns the minimum required size, + * However, in the future, the actual size may be obtained from an environment + * variable. + */ +unsigned long mc_get_dram_block_size(void) +{ + return CONFIG_SYS_LS_MC_DRAM_BLOCK_MIN_SIZE; +} diff --git a/drivers/net/macb.c b/drivers/net/macb.c index 781a272..01a94a4 100644 --- a/drivers/net/macb.c +++ b/drivers/net/macb.c @@ -40,17 +40,21 @@ #include "macb.h" -#define CONFIG_SYS_MACB_RX_BUFFER_SIZE 4096 -#define CONFIG_SYS_MACB_RX_RING_SIZE (CONFIG_SYS_MACB_RX_BUFFER_SIZE / 128) -#define CONFIG_SYS_MACB_TX_RING_SIZE 16 -#define CONFIG_SYS_MACB_TX_TIMEOUT 1000 -#define CONFIG_SYS_MACB_AUTONEG_TIMEOUT 5000000 +#define MACB_RX_BUFFER_SIZE 4096 +#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 struct macb_dma_desc { u32 addr; u32 ctrl; }; +#define DMA_DESC_BYTES(n) (n * sizeof(struct macb_dma_desc)) +#define MACB_TX_DMA_DESC_SIZE (DMA_DESC_BYTES(MACB_TX_RING_SIZE)) +#define MACB_RX_DMA_DESC_SIZE (DMA_DESC_BYTES(MACB_RX_RING_SIZE)) + #define RXADDR_USED 0x00000001 #define RXADDR_WRAP 0x00000002 @@ -170,7 +174,7 @@ int macb_miiphy_read(const char *devname, u8 phy_adr, u8 reg, u16 *value) struct eth_device *dev = eth_get_dev_by_name(devname); struct macb_device *macb = to_macb(dev); - if ( macb->phy_addr != phy_adr ) + if (macb->phy_addr != phy_adr) return -1; arch_get_mdio_control(devname); @@ -184,7 +188,7 @@ int macb_miiphy_write(const char *devname, u8 phy_adr, u8 reg, u16 value) struct eth_device *dev = eth_get_dev_by_name(devname); struct macb_device *macb = to_macb(dev); - if ( macb->phy_addr != phy_adr ) + if (macb->phy_addr != phy_adr) return -1; arch_get_mdio_control(devname); @@ -194,6 +198,39 @@ int macb_miiphy_write(const char *devname, u8 phy_adr, u8 reg, u16 value) } #endif +#define RX 1 +#define TX 0 +static inline void macb_invalidate_ring_desc(struct macb_device *macb, bool rx) +{ + if (rx) + invalidate_dcache_range(macb->rx_ring_dma, macb->rx_ring_dma + + MACB_RX_DMA_DESC_SIZE); + else + invalidate_dcache_range(macb->tx_ring_dma, macb->tx_ring_dma + + MACB_TX_DMA_DESC_SIZE); +} + +static inline void macb_flush_ring_desc(struct macb_device *macb, bool rx) +{ + if (rx) + flush_dcache_range(macb->rx_ring_dma, macb->rx_ring_dma + + MACB_RX_DMA_DESC_SIZE); + else + flush_dcache_range(macb->tx_ring_dma, macb->tx_ring_dma + + MACB_TX_DMA_DESC_SIZE); +} + +static inline void macb_flush_rx_buffer(struct macb_device *macb) +{ + flush_dcache_range(macb->rx_buffer_dma, macb->rx_buffer_dma + + MACB_RX_BUFFER_SIZE); +} + +static inline void macb_invalidate_rx_buffer(struct macb_device *macb) +{ + invalidate_dcache_range(macb->rx_buffer_dma, macb->rx_buffer_dma + + MACB_RX_BUFFER_SIZE); +} #if defined(CONFIG_CMD_NET) @@ -208,23 +245,28 @@ static int macb_send(struct eth_device *netdev, void *packet, int length) ctrl = length & TXBUF_FRMLEN_MASK; ctrl |= TXBUF_FRAME_END; - if (tx_head == (CONFIG_SYS_MACB_TX_RING_SIZE - 1)) { + if (tx_head == (MACB_TX_RING_SIZE - 1)) { ctrl |= TXBUF_WRAP; macb->tx_head = 0; - } else + } else { macb->tx_head++; + } macb->tx_ring[tx_head].ctrl = ctrl; macb->tx_ring[tx_head].addr = paddr; barrier(); + macb_flush_ring_desc(macb, TX); + /* Do we need check paddr and length is dcache line aligned? */ + flush_dcache_range(paddr, paddr + length); 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... */ - for (i = 0; i <= CONFIG_SYS_MACB_TX_TIMEOUT; i++) { + for (i = 0; i <= MACB_TX_TIMEOUT; i++) { barrier(); + macb_invalidate_ring_desc(macb, TX); ctrl = macb->tx_ring[tx_head].ctrl; if (ctrl & TXBUF_USED) break; @@ -233,7 +275,7 @@ static int macb_send(struct eth_device *netdev, void *packet, int length) dma_unmap_single(packet, length, paddr); - if (i <= CONFIG_SYS_MACB_TX_TIMEOUT) { + if (i <= MACB_TX_TIMEOUT) { if (ctrl & TXBUF_UNDERRUN) printf("%s: TX underrun\n", netdev->name); if (ctrl & TXBUF_EXHAUSTED) @@ -253,10 +295,12 @@ static void reclaim_rx_buffers(struct macb_device *macb, unsigned int i; i = macb->rx_tail; + + macb_invalidate_ring_desc(macb, RX); while (i > new_tail) { macb->rx_ring[i].addr &= ~RXADDR_USED; i++; - if (i > CONFIG_SYS_MACB_RX_RING_SIZE) + if (i > MACB_RX_RING_SIZE) i = 0; } @@ -266,6 +310,7 @@ static void reclaim_rx_buffers(struct macb_device *macb, } barrier(); + macb_flush_ring_desc(macb, RX); macb->rx_tail = new_tail; } @@ -279,6 +324,8 @@ static int macb_recv(struct eth_device *netdev) u32 status; for (;;) { + macb_invalidate_ring_desc(macb, RX); + if (!(macb->rx_ring[rx_tail].addr & RXADDR_USED)) return -1; @@ -292,10 +339,12 @@ static int macb_recv(struct eth_device *netdev) if (status & RXBUF_FRAME_END) { buffer = macb->rx_buffer + 128 * macb->rx_tail; length = status & RXBUF_FRMLEN_MASK; + + macb_invalidate_rx_buffer(macb); if (wrapped) { unsigned int headlen, taillen; - headlen = 128 * (CONFIG_SYS_MACB_RX_RING_SIZE + headlen = 128 * (MACB_RX_RING_SIZE - macb->rx_tail); taillen = length - headlen; memcpy((void *)NetRxPackets[0], @@ -306,11 +355,11 @@ static int macb_recv(struct eth_device *netdev) } NetReceive(buffer, length); - if (++rx_tail >= CONFIG_SYS_MACB_RX_RING_SIZE) + if (++rx_tail >= MACB_RX_RING_SIZE) rx_tail = 0; reclaim_rx_buffers(macb, rx_tail); } else { - if (++rx_tail >= CONFIG_SYS_MACB_RX_RING_SIZE) { + if (++rx_tail >= MACB_RX_RING_SIZE) { wrapped = 1; rx_tail = 0; } @@ -333,7 +382,7 @@ static void macb_phy_reset(struct macb_device *macb) macb_mdio_write(macb, MII_BMCR, (BMCR_ANENABLE | BMCR_ANRESTART)); - for (i = 0; i < CONFIG_SYS_MACB_AUTONEG_TIMEOUT / 100; i++) { + for (i = 0; i < MACB_AUTONEG_TIMEOUT / 100; i++) { status = macb_mdio_read(macb, MII_BMSR); if (status & BMSR_ANEGCOMPLETE) break; @@ -385,9 +434,8 @@ static int macb_phy_init(struct macb_device *macb) arch_get_mdio_control(netdev->name); #ifdef CONFIG_MACB_SEARCH_PHY /* Auto-detect phy_addr */ - if (!macb_phy_find(macb)) { + if (!macb_phy_find(macb)) return 0; - } #endif /* CONFIG_MACB_SEARCH_PHY */ /* Check if the PHY is up to snuff... */ @@ -414,7 +462,7 @@ static int macb_phy_init(struct macb_device *macb) /* Try to re-negotiate if we don't have link already. */ macb_phy_reset(macb); - for (i = 0; i < CONFIG_SYS_MACB_AUTONEG_TIMEOUT / 100; i++) { + for (i = 0; i < MACB_AUTONEG_TIMEOUT / 100; i++) { status = macb_mdio_read(macb, MII_BMSR); if (status & BMSR_LSTATUS) break; @@ -499,21 +547,28 @@ static int macb_init(struct eth_device *netdev, bd_t *bd) /* initialize DMA descriptors */ paddr = macb->rx_buffer_dma; - for (i = 0; i < CONFIG_SYS_MACB_RX_RING_SIZE; i++) { - if (i == (CONFIG_SYS_MACB_RX_RING_SIZE - 1)) + 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 < CONFIG_SYS_MACB_TX_RING_SIZE; i++) { + macb_flush_ring_desc(macb, RX); + macb_flush_rx_buffer(macb); + + for (i = 0; i < MACB_TX_RING_SIZE; i++) { macb->tx_ring[i].addr = 0; - if (i == (CONFIG_SYS_MACB_TX_RING_SIZE - 1)) + 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_flush_ring_desc(macb, TX); + + macb->rx_tail = 0; + macb->tx_head = 0; + macb->tx_tail = 0; macb_writel(macb, RBQP, macb->rx_ring_dma); macb_writel(macb, TBQP, macb->tx_ring_dma); @@ -654,15 +709,15 @@ int macb_eth_initialize(int id, void *regs, unsigned int phy_addr) netdev = &macb->netdev; - macb->rx_buffer = dma_alloc_coherent(CONFIG_SYS_MACB_RX_BUFFER_SIZE, + macb->rx_buffer = dma_alloc_coherent(MACB_RX_BUFFER_SIZE, &macb->rx_buffer_dma); - macb->rx_ring = dma_alloc_coherent(CONFIG_SYS_MACB_RX_RING_SIZE - * sizeof(struct macb_dma_desc), + macb->rx_ring = dma_alloc_coherent(MACB_RX_DMA_DESC_SIZE, &macb->rx_ring_dma); - macb->tx_ring = dma_alloc_coherent(CONFIG_SYS_MACB_TX_RING_SIZE - * sizeof(struct macb_dma_desc), + macb->tx_ring = dma_alloc_coherent(MACB_TX_DMA_DESC_SIZE, &macb->tx_ring_dma); + /* TODO: we need check the rx/tx_ring_dma is dcache line aligned */ + macb->regs = regs; macb->phy_addr = phy_addr; diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index 230ed97..aac85c4 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -609,10 +609,8 @@ static struct phy_device *create_phy_by_mask(struct mii_dev *bus, while (phy_mask) { int addr = ffs(phy_mask) - 1; int r = get_phy_id(bus, addr, devad, &phy_id); - if (r < 0) - return ERR_PTR(r); /* If the PHY ID is mostly f's, we didn't find anything */ - if ((phy_id & 0x1fffffff) != 0x1fffffff) + if (r == 0 && (phy_id & 0x1fffffff) != 0x1fffffff) return phy_device_create(bus, addr, phy_id, interface); phy_mask &= ~(1 << addr); } diff --git a/drivers/net/sh_eth.c b/drivers/net/sh_eth.c index 5e132f2..81e8ddb 100644 --- a/drivers/net/sh_eth.c +++ b/drivers/net/sh_eth.c @@ -67,7 +67,8 @@ int sh_eth_send(struct eth_device *dev, void *packet, int len) /* packet must be a 4 byte boundary */ if ((int)packet & 3) { - printf(SHETHER_NAME ": %s: packet not 4 byte alligned\n", __func__); + printf(SHETHER_NAME ": %s: packet not 4 byte alligned\n" + , __func__); ret = -EFAULT; goto err; } @@ -148,7 +149,7 @@ int sh_eth_recv(struct eth_device *dev) static int sh_eth_reset(struct sh_eth_dev *eth) { -#if defined(SH_ETH_TYPE_GETHER) +#if defined(SH_ETH_TYPE_GETHER) || defined(SH_ETH_TYPE_RZ) int ret = 0, i; /* Start e-dmac transmitter and receiver */ @@ -156,7 +157,7 @@ static int sh_eth_reset(struct sh_eth_dev *eth) /* Perform a software reset and wait for it to complete */ sh_eth_write(eth, EDMR_SRST, EDMR); - for (i = 0; i < TIMEOUT_CNT ; i++) { + for (i = 0; i < TIMEOUT_CNT; i++) { if (!(sh_eth_read(eth, EDMR) & EDMR_SRST)) break; udelay(1000); @@ -218,7 +219,7 @@ static int sh_eth_tx_desc_init(struct sh_eth_dev *eth) /* 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); -#if defined(SH_ETH_TYPE_GETHER) +#if defined(SH_ETH_TYPE_GETHER) || defined(SH_ETH_TYPE_RZ) 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 */ @@ -288,7 +289,7 @@ static int sh_eth_rx_desc_init(struct sh_eth_dev *eth) /* Point the controller to the rx descriptor list */ sh_eth_write(eth, ADDR_TO_PHY(port_info->rx_desc_base), RDLAR); -#if defined(SH_ETH_TYPE_GETHER) +#if defined(SH_ETH_TYPE_GETHER) || defined(SH_ETH_TYPE_RZ) 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); @@ -384,7 +385,7 @@ static int sh_eth_config(struct sh_eth_dev *eth, bd_t *bd) sh_eth_write(eth, 0, TFTR); sh_eth_write(eth, (FIFO_SIZE_T | FIFO_SIZE_R), FDR); sh_eth_write(eth, RMCR_RST, RMCR); -#if defined(SH_ETH_TYPE_GETHER) +#if defined(SH_ETH_TYPE_GETHER) || defined(SH_ETH_TYPE_RZ) sh_eth_write(eth, 0, RPADIR); #endif sh_eth_write(eth, (FIFO_F_D_RFF | FIFO_F_D_RFD), FCFTR); @@ -403,6 +404,8 @@ static int sh_eth_config(struct sh_eth_dev *eth, bd_t *bd) sh_eth_write(eth, RFLR_RFL_MIN, RFLR); #if defined(SH_ETH_TYPE_GETHER) sh_eth_write(eth, 0, PIPR); +#endif +#if defined(SH_ETH_TYPE_GETHER) || defined(SH_ETH_TYPE_RZ) sh_eth_write(eth, APR_AP, APR); sh_eth_write(eth, MPR_MP, MPR); sh_eth_write(eth, TPAUSER_TPAUSE, TPAUSER); @@ -521,41 +524,41 @@ void sh_eth_halt(struct eth_device *dev) int sh_eth_initialize(bd_t *bd) { - int ret = 0; + int ret = 0; struct sh_eth_dev *eth = NULL; - struct eth_device *dev = NULL; + struct eth_device *dev = NULL; - eth = (struct sh_eth_dev *)malloc(sizeof(struct sh_eth_dev)); + eth = (struct sh_eth_dev *)malloc(sizeof(struct sh_eth_dev)); if (!eth) { printf(SHETHER_NAME ": %s: malloc failed\n", __func__); ret = -ENOMEM; goto err; } - dev = (struct eth_device *)malloc(sizeof(struct eth_device)); + dev = (struct eth_device *)malloc(sizeof(struct eth_device)); if (!dev) { printf(SHETHER_NAME ": %s: malloc failed\n", __func__); ret = -ENOMEM; goto err; } - 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)); eth->port = CONFIG_SH_ETHER_USE_PORT; eth->port_info[eth->port].phy_addr = CONFIG_SH_ETHER_PHY_ADDR; - 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; sprintf(dev->name, SHETHER_NAME); - /* Register Device to EtherNet subsystem */ - eth_register(dev); + /* Register Device to EtherNet subsystem */ + eth_register(dev); bb_miiphy_buses[0].priv = eth; miiphy_register(dev->name, bb_miiphy_read, bb_miiphy_write); diff --git a/drivers/net/sh_eth.h b/drivers/net/sh_eth.h index 331c07c..d0d9aaa 100644 --- a/drivers/net/sh_eth.h +++ b/drivers/net/sh_eth.h @@ -230,6 +230,61 @@ static const u16 sh_eth_offset_gigabit[SH_ETH_MAX_REGISTER_OFFSET] = { [RMII_MII] = 0x0790, }; +#if defined(SH_ETH_TYPE_RZ) +static const u16 sh_eth_offset_rz[SH_ETH_MAX_REGISTER_OFFSET] = { + [EDSR] = 0x0000, + [EDMR] = 0x0400, + [EDTRR] = 0x0408, + [EDRRR] = 0x0410, + [EESR] = 0x0428, + [EESIPR] = 0x0430, + [TDLAR] = 0x0010, + [TDFAR] = 0x0014, + [TDFXR] = 0x0018, + [TDFFR] = 0x001c, + [RDLAR] = 0x0030, + [RDFAR] = 0x0034, + [RDFXR] = 0x0038, + [RDFFR] = 0x003c, + [TRSCER] = 0x0438, + [RMFCR] = 0x0440, + [TFTR] = 0x0448, + [FDR] = 0x0450, + [RMCR] = 0x0458, + [RPADIR] = 0x0460, + [FCFTR] = 0x0468, + [CSMR] = 0x04E4, + + [ECMR] = 0x0500, + [ECSR] = 0x0510, + [ECSIPR] = 0x0518, + [PSR] = 0x0528, + [PIPR] = 0x052c, + [RFLR] = 0x0508, + [APR] = 0x0554, + [MPR] = 0x0558, + [PFTCR] = 0x055c, + [PFRCR] = 0x0560, + [TPAUSER] = 0x0564, + [GECMR] = 0x05b0, + [BCULR] = 0x05b4, + [MAHR] = 0x05c0, + [MALR] = 0x05c8, + [TROCR] = 0x0700, + [CDCR] = 0x0708, + [LCCR] = 0x0710, + [CEFCR] = 0x0740, + [FRECR] = 0x0748, + [TSFRCR] = 0x0750, + [TLFRCR] = 0x0758, + [RFCR] = 0x0760, + [CERCR] = 0x0768, + [CEECR] = 0x0770, + [MAFCR] = 0x0778, + [RMII_MII] = 0x0790, +}; +#endif + static const u16 sh_eth_offset_fast_sh4[SH_ETH_MAX_REGISTER_OFFSET] = { [ECMR] = 0x0100, [RFLR] = 0x0108, @@ -306,13 +361,16 @@ static const u16 sh_eth_offset_fast_sh4[SH_ETH_MAX_REGISTER_OFFSET] = { #elif defined(CONFIG_R8A7790) || defined(CONFIG_R8A7791) #define SH_ETH_TYPE_ETHER #define BASE_IO_ADDR 0xEE700200 +#elif defined(CONFIG_R7S72100) +#define SH_ETH_TYPE_RZ +#define BASE_IO_ADDR 0xE8203000 #endif /* * Register's bits * Copy from Linux driver source code */ -#if defined(SH_ETH_TYPE_GETHER) +#if defined(SH_ETH_TYPE_GETHER) || defined(SH_ETH_TYPE_RZ) /* EDSR */ enum EDSR_BIT { EDSR_ENT = 0x01, EDSR_ENR = 0x02, @@ -323,7 +381,7 @@ enum EDSR_BIT { /* EDMR */ enum DMAC_M_BIT { EDMR_DL1 = 0x20, EDMR_DL0 = 0x10, -#if defined(SH_ETH_TYPE_GETHER) +#if defined(SH_ETH_TYPE_GETHER) || defined(SH_ETH_TYPE_RZ) EDMR_SRST = 0x03, /* Receive/Send reset */ EMDR_DESC_R = 0x30, /* Descriptor reserve size */ EDMR_EL = 0x40, /* Litte endian */ @@ -349,7 +407,7 @@ enum DMAC_M_BIT { /* EDTRR */ enum DMAC_T_BIT { -#if defined(SH_ETH_TYPE_GETHER) +#if defined(SH_ETH_TYPE_GETHER) || defined(SH_ETH_TYPE_RZ) EDTRR_TRNS = 0x03, #else EDTRR_TRNS = 0x01, @@ -394,7 +452,6 @@ enum PHY_STATUS_BIT { PHY_ST_LINK = 0x01, }; /* EESR */ enum EESR_BIT { - #if defined(SH_ETH_TYPE_ETHER) EESR_TWB = 0x40000000, #else @@ -419,12 +476,12 @@ enum EESR_BIT { EESR_CD = 0x00000200, EESR_RTO = 0x00000100, EESR_RMAF = 0x00000080, EESR_CEEF = 0x00000040, EESR_CELF = 0x00000020, EESR_RRF = 0x00000010, - rESR_RTLF = 0x00000008, EESR_RTSF = 0x00000004, + EESR_RTLF = 0x00000008, EESR_RTSF = 0x00000004, EESR_PRE = 0x00000002, EESR_CERF = 0x00000001, }; -#if defined(SH_ETH_TYPE_GETHER) +#if defined(SH_ETH_TYPE_GETHER) || defined(SH_ETH_TYPE_RZ) # define TX_CHECK (EESR_TC1 | EESR_FTC) # define EESR_ERR_CHECK (EESR_TWB | EESR_TABT | EESR_RABT | EESR_RDE \ | EESR_RFRMER | EESR_TFE | EESR_TDE | EESR_ECI) @@ -484,7 +541,8 @@ enum FCFTR_BIT { /* Transfer descriptor bit */ enum TD_STS_BIT { -#if defined(SH_ETH_TYPE_GETHER) || defined(SH_ETH_TYPE_ETHER) +#if defined(SH_ETH_TYPE_GETHER) || defined(SH_ETH_TYPE_ETHER) || \ + defined(SH_ETH_TYPE_RZ) TD_TACT = 0x80000000, #else TD_TACT = 0x7fffffff, @@ -500,9 +558,9 @@ enum TD_STS_BIT { enum RECV_RST_BIT { RMCR_RST = 0x01, }; /* ECMR */ enum FELIC_MODE_BIT { -#if defined(SH_ETH_TYPE_GETHER) - ECMR_TRCCM=0x04000000, ECMR_RCSC= 0x00800000, ECMR_DPAD= 0x00200000, - ECMR_RZPF = 0x00100000, +#if defined(SH_ETH_TYPE_GETHER) || defined(SH_ETH_TYPE_RZ) + ECMR_TRCCM = 0x04000000, ECMR_RCSC = 0x00800000, + ECMR_DPAD = 0x00200000, ECMR_RZPF = 0x00100000, #endif ECMR_ZPF = 0x00080000, ECMR_PFR = 0x00040000, ECMR_RXF = 0x00020000, ECMR_TXF = 0x00010000, ECMR_MCT = 0x00002000, ECMR_PRCEF = 0x00001000, @@ -517,9 +575,9 @@ enum FELIC_MODE_BIT { }; -#if defined(SH_ETH_TYPE_GETHER) -#define ECMR_CHG_DM (ECMR_TRCCM | ECMR_RZPF | ECMR_ZPF | ECMR_PFR | ECMR_RXF | \ - ECMR_TXF | ECMR_MCT) +#if defined(SH_ETH_TYPE_GETHER) || defined(SH_ETH_TYPE_RZ) +#define ECMR_CHG_DM (ECMR_TRCCM | ECMR_RZPF | ECMR_ZPF | ECMR_PFR | \ + ECMR_RXF | ECMR_TXF | ECMR_MCT) #elif defined(SH_ETH_TYPE_ETHER) #define ECMR_CHG_DM (ECMR_ZPF | ECMR_PFR | ECMR_RXF | ECMR_TXF) #else @@ -535,7 +593,7 @@ enum ECSR_STATUS_BIT { ECSR_MPD = 0x02, ECSR_ICD = 0x01, }; -#if defined(SH_ETH_TYPE_GETHER) +#if defined(SH_ETH_TYPE_GETHER) || defined(SH_ETH_TYPE_RZ) # define ECSR_INIT (ECSR_ICD | ECSIPR_MPDIP) #else # define ECSR_INIT (ECSR_BRCRX | ECSR_PSRTO | \ @@ -556,7 +614,7 @@ enum ECSIPR_STATUS_MASK_BIT { ECSIPR_ICDIP = 0x01, }; -#if defined(SH_ETH_TYPE_GETHER) +#if defined(SH_ETH_TYPE_GETHER) || defined(SH_ETH_TYPE_RZ) # define ECSIPR_INIT (ECSIPR_LCHNGIP | ECSIPR_ICDIP | ECSIPR_MPDIP) #else # define ECSIPR_INIT (ECSIPR_BRCRXIP | ECSIPR_PSRTOIP | ECSIPR_LCHNGIP | \ @@ -587,7 +645,7 @@ enum RPADIR_BIT { RPADIR_PADR = 0x0003f, }; -#if defined(SH_ETH_TYPE_GETHER) +#if defined(SH_ETH_TYPE_GETHER) || defined(SH_ETH_TYPE_RZ) # define RPADIR_INIT (0x00) #else # define RPADIR_INIT (RPADIR_PADS1) @@ -605,6 +663,8 @@ static inline unsigned long sh_eth_reg_addr(struct sh_eth_dev *eth, const u16 *reg_offset = sh_eth_offset_gigabit; #elif defined(SH_ETH_TYPE_ETHER) const u16 *reg_offset = sh_eth_offset_fast_sh4; +#elif defined(SH_ETH_TYPE_RZ) + const u16 *reg_offset = sh_eth_offset_rz; #else #error #endif |