[U-Boot] [PATCH 0/3] qong: support for Dave/DENX QongEVB-LITE

These patches add support for Dave/DENX QongEVB-LITE i.MX31-based board.
Signed-off-by: Ilya Yanok yanok@emcraft.com

Added definitions for i.MX31 processor GPIO registers.
Signed-off-by: Ilya Yanok yanok@emcraft.com --- include/asm-arm/arch-mx31/mx31-regs.h | 10 ++++++++++ 1 files changed, 10 insertions(+), 0 deletions(-)
diff --git a/include/asm-arm/arch-mx31/mx31-regs.h b/include/asm-arm/arch-mx31/mx31-regs.h index b04a718..939bdd3 100644 --- a/include/asm-arm/arch-mx31/mx31-regs.h +++ b/include/asm-arm/arch-mx31/mx31-regs.h @@ -87,6 +87,16 @@ #define WDOG_BASE 0x53FDC000
/* + * GPIO + */ +#define GPIO1_BASE (0x53FCC000) +#define GPIO2_BASE (0x53FD0000) +#define GPIO3_BASE (0x53FA4000) +#define GPIO_DR (0x00000000) +#define GPIO_GDIR (0x00000004) +#define GPIO_PSR (0x00000008) + +/* * Signal Multiplexing (IOMUX) */

Dear Ilya Yanok,
In message 1233589490-14293-2-git-send-email-yanok@emcraft.com you wrote:
Added definitions for i.MX31 processor GPIO registers.
Signed-off-by: Ilya Yanok yanok@emcraft.com
include/asm-arm/arch-mx31/mx31-regs.h | 10 ++++++++++ 1 files changed, 10 insertions(+), 0 deletions(-)
diff --git a/include/asm-arm/arch-mx31/mx31-regs.h b/include/asm-arm/arch-mx31/mx31-regs.h index b04a718..939bdd3 100644 --- a/include/asm-arm/arch-mx31/mx31-regs.h +++ b/include/asm-arm/arch-mx31/mx31-regs.h @@ -87,6 +87,16 @@ #define WDOG_BASE 0x53FDC000
/*
- GPIO
- */
+#define GPIO1_BASE (0x53FCC000) +#define GPIO2_BASE (0x53FD0000) +#define GPIO3_BASE (0x53FA4000) +#define GPIO_DR (0x00000000) +#define GPIO_GDIR (0x00000004) +#define GPIO_PSR (0x00000008)
No need for parens around simple constants.
But please add a few comments what all these mean/
Best regards,
Wolfgang Denk

Driver for Dave DNET ethernet controller (used on Dave/DENX QongEVB-LITE board).
Signed-off-by: Ilya Yanok yanok@emcraft.com --- drivers/net/Makefile | 1 + drivers/net/dnet.c | 405 ++++++++++++++++++++++++++++++++++++++++++++++++++ drivers/net/dnet.h | 169 +++++++++++++++++++++ 3 files changed, 575 insertions(+), 0 deletions(-) create mode 100644 drivers/net/dnet.c create mode 100644 drivers/net/dnet.h
diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 631336a..a1084a6 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -69,6 +69,7 @@ COBJS-$(CONFIG_VSC7385_ENET) += vsc7385.o COBJS-$(CONFIG_XILINX_EMAC) += xilinx_emac.o COBJS-$(CONFIG_XILINX_EMACLITE) += xilinx_emaclite.o COBJS-$(CONFIG_SH_ETHER) += sh_eth.o +COBJS-$(CONFIG_DRIVER_DNET) += dnet.o
COBJS := $(COBJS-y) SRCS := $(COBJS:.o=.c) diff --git a/drivers/net/dnet.c b/drivers/net/dnet.c new file mode 100644 index 0000000..4513707 --- /dev/null +++ b/drivers/net/dnet.c @@ -0,0 +1,405 @@ +/* + * Dave Ethernet Controller driver + * + * Copyright (C) 2008 Dave S.r.l. <www.dave.eu> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <common.h> + +#if defined(CONFIG_DRIVER_DNET) \ + && (defined(CONFIG_CMD_NET) || defined(CONFIG_CMD_MII)) + +#define CFG_DNET_AUTONEG_TIMEOUT 5000000 + +#include <net.h> +#include <malloc.h> +#include <linux/mii.h> + +#include <miiphy.h> +#include <asm/io.h> + +#include "dnet.h" + +struct dnet_device { + void *regs; + + const struct device *dev; + struct eth_device netdev; + unsigned short phy_addr; +}; + +#define to_dnet(_nd) container_of(_nd, struct dnet_device, netdev) + +/* function for reading internal MAC register */ +u16 dnet_readw_mac(struct dnet_device *dnet, u16 reg) +{ + u16 data_read; + + /* issue a read */ + dnet_writel(dnet, reg, MACREG_ADDR); + + /* since a read/write op to the MAC is very slow, + * we must wait before reading the data */ + udelay(1); + + /* read data read from the MAC register */ + data_read = dnet_readl(dnet, MACREG_DATA); + + /* all done */ + return(data_read); +} + +/* function for writing internal MAC register */ +void dnet_writew_mac(struct dnet_device *dnet, u16 reg, u16 val) +{ + /* load data to write */ + dnet_writel(dnet, val, MACREG_DATA); + + /* issue a write */ + dnet_writel(dnet, reg | DNET_INTERNAL_WRITE, MACREG_ADDR); + + /* since a read/write op to the MAC is very slow, + * we must wait before exiting */ + udelay(1); + + /* all done */ + return; +} + +static void dnet_mdio_write(struct dnet_device *dnet, u8 reg, u16 value) +{ + u16 tmp; + + debug(DRIVERNAME "dnet_mdio_write %02x:%02x <- %04x\n", + dnet->phy_addr, reg, value); + + while (!(dnet_readw_mac(dnet, DNET_INTERNAL_GMII_MNG_CTL_REG) & + DNET_INTERNAL_GMII_MNG_CMD_FIN)); + + /* prepare for a write operation */ + tmp = (1 << 13); + + /* only 5 bits allowed for register offset */ + reg &= 0x1f; + + /* prepare reg_value for a write */ + tmp |= (dnet->phy_addr << 8); + tmp |= reg; + + /* write data to write first */ + dnet_writew_mac(dnet, DNET_INTERNAL_GMII_MNG_DAT_REG, value); + + /* write control word */ + dnet_writew_mac(dnet, DNET_INTERNAL_GMII_MNG_CTL_REG, tmp); + + while (!(dnet_readw_mac(dnet, DNET_INTERNAL_GMII_MNG_CTL_REG) & + DNET_INTERNAL_GMII_MNG_CMD_FIN)); +} + +static u16 dnet_mdio_read(struct dnet_device *dnet, u8 reg) +{ + u16 value; + + while (!(dnet_readw_mac(dnet, DNET_INTERNAL_GMII_MNG_CTL_REG) & + DNET_INTERNAL_GMII_MNG_CMD_FIN)); + + /* only 5 bits allowed for register offset*/ + reg &= 0x1f; + + /* prepare reg_value for a read */ + value = (dnet->phy_addr << 8); + value |= reg; + + /* write control word */ + dnet_writew_mac(dnet, DNET_INTERNAL_GMII_MNG_CTL_REG, value); + + /* wait for end of transfer */ + while (!(dnet_readw_mac(dnet, DNET_INTERNAL_GMII_MNG_CTL_REG) & + DNET_INTERNAL_GMII_MNG_CMD_FIN)); + + value = dnet_readw_mac(dnet, DNET_INTERNAL_GMII_MNG_DAT_REG); + + debug(DRIVERNAME "dnet_mdio_read %02x:%02x <- %04x\n", + dnet->phy_addr, reg, value); + + return value; +} + +#if defined(CONFIG_CMD_NET) + +static int dnet_send(struct eth_device *netdev, volatile void *packet, + int length) +{ + struct dnet_device *dnet = to_dnet(netdev); + int i, len, wrsz; + unsigned int * bufp; + unsigned int tx_cmd; + + debug(DRIVERNAME "[%s] Sending %u bytes\n", __FUNCTION__, length); + + /* frame size (words) */ + len = (length + 3) >> 2; + + bufp = (unsigned int *) (((u32)packet) & 0xFFFFFFFC); + wrsz = (u32)length + 3; + wrsz += ((u32)packet) & 0x3; + wrsz >>= 2; + tx_cmd = ((((unsigned int)(packet)) & 0x03) << 16) | (u32)length; + + /* check if there is enough room for the current frame */ + if (wrsz < (DNET_FIFO_SIZE - dnet_readl(dnet, TX_FIFO_WCNT))) { + for (i = 0; i < wrsz; i++) { + dnet_writel(dnet, *bufp++, TX_DATA_FIFO); + } + /* + * inform MAC that a packet's written and ready + * to be shipped out + */ + dnet_writel(dnet, tx_cmd, TX_LEN_FIFO); + } else { + printf(DRIVERNAME "No free space (actual %d, required %d " + "(words))\n", DNET_FIFO_SIZE - + dnet_readl(dnet, TX_FIFO_WCNT), wrsz); + } + + /* No one cares anyway */ + return 0; +} + + +static int dnet_recv(struct eth_device *netdev) +{ + struct dnet_device *dnet = to_dnet(netdev); + unsigned int * data_ptr; + int pkt_len, poll, i; + u32 cmd_word; + + debug("Waiting for pkt (polling)\n"); + poll = 50; + while ((dnet_readl(dnet, RX_FIFO_WCNT) >> 16) == 0) { + udelay(10); // wait 10 usec + --poll; + if (poll == 0) + return 0; // no pkt available + } + + cmd_word = dnet_readl(dnet, RX_LEN_FIFO); + pkt_len = cmd_word & 0xFFFF; + + debug("Got pkt with size %d bytes\n", pkt_len); + + if (cmd_word & 0xDF180000) + printf("%s packet receive error %x\n", __FUNCTION__, cmd_word); + + data_ptr = (unsigned int *) NetRxPackets[0]; + + for (i = 0; i < (pkt_len + 3) >> 2; i++) + *data_ptr++ = dnet_readl(dnet, RX_DATA_FIFO); + + NetReceive(NetRxPackets[0], pkt_len + 5); /* ok + 5 ?? */ + + return 0; +} + +static void dnet_set_hwaddr(struct eth_device *netdev) +{ + struct dnet_device *dnet = to_dnet(netdev); + u16 tmp; + + tmp = cpu_to_be16(*((u16 *)netdev->enetaddr)); + dnet_writew_mac(dnet, DNET_INTERNAL_MAC_ADDR_0_REG, tmp); + tmp = cpu_to_be16(*((u16 *)(netdev->enetaddr + 2))); + dnet_writew_mac(dnet, DNET_INTERNAL_MAC_ADDR_1_REG, tmp); + tmp = cpu_to_be16(*((u16 *)(netdev->enetaddr + 4))); + dnet_writew_mac(dnet, DNET_INTERNAL_MAC_ADDR_2_REG, tmp); +} + +static void dnet_phy_reset(struct dnet_device *dnet) +{ + struct eth_device *netdev = &dnet->netdev; + int i; + u16 status, adv; + + adv = ADVERTISE_CSMA | ADVERTISE_ALL; + dnet_mdio_write(dnet, MII_ADVERTISE, adv); + printf("%s: Starting autonegotiation...\n", netdev->name); + dnet_mdio_write(dnet, MII_BMCR, (BMCR_ANENABLE + | BMCR_ANRESTART)); + + for (i = 0; i < CFG_DNET_AUTONEG_TIMEOUT / 100; i++) { + status = dnet_mdio_read(dnet, MII_BMSR); + if (status & BMSR_ANEGCOMPLETE) + break; + udelay(100); + } + + if (status & BMSR_ANEGCOMPLETE) + printf("%s: Autonegotiation complete\n", netdev->name); + else + printf("%s: Autonegotiation timed out (status=0x%04x)\n", + netdev->name, status); +} + +static int dnet_phy_init(struct dnet_device *dnet) +{ + struct eth_device *netdev = &dnet->netdev; + u16 phy_id, status, adv, lpa; + int media, speed, duplex; + int i; + u32 ctl_reg; + + /* Find a PHY */ + for (i = 0; i < 32; i++) { + dnet->phy_addr = i; + phy_id = dnet_mdio_read(dnet, MII_PHYSID1); + if (phy_id != 0xffff) { + /* ok we found it */ + printf("Found PHY at address %d PHYID (%04x:%04x)\n", + i, phy_id, + dnet_mdio_read(dnet, MII_PHYSID2)); + break; + } + } + + /* Check if the PHY is up to snuff... */ + phy_id = dnet_mdio_read(dnet, MII_PHYSID1); + if (phy_id == 0xffff) { + printf("%s: No PHY present\n", netdev->name); + return 0; + } + + status = dnet_mdio_read(dnet, MII_BMSR); + if (!(status & BMSR_LSTATUS)) { + /* Try to re-negotiate if we don't have link already. */ + dnet_phy_reset(dnet); + + for (i = 0; i < CFG_DNET_AUTONEG_TIMEOUT / 100; i++) { + status = dnet_mdio_read(dnet, MII_BMSR); + if (status & BMSR_LSTATUS) + break; + udelay(100); + } + } + + if (!(status & BMSR_LSTATUS)) { + printf("%s: link down (status: 0x%04x)\n", + netdev->name, status); + return 0; + } else { + adv = dnet_mdio_read(dnet, MII_ADVERTISE); + lpa = dnet_mdio_read(dnet, MII_LPA); + media = mii_nway_result(lpa & adv); + speed = (media & (ADVERTISE_100FULL | ADVERTISE_100HALF) + ? 1 : 0); + duplex = (media & ADVERTISE_FULL) ? 1 : 0; + /* 1000BaseT ethernet is not supported */ + printf("%s: link up, %sMbps %s-duplex (lpa: 0x%04x)\n", + netdev->name, + speed ? "100" : "10", + duplex ? "full" : "half", + lpa); + + ctl_reg = dnet_readw_mac(dnet, DNET_INTERNAL_RXTX_CONTROL_REG); + + if (duplex) + ctl_reg &= ~(DNET_INTERNAL_RXTX_CONTROL_ENABLEHALFDUP); + else + ctl_reg |= DNET_INTERNAL_RXTX_CONTROL_ENABLEHALFDUP; + + dnet_writew_mac(dnet, DNET_INTERNAL_RXTX_CONTROL_REG, ctl_reg); + + return 1; + } +} + +static int dnet_init(struct eth_device *netdev, bd_t *bd) +{ + struct dnet_device *dnet = to_dnet(netdev); + u32 config; + + /* + * dnet_halt should have been called at some point before now, + * so we'll assume the controller is idle. + */ + + /* set hardware address */ + dnet_set_hwaddr(netdev); + + if (!dnet_phy_init(dnet)) + return 0; + + /* flush rx/tx fifos */ + dnet_writel(dnet, DNET_SYS_CTL_RXFIFOFLUSH | + DNET_SYS_CTL_TXFIFOFLUSH, SYS_CTL); + udelay(1000); + dnet_writel(dnet, 0, SYS_CTL); + + config = dnet_readw_mac(dnet, DNET_INTERNAL_RXTX_CONTROL_REG); + + config |= DNET_INTERNAL_RXTX_CONTROL_RXPAUSE | + DNET_INTERNAL_RXTX_CONTROL_RXBROADCAST | + DNET_INTERNAL_RXTX_CONTROL_DROPCONTROL | + DNET_INTERNAL_RXTX_CONTROL_DISCFXFCS; + + dnet_writew_mac(dnet, DNET_INTERNAL_RXTX_CONTROL_REG, config); + + /* Enable TX and RX */ + dnet_writew_mac(dnet, DNET_INTERNAL_MODE_REG, + DNET_INTERNAL_MODE_RXEN | DNET_INTERNAL_MODE_TXEN); + + return 1; +} + +static void dnet_halt(struct eth_device *netdev) +{ + struct dnet_device *dnet = to_dnet(netdev); + + /* Disable TX and RX */ + dnet_writew_mac(dnet, DNET_INTERNAL_MODE_REG, 0); +} + +int dnet_eth_initialize(int id, void *regs, unsigned int phy_addr) +{ + struct dnet_device *dnet; + struct eth_device *netdev; + unsigned int dev_capa; + + dnet = malloc(sizeof(struct dnet_device)); + if (!dnet) { + printf("Error: Failed to allocate memory for DNET%d\n", id); + return -1; + } + memset(dnet, 0, sizeof(struct dnet_device)); + + netdev = &dnet->netdev; + + dnet->regs = regs; + dnet->phy_addr = phy_addr; + + sprintf(netdev->name, "dnet%d", id); + netdev->init = dnet_init; + netdev->halt = dnet_halt; + netdev->send = dnet_send; + netdev->recv = dnet_recv; + + dev_capa = dnet_readl(dnet, VERCAPS) & 0xFFFF; + debug("%s: has %smdio, %sirq, %sgigabit, %sdma \n", netdev->name, + (dev_capa & DNET_HAS_MDIO) ? "" : "no ", + (dev_capa & DNET_HAS_IRQ) ? "" : "no ", + (dev_capa & DNET_HAS_GIGABIT) ? "" : "no ", + (dev_capa & DNET_HAS_DMA) ? "" : "no "); + + eth_register(netdev); + + return 0; +} + + +#endif /* CONFIG_CMD_NET */ + + +#endif /* CONFIG_DRIVER_DNET */ diff --git a/drivers/net/dnet.h b/drivers/net/dnet.h new file mode 100644 index 0000000..5bd4986 --- /dev/null +++ b/drivers/net/dnet.h @@ -0,0 +1,169 @@ +/* + * Dave Ethernet Controller driver + * + * Copyright (C) 2008 Dave S.r.l. <www.dave.eu> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __DRIVERS_DNET_H__ +#define __DRIVERS_DNET_H__ + +#define DRIVERNAME "dnet" + +/* Register access macros */ +#define dnet_writel(port, value, reg) \ + writel((value), (port)->regs + DNET_##reg) +#define dnet_readl(port, reg) readl((port)->regs + DNET_##reg) + +/* ALL DNET FIFO REGISTERS */ +#define DNET_RX_LEN_FIFO (0x000) /* RX_LEN_FIFO */ +#define DNET_RX_DATA_FIFO (0x004) /* RX_DATA_FIFO */ +#define DNET_TX_LEN_FIFO (0x008) /* TX_LEN_FIFO */ +#define DNET_TX_DATA_FIFO (0x00C) /* TX_DATA_FIFO */ + +/* ALL DNET CONTROL/STATUS REGISTERS OFFSETS */ +#define DNET_VERCAPS (0x100) /* VERCAPS */ +#define DNET_INTR_SRC (0x104) /* INTR_SRC */ +#define DNET_INTR_ENB (0x108) /* INTR_ENB */ +#define DNET_RX_STATUS (0x10C) /* RX_STATUS */ +#define DNET_TX_STATUS (0x110) /* TX_STATUS */ +#define DNET_RX_FRAMES_CNT (0x114) /* RX_FRAMES_CNT */ +#define DNET_TX_FRAMES_CNT (0x118) /* TX_FRAMES_CNT */ +#define DNET_RX_FIFO_TH (0x11C) /* RX_FIFO_TH */ +#define DNET_TX_FIFO_TH (0x120) /* TX_FIFO_TH */ +#define DNET_SYS_CTL (0x124) /* SYS_CTL */ +#define DNET_PAUSE_TMR (0x128) /* PAUSE_TMR */ +#define DNET_RX_FIFO_WCNT (0x12C) /* RX_FIFO_WCNT */ +#define DNET_TX_FIFO_WCNT (0x130) /* TX_FIFO_WCNT */ + +/* ALL DNET MAC REGISTERS */ +#define DNET_MACREG_DATA (0x200) /* Mac-Reg Data */ +#define DNET_MACREG_ADDR (0x204) /* Mac-Reg Addr */ + +/* ALL DNET RX STATISTICS COUNTERS */ +#define DNET_RX_PKT_IGNR_CNT (0x300) +#define DNET_RX_LEN_CHK_ERR_CNT (0x304) +#define DNET_RX_LNG_FRM_CNT (0x308) +#define DNET_RX_SHRT_FRM_CNT (0x30C) +#define DNET_RX_IPG_VIOL_CNT (0x310) +#define DNET_RX_CRC_ERR_CNT (0x314) +#define DNET_RX_OK_PKT_CNT (0x318) +#define DNET_RX_CTL_FRM_CNT (0x31C) +#define DNET_RX_PAUSE_FRM_CNT (0x320) +#define DNET_RX_MULTICAST_CNT (0x324) +#define DNET_RX_BROADCAST_CNT (0x328) +#define DNET_RX_VLAN_TAG_CNT (0x32C) +#define DNET_RX_PRE_SHRINK_CNT (0x330) +#define DNET_RX_DRIB_NIB_CNT (0x334) +#define DNET_RX_UNSUP_OPCD_CNT (0x338) +#define DNET_RX_BYTE_CNT (0x33C) + +/* DNET TX STATISTICS COUNTERS */ +#define DNET_TX_UNICAST_CNT (0x400) +#define DNET_TX_PAUSE_FRM_CNT (0x404) +#define DNET_TX_MULTICAST_CNT (0x408) +#define DNET_TX_BRDCAST_CNT (0x40C) +#define DNET_TX_VLAN_TAG_CNT (0x410) +#define DNET_TX_BAD_FCS_CNT (0x414) +#define DNET_TX_JUMBO_CNT (0x418) +#define DNET_TX_BYTE_CNT (0x41C) + +/* SOME INTERNAL MAC-CORE REGISTER */ +#define DNET_INTERNAL_MODE_REG (0x0) +#define DNET_INTERNAL_RXTX_CONTROL_REG (0x2) +#define DNET_INTERNAL_MAX_PKT_SIZE_REG (0x4) +#define DNET_INTERNAL_IGP_REG (0x8) +#define DNET_INTERNAL_MAC_ADDR_0_REG (0xa) +#define DNET_INTERNAL_MAC_ADDR_1_REG (0xc) +#define DNET_INTERNAL_MAC_ADDR_2_REG (0xe) +#define DNET_INTERNAL_TX_RX_STS_REG (0x12) +#define DNET_INTERNAL_GMII_MNG_CTL_REG (0x14) +#define DNET_INTERNAL_GMII_MNG_DAT_REG (0x16) + +#define DNET_INTERNAL_GMII_MNG_CMD_FIN (1 << 14) + +#define DNET_INTERNAL_WRITE (1 << 31) + +/* MAC-CORE REGISTER FIELDS */ + +/* MAC-CORE MODE REGISTER FIELDS */ +#define DNET_INTERNAL_MODE_GBITEN (1 << 0) +#define DNET_INTERNAL_MODE_FCEN (1 << 1) +#define DNET_INTERNAL_MODE_RXEN (1 << 2) +#define DNET_INTERNAL_MODE_TXEN (1 << 3) + +/* MAC-CORE RXTX CONTROL REGISTER FIELDS */ +#define DNET_INTERNAL_RXTX_CONTROL_RXSHORTFRAME (1 << 8) +#define DNET_INTERNAL_RXTX_CONTROL_RXBROADCAST (1 << 7) +#define DNET_INTERNAL_RXTX_CONTROL_RXMULTICAST (1 << 4) +#define DNET_INTERNAL_RXTX_CONTROL_RXPAUSE (1 << 3) +#define DNET_INTERNAL_RXTX_CONTROL_DISTXFCS (1 << 2) +#define DNET_INTERNAL_RXTX_CONTROL_DISCFXFCS (1 << 1) +#define DNET_INTERNAL_RXTX_CONTROL_ENPROMISC (1 << 0) +#define DNET_INTERNAL_RXTX_CONTROL_DROPCONTROL (1 << 6) +#define DNET_INTERNAL_RXTX_CONTROL_ENABLEHALFDUP (1 << 5) + +/* SYSTEM CONTROL REGISTER FIELDS */ +#define DNET_SYS_CTL_IGNORENEXTPKT (1 << 0) +#define DNET_SYS_CTL_SENDPAUSE (1 << 2) +#define DNET_SYS_CTL_RXFIFOFLUSH (1 << 3) +#define DNET_SYS_CTL_TXFIFOFLUSH (1 << 4) + +/* TX STATUS REGISTER FIELDS */ +#define DNET_TX_STATUS_FIFO_ALMOST_EMPTY (1 << 2) +#define DNET_TX_STATUS_FIFO_ALMOST_FULL (1 << 1) + +/* INTERRUPT SOURCE REGISTER FIELDS */ +#define DNET_INTR_SRC_TX_PKTSENT (1 << 0) +#define DNET_INTR_SRC_TX_FIFOAF (1 << 1) +#define DNET_INTR_SRC_TX_FIFOAE (1 << 2) +#define DNET_INTR_SRC_TX_DISCFRM (1 << 3) +#define DNET_INTR_SRC_TX_FIFOFULL (1 << 4) +#define DNET_INTR_SRC_RX_CMDFIFOAF (1 << 8) +#define DNET_INTR_SRC_RX_CMDFIFOFF (1 << 9) +#define DNET_INTR_SRC_RX_DATAFIFOFF (1 << 10) +#define DNET_INTR_SRC_TX_SUMMARY (1 << 16) +#define DNET_INTR_SRC_RX_SUMMARY (1 << 17) +#define DNET_INTR_SRC_PHY (1 << 19) + +/* INTERRUPT ENABLE REGISTER FIELDS */ +#define DNET_INTR_ENB_TX_PKTSENT (1 << 0) +#define DNET_INTR_ENB_TX_FIFOAF (1 << 1) +#define DNET_INTR_ENB_TX_FIFOAE (1 << 2) +#define DNET_INTR_ENB_TX_DISCFRM (1 << 3) +#define DNET_INTR_ENB_TX_FIFOFULL (1 << 4) +#define DNET_INTR_ENB_RX_PKTRDY (1 << 8) +#define DNET_INTR_ENB_RX_FIFOAF (1 << 9) +#define DNET_INTR_ENB_RX_FIFOERR (1 << 10) +#define DNET_INTR_ENB_RX_ERROR (1 << 11) +#define DNET_INTR_ENB_RX_FIFOFULL (1 << 12) +#define DNET_INTR_ENB_RX_FIFOAE (1 << 13) +#define DNET_INTR_ENB_TX_SUMMARY (1 << 16) +#define DNET_INTR_ENB_RX_SUMMARY (1 << 17) +#define DNET_INTR_ENB_GLOBAL_ENABLE (1 << 18) + +/* + * Capabilities. Used by the driver to know the capabilities that + * the ethernet controller inside the FPGA have. + */ + +#define DNET_HAS_MDIO (1 << 0) +#define DNET_HAS_IRQ (1 << 1) +#define DNET_HAS_GIGABIT (1 << 2) +#define DNET_HAS_DMA (1 << 3) + +#define DNET_HAS_MII (1 << 4) // or GMII +#define DNET_HAS_RMII (1 << 5) // or RGMII + +#define DNET_CAPS_MASK 0xFFFF + +#define DNET_FIFO_SIZE 2048 /* 2K x 32 bit */ +#define DNET_FIFO_TX_DATA_AF_TH (DNET_FIFO_SIZE - 384) /* 384 = 1536 / 4 */ +#define DNET_FIFO_TX_DATA_AE_TH (384) + +#define DNET_FIFO_RX_CMD_AF_TH (1 << 16) /* just one frame inside the FIFO */ + +#endif

Hi Ilya,
Ilya Yanok wrote:
Driver for Dave DNET ethernet controller (used on Dave/DENX QongEVB-LITE board).
Signed-off-by: Ilya Yanok yanok@emcraft.com
drivers/net/Makefile | 1 + drivers/net/dnet.c | 405 ++++++++++++++++++++++++++++++++++++++++++++++++++ drivers/net/dnet.h | 169 +++++++++++++++++++++ 3 files changed, 575 insertions(+), 0 deletions(-) create mode 100644 drivers/net/dnet.c create mode 100644 drivers/net/dnet.h
You need to add your initialize() function to include/netdev.h
diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 631336a..a1084a6 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -69,6 +69,7 @@ COBJS-$(CONFIG_VSC7385_ENET) += vsc7385.o COBJS-$(CONFIG_XILINX_EMAC) += xilinx_emac.o COBJS-$(CONFIG_XILINX_EMACLITE) += xilinx_emaclite.o COBJS-$(CONFIG_SH_ETHER) += sh_eth.o +COBJS-$(CONFIG_DRIVER_DNET) += dnet.o
In alphabetical order, please. (ignore the other transgressions)
COBJS := $(COBJS-y) SRCS := $(COBJS:.o=.c) diff --git a/drivers/net/dnet.c b/drivers/net/dnet.c new file mode 100644 index 0000000..4513707 --- /dev/null +++ b/drivers/net/dnet.c @@ -0,0 +1,405 @@ +/*
- Dave Ethernet Controller driver
- Copyright (C) 2008 Dave S.r.l. <www.dave.eu>
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License version 2 as
- published by the Free Software Foundation.
- */
+#include <common.h>
+#if defined(CONFIG_DRIVER_DNET) \
- && (defined(CONFIG_CMD_NET) || defined(CONFIG_CMD_MII))
Not needed, this is taken care of in the Makefile
+#define CFG_DNET_AUTONEG_TIMEOUT 5000000
+#include <net.h> +#include <malloc.h> +#include <linux/mii.h>
+#include <miiphy.h> +#include <asm/io.h>
+#include "dnet.h"
+struct dnet_device {
- void *regs;
Surely you know enough about this to define its type
- const struct device *dev;
- struct eth_device netdev;
- unsigned short phy_addr;
+};
+#define to_dnet(_nd) container_of(_nd, struct dnet_device, netdev)
+/* function for reading internal MAC register */ +u16 dnet_readw_mac(struct dnet_device *dnet, u16 reg) +{
- u16 data_read;
- /* issue a read */
- dnet_writel(dnet, reg, MACREG_ADDR);
- /* since a read/write op to the MAC is very slow,
* we must wait before reading the data */
- udelay(1);
- /* read data read from the MAC register */
- data_read = dnet_readl(dnet, MACREG_DATA);
- /* all done */
- return(data_read);
+}
+/* function for writing internal MAC register */ +void dnet_writew_mac(struct dnet_device *dnet, u16 reg, u16 val) +{
- /* load data to write */
- dnet_writel(dnet, val, MACREG_DATA);
- /* issue a write */
- dnet_writel(dnet, reg | DNET_INTERNAL_WRITE, MACREG_ADDR);
- /* since a read/write op to the MAC is very slow,
* we must wait before exiting */
- udelay(1);
- /* all done */
- return;
Not necessary to return
+}
+static void dnet_mdio_write(struct dnet_device *dnet, u8 reg, u16 value) +{
- u16 tmp;
- debug(DRIVERNAME "dnet_mdio_write %02x:%02x <- %04x\n",
dnet->phy_addr, reg, value);
- while (!(dnet_readw_mac(dnet, DNET_INTERNAL_GMII_MNG_CTL_REG) &
DNET_INTERNAL_GMII_MNG_CMD_FIN));
- /* prepare for a write operation */
- tmp = (1 << 13);
- /* only 5 bits allowed for register offset */
- reg &= 0x1f;
- /* prepare reg_value for a write */
- tmp |= (dnet->phy_addr << 8);
- tmp |= reg;
- /* write data to write first */
- dnet_writew_mac(dnet, DNET_INTERNAL_GMII_MNG_DAT_REG, value);
- /* write control word */
- dnet_writew_mac(dnet, DNET_INTERNAL_GMII_MNG_CTL_REG, tmp);
- while (!(dnet_readw_mac(dnet, DNET_INTERNAL_GMII_MNG_CTL_REG) &
DNET_INTERNAL_GMII_MNG_CMD_FIN));
+}
+static u16 dnet_mdio_read(struct dnet_device *dnet, u8 reg) +{
- u16 value;
- while (!(dnet_readw_mac(dnet, DNET_INTERNAL_GMII_MNG_CTL_REG) &
DNET_INTERNAL_GMII_MNG_CMD_FIN));
- /* only 5 bits allowed for register offset*/
- reg &= 0x1f;
- /* prepare reg_value for a read */
- value = (dnet->phy_addr << 8);
- value |= reg;
- /* write control word */
- dnet_writew_mac(dnet, DNET_INTERNAL_GMII_MNG_CTL_REG, value);
- /* wait for end of transfer */
- while (!(dnet_readw_mac(dnet, DNET_INTERNAL_GMII_MNG_CTL_REG) &
DNET_INTERNAL_GMII_MNG_CMD_FIN));
- value = dnet_readw_mac(dnet, DNET_INTERNAL_GMII_MNG_DAT_REG);
- debug(DRIVERNAME "dnet_mdio_read %02x:%02x <- %04x\n",
dnet->phy_addr, reg, value);
- return value;
+}
+#if defined(CONFIG_CMD_NET)
Not necessary
+static int dnet_send(struct eth_device *netdev, volatile void *packet,
int length)
+{
- struct dnet_device *dnet = to_dnet(netdev);
- int i, len, wrsz;
- unsigned int * bufp;
- unsigned int tx_cmd;
- debug(DRIVERNAME "[%s] Sending %u bytes\n", __FUNCTION__, length);
- /* frame size (words) */
- len = (length + 3) >> 2;
- bufp = (unsigned int *) (((u32)packet) & 0xFFFFFFFC);
- wrsz = (u32)length + 3;
- wrsz += ((u32)packet) & 0x3;
- wrsz >>= 2;
- tx_cmd = ((((unsigned int)(packet)) & 0x03) << 16) | (u32)length;
- /* check if there is enough room for the current frame */
- if (wrsz < (DNET_FIFO_SIZE - dnet_readl(dnet, TX_FIFO_WCNT))) {
for (i = 0; i < wrsz; i++) {
dnet_writel(dnet, *bufp++, TX_DATA_FIFO);
}
/*
* inform MAC that a packet's written and ready
* to be shipped out
*/
dnet_writel(dnet, tx_cmd, TX_LEN_FIFO);
- } else {
printf(DRIVERNAME "No free space (actual %d, required %d "
"(words))\n", DNET_FIFO_SIZE -
dnet_readl(dnet, TX_FIFO_WCNT), wrsz);
- }
- /* No one cares anyway */
- return 0;
+}
+static int dnet_recv(struct eth_device *netdev) +{
- struct dnet_device *dnet = to_dnet(netdev);
- unsigned int * data_ptr;
- int pkt_len, poll, i;
- u32 cmd_word;
- debug("Waiting for pkt (polling)\n");
- poll = 50;
- while ((dnet_readl(dnet, RX_FIFO_WCNT) >> 16) == 0) {
udelay(10); // wait 10 usec
--poll;
if (poll == 0)
You can combine these two lines
return 0; // no pkt available
- }
- cmd_word = dnet_readl(dnet, RX_LEN_FIFO);
- pkt_len = cmd_word & 0xFFFF;
- debug("Got pkt with size %d bytes\n", pkt_len);
- if (cmd_word & 0xDF180000)
printf("%s packet receive error %x\n", __FUNCTION__, cmd_word);
- data_ptr = (unsigned int *) NetRxPackets[0];
- for (i = 0; i < (pkt_len + 3) >> 2; i++)
*data_ptr++ = dnet_readl(dnet, RX_DATA_FIFO);
- NetReceive(NetRxPackets[0], pkt_len + 5); /* ok + 5 ?? */
- return 0;
+}
+static void dnet_set_hwaddr(struct eth_device *netdev) +{
- struct dnet_device *dnet = to_dnet(netdev);
- u16 tmp;
- tmp = cpu_to_be16(*((u16 *)netdev->enetaddr));
- dnet_writew_mac(dnet, DNET_INTERNAL_MAC_ADDR_0_REG, tmp);
- tmp = cpu_to_be16(*((u16 *)(netdev->enetaddr + 2)));
- dnet_writew_mac(dnet, DNET_INTERNAL_MAC_ADDR_1_REG, tmp);
- tmp = cpu_to_be16(*((u16 *)(netdev->enetaddr + 4)));
- dnet_writew_mac(dnet, DNET_INTERNAL_MAC_ADDR_2_REG, tmp);
+}
+static void dnet_phy_reset(struct dnet_device *dnet) +{
- struct eth_device *netdev = &dnet->netdev;
- int i;
- u16 status, adv;
- adv = ADVERTISE_CSMA | ADVERTISE_ALL;
- dnet_mdio_write(dnet, MII_ADVERTISE, adv);
- printf("%s: Starting autonegotiation...\n", netdev->name);
- dnet_mdio_write(dnet, MII_BMCR, (BMCR_ANENABLE
| BMCR_ANRESTART));
- for (i = 0; i < CFG_DNET_AUTONEG_TIMEOUT / 100; i++) {
status = dnet_mdio_read(dnet, MII_BMSR);
if (status & BMSR_ANEGCOMPLETE)
break;
udelay(100);
- }
- if (status & BMSR_ANEGCOMPLETE)
printf("%s: Autonegotiation complete\n", netdev->name);
- else
printf("%s: Autonegotiation timed out (status=0x%04x)\n",
netdev->name, status);
+}
+static int dnet_phy_init(struct dnet_device *dnet) +{
- struct eth_device *netdev = &dnet->netdev;
- u16 phy_id, status, adv, lpa;
- int media, speed, duplex;
- int i;
- u32 ctl_reg;
- /* Find a PHY */
- for (i = 0; i < 32; i++) {
dnet->phy_addr = i;
phy_id = dnet_mdio_read(dnet, MII_PHYSID1);
if (phy_id != 0xffff) {
/* ok we found it */
printf("Found PHY at address %d PHYID (%04x:%04x)\n",
i, phy_id,
dnet_mdio_read(dnet, MII_PHYSID2));
break;
}
- }
- /* Check if the PHY is up to snuff... */
- phy_id = dnet_mdio_read(dnet, MII_PHYSID1);
- if (phy_id == 0xffff) {
printf("%s: No PHY present\n", netdev->name);
return 0;
Convention is to return 0 on success, -1 on failure
- }
- status = dnet_mdio_read(dnet, MII_BMSR);
- if (!(status & BMSR_LSTATUS)) {
/* Try to re-negotiate if we don't have link already. */
dnet_phy_reset(dnet);
for (i = 0; i < CFG_DNET_AUTONEG_TIMEOUT / 100; i++) {
status = dnet_mdio_read(dnet, MII_BMSR);
if (status & BMSR_LSTATUS)
break;
udelay(100);
}
- }
- if (!(status & BMSR_LSTATUS)) {
printf("%s: link down (status: 0x%04x)\n",
netdev->name, status);
return 0;
- } else {
adv = dnet_mdio_read(dnet, MII_ADVERTISE);
lpa = dnet_mdio_read(dnet, MII_LPA);
media = mii_nway_result(lpa & adv);
speed = (media & (ADVERTISE_100FULL | ADVERTISE_100HALF)
? 1 : 0);
duplex = (media & ADVERTISE_FULL) ? 1 : 0;
/* 1000BaseT ethernet is not supported */
printf("%s: link up, %sMbps %s-duplex (lpa: 0x%04x)\n",
netdev->name,
speed ? "100" : "10",
duplex ? "full" : "half",
lpa);
ctl_reg = dnet_readw_mac(dnet, DNET_INTERNAL_RXTX_CONTROL_REG);
if (duplex)
ctl_reg &= ~(DNET_INTERNAL_RXTX_CONTROL_ENABLEHALFDUP);
else
ctl_reg |= DNET_INTERNAL_RXTX_CONTROL_ENABLEHALFDUP;
dnet_writew_mac(dnet, DNET_INTERNAL_RXTX_CONTROL_REG, ctl_reg);
return 1;
- }
+}
+static int dnet_init(struct eth_device *netdev, bd_t *bd) +{
- struct dnet_device *dnet = to_dnet(netdev);
- u32 config;
- /*
* dnet_halt should have been called at some point before now,
* so we'll assume the controller is idle.
*/
- /* set hardware address */
- dnet_set_hwaddr(netdev);
- if (!dnet_phy_init(dnet))
return 0;
- /* flush rx/tx fifos */
- dnet_writel(dnet, DNET_SYS_CTL_RXFIFOFLUSH |
DNET_SYS_CTL_TXFIFOFLUSH, SYS_CTL);
- udelay(1000);
- dnet_writel(dnet, 0, SYS_CTL);
- config = dnet_readw_mac(dnet, DNET_INTERNAL_RXTX_CONTROL_REG);
- config |= DNET_INTERNAL_RXTX_CONTROL_RXPAUSE |
DNET_INTERNAL_RXTX_CONTROL_RXBROADCAST |
DNET_INTERNAL_RXTX_CONTROL_DROPCONTROL |
DNET_INTERNAL_RXTX_CONTROL_DISCFXFCS;
- dnet_writew_mac(dnet, DNET_INTERNAL_RXTX_CONTROL_REG, config);
- /* Enable TX and RX */
- dnet_writew_mac(dnet, DNET_INTERNAL_MODE_REG,
DNET_INTERNAL_MODE_RXEN | DNET_INTERNAL_MODE_TXEN);
- return 1;
+}
+static void dnet_halt(struct eth_device *netdev) +{
- struct dnet_device *dnet = to_dnet(netdev);
- /* Disable TX and RX */
- dnet_writew_mac(dnet, DNET_INTERNAL_MODE_REG, 0);
+}
+int dnet_eth_initialize(int id, void *regs, unsigned int phy_addr) +{
- struct dnet_device *dnet;
- struct eth_device *netdev;
- unsigned int dev_capa;
- dnet = malloc(sizeof(struct dnet_device));
- if (!dnet) {
printf("Error: Failed to allocate memory for DNET%d\n", id);
return -1;
- }
- memset(dnet, 0, sizeof(struct dnet_device));
- netdev = &dnet->netdev;
- dnet->regs = regs;
- dnet->phy_addr = phy_addr;
- sprintf(netdev->name, "dnet%d", id);
- netdev->init = dnet_init;
- netdev->halt = dnet_halt;
- netdev->send = dnet_send;
- netdev->recv = dnet_recv;
- dev_capa = dnet_readl(dnet, VERCAPS) & 0xFFFF;
- debug("%s: has %smdio, %sirq, %sgigabit, %sdma \n", netdev->name,
(dev_capa & DNET_HAS_MDIO) ? "" : "no ",
(dev_capa & DNET_HAS_IRQ) ? "" : "no ",
(dev_capa & DNET_HAS_GIGABIT) ? "" : "no ",
(dev_capa & DNET_HAS_DMA) ? "" : "no ");
- eth_register(netdev);
- return 0;
+}
+#endif /* CONFIG_CMD_NET */
+#endif /* CONFIG_DRIVER_DNET */ diff --git a/drivers/net/dnet.h b/drivers/net/dnet.h new file mode 100644 index 0000000..5bd4986 --- /dev/null +++ b/drivers/net/dnet.h @@ -0,0 +1,169 @@ +/*
- Dave Ethernet Controller driver
- Copyright (C) 2008 Dave S.r.l. <www.dave.eu>
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License version 2 as
- published by the Free Software Foundation.
- */
+#ifndef __DRIVERS_DNET_H__ +#define __DRIVERS_DNET_H__
+#define DRIVERNAME "dnet"
+/* Register access macros */ +#define dnet_writel(port, value, reg) \
- writel((value), (port)->regs + DNET_##reg)
+#define dnet_readl(port, reg) readl((port)->regs + DNET_##reg)
+/* ALL DNET FIFO REGISTERS */ +#define DNET_RX_LEN_FIFO (0x000) /* RX_LEN_FIFO */ +#define DNET_RX_DATA_FIFO (0x004) /* RX_DATA_FIFO */ +#define DNET_TX_LEN_FIFO (0x008) /* TX_LEN_FIFO */ +#define DNET_TX_DATA_FIFO (0x00C) /* TX_DATA_FIFO */
+/* ALL DNET CONTROL/STATUS REGISTERS OFFSETS */ +#define DNET_VERCAPS (0x100) /* VERCAPS */ +#define DNET_INTR_SRC (0x104) /* INTR_SRC */ +#define DNET_INTR_ENB (0x108) /* INTR_ENB */ +#define DNET_RX_STATUS (0x10C) /* RX_STATUS */ +#define DNET_TX_STATUS (0x110) /* TX_STATUS */ +#define DNET_RX_FRAMES_CNT (0x114) /* RX_FRAMES_CNT */ +#define DNET_TX_FRAMES_CNT (0x118) /* TX_FRAMES_CNT */ +#define DNET_RX_FIFO_TH (0x11C) /* RX_FIFO_TH */ +#define DNET_TX_FIFO_TH (0x120) /* TX_FIFO_TH */ +#define DNET_SYS_CTL (0x124) /* SYS_CTL */ +#define DNET_PAUSE_TMR (0x128) /* PAUSE_TMR */ +#define DNET_RX_FIFO_WCNT (0x12C) /* RX_FIFO_WCNT */ +#define DNET_TX_FIFO_WCNT (0x130) /* TX_FIFO_WCNT */
+/* ALL DNET MAC REGISTERS */ +#define DNET_MACREG_DATA (0x200) /* Mac-Reg Data */ +#define DNET_MACREG_ADDR (0x204) /* Mac-Reg Addr */
+/* ALL DNET RX STATISTICS COUNTERS */ +#define DNET_RX_PKT_IGNR_CNT (0x300) +#define DNET_RX_LEN_CHK_ERR_CNT (0x304) +#define DNET_RX_LNG_FRM_CNT (0x308) +#define DNET_RX_SHRT_FRM_CNT (0x30C) +#define DNET_RX_IPG_VIOL_CNT (0x310) +#define DNET_RX_CRC_ERR_CNT (0x314) +#define DNET_RX_OK_PKT_CNT (0x318) +#define DNET_RX_CTL_FRM_CNT (0x31C) +#define DNET_RX_PAUSE_FRM_CNT (0x320) +#define DNET_RX_MULTICAST_CNT (0x324) +#define DNET_RX_BROADCAST_CNT (0x328) +#define DNET_RX_VLAN_TAG_CNT (0x32C) +#define DNET_RX_PRE_SHRINK_CNT (0x330) +#define DNET_RX_DRIB_NIB_CNT (0x334) +#define DNET_RX_UNSUP_OPCD_CNT (0x338) +#define DNET_RX_BYTE_CNT (0x33C)
+/* DNET TX STATISTICS COUNTERS */ +#define DNET_TX_UNICAST_CNT (0x400) +#define DNET_TX_PAUSE_FRM_CNT (0x404) +#define DNET_TX_MULTICAST_CNT (0x408) +#define DNET_TX_BRDCAST_CNT (0x40C) +#define DNET_TX_VLAN_TAG_CNT (0x410) +#define DNET_TX_BAD_FCS_CNT (0x414) +#define DNET_TX_JUMBO_CNT (0x418) +#define DNET_TX_BYTE_CNT (0x41C)
+/* SOME INTERNAL MAC-CORE REGISTER */ +#define DNET_INTERNAL_MODE_REG (0x0) +#define DNET_INTERNAL_RXTX_CONTROL_REG (0x2) +#define DNET_INTERNAL_MAX_PKT_SIZE_REG (0x4) +#define DNET_INTERNAL_IGP_REG (0x8) +#define DNET_INTERNAL_MAC_ADDR_0_REG (0xa) +#define DNET_INTERNAL_MAC_ADDR_1_REG (0xc) +#define DNET_INTERNAL_MAC_ADDR_2_REG (0xe) +#define DNET_INTERNAL_TX_RX_STS_REG (0x12) +#define DNET_INTERNAL_GMII_MNG_CTL_REG (0x14) +#define DNET_INTERNAL_GMII_MNG_DAT_REG (0x16)
+#define DNET_INTERNAL_GMII_MNG_CMD_FIN (1 << 14)
+#define DNET_INTERNAL_WRITE (1 << 31)
+/* MAC-CORE REGISTER FIELDS */
+/* MAC-CORE MODE REGISTER FIELDS */ +#define DNET_INTERNAL_MODE_GBITEN (1 << 0) +#define DNET_INTERNAL_MODE_FCEN (1 << 1) +#define DNET_INTERNAL_MODE_RXEN (1 << 2) +#define DNET_INTERNAL_MODE_TXEN (1 << 3)
+/* MAC-CORE RXTX CONTROL REGISTER FIELDS */ +#define DNET_INTERNAL_RXTX_CONTROL_RXSHORTFRAME (1 << 8) +#define DNET_INTERNAL_RXTX_CONTROL_RXBROADCAST (1 << 7) +#define DNET_INTERNAL_RXTX_CONTROL_RXMULTICAST (1 << 4) +#define DNET_INTERNAL_RXTX_CONTROL_RXPAUSE (1 << 3) +#define DNET_INTERNAL_RXTX_CONTROL_DISTXFCS (1 << 2) +#define DNET_INTERNAL_RXTX_CONTROL_DISCFXFCS (1 << 1) +#define DNET_INTERNAL_RXTX_CONTROL_ENPROMISC (1 << 0) +#define DNET_INTERNAL_RXTX_CONTROL_DROPCONTROL (1 << 6) +#define DNET_INTERNAL_RXTX_CONTROL_ENABLEHALFDUP (1 << 5)
+/* SYSTEM CONTROL REGISTER FIELDS */ +#define DNET_SYS_CTL_IGNORENEXTPKT (1 << 0) +#define DNET_SYS_CTL_SENDPAUSE (1 << 2) +#define DNET_SYS_CTL_RXFIFOFLUSH (1 << 3) +#define DNET_SYS_CTL_TXFIFOFLUSH (1 << 4)
+/* TX STATUS REGISTER FIELDS */ +#define DNET_TX_STATUS_FIFO_ALMOST_EMPTY (1 << 2) +#define DNET_TX_STATUS_FIFO_ALMOST_FULL (1 << 1)
+/* INTERRUPT SOURCE REGISTER FIELDS */ +#define DNET_INTR_SRC_TX_PKTSENT (1 << 0) +#define DNET_INTR_SRC_TX_FIFOAF (1 << 1) +#define DNET_INTR_SRC_TX_FIFOAE (1 << 2) +#define DNET_INTR_SRC_TX_DISCFRM (1 << 3) +#define DNET_INTR_SRC_TX_FIFOFULL (1 << 4) +#define DNET_INTR_SRC_RX_CMDFIFOAF (1 << 8) +#define DNET_INTR_SRC_RX_CMDFIFOFF (1 << 9) +#define DNET_INTR_SRC_RX_DATAFIFOFF (1 << 10) +#define DNET_INTR_SRC_TX_SUMMARY (1 << 16) +#define DNET_INTR_SRC_RX_SUMMARY (1 << 17) +#define DNET_INTR_SRC_PHY (1 << 19)
+/* INTERRUPT ENABLE REGISTER FIELDS */ +#define DNET_INTR_ENB_TX_PKTSENT (1 << 0) +#define DNET_INTR_ENB_TX_FIFOAF (1 << 1) +#define DNET_INTR_ENB_TX_FIFOAE (1 << 2) +#define DNET_INTR_ENB_TX_DISCFRM (1 << 3) +#define DNET_INTR_ENB_TX_FIFOFULL (1 << 4) +#define DNET_INTR_ENB_RX_PKTRDY (1 << 8) +#define DNET_INTR_ENB_RX_FIFOAF (1 << 9) +#define DNET_INTR_ENB_RX_FIFOERR (1 << 10) +#define DNET_INTR_ENB_RX_ERROR (1 << 11) +#define DNET_INTR_ENB_RX_FIFOFULL (1 << 12) +#define DNET_INTR_ENB_RX_FIFOAE (1 << 13) +#define DNET_INTR_ENB_TX_SUMMARY (1 << 16) +#define DNET_INTR_ENB_RX_SUMMARY (1 << 17) +#define DNET_INTR_ENB_GLOBAL_ENABLE (1 << 18)
+/*
- Capabilities. Used by the driver to know the capabilities that
- the ethernet controller inside the FPGA have.
- */
+#define DNET_HAS_MDIO (1 << 0) +#define DNET_HAS_IRQ (1 << 1) +#define DNET_HAS_GIGABIT (1 << 2) +#define DNET_HAS_DMA (1 << 3)
+#define DNET_HAS_MII (1 << 4) // or GMII +#define DNET_HAS_RMII (1 << 5) // or RGMII
+#define DNET_CAPS_MASK 0xFFFF
+#define DNET_FIFO_SIZE 2048 /* 2K x 32 bit */ +#define DNET_FIFO_TX_DATA_AF_TH (DNET_FIFO_SIZE - 384) /* 384 = 1536 / 4 */ +#define DNET_FIFO_TX_DATA_AE_TH (384)
+#define DNET_FIFO_RX_CMD_AF_TH (1 << 16) /* just one frame inside the FIFO */
+#endif
regards, Ben

Hi Ben,
Thanks a lot for your comments! I'll address them and repost the patch in a short time.
Regards, Ilya.

Dear Ilya Yanok,
In message 1233589490-14293-3-git-send-email-yanok@emcraft.com you wrote:
Driver for Dave DNET ethernet controller (used on Dave/DENX QongEVB-LITE board).
...
--- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -69,6 +69,7 @@ COBJS-$(CONFIG_VSC7385_ENET) += vsc7385.o COBJS-$(CONFIG_XILINX_EMAC) += xilinx_emac.o COBJS-$(CONFIG_XILINX_EMACLITE) += xilinx_emaclite.o COBJS-$(CONFIG_SH_ETHER) += sh_eth.o +COBJS-$(CONFIG_DRIVER_DNET) += dnet.o
Please omit the "DIVER_" part in the name.
+struct dnet_device {
- void *regs;
- const struct device *dev;
- struct eth_device netdev;
- unsigned short phy_addr;
+};
Please no empty line in the struct declaration.
+#define to_dnet(_nd) container_of(_nd, struct dnet_device, netdev)
Maybe a comment what this is good for?
+static void dnet_mdio_write(struct dnet_device *dnet, u8 reg, u16 value) +{
- u16 tmp;
- debug(DRIVERNAME "dnet_mdio_write %02x:%02x <- %04x\n",
dnet->phy_addr, reg, value);
- while (!(dnet_readw_mac(dnet, DNET_INTERNAL_GMII_MNG_CTL_REG) &
DNET_INTERNAL_GMII_MNG_CMD_FIN));
Please move the semicolon to a separate line.
- while (!(dnet_readw_mac(dnet, DNET_INTERNAL_GMII_MNG_CTL_REG) &
DNET_INTERNAL_GMII_MNG_CMD_FIN));
Ditto.
+static u16 dnet_mdio_read(struct dnet_device *dnet, u8 reg) +{
- u16 value;
- while (!(dnet_readw_mac(dnet, DNET_INTERNAL_GMII_MNG_CTL_REG) &
DNET_INTERNAL_GMII_MNG_CMD_FIN));
- /* only 5 bits allowed for register offset*/
- reg &= 0x1f;
- /* prepare reg_value for a read */
- value = (dnet->phy_addr << 8);
- value |= reg;
- /* write control word */
- dnet_writew_mac(dnet, DNET_INTERNAL_GMII_MNG_CTL_REG, value);
- /* wait for end of transfer */
- while (!(dnet_readw_mac(dnet, DNET_INTERNAL_GMII_MNG_CTL_REG) &
DNET_INTERNAL_GMII_MNG_CMD_FIN));
Ditto - and so on.
+static int dnet_recv(struct eth_device *netdev) +{
- struct dnet_device *dnet = to_dnet(netdev);
- unsigned int * data_ptr;
- int pkt_len, poll, i;
- u32 cmd_word;
- debug("Waiting for pkt (polling)\n");
- poll = 50;
- while ((dnet_readl(dnet, RX_FIFO_WCNT) >> 16) == 0) {
udelay(10); // wait 10 usec
----------------------------^^^
--poll;
if (poll == 0)
return 0; // no pkt available
---------------------------------------^^^
No C++ comments, please.
+/* Register access macros */ +#define dnet_writel(port, value, reg) \
- writel((value), (port)->regs + DNET_##reg)
Please do not swap arguments.
+#define dnet_readl(port, reg) readl((port)->regs + DNET_##reg)
Hmm... Why do we need this?
+/* ALL DNET FIFO REGISTERS */ +#define DNET_RX_LEN_FIFO (0x000) /* RX_LEN_FIFO */ +#define DNET_RX_DATA_FIFO (0x004) /* RX_DATA_FIFO */ +#define DNET_TX_LEN_FIFO (0x008) /* TX_LEN_FIFO */ +#define DNET_TX_DATA_FIFO (0x00C) /* TX_DATA_FIFO */
+/* ALL DNET CONTROL/STATUS REGISTERS OFFSETS */ +#define DNET_VERCAPS (0x100) /* VERCAPS */ +#define DNET_INTR_SRC (0x104) /* INTR_SRC */ +#define DNET_INTR_ENB (0x108) /* INTR_ENB */ +#define DNET_RX_STATUS (0x10C) /* RX_STATUS */ +#define DNET_TX_STATUS (0x110) /* TX_STATUS */ +#define DNET_RX_FRAMES_CNT (0x114) /* RX_FRAMES_CNT */ +#define DNET_TX_FRAMES_CNT (0x118) /* TX_FRAMES_CNT */ +#define DNET_RX_FIFO_TH (0x11C) /* RX_FIFO_TH */ +#define DNET_TX_FIFO_TH (0x120) /* TX_FIFO_TH */ +#define DNET_SYS_CTL (0x124) /* SYS_CTL */ +#define DNET_PAUSE_TMR (0x128) /* PAUSE_TMR */ +#define DNET_RX_FIFO_WCNT (0x12C) /* RX_FIFO_WCNT */ +#define DNET_TX_FIFO_WCNT (0x130) /* TX_FIFO_WCNT */
...
I see.
Please do not operate on base register plus magic offset - implement a proper C structure instead to describe the controller hardware.
+/*
- Capabilities. Used by the driver to know the capabilities that
- the ethernet controller inside the FPGA have.
- */
+#define DNET_HAS_MDIO (1 << 0) +#define DNET_HAS_IRQ (1 << 1) +#define DNET_HAS_GIGABIT (1 << 2) +#define DNET_HAS_DMA (1 << 3)
+#define DNET_HAS_MII (1 << 4) // or GMII +#define DNET_HAS_RMII (1 << 5) // or RGMII
No C++ comments, please.
Best regards,
Wolfgang Denk

Dear Wolfgang,
thanks for your review. I think I've addressed all your comments. Please take a look on updated patches.
Wolfgang Denk wrote:
I see.
Please do not operate on base register plus magic offset - implement a proper C structure instead to describe the controller hardware.
I've done as you requested but I'm really in doubt why do you like it? In the kernel offsets are preferred over C structures... And there is nothing magical in offsets actually... we usually have offsets in specs not C structures...
Regards, Ilya.

Dear Ilya Yanok,
In message 498A5F2F.1030603@emcraft.com you wrote:
Please do not operate on base register plus magic offset - implement a proper C structure instead to describe the controller hardware.
I've done as you requested but I'm really in doubt why do you like it? In the kernel offsets are preferred over C structures... And there is
With "in the kernel" you probaly mean "in the ARM architecture code of the kernel". Compare for example PowerPC...
nothing magical in offsets actually... we usually have offsets in specs not C structures...
Just to name one reason (but a very important one): using a struct allows for strict type checking by the compiler. If you use address + offset you will not get any help from the compiler when you for example read 8 bit from a register that must be accessed as a 32 bit entity.
Best regards,
Wolfgang Denk

Dear Wolfgang,
Wolfgang Denk wrote:
nothing magical in offsets actually... we usually have offsets in specs not C structures...
Just to name one reason (but a very important one): using a struct allows for strict type checking by the compiler. If you use address + offset you will not get any help from the compiler when you for example read 8 bit from a register that must be accessed as a 32 bit entity.
But this works only if we use "memory-style" IO access, if we use read/write accessor functions that info we be lost as all pointers we be silently converted into void*... And using "memory-style" IO access is strongly discouraged in the kernel... BTW, what is the general rule for U-Boot? I can see that most accesses are done "memory-style" but I can see accessor functions used here and there...
Regards, Ilya.

This patch adds support for Dave/DENX QongEVB-LITE i.MX31-based board.
Signed-off-by: Ilya Yanok yanok@emcraft.com --- Makefile | 4 + board/dave/qong/Makefile | 51 +++++++++ board/dave/qong/config.mk | 1 + board/dave/qong/lowlevel_init.S | 170 +++++++++++++++++++++++++++++++ board/dave/qong/qong.c | 167 ++++++++++++++++++++++++++++++ board/dave/qong/qong_fpga.h | 41 ++++++++ board/dave/qong/u-boot.lds | 59 +++++++++++ include/configs/qong.h | 213 +++++++++++++++++++++++++++++++++++++++ 8 files changed, 706 insertions(+), 0 deletions(-) create mode 100644 board/dave/qong/Makefile create mode 100644 board/dave/qong/config.mk create mode 100644 board/dave/qong/lowlevel_init.S create mode 100644 board/dave/qong/qong.c create mode 100644 board/dave/qong/qong_fpga.h create mode 100644 board/dave/qong/u-boot.lds create mode 100644 include/configs/qong.h
diff --git a/Makefile b/Makefile index 9647bd2..9436107 100644 --- a/Makefile +++ b/Makefile @@ -2994,6 +2994,10 @@ mx31ads_config : unconfig omap2420h4_config : unconfig @$(MKCONFIG) $(@:_config=) arm arm1136 omap2420h4 NULL omap24xx
+qong_config : unconfig + @$(MKCONFIG) $(@:_config=) arm arm1136 qong dave mx31 + + ######################################################################### ## ARM1176 Systems ######################################################################### diff --git a/board/dave/qong/Makefile b/board/dave/qong/Makefile new file mode 100644 index 0000000..b08bc72 --- /dev/null +++ b/board/dave/qong/Makefile @@ -0,0 +1,51 @@ +# +# (C) Copyright 2000-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# See file CREDITS for list of people who contributed to this +# project. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# + +include $(TOPDIR)/config.mk + +LIB = $(obj)lib$(BOARD).a + +COBJS := qong.o +SOBJS := lowlevel_init.o + +SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) +OBJS := $(addprefix $(obj),$(COBJS)) +SOBJS := $(addprefix $(obj),$(SOBJS)) + +$(LIB): $(obj).depend $(OBJS) $(SOBJS) + $(AR) $(ARFLAGS) $@ $(OBJS) $(SOBJS) + +clean: + rm -f $(SOBJS) $(OBJS) + +distclean: clean + rm -f $(LIB) core *.bak .depend + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/board/dave/qong/config.mk b/board/dave/qong/config.mk new file mode 100644 index 0000000..d34dc02 --- /dev/null +++ b/board/dave/qong/config.mk @@ -0,0 +1 @@ +TEXT_BASE = 0x87f00000 diff --git a/board/dave/qong/lowlevel_init.S b/board/dave/qong/lowlevel_init.S new file mode 100644 index 0000000..92d5409 --- /dev/null +++ b/board/dave/qong/lowlevel_init.S @@ -0,0 +1,170 @@ +/* + * Copyright (C) 2009, Emcraft Systems, Ilya Yanok yanok@emcraft.com + * + * Based on board/freescale/mx31ads/lowlevel_init.S + * by Guennadi Liakhovetski. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <asm/arch/mx31-regs.h> + +.macro REG reg, val + ldr r2, =\reg + ldr r3, =\val + str r3, [r2] +.endm + +.macro REG8 reg, val + ldr r2, =\reg + ldr r3, =\val + strb r3, [r2] +.endm + +.macro DELAY loops + ldr r2, =\loops +1: + subs r2, r2, #1 + nop + bcs 1b +.endm + +/* RedBoot: To support 133MHz DDR */ +.macro init_drive_strength + /* + * Disable maximum drive strength SDRAM/DDR lines by clearing DSE1 bits + * in SW_PAD_CTL registers + */ + + /* SDCLK */ + ldr r1, =0x43FAC200 + ldr r0, [r1, #0x6C] + bic r0, r0, #(1 << 12) + str r0, [r1, #0x6C] + + /* CAS */ + ldr r0, [r1, #0x70] + bic r0, r0, #(1 << 22) + str r0, [r1, #0x70] + + /* RAS */ + ldr r0, [r1, #0x74] + bic r0, r0, #(1 << 2) + str r0, [r1, #0x74] + + /* CS2 (CSD0) */ + ldr r0, [r1, #0x7C] + bic r0, r0, #(1 << 22) + str r0, [r1, #0x7C] + + /* DQM3 */ + ldr r0, [r1, #0x84] + bic r0, r0, #(1 << 22) + str r0, [r1, #0x84] + + /* DQM2, DQM1, DQM0, SD31-SD0, A25-A0, MA10 (0x288..0x2DC) */ + ldr r2, =22 /* (0x2E0 - 0x288) / 4 = 22 */ +pad_loop: + ldr r0, [r1, #0x88] + bic r0, r0, #(1 << 22) + bic r0, r0, #(1 << 12) + bic r0, r0, #(1 << 2) + str r0, [r1, #0x88] + add r1, r1, #4 + subs r2, r2, #0x1 + bne pad_loop +.endm /* init_drive_strength */ + +.globl lowlevel_init +lowlevel_init: + + init_drive_strength + + /* Image Processing Unit: */ + /* Too early to switch display on? */ + REG IPU_CONF, IPU_CONF_DI_EN /* Switch on Display Interface */ + /* Clock Control Module: */ + REG CCM_CCMR, 0x074B0BF5 /* Use CKIH, MCU PLL off */ + + DELAY 0x40000 + + REG CCM_CCMR, 0x074B0BF5 | CCMR_MPE /* MCU PLL on */ + REG CCM_CCMR, (0x074B0BF5 | CCMR_MPE) & ~CCMR_MDS /* Switch to MCU PLL */ + + /* 399-133-66.5 */ + ldr r0, =CCM_BASE + ldr r1, =0xFF871650 + /* PDR0 */ + str r1, [r0, #0x4] + ldr r1, MPCTL_PARAM_399 + /* MPCTL */ + str r1, [r0, #0x10] + + /* Set UPLL=240MHz, USB=60MHz */ + ldr r1, =0x49FCFE7F + /* PDR1 */ + str r1, [r0, #0x8] + ldr r1, UPCTL_PARAM_240 + /* UPCTL */ + str r1, [r0, #0x14] + /* default CLKO to 1/8 of the ARM core */ + mov r1, #0x00000208 + /* COSR */ + str r1, [r0, #0x1c] + + /* Default: 1, 4, 12, 1 */ + REG CCM_SPCTL, PLL_PD(1) | PLL_MFD(4) | PLL_MFI(12) | PLL_MFN(1) + + /* B8xxxxxx - NAND, 8xxxxxxx - CSD0 RAM */ + REG 0xB8001010, 0x00000004 + REG 0xB8001004, ((3<<21) | /* tXP */ \ + (0<<20) | /* tWTR */ \ + (2<<18) | /* tRP */ \ + (1<<16) | /* tMRD */ \ + (0<<15) | /* tWR */ \ + (5<<12) | /* tRAS */ \ + (1<<10) | /* tRRD */ \ + (3<<8) | /* tCAS */ \ + (2<<4) | /* tRCD */ \ + (7<<0) /* tRC */ ) + REG 0xB8001000, 0x92100000 + REG 0x80000f00, 0x12344321 + REG 0xB8001000, 0xa2100000 + REG 0x80000000, 0x12344321 + REG 0x80000000, 0x12344321 + REG 0xB8001000, 0xb2100000 + REG8 0x80000033, 0xda + REG8 0x81000000, 0xff + REG 0xB8001000, ((1<<31) | \ + (0<<28) | \ + (0<<27) | \ + (3<<24) | /* 14 rows */ \ + (2<<20) | /* 10 cols */ \ + (2<<16) | \ + (4<<13) | /* 3.91us (64ms/16384) */ \ + (0<<10) | \ + (0<<8) | \ + (1<<7) | \ + (0<<0)) + REG 0x80000000, 0xDEADBEEF + REG 0xB8001010, 0x0000000c + + mov pc, lr + +MPCTL_PARAM_399: + .word (((1-1) << 26) + ((52-1) << 16) + (7 << 10) + (35 << 0)) +UPCTL_PARAM_240: + .word (((2-1) << 26) + ((13-1) << 16) + (9 << 10) + (3 << 0)) diff --git a/board/dave/qong/qong.c b/board/dave/qong/qong.c new file mode 100644 index 0000000..5d12a13 --- /dev/null +++ b/board/dave/qong/qong.c @@ -0,0 +1,167 @@ +/* + * + * (c) 2009 Emcraft Systems, Ilya Yanok yanok@emcraft.com + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + + +#include <common.h> +#include <asm/arch/mx31.h> +#include <asm/arch/mx31-regs.h> +#include "qong_fpga.h" + +DECLARE_GLOBAL_DATA_PTR; + +int dram_init (void) +{ + gd->bd->bi_dram[0].start = PHYS_SDRAM_1; + gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE; + + return 0; +} + +int board_init (void) +{ + /* Chip selects */ + /* CS0: Nor Flash #0 - it must be init'ed when executing from DDR */ + /* Assumptions: HCLK = 133 MHz, tACC = 130ns */ + __REG(CSCR_U(0)) = ((0 << 31) | /* SP */ + (0 << 30) | /* WP */ + (0 << 28) | /* BCD */ + (0 << 24) | /* BCS */ + (0 << 22) | /* PSZ */ + (0 << 21) | /* PME */ + (0 << 20) | /* SYNC */ + (0 << 16) | /* DOL */ + (3 << 14) | /* CNC */ + (21 << 8) | /* WSC */ + (0 << 7) | /* EW */ + (0 << 4) | /* WWS */ + (6 << 0) /* EDC */ + ); + + __REG(CSCR_L(0)) = ((2 << 28) | /* OEA */ + (1 << 24) | /* OEN */ + (3 << 20) | /* EBWA */ + (3 << 16) | /* EBWN */ + (1 << 12) | /* CSA */ + (1 << 11) | /* EBC */ + (5 << 8) | /* DSZ */ + (1 << 4) | /* CSN */ + (0 << 3) | /* PSR */ + (0 << 2) | /* CRE */ + (0 << 1) | /* WRAP */ + (1 << 0) /* CSEN */ + ); + + __REG(CSCR_A(0)) = ((2 << 28) | /* EBRA */ + (1 << 24) | /* EBRN */ + (2 << 20) | /* RWA */ + (2 << 16) | /* RWN */ + (0 << 15) | /* MUM */ + (0 << 13) | /* LAH */ + (2 << 10) | /* LBN */ + (0 << 8) | /* LBA */ + (0 << 6) | /* DWW */ + (0 << 4) | /* DCT */ + (0 << 3) | /* WWU */ + (0 << 2) | /* AGE */ + (0 << 1) | /* CNC2 */ + (0 << 0) /* FCE */ + ); + +#ifdef CONFIG_QONG_FPGA + /* CS1: FPGA/Network Controller/GPIO */ + /* 16-bit, no DTACK */ + __REG(CSCR_U(1)) = 0x00000A01; + __REG(CSCR_L(1)) = 0x20040501; + __REG(CSCR_A(1)) = 0x04020C00; + + /* setup pins for FPGA */ + mx31_gpio_mux(IOMUX_MODE(0x76, MUX_CTL_GPIO)); + mx31_gpio_mux(IOMUX_MODE(0x7e, MUX_CTL_GPIO)); + mx31_gpio_mux(IOMUX_MODE(0x91, MUX_CTL_OUT_FUNC | MUX_CTL_IN_GPIO)); + mx31_gpio_mux(IOMUX_MODE(0x92, MUX_CTL_GPIO)); + mx31_gpio_mux(IOMUX_MODE(0x93, MUX_CTL_GPIO)); +#endif + + /* setup pins for UART1 */ + mx31_gpio_mux(MUX_RXD1__UART1_RXD_MUX); + mx31_gpio_mux(MUX_TXD1__UART1_TXD_MUX); + mx31_gpio_mux(MUX_RTS1__UART1_RTS_B); + mx31_gpio_mux(MUX_CTS1__UART1_CTS_B); + + gd->bd->bi_arch_number = 1524; /* board id for linux */ + gd->bd->bi_boot_params = (0x80000100); /* adress of boot parameters */ + + return 0; +} + +int checkboard (void) +{ + printf("Board: DAVE/DENX QongEVB-LITE\n"); + return 0; +} + +int misc_init_r (void) +{ +#ifdef CONFIG_QONG_FPGA + u32 tmp; + + /* FPGA reset */ + /* rstn = 0 */ + tmp = __REG(GPIO2_BASE + GPIO_DR); + tmp &= (~(1 << QONG_FPGA_RST_PIN)); + __REG(GPIO2_BASE + GPIO_DR) = tmp; + /* set the GPIO as output */ + tmp = __REG(GPIO2_BASE + GPIO_GDIR); + tmp |= (1 << QONG_FPGA_RST_PIN); + __REG(GPIO2_BASE + GPIO_GDIR) = tmp; + /* wait */ + udelay(30); + /* rstn = 1 */ + tmp = __REG(GPIO2_BASE + GPIO_DR); + tmp |= (1 << QONG_FPGA_RST_PIN); + __REG(GPIO2_BASE + GPIO_DR) = tmp; + /* set interrupt pin as input */ + __REG(GPIO2_BASE + GPIO_GDIR) = tmp | (1 << QONG_FPGA_IRQ_PIN); + /* wait while the FPGA starts */ + udelay(300); + + tmp = *(volatile u32*)QONG_FPGA_CTRL_VERSION; + printf("FPGA: "); + printf("version register = %u.%u.%u\n", + (tmp & 0xF000)>>12, (tmp & 0x0F00) >> 8, tmp & 0x00FF ); +#endif + + return 0; +} + +extern int dnet_eth_initialize(int id, void *regs, unsigned int phy_addr); + +int board_eth_init(bd_t *bis) +{ +#if defined(CONFIG_QONG_FPGA) && defined(CONFIG_DRIVER_DNET) + return dnet_eth_initialize(0, (void *)CONFIG_DNET_BASE, -1); +#else + return 0; +#endif +} + diff --git a/board/dave/qong/qong_fpga.h b/board/dave/qong/qong_fpga.h new file mode 100644 index 0000000..b1cb08a --- /dev/null +++ b/board/dave/qong/qong_fpga.h @@ -0,0 +1,41 @@ +/* + * + * (c) 2009 Emcraft Systems, Ilya Yanok yanok@emcraft.com + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef QONG_FPGA_H +#define QONG_FPGA_H + +#ifdef CONFIG_QONG_FPGA +#define QONG_FPGA_CTRL_BASE CONFIG_FPGA_BASE +#define QONG_FPGA_CTRL_VERSION (QONG_FPGA_CTRL_BASE + 0x00000000) +#define QONG_FPGA_PERIPH_SIZE (1 << 24) + +#define QONG_FPGA_TCK_PIN 26 +#define QONG_FPGA_TMS_PIN 25 +#define QONG_FPGA_TDI_PIN 8 +#define QONG_FPGA_TDO_PIN 7 +#define QONG_FPGA_RST_PIN 16 +#define QONG_FPGA_IRQ_PIN 8 +#endif + +#endif /* QONG_FPGA_H */ + diff --git a/board/dave/qong/u-boot.lds b/board/dave/qong/u-boot.lds new file mode 100644 index 0000000..1460adc --- /dev/null +++ b/board/dave/qong/u-boot.lds @@ -0,0 +1,59 @@ +/* + * January 2004 - Changed to support H4 device + * Copyright (c) 2004 Texas Instruments + * + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, gj@denx.de + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ + . = 0x00000000; + + . = ALIGN(4); + .text : + { + cpu/arm1136/start.o (.text) + *(.text) + } + + . = ALIGN(4); + .rodata : { *(.rodata) } + + . = ALIGN(4); + .data : { *(.data) } + + . = ALIGN(4); + .got : { *(.got) } + + . = .; + __u_boot_cmd_start = .; + .u_boot_cmd : { *(.u_boot_cmd) } + __u_boot_cmd_end = .; + + . = ALIGN(4); + __bss_start = .; + .bss : { *(.bss) } + _end = .; +} diff --git a/include/configs/qong.h b/include/configs/qong.h new file mode 100644 index 0000000..8fae342 --- /dev/null +++ b/include/configs/qong.h @@ -0,0 +1,213 @@ +/* + * Copyright (C) 2009, Ilya Yanok, Emcraft Systems, yanok@emcraft.com + * + * Configuration settings for the Dave/DENX QongEVB-LITE board. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef __CONFIG_H +#define __CONFIG_H + +#include <asm/arch/mx31-regs.h> +#include <asm/sizes.h> + + /* High Level Configuration Options */ +#define CONFIG_ARM1136 1 /* This is an arm1136 CPU core */ +#define CONFIG_MX31 1 /* in a mx31 */ +#define CONFIG_QONG 1 +#define CONFIG_MX31_HCLK_FREQ 26000000 /* 26MHz */ +#define CONFIG_MX31_CLK32 32768 + +#define CONFIG_DISPLAY_CPUINFO +#define CONFIG_DISPLAY_BOARDINFO + +#define CONFIG_CMDLINE_TAG 1 /* enable passing of ATAGs */ +#define CONFIG_SETUP_MEMORY_TAGS 1 +#define CONFIG_INITRD_TAG 1 + +/* + * Size of malloc() pool + */ +#define CONFIG_SYS_MALLOC_LEN (CONFIG_ENV_SIZE + 128 * 1024) +/* size in bytes reserved for initial data */ +#define CONFIG_SYS_GBL_DATA_SIZE 128 + +/* + * Hardware drivers + */ + +#define CONFIG_MX31_UART 1 +#define CONFIG_SYS_MX31_UART1 1 + +/* FPGA */ +#define CONFIG_QONG_FPGA 1 +#define CONFIG_FPGA_BASE (CS1_BASE) + +#ifdef CONFIG_QONG_FPGA +/* Ethernet */ +#define CONFIG_DRIVER_DNET 1 +#define CONFIG_DNET_BASE (CS1_BASE + QONG_FPGA_PERIPH_SIZE) +#define CONFIG_NET_MULTI 1 + +/* + * Reducing the ARP timeout from default 5 seconds to 200ms we speed up the + * initial TFTP transfer, should the user wish one, significantly. + */ +#define CONFIG_ARP_TIMEOUT 200UL + +#endif /* CONFIG_QONG_FPGA */ + +/* allow to overwrite serial and ethaddr */ +#define CONFIG_ENV_OVERWRITE +#define CONFIG_CONS_INDEX 1 +#define CONFIG_BAUDRATE 115200 +#define CONFIG_SYS_BAUDRATE_TABLE {9600, 19200, 38400, 57600, 115200} + +/*********************************************************** + * Command definition + ***********************************************************/ + +#include <config_cmd_default.h> + +#define CONFIG_CMD_PING +#define CONFIG_CMD_DHCP +#define CONFIG_CMD_NET +#define CONFIG_CMD_MII + +#define CONFIG_ETHADDR 00:50:c2:1e:af:e7 +#define CONFIG_NETMASK 255.255.0.0 +#define CONFIG_IPADDR 192.168.0.81 +#define CONFIG_SERVERIP 192.168.1.1 +#define CONFIG_GATEWAYIP 192.168.1.1 + +#define CONFIG_BOOTDELAY 3 + +#define CONFIG_LOADADDR 0x80800000 /* loadaddr env var */ + +#define xstr(s) str(s) +#define str(s) #s + +#define CONFIG_EXTRA_ENV_SETTINGS \ + "netdev=eth0\0" \ + "nfsargs=setenv bootargs root=/dev/nfs rw " \ + "nfsroot=${serverip}:${rootpath}\0" \ + "ramargs=setenv bootargs root=/dev/ram rw\0" \ + "addip=setenv bootargs ${bootargs} " \ + "ip=${ipaddr}:${serverip}:${gatewayip}:${netmask}" \ + ":${hostname}:${netdev}:off panic=1\0" \ + "addtty=setenv bootargs ${bootargs}" \ + " console=ttymxc0,${baudrate}\0" \ + "addmisc=setenv bootargs ${bootargs}\0" \ + "uboot_addr=0xa0000000\0" \ + "uboot=qong/u-boot.bin\0" \ + "kernel_addr_r=0x80800000\0" \ + "hostname=qong\0" \ + "bootfile=qong/uImage\0" \ + "rootpath=/opt/eldk-4.2-arm/armVFP\0" \ + "flash_self=run ramargs addip addtty addmisc;" \ + "bootm ${kernel_addr} ${ramdisk_addr}\0" \ + "flash_nfs=run nfsargs addip addtty addmisc;" \ + "bootm ${kernel_addr}\0" \ + "net_nfs=tftp ${kernel_addr_r} ${bootfile};" \ + "run nfsargs addip addtty addmisc;" \ + "bootm ${kernel_addr_r}\0" \ + "load=tftp ${loadaddr} ${uboot}\0" \ + "update=protect off " xstr(CONFIG_SYS_MONITOR_BASE) " +" \ + xstr(CONFIG_SYS_MONITOR_LEN)";" \ + "era " xstr(CONFIG_SYS_MONITOR_BASE) " +" \ + xstr(CONFIG_SYS_MONITOR_LEN)";" \ + "cp.b ${fileaddr} " xstr(CONFIG_SYS_MONITOR_BASE) \ + " ${filesize};" \ + "setenv filesize;saveenv\0" \ + "upd=run load update\0" \ + +/* + * Miscellaneous configurable options + */ +#define CONFIG_SYS_LONGHELP /* undef to save memory */ +#define CONFIG_SYS_PROMPT "=> " +#define CONFIG_SYS_CBSIZE 256 /* Console I/O Buffer Size */ +/* Print Buffer Size */ +#define CONFIG_SYS_PBSIZE (CONFIG_SYS_CBSIZE + \ + sizeof(CONFIG_SYS_PROMPT) + 16) +#define CONFIG_SYS_MAXARGS 16 /* max number of command args */ +/* Boot Argument Buffer Size */ +#define CONFIG_SYS_BARGSIZE CONFIG_SYS_CBSIZE + +#define CONFIG_SYS_MEMTEST_START 0 /* memtest works on */ +#define CONFIG_SYS_MEMTEST_END 0x10000 + +#define CONFIG_SYS_LOAD_ADDR CONFIG_LOADADDR + +#define CONFIG_SYS_HZ 1000 + +#define CONFIG_CMDLINE_EDITING 1 + +#define CONFIG_MISC_INIT_R 1 +/*----------------------------------------------------------------------- + * Stack sizes + * + * The stack sizes are set up in start.S using the settings below + */ +#define CONFIG_STACKSIZE (128 * 1024) /* regular stack */ + +/*----------------------------------------------------------------------- + * Physical Memory Map + */ +#define CONFIG_NR_DRAM_BANKS 1 +#define PHYS_SDRAM_1 CSD0_BASE +#define PHYS_SDRAM_1_SIZE SZ_256M + +/*----------------------------------------------------------------------- + * FLASH and environment organization + */ +#define CONFIG_SYS_FLASH_BASE CS0_BASE +#define CONFIG_SYS_MAX_FLASH_BANKS 1 /* max number of memory banks */ +/* max number of sectors on one chip */ +#define CONFIG_SYS_MAX_FLASH_SECT 1024 +/* Monitor at beginning of flash */ +#define CONFIG_SYS_MONITOR_BASE CONFIG_SYS_FLASH_BASE +#define CONFIG_SYS_MONITOR_LEN 0x40000 /* Reserve 256KiB */ + +#define CONFIG_ENV_IS_IN_FLASH 1 +#define CONFIG_ENV_SECT_SIZE SZ_128K +#define CONFIG_ENV_SIZE CONFIG_ENV_SECT_SIZE +#define CONFIG_ENV_ADDR (CONFIG_SYS_FLASH_BASE+(2*SZ_128K)) + +/* Address and size of Redundant Environment Sector */ +#define CONFIG_ENV_OFFSET_REDUND (CONFIG_ENV_OFFSET + CONFIG_ENV_SIZE) +#define CONFIG_ENV_SIZE_REDUND CONFIG_ENV_SIZE + +/*----------------------------------------------------------------------- + * CFI FLASH driver setup + */ +/* Flash memory is CFI compliant */ +#define CONFIG_SYS_FLASH_CFI 1 +/* Use drivers/cfi_flash.c */ +#define CONFIG_FLASH_CFI_DRIVER 1 +/* Use buffered writes (~10x faster) */ +#define CONFIG_SYS_FLASH_USE_BUFFER_WRITE 1 +/* Use hardware sector protection */ +#define CONFIG_SYS_FLASH_PROTECTION 1 + +/* + * JFFS2 partitions + */ +#undef CONFIG_JFFS2_CMDLINE +#define CONFIG_JFFS2_DEV "nor0" + +#endif /* __CONFIG_H */

Dear Ilya Yanok,
In message 1233589490-14293-4-git-send-email-yanok@emcraft.com you wrote:
This patch adds support for Dave/DENX QongEVB-LITE i.MX31-based board.
Signed-off-by: Ilya Yanok yanok@emcraft.com
...
board/dave/qong/Makefile | 51 +++++++++ board/dave/qong/config.mk | 1 + board/dave/qong/lowlevel_init.S | 170 +++++++++++++++++++++++++++++++ board/dave/qong/qong.c | 167 ++++++++++++++++++++++++++++++ board/dave/qong/qong_fpga.h | 41 ++++++++ board/dave/qong/u-boot.lds | 59 +++++++++++
The vendor name should be "davedenx", thus the directory name should be board/davedenx/qong/, please.
diff --git a/board/dave/qong/qong.c b/board/dave/qong/qong.c new file mode 100644 index 0000000..5d12a13 --- /dev/null +++ b/board/dave/qong/qong.c @@ -0,0 +1,167 @@
...
+int dram_init (void) +{
- gd->bd->bi_dram[0].start = PHYS_SDRAM_1;
- gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE;
- return 0;
+}
Why do we not auto-size the RAM here like U-Boot is supposed to do?
diff --git a/board/dave/qong/u-boot.lds b/board/dave/qong/u-boot.lds new file mode 100644 index 0000000..1460adc --- /dev/null +++ b/board/dave/qong/u-boot.lds @@ -0,0 +1,59 @@ +/*
- January 2004 - Changed to support H4 device
- Copyright (c) 2004 Texas Instruments
Are you sure this is an appropriate comment for this file?
diff --git a/include/configs/qong.h b/include/configs/qong.h new file mode 100644 index 0000000..8fae342 --- /dev/null +++ b/include/configs/qong.h
...
+/*
- Reducing the ARP timeout from default 5 seconds to 200ms we speed up the
- initial TFTP transfer, should the user wish one, significantly.
- */
+#define CONFIG_ARP_TIMEOUT 200UL
Is this really necessary on this hardware?
+/* allow to overwrite serial and ethaddr */ +#define CONFIG_ENV_OVERWRITE
Please don't.
+/***********************************************************
- Command definition
- ***********************************************************/
+#include <config_cmd_default.h>
+#define CONFIG_CMD_PING +#define CONFIG_CMD_DHCP +#define CONFIG_CMD_NET +#define CONFIG_CMD_MII
+#define CONFIG_ETHADDR 00:50:c2:1e:af:e7 +#define CONFIG_NETMASK 255.255.0.0 +#define CONFIG_IPADDR 192.168.0.81 +#define CONFIG_SERVERIP 192.168.1.1 +#define CONFIG_GATEWAYIP 192.168.1.1
Please never, never ever hardcode any network configuration into U-Boot. Delete this, please.
And please add image timestamp support.
+#define CONFIG_BOOTDELAY 3
Make this standard 5 seconds, please.
+#define CONFIG_EXTRA_ENV_SETTINGS \
- "netdev=eth0\0" \
- "nfsargs=setenv bootargs root=/dev/nfs rw " \
"nfsroot=${serverip}:${rootpath}\0" \
- "ramargs=setenv bootargs root=/dev/ram rw\0" \
- "addip=setenv bootargs ${bootargs} " \
"ip=${ipaddr}:${serverip}:${gatewayip}:${netmask}" \
":${hostname}:${netdev}:off panic=1\0" \
- "addtty=setenv bootargs ${bootargs}" \
" console=ttymxc0,${baudrate}\0" \
- "addmisc=setenv bootargs ${bootargs}\0" \
- "uboot_addr=0xa0000000\0" \
--------------------^^
- "uboot=qong/u-boot.bin\0" \
- "kernel_addr_r=0x80800000\0" \
-----------------------^^
No need for 0x prefix.
- "hostname=qong\0" \
- "bootfile=qong/uImage\0" \
- "rootpath=/opt/eldk-4.2-arm/armVFP\0" \
- "flash_self=run ramargs addip addtty addmisc;" \
"bootm ${kernel_addr} ${ramdisk_addr}\0" \
- "flash_nfs=run nfsargs addip addtty addmisc;" \
"bootm ${kernel_addr}\0" \
- "net_nfs=tftp ${kernel_addr_r} ${bootfile};" \
"run nfsargs addip addtty addmisc;" \
"bootm ${kernel_addr_r}\0" \
Pleain "bootm" would do as well.
- "load=tftp ${loadaddr} ${uboot}\0" \
- "update=protect off " xstr(CONFIG_SYS_MONITOR_BASE) " +" \
xstr(CONFIG_SYS_MONITOR_LEN)";" \
----------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^
"era " xstr(CONFIG_SYS_MONITOR_BASE) " +" \
xstr(CONFIG_SYS_MONITOR_LEN)";" \
----------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Please use "+${filesize}" instead.
+#define CONFIG_SYS_PBSIZE (CONFIG_SYS_CBSIZE + \
sizeof(CONFIG_SYS_PROMPT) + 16)
+#define CONFIG_SYS_MAXARGS 16 /* max number of command args */
32 ?
+#define CONFIG_SYS_MEMTEST_START 0 /* memtest works on */ +#define CONFIG_SYS_MEMTEST_END 0x10000
Hm... tha RAM test operates on the first 64 kB of flash memory? Or am I missing something?
+#define CONFIG_ENV_IS_IN_FLASH 1 +#define CONFIG_ENV_SECT_SIZE SZ_128K
Please do not use any of these funny "SZ_" definitions. These shall be removed ASAP.
+#define CONFIG_ENV_SIZE CONFIG_ENV_SECT_SIZE +#define CONFIG_ENV_ADDR (CONFIG_SYS_FLASH_BASE+(2*SZ_128K))
Ditto.
+/*
- JFFS2 partitions
- */
+#undef CONFIG_JFFS2_CMDLINE
Why?
Best regards,
Wolfgang Denk

Dear Wolfgang,
Wolfgang Denk wrote:
+/*
- Reducing the ARP timeout from default 5 seconds to 200ms we speed up the
- initial TFTP transfer, should the user wish one, significantly.
- */
+#define CONFIG_ARP_TIMEOUT 200UL
Is this really necessary on this hardware?
Yes. I get a timeout during first tftp transfer without this.
Regards, Ilya.
participants (3)
-
Ben Warren
-
Ilya Yanok
-
Wolfgang Denk