U-Boot
Threads by month
- ----- 2025 -----
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2002 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2001 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2000 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
February 2012
- 160 participants
- 492 discussions

[U-Boot] [PATCH v4 0/6] Run-time configuration of U-Boot via a flat device tree (fdt)
by Simon Glass 12 Apr '12
by Simon Glass 12 Apr '12
12 Apr '12
At present in U-Boot configuration is mostly done using CONFIG options in the
board file. This patch set makes it possible for a single U-Boot binary to
support multiple boards, with the exact configuration of each board
controlled by a flat device tree (fdt). This is the approach recently taken
by the ARM Linux kernel and has been used by PowerPC for some time.
In other words, manufacturers can potentially use a single U-Boot binary
across an entire product line, with one fdt per model.
The fdt is a convenient vehicle for implementing run-time configuration for
three reasons. Firstly it is easy to use, being a simple text file. It is
extensible since it consists of nodes and properties in a nice hierarchical
format.
Finally, there is already excellent infrastructure for the fdt: a compiler
checks the text file and converts it to a compact binary format, and a library
is already available in U-Boot (libfdt) for handling this format.
To read about fdts, take a look at the specification here:
https://www.power.org/resources/downloads/Power_ePAPR_APPROVED_v1.0.pdf
You also might find this section of the Linux kernel documentation useful:
(access this in the Linux kernel source code)
Documentation/devicetree/booting-without-of.txt
To use this patch set you will need to get the device tree compiler here:
git://jdl.com/software/dtc.git
and add some defines to your board (only ARM is currently supported):
#define CONFIG_OF_CONTROL (to enable run-time config control via fdt)
#define CONFIG_OF_EMBED or CONFIG_OF_SEPARATE
(either build the fdt blob into U-Boot, or create a separate u-boot.dtb
and u-boot-dtb.bin)
#define CONFIG_DEFAULT_DEVICE_TREE "<your name>"
(to specify the name of the device tree file is
board/<vendor>/dts/<your name>.dts)
Typically a CPU device tree include file is provided which defines all the
devices available on that CPU/SOC, with each set to 'status = "ok"'.
Board device tree files should adjust only the devices they need to. If a
device should be disabled, then it should be changed to
'status = 'disabled"' to indicate this. To facilitate this, a CPU/SOC device
tree header is supported in arch/<arch>/dts. The name of this is defined by
CONFIG_ARCH_DEVICE_TREE, typically defined in arch/<arch>/cpu/.../config.mk.
You can use the following line within the board device tree file to include
this header:
/include/ ARCH_CPU_DTS
For example, for Tegra2 we might have in arch/arm/cpu/armv7/tegra2/config.mk
these lines:
CONFIG_ARCH_DEVICE_TREE := tegra20
This means that ARCH_CPU_DTS will point to arch/arm/dts/tegra20.dtsi.
This patch set does not include any drivers which actually use the fdt, but
there is a basic fdt decode library (fdtdec) to simplify this process. I
have provided an example i2c implementation previously:
http://patchwork.ozlabs.org/patch/114425/
It is important to understand that the fdt only selects options available in
the platform / drivers. It cannot add new drivers (yet). So you must still
have the CONFIG option to enable the driver. For example, you need to define
CONFIG_SYS_NS16550 to bring in the NS16550 driver, but can use the fdt to
specific the UART clock, peripheral address, etc. In very broad terms, the
CONFIG options in general control *what* driver files are pulled in, and the
fdt controls *how* those files work.
While only ARM is supported in this patch series, it should be easy enough to
add support for other architectures.
I experimented with using dtc's asm output to avoid all the arch/oformat
ugliness in dts/Makefile as suggested by Stephen Warren
<swarren(a)nvidia.com>. This simplified the Makefile commands greatly by
removing the need to detect the output format and architecture. However
Grant Likely <grant.likely(a)secretlab.ca> explained that this feature is
not well tested and still has some big-endian-ims in it.
Changes in v2:
- Modify Makefile to create combined U-boot/fdt (u-boot-dtb.bin)
- Add example proposed decode helper library
Changes in v3:
- Rename gd->blob to gd->fdt_blob
- Move fdt files into board/<vendor>/dts
- Provide access to ARCH_CPU_DTS which is the CPU's base device tree
- Add fdtcontroladdr environment variable
- Simplify decode library to remove provide only primitive functions
- Remove i2c decode function
- Rename fdt_decode to fdtdec, since it will be used a lot
- Moved fdt_decode.c to /lib
- Export almost all functions from fdtdec, to allow widespread use
- Remove use of FDT_ERR_MISSING which is not strictly needed now
Changes in v4:
- Fix reference to gd->blob which should be gd->fdt_blob
- Remove unused 'clean' targets in dts/Makefile (remmove *.tmp at top-level)
- Move documentation into the first 'fdt' patch in the series
- Add note about CONFIG_ARCH_DEVICE_TREE
- Add assert on sprintf() string length
- Rename addr_t to fdt_addr_t to make it more fdt-specific
- Remove gpio.h header in fdtdec.c which is not needed yet
Simon Glass (6):
fdt: ARM: Add device tree control of U-Boot (CONFIG_OF_CONTROL)
fdt: Add support for embedded device tree (CONFIG_OF_EMBED)
fdt: Add support for a separate device tree (CONFIG_OF_SEPARATE)
fdt: ARM: Implement and verify embedded and separate device tree
fdt: ARM: Add fdtcontroladdr to set device tree address in
environment
fdt: add decode helper library
.gitignore | 1 +
Makefile | 13 +++
README | 34 +++++++
arch/arm/include/asm/global_data.h | 1 +
arch/arm/lib/board.c | 52 +++++++++--
config.mk | 1 +
doc/README.fdt-control | 184 ++++++++++++++++++++++++++++++++++++
dts/Makefile | 103 ++++++++++++++++++++
include/common.h | 1 +
include/fdtdec.h | 122 ++++++++++++++++++++++++
lib/Makefile | 1 +
lib/fdtdec.c | 131 +++++++++++++++++++++++++
12 files changed, 637 insertions(+), 7 deletions(-)
create mode 100644 doc/README.fdt-control
create mode 100644 dts/Makefile
create mode 100644 include/fdtdec.h
create mode 100644 lib/fdtdec.c
--
1.7.3.1
5
16
Dear Wolfgang,
The following changes since commit 2acca35ce4604dcef933f07d90aa9c9c930e1049:
Merge branch 'master' of git://git.denx.de/u-boot-mmc (2012-02-17 23:54:46 +0100)
are available in the git repository at:
git://git.denx.de/u-boot-nios.git master
Alex Hornung (2):
nios2: implement get_ticks and get_tbclk
nios2 - adjust gbl data off to account for bd_info
Stefan Kristiansson (1):
nios2: add flush_dcache_range function
arch/nios2/cpu/interrupts.c | 21 +++++++++++++++++++++
arch/nios2/lib/cache.S | 10 ++++++++++
include/configs/nios2-generic.h | 3 ++-
3 files changed, 33 insertions(+), 1 deletions(-)
3
6

04 Apr '12
Xilinx LocalLink Tri-Mode Ether MAC driver can be
used by Xilinx Microblaze or Xilinx ppc405/440 in
SDMA and FIFO mode. DCR or XPS bus can be used.
The driver uses and requires MII and PHYLIB.
CP: 4 warnings: 'Use of volatile is usually wrong'
I won't fix this, because it depends on the network
driver subsystem.
Reported-by: Michal Simek <monstr(a)monstr.eu>
Signed-off-by: Stephan Linz <linz(a)li-pro.net>
---
v10: Reduce the driver initialization code. Remove the standardized
initialization routine and all components involved.
Generate unique device/bus names automaticaly on demand.
v9: Remove private Rx/Tx transfer buffer for SDMA and FIFO.
Use the PktBuf infrastruct from upper network layer.
Review all the recv/send functions for SDMA and FIFO mode
and insert more detailed comments.
Test with tftp put/get on ML605 and SP3ADSP1800.
v8: Remove deprecated interface: miiphy_register()
Implement MDIO bus/phy access code as independent part of driver.
Make the direct PHY access code accessible for upper layer like
the MDIO command.
Define proper device names for TEMAC and MII interfaces.
Support of TEMAC0 and TEMAC1 at same time is prepared and should
work.
v7: Call udelay() in polling loops to avoid unintended watchdog reset
Define well known timeout values in usec
Handle timeouts as error situations
Reduce duplicated code in SDMA operations
Add a real and plausible PHY detect mask
Remove ETH_HALTING code exclusion
Code cleanup as recommended
Fix typos
v6: Code cleanup with ./tools/checkpatch.pl
v5: Remove more endless loops
Remove useless parenthesis in pointer operations
Move phyaddr predefinition on top
Remove supernumerary newlines
Remove parenthesis around numbers (globally)
v4: Separate fifo and sdma code from driver core
Split sdma code into separate DCR and XPS bus access code
Add extensive register struct definitions and enumerations
Add new callbacks into fifo an sdma code
Prepare CDMAC buffer handling to be unique for every instance
Separate Xilinx specific indirect DCR access, so we can move to arch
Remove useless 'emac' parameter from indirect access helper functions
Correct MDIO clock setup.
Remove endless loops
Common code beautifying
v3: Use helper functions for fifo mode
Use helper functions for indirect accesses
Code cleanup
Add comments for MAGIC values
Simplify code in fifo mode
v2: Remove helper function for access to temac
Remove SDMA/FIFO/DCR macros and configure it in board
Setup mac by write_hwaddr
---
drivers/net/Makefile | 2 +
drivers/net/xilinx_ll_temac.c | 399 ++++++++++++++++++++++++++++++++++++
drivers/net/xilinx_ll_temac.h | 310 ++++++++++++++++++++++++++++
drivers/net/xilinx_ll_temac_fifo.c | 143 +++++++++++++
drivers/net/xilinx_ll_temac_fifo.h | 122 +++++++++++
drivers/net/xilinx_ll_temac_mdio.c | 180 ++++++++++++++++
drivers/net/xilinx_ll_temac_mdio.h | 53 +++++
drivers/net/xilinx_ll_temac_sdma.c | 370 +++++++++++++++++++++++++++++++++
drivers/net/xilinx_ll_temac_sdma.h | 281 +++++++++++++++++++++++++
include/netdev.h | 12 +
10 files changed, 1872 insertions(+), 0 deletions(-)
create mode 100644 drivers/net/xilinx_ll_temac.c
create mode 100644 drivers/net/xilinx_ll_temac.h
create mode 100644 drivers/net/xilinx_ll_temac_fifo.c
create mode 100644 drivers/net/xilinx_ll_temac_fifo.h
create mode 100644 drivers/net/xilinx_ll_temac_mdio.c
create mode 100644 drivers/net/xilinx_ll_temac_mdio.h
create mode 100644 drivers/net/xilinx_ll_temac_sdma.c
create mode 100644 drivers/net/xilinx_ll_temac_sdma.h
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index f4f7ea3..430f90c 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -77,6 +77,8 @@ COBJS-$(CONFIG_ULI526X) += uli526x.o
COBJS-$(CONFIG_VSC7385_ENET) += vsc7385.o
COBJS-$(CONFIG_XILINX_AXIEMAC) += xilinx_axi_emac.o
COBJS-$(CONFIG_XILINX_EMACLITE) += xilinx_emaclite.o
+COBJS-$(CONFIG_XILINX_LL_TEMAC) += xilinx_ll_temac.o xilinx_ll_temac_mdio.o \
+ xilinx_ll_temac_fifo.o xilinx_ll_temac_sdma.o
COBJS := $(sort $(COBJS-y))
SRCS := $(COBJS:.o=.c)
diff --git a/drivers/net/xilinx_ll_temac.c b/drivers/net/xilinx_ll_temac.c
new file mode 100644
index 0000000..85660c0
--- /dev/null
+++ b/drivers/net/xilinx_ll_temac.c
@@ -0,0 +1,399 @@
+/*
+ * Xilinx xps_ll_temac ethernet driver for u-boot
+ *
+ * supports SDMA or FIFO access and MDIO bus communication
+ *
+ * Copyright (C) 2011 - 2012 Stephan Linz <linz(a)li-pro.net>
+ * Copyright (C) 2008 - 2011 Michal Simek <monstr(a)monstr.eu>
+ * Copyright (C) 2008 - 2011 PetaLogix
+ *
+ * Based on Yoshio Kashiwagi kashiwagi(a)co-nss.co.jp driver
+ * Copyright (C) 2008 Nissin Systems Co.,Ltd.
+ * March 2008 created
+ *
+ * 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.
+ *
+ * [0]: http://www.xilinx.com/support/documentation
+ *
+ * [S]: [0]/ip_documentation/xps_ll_temac.pdf
+ * [A]: [0]/application_notes/xapp1041.pdf
+ */
+
+#include <config.h>
+#include <common.h>
+#include <net.h>
+#include <netdev.h>
+#include <malloc.h>
+#include <asm/io.h>
+#include <miiphy.h>
+
+#include "xilinx_ll_temac.h"
+#include "xilinx_ll_temac_fifo.h"
+#include "xilinx_ll_temac_sdma.h"
+#include "xilinx_ll_temac_mdio.h"
+
+#if !defined(CONFIG_MII)
+# error "LL_TEMAC requires MII -- missing CONFIG_MII"
+#endif
+
+#if !defined(CONFIG_PHYLIB)
+# error "LL_TEMAC requires PHYLIB -- missing CONFIG_PHYLIB"
+#endif
+
+struct ll_temac_info {
+ int flags;
+ unsigned long base_addr;
+ unsigned long ctrl_addr;
+ char *devname;
+ unsigned int phyaddr;
+ char *mdio_busname;
+};
+
+/* Ethernet interface ready status */
+int ll_temac_check_status(struct temac_reg *regs, u32 mask)
+{
+ unsigned timeout = 50; /* 1usec * 50 = 50usec */
+
+ /*
+ * Quote from LL TEMAC documentation: The bits in the RDY
+ * register are asserted when there is no access in progress.
+ * When an access is in progress, a bit corresponding to the
+ * type of access is automatically de-asserted. The bit is
+ * automatically re-asserted when the access is complete.
+ */
+ while (timeout && (!(in_be32(®s->rdy) & mask))) {
+ timeout--;
+ udelay(1);
+ }
+
+ if (!timeout) {
+ printf("%s: Timeout on 0x%08x @%p\n", __func__,
+ mask, ®s->rdy);
+ return 1;
+ }
+
+ return 0;
+}
+
+/*
+ * Indirect write to ll_temac.
+ *
+ * http://www.xilinx.com/support/documentation/ip_documentation/xps_ll_temac.p…
+ * page 23, second paragraph, The use of CTL0 register or CTL1 register
+ */
+int ll_temac_indirect_set(struct temac_reg *regs, u16 regn, u32 reg_data)
+{
+ out_be32(®s->lsw, (reg_data & MLSW_MASK));
+ out_be32(®s->ctl, CTL_WEN | (regn & CTL_ADDR_MASK));
+
+ if (ll_temac_check_status(regs, RSE_CFG_WR))
+ return 0;
+
+ return 1;
+}
+
+/*
+ * Indirect read from ll_temac.
+ *
+ * http://www.xilinx.com/support/documentation/ip_documentation/xps_ll_temac.p…
+ * page 23, second paragraph, The use of CTL0 register or CTL1 register
+ */
+int ll_temac_indirect_get(struct temac_reg *regs, u16 regn, u32* reg_data)
+{
+ out_be32(®s->ctl, (regn & CTL_ADDR_MASK));
+
+ if (ll_temac_check_status(regs, RSE_CFG_RR))
+ return 0;
+
+ *reg_data = in_be32(®s->lsw) & MLSW_MASK;
+ return 1;
+}
+
+/* setting sub-controller and ll_temac to proper setting */
+static int ll_temac_setup_ctrl(struct eth_device *dev)
+{
+ struct ll_temac *ll_temac = dev->priv;
+ struct temac_reg *regs = (struct temac_reg *)dev->iobase;
+
+ if (ll_temac->ctrlreset && ll_temac->ctrlreset(dev))
+ return 0;
+
+ if (ll_temac->ctrlinit && ll_temac->ctrlinit(dev))
+ return 0;
+
+ /* Promiscuous mode disable */
+ if (!ll_temac_indirect_set(regs, TEMAC_AFM, 0))
+ return 0;
+
+ /* Enable Receiver - RX bit */
+ if (!ll_temac_indirect_set(regs, TEMAC_RCW1, RCW1_RX))
+ return 0;
+
+ /* Enable Transmitter - TX bit */
+ if (!ll_temac_indirect_set(regs, TEMAC_TC, TC_TX))
+ return 0;
+
+ return 1;
+}
+
+/*
+ * Configure ll_temac based on negotiated speed and duplex
+ * reported by PHY handling code
+ */
+static int ll_temac_adjust_link(struct eth_device *dev)
+{
+ unsigned int speed, emmc_reg;
+ struct temac_reg *regs = (struct temac_reg *)dev->iobase;
+ struct ll_temac *ll_temac = dev->priv;
+ struct phy_device *phydev = ll_temac->phydev;
+
+ if (!phydev->link) {
+ printf("%s: No link.\n", phydev->dev->name);
+ return 0;
+ }
+
+ switch (phydev->speed) {
+ case 1000:
+ speed = EMMC_LSPD_1000;
+ break;
+ case 100:
+ speed = EMMC_LSPD_100;
+ break;
+ case 10:
+ speed = EMMC_LSPD_10;
+ break;
+ default:
+ return 0;
+ }
+
+ if (!ll_temac_indirect_get(regs, TEMAC_EMMC, &emmc_reg))
+ return 0;
+
+ emmc_reg &= ~EMMC_LSPD_MASK;
+ emmc_reg |= speed;
+
+ if (!ll_temac_indirect_set(regs, TEMAC_EMMC, emmc_reg))
+ return 0;
+
+ printf("%s: PHY is %s with %dbase%s, %s%s\n",
+ dev->name, phydev->drv->name,
+ phydev->speed, (phydev->port == PORT_TP) ? "T" : "X",
+ (phydev->duplex) ? "FDX" : "HDX",
+ (phydev->port == PORT_OTHER) ? ", unkown mode" : "");
+
+ return 1;
+}
+
+/* setup mac addr */
+static int ll_temac_setup_mac_addr(struct eth_device *dev)
+{
+ struct temac_reg *regs = (struct temac_reg *)dev->iobase;
+ u32 val;
+
+ /* set up unicast MAC address filter */
+ val = ((dev->enetaddr[3] << 24) | (dev->enetaddr[2] << 16) |
+ (dev->enetaddr[1] << 8) | (dev->enetaddr[0]));
+ val &= UAW0_UADDR_MASK;
+
+ if (!ll_temac_indirect_set(regs, TEMAC_UAW0, val))
+ return 1;
+
+ val = ((dev->enetaddr[5] << 8) | dev->enetaddr[4]);
+ val &= UAW1_UADDR_MASK;
+
+ if (!ll_temac_indirect_set(regs, TEMAC_UAW1, val))
+ return 1;
+
+ return 0;
+}
+
+/* halt device */
+static void ll_temac_halt(struct eth_device *dev)
+{
+ struct ll_temac *ll_temac = dev->priv;
+ struct temac_reg *regs = (struct temac_reg *)dev->iobase;
+
+ /* Disable Receiver */
+ ll_temac_indirect_set(regs, TEMAC_RCW0, 0);
+
+ /* Disable Transmitter */
+ ll_temac_indirect_set(regs, TEMAC_TC, 0);
+
+ if (ll_temac->ctrlhalt)
+ ll_temac->ctrlhalt(dev);
+
+ /* Shut down the PHY, as needed */
+ phy_shutdown(ll_temac->phydev);
+}
+
+static int ll_temac_init(struct eth_device *dev, bd_t *bis)
+{
+ struct ll_temac *ll_temac = dev->priv;
+
+ printf("%s: Xilinx XPS LocalLink Tri-Mode Ether MAC #%d at 0x%08X.\n",
+ dev->name, dev->index, dev->iobase);
+
+ if (!ll_temac_setup_ctrl(dev))
+ return -1;
+
+ /* Start up the PHY */
+ phy_startup(ll_temac->phydev);
+
+ if (!ll_temac_adjust_link(dev)) {
+ ll_temac_halt(dev);
+ return -1;
+ }
+
+ /* If there's no link, fail */
+ return ll_temac->phydev->link ? 0 : -1;
+}
+
+/*
+ * Discover which PHY is attached to the device, and configure it
+ * properly. If the PHY is not recognized, then return 0
+ * (failure). Otherwise, return 1
+ */
+static int ll_temac_phy_init(struct eth_device *dev)
+{
+ struct ll_temac *ll_temac = dev->priv;
+ struct phy_device *phydev;
+ unsigned int supported = PHY_GBIT_FEATURES;
+
+ /* interface - look at driver/net/tsec.c */
+ phydev = phy_connect(ll_temac->bus, ll_temac->phyaddr,
+ dev, PHY_INTERFACE_MODE_NONE);
+
+ phydev->supported &= supported;
+ phydev->advertising = phydev->supported;
+
+ ll_temac->phydev = phydev;
+
+ phy_config(phydev);
+
+ return 1;
+}
+
+/*
+ * Initialize a single ll_temac devices
+ *
+ * Returns the result of ll_temac phy interface that were initialized
+ */
+int xilinx_ll_temac_initialize(bd_t *bis, struct ll_temac_info *devinf)
+{
+ struct eth_device *dev;
+ struct ll_temac *ll_temac;
+
+ dev = calloc(1, sizeof(*dev));
+ if (dev == NULL)
+ return 0;
+
+ ll_temac = calloc(1, sizeof(struct ll_temac));
+ if (ll_temac == NULL) {
+ free(dev);
+ return 0;
+ }
+
+ /* use given name or generate its own unique name */
+ if (devinf->devname) {
+ strncpy(dev->name, devinf->devname, NAMESIZE);
+ } else {
+ snprintf(dev->name, NAMESIZE, "lltemac.%lx", devinf->base_addr);
+ devinf->devname = dev->name;
+ }
+
+ dev->iobase = devinf->base_addr;
+
+ dev->priv = ll_temac;
+ dev->init = ll_temac_init;
+ dev->halt = ll_temac_halt;
+ dev->write_hwaddr = ll_temac_setup_mac_addr;
+
+ ll_temac->ctrladdr = devinf->ctrl_addr;
+ if (devinf->flags & XILINX_LL_TEMAC_M_SDMA_PLB) {
+#if defined(CONFIG_XILINX_440) || defined(CONFIG_XILINX_405)
+ if (devinf->flags & XILINX_LL_TEMAC_M_SDMA_DCR) {
+ ll_temac_collect_xldcr_sdma_reg_addr(dev);
+ ll_temac->in32 = ll_temac_xldcr_in32;
+ ll_temac->out32 = ll_temac_xldcr_out32;
+ } else
+#endif
+ {
+ ll_temac_collect_xlplb_sdma_reg_addr(dev);
+ ll_temac->in32 = ll_temac_xlplb_in32;
+ ll_temac->out32 = ll_temac_xlplb_out32;
+ }
+ ll_temac->ctrlinit = ll_temac_init_sdma;
+ ll_temac->ctrlhalt = ll_temac_halt_sdma;
+ ll_temac->ctrlreset = ll_temac_reset_sdma;
+ dev->recv = ll_temac_recv_sdma;
+ dev->send = ll_temac_send_sdma;
+ } else {
+ ll_temac->in32 = NULL;
+ ll_temac->out32 = NULL;
+ ll_temac->ctrlinit = NULL;
+ ll_temac->ctrlhalt = NULL;
+ ll_temac->ctrlreset = ll_temac_reset_fifo;
+ dev->recv = ll_temac_recv_fifo;
+ dev->send = ll_temac_send_fifo;
+ }
+
+ /* Link to specified MDIO bus */
+ strncpy(ll_temac->mdio_busname, devinf->mdio_busname, MDIO_NAME_LEN);
+ ll_temac->bus = miiphy_get_dev_by_name(ll_temac->mdio_busname);
+
+ /* Looking for a valid PHY address if it is not yet set */
+ if (devinf->phyaddr == -1)
+ ll_temac->phyaddr = ll_temac_phy_addr(ll_temac->bus);
+ else
+ ll_temac->phyaddr = devinf->phyaddr;
+
+ eth_register(dev);
+
+ /* Try to initialize PHY here, and return */
+ return ll_temac_phy_init(dev);
+}
+
+/*
+ * Initialize a single ll_temac device with its mdio bus behind ll_temac
+ *
+ * Returns 1 if the ll_temac device and the mdio bus were initialized
+ * otherwise returns 0
+ */
+int xilinx_ll_temac_eth_init(bd_t *bis, unsigned long base_addr, int flags,
+ unsigned long ctrl_addr)
+{
+ struct ll_temac_info devinf;
+ struct ll_temac_mdio_info mdioinf;
+ int ret;
+
+ /* prepare the internal driver informations */
+ devinf.flags = flags;
+ devinf.base_addr = base_addr;
+ devinf.ctrl_addr = ctrl_addr;
+ devinf.devname = NULL;
+ devinf.phyaddr = -1;
+
+ mdioinf.name = devinf.mdio_busname = NULL;
+ mdioinf.regs = (struct temac_reg *)devinf.base_addr;
+
+ ret = xilinx_ll_temac_mdio_initialize(bis, &mdioinf);
+ if (ret >= 0) {
+
+ /*
+ * If there was no MDIO bus name then take over the
+ * new automaticaly generated by the MDIO init code.
+ */
+ if (mdioinf.name != devinf.mdio_busname)
+ devinf.mdio_busname = mdioinf.name;
+
+ ret = xilinx_ll_temac_initialize(bis, &devinf);
+ if (ret > 0)
+ return 1;
+
+ }
+
+ return 0;
+}
diff --git a/drivers/net/xilinx_ll_temac.h b/drivers/net/xilinx_ll_temac.h
new file mode 100644
index 0000000..ece3b60
--- /dev/null
+++ b/drivers/net/xilinx_ll_temac.h
@@ -0,0 +1,310 @@
+/*
+ * Xilinx xps_ll_temac ethernet driver for u-boot
+ *
+ * LL_TEMAC interface
+ *
+ * Copyright (C) 2011 - 2012 Stephan Linz <linz(a)li-pro.net>
+ * Copyright (C) 2008 - 2011 Michal Simek <monstr(a)monstr.eu>
+ * Copyright (C) 2008 - 2011 PetaLogix
+ *
+ * Based on Yoshio Kashiwagi kashiwagi(a)co-nss.co.jp driver
+ * Copyright (C) 2008 Nissin Systems Co.,Ltd.
+ * March 2008 created
+ *
+ * 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.
+ *
+ * [0]: http://www.xilinx.com/support/documentation
+ *
+ * [S]: [0]/ip_documentation/xps_ll_temac.pdf
+ * [A]: [0]/application_notes/xapp1041.pdf
+ */
+#ifndef _XILINX_LL_TEMAC_
+#define _XILINX_LL_TEMAC_
+
+#include <config.h>
+#include <net.h>
+#include <phy.h>
+#include <miiphy.h>
+
+#include <asm/types.h>
+#include <asm/byteorder.h>
+
+#include "xilinx_ll_temac_sdma.h"
+
+#if !defined(__BIG_ENDIAN)
+# error LL_TEMAC requires big endianess
+#endif
+
+/*
+ * TEMAC Memory and Register Definition
+ *
+ * [1]: [0]/ip_documentation/xps_ll_temac.pdf
+ * page 19, Memory and Register Descriptions
+ */
+struct temac_reg {
+ /* direct soft registers (low part) */
+ u32 raf; /* Reset and Address Filter */
+ u32 tpf; /* Transmit Pause Frame */
+ u32 ifgp; /* Transmit Inter Frame Gap Adjustment */
+ u32 is; /* Interrupt Status */
+ u32 ip; /* Interrupt Pending */
+ u32 ie; /* Interrupt Enable */
+ u32 ttag; /* Transmit VLAN Tag */
+ u32 rtag; /* Receive VLAN Tag */
+ /* hard TEMAC registers */
+ u32 msw; /* Most Significant Word Data */
+ u32 lsw; /* Least Significant Word Data */
+ u32 ctl; /* Control */
+ u32 rdy; /* Ready Status */
+ /* direct soft registers (high part) */
+ u32 uawl; /* Unicast Address Word Lower */
+ u32 uawu; /* Unicast Address Word Upper */
+ u32 tpid0; /* VLAN TPID Word 0 */
+ u32 tpid1; /* VLAN TPID Word 1 */
+};
+
+/* Reset and Address Filter Registers (raf), [1] p25 */
+#define RAF_SR (1 << 13)
+#define RAF_EMFE (1 << 12)
+#define RAF_NFE (1 << 11)
+#define RAF_RVSTM_POS 9
+#define RAF_RVSTM_MASK (3 << RAF_RVSTM_POS)
+#define RAF_TVSTM_POS 7
+#define RAF_TVSTM_MASK (3 << RAF_TVSTM_POS)
+#define RAF_RVTM_POS 5
+#define RAF_RVTM_MASK (3 << RAF_RVTM_POS)
+#define RAF_TVTM_POS 3
+#define RAF_TVTM_MASK (3 << RAF_TVTM_POS)
+#define RAF_BCREJ (1 << 2)
+#define RAF_MCREJ (1 << 1)
+#define RAF_HTRST (1 << 0)
+
+/* Transmit Pause Frame Registers (tpf), [1] p28 */
+#define TPF_TPFV_POS 0
+#define TPF_TPFV_MASK (0xFFFF << TPF_TPFV_POS)
+
+/* Transmit Inter Frame Gap Adjustment Registers (ifgp), [1] p28 */
+#define IFGP_POS 0
+#define IFGP_MASK (0xFF << IFGP_POS)
+
+/* Interrupt Status, Pending, Enable Registers (is, ip, ie), [1] p29-33 */
+#define ISPE_MR (1 << 7)
+#define ISPE_RDL (1 << 6)
+#define ISPE_TC (1 << 5)
+#define ISPE_RFO (1 << 4)
+#define ISPE_RR (1 << 3)
+#define ISPE_RC (1 << 2)
+#define ISPE_AN (1 << 1)
+#define ISPE_HAC (1 << 0)
+
+/* Transmit, Receive VLAN Tag Registers (ttag, rtag), [1] p34-35 */
+#define TRTAG_TPID_POS 16
+#define TRTAG_TPID_MASK (0xFFFF << TRTAG_TPID_POS)
+#define TRTAG_PRIO_POS 13
+#define TRTAG_PRIO_MASK (7 << TRTAG_PRIO_POS)
+#define TRTAG_CFI (1 << 12)
+#define TRTAG_VID_POS 0
+#define TRTAG_VID_MASK (0xFFF << TRTAG_VID_POS)
+
+/* Most, Least Significant Word Data Register (msw, lsw), [1] p46 */
+#define MLSW_POS 0
+#define MLSW_MASK (~0UL << MLSW_POS)
+
+/* LSW Data Register for PHY addresses (lsw), [1] p66 */
+#define LSW_REGAD_POS 0
+#define LSW_REGAD_MASK (0x1F << LSW_REGAD_POS)
+#define LSW_PHYAD_POS 5
+#define LSW_PHYAD_MASK (0x1F << LSW_PHYAD_POS)
+
+/* LSW Data Register for PHY data (lsw), [1] p66 */
+#define LSW_REGDAT_POS 0
+#define LSW_REGDAT_MASK (0xFFFF << LSW_REGDAT_POS)
+
+/* Control Register (ctl), [1] p47 */
+#define CTL_WEN (1 << 15)
+#define CTL_ADDR_POS 0
+#define CTL_ADDR_MASK (0x3FF << CTL_ADDR_POS)
+
+/* Ready Status Register Ethernet (rdy), [1] p48 */
+#define RSE_HACS_RDY (1 << 14)
+#define RSE_CFG_WR (1 << 6)
+#define RSE_CFG_RR (1 << 5)
+#define RSE_AF_WR (1 << 4)
+#define RSE_AF_RR (1 << 3)
+#define RSE_MIIM_WR (1 << 2)
+#define RSE_MIIM_RR (1 << 1)
+#define RSE_FABR_RR (1 << 0)
+
+/* Unicast Address Word Lower, Upper Registers (uawl, uawu), [1] p35-36 */
+#define UAWL_UADDR_POS 0
+#define UAWL_UADDR_MASK (~0UL << UAWL_UADDR_POS)
+#define UAWU_UADDR_POS 0
+#define UAWU_UADDR_MASK (0xFFFF << UAWU_UADDR_POS)
+
+/* VLAN TPID Word 0, 1 Registers (tpid0, tpid1), [1] p37 */
+#define TPID0_V0_POS 0
+#define TPID0_V0_MASK (0xFFFF << TPID0_V0_POS)
+#define TPID0_V1_POS 16
+#define TPID0_V1_MASK (0xFFFF << TPID0_V1_POS)
+#define TPID1_V2_POS 0
+#define TPID1_V2_MASK (0xFFFF << TPID1_V2_POS)
+#define TPID1_V3_POS 16
+#define TPID1_V3_MASK (0xFFFF << TPID1_V3_POS)
+
+/*
+ * TEMAC Indirectly Addressable Register Index Enumeration
+ *
+ * [0]: http://www.xilinx.com/support/documentation
+ *
+ * [1]: [0]/ip_documentation/xps_ll_temac.pdf
+ * page 23, PLB Indirectly Addressable TEMAC Registers
+ */
+enum temac_ctrl {
+ TEMAC_RCW0 = 0x200,
+ TEMAC_RCW1 = 0x240,
+ TEMAC_TC = 0x280,
+ TEMAC_FCC = 0x2C0,
+ TEMAC_EMMC = 0x300,
+ TEMAC_PHYC = 0x320,
+ TEMAC_MC = 0x340,
+ TEMAC_UAW0 = 0x380,
+ TEMAC_UAW1 = 0x384,
+ TEMAC_MAW0 = 0x388,
+ TEMAC_MAW1 = 0x38C,
+ TEMAC_AFM = 0x390,
+ TEMAC_TIS = 0x3A0,
+ TEMAC_TIE = 0x3A4,
+ TEMAC_MIIMWD = 0x3B0,
+ TEMAC_MIIMAI = 0x3B4
+};
+
+/* Receive Configuration Word 0, 1 Registers (RCW0, RCW1), [1] p50-51 */
+#define RCW0_PADDR_POS 0
+#define RCW0_PADDR_MASK (~0UL << RCW_PADDR_POS)
+#define RCW1_RST (1 << 31)
+#define RCW1_JUM (1 << 30)
+#define RCW1_FCS (1 << 29)
+#define RCW1_RX (1 << 28)
+#define RCW1_VLAN (1 << 27)
+#define RCW1_HD (1 << 26)
+#define RCW1_LT_DIS (1 << 25)
+#define RCW1_PADDR_POS 0
+#define RCW1_PADDR_MASK (0xFFFF << RCW_PADDR_POS)
+
+/* Transmit Configuration Registers (TC), [1] p52 */
+#define TC_RST (1 << 31)
+#define TC_JUM (1 << 30)
+#define TC_FCS (1 << 29)
+#define TC_TX (1 << 28)
+#define TC_VLAN (1 << 27)
+#define TC_HD (1 << 26)
+#define TC_IFG (1 << 25)
+
+/* Flow Control Configuration Registers (FCC), [1] p54 */
+#define FCC_FCTX (1 << 30)
+#define FCC_FCRX (1 << 29)
+
+/* Ethernet MAC Mode Configuration Registers (EMMC), [1] p54 */
+#define EMMC_LSPD_POS 30
+#define EMMC_LSPD_MASK (3 << EMMC_LSPD_POS)
+#define EMMC_LSPD_1000 (2 << EMMC_LSPD_POS)
+#define EMMC_LSPD_100 (1 << EMMC_LSPD_POS)
+#define EMMC_LSPD_10 0
+#define EMMC_RGMII (1 << 29)
+#define EMMC_SGMII (1 << 28)
+#define EMMC_GPCS (1 << 27)
+#define EMMC_HOST (1 << 26)
+#define EMMC_TX16 (1 << 25)
+#define EMMC_RX16 (1 << 24)
+
+/* RGMII/SGMII Configuration Registers (PHYC), [1] p56 */
+#define PHYC_SLSPD_POS 30
+#define PHYC_SLSPD_MASK (3 << EMMC_SLSPD_POS)
+#define PHYC_SLSPD_1000 (2 << EMMC_SLSPD_POS)
+#define PHYC_SLSPD_100 (1 << EMMC_SLSPD_POS)
+#define PHYC_SLSPD_10 0
+#define PHYC_RLSPD_POS 2
+#define PHYC_RLSPD_MASK (3 << EMMC_RLSPD_POS)
+#define PHYC_RLSPD_1000 (2 << EMMC_RLSPD_POS)
+#define PHYC_RLSPD_100 (1 << EMMC_RLSPD_POS)
+#define PHYC_RLSPD_10 0
+#define PHYC_RGMII_HD (1 << 1)
+#define PHYC_RGMII_LINK (1 << 0)
+
+/* Management Configuration Registers (MC), [1] p57 */
+#define MC_MDIOEN (1 << 6)
+#define MC_CLKDIV_POS 0
+#define MC_CLKDIV_MASK (0x3F << MC_CLKDIV_POS)
+
+/*
+ * fHOSTCLK fMDC = fHOSTCLK
+ * fMDC = ------------------- ---------> MC_CLKDIV = -------- - 1
+ * (1 + MC_CLKDIV) * 2 2.5 MHz 5MHz
+ */
+#define MC_CLKDIV(f, m) ((f / (2 * m)) - 1)
+#define MC_CLKDIV_25(f) MC_CLKDIV(f, 2500000)
+#define MC_CLKDIV_20(f) MC_CLKDIV(f, 2000000)
+#define MC_CLKDIV_15(f) MC_CLKDIV(f, 1500000)
+#define MC_CLKDIV_10(f) MC_CLKDIV(f, 1000000)
+
+/* Unicast Address Word 0, 1 Registers (UAW0, UAW1), [1] p58-59 */
+#define UAW0_UADDR_POS 0
+#define UAW0_UADDR_MASK (~0UL << UAW0_UADDR_POS)
+#define UAW1_UADDR_POS 0
+#define UAW1_UADDR_MASK (0xFFFF << UAW1_UADDR_POS)
+
+/* Multicast Address Word 0, 1 Registers (MAW0, MAW1), [1] p60 */
+#define MAW0_MADDR_POS 0
+#define MAW0_MADDR_MASK (~0UL << MAW0_MADDR_POS)
+#define MAW1_RNW (1 << 23)
+#define MAW1_MAIDX_POS 16
+#define MAW1_MAIDX_MASK (3 << MAW1_MAIDX_POS)
+#define MAW1_MADDR_POS 0
+#define MAW1_MADDR_MASK (0xFFFF << MAW1_MADDR_POS)
+
+/* Address Filter Mode Registers (AFM), [1] p63 */
+#define AFM_PM (1 << 31)
+
+/* Interrupt Status, Enable Registers (TIS, TIE), [1] p63-65 */
+#define TISE_CFG_W (1 << 6)
+#define TISE_CFG_R (1 << 5)
+#define TISE_AF_W (1 << 4)
+#define TISE_AF_R (1 << 3)
+#define TISE_MIIM_W (1 << 2)
+#define TISE_MIIM_R (1 << 1)
+#define TISE_FABR_R (1 << 0)
+
+/* MII Management Write Data Registers (MIIMWD), [1] p66 */
+#define MIIMWD_DATA_POS 0
+#define MIIMWD_DATA_MASK (0xFFFF << MIIMWD_DATA_POS)
+
+/* Ethernet interface ready status */
+int ll_temac_check_status(struct temac_reg *regs, u32 mask);
+
+/* Indirect write to ll_temac. */
+int ll_temac_indirect_set(struct temac_reg *regs, u16 regn, u32 reg_data);
+
+/* Indirect read from ll_temac. */
+int ll_temac_indirect_get(struct temac_reg *regs, u16 regn, u32* reg_data);
+
+struct ll_temac {
+ phys_addr_t ctrladdr;
+ phys_addr_t sdma_reg_addr[SDMA_CTRL_REGNUMS];
+
+ unsigned (*in32)(phys_addr_t);
+ void (*out32)(phys_addr_t, unsigned);
+
+ int (*ctrlinit) (struct eth_device *);
+ int (*ctrlhalt) (struct eth_device *);
+ int (*ctrlreset) (struct eth_device *);
+
+ int phyaddr;
+ struct phy_device *phydev;
+ struct mii_dev *bus;
+ char mdio_busname[MDIO_NAME_LEN];
+};
+
+#endif /* _XILINX_LL_TEMAC_ */
diff --git a/drivers/net/xilinx_ll_temac_fifo.c b/drivers/net/xilinx_ll_temac_fifo.c
new file mode 100644
index 0000000..3ff0f34
--- /dev/null
+++ b/drivers/net/xilinx_ll_temac_fifo.c
@@ -0,0 +1,143 @@
+/*
+ * Xilinx xps_ll_temac ethernet driver for u-boot
+ *
+ * FIFO sub-controller
+ *
+ * Copyright (C) 2011 - 2012 Stephan Linz <linz(a)li-pro.net>
+ * Copyright (C) 2008 - 2011 Michal Simek <monstr(a)monstr.eu>
+ * Copyright (C) 2008 - 2011 PetaLogix
+ *
+ * Based on Yoshio Kashiwagi kashiwagi(a)co-nss.co.jp driver
+ * Copyright (C) 2008 Nissin Systems Co.,Ltd.
+ * March 2008 created
+ *
+ * CREDITS: tsec driver
+ *
+ * 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.
+ *
+ * [0]: http://www.xilinx.com/support/documentation
+ *
+ * [F]: [0]/ip_documentation/xps_ll_fifo.pdf
+ * [S]: [0]/ip_documentation/xps_ll_temac.pdf
+ * [A]: [0]/application_notes/xapp1041.pdf
+ */
+
+#include <config.h>
+#include <common.h>
+#include <net.h>
+
+#include <asm/types.h>
+#include <asm/io.h>
+
+#include "xilinx_ll_temac.h"
+#include "xilinx_ll_temac_fifo.h"
+
+int ll_temac_reset_fifo(struct eth_device *dev)
+{
+ struct ll_temac *ll_temac = dev->priv;
+ struct fifo_ctrl *fifo_ctrl = (void *)ll_temac->ctrladdr;
+
+ out_be32(&fifo_ctrl->tdfr, LL_FIFO_TDFR_KEY);
+ out_be32(&fifo_ctrl->rdfr, LL_FIFO_RDFR_KEY);
+ out_be32(&fifo_ctrl->isr, ~0UL);
+ out_be32(&fifo_ctrl->ier, 0);
+
+ return 0;
+}
+
+int ll_temac_recv_fifo(struct eth_device *dev)
+{
+ int i, length = 0;
+ u32 *buf = (u32 *)NetRxPackets[0];
+ struct ll_temac *ll_temac = dev->priv;
+ struct fifo_ctrl *fifo_ctrl = (void *)ll_temac->ctrladdr;
+
+ if (in_be32(&fifo_ctrl->isr) & LL_FIFO_ISR_RC) {
+
+ /* reset isr */
+ out_be32(&fifo_ctrl->isr, ~0UL);
+
+ /*
+ * MAYBE here:
+ * while (fifo_ctrl->isr);
+ */
+
+ /*
+ * The length is written (into RLR) by the XPS LL FIFO
+ * when the packet is received across the RX LocalLink
+ * interface and the receive data FIFO had enough
+ * locations that all of the packet data has been saved.
+ * The RLR should only be read when a receive packet is
+ * available for processing (the receive occupancy is
+ * not zero). Once the RLR is read, the receive packet
+ * data should be read from the receive data FIFO before
+ * the RLR is read again.
+ *
+ * [F] page 17, Receive Length Register (RLR)
+ */
+ if (in_be32(&fifo_ctrl->rdfo) & LL_FIFO_RDFO_MASK) {
+ length = in_be32(&fifo_ctrl->rlf) & LL_FIFO_RLF_MASK;
+ } else {
+ printf("%s: Got error, no receive occupancy\n",
+ __func__);
+ return -1;
+ }
+
+ if (length > PKTSIZE_ALIGN) {
+ printf("%s: Got error, receive package too big (%i)\n",
+ __func__, length);
+ ll_temac_reset_fifo(dev);
+ return -1;
+ }
+
+ for (i = 0; i < length; i += 4)
+ *buf++ = in_be32(&fifo_ctrl->rdfd);
+
+ NetReceive(NetRxPackets[0], length);
+ }
+
+ return 0;
+}
+
+int ll_temac_send_fifo(struct eth_device *dev, volatile void *packet,
+ int length)
+{
+ int i;
+ u32 *buf = (u32 *)packet;
+ struct ll_temac *ll_temac = dev->priv;
+ struct fifo_ctrl *fifo_ctrl = (void *)ll_temac->ctrladdr;
+
+ if (length < LL_FIFO_TLF_MIN) {
+ printf("%s: Got error, transmit package too small (%i)\n",
+ __func__, length);
+ return -1;
+ }
+
+ if (length > LL_FIFO_TLF_MAX) {
+ printf("%s: Got error, transmit package too big (%i)\n",
+ __func__, length);
+ return -1;
+ }
+
+ for (i = 0; i < length; i += 4)
+ out_be32(&fifo_ctrl->tdfd, *buf++);
+
+ /*
+ * Once the packet length is written to the TLR it is
+ * automatically moved to the transmit data FIFO with
+ * the packet data freeing up the TLR for another value.
+ * The packet length must be written to the TLR after
+ * the packet data is written to the transmit data FIFO.
+ * It is not valid to write data for multiple packets
+ * to the transmit data FIFO before writing the packet
+ * length values.
+ *
+ * [F] page 17, Transmit Length Register (TLR)
+ */
+ out_be32(&fifo_ctrl->tlf, length);
+
+ return 0;
+}
diff --git a/drivers/net/xilinx_ll_temac_fifo.h b/drivers/net/xilinx_ll_temac_fifo.h
new file mode 100644
index 0000000..f0d6e68
--- /dev/null
+++ b/drivers/net/xilinx_ll_temac_fifo.h
@@ -0,0 +1,122 @@
+/*
+ * Xilinx xps_ll_temac ethernet driver for u-boot
+ *
+ * FIFO sub-controller interface
+ *
+ * Copyright (C) 2011 - 2012 Stephan Linz <linz(a)li-pro.net>
+ * Copyright (C) 2008 - 2011 Michal Simek <monstr(a)monstr.eu>
+ * Copyright (C) 2008 - 2011 PetaLogix
+ *
+ * Based on Yoshio Kashiwagi kashiwagi(a)co-nss.co.jp driver
+ * Copyright (C) 2008 Nissin Systems Co.,Ltd.
+ * March 2008 created
+ *
+ * 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.
+ *
+ * [0]: http://www.xilinx.com/support/documentation
+ *
+ * [S]: [0]/ip_documentation/xps_ll_temac.pdf
+ * [A]: [0]/application_notes/xapp1041.pdf
+ */
+#ifndef _XILINX_LL_TEMAC_FIFO_
+#define _XILINX_LL_TEMAC_FIFO_
+
+#include <net.h>
+
+#include <asm/types.h>
+#include <asm/byteorder.h>
+
+#if !defined(__BIG_ENDIAN)
+# error LL_TEMAC requires big endianess
+#endif
+
+/*
+ * FIFO Register Definition
+ *
+ * Used for memory mapped access from and to (Rd/Td) the LocalLink (LL)
+ * Tri-Mode Ether MAC (TEMAC) via the 2 kb full duplex FIFO Controller,
+ * one for each.
+ *
+ * [1]: [0]/ip_documentation/xps_ll_fifo.pdf
+ * page 10, Registers Definition
+ */
+struct fifo_ctrl {
+ u32 isr; /* Interrupt Status Register (RW) */
+ u32 ier; /* Interrupt Enable Register (RW) */
+ u32 tdfr; /* Transmit Data FIFO Reset (WO) */
+ u32 tdfv; /* Transmit Data FIFO Vacancy (RO) */
+ u32 tdfd; /* Transmit Data FIFO 32bit wide Data write port (WO) */
+ u32 tlf; /* Transmit Length FIFO (WO) */
+ u32 rdfr; /* Receive Data FIFO Reset (WO) */
+ u32 rdfo; /* Receive Data FIFO Occupancy (RO) */
+ u32 rdfd; /* Receive Data FIFO 32bit wide Data read port (RO) */
+ u32 rlf; /* Receive Length FIFO (RO) */
+ u32 llr; /* LocalLink Reset (WO) */
+};
+
+/* Interrupt Status Register (ISR), [1] p11 */
+#define LL_FIFO_ISR_RPURE (1 << 31) /* Receive Packet Underrun Read Err */
+#define LL_FIFO_ISR_RPORE (1 << 30) /* Receive Packet Overrun Read Err */
+#define LL_FIFO_ISR_RPUE (1 << 29) /* Receive Packet Underrun Error */
+#define LL_FIFO_ISR_TPOE (1 << 28) /* Transmit Packet Overrun Error */
+#define LL_FIFO_ISR_TC (1 << 27) /* Transmit Complete */
+#define LL_FIFO_ISR_RC (1 << 26) /* Receive Complete */
+#define LL_FIFO_ISR_TSE (1 << 25) /* Transmit Size Error */
+#define LL_FIFO_ISR_TRC (1 << 24) /* Transmit Reset Complete */
+#define LL_FIFO_ISR_RRC (1 << 23) /* Receive Reset Complete */
+
+/* Interrupt Enable Register (IER), [1] p12/p13 */
+#define LL_FIFO_IER_RPURE (1 << 31) /* Receive Packet Underrun Read Err */
+#define LL_FIFO_IER_RPORE (1 << 30) /* Receive Packet Overrun Read Err */
+#define LL_FIFO_IER_RPUE (1 << 29) /* Receive Packet Underrun Error */
+#define LL_FIFO_IER_TPOE (1 << 28) /* Transmit Packet Overrun Error */
+#define LL_FIFO_IER_TC (1 << 27) /* Transmit Complete */
+#define LL_FIFO_IER_RC (1 << 26) /* Receive Complete */
+#define LL_FIFO_IER_TSE (1 << 25) /* Transmit Size Error */
+#define LL_FIFO_IER_TRC (1 << 24) /* Transmit Reset Complete */
+#define LL_FIFO_IER_RRC (1 << 23) /* Receive Reset Complete */
+
+/* Transmit Data FIFO Reset (TDFR), [1] p13/p14 */
+#define LL_FIFO_TDFR_KEY 0x000000A5UL
+
+/* Transmit Data FIFO Vacancy (TDFV), [1] p14 */
+#define LL_FIFO_TDFV_POS 0
+#define LL_FIFO_TDFV_MASK (0x000001FFUL << LL_FIFO_TDFV_POS)
+
+/* Transmit Length FIFO (TLF), [1] p16/p17 */
+#define LL_FIFO_TLF_POS 0
+#define LL_FIFO_TLF_MASK (0x000007FFUL << LL_FIFO_TLF_POS)
+#define LL_FIFO_TLF_MIN ((4 * sizeof(u32)) & LL_FIFO_TLF_MASK)
+#define LL_FIFO_TLF_MAX ((510 * sizeof(u32)) & LL_FIFO_TLF_MASK)
+
+/* Receive Data FIFO Reset (RDFR), [1] p15 */
+#define LL_FIFO_RDFR_KEY 0x000000A5UL
+
+/* Receive Data FIFO Occupancy (RDFO), [1] p16 */
+#define LL_FIFO_RDFO_POS 0
+#define LL_FIFO_RDFO_MASK (0x000001FFUL << LL_FIFO_RDFO_POS)
+
+/* Receive Length FIFO (RLF), [1] p17/p18 */
+#define LL_FIFO_RLF_POS 0
+#define LL_FIFO_RLF_MASK (0x000007FFUL << LL_FIFO_RLF_POS)
+#define LL_FIFO_RLF_MIN ((4 * sizeof(uint32)) & LL_FIFO_RLF_MASK)
+#define LL_FIFO_RLF_MAX ((510 * sizeof(uint32)) & LL_FIFO_RLF_MASK)
+
+/* LocalLink Reset (LLR), [1] p18 */
+#define LL_FIFO_LLR_KEY 0x000000A5UL
+
+
+/* reset FIFO and IRQ, disable interrupts */
+int ll_temac_reset_fifo(struct eth_device *dev);
+
+/* receive buffered data from FIFO (polling ISR) */
+int ll_temac_recv_fifo(struct eth_device *dev);
+
+/* send buffered data to FIFO */
+int ll_temac_send_fifo(struct eth_device *dev, volatile void *packet,
+ int length);
+
+#endif /* _XILINX_LL_TEMAC_FIFO_ */
diff --git a/drivers/net/xilinx_ll_temac_mdio.c b/drivers/net/xilinx_ll_temac_mdio.c
new file mode 100644
index 0000000..c56ff48
--- /dev/null
+++ b/drivers/net/xilinx_ll_temac_mdio.c
@@ -0,0 +1,180 @@
+/*
+ * Xilinx xps_ll_temac ethernet driver for u-boot
+ *
+ * MDIO bus access
+ *
+ * Copyright (C) 2011 - 2012 Stephan Linz <linz(a)li-pro.net>
+ * Copyright (C) 2008 - 2011 Michal Simek <monstr(a)monstr.eu>
+ * Copyright (C) 2008 - 2011 PetaLogix
+ *
+ * Based on Yoshio Kashiwagi kashiwagi(a)co-nss.co.jp driver
+ * Copyright (C) 2008 Nissin Systems Co.,Ltd.
+ * March 2008 created
+ *
+ * CREDITS: tsec driver
+ *
+ * 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.
+ *
+ * [0]: http://www.xilinx.com/support/documentation
+ *
+ * [S]: [0]/ip_documentation/xps_ll_temac.pdf
+ * [A]: [0]/application_notes/xapp1041.pdf
+ */
+
+#include <config.h>
+#include <common.h>
+#include <miiphy.h>
+#include <phy.h>
+#include <malloc.h>
+#include <asm/io.h>
+
+#include "xilinx_ll_temac.h"
+#include "xilinx_ll_temac_mdio.h"
+
+#if !defined(CONFIG_MII)
+# error "LL_TEMAC requires MII -- missing CONFIG_MII"
+#endif
+
+#if !defined(CONFIG_PHYLIB)
+# error "LL_TEMAC requires PHYLIB -- missing CONFIG_PHYLIB"
+#endif
+
+/*
+ * Prior to PHY access, the MDIO clock must be setup. This driver will set a
+ * safe default that should work with PLB bus speeds of up to 150 MHz and keep
+ * the MDIO clock below 2.5 MHz. If the user wishes faster access to the PHY
+ * then the clock divisor can be set to a different value by setting the
+ * correct bus speed value with CONFIG_XILINX_LL_TEMAC_CLK.
+ */
+#if !defined(CONFIG_XILINX_LL_TEMAC_CLK)
+#define MDIO_CLOCK_DIV MC_CLKDIV_10(150000000)
+#else
+#define MDIO_CLOCK_DIV MC_CLKDIV_25(CONFIG_XILINX_LL_TEMAC_CLK)
+#endif
+
+static int ll_temac_mdio_setup(struct mii_dev *bus)
+{
+ struct temac_reg *regs = (struct temac_reg *)bus->priv;
+
+ /* setup MDIO clock */
+ ll_temac_indirect_set(regs, TEMAC_MC,
+ MC_MDIOEN | (MDIO_CLOCK_DIV & MC_CLKDIV_MASK));
+
+ return 0;
+}
+
+/*
+ * Indirect MII PHY read via ll_temac.
+ *
+ * http://www.xilinx.com/support/documentation/ip_documentation/xps_ll_temac.p…
+ * page 67, Using the MII Management to Access PHY Registers
+ */
+int ll_temac_local_mdio_read(struct temac_reg *regs, int addr, int devad,
+ int regnum)
+{
+ out_be32(®s->lsw,
+ ((addr << LSW_PHYAD_POS) & LSW_PHYAD_MASK) |
+ (regnum & LSW_REGAD_MASK));
+ out_be32(®s->ctl, TEMAC_MIIMAI);
+
+ ll_temac_check_status(regs, RSE_MIIM_RR);
+
+ return in_be32(®s->lsw) & LSW_REGDAT_MASK;
+}
+
+/*
+ * Indirect MII PHY write via ll_temac.
+ *
+ * http://www.xilinx.com/support/documentation/ip_documentation/xps_ll_temac.p…
+ * page 67, Using the MII Management to Access PHY Registers
+ */
+void ll_temac_local_mdio_write(struct temac_reg *regs, int addr, int devad,
+ int regnum, u16 value)
+{
+ out_be32(®s->lsw, (value & LSW_REGDAT_MASK));
+ out_be32(®s->ctl, CTL_WEN | TEMAC_MIIMWD);
+
+ out_be32(®s->lsw,
+ ((addr << LSW_PHYAD_POS) & LSW_PHYAD_MASK) |
+ (regnum & LSW_REGAD_MASK));
+ out_be32(®s->ctl, CTL_WEN | TEMAC_MIIMAI);
+
+ ll_temac_check_status(regs, RSE_MIIM_WR);
+}
+
+int ll_temac_phy_read(struct mii_dev *bus, int addr, int devad, int regnum)
+{
+ struct temac_reg *regs = (struct temac_reg *)bus->priv;
+
+ return ll_temac_local_mdio_read(regs, addr, devad, regnum);
+}
+
+int ll_temac_phy_write(struct mii_dev *bus, int addr, int devad, int regnum,
+ u16 value)
+{
+ struct temac_reg *regs = (struct temac_reg *)bus->priv;
+
+ ll_temac_local_mdio_write(regs, addr, devad, regnum, value);
+
+ return 0;
+}
+
+/*
+ * Use MII register 1 (MII status register) to detect PHY
+ *
+ * A Mask used to verify certain PHY features (register content)
+ * in the PHY detection register:
+ * Auto-negotiation support, 10Mbps half/full duplex support
+ */
+#define PHY_DETECT_REG MII_BMSR
+#define PHY_DETECT_MASK (BMSR_10FULL | BMSR_10HALF | BMSR_ANEGCAPABLE)
+
+/* Looking for a valid PHY address */
+int ll_temac_phy_addr(struct mii_dev *bus)
+{
+ struct temac_reg *regs = (struct temac_reg *)bus->priv;
+ unsigned short val;
+ unsigned int phy;
+
+ for (phy = PHY_MAX_ADDR; phy >= 0; phy--) {
+ val = ll_temac_local_mdio_read(regs, phy, 0, PHY_DETECT_REG);
+ if ((val != 0xFFFF) &&
+ ((val & PHY_DETECT_MASK) == PHY_DETECT_MASK)) {
+ /* Found a valid PHY address */
+ return phy;
+ }
+ }
+
+ return -1;
+}
+
+int xilinx_ll_temac_mdio_initialize(bd_t *bis, struct ll_temac_mdio_info *info)
+{
+ struct mii_dev *bus = mdio_alloc();
+
+ if (!bus) {
+ printf("Failed to allocate LL_TEMAC MDIO bus: %s\n",
+ info->name);
+ return -1;
+ }
+
+ bus->read = ll_temac_phy_read;
+ bus->write = ll_temac_phy_write;
+ bus->reset = NULL;
+
+ /* use given name or generate its own unique name */
+ if (info->name) {
+ strncpy(bus->name, info->name, MDIO_NAME_LEN);
+ } else {
+ snprintf(bus->name, MDIO_NAME_LEN, "lltemii.%p", info->regs);
+ info->name = bus->name;
+ }
+
+ bus->priv = info->regs;
+
+ ll_temac_mdio_setup(bus);
+ return mdio_register(bus);
+}
diff --git a/drivers/net/xilinx_ll_temac_mdio.h b/drivers/net/xilinx_ll_temac_mdio.h
new file mode 100644
index 0000000..8d8fabd
--- /dev/null
+++ b/drivers/net/xilinx_ll_temac_mdio.h
@@ -0,0 +1,53 @@
+/*
+ * Xilinx xps_ll_temac ethernet driver for u-boot
+ *
+ * MDIO bus access interface
+ *
+ * Copyright (C) 2011 - 2012 Stephan Linz <linz(a)li-pro.net>
+ * Copyright (C) 2008 - 2011 Michal Simek <monstr(a)monstr.eu>
+ * Copyright (C) 2008 - 2011 PetaLogix
+ *
+ * Based on Yoshio Kashiwagi kashiwagi(a)co-nss.co.jp driver
+ * Copyright (C) 2008 Nissin Systems Co.,Ltd.
+ * March 2008 created
+ *
+ * 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.
+ *
+ * [0]: http://www.xilinx.com/support/documentation
+ *
+ * [S]: [0]/ip_documentation/xps_ll_temac.pdf
+ * [A]: [0]/application_notes/xapp1041.pdf
+ */
+#ifndef _XILINX_LL_TEMAC_MDIO_
+#define _XILINX_LL_TEMAC_MDIO_
+
+#include <net.h>
+#include <miiphy.h>
+
+#include <asm/types.h>
+#include <asm/byteorder.h>
+
+#include "xilinx_ll_temac.h"
+
+int ll_temac_local_mdio_read(struct temac_reg *regs, int addr, int devad,
+ int regnum);
+void ll_temac_local_mdio_write(struct temac_reg *regs, int addr, int devad,
+ int regnum, u16 value);
+
+int ll_temac_phy_read(struct mii_dev *bus, int addr, int devad, int regnum);
+int ll_temac_phy_write(struct mii_dev *bus, int addr, int devad, int regnum,
+ u16 value);
+
+int ll_temac_phy_addr(struct mii_dev *bus);
+
+struct ll_temac_mdio_info {
+ struct temac_reg *regs;
+ char *name;
+};
+
+int xilinx_ll_temac_mdio_initialize(bd_t *bis, struct ll_temac_mdio_info *info);
+
+#endif /* _XILINX_LL_TEMAC_MDIO_ */
diff --git a/drivers/net/xilinx_ll_temac_sdma.c b/drivers/net/xilinx_ll_temac_sdma.c
new file mode 100644
index 0000000..621d100
--- /dev/null
+++ b/drivers/net/xilinx_ll_temac_sdma.c
@@ -0,0 +1,370 @@
+/*
+ * Xilinx xps_ll_temac ethernet driver for u-boot
+ *
+ * SDMA sub-controller
+ *
+ * Copyright (C) 2011 - 2012 Stephan Linz <linz(a)li-pro.net>
+ * Copyright (C) 2008 - 2011 Michal Simek <monstr(a)monstr.eu>
+ * Copyright (C) 2008 - 2011 PetaLogix
+ *
+ * Based on Yoshio Kashiwagi kashiwagi(a)co-nss.co.jp driver
+ * Copyright (C) 2008 Nissin Systems Co.,Ltd.
+ * March 2008 created
+ *
+ * CREDITS: tsec driver
+ *
+ * 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.
+ *
+ * [0]: http://www.xilinx.com/support/documentation
+ *
+ * [M]: [0]/ip_documentation/mpmc.pdf
+ * [S]: [0]/ip_documentation/xps_ll_temac.pdf
+ * [A]: [0]/application_notes/xapp1041.pdf
+ */
+
+#include <config.h>
+#include <common.h>
+#include <net.h>
+
+#include <asm/types.h>
+#include <asm/io.h>
+
+#include "xilinx_ll_temac.h"
+#include "xilinx_ll_temac_sdma.h"
+
+#define TX_BUF_CNT 2
+
+static unsigned int rx_idx; /* index of the current RX buffer */
+static unsigned int tx_idx; /* index of the current TX buffer */
+
+struct rtx_cdmac_bd {
+ struct cdmac_bd rx[PKTBUFSRX];
+ struct cdmac_bd tx[TX_BUF_CNT];
+};
+
+/*
+ * DMA Buffer Descriptor alignment
+ *
+ * If the address contained in the Next Descriptor Pointer register is not
+ * 8-word aligned or reaches beyond the range of available memory, the SDMA
+ * halts processing and sets the CDMAC_BD_STCTRL_ERROR bit in the respective
+ * status register (tx_chnl_sts or rx_chnl_sts).
+ *
+ * [1]: [0]/ip_documentation/mpmc.pdf
+ * page 161, Next Descriptor Pointer
+ */
+static struct rtx_cdmac_bd cdmac_bd __aligned(32);
+
+#if defined(CONFIG_XILINX_440) || defined(CONFIG_XILINX_405)
+
+/*
+ * Indirect DCR access operations mi{ft}dcr_xilinx() espacialy
+ * for Xilinx PowerPC implementations on FPGA.
+ *
+ * FIXME: This part should go up to arch/powerpc -- but where?
+ */
+#include <asm/processor.h>
+#define XILINX_INDIRECT_DCR_ADDRESS_REG 0
+#define XILINX_INDIRECT_DCR_ACCESS_REG 1
+inline unsigned mifdcr_xilinx(const unsigned dcrn)
+{
+ mtdcr(XILINX_INDIRECT_DCR_ADDRESS_REG, dcrn);
+ return mfdcr(XILINX_INDIRECT_DCR_ACCESS_REG);
+}
+inline void mitdcr_xilinx(const unsigned dcrn, int val)
+{
+ mtdcr(XILINX_INDIRECT_DCR_ADDRESS_REG, dcrn);
+ mtdcr(XILINX_INDIRECT_DCR_ACCESS_REG, val);
+}
+
+/* Xilinx Device Control Register (DCR) in/out accessors */
+inline unsigned ll_temac_xldcr_in32(phys_addr_t addr)
+{
+ return mifdcr_xilinx((const unsigned)addr);
+}
+inline void ll_temac_xldcr_out32(phys_addr_t addr, unsigned value)
+{
+ mitdcr_xilinx((const unsigned)addr, value);
+}
+
+void ll_temac_collect_xldcr_sdma_reg_addr(struct eth_device *dev)
+{
+ struct ll_temac *ll_temac = dev->priv;
+ phys_addr_t dmac_ctrl = ll_temac->ctrladdr;
+ phys_addr_t *ra = ll_temac->sdma_reg_addr;
+
+ ra[TX_NXTDESC_PTR] = dmac_ctrl + TX_NXTDESC_PTR;
+ ra[TX_CURBUF_ADDR] = dmac_ctrl + TX_CURBUF_ADDR;
+ ra[TX_CURBUF_LENGTH] = dmac_ctrl + TX_CURBUF_LENGTH;
+ ra[TX_CURDESC_PTR] = dmac_ctrl + TX_CURDESC_PTR;
+ ra[TX_TAILDESC_PTR] = dmac_ctrl + TX_TAILDESC_PTR;
+ ra[TX_CHNL_CTRL] = dmac_ctrl + TX_CHNL_CTRL;
+ ra[TX_IRQ_REG] = dmac_ctrl + TX_IRQ_REG;
+ ra[TX_CHNL_STS] = dmac_ctrl + TX_CHNL_STS;
+ ra[RX_NXTDESC_PTR] = dmac_ctrl + RX_NXTDESC_PTR;
+ ra[RX_CURBUF_ADDR] = dmac_ctrl + RX_CURBUF_ADDR;
+ ra[RX_CURBUF_LENGTH] = dmac_ctrl + RX_CURBUF_LENGTH;
+ ra[RX_CURDESC_PTR] = dmac_ctrl + RX_CURDESC_PTR;
+ ra[RX_TAILDESC_PTR] = dmac_ctrl + RX_TAILDESC_PTR;
+ ra[RX_CHNL_CTRL] = dmac_ctrl + RX_CHNL_CTRL;
+ ra[RX_IRQ_REG] = dmac_ctrl + RX_IRQ_REG;
+ ra[RX_CHNL_STS] = dmac_ctrl + RX_CHNL_STS;
+ ra[DMA_CONTROL_REG] = dmac_ctrl + DMA_CONTROL_REG;
+}
+
+#endif /* CONFIG_XILINX_440 || ONFIG_XILINX_405 */
+
+/* Xilinx Processor Local Bus (PLB) in/out accessors */
+inline unsigned ll_temac_xlplb_in32(phys_addr_t addr)
+{
+ return in_be32((void *)addr);
+}
+inline void ll_temac_xlplb_out32(phys_addr_t addr, unsigned value)
+{
+ out_be32((void *)addr, value);
+}
+
+/* collect all register addresses for Xilinx PLB in/out accessors */
+void ll_temac_collect_xlplb_sdma_reg_addr(struct eth_device *dev)
+{
+ struct ll_temac *ll_temac = dev->priv;
+ struct sdma_ctrl *sdma_ctrl = (void *)ll_temac->ctrladdr;
+ phys_addr_t *ra = ll_temac->sdma_reg_addr;
+
+ ra[TX_NXTDESC_PTR] = (phys_addr_t)&sdma_ctrl->tx_nxtdesc_ptr;
+ ra[TX_CURBUF_ADDR] = (phys_addr_t)&sdma_ctrl->tx_curbuf_addr;
+ ra[TX_CURBUF_LENGTH] = (phys_addr_t)&sdma_ctrl->tx_curbuf_length;
+ ra[TX_CURDESC_PTR] = (phys_addr_t)&sdma_ctrl->tx_curdesc_ptr;
+ ra[TX_TAILDESC_PTR] = (phys_addr_t)&sdma_ctrl->tx_taildesc_ptr;
+ ra[TX_CHNL_CTRL] = (phys_addr_t)&sdma_ctrl->tx_chnl_ctrl;
+ ra[TX_IRQ_REG] = (phys_addr_t)&sdma_ctrl->tx_irq_reg;
+ ra[TX_CHNL_STS] = (phys_addr_t)&sdma_ctrl->tx_chnl_sts;
+ ra[RX_NXTDESC_PTR] = (phys_addr_t)&sdma_ctrl->rx_nxtdesc_ptr;
+ ra[RX_CURBUF_ADDR] = (phys_addr_t)&sdma_ctrl->rx_curbuf_addr;
+ ra[RX_CURBUF_LENGTH] = (phys_addr_t)&sdma_ctrl->rx_curbuf_length;
+ ra[RX_CURDESC_PTR] = (phys_addr_t)&sdma_ctrl->rx_curdesc_ptr;
+ ra[RX_TAILDESC_PTR] = (phys_addr_t)&sdma_ctrl->rx_taildesc_ptr;
+ ra[RX_CHNL_CTRL] = (phys_addr_t)&sdma_ctrl->rx_chnl_ctrl;
+ ra[RX_IRQ_REG] = (phys_addr_t)&sdma_ctrl->rx_irq_reg;
+ ra[RX_CHNL_STS] = (phys_addr_t)&sdma_ctrl->rx_chnl_sts;
+ ra[DMA_CONTROL_REG] = (phys_addr_t)&sdma_ctrl->dma_control_reg;
+}
+
+/* Check for TX and RX channel errors. */
+static inline int ll_temac_sdma_error(struct eth_device *dev)
+{
+ int err;
+ struct ll_temac *ll_temac = dev->priv;
+ phys_addr_t *ra = ll_temac->sdma_reg_addr;
+
+ err = ll_temac->in32(ra[TX_CHNL_STS]) & CHNL_STS_ERROR;
+ err |= ll_temac->in32(ra[RX_CHNL_STS]) & CHNL_STS_ERROR;
+
+ return err;
+}
+
+int ll_temac_init_sdma(struct eth_device *dev)
+{
+ struct ll_temac *ll_temac = dev->priv;
+ struct cdmac_bd *rx_dp;
+ struct cdmac_bd *tx_dp;
+ phys_addr_t *ra = ll_temac->sdma_reg_addr;
+ int i;
+
+ printf("%s: SDMA: %d Rx buffers, %d Tx buffers\n",
+ dev->name, PKTBUFSRX, TX_BUF_CNT);
+
+ /* Initialize the Rx Buffer descriptors */
+ for (i = 0; i < PKTBUFSRX; i++) {
+ rx_dp = &cdmac_bd.rx[i];
+ memset(rx_dp, 0, sizeof(*rx_dp));
+ rx_dp->next_p = rx_dp;
+ rx_dp->buf_len = PKTSIZE_ALIGN;
+ rx_dp->phys_buf_p = (u8 *)NetRxPackets[i];
+ flush_cache((u32)rx_dp->phys_buf_p, PKTSIZE_ALIGN);
+ }
+ flush_cache((u32)cdmac_bd.rx, sizeof(cdmac_bd.rx));
+
+ /* Initialize the TX Buffer Descriptors */
+ for (i = 0; i < TX_BUF_CNT; i++) {
+ tx_dp = &cdmac_bd.tx[i];
+ memset(tx_dp, 0, sizeof(*tx_dp));
+ tx_dp->next_p = tx_dp;
+ }
+ flush_cache((u32)cdmac_bd.tx, sizeof(cdmac_bd.tx));
+
+ /* Reset index counter to the Rx and Tx Buffer descriptors */
+ rx_idx = tx_idx = 0;
+
+ /* initial Rx DMA start by writing to respective TAILDESC_PTR */
+ ll_temac->out32(ra[RX_CURDESC_PTR], (int)&cdmac_bd.rx[rx_idx]);
+ ll_temac->out32(ra[RX_TAILDESC_PTR], (int)&cdmac_bd.rx[rx_idx]);
+
+ return 0;
+}
+
+int ll_temac_halt_sdma(struct eth_device *dev)
+{
+ unsigned timeout = 50; /* 1usec * 50 = 50usec */
+ struct ll_temac *ll_temac = dev->priv;
+ phys_addr_t *ra = ll_temac->sdma_reg_addr;
+
+ /*
+ * Soft reset the DMA
+ *
+ * Quote from MPMC documentation: Writing a 1 to this field
+ * forces the DMA engine to shutdown and reset itself. After
+ * setting this bit, software must poll it until the bit is
+ * cleared by the DMA. This indicates that the reset process
+ * is done and the pipeline has been flushed.
+ */
+ ll_temac->out32(ra[DMA_CONTROL_REG], DMA_CONTROL_RESET);
+ while (timeout && (ll_temac->in32(ra[DMA_CONTROL_REG])
+ & DMA_CONTROL_RESET)) {
+ timeout--;
+ udelay(1);
+ }
+
+ if (!timeout) {
+ printf("%s: Timeout\n", __func__);
+ return -1;
+ }
+
+ return 0;
+}
+
+int ll_temac_reset_sdma(struct eth_device *dev)
+{
+ u32 r;
+ struct ll_temac *ll_temac = dev->priv;
+ phys_addr_t *ra = ll_temac->sdma_reg_addr;
+
+ /* Soft reset the DMA. */
+ if (ll_temac_halt_sdma(dev))
+ return -1;
+
+ /* Now clear the interrupts. */
+ r = ll_temac->in32(ra[TX_CHNL_CTRL]);
+ r &= ~CHNL_CTRL_IRQ_MASK;
+ ll_temac->out32(ra[TX_CHNL_CTRL], r);
+
+ r = ll_temac->in32(ra[RX_CHNL_CTRL]);
+ r &= ~CHNL_CTRL_IRQ_MASK;
+ ll_temac->out32(ra[RX_CHNL_CTRL], r);
+
+ /* Now ACK pending IRQs. */
+ ll_temac->out32(ra[TX_IRQ_REG], IRQ_REG_IRQ_MASK);
+ ll_temac->out32(ra[RX_IRQ_REG], IRQ_REG_IRQ_MASK);
+
+ /* Set tail-ptr mode, disable errors for both channels. */
+ ll_temac->out32(ra[DMA_CONTROL_REG],
+ /* Enable use of tail pointer register */
+ DMA_CONTROL_TPE |
+ /* Disable error when 2 or 4 bit coalesce cnt overfl */
+ DMA_CONTROL_RXOCEID |
+ /* Disable error when 2 or 4 bit coalesce cnt overfl */
+ DMA_CONTROL_TXOCEID);
+
+ return 0;
+}
+
+int ll_temac_recv_sdma(struct eth_device *dev)
+{
+ int length, pb_idx;
+ struct cdmac_bd *rx_dp = &cdmac_bd.rx[rx_idx];
+ struct ll_temac *ll_temac = dev->priv;
+ phys_addr_t *ra = ll_temac->sdma_reg_addr;
+
+ if (ll_temac_sdma_error(dev)) {
+
+ if (ll_temac_reset_sdma(dev))
+ return -1;
+
+ ll_temac_init_sdma(dev);
+ }
+
+ flush_cache((u32)rx_dp, sizeof(*rx_dp));
+
+ if (!(rx_dp->sca.stctrl & CDMAC_BD_STCTRL_COMPLETED))
+ return 0;
+
+ if (rx_dp->sca.stctrl & (CDMAC_BD_STCTRL_SOP | CDMAC_BD_STCTRL_EOP)) {
+ pb_idx = rx_idx;
+ length = rx_dp->sca.app[4] & CDMAC_BD_APP4_RXBYTECNT_MASK;
+ } else {
+ pb_idx = -1;
+ length = 0;
+ printf("%s: Got part of package, unsupported (%x)\n",
+ __func__, rx_dp->sca.stctrl);
+ }
+
+ /* flip the buffer */
+ flush_cache((u32)rx_dp->phys_buf_p, length);
+
+ /* reset the current descriptor */
+ rx_dp->sca.stctrl = 0;
+ rx_dp->sca.app[4] = 0;
+ flush_cache((u32)rx_dp, sizeof(*rx_dp));
+
+ /* Find next empty buffer descriptor, preparation for next iteration */
+ rx_idx = (rx_idx + 1) % PKTBUFSRX;
+ rx_dp = &cdmac_bd.rx[rx_idx];
+ flush_cache((u32)rx_dp, sizeof(*rx_dp));
+
+ /* DMA start by writing to respective TAILDESC_PTR */
+ ll_temac->out32(ra[RX_CURDESC_PTR], (int)&cdmac_bd.rx[rx_idx]);
+ ll_temac->out32(ra[RX_TAILDESC_PTR], (int)&cdmac_bd.rx[rx_idx]);
+
+ if (length > 0 && pb_idx != -1)
+ NetReceive(NetRxPackets[pb_idx], length);
+
+ return 0;
+}
+
+int ll_temac_send_sdma(struct eth_device *dev, volatile void *packet,
+ int length)
+{
+ unsigned timeout = 50; /* 1usec * 50 = 50usec */
+ struct cdmac_bd *tx_dp = &cdmac_bd.tx[tx_idx];
+ struct ll_temac *ll_temac = dev->priv;
+ phys_addr_t *ra = ll_temac->sdma_reg_addr;
+
+ if (ll_temac_sdma_error(dev)) {
+
+ if (ll_temac_reset_sdma(dev))
+ return -1;
+
+ ll_temac_init_sdma(dev);
+ }
+
+ tx_dp->phys_buf_p = (u8 *)packet;
+ tx_dp->buf_len = length;
+ tx_dp->sca.stctrl = CDMAC_BD_STCTRL_SOP | CDMAC_BD_STCTRL_EOP |
+ CDMAC_BD_STCTRL_STOP_ON_END;
+
+ flush_cache((u32)packet, length);
+ flush_cache((u32)tx_dp, sizeof(*tx_dp));
+
+ /* DMA start by writing to respective TAILDESC_PTR */
+ ll_temac->out32(ra[TX_CURDESC_PTR], (int)tx_dp);
+ ll_temac->out32(ra[TX_TAILDESC_PTR], (int)tx_dp);
+
+ /* Find next empty buffer descriptor, preparation for next iteration */
+ tx_idx = (tx_idx + 1) % TX_BUF_CNT;
+ tx_dp = &cdmac_bd.tx[tx_idx];
+
+ do {
+ flush_cache((u32)tx_dp, sizeof(*tx_dp));
+ udelay(1);
+ } while (timeout-- && !(tx_dp->sca.stctrl & CDMAC_BD_STCTRL_COMPLETED));
+
+ if (!timeout) {
+ printf("%s: Timeout\n", __func__);
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/drivers/net/xilinx_ll_temac_sdma.h b/drivers/net/xilinx_ll_temac_sdma.h
new file mode 100644
index 0000000..51e258d
--- /dev/null
+++ b/drivers/net/xilinx_ll_temac_sdma.h
@@ -0,0 +1,281 @@
+/*
+ * Xilinx xps_ll_temac ethernet driver for u-boot
+ *
+ * SDMA sub-controller interface
+ *
+ * Copyright (C) 2011 - 2012 Stephan Linz <linz(a)li-pro.net>
+ * Copyright (C) 2008 - 2011 Michal Simek <monstr(a)monstr.eu>
+ * Copyright (C) 2008 - 2011 PetaLogix
+ *
+ * Based on Yoshio Kashiwagi kashiwagi(a)co-nss.co.jp driver
+ * Copyright (C) 2008 Nissin Systems Co.,Ltd.
+ * March 2008 created
+ *
+ * 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.
+ *
+ * [0]: http://www.xilinx.com/support/documentation
+ *
+ * [S]: [0]/ip_documentation/xps_ll_temac.pdf
+ * [A]: [0]/application_notes/xapp1041.pdf
+ */
+#ifndef _XILINX_LL_TEMAC_SDMA_
+#define _XILINX_LL_TEMAC_SDMA_
+
+#include <net.h>
+
+#include <asm/types.h>
+#include <asm/byteorder.h>
+
+#include <linux/compiler.h>
+
+#if !defined(__BIG_ENDIAN)
+# error LL_TEMAC requires big endianess
+#endif
+
+/*
+ * DMA Buffer Descriptor for CDMAC
+ *
+ * Used for data connection from and to (Rx/Tx) the LocalLink (LL) TEMAC via
+ * the Communications Direct Memory Access Controller (CDMAC) -- one for each.
+ *
+ * overview:
+ * ftp://ftp.xilinx.com/pub/documentation/misc/mpmc_getting_started.pdf
+ *
+ * [1]: [0]/ip_documentation/mpmc.pdf
+ * page 140, DMA Operation Descriptors
+ *
+ * [2]: [0]/user_guides/ug200.pdf
+ * page 229, DMA Controller -- Descriptor Format
+ *
+ * [3]: [0]/ip_documentation/xps_ll_temac.pdf
+ * page 72, Transmit LocalLink Frame Format
+ * page 73, Receive LocalLink Frame Format
+ */
+struct cdmac_bd {
+ struct cdmac_bd *next_p; /* Next Descriptor Pointer */
+ u8 *phys_buf_p; /* Buffer Address */
+ u32 buf_len; /* Buffer Length */
+ union {
+ u8 stctrl; /* Status/Control the DMA transfer */
+ u32 app[5]; /* application specific data */
+ } __packed __aligned(1) sca;
+};
+
+/* CDMAC Descriptor Status and Control (stctrl), [1] p140, [2] p230 */
+#define CDMAC_BD_STCTRL_ERROR (1 << 7)
+#define CDMAC_BD_STCTRL_IRQ_ON_END (1 << 6)
+#define CDMAC_BD_STCTRL_STOP_ON_END (1 << 5)
+#define CDMAC_BD_STCTRL_COMPLETED (1 << 4)
+#define CDMAC_BD_STCTRL_SOP (1 << 3)
+#define CDMAC_BD_STCTRL_EOP (1 << 2)
+#define CDMAC_BD_STCTRL_DMACHBUSY (1 << 1)
+
+/* CDMAC Descriptor APP0: Transmit LocalLink Footer Word 3, [3] p72 */
+#define CDMAC_BD_APP0_TXCSCNTRL (1 << 0)
+
+/* CDMAC Descriptor APP1: Transmit LocalLink Footer Word 4, [3] p73 */
+#define CDMAC_BD_APP1_TXCSBEGIN_POS 16
+#define CDMAC_BD_APP1_TXCSBEGIN_MASK (0xFFFF << CDMAC_BD_APP1_TXCSBEGIN_POS)
+#define CDMAC_BD_APP1_TXCSINSERT_POS 0
+#define CDMAC_BD_APP1_TXCSINSERT_MASK (0xFFFF << CDMAC_BD_APP1_TXCSINSERT_POS)
+
+/* CDMAC Descriptor APP2: Transmit LocalLink Footer Word 5, [3] p73 */
+#define CDMAC_BD_APP2_TXCSINIT_POS 0
+#define CDMAC_BD_APP2_TXCSINIT_MASK (0xFFFF << CDMAC_BD_APP2_TXCSINIT_POS)
+
+/* CDMAC Descriptor APP0: Receive LocalLink Footer Word 3, [3] p73 */
+#define CDMAC_BD_APP0_MADDRU_POS 0
+#define CDMAC_BD_APP0_MADDRU_MASK (0xFFFF << CDMAC_BD_APP0_MADDRU_POS)
+
+/* CDMAC Descriptor APP1: Receive LocalLink Footer Word 4, [3] p74 */
+#define CDMAC_BD_APP1_MADDRL_POS 0
+#define CDMAC_BD_APP1_MADDRL_MASK (~0UL << CDMAC_BD_APP1_MADDRL_POS)
+
+/* CDMAC Descriptor APP2: Receive LocalLink Footer Word 5, [3] p74 */
+#define CDMAC_BD_APP2_BCAST_FRAME (1 << 2)
+#define CDMAC_BD_APP2_IPC_MCAST_FRAME (1 << 1)
+#define CDMAC_BD_APP2_MAC_MCAST_FRAME (1 << 0)
+
+/* CDMAC Descriptor APP3: Receive LocalLink Footer Word 6, [3] p74 */
+#define CDMAC_BD_APP3_TLTPID_POS 16
+#define CDMAC_BD_APP3_TLTPID_MASK (0xFFFF << CDMAC_BD_APP3_TLTPID_POS)
+#define CDMAC_BD_APP3_RXCSRAW_POS 0
+#define CDMAC_BD_APP3_RXCSRAW_MASK (0xFFFF << CDMAC_BD_APP3_RXCSRAW_POS)
+
+/* CDMAC Descriptor APP4: Receive LocalLink Footer Word 7, [3] p74 */
+#define CDMAC_BD_APP4_VLANTAG_POS 16
+#define CDMAC_BD_APP4_VLANTAG_MASK (0xFFFF << CDMAC_BD_APP4_VLANTAG_POS)
+#define CDMAC_BD_APP4_RXBYTECNT_POS 0
+#define CDMAC_BD_APP4_RXBYTECNT_MASK (0x3FFF << CDMAC_BD_APP4_RXBYTECNT_POS)
+
+/*
+ * SDMA Register Definition
+ *
+ * [0]: http://www.xilinx.com/support/documentation
+ *
+ * [1]: [0]/ip_documentation/mpmc.pdf
+ * page 54, SDMA Register Summary
+ * page 160, SDMA Registers
+ *
+ * [2]: [0]/user_guides/ug200.pdf
+ * page 244, DMA Controller -- Programming Interface and Registers
+ */
+#define SDMA_CTRL_REGTYPE u32
+#define SDMA_CTRL_REGSIZE sizeof(SDMA_CTRL_REGTYPE)
+struct sdma_ctrl {
+ /* Transmit Registers */
+ SDMA_CTRL_REGTYPE tx_nxtdesc_ptr; /* TX Next Description Pointer */
+ SDMA_CTRL_REGTYPE tx_curbuf_addr; /* TX Current Buffer Address */
+ SDMA_CTRL_REGTYPE tx_curbuf_length; /* TX Current Buffer Length */
+ SDMA_CTRL_REGTYPE tx_curdesc_ptr; /* TX Current Descriptor Pointer */
+ SDMA_CTRL_REGTYPE tx_taildesc_ptr; /* TX Tail Descriptor Pointer */
+ SDMA_CTRL_REGTYPE tx_chnl_ctrl; /* TX Channel Control */
+ SDMA_CTRL_REGTYPE tx_irq_reg; /* TX Interrupt Register */
+ SDMA_CTRL_REGTYPE tx_chnl_sts; /* TX Status Register */
+ /* Receive Registers */
+ SDMA_CTRL_REGTYPE rx_nxtdesc_ptr; /* RX Next Descriptor Pointer */
+ SDMA_CTRL_REGTYPE rx_curbuf_addr; /* RX Current Buffer Address */
+ SDMA_CTRL_REGTYPE rx_curbuf_length; /* RX Current Buffer Length */
+ SDMA_CTRL_REGTYPE rx_curdesc_ptr; /* RX Current Descriptor Pointer */
+ SDMA_CTRL_REGTYPE rx_taildesc_ptr; /* RX Tail Descriptor Pointer */
+ SDMA_CTRL_REGTYPE rx_chnl_ctrl; /* RX Channel Control */
+ SDMA_CTRL_REGTYPE rx_irq_reg; /* RX Interrupt Register */
+ SDMA_CTRL_REGTYPE rx_chnl_sts; /* RX Status Register */
+ /* Control Registers */
+ SDMA_CTRL_REGTYPE dma_control_reg; /* DMA Control Register */
+};
+
+#define SDMA_CTRL_REGNUMS sizeof(struct sdma_ctrl)/SDMA_CTRL_REGSIZE
+
+/*
+ * DMAC Register Index Enumeration
+ *
+ * [2]: http://www.xilinx.com/support/documentation/user_guides/ug200.pdf
+ * page 244, DMA Controller -- Programming Interface and Registers
+ */
+enum dmac_ctrl {
+ /* Transmit Registers */
+ TX_NXTDESC_PTR = 0, /* TX Next Description Pointer */
+ TX_CURBUF_ADDR, /* TX Current Buffer Address */
+ TX_CURBUF_LENGTH, /* TX Current Buffer Length */
+ TX_CURDESC_PTR, /* TX Current Descriptor Pointer */
+ TX_TAILDESC_PTR, /* TX Tail Descriptor Pointer */
+ TX_CHNL_CTRL, /* TX Channel Control */
+ TX_IRQ_REG, /* TX Interrupt Register */
+ TX_CHNL_STS, /* TX Status Register */
+ /* Receive Registers */
+ RX_NXTDESC_PTR, /* RX Next Descriptor Pointer */
+ RX_CURBUF_ADDR, /* RX Current Buffer Address */
+ RX_CURBUF_LENGTH, /* RX Current Buffer Length */
+ RX_CURDESC_PTR, /* RX Current Descriptor Pointer */
+ RX_TAILDESC_PTR, /* RX Tail Descriptor Pointer */
+ RX_CHNL_CTRL, /* RX Channel Control */
+ RX_IRQ_REG, /* RX Interrupt Register */
+ RX_CHNL_STS, /* RX Status Register */
+ /* Control Registers */
+ DMA_CONTROL_REG /* DMA Control Register */
+};
+
+/* Rx/Tx Channel Control Register (*_chnl_ctrl), [1] p163, [2] p246/p252 */
+#define CHNL_CTRL_ITO_POS 24
+#define CHNL_CTRL_ITO_MASK (0xFF << CHNL_CTRL_ITO_POS)
+#define CHNL_CTRL_IC_POS 16
+#define CHNL_CTRL_IC_MASK (0xFF << CHNL_CTRL_IC_POS)
+#define CHNL_CTRL_MSBADDR_POS 12
+#define CHNL_CTRL_MSBADDR_MASK (0xF << CHNL_CTRL_MSBADDR_POS)
+#define CHNL_CTRL_AME (1 << 11)
+#define CHNL_CTRL_OBWC (1 << 10)
+#define CHNL_CTRL_IOE (1 << 9)
+#define CHNL_CTRL_LIC (1 << 8)
+#define CHNL_CTRL_IE (1 << 7)
+#define CHNL_CTRL_IEE (1 << 2)
+#define CHNL_CTRL_IDE (1 << 1)
+#define CHNL_CTRL_ICE (1 << 0)
+
+/* All interrupt enable bits */
+#define CHNL_CTRL_IRQ_MASK (CHNL_CTRL_IE | \
+ CHNL_CTRL_IEE | \
+ CHNL_CTRL_IDE | \
+ CHNL_CTRL_ICE)
+
+/* Rx/Tx Interrupt Status Register (*_irq_reg), [1] p164, [2] p247/p253 */
+#define IRQ_REG_DTV_POS 24
+#define IRQ_REG_DTV_MASK (0xFF << IRQ_REG_DTV_POS)
+#define IRQ_REG_CCV_POS 16
+#define IRQ_REG_CCV_MASK (0xFF << IRQ_REG_CCV_POS)
+#define IRQ_REG_WRCQ_EMPTY (1 << 14)
+#define IRQ_REG_CIC_POS 10
+#define IRQ_REG_CIC_MASK (0xF << IRQ_REG_CIC_POS)
+#define IRQ_REG_DIC_POS 8
+#define IRQ_REG_DIC_MASK (3 << 8)
+#define IRQ_REG_PLB_RD_NMI (1 << 4)
+#define IRQ_REG_PLB_WR_NMI (1 << 3)
+#define IRQ_REG_EI (1 << 2)
+#define IRQ_REG_DI (1 << 1)
+#define IRQ_REG_CI (1 << 0)
+
+/* All interrupt bits */
+#define IRQ_REG_IRQ_MASK (IRQ_REG_PLB_RD_NMI | \
+ IRQ_REG_PLB_WR_NMI | \
+ IRQ_REG_EI | IRQ_REG_DI | IRQ_REG_CI)
+
+/* Rx/Tx Channel Status Register (*_chnl_sts), [1] p165, [2] p249/p255 */
+#define CHNL_STS_ERROR_TAIL (1 << 21)
+#define CHNL_STS_ERROR_CMP (1 << 20)
+#define CHNL_STS_ERROR_ADDR (1 << 19)
+#define CHNL_STS_ERROR_NXTP (1 << 18)
+#define CHNL_STS_ERROR_CURP (1 << 17)
+#define CHNL_STS_ERROR_BSYWR (1 << 16)
+#define CHNL_STS_ERROR (1 << 7)
+#define CHNL_STS_IOE (1 << 6)
+#define CHNL_STS_SOE (1 << 5)
+#define CHNL_STS_CMPLT (1 << 4)
+#define CHNL_STS_SOP (1 << 3)
+#define CHNL_STS_EOP (1 << 2)
+#define CHNL_STS_EBUSY (1 << 1)
+
+/* DMA Control Register (dma_control_reg), [1] p166, [2] p256 */
+#define DMA_CONTROL_PLBED (1 << 5)
+#define DMA_CONTROL_RXOCEID (1 << 4)
+#define DMA_CONTROL_TXOCEID (1 << 3)
+#define DMA_CONTROL_TPE (1 << 2)
+#define DMA_CONTROL_RESET (1 << 0)
+
+#if defined(CONFIG_XILINX_440) || defined(CONFIG_XILINX_405)
+
+/* Xilinx Device Control Register (DCR) in/out accessors */
+unsigned ll_temac_xldcr_in32(phys_addr_t addr);
+void ll_temac_xldcr_out32(phys_addr_t addr, unsigned value);
+
+/* collect all register addresses for Xilinx DCR in/out accessors */
+void ll_temac_collect_xldcr_sdma_reg_addr(struct eth_device *dev);
+
+#endif /* CONFIG_XILINX_440 || CONFIG_XILINX_405 */
+
+/* Xilinx Processor Local Bus (PLB) in/out accessors */
+unsigned ll_temac_xlplb_in32(phys_addr_t base);
+void ll_temac_xlplb_out32(phys_addr_t base, unsigned value);
+
+/* collect all register addresses for Xilinx PLB in/out accessors */
+void ll_temac_collect_xlplb_sdma_reg_addr(struct eth_device *dev);
+
+/* initialize both Rx/Tx buffer descriptors */
+int ll_temac_init_sdma(struct eth_device *dev);
+
+/* halt both Rx/Tx transfers */
+int ll_temac_halt_sdma(struct eth_device *dev);
+
+/* reset SDMA and IRQ, disable interrupts and errors */
+int ll_temac_reset_sdma(struct eth_device *dev);
+
+/* receive buffered data from SDMA (polling ISR) */
+int ll_temac_recv_sdma(struct eth_device *dev);
+
+/* send buffered data to SDMA */
+int ll_temac_send_sdma(struct eth_device *dev, volatile void *packet,
+ int length);
+
+#endif /* _XILINX_LL_TEMAC_SDMA_ */
diff --git a/include/netdev.h b/include/netdev.h
index b0c21d5..4724717 100644
--- a/include/netdev.h
+++ b/include/netdev.h
@@ -102,6 +102,18 @@ int xilinx_axiemac_initialize(bd_t *bis, unsigned long base_addr,
unsigned long dma_addr);
int xilinx_emaclite_initialize(bd_t *bis, unsigned long base_addr,
int txpp, int rxpp);
+int xilinx_ll_temac_eth_init(bd_t *bis, unsigned long base_addr, int flags,
+ unsigned long ctrl_addr);
+
+/*
+ * As long as the Xilinx xps_ll_temac ethernet driver has not its own interface
+ * exported by a public hader file, we need a global definition at this point.
+ */
+#if defined(CONFIG_XILINX_LL_TEMAC)
+#define XILINX_LL_TEMAC_M_FIFO 0 /* use FIFO Ctrl */
+#define XILINX_LL_TEMAC_M_SDMA_PLB (1 << 0)/* use SDMA Ctrl via PLB */
+#define XILINX_LL_TEMAC_M_SDMA_DCR (1 << 1)/* use SDMA Ctrl via DCR */
+#endif
/* Boards with PCI network controllers can call this from their board_eth_init()
* function to initialize whatever's on board.
--
1.7.0.4
3
12
In our setup (OMAP3 EHCI host, keyboard, mouse mass storage and BT
dongle devices connected via several hubs) keyboard fails to initialize
during the bus scan (stalled endpoint while get_descriptor/64) and after
that keyboard is unusable (even in Linux) until power off/on.
Increasing the delay after port reset from 200ms to 260ms solves this
problem.
Signed-off-by: Ilya Yanok <yanok(a)emcraft.com>
---
common/usb.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/common/usb.c b/common/usb.c
index bed5116..5e282c6 100644
--- a/common/usb.c
+++ b/common/usb.c
@@ -1147,7 +1147,7 @@ void usb_hub_port_connect_change(struct usb_device *dev, int port)
return;
}
- wait_ms(200);
+ wait_ms(260);
/* Allocate a new device struct for it */
usb = usb_alloc_new_device();
--
1.7.6.4
4
6
Hey
For the Debian package, we currently maintain lists like:
dbau1100 u-boot.img
dockstar u-boot.kwb
eNET u-boot.bin
efikamx u-boot.imx
omap4_panda MLO u-boot.bin
[...]
for two reasons:
- because we need to call make u-boot.kwb explicitly to get it built
- to list the files from the obj-dir that we actually want in the .deb
it would be nicer for the packaging, but I guess also for u-boot
maintainers, if these files were just generated by default when one
calls "make".
The subsequent patches will generate u-boot.imx and u-boot.kwb when
it's obvious that these are desired.
However, I didn't manage to find hints in the u-boot tree on when
"u-boot.img" should be generated, and when u-boot.bin is enough;
apparently one can mkimage -T firmware for any board config. Ideas
welcome on how to detect these.
Thanks,
--
Loïc Minier
8
22
This patch adds initial support for EMMA3SL/LP board.
Network and USB support will be added as follow up patches.
Signed-off-by: Serge Ziryukin <ftrvxmtrx(a)gmail.com>
---
MAINTAINERS | 4 +
MAKEALL | 1 +
Makefile | 3 +
board/emma3sllp/Makefile | 45 +++++++++
board/emma3sllp/config.mk | 28 ++++++
board/emma3sllp/emma3sllp.c | 39 ++++++++
board/emma3sllp/emma3sllp.h | 51 +++++++++++
board/emma3sllp/lowlevel_init.S | 190 +++++++++++++++++++++++++++++++++++++++
board/emma3sllp/u-boot.lds | 70 ++++++++++++++
doc/README.emma3sllp | 10 ++
include/configs/emma3sllp.h | 131 +++++++++++++++++++++++++++
11 files changed, 572 insertions(+), 0 deletions(-)
create mode 100644 board/emma3sllp/Makefile
create mode 100644 board/emma3sllp/config.mk
create mode 100644 board/emma3sllp/emma3sllp.c
create mode 100644 board/emma3sllp/emma3sllp.h
create mode 100644 board/emma3sllp/lowlevel_init.S
create mode 100644 board/emma3sllp/u-boot.lds
create mode 100644 doc/README.emma3sllp
create mode 100644 include/configs/emma3sllp.h
diff --git a/MAINTAINERS b/MAINTAINERS
index 5cbc845..ec5927d 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -841,6 +841,10 @@ Stefan Roese <sr(a)denx.de>
vct_xxx MIPS32 4Kc
+Serge Ziryukin <ftrvxmtrx(a)gmail.com>
+
+ emma3sllp MIPS32 4KEc
+
#########################################################################
# Nios-32 Systems: #
# #
diff --git a/MAKEALL b/MAKEALL
index bb09627..75c07ef 100755
--- a/MAKEALL
+++ b/MAKEALL
@@ -741,6 +741,7 @@ LIST_arm=" \
#########################################################################
LIST_mips4kc=" \
+ emma3sllp \
incaip \
qemu_mips \
vct_platinum \
diff --git a/Makefile b/Makefile
index 82cbbf4..0bbbbf1 100644
--- a/Makefile
+++ b/Makefile
@@ -3408,6 +3408,9 @@ vct_platinumavc_onenand_small_config: unconfig
fi
@$(MKCONFIG) -a vct mips mips vct micronas
+emma3sllp_config: unconfig
+ @$(MKCONFIG) $(@:_config=) mips mips emma3sllp
+
#########################################################################
## MIPS32 AU1X00
#########################################################################
diff --git a/board/emma3sllp/Makefile b/board/emma3sllp/Makefile
new file mode 100644
index 0000000..aa42b44
--- /dev/null
+++ b/board/emma3sllp/Makefile
@@ -0,0 +1,45 @@
+#
+# (C) Copyright 2003-2006
+# Wolfgang Denk, DENX Software Engineering, wd(a)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 = $(BOARD).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)
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/board/emma3sllp/config.mk b/board/emma3sllp/config.mk
new file mode 100644
index 0000000..d4ff9b5
--- /dev/null
+++ b/board/emma3sllp/config.mk
@@ -0,0 +1,28 @@
+#
+# (C) Copyright 2010
+# Serge Ziryukin, ftrvxmtrx(a)gmail.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
+#
+
+#
+# EMMA3SL/LP
+#
+
+TEXT_BASE = 0xbc000000
diff --git a/board/emma3sllp/emma3sllp.c b/board/emma3sllp/emma3sllp.c
new file mode 100644
index 0000000..ff6e12a
--- /dev/null
+++ b/board/emma3sllp/emma3sllp.c
@@ -0,0 +1,39 @@
+/*
+ * (C) Copyright 2010
+ * Serge Ziryukin, ftrvxmtrx(a)gmail.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 <configs/emma3sllp.h>
+#include <asm/io.h>
+#include "emma3sllp.h"
+
+phys_size_t initdram(int board_type)
+{
+ return CONFIG_SYS_SDRAM_SIZE;
+}
+
+int checkboard(void)
+{
+ puts("EMMA3SL/LP\n");
+
+ return 0;
+}
diff --git a/board/emma3sllp/emma3sllp.h b/board/emma3sllp/emma3sllp.h
new file mode 100644
index 0000000..335f6fd
--- /dev/null
+++ b/board/emma3sllp/emma3sllp.h
@@ -0,0 +1,51 @@
+/*
+ * (C) Copyright 2010
+ * Serge Ziryukin, ftrvxmtrx(a)gmail.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 __EMMA3SLLP_H
+#define __EMMA3SLLP_H
+
+/* host interface */
+#define BHIF_BASE_ADDRESS 0xb0000000
+#define BHIF_ALTERNATE0 0x28
+
+/* rom interface */
+#define BROI_BASE_ADDRESS 0xb0000600
+#define BROI_ROM_MODE 0x00
+#define BROI_ROM_IF_MODE 0x08
+
+/* memory interface */
+#define MIF_BASE_ADDRESS 0xb0000c00
+#define MIF_CONFIG1 0x04
+#define MIF_INIT 0x08
+#define MIF_REFCNT 0x0c
+#define MIF_CONFIG2 0x10
+#define MIF_DLLSTBY 0xf0
+#define MIF_DLLCTRL 0xf4
+#define MIF_DLLOFSTW 0xf8
+#define MIF_DLLOFSTR 0xfc
+#define MIF_RSTB 0xe0
+#define MIF_ODTSW 0xe4
+#define MIF_IOLHRSTB 0xe8
+#define MIF_IOLHCTRL 0xec
+
+#endif /* __EMMA3SLLP_H */
diff --git a/board/emma3sllp/lowlevel_init.S b/board/emma3sllp/lowlevel_init.S
new file mode 100644
index 0000000..689e6dc
--- /dev/null
+++ b/board/emma3sllp/lowlevel_init.S
@@ -0,0 +1,190 @@
+/*
+ * (C) Copyright 2010
+ * Serge Ziryukin, ftrvxmtrx(a)gmail.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 <config.h>
+#include <asm/asm.h>
+#include <asm/regdef.h>
+#include "emma3sllp.h"
+
+.text
+.set noreorder
+.set mips32
+
+.macro REGWR offset, val
+ li t1, \val
+ sw t1, \offset(t0)
+.endm
+
+#define MEM_200US (200 * CPU_CLOCK_RATE / 1000000)
+
+.global lowlevel_init
+lowlevel_init:
+
+ /* =================================== */
+ /* enable peripherals */
+ /* =================================== */
+ li t0, BHIF_BASE_ADDRESS
+
+ /* 17: usb, 18: ethernet, 19: fuart0 */
+ REGWR BHIF_ALTERNATE0 0x000e0000
+
+ /* =================================== */
+ /* set flash options */
+ /* =================================== */
+ li t0, BROI_BASE_ADDRESS
+
+ /* change max size flash rom to 64Mb
+ to make it start from 0xbc000000 */
+ lw t1, BROI_ROM_MODE(t0)
+ li t2, 0x08
+ sub t2, zero, t2
+ and t1, t1, t2
+ ori t1, t1, 0x04
+ sw t1, BROI_ROM_MODE(t0)
+
+ /* enable write (for 4 possible flash chips) */
+ lw t1, BROI_ROM_IF_MODE(t0)
+ ori t1, t1, 0x0f
+ sw t1, BROI_ROM_IF_MODE(t0)
+
+ /* =================================== */
+ /* DDR2 initialization */
+ /* =================================== */
+ li t0, MIF_BASE_ADDRESS
+
+ /*
+ set wiring delay
+ 91-467ps @ 327.68MHz
+ 110-440ps @ 333.33MHz
+ */
+ REGWR MIF_DLLOFSTW 0x0000e1e1
+ REGWR MIF_DLLOFSTR 0x00002424
+
+ /* 316-350MHz (FSL=6) */
+ REGWR MIF_DLLCTRL 0x00000020
+
+ /* exit from stand-by mode */
+ REGWR MIF_DLLSTBY 0x00000000
+
+ /* clear rst */
+ REGWR MIF_IOLHRSTB 0x00000001
+
+ /* wait until locked */
+ li t2, 0x1
+1:
+ lw t1, MIF_DLLCTRL(t0)
+ and t1, t2
+ bne t1, t2, 1b
+ nop
+
+ /* wait until fixed */
+ li t2, 0x1
+1:
+ lw t1, MIF_IOLHCTRL(t0)
+ and t1, t2
+ bne t1, t2, 1b
+ nop
+
+ /* clear rst */
+ REGWR MIF_RSTB 0x00000001
+
+ /* set on-die termination to 75ohm and enable clock */
+ REGWR MIF_ODTSW 0x00000101
+
+ /* 200us */
+ li t2, MEM_200US
+1:
+ bne t2, zero, 1b
+ addi t2, -1
+
+ /*
+ column 10 bits (A0 - A9), row 13 bits (A0 - A12)
+ CAS latency 5, 16-bit bus, 4 banks
+ */
+ REGWR MIF_CONFIG1 0x74ba1b65
+
+ /* small PCB delay, one CS, 64Mb */
+ REGWR MIF_CONFIG2 0x0aa20049
+
+ /* CKE high */
+ REGWR MIF_INIT 0x00000020
+
+ /* 400ns */
+ .rept 16
+ nop
+ .endr
+
+ /* precharge all banks (BA0=0, BA1=0, A10=1) */
+ REGWR MIF_INIT 0x10000004
+ /* EMRS(2): (BA1=1, BA0=0, Ax=0) */
+ REGWR MIF_INIT 0x00020002
+ /* EMRS(3): (BA0=1, BA1=1, Ax=0) */
+ REGWR MIF_INIT 0x00030002
+ /* EMRS(1): enable DLL (BA0=1, BA1=0, Ax=0) */
+ REGWR MIF_INIT 0x00010002
+
+ /*
+ MRS: reset DLL (A8=1), BL=4 (A1=1)
+ CL=5 (A4=1, A6=1), WR=5 (A11=1)
+ */
+ REGWR MIF_INIT 0x25480002
+
+ /* 200us */
+ li t2, MEM_200US
+1:
+ bne t2, zero, 1b
+ addi t2, -1
+
+ /* precharge all banks (BA0=0, BA1=0, A10=1) */
+ REGWR MIF_INIT 0x10000004
+ /* refresh */
+ REGWR MIF_INIT 0x00000001
+ /* refresh */
+ REGWR MIF_INIT 0x00000001
+
+ /* 100ns */
+ .rept 4
+ nop
+ .endr
+
+ /*
+ MRS: clear DLL reset flag (A8=0)
+ leave other parms as in earlier issued MRS
+ */
+ REGWR MIF_INIT 0x21480002
+
+ /*
+ EMRS(1): OCD calibration
+ driver strength weak (A1=1), Rtt=75ohm (A2=1, A6=0)
+ */
+ REGWR MIF_INIT 0x00590002
+
+ /*
+ set refresh interval to (0x50 * 16 * SCLK)
+ register = (0x50 | REFRESH_ENABLE)
+ REFRESH_ENABLE = 0x100
+ */
+ REGWR MIF_REFCNT 0x00000150
+
+ jr ra
+ nop
diff --git a/board/emma3sllp/u-boot.lds b/board/emma3sllp/u-boot.lds
new file mode 100644
index 0000000..73979af
--- /dev/null
+++ b/board/emma3sllp/u-boot.lds
@@ -0,0 +1,70 @@
+/*
+ * (C) Copyright 2003
+ * Wolfgang Denk Engineering, <wd(a)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-bigmips", "elf32-bigmips", "elf32-bigmips")
+*/
+OUTPUT_FORMAT("elf32-tradbigmips", "elf32-tradbigmips", "elf32-tradbigmips")
+OUTPUT_ARCH(mips)
+ENTRY(_start)
+SECTIONS
+{
+ . = 0x00000000;
+
+ . = ALIGN(4);
+ .text :
+ {
+ *(.text)
+ }
+
+ . = ALIGN(4);
+ .rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }
+
+ . = ALIGN(4);
+ .data : { *(.data) }
+
+ . = .;
+ _gp = ALIGN(16) + 0x7ff0;
+
+ .got : {
+ __got_start = .;
+ *(.got)
+ __got_end = .;
+ }
+
+ .sdata : { *(.sdata) }
+
+ .u_boot_cmd : {
+ __u_boot_cmd_start = .;
+ *(.u_boot_cmd)
+ __u_boot_cmd_end = .;
+ }
+
+ uboot_end_data = .;
+ num_got_entries = (__got_end - __got_start ) >> 2;
+
+ . = ALIGN(4);
+ .sbss (NOLOAD) : { *(.sbss) }
+ .bss (NOLOAD) : { *(.bss) . = ALIGN(4); }
+ uboot_end = .;
+}
diff --git a/doc/README.emma3sllp b/doc/README.emma3sllp
new file mode 100644
index 0000000..dfefa9a
--- /dev/null
+++ b/doc/README.emma3sllp
@@ -0,0 +1,10 @@
+EMMA3SL/LP
+
+generation: 0x02000011 (EMMA3SL/L)
+product version: 0x018e
+cpu: 4KEc, 288MHz
+endianess: big
+unified mem clock: 156MHz (SCLK = MCLK/2 = 312/2)
+flash: S29GL064N90BFI04 (8Mb, 16bit, bottom boot)
+memory: EDE5116AJBG-6E-E (64Mb, 16bit, 667Mbps)
+ethernet: KSZ8041NL, RMII
diff --git a/include/configs/emma3sllp.h b/include/configs/emma3sllp.h
new file mode 100644
index 0000000..599104e
--- /dev/null
+++ b/include/configs/emma3sllp.h
@@ -0,0 +1,131 @@
+/*
+ * (C) Copyright 2010
+ * Serge Ziryukin, ftrvxmtrx(a)gmail.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 __CONFIG_H
+#define __CONFIG_H
+
+#include <asm/addrspace.h>
+
+#define CONFIG_BOOT_RETRY_TIME -1
+#define CONFIG_MIPS32 1
+
+#define CPU_CLOCK_RATE 288000000
+
+#define CONFIG_BOOTDELAY 5
+#define CONFIG_ZERO_BOOTDELAY_CHECK
+
+#define CONFIG_TIMESTAMP
+#define CONFIG_CMDLINE_EDITING 1
+#define CONFIG_BOOTARGS ""
+#define CONFIG_EXTRA_ENV_SETTINGS ""
+#define CONFIG_BOOTCOMMAND ""
+#include <config_cmd_default.h>
+
+#define CONFIG_CMD_ASKENV
+#define CONFIG_CMD_FLASH
+#define CONFIG_CMD_SAVEENV
+
+#undef CONFIG_CMD_MII
+#undef CONFIG_CMD_PING
+#undef CONFIG_CMD_DHCP
+#undef CONFIG_CMD_NET
+#undef CONFIG_CMD_USB
+#undef CONFIG_CMD_FAT
+
+#define CONFIG_CMD_REGINFO
+#define CONFIG_CMD_BSP
+#define CONFIG_CMD_ELF
+#define CONFIG_CMD_UNZIP
+#define CONFIG_CMD_PORTIO
+
+#define CONFIG_SYS_LONGHELP
+#define CONFIG_SYS_PROMPT "> "
+#define CONFIG_SYS_CBSIZE 256
+#define CONFIG_SYS_PBSIZE \
+ (CONFIG_SYS_CBSIZE + sizeof(CONFIG_SYS_PROMPT) + 16)
+#define CONFIG_SYS_MAXARGS 16
+
+/* 256Kb */
+#define CONFIG_SYS_MALLOC_LEN (256 << 10)
+/* 64Kb */
+#define CONFIG_SYS_BOOTPARAMS_LEN (64 << 10)
+
+#define CONFIG_SYS_HZ 1000
+#define CONFIG_SYS_MIPS_TIMER_FREQ (CPU_CLOCK_RATE / 2)
+
+#define CONFIG_SYS_SDRAM_BASE 0x80000000
+#define CONFIG_SYS_SDRAM_SIZE (64 << 20)
+#define CONFIG_NR_DRAM_BANKS 1
+
+#define CONFIG_SYS_LOAD_ADDR 0x80400000
+#define CONFIG_SYS_MEMTEST_START 0x80000000
+#define CONFIG_SYS_MEMTEST_END 0x80800000
+
+#define CONFIG_SYS_INIT_SP_OFFSET 0x400000
+
+/* one flash bank */
+#define PHYS_FLASH_1 0xbc000000
+#define CONFIG_SYS_MAX_FLASH_BANKS 1
+#define CONFIG_SYS_MAX_FLASH_SECT 135
+#define CONFIG_SYS_FLASH_BASE PHYS_FLASH_1
+#define CONFIG_SYS_FLASH_BANKS_LIST { CONFIG_SYS_FLASH_BASE }
+#define CONFIG_SYS_FLASH_PROTECTION 1
+
+/* erase/write timeouts in ticks */
+#define CONFIG_SYS_FLASH_ERASE_TOUT (2 * CONFIG_SYS_HZ)
+#define CONFIG_SYS_FLASH_WRITE_TOUT (2 * CONFIG_SYS_HZ)
+
+#define CONFIG_FLASH_CFI_DRIVER
+#define CONFIG_SYS_FLASH_CFI
+#define CONFIG_SYS_FLASH_CFI_WIDTH FLASH_CFI_16BIT
+/* print 'E' for empty sector on flinfo */
+#define CONFIG_SYS_FLASH_EMPTY_INFO
+
+#define CONFIG_SYS_MONITOR_BASE TEXT_BASE
+#define CONFIG_SYS_MONITOR_LEN 0x40000
+
+/* env on flash */
+#define CONFIG_ENV_ADDR \
+ (PHYS_FLASH_1 + CONFIG_SYS_MONITOR_LEN)
+#define CONFIG_ENV_SIZE (64 << 10)
+#define CONFIG_ENV_SECT_SIZE CONFIG_ENV_SIZE
+#define CONFIG_ENV_IS_IN_FLASH
+#define CONFIG_ENV_OVERWRITE
+
+/* cache */
+#define CONFIG_SYS_DCACHE_SIZE (8 << 10) /* 8kB */
+#define CONFIG_SYS_ICACHE_SIZE (8 << 10) /* 8kB */
+#define CONFIG_SYS_CACHELINE_SIZE 16
+
+/* serial */
+#define CONFIG_SYS_NS16550
+#define CONFIG_SYS_NS16550_SERIAL
+#define CONFIG_SYS_NS16550_REG_SIZE 4
+#define CONFIG_SYS_NS16550_CLK 18432000
+#define CONFIG_SYS_NS16550_COM1 0xb0101000
+#define CONFIG_SYS_NS16550_COM2 0xb0102000
+#define CONFIG_CONS_INDEX 1
+#define CONFIG_BAUDRATE 115200
+#define CONFIG_SYS_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200 }
+
+#endif /* __CONFIG_H */
--
1.7.1
3
3
This aligns buffers,passed to usb controller at
dcache boundary.
Buffer "stop" address = "start" address + size.
Stop address can not be aligned even though
"start" address is aligned as size does not fall
at cache line boundary. Therefore "debug" in place of
"printf" is added in "arch/arm/cpu/armv7/cache_v7.c".
Cleaning and invalidating last cache line to avoid
stale data to be reused.
Ignoring "checkpatch.pl" warnings to replace "__attribute__((packed))"
by "__packed" and "__attribute__((aligned(size)))" by "__aligned(size)".
As "__GNUC__" directive should be defined to use "__packed" and
"__aligned(size)" and current patch is not supporting it, ignoring
the "checkpatch.pl" warning.
Signed-off-by: Puneet Saxena <puneets(a)nvidia.com>
Signed-off-by: Jim Lin <jilin(a)nvidia.com>
---
The patch is applicable on tegra U-Boot Custodian Tree owned by Tom Warren.
To apply the patch clone "git://git.denx.de/u-boot-tegra.git" and checkout
"test" branch.
arch/arm/cpu/armv7/cache_v7.c | 8 ++++-
common/cmd_usb.c | 3 +-
common/usb.c | 42 ++++++++++++++++------------
common/usb_storage.c | 60 ++++++++++++++++++++++++-----------------
drivers/usb/host/ehci-hcd.c | 12 ++++++++
include/scsi.h | 8 +++++-
include/usb.h | 8 +++++-
7 files changed, 93 insertions(+), 48 deletions(-)
diff --git a/arch/arm/cpu/armv7/cache_v7.c b/arch/arm/cpu/armv7/cache_v7.c
index 1b4e808..435d08b 100644
--- a/arch/arm/cpu/armv7/cache_v7.c
+++ b/arch/arm/cpu/armv7/cache_v7.c
@@ -192,12 +192,16 @@ static void v7_dcache_inval_range(u32 start, u32 stop, u32 line_len)
}
/*
+ * We can't avoid stop address not aligned with cache-line.
+ * Allocating cache -aligned buffer might waste memory.
* If stop address is not aligned to cache-line do not
- * invalidate the last cache-line
+ * invalidate the last cache-line and flush the last
+ * line to prevent affecting somebody else's buffer.
*/
if (stop & (line_len - 1)) {
- printf("ERROR: %s - stop address is not aligned - 0x%08x\n",
+ debug("ERROR: %s - stop address is not aligned - 0x%08x\n",
__func__, stop);
+ v7_dcache_clean_inval_range(stop, stop + 1, line_len);
/* align to the beginning of this cache line */
stop &= ~(line_len - 1);
}
diff --git a/common/cmd_usb.c b/common/cmd_usb.c
index 320667f..bca9d94 100644
--- a/common/cmd_usb.c
+++ b/common/cmd_usb.c
@@ -150,7 +150,8 @@ void usb_display_class_sub(unsigned char dclass, unsigned char subclass,
void usb_display_string(struct usb_device *dev, int index)
{
- char buffer[256];
+ ALLOC_CACHE_ALIGN_BUFFER(char, buffer, 256);
+
if (index != 0) {
if (usb_string(dev, index, &buffer[0], 256) > 0)
printf("String: \"%s\"", buffer);
diff --git a/common/usb.c b/common/usb.c
index 63a11c8..07f7ed6 100644
--- a/common/usb.c
+++ b/common/usb.c
@@ -73,7 +73,12 @@ static struct usb_device usb_dev[USB_MAX_DEVICE];
static int dev_index;
static int running;
static int asynch_allowed;
-static struct devrequest setup_packet;
+#ifdef CONFIG_SYS_CACHELINE_SIZE
+ static struct devrequest setup_packet
+ __attribute__((aligned(CONFIG_SYS_CACHELINE_SIZE)));
+#else
+ static struct devrequest setup_packet;
+#endif
char usb_started; /* flag for the started/stopped USB status */
@@ -694,7 +699,7 @@ static int usb_string_sub(struct usb_device *dev, unsigned int langid,
*/
int usb_string(struct usb_device *dev, int index, char *buf, size_t size)
{
- unsigned char mybuf[USB_BUFSIZ];
+ ALLOC_CACHE_ALIGN_BUFFER(unsigned char, mybuf, USB_BUFSIZ);
unsigned char *tbuf;
int err;
unsigned int u, idx;
@@ -794,7 +799,7 @@ int usb_new_device(struct usb_device *dev)
{
int addr, err;
int tmp;
- unsigned char tmpbuf[USB_BUFSIZ];
+ ALLOC_CACHE_ALIGN_BUFFER(unsigned char, tmpbuf, USB_BUFSIZ);
/* We still haven't set the Address yet */
addr = dev->devnum;
@@ -921,8 +926,8 @@ int usb_new_device(struct usb_device *dev)
le16_to_cpus(&dev->descriptor.idProduct);
le16_to_cpus(&dev->descriptor.bcdDevice);
/* only support for one config for now */
- usb_get_configuration_no(dev, &tmpbuf[0], 0);
- usb_parse_config(dev, &tmpbuf[0], 0);
+ usb_get_configuration_no(dev, tmpbuf, 0);
+ usb_parse_config(dev, tmpbuf, 0);
usb_set_maxpacket(dev);
/* we set the default configuration here */
if (usb_set_configuration(dev, dev->config.desc.bConfigurationValue)) {
@@ -1076,7 +1081,7 @@ static int hub_port_reset(struct usb_device *dev, int port,
unsigned short *portstat)
{
int tries;
- struct usb_port_status portsts;
+ ALLOC_CACHE_ALIGN_BUFFER(struct usb_port_status, portsts, 1);
unsigned short portstatus, portchange;
USB_HUB_PRINTF("hub_port_reset: resetting port %d...\n", port);
@@ -1085,13 +1090,13 @@ static int hub_port_reset(struct usb_device *dev, int port,
usb_set_port_feature(dev, port + 1, USB_PORT_FEAT_RESET);
wait_ms(200);
- if (usb_get_port_status(dev, port + 1, &portsts) < 0) {
+ if (usb_get_port_status(dev, port + 1, portsts) < 0) {
USB_HUB_PRINTF("get_port_status failed status %lX\n",
dev->status);
return -1;
}
- portstatus = le16_to_cpu(portsts.wPortStatus);
- portchange = le16_to_cpu(portsts.wPortChange);
+ portstatus = le16_to_cpu(portsts->wPortStatus);
+ portchange = le16_to_cpu(portsts->wPortChange);
USB_HUB_PRINTF("portstatus %x, change %x, %s\n",
portstatus, portchange,
@@ -1129,19 +1134,19 @@ static int hub_port_reset(struct usb_device *dev, int port,
void usb_hub_port_connect_change(struct usb_device *dev, int port)
{
struct usb_device *usb;
- struct usb_port_status portsts;
+ ALLOC_CACHE_ALIGN_BUFFER(struct usb_port_status, portsts, 1);
unsigned short portstatus;
/* Check status */
- if (usb_get_port_status(dev, port + 1, &portsts) < 0) {
+ if (usb_get_port_status(dev, port + 1, portsts) < 0) {
USB_HUB_PRINTF("get_port_status failed\n");
return;
}
- portstatus = le16_to_cpu(portsts.wPortStatus);
+ portstatus = le16_to_cpu(portsts->wPortStatus);
USB_HUB_PRINTF("portstatus %x, change %x, %s\n",
portstatus,
- le16_to_cpu(portsts.wPortChange),
+ le16_to_cpu(portsts->wPortChange),
portspeed(portstatus));
/* Clear the connection change status */
@@ -1190,7 +1195,8 @@ void usb_hub_port_connect_change(struct usb_device *dev, int port)
int usb_hub_configure(struct usb_device *dev)
{
int i;
- unsigned char buffer[USB_BUFSIZ], *bitmap;
+ ALLOC_CACHE_ALIGN_BUFFER(unsigned char, buffer, USB_BUFSIZ);
+ unsigned char *bitmap;
struct usb_hub_descriptor *descriptor;
struct usb_hub_device *hub;
#ifdef USB_HUB_DEBUG
@@ -1312,16 +1318,16 @@ int usb_hub_configure(struct usb_device *dev)
usb_hub_power_on(hub);
for (i = 0; i < dev->maxchild; i++) {
- struct usb_port_status portsts;
+ ALLOC_CACHE_ALIGN_BUFFER(struct usb_port_status, portsts, 1);
unsigned short portstatus, portchange;
- if (usb_get_port_status(dev, i + 1, &portsts) < 0) {
+ if (usb_get_port_status(dev, i + 1, portsts) < 0) {
USB_HUB_PRINTF("get_port_status failed\n");
continue;
}
- portstatus = le16_to_cpu(portsts.wPortStatus);
- portchange = le16_to_cpu(portsts.wPortChange);
+ portstatus = le16_to_cpu(portsts->wPortStatus);
+ portchange = le16_to_cpu(portsts->wPortChange);
USB_HUB_PRINTF("Port %d Status %X Change %X\n",
i + 1, portstatus, portchange);
diff --git a/common/usb_storage.c b/common/usb_storage.c
index de84c8d..71e13b1 100644
--- a/common/usb_storage.c
+++ b/common/usb_storage.c
@@ -79,8 +79,18 @@ static const unsigned char us_direction[256/8] = {
};
#define US_DIRECTION(x) ((us_direction[x>>3] >> (x & 7)) & 1)
-static unsigned char usb_stor_buf[512];
-static ccb usb_ccb;
+#ifdef CONFIG_SYS_CACHELINE_SIZE
+ static unsigned char usb_stor_buf[512]
+ __attribute__((aligned(CONFIG_SYS_CACHELINE_SIZE)));
+#else
+ static unsigned char usb_stor_buf[512];
+#endif
+
+#ifdef CONFIG_SYS_CACHELINE_SIZE
+ static ccb usb_ccb __attribute__((aligned(CONFIG_SYS_CACHELINE_SIZE)));
+#else
+ static ccb usb_ccb;
+#endif
/*
* CBI style
@@ -210,17 +220,17 @@ int usb_stor_info(void)
static unsigned int usb_get_max_lun(struct us_data *us)
{
int len;
- unsigned char result;
+ ALLOC_CACHE_ALIGN_BUFFER(unsigned char, result, 1);
len = usb_control_msg(us->pusb_dev,
usb_rcvctrlpipe(us->pusb_dev, 0),
US_BBB_GET_MAX_LUN,
USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
0, us->ifnum,
- &result, sizeof(result),
+ result, sizeof(char),
USB_CNTL_TIMEOUT * 5);
USB_STOR_PRINTF("Get Max LUN -> len = %i, result = %i\n",
- len, (int) result);
- return (len > 0) ? result : 0;
+ len, (int) *result);
+ return (len > 0) ? *result : 0;
}
/*******************************************************************************
@@ -499,7 +509,7 @@ int usb_stor_BBB_comdat(ccb *srb, struct us_data *us)
int actlen;
int dir_in;
unsigned int pipe;
- umass_bbb_cbw_t cbw;
+ ALLOC_CACHE_ALIGN_BUFFER(umass_bbb_cbw_t, cbw, 1);
dir_in = US_DIRECTION(srb->cmd[0]);
@@ -522,16 +532,16 @@ int usb_stor_BBB_comdat(ccb *srb, struct us_data *us)
/* always OUT to the ep */
pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
- cbw.dCBWSignature = cpu_to_le32(CBWSIGNATURE);
- cbw.dCBWTag = cpu_to_le32(CBWTag++);
- cbw.dCBWDataTransferLength = cpu_to_le32(srb->datalen);
- cbw.bCBWFlags = (dir_in ? CBWFLAGS_IN : CBWFLAGS_OUT);
- cbw.bCBWLUN = srb->lun;
- cbw.bCDBLength = srb->cmdlen;
+ cbw->dCBWSignature = cpu_to_le32(CBWSIGNATURE);
+ cbw->dCBWTag = cpu_to_le32(CBWTag++);
+ cbw->dCBWDataTransferLength = cpu_to_le32(srb->datalen);
+ cbw->bCBWFlags = (dir_in ? CBWFLAGS_IN : CBWFLAGS_OUT);
+ cbw->bCBWLUN = srb->lun;
+ cbw->bCDBLength = srb->cmdlen;
/* copy the command data into the CBW command data buffer */
/* DST SRC LEN!!! */
- memcpy(cbw.CBWCDB, srb->cmd, srb->cmdlen);
- result = usb_bulk_msg(us->pusb_dev, pipe, &cbw, UMASS_BBB_CBW_SIZE,
+ memcpy(cbw->CBWCDB, srb->cmd, srb->cmdlen);
+ result = usb_bulk_msg(us->pusb_dev, pipe, cbw, UMASS_BBB_CBW_SIZE,
&actlen, USB_CNTL_TIMEOUT * 5);
if (result < 0)
USB_STOR_PRINTF("usb_stor_BBB_comdat:usb_bulk_msg error\n");
@@ -675,7 +685,7 @@ int usb_stor_BBB_transport(ccb *srb, struct us_data *us)
int dir_in;
int actlen, data_actlen;
unsigned int pipe, pipein, pipeout;
- umass_bbb_csw_t csw;
+ ALLOC_CACHE_ALIGN_BUFFER(umass_bbb_csw_t, csw, 1);
#ifdef BBB_XPORT_TRACE
unsigned char *ptr;
int index;
@@ -733,7 +743,7 @@ st:
retry = 0;
again:
USB_STOR_PRINTF("STATUS phase\n");
- result = usb_bulk_msg(us->pusb_dev, pipein, &csw, UMASS_BBB_CSW_SIZE,
+ result = usb_bulk_msg(us->pusb_dev, pipein, csw, UMASS_BBB_CSW_SIZE,
&actlen, USB_CNTL_TIMEOUT*5);
/* special handling of STALL in STATUS phase */
@@ -753,28 +763,28 @@ again:
return USB_STOR_TRANSPORT_FAILED;
}
#ifdef BBB_XPORT_TRACE
- ptr = (unsigned char *)&csw;
+ ptr = (unsigned char *)csw;
for (index = 0; index < UMASS_BBB_CSW_SIZE; index++)
printf("ptr[%d] %#x ", index, ptr[index]);
printf("\n");
#endif
/* misuse pipe to get the residue */
- pipe = le32_to_cpu(csw.dCSWDataResidue);
+ pipe = le32_to_cpu(csw->dCSWDataResidue);
if (pipe == 0 && srb->datalen != 0 && srb->datalen - data_actlen != 0)
pipe = srb->datalen - data_actlen;
- if (CSWSIGNATURE != le32_to_cpu(csw.dCSWSignature)) {
+ if (CSWSIGNATURE != le32_to_cpu(csw->dCSWSignature)) {
USB_STOR_PRINTF("!CSWSIGNATURE\n");
usb_stor_BBB_reset(us);
return USB_STOR_TRANSPORT_FAILED;
- } else if ((CBWTag - 1) != le32_to_cpu(csw.dCSWTag)) {
+ } else if ((CBWTag - 1) != le32_to_cpu(csw->dCSWTag)) {
USB_STOR_PRINTF("!Tag\n");
usb_stor_BBB_reset(us);
return USB_STOR_TRANSPORT_FAILED;
- } else if (csw.bCSWStatus > CSWSTATUS_PHASE) {
+ } else if (csw->bCSWStatus > CSWSTATUS_PHASE) {
USB_STOR_PRINTF(">PHASE\n");
usb_stor_BBB_reset(us);
return USB_STOR_TRANSPORT_FAILED;
- } else if (csw.bCSWStatus == CSWSTATUS_PHASE) {
+ } else if (csw->bCSWStatus == CSWSTATUS_PHASE) {
USB_STOR_PRINTF("=PHASE\n");
usb_stor_BBB_reset(us);
return USB_STOR_TRANSPORT_FAILED;
@@ -782,7 +792,7 @@ again:
USB_STOR_PRINTF("transferred %dB instead of %ldB\n",
data_actlen, srb->datalen);
return USB_STOR_TRANSPORT_FAILED;
- } else if (csw.bCSWStatus == CSWSTATUS_FAILED) {
+ } else if (csw->bCSWStatus == CSWSTATUS_FAILED) {
USB_STOR_PRINTF("FAILED\n");
return USB_STOR_TRANSPORT_FAILED;
}
@@ -1343,7 +1353,7 @@ int usb_stor_get_info(struct usb_device *dev, struct us_data *ss,
block_dev_desc_t *dev_desc)
{
unsigned char perq, modi;
- unsigned long cap[2];
+ ALLOC_CACHE_ALIGN_BUFFER(unsigned long, cap, 2);
unsigned long *capacity, *blksz;
ccb *pccb = &usb_ccb;
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index d893b2a..7929c26 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -132,8 +132,20 @@ static void cache_qtd(struct qTD *qtd, int flush)
int len = (qtd->qt_token & 0x7fff0000) >> 16;
flush_invalidate((u32)qtd, sizeof(struct qTD), flush);
+
+ /*
+ * Invalidate cache for the aligned address
+ * and for the data length which is DMAed.
+ * Do not invalidate again intermidiate address
+ * as it may not be aligned.
+ */
+#if CONFIG_SYS_CACHELINE_SIZE
+ if (!((u32) ptr & (CONFIG_SYS_CACHELINE_SIZE - 1)) && len)
+ flush_invalidate((u32)ptr, len, flush);
+#else
if (ptr && len)
flush_invalidate((u32)ptr, len, flush);
+#endif
}
diff --git a/include/scsi.h b/include/scsi.h
index c52759c..c07b1dd 100644
--- a/include/scsi.h
+++ b/include/scsi.h
@@ -26,7 +26,13 @@
typedef struct SCSI_cmd_block{
unsigned char cmd[16]; /* command */
- unsigned char sense_buf[64]; /* for request sense */
+ /* for request sense */
+#ifdef CONFIG_SYS_CACHELINE_SIZE
+ unsigned char sense_buf[64]
+ __attribute__((aligned(CONFIG_SYS_CACHELINE_SIZE)));
+#else
+ unsigned char sense_buf[64];
+#endif
unsigned char status; /* SCSI Status */
unsigned char target; /* Target ID */
unsigned char lun; /* Target LUN */
diff --git a/include/usb.h b/include/usb.h
index 06170cd..55b786e 100644
--- a/include/usb.h
+++ b/include/usb.h
@@ -109,7 +109,13 @@ struct usb_device {
int epmaxpacketout[16]; /* OUTput endpoint specific maximums */
int configno; /* selected config number */
- struct usb_device_descriptor descriptor; /* Device Descriptor */
+ /* Device Descriptor */
+#ifdef CONFIG_SYS_CACHELINE_SIZE
+ struct usb_device_descriptor descriptor
+ __attribute__((aligned(CONFIG_SYS_CACHELINE_SIZE)));
+#else
+ struct usb_device_descriptor descriptor;
+#endif
struct usb_config config; /* config descriptor */
int have_langid; /* whether string_langid is valid yet */
--
1.7.1
10
82

02 Apr '12
This code differs in only trivial ways from the altera_spi driver. It plays
nice with Thomas Chou's mmc_spi driver, as well as with SPI flash.
Documentation for the SPI core is available here:
http://www.xilinx.com/support/documentation/ip_documentation/xps_spi.pdf
Signed-off-by: Graeme Smecher <graeme.smecher(a)mail.mcgill.ca>
---
drivers/spi/Makefile | 1 +
drivers/spi/xilinx_spi.c | 173 ++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 174 insertions(+), 0 deletions(-)
create mode 100644 drivers/spi/xilinx_spi.c
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index dfcbb8b..34e0f31 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -26,6 +26,7 @@ include $(TOPDIR)/config.mk
LIB := $(obj)libspi.a
COBJS-$(CONFIG_ALTERA_SPI) += altera_spi.o
+COBJS-$(CONFIG_XILINX_SPI) += xilinx_spi.o
COBJS-$(CONFIG_ATMEL_DATAFLASH_SPI) += atmel_dataflash_spi.o
COBJS-$(CONFIG_ATMEL_SPI) += atmel_spi.o
COBJS-$(CONFIG_BFIN_SPI) += bfin_spi.o
diff --git a/drivers/spi/xilinx_spi.c b/drivers/spi/xilinx_spi.c
new file mode 100644
index 0000000..bda7c5b
--- /dev/null
+++ b/drivers/spi/xilinx_spi.c
@@ -0,0 +1,173 @@
+/*
+ * Xilinx SPI driver
+ *
+ * based on bfin_spi.c, by way of altera_spi.c
+ * Copyright (c) 2005-2008 Analog Devices Inc.
+ * Copyright (c) 2010 Thomas Chou <thomas(a)wytron.com.tw>
+ * Copyright (c) 2010 Graeme Smecher <graeme.smecher(a)mail.mcgill.ca>
+ *
+ * Licensed under the GPL-2 or later.
+ */
+#include <common.h>
+#include <asm/io.h>
+#include <malloc.h>
+#include <spi.h>
+
+#define XILINX_SPI_RR 0x6c
+#define XILINX_SPI_TR 0x68
+#define XILINX_SPI_SR 0x64
+#define XILINX_SPI_CR 0x60
+#define XILINX_SPI_SSR 0x70
+
+#define XILINX_SPI_SR_RX_EMPTY_MSK 0x01
+
+#define XILINX_SPI_CR_DEFAULT (0x0006)
+#define XILINX_SPI_CR_MSS_MSK (0x0080)
+
+#if XPAR_XSPI_NUM_INSTANCES > 4
+# warning "The xilinx_spi driver will ignore some of your SPI peripherals!"
+#endif
+
+static ulong xilinx_spi_base_list[] = {
+#ifdef XPAR_SPI_0_BASEADDR
+ XPAR_SPI_0_BASEADDR,
+#endif
+#ifdef XPAR_SPI_1_BASEADDR
+ XPAR_SPI_1_BASEADDR,
+#endif
+#ifdef XPAR_SPI_2_BASEADDR
+ XPAR_SPI_2_BASEADDR,
+#endif
+#ifdef XPAR_SPI_3_BASEADDR
+ XPAR_SPI_3_BASEADDR,
+#endif
+};
+
+struct xilinx_spi_slave {
+ struct spi_slave slave;
+ ulong base;
+};
+#define to_xilinx_spi_slave(s) container_of(s, struct xilinx_spi_slave, slave)
+
+__attribute__((weak))
+int spi_cs_is_valid(unsigned int bus, unsigned int cs)
+{
+ return bus < ARRAY_SIZE(xilinx_spi_base_list) && cs < 32;
+}
+
+__attribute__((weak))
+void spi_cs_activate(struct spi_slave *slave)
+{
+ struct xilinx_spi_slave *xilspi = to_xilinx_spi_slave(slave);
+ writel(~(1 << slave->cs), xilspi->base + XILINX_SPI_SSR);
+ writel(XILINX_SPI_CR_DEFAULT | XILINX_SPI_CR_MSS_MSK,
+ xilspi->base + XILINX_SPI_CR);
+}
+
+__attribute__((weak))
+void spi_cs_deactivate(struct spi_slave *slave)
+{
+ struct xilinx_spi_slave *xilspi = to_xilinx_spi_slave(slave);
+
+ writel(XILINX_SPI_CR_DEFAULT, xilspi->base + XILINX_SPI_CR);
+ writel(~0, xilspi->base + XILINX_SPI_SSR);
+}
+
+void spi_init(void)
+{
+}
+
+struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
+ unsigned int max_hz, unsigned int mode)
+{
+ struct xilinx_spi_slave *xilspi;
+
+ if (!spi_cs_is_valid(bus, cs))
+ return NULL;
+
+ xilspi = malloc(sizeof(*xilspi));
+ if (!xilspi)
+ return NULL;
+
+ xilspi->slave.bus = bus;
+ xilspi->slave.cs = cs;
+ xilspi->base = xilinx_spi_base_list[bus];
+ debug("%s: bus:%i cs:%i base:%lx\n", __func__,
+ bus, cs, xilspi->base);
+
+ return &xilspi->slave;
+}
+
+void spi_free_slave(struct spi_slave *slave)
+{
+ struct xilinx_spi_slave *xilspi = to_xilinx_spi_slave(slave);
+ free(xilspi);
+}
+
+int spi_claim_bus(struct spi_slave *slave)
+{
+ struct xilinx_spi_slave *xilspi = to_xilinx_spi_slave(slave);
+
+ debug("%s: bus:%i cs:%i\n", __func__, slave->bus, slave->cs);
+ writel(XILINX_SPI_CR_DEFAULT, xilspi->base + XILINX_SPI_CR);
+ writel(~0, xilspi->base + XILINX_SPI_SSR);
+ return 0;
+}
+
+void spi_release_bus(struct spi_slave *slave)
+{
+ struct xilinx_spi_slave *xilspi = to_xilinx_spi_slave(slave);
+
+ debug("%s: bus:%i cs:%i\n", __func__, slave->bus, slave->cs);
+ writel(~0, xilspi->base + XILINX_SPI_SSR);
+}
+
+#ifndef CONFIG_XILINX_SPI_IDLE_VAL
+# define CONFIG_XILINX_SPI_IDLE_VAL 0xff
+#endif
+
+int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
+ void *din, unsigned long flags)
+{
+ struct xilinx_spi_slave *xilspi = to_xilinx_spi_slave(slave);
+ /* assume spi core configured to do 8 bit transfers */
+ uint bytes = bitlen / 8;
+ const uchar *txp = dout;
+ uchar *rxp = din;
+
+ debug("%s: bus:%i cs:%i bitlen:%i bytes:%i flags:%lx\n", __func__,
+ slave->bus, slave->cs, bitlen, bytes, flags);
+ if (bitlen == 0)
+ goto done;
+
+ if (bitlen % 8) {
+ flags |= SPI_XFER_END;
+ goto done;
+ }
+
+ /* empty read buffer */
+ while (!(readl(xilspi->base + XILINX_SPI_SR) &
+ XILINX_SPI_SR_RX_EMPTY_MSK))
+ readl(xilspi->base + XILINX_SPI_RR);
+
+ if (flags & SPI_XFER_BEGIN)
+ spi_cs_activate(slave);
+
+ while (bytes--) {
+ uchar d = txp ? *txp++ : CONFIG_XILINX_SPI_IDLE_VAL;
+ debug("%s: tx:%x ", __func__, d);
+ writel(d, xilspi->base + XILINX_SPI_TR);
+ while (readl(xilspi->base + XILINX_SPI_SR) &
+ XILINX_SPI_SR_RX_EMPTY_MSK)
+ ;
+ d = readl(xilspi->base + XILINX_SPI_RR);
+ if (rxp)
+ *rxp++ = d;
+ debug("rx:%x\n", d);
+ }
+ done:
+ if (flags & SPI_XFER_END)
+ spi_cs_deactivate(slave);
+
+ return 0;
+}
--
1.6.3.3
6
11
This series contains bugfixes and coding style cleanups.
Furthermore it contains some extensions for MIPS24k and MIPS34k cores
as preparation for merging the support for various Lantiq SoCs.
Daniel Schwierzeck (11):
MIPS: board.c: make checkpatch.pl clean
MIPS: board.c: fix warning if CONFIG_CMD_NET is not defined
MIPS: board.c: fix init of flash data in bd_info
MIPS: add register definition for EBase register
MIPS: add sleep handler for slave CPUs in multi-processor systems
MIPS: make cache operation mode configurable in dcache_enable()
MIPS: extend cache initialization for MIPS24K and MIPS34K cores
MIPS: add additional reserved vectors for MIPS24K and MIPS34K cores
MIPS: add header file for generic GPIO API
MIPS: add init hook for CPU specific initialization
MIPS: MAKEALL: fix lists for MIPSel and MIPS boards
MAKEALL | 11 +---
arch/mips/cpu/mips32/cache.S | 24 ++++++-
arch/mips/cpu/mips32/start.S | 37 ++++++++++-
arch/mips/include/asm/gpio.h | 13 ++++
arch/mips/include/asm/mipsregs.h | 20 ++++++
arch/mips/lib/board.c | 139 +++++++++++++++++++++-----------------
6 files changed, 171 insertions(+), 73 deletions(-)
create mode 100644 arch/mips/include/asm/gpio.h
--
1.7.7.2
9
49
Use GENERATED_GBL_DATA_SIZE for calculating CONFIG_SYS_INIT_SP_OFFSET.
Signed-off-by: Fabio Estevam <fabio.estevam(a)freescale.com>
---
include/configs/m28evk.h | 9 ++++++++-
1 files changed, 8 insertions(+), 1 deletions(-)
diff --git a/include/configs/m28evk.h b/include/configs/m28evk.h
index 39c841f..2b4871e 100644
--- a/include/configs/m28evk.h
+++ b/include/configs/m28evk.h
@@ -92,7 +92,14 @@
#define CONFIG_SYS_MEMTEST_END 0x40400000 /* 4 MB RAM test */
#define CONFIG_SYS_SDRAM_BASE PHYS_SDRAM_1
/* Point initial SP in SRAM so SPL can use it too. */
-#define CONFIG_SYS_INIT_SP_ADDR 0x00002000
+
+#define CONFIG_SYS_INIT_RAM_ADDR 0x00002000
+#define CONFIG_SYS_INIT_RAM_SIZE (128 * 1024)
+
+#define CONFIG_SYS_INIT_SP_OFFSET \
+ (CONFIG_SYS_INIT_RAM_SIZE - GENERATED_GBL_DATA_SIZE)
+#define CONFIG_SYS_INIT_SP_ADDR \
+ (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_SP_OFFSET)
/*
* We need to sacrifice first 4 bytes of RAM here to avoid triggering some
* strange BUG in ROM corrupting first 4 bytes of RAM when loading U-Boot
--
1.7.1
4
6