[U-Boot] [patch V3] [0/3] U-Boot Firetux board support (PNX8181)

Hi U-Boot mailling list,
This patchset adds a new ARM board with the NXP PNX8181 cpu to u-boot. The PNX8181 is an ARM926ej with an internal DSP (mostly used for Audio processing and VOIP codecs) and a baseband processor (used for DECT). The chip also features dual ethernet, digital to analog interface, spi, i2c and other SOC peripherals.
These boards have been build by NXP Semiconductors GmbH, Nuremberg, Germany and are now build by DSPG Technologies GmbH, Nuremberg, Germany.
Signed-off-by: Jürgen Schöw js@emlix.com Signed-off-by: Sebastian Hess sh@emlix.com Signed-off-by: Matthias Mwenzel nxp@mazzoo.de Signed-off-by: Dirk Hörner dirk.hoerner@dspg.com Signed-off-by: Andreas Weißel andreas.weissel@dspg.com ---
It took quite some time to rework the patchset to match your requierments. In this 3rd patchset the folling changes have been done:
- separate the network driver and move to drivers/net/ - use new network API - make network driver independ from board - use CONFIG_NET_MULTI-style API - initialize network driver with board_eth_init() - move board files to vendor directory dspg - implement a gpio driver for the gpio A pins - separate board detection - use deferent function for each hardware revision - create a led driver - move timer functions to SOC specific directory
Complete stats: MAINTAINERS | 4 + MAKEALL | 1 + Makefile | 7 + board/dspg/firetux/Makefile | 59 ++++ board/dspg/firetux/boardrevision.c | 299 ++++++++++++++++ board/dspg/firetux/config.mk | 44 +++ board/dspg/firetux/firetux.c | 413 ++++++++++++++++++++++ board/dspg/firetux/firetux.h | 144 ++++++++ board/dspg/firetux/gpio.c | 134 ++++++++ board/dspg/firetux/led.c | 169 +++++++++ board/dspg/firetux/lowlevel_init.S | 404 ++++++++++++++++++++++ board/dspg/firetux/memsetup.S | 381 +++++++++++++++++++++ board/dspg/firetux/nand.c | 68 ++++ board/dspg/firetux/relocate.S | 252 ++++++++++++++ board/dspg/firetux/u-boot.lds | 57 +++ cpu/arm926ejs/pnx8181/Makefile | 45 +++ cpu/arm926ejs/pnx8181/timer.c | 141 ++++++++ drivers/i2c/Makefile | 1 + drivers/i2c/pnx8181_i2c.c | 304 +++++++++++++++++ drivers/net/Makefile | 1 + drivers/net/ip3912.c | 659 ++++++++++++++++++++++++++++++++++++ drivers/net/ip3912.h | 174 ++++++++++ include/configs/firetux.h | 454 +++++++++++++++++++++++++ 23 files changed, 4215 insertions(+), 0 deletions(-)
Regards
Jürgen Schöw

cpu/arm926ejs/pnx8181/Makefile | 45 +++ cpu/arm926ejs/pnx8181/timer.c | 141 ++++++++ drivers/i2c/Makefile | 1 + drivers/i2c/pnx8181_i2c.c | 304 +++++++++++++++++
diff --git a/cpu/arm926ejs/pnx8181/Makefile b/cpu/arm926ejs/pnx8181/Makefile new file mode 100644 index 0000000..b34d9e8 --- /dev/null +++ b/cpu/arm926ejs/pnx8181/Makefile @@ -0,0 +1,45 @@ +# +# (C) Copyright 2000-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# See file CREDITS for list of people who contributed to this +# project. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# + +include $(TOPDIR)/config.mk + +LIB = $(obj)lib$(SOC).a + +COBJS = timer.o + +SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) +OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS)) + +all: $(obj).depend $(LIB) + +$(LIB): $(OBJS) + $(AR) $(ARFLAGS) $@ $(OBJS) + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/cpu/arm926ejs/pnx8181/timer.c b/cpu/arm926ejs/pnx8181/timer.c new file mode 100644 index 0000000..585aede --- /dev/null +++ b/cpu/arm926ejs/pnx8181/timer.c @@ -0,0 +1,141 @@ +/* + * pnx8181 SOC timer routines + * + * (C) Copyright 2007-2009, emlix GmbH, Germany + * Juergen Schoew js@emlix.com + * + * (C) Copyright 2008, DSPG Technologies GmbH, Germany + * (C) Copyright 2007, NXP Semiconductors Germany GmbH + * Matthias Wenzel, nxp@mazzoo.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 <common.h> +#include <asm/io.h> + +/* + * timer without interrupts + */ +/* timer */ +#define PNX8181_SCTU1_BASE 0xC2102000 +#define PNX8181_SCTU2_BASE 0xC2103000 + +#define PNX8181_SCTU_TIMxCR 0x00 +#define PNX8181_SCTU_TIMxRR 0x04 +#define PNX8181_SCTU_TIMxWR 0x08 +#define PNX8181_SCTU_TIMxC0 0x0c +#define PNX8181_SCTU_TIMxC1 0x10 +#define PNX8181_SCTU_TIMxC2 0x14 +#define PNX8181_SCTU_TIMxC3 0x18 +#define PNX8181_SCTU_TIMxSR 0x1c +#define PNX8181_SCTU_TIMxPR 0x20 + +/* + * U-Boot expects a 32 bit timer, running at CONFIG_SYS_HZ + * Keep total timer count to avoid losing decrements < div_timer + */ + +/* U-Boot ticks since startup */ +static ulong timestamp; +static ulong last_timer_read; + +/* + * starts up a counter + */ +void timer_init(void) +{ + /* set prescaler to have timer run at 64 kHz */ + writeb(0x00, (void *)(PNX8181_SCTU1_BASE + PNX8181_SCTU_TIMxPR)); + + /* timer reload value = 0xffff - 13824, overflow @ 1kHz */ + writew(0xca00, (void *)(PNX8181_SCTU1_BASE + PNX8181_SCTU_TIMxRR)); + + /* timer has no interrupt, run */ + writew(0x0001, (void *)(PNX8181_SCTU1_BASE + PNX8181_SCTU_TIMxCR)); + + /* init the timestamp */ + reset_timer_masked(); +} + +ulong get_timer(ulong base_ticks) +{ + return get_timer_masked() - base_ticks; +} + +/* + * converts the timer reading to U-Boot ticks + * the timestamp is the number of ticks since reset + */ +ulong get_timer_masked(void) +{ + /* get current count */ + ulong now = readw((void *)(PNX8181_SCTU1_BASE + PNX8181_SCTU_TIMxWR)); + + if (now < last_timer_read) + timestamp += 13824; + last_timer_read = now; + + /* + * FIXME this value is empirical! + * for some reason the calculated values are way to fast + */ + return (timestamp + now) / 64; +} + +/* + * timer without interrupts + */ +void reset_timer(void) +{ + reset_timer_masked(); +} + + +/* busy-loop spin-delay */ +void sdelay(unsigned long usec) +{ + ulong i, tmp; + tmp = 42; + for (i = 0 ; i < usec*3 ; i++) + /* avoid compiler optimisation */ + tmp = -tmp; +} + +/* delay usec useconds */ +void udelay(unsigned long usec) +{ + ulong tmo, tmp; + + /* Convert to U-Boot ticks */ + tmo = usec / 1500; + + tmp = get_timer_masked(); /* get current timestamp */ + tmo += tmp; /* form target timestamp */ + + /* loop till event */ + while (get_timer_masked() < tmo) + ; +} + +void reset_timer_masked(void) +{ + /* start "advancing" time stamp from 0 */ + timestamp = 0L; +} diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile index 6079c05..ef457a5 100644 --- a/drivers/i2c/Makefile +++ b/drivers/i2c/Makefile @@ -31,6 +31,7 @@ COBJS-$(CONFIG_DRIVER_OMAP1510_I2C) += omap1510_i2c.o COBJS-$(CONFIG_DRIVER_OMAP24XX_I2C) += omap24xx_i2c.o COBJS-$(CONFIG_SOFT_I2C) += soft_i2c.o COBJS-$(CONFIG_TSI108_I2C) += tsi108_i2c.o +COBJS-$(CONFIG_PNX8181_I2C) += pnx8181_i2c.o
COBJS := $(COBJS-y) SRCS := $(COBJS:.o=.c) diff --git a/drivers/i2c/pnx8181_i2c.c b/drivers/i2c/pnx8181_i2c.c new file mode 100644 index 0000000..75a76a4 --- /dev/null +++ b/drivers/i2c/pnx8181_i2c.c @@ -0,0 +1,304 @@ +/* + * (C) Copyright 2008-2009, emlix GmbH, Germany + * Juergen Schoew js@emlix.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 <common.h> +#include <asm/io.h> + +#define I2C_TIMEOUT 10000 +#define I2C_DELAY 10 + +#define ARM_VPB1_BASE_ADDR 0xC2000000 +#define ARM_VPB3_BASE_ADDR 0xC2200000 +#define ARM_VPB_SIZE_SHIFT 12 + +#define SCON_BASE_ADDR (ARM_VPB3_BASE_ADDR + (4<<ARM_VPB_SIZE_SHIFT)) +#define SCON_BASE SCON_BASE_ADDR +#define SCON_SYSMUX1_OFFSET (0x010) +#define SCON_SYSMUX1_REG (void *)(SCON_BASE + SCON_SYSMUX1_OFFSET) +#define SCON_GPIOA27_MUX_SHIFT 22 +#define SCON_GPIOA27_MUX_FIELD (0xFFFFFFFF-(3<<SCON_GPIOA27_MUX_SHIFT)) +#define SCON_GPIOA27_SCL (1<<SCON_GPIOA27_MUX_SHIFT) +#define SCON_GPIOA28_MUX_SHIFT 24 +#define SCON_GPIOA28_MUX_FIELD (0xFFFFFFFF-(3<<SCON_GPIOA28_MUX_SHIFT)) +#define SCON_GPIOA28_SDA (1<<SCON_GPIOA28_MUX_SHIFT) + +#define CGU_BASE_ADDR (ARM_VPB3_BASE_ADDR + (0<<ARM_VPB_SIZE_SHIFT)) +#define CGU_BASE (CGU_BASE_ADDR) +#define CGU_GATESC_OFFSET (0x008) +#define CGU_GATESC_REG (void *)(CGU_BASE + CGU_GATESC_OFFSET) +#define CGU_I2C1EN 0x00000020 +#define CGU_I2CEN CGU_I2C1EN + +#define I2C_BASE_ADDR (ARM_VPB1_BASE_ADDR + (1<<ARM_VPB_SIZE_SHIFT)) +#define I2C_BASE I2C_BASE_ADDR +#define I2C_CLKHI_OFFSET (0x00C) +#define I2C_CLKHI_REG (void *)(I2C_BASE + I2C_CLKHI_OFFSET) +#define I2C_CLKLO_OFFSET (0x010) +#define I2C_CLKLO_REG (void *)(I2C_BASE + I2C_CLKLO_OFFSET) +#define I2C_ADR_OFFSET (0x014) +#define I2C_ADR_REG (void *)(I2C_BASE + I2C_ADR_OFFSET) +#define I2C_SADDR_FIELD 0xFFFFFF80 +#define I2C_HOLDDAT_OFFSET (0x018) +#define I2C_HOLDDAT_REG (void *)(I2C_BASE + I2C_HOLDDAT_OFFSET) +#define I2C_CLKDIV_FIELD 0xFFFFFC00 +#define I2C_STS_OFFSET (0x004) +#define I2C_STS_REG (void *)(I2C_BASE + I2C_STS_OFFSET) +#define I2C_CTL_OFFSET (0x008) +#define I2C_CTL_REG (void *)(I2C_BASE + I2C_CTL_OFFSET) +#define I2C_TX_OFFSET (0x000) +#define I2C_TX_REG (void *)(I2C_BASE + I2C_TX_OFFSET) +#define I2C_RX_OFFSET (0x000) +#define I2C_RX_REG (void *)(I2C_BASE + I2C_RX_OFFSET) + +#define I2C_TDI 0x00000001 +#define I2C_AFI 0x00000002 +#define I2C_NAI 0x00000004 +#define I2C_DRMI 0x00000008 +#define I2C_DRSI 0x00000010 +#define I2C_ACTIVE 0x00000020 +#define I2C_SCL 0x00000040 +#define I2C_SDA 0x00000080 +#define I2C_RFF 0x00000100 +#define I2C_RFE 0x00000200 +#define I2C_TFF 0x00000400 +#define I2C_TFE 0x00000800 +#define I2C_TFFS 0x00001000 +#define I2C_TFES 0x00002000 +#define I2C_MAST 0x00004000 + +#define I2C_RESET 0x00000100 + +#define SEND_I2C_DEVICE_ADDRESS_START_STOP(addr) \ + writel(((0x80 + addr) << 1) + 0x200, I2C_TX_REG); +#define SEND_I2C_START_ADDRESS(addr) writel((0x80 + addr) << 1, I2C_TX_REG); +#define SEND_I2C_STOP_DATA(data) writel(0x200 + data, I2C_TX_REG); +#define SEND_I2C_READ_ADDRESS(addr) \ + writel(((0x80 + addr) << 1) + 1, I2C_TX_REG); +#define SOFT_I2C_RESET \ + writel(readl(I2C_CTL_REG) | I2C_RESET, I2C_CTL_REG); + +int eeprom_write_enable(unsigned dev_addr, int state) +{ + /* nothing to be done here */ + return 0; +} + +void i2c_init(int speed, int slaveaddr) +{ + unsigned long timeout; + + writel(readl(SCON_SYSMUX1_REG) & SCON_GPIOA27_MUX_FIELD & + SCON_GPIOA28_MUX_FIELD, SCON_SYSMUX1_REG); + writel(readl(SCON_SYSMUX1_REG) | SCON_GPIOA27_SCL | SCON_GPIOA28_SDA, + SCON_SYSMUX1_REG); + writel(readl(CGU_GATESC_REG) | CGU_I2CEN, CGU_GATESC_REG); + if (speed == 400000) { + /* + * here the registers are set in order to have a 400KHz clk + * for a pclk1 of 104Mhz + */ + writel(I2C_CLKDIV_FIELD | 84, I2C_CLKHI_REG); + writel(I2C_CLKDIV_FIELD | 168, I2C_CLKLO_REG); + writel(42, I2C_HOLDDAT_REG); + } else { + speed = 100000; + /* + * here the registers are set in order to have a 100KHz clk + * for a pclk1 of 104Mhz + */ + writel(I2C_CLKDIV_FIELD | 488, I2C_CLKHI_REG); + writel(I2C_CLKDIV_FIELD | 544, I2C_CLKLO_REG); + writel(68, I2C_HOLDDAT_REG); + } + writel(slaveaddr & ~I2C_SADDR_FIELD, I2C_ADR_REG); + SOFT_I2C_RESET; + timeout = 0; + while ((readl(I2C_STS_REG) & I2C_ACTIVE) == I2C_ACTIVE) { + if (timeout > I2C_TIMEOUT) + break; + timeout++; + udelay(I2C_DELAY); + } + debug("%s: speed: %d\n", __func__, speed); +} + + +int i2c_probe(uchar chip) +{ + unsigned long timeout; + + SEND_I2C_DEVICE_ADDRESS_START_STOP(chip); + timeout = 0; + while ((readl(I2C_STS_REG) & I2C_TDI) != I2C_TDI) { + if (timeout > I2C_TIMEOUT) + return -1; + timeout++; + udelay(I2C_DELAY); + } + writel(readl(I2C_STS_REG) | I2C_TDI, I2C_STS_REG); + if ((readl(I2C_STS_REG) & I2C_NAI) == I2C_NAI) + return -1; + return 0; +} + +static int i2c_read_byte(u8 chip, u16 addr, u8 *byte) +{ + unsigned long timeout; + + timeout = 0; + while ((readl(I2C_STS_REG) & I2C_ACTIVE) == I2C_ACTIVE) { + if (timeout > I2C_TIMEOUT) + return -1; + timeout++; + udelay(I2C_DELAY); + } + SEND_I2C_START_ADDRESS(chip); + /* loop if scl=1, active=0 or drmi=0 */ + timeout = 0; + while (((readl(I2C_STS_REG) & I2C_SCL) == I2C_SCL) || + ((readl(I2C_STS_REG) & I2C_ACTIVE) != I2C_ACTIVE) || + ((readl(I2C_STS_REG) & I2C_DRMI) != I2C_DRMI)) + if (timeout > I2C_TIMEOUT) { + return -1; + timeout++; + udelay(I2C_DELAY); + } + writel((addr & 0xFF00) >> 8, I2C_TX_REG); /* ADDRESS_MODE16 */ + writel((addr & 0x00FF) >> 0, I2C_TX_REG); + SEND_I2C_READ_ADDRESS(chip); /* Dev Sel to Read */ + SEND_I2C_STOP_DATA(0x00); /* dummy write */ + timeout = 0; + while (((readl(I2C_STS_REG) & I2C_NAI) == I2C_NAI) || + ((readl(I2C_STS_REG) & I2C_TDI) != I2C_TDI) || + ((readl(I2C_STS_REG) & I2C_SCL) != I2C_SCL) || + ((readl(I2C_STS_REG) & I2C_ACTIVE) == I2C_ACTIVE) || + ((readl(I2C_STS_REG) & I2C_DRMI) == I2C_DRMI)) + if (timeout > I2C_TIMEOUT) { + return -1; + timeout++; + udelay(I2C_DELAY); + } + writel(readl(I2C_STS_REG) | I2C_TDI, I2C_STS_REG); + timeout = 0; + while ((readl(I2C_STS_REG) & I2C_TDI) == I2C_TDI) { + if (timeout > I2C_TIMEOUT) + return -1; + timeout++; + udelay(I2C_DELAY); + } + *byte = readl(I2C_RX_REG) & 0xff; + return 0; +} + +static int i2c_write_byte(u8 chip, u16 addr, u8 *byte) +{ + u8 dummy; + unsigned long timeout; + + /* wait until data is written and eeprom back again */ + timeout = 0; + dummy = 1; + while ((timeout < I2C_TIMEOUT) && (dummy != 0)) { + dummy = -i2c_probe(chip); + timeout++; + udelay(I2C_DELAY); + } + timeout = 0; + while ((readl(I2C_STS_REG) & I2C_ACTIVE) == I2C_ACTIVE) { + if (timeout > I2C_TIMEOUT) + return -1; + timeout++; + udelay(I2C_DELAY); + } + SEND_I2C_START_ADDRESS(chip); + /* loop if scl=1, active=0 or drmi=0 */ + timeout = 0; + while (((readl(I2C_STS_REG) & I2C_SCL) == I2C_SCL) || + ((readl(I2C_STS_REG) & I2C_ACTIVE) != I2C_ACTIVE) || + ((readl(I2C_STS_REG) & I2C_DRMI) != I2C_DRMI)) { + if (timeout > I2C_TIMEOUT) + return -2; + timeout++; + udelay(I2C_DELAY); + } + writel((addr & 0xFF00) >> 8, I2C_TX_REG); /* ADDRESS_MODE16 */ + writel((addr & 0x00FF) >> 0, I2C_TX_REG); + SEND_I2C_STOP_DATA(*byte); + timeout = 0; + while (((readl(I2C_STS_REG) & I2C_NAI) == I2C_NAI) || + ((readl(I2C_STS_REG) & I2C_TDI) != I2C_TDI) || + ((readl(I2C_STS_REG) & I2C_SCL) != I2C_SCL) || + ((readl(I2C_STS_REG) & I2C_ACTIVE) == I2C_ACTIVE) || + ((readl(I2C_STS_REG) & I2C_DRMI) == I2C_DRMI)) { + if (timeout > I2C_TIMEOUT) + return -3; + timeout++; + udelay(I2C_DELAY); + } + writel(readl(I2C_STS_REG) | I2C_TDI, I2C_STS_REG); + timeout = 0; + while ((readl(I2C_STS_REG) & I2C_TDI) == I2C_TDI) { + if (timeout > I2C_TIMEOUT) + return -4; + timeout++; + udelay(I2C_DELAY); + } + dummy = readl(I2C_RX_REG) & 0xff; + return 0; +} + +int i2c_read(uchar chip, uint addr, int alen, uchar *buf, int len) +{ + int ret; + u8 byte; + + debug("%s chip: 0x%02x addr: 0x%04x alen: %d len: %d\n", + __func__, chip, addr, alen, len); + while (len--) { + ret = i2c_read_byte(chip, addr, &byte); + if (ret < 0) + return -1; + *buf++ = byte; + addr++; + } + return 0; +} + +int i2c_write(uchar chip, uint addr, int alen, uchar *buf, int len) +{ + int ret; + + debug("%s chip: 0x%02x addr: 0x%04x alen: %d len: %d\n", + __func__, chip, addr, alen, len); + while (len--) { + ret = i2c_write_byte(chip, addr++, buf++); + if (ret) { + printf("i2c_write failed chip: 0x%x addr: " + "0x%04x error %d\n", chip, addr, ret); + return -1; + } + } + return 0; +}

On 22:54 Sun 04 Jan , Jürgen Schöw wrote:
cpu/arm926ejs/pnx8181/Makefile | 45 +++ cpu/arm926ejs/pnx8181/timer.c | 141 ++++++++ drivers/i2c/Makefile | 1 + drivers/i2c/pnx8181_i2c.c | 304 +++++++++++++++++
diff --git a/cpu/arm926ejs/pnx8181/Makefile b/cpu/arm926ejs/pnx8181/Makefile new file mode 100644 index 0000000..b34d9e8 --- /dev/null +++ b/cpu/arm926ejs/pnx8181/Makefile @@ -0,0 +1,45 @@ +# +# (C) Copyright 2000-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# See file CREDITS for list of people who contributed to this +# project. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +#
+include $(TOPDIR)/config.mk
+LIB = $(obj)lib$(SOC).a
+COBJS = timer.o
+SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) +OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS))
+all: $(obj).depend $(LIB)
+$(LIB): $(OBJS)
- $(AR) $(ARFLAGS) $@ $(OBJS)
+#########################################################################
+# defines $(obj).depend target +include $(SRCTREE)/rules.mk
+sinclude $(obj).depend
+######################################################################### diff --git a/cpu/arm926ejs/pnx8181/timer.c b/cpu/arm926ejs/pnx8181/timer.c new file mode 100644 index 0000000..585aede --- /dev/null +++ b/cpu/arm926ejs/pnx8181/timer.c @@ -0,0 +1,141 @@ +/*
- pnx8181 SOC timer routines
- (C) Copyright 2007-2009, emlix GmbH, Germany
- Juergen Schoew js@emlix.com
- (C) Copyright 2008, DSPG Technologies GmbH, Germany
- (C) Copyright 2007, NXP Semiconductors Germany GmbH
- Matthias Wenzel, nxp@mazzoo.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 <common.h> +#include <asm/io.h>
+/*
- timer without interrupts
- */
+/* timer */ +#define PNX8181_SCTU1_BASE 0xC2102000 +#define PNX8181_SCTU2_BASE 0xC2103000
+#define PNX8181_SCTU_TIMxCR 0x00 +#define PNX8181_SCTU_TIMxRR 0x04 +#define PNX8181_SCTU_TIMxWR 0x08 +#define PNX8181_SCTU_TIMxC0 0x0c +#define PNX8181_SCTU_TIMxC1 0x10 +#define PNX8181_SCTU_TIMxC2 0x14 +#define PNX8181_SCTU_TIMxC3 0x18 +#define PNX8181_SCTU_TIMxSR 0x1c +#define PNX8181_SCTU_TIMxPR 0x20
please moce this to a header
+/*
- U-Boot expects a 32 bit timer, running at CONFIG_SYS_HZ
- Keep total timer count to avoid losing decrements < div_timer
- */
+/* U-Boot ticks since startup */ +static ulong timestamp; +static ulong last_timer_read;
+/*
- starts up a counter
- */
+void timer_init(void) +{
- /* set prescaler to have timer run at 64 kHz */
- writeb(0x00, (void *)(PNX8181_SCTU1_BASE + PNX8181_SCTU_TIMxPR));
- /* timer reload value = 0xffff - 13824, overflow @ 1kHz */
- writew(0xca00, (void *)(PNX8181_SCTU1_BASE + PNX8181_SCTU_TIMxRR));
- /* timer has no interrupt, run */
- writew(0x0001, (void *)(PNX8181_SCTU1_BASE + PNX8181_SCTU_TIMxCR));
- /* init the timestamp */
- reset_timer_masked();
+}
+ulong get_timer(ulong base_ticks) +{
- return get_timer_masked() - base_ticks;
+}
+/*
- converts the timer reading to U-Boot ticks
- the timestamp is the number of ticks since reset
- */
+ulong get_timer_masked(void) +{
- /* get current count */
- ulong now = readw((void *)(PNX8181_SCTU1_BASE + PNX8181_SCTU_TIMxWR));
- if (now < last_timer_read)
timestamp += 13824;
- last_timer_read = now;
- /*
* FIXME this value is empirical!
* for some reason the calculated values are way to fast
*/
- return (timestamp + now) / 64;
+}
+/*
- timer without interrupts
- */
+void reset_timer(void) +{
- reset_timer_masked();
+}
+/* busy-loop spin-delay */ +void sdelay(unsigned long usec) +{
- ulong i, tmp;
- tmp = 42;
- for (i = 0 ; i < usec*3 ; i++)
/* avoid compiler optimisation */
tmp = -tmp;
+}
+/* delay usec useconds */ +void udelay(unsigned long usec) +{
- ulong tmo, tmp;
- /* Convert to U-Boot ticks */
- tmo = usec / 1500;
- tmp = get_timer_masked(); /* get current timestamp */
- tmo += tmp; /* form target timestamp */
- /* loop till event */
- while (get_timer_masked() < tmo)
;
+}
+void reset_timer_masked(void) +{
- /* start "advancing" time stamp from 0 */
- timestamp = 0L;
+} diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile index 6079c05..ef457a5 100644 --- a/drivers/i2c/Makefile +++ b/drivers/i2c/Makefile @@ -31,6 +31,7 @@ COBJS-$(CONFIG_DRIVER_OMAP1510_I2C) += omap1510_i2c.o COBJS-$(CONFIG_DRIVER_OMAP24XX_I2C) += omap24xx_i2c.o COBJS-$(CONFIG_SOFT_I2C) += soft_i2c.o COBJS-$(CONFIG_TSI108_I2C) += tsi108_i2c.o +COBJS-$(CONFIG_PNX8181_I2C) += pnx8181_i2c.o
please keep list sorted
COBJS := $(COBJS-y) SRCS := $(COBJS:.o=.c) diff --git a/drivers/i2c/pnx8181_i2c.c b/drivers/i2c/pnx8181_i2c.c new file mode 100644 index 0000000..75a76a4 --- /dev/null +++ b/drivers/i2c/pnx8181_i2c.c @@ -0,0 +1,304 @@ +/*
- (C) Copyright 2008-2009, emlix GmbH, Germany
- Juergen Schoew js@emlix.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 <common.h> +#include <asm/io.h>
+#define I2C_TIMEOUT 10000 +#define I2C_DELAY 10
+#define ARM_VPB1_BASE_ADDR 0xC2000000 +#define ARM_VPB3_BASE_ADDR 0xC2200000 +#define ARM_VPB_SIZE_SHIFT 12
please move define to a header
+#define SCON_BASE_ADDR (ARM_VPB3_BASE_ADDR + (4<<ARM_VPB_SIZE_SHIFT)) +#define SCON_BASE SCON_BASE_ADDR +#define SCON_SYSMUX1_OFFSET (0x010) +#define SCON_SYSMUX1_REG (void *)(SCON_BASE + SCON_SYSMUX1_OFFSET) +#define SCON_GPIOA27_MUX_SHIFT 22 +#define SCON_GPIOA27_MUX_FIELD (0xFFFFFFFF-(3<<SCON_GPIOA27_MUX_SHIFT)) +#define SCON_GPIOA27_SCL (1<<SCON_GPIOA27_MUX_SHIFT) +#define SCON_GPIOA28_MUX_SHIFT 24 +#define SCON_GPIOA28_MUX_FIELD (0xFFFFFFFF-(3<<SCON_GPIOA28_MUX_SHIFT)) +#define SCON_GPIOA28_SDA (1<<SCON_GPIOA28_MUX_SHIFT)
+#define CGU_BASE_ADDR (ARM_VPB3_BASE_ADDR + (0<<ARM_VPB_SIZE_SHIFT)) +#define CGU_BASE (CGU_BASE_ADDR) +#define CGU_GATESC_OFFSET (0x008) +#define CGU_GATESC_REG (void *)(CGU_BASE + CGU_GATESC_OFFSET) +#define CGU_I2C1EN 0x00000020 +#define CGU_I2CEN CGU_I2C1EN
+#define I2C_BASE_ADDR (ARM_VPB1_BASE_ADDR + (1<<ARM_VPB_SIZE_SHIFT)) +#define I2C_BASE I2C_BASE_ADDR +#define I2C_CLKHI_OFFSET (0x00C) +#define I2C_CLKHI_REG (void *)(I2C_BASE + I2C_CLKHI_OFFSET) +#define I2C_CLKLO_OFFSET (0x010) +#define I2C_CLKLO_REG (void *)(I2C_BASE + I2C_CLKLO_OFFSET) +#define I2C_ADR_OFFSET (0x014) +#define I2C_ADR_REG (void *)(I2C_BASE + I2C_ADR_OFFSET)
^^^^^^^^^^^^^ whitespace please fix
+#define I2C_SADDR_FIELD 0xFFFFFF80
^^^^^^^^^ whitespace please fix and other in the code please fix
Best Regards, J.

On Fri, 6 Feb 2009 23:18:20 +0100 Jean-Christophe PLAGNIOL-VILLARD plagnioj@jcrosoft.com wrote:
On 22:54 Sun 04 Jan , Jürgen Schöw wrote:
cpu/arm926ejs/pnx8181/Makefile | 45 +++ cpu/arm926ejs/pnx8181/timer.c | 141 ++++++++ drivers/i2c/Makefile | 1 + drivers/i2c/pnx8181_i2c.c | 304 +++++++++++++++++
diff --git a/cpu/arm926ejs/pnx8181/timer.c b/cpu/arm926ejs/pnx8181/timer.c new file mode 100644 index 0000000..585aede --- /dev/null +++ b/cpu/arm926ejs/pnx8181/timer.c +#define PNX8181_SCTU_TIMxRR 0x04 +#define PNX8181_SCTU_TIMxWR 0x08 +#define PNX8181_SCTU_TIMxC0 0x0c +#define PNX8181_SCTU_TIMxC1 0x10 +#define PNX8181_SCTU_TIMxC2 0x14 +#define PNX8181_SCTU_TIMxC3 0x18 +#define PNX8181_SCTU_TIMxSR 0x1c +#define PNX8181_SCTU_TIMxPR 0x20
please moce this to a header
Yes, done.
diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile index 6079c05..ef457a5 100644 --- a/drivers/i2c/Makefile +++ b/drivers/i2c/Makefile @@ -31,6 +31,7 @@ COBJS-$(CONFIG_DRIVER_OMAP1510_I2C) += omap1510_i2c.o COBJS-$(CONFIG_DRIVER_OMAP24XX_I2C) += omap24xx_i2c.o COBJS-$(CONFIG_SOFT_I2C) += soft_i2c.o COBJS-$(CONFIG_TSI108_I2C) += tsi108_i2c.o +COBJS-$(CONFIG_PNX8181_I2C) += pnx8181_i2c.o
please keep list sorted
Yes, will change this.
diff --git a/drivers/i2c/pnx8181_i2c.c b/drivers/i2c/pnx8181_i2c.c new file mode 100644 index 0000000..75a76a4 --- /dev/null +++ b/drivers/i2c/pnx8181_i2c.c @@ -0,0 +1,304 @@ +#define ARM_VPB1_BASE_ADDR 0xC2000000 +#define ARM_VPB3_BASE_ADDR 0xC2200000 +#define ARM_VPB_SIZE_SHIFT 12
please move define to a header
OK, done.
+#define I2C_ADR_REG (void *)(I2C_BASE + I2C_ADR_OFFSET)
^^^^^^^^^^^^^
whitespace please fix
+#define I2C_SADDR_FIELD 0xFFFFFF80
^^^^^^^^^
whitespace please fix and other in the code please fix
Sorry, I searched for all whitespace errors, but it seemed I missed those. Thanks for mentioning.
Being on FOSDEM, I will try to send the next patchset as soon as possible. BTW: Thanks for reviewing!
Regards
Jürgen Schöw

drivers/net/Makefile | 1 + drivers/net/ip3912.c | 659 ++++++++++++++++++++++++++++++++++++ drivers/net/ip3912.h | 174 ++++++++++
diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 631336a..7c82880 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -69,6 +69,7 @@ COBJS-$(CONFIG_VSC7385_ENET) += vsc7385.o COBJS-$(CONFIG_XILINX_EMAC) += xilinx_emac.o COBJS-$(CONFIG_XILINX_EMACLITE) += xilinx_emaclite.o COBJS-$(CONFIG_SH_ETHER) += sh_eth.o +COBJS-$(CONFIG_IP3912_ETHER) += ip3912.o
COBJS := $(COBJS-y) SRCS := $(COBJS:.o=.c) diff --git a/drivers/net/ip3912.c b/drivers/net/ip3912.c new file mode 100644 index 0000000..399f0b7 --- /dev/null +++ b/drivers/net/ip3912.c @@ -0,0 +1,659 @@ +/* + * ip3912 ethernet driver (PNX8181 / firetux) + * + * (C) Copyright 2007-2009, emlix GmbH, Germany + * Juergen Schoew js@emlix.com + * + * (C) Copyright 2008, DSPG Technologies GmbH, Germany + * (C) Copyright 2007, NXP Semiconductors Germany GmbH + * Matthias Wenzel, nxp@mazzoo.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 <common.h> +#include <net.h> +#include <malloc.h> + +#include <asm/io.h> + +#include "ip3912.h" +#include <miiphy.h> + +#define ALIGN8 __attribute__ ((aligned(8))) +#define ALIGN4 __attribute__ ((aligned(4))) + +/* globals */ +/* ETN rx */ +ALIGN8 rx_descriptor_t etn_rxdescriptor[CONFIG_SYS_ETN_RX_DESCRIPTOR_NUMBER]; +ALIGN8 rx_status_t etn_rxstatus[CONFIG_SYS_ETN_RX_DESCRIPTOR_NUMBER]; + +/* ETN tx */ +ALIGN8 tx_descriptor_t etn_txdescriptor[CONFIG_SYS_ETN_TX_DESCRIPTOR_NUMBER]; +ALIGN4 tx_status_t etn_txstatus[CONFIG_SYS_ETN_TX_DESCRIPTOR_NUMBER]; + +struct ip3912_device { + unsigned int etn_base; + unsigned int phy_base; + unsigned char nr; + unsigned char phy_addr; + unsigned char autonegotiate; + unsigned char speed; + unsigned char duplex; + unsigned char rmii; + + const struct device *dev; + struct eth_device *netdev; +}; + +int ip3912_miiphy_write(char *devname, unsigned char addr, + unsigned char reg, unsigned short value) +{ + int status = 1; + int i = 0; + struct eth_device *netdev; + struct ip3912_device *ip3912; + + netdev = eth_get_dev(); + ip3912 = netdev->priv; + + reg &= 0x001f; /* 5 bit PHY register address */ + + writel(PHYADDR_TO_REG(addr) | reg, (void *)(ip3912->phy_base + + ETN_MADR)); + writel(value, (void *)(ip3912->phy_base + ETN_MWTD)); + + /* poll for done, max 100ms */ + while (status && i < 100000) { + status = readl((void *)(ip3912->phy_base + ETN_MIND)) & 0x7; + udelay(1); + i++; + } + + if (status) { + printf("ERROR: ip3912_miiphy_write(%d) = " + "0x%x [phy_addr=%x]\n", reg, status, addr); + return -1; + } else { + debug("### ip3912_miiphy_write(%2.d, 0x%4.4x) success after" + " %d cycles [phy_addr=%x]###\n", reg, value, i, addr); + } + + return 0; +} + +int ip3912_miiphy_read(char *devname, unsigned char addr, + unsigned char reg, unsigned short *value) +{ + int i = 0, status = 1; + struct eth_device *netdev; + struct ip3912_device *ip3912; + + netdev = eth_get_dev(); + ip3912 = netdev->priv; + + reg &= 0x001f; /* 5 bit PHY register address */ + writel(PHYADDR_TO_REG(addr) | reg, (void *)(ip3912->phy_base + + ETN_MADR)); + writel(0x00000001, (void *)(ip3912->phy_base + ETN_MCMD)); + + /* poll for done, max 100ms */ + while (status && i < 100000) { + status = readl((void *)(ip3912->phy_base + ETN_MIND)) & 0x7; + udelay(1); + i++; + } + + *value = (unsigned short)readl((void *)(ip3912->phy_base + ETN_MRDD)); + + writel(0, (void *)(ip3912->phy_base + ETN_MCMD)); /* stop MII */ + + if (status) { + printf("ERROR: ip3912_miiphy_read(%d) = 0x%x after %d cycles " + "[phy_addr=%x]\n", reg, *value, i, ip3912->phy_addr); + return -1; + } else { + debug("### ip3912_phy_read(%2.d)=0x%4.4x success after %d " + "cycles [phy_addr=%x]###\n", + reg, *value, i, ip3912->phy_addr); + } + + return 0; +} + +#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) +int ip3912_mii_negotiate_phy(void) +{ + char *mode; + int i; + unsigned short value; + struct eth_device *netdev; + struct ip3912_device *ip3912; + + netdev = eth_get_dev(); + ip3912 = netdev->priv; + + /* only set phy if exists */ + ip3912_miiphy_read(netdev->name, ip3912->phy_addr, + PHY_PHYIDR1, &value); + if (value == 0xffff) + return -1; + + /* get mode from environment */ + mode = getenv("phymode"); + if (mode != NULL) { + if (0 == strcmp(mode, "auto")) { + ip3912->autonegotiate = 1; + ip3912->speed = 100; + ip3912->duplex = 1; + } else { + if (0 == strcmp(mode, "100FD")) { + ip3912->speed = 100; + ip3912->duplex = 1; + } + if (0 == strcmp(mode, "100HD")) { + ip3912->speed = 100; + ip3912->duplex = 0; + } + if (0 == strcmp(mode, "10FD")) { + ip3912->speed = 10; + ip3912->duplex = 1; + } + if (0 == strcmp(mode, "10HD")) { + ip3912->speed = 10; + ip3912->duplex = 0; + } + ip3912->autonegotiate = 0; + } + } else { + /* we use 10Mbit FD as fallback */ + ip3912->autonegotiate = 0; + ip3912->speed = 10; + ip3912->duplex = 1; + } + + /* do autonegotiation */ + if (ip3912->autonegotiate) { + /* 10/100 and FD/HD mode supported, ieee802.3 */ + ip3912_miiphy_write(netdev->name, ip3912->phy_addr, + ETN_PHY_AUTONEG_ADV, ((0xf << 5) | 1)); + /* force autorenegotiation */ + ip3912_miiphy_write(netdev->name, ip3912->phy_addr, + ETN_PHY_BASIC_CONTROL, ((1 << 13) | (1 << 12) | + (1 << 9) | (1 << 8))); + } else { + /* only advertise the selected mode */ + i = 0x1e0; + if (ip3912->speed == 100) + i &= 0x180; + else + i &= 0x060; + if (ip3912->duplex) + i &= 0x140; + else + i &= 0x0a0; + /* set advertise mode */ + ip3912_miiphy_write(netdev->name, ip3912->phy_addr, + ETN_PHY_AUTONEG_ADV, (i|1)); + /* we set the phy parameter */ + ip3912_miiphy_write(netdev->name, ip3912->phy_addr, + ETN_PHY_BASIC_CONTROL, ((ip3912->duplex ? (1<<8) : 0) + | (1 << 9) | ((ip3912->speed == 100) ? (1 << 13) : 0))); + } + + /* wait for negotiation finished (max 3.5s) */ + i = 0; + ip3912_miiphy_read(netdev->name, ip3912->phy_addr, ETN_PHY_BASIC_STATUS, + &value); + while (((value & (1 << 5)) == 0) && (i < 350)) { + udelay(10000); + i++; + ip3912_miiphy_read(netdev->name, ip3912->phy_addr, + ETN_PHY_BASIC_STATUS, &value); + } + if (i == 350) + puts("link negotiation timed out\n"); + + + /* check for link */ + if (value & (1 << 2)) { + /* OK link present */ + ip3912_miiphy_read(netdev->name, ip3912->phy_addr, + ETN_PHY_SPECIAL_MODE_CONTROL_STATUS, &value); + ip3912->speed = (value & (1 << 2)) ? 10 : 100; + ip3912->duplex = (value & (1 << 4)) ? 1 : 0; + } + + /* program the mac */ + writel((readl((void *)(ip3912->etn_base + ETN_SUPP)) & 0x000018fb) | + ((ip3912->speed == 100) ? (1 << 8) : 0), + (void *)(ip3912->etn_base + ETN_SUPP)); + writel((readl((void *)(ip3912->etn_base + ETN_MAC2)) & 0x000073fe) | + ip3912->duplex, (void *)(ip3912->etn_base + ETN_MAC2)); + /* + * release rx-path, tx-path, host registers reset + * set Duplex, enable RMII, enable rx+tx + * no flow control, no frames<64b + */ + writel(0x00000283 | (ip3912->duplex ? (1 << 10) : 0), + (void *)(ip3912->etn_base + ETN_COMMAND)); + + udelay(100000); /* the mac still needs some time to settle 100ms */ + ip3912_miiphy_read(netdev->name, ip3912->phy_addr, + ETN_PHY_SPECIAL_MODE_CONTROL_STATUS, &value); + printf(" %s %s negotiation", netdev->name, + (value & (1 << 12)) ? "Auto" : "Manual"); + printf(" (10%s Mbit", (value & (1 << 3)) ? "0" : ""); + printf(" %sD", (value & (1 << 4)) ? "F" : "H"); + ip3912_miiphy_read(netdev->name, ip3912->phy_addr, ETN_PHY_BASIC_STATUS, + &value); + printf(" (%s)\n", (value & 1<<2) + ? "Link detected" : "No Link detected, trying anyway"); + + return 0; +} + +#if defined(CONFIG_DISCOVER_PHY) +int mii_discover_phy(void) +{ + unsigned short id1, id2; + int phytype, phyno; + struct eth_device *netdev; + struct ip3912_device *ip3912; + + netdev = eth_get_dev(); + ip3912 = netdev->priv; + + for (phyno = 0; phyno <= 31 ; ++phyno) { + ip3912_miiphy_read(netdev->name, phyno, PHY_PHYIDR1, &id1); + if (id1 != 0xffff) { + ip3912_miiphy_read(netdev->name, phyno, PHY_PHYIDR2, + &id2); + phytype = ((id1 << 16) | id2); + puts("Using Transceiver: "); + switch (phytype & 0xfffffff0) { + case PHY_ID_LXT970: + puts("LXT970"); + break; + case PHY_ID_LXT971: + puts("LXT971"); + break; + case PHY_ID_82555: + puts("82555"); + break; + case PHY_ID_QS6612: + puts("QS6612"); + break; + case PHY_ID_AMD79C784: + puts("AMD79C784"); + break; + case PHY_ID_LSI80225: + puts("LSI L80225"); + break; + case PHY_ID_LSI80225B: + puts("LSI L80225/B"); + break; + case PHY_ID_DM9161: + puts("Davicom DM9161"); + break; + case PHY_ID_KSM8995M: + puts("MICREL KS8995M"); + break; + case PHY_ID_SMSC8700: + puts("SMSC Lan 8700"); + break; + default: + printf("0x%08x", phytype); + break; + } + } + } + + return 0; +} +#endif /* CONFIG_DISCOVER_PHY */ + +#endif /* defined(CONFIG_MII) || defined(CONFIG_CMD_MII) */ + +int ip3912_miiphy_initialize(bd_t *bis) +{ +#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) + miiphy_register("ip3912", ip3912_miiphy_read, ip3912_miiphy_write); +#endif + return 0; +} + +static int ip3912_init_descriptors(struct eth_device *netdev) +{ + struct ip3912_device *ip3912; + static void *rxbuf; + int i; + + ip3912 = netdev->priv; + + /* fill in pointer in regs */ + writel((unsigned long)etn_rxdescriptor, (void *)(ip3912->etn_base + + ETN_RXDESCRIPTOR)); + writel((unsigned long)etn_rxstatus, (void *)(ip3912->etn_base + + ETN_RXSTATUS)); + writel(0x00000000, (void *)(ip3912->etn_base + ETN_RXCONSUMEINDEX)); + writel(CONFIG_SYS_ETN_RX_DESCRIPTOR_NUMBER - 1, + (void *)(ip3912->etn_base + + ETN_RXDESCRIPTORNUMBER)); + + writel((unsigned long)etn_txdescriptor, (void *)(ip3912->etn_base + + ETN_TXDESCRIPTOR)); + writel((unsigned long)etn_txstatus, (void *)(ip3912->etn_base + + ETN_TXSTATUS)); + writel(0x00000000, (void *)(ip3912->etn_base + ETN_TXPRODUCEINDEX)); + writel(CONFIG_SYS_ETN_TX_DESCRIPTOR_NUMBER - 1, + (void *)(ip3912->etn_base + ETN_TXDESCRIPTORNUMBER)); + + /* allocate rx-buffers, but only once, we're called multiple times! */ + if (!rxbuf) + rxbuf = malloc(MAX_ETH_FRAME_SIZE + * CONFIG_SYS_ETN_RX_DESCRIPTOR_NUMBER); + if (!rxbuf) { + puts("ERROR: couldn't allocate rx buffers!\n"); + return -1; + } + + for (i = 0; i < CONFIG_SYS_ETN_RX_DESCRIPTOR_NUMBER; i++) { + etn_rxdescriptor[i].packet = rxbuf + i * MAX_ETH_FRAME_SIZE; + etn_rxdescriptor[i].control = MAX_ETH_FRAME_SIZE + - sizeof(unsigned long); + etn_rxstatus[i].info = 0; + etn_rxstatus[i].hashCRC = 0; + } + + for (i = 0; i < CONFIG_SYS_ETN_TX_DESCRIPTOR_NUMBER; i++) { + etn_txdescriptor[i].packet = 0; + etn_txdescriptor[i].control = 0; + etn_txstatus[i].info = 0; + } + return 0; +} + +void ip3912_setmac(struct eth_device *netdev) +{ + struct ip3912_device *ip3912; + unsigned char i, use_etn1addr = 0; + char *mac_string, *pmac, *end; + char tmp[18]; + + ip3912 = netdev->priv; + + mac_string = getenv("ethaddr"); + + if (ip3912->nr) { + /* we use ETN2 */ + mac_string = getenv("eth1addr"); + if (!mac_string) { + mac_string = getenv("ethaddr"); + use_etn1addr = 1; + } + } + + pmac = mac_string; + for (i = 0; i < 6; i++) { + netdev->enetaddr[i] = pmac ? simple_strtoul(pmac, &end, 16) : 0; + if (pmac) + pmac = (*end) ? end + 1 : end; + } + + if (use_etn1addr) { + /* flip last bit of mac address */ + debug("ip3912_setmac %s flipping last bit\n", netdev->name); + if (netdev->enetaddr[5] & 1) + netdev->enetaddr[5] &= 0xfe; + else + netdev->enetaddr[5] |= 0x01; + sprintf(tmp, "%02X:%02X:%02X:%02X:%02X:%02X", + netdev->enetaddr[0], netdev->enetaddr[1], + netdev->enetaddr[2], netdev->enetaddr[3], + netdev->enetaddr[4], netdev->enetaddr[5]); + setenv("eth1addr", tmp); + mac_string = tmp; + } + + debug("ip3912_setmac set %s to address %s\n", netdev->name, mac_string); + + writel((netdev->enetaddr[5] << 8) | netdev->enetaddr[4], + (void *)(ip3912->etn_base + ETN_SA0)); + writel((netdev->enetaddr[3] << 8) | netdev->enetaddr[2], + (void *)(ip3912->etn_base + ETN_SA1)); + writel((netdev->enetaddr[1] << 8) | netdev->enetaddr[0], + (void *)(ip3912->etn_base + ETN_SA2)); +} + +int ip3912_macreset(void) +{ + struct eth_device *netdev; + struct ip3912_device *ip3912; + + netdev = eth_get_dev(); + ip3912 = netdev->priv; + + debug("ip3912_macreset resetting %s\n", netdev->name); + + /* reset MAC layer */ + writel(0x0000cf00, (void *)(ip3912->etn_base + ETN_MAC1)); + /* release MAC soft reset */ + writel(0x00000000, (void *)(ip3912->etn_base + ETN_MAC1)); + /* reset rx-path, tx-path, host registers */ + writel(0x00000038, (void *)(ip3912->etn_base + ETN_COMMAND)); + /* reset RMII, 100Mbps MAC, 10Mbps MAC */ + writel(0x1888, (void *)(ip3912->etn_base + ETN_SUPP)); + writel(0x1000, (void *)(ip3912->etn_base + ETN_SUPP)); + + return 0; +} + +static int ip3912_init(struct eth_device *netdev, bd_t *bd) +{ + unsigned char i; + struct ip3912_device *ip3912 = netdev->priv; + + /* update mac address in boardinfo */ + ip3912_setmac(netdev); + for (i = 0; i < 6 ; i++) + bd->bi_enetaddr[i] = netdev->enetaddr[i]; + + /* before enabling the rx-path we need to set up rx-descriptors */ + if (ip3912_init_descriptors(netdev)) + return -1; + + /* set max packet length to 1536 bytes */ + writel(MAX_ETH_FRAME_SIZE, (void *)(ip3912->etn_base + ETN_MAXF)); + /* full duplex */ + writel(0x00000023, (void *)(ip3912->etn_base + ETN_MAC2)); + /* inter packet gap register */ + writel(0x15, (void *)(ip3912->etn_base + ETN_IPGT)); + writel(0x12, (void *)(ip3912->etn_base + ETN_IPGR)); + /* enable rx, receive all frames */ + writel(0x00000003, (void *)(ip3912->etn_base + ETN_MAC1)); + /* accept all multicast, broadcast and station packets */ + writel(0x00000026, (void *)(ip3912->etn_base + ETN_RXFILTERCTRL)); + + /* reset MII mgmt, set MII clock */ + writel(0x0000801c, (void *)(ip3912->etn_base + ETN_MCFG)); + writel(0x0000001c, (void *)(ip3912->etn_base + ETN_MCFG)); + + /* release rx-path, tx-path, host registers reset + * set FullDuplex, enable RMMI, enable rx+tx + * no flow control, no frames<64b + */ + writel(0x00000683, (void *)(ip3912->etn_base + ETN_COMMAND)); + ip3912_init_descriptors(netdev); + +#ifdef CONFIG_DISCOVER_PHY + mii_discover_phy(); +#endif +#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) + /* check autonegotiation */ + ip3912_mii_negotiate_phy(); +#endif + return 0; +} + +/* Send a packet */ +static int ip3912_send(struct eth_device *netdev, volatile void *packet, + int length) +{ + struct ip3912_device *ip3912 = netdev->priv; + uint32_t next_packet; + uint32_t this_packet; + uint32_t last_packet; + + if ((length > MAX_ETH_FRAME_SIZE) || (length <= 0)) { + printf("ERROR: cannot transmit a %d bytes frame!\n", length); + return -1; + } + + this_packet = readl((void *)(ip3912->etn_base + ETN_TXPRODUCEINDEX)); + next_packet = (this_packet + 1) % CONFIG_SYS_ETN_TX_DESCRIPTOR_NUMBER; + last_packet = readl((void *)(ip3912->etn_base + ETN_TXCONSUMEINDEX)); + +#define ETN_TX_MAX_RETRY 1000000 + int i = 0; + /* wait until the FIFO is ready to accept a new packet */ + + while ((this_packet == ((last_packet + + CONFIG_SYS_ETN_TX_DESCRIPTOR_NUMBER - 1) + % CONFIG_SYS_ETN_TX_DESCRIPTOR_NUMBER)) + && (i < ETN_TX_MAX_RETRY)) { +#ifdef ET_DEBUG + /* debug print when FIFO full*/ + if ((i > 50000) && (!(i % 50000))) { + this_packet = + readl((void *)(ip3912->etn_base + + ETN_TXPRODUCEINDEX)); + last_packet = + readl((void *)(ip3912->etn_base + + ETN_TXCONSUMEINDEX)); + printf("this=%3.d, last=%3.d, i=%d\n", + this_packet, last_packet, i); + } +#endif + i++; + last_packet = readl((void *)(ip3912->etn_base + + ETN_TXCONSUMEINDEX)); + } + if (i == ETN_TX_MAX_RETRY) { + printf("tx FAILED after %d cycles\n", i); + return -1; + } + if (i) + printf("tx after %d cycles\n", i); + + etn_txdescriptor[this_packet].packet = packet; + etn_txdescriptor[this_packet].control = (length - 1) | + ETN_CONTROL_INTERRUPT | ETN_CONTROL_LAST; + + /* let the HW know a new packet is ready */ + writel(next_packet, (void *)(ip3912->etn_base + ETN_TXPRODUCEINDEX)); + + return 0; +} + +/* Check for received packets */ +static int ip3912_recv(struct eth_device *netdev) +{ + struct ip3912_device *ip3912 = netdev->priv; + + unsigned short rxconsume = (unsigned short) + (readl((void *)(ip3912->etn_base + ETN_RXCONSUMEINDEX))); + unsigned short rxproduce = (unsigned short) + (readl((void *)(ip3912->etn_base + ETN_RXPRODUCEINDEX))); + unsigned short psize = 0; + + debug("eth_rx: receive_rsv 0x%08x\n", + readl((void *)(ip3912->etn_base + ETN_RSV))); + debug("eth_rx: consume 0x%04x produce 0x%04x\n", + rxconsume, rxproduce); + while (rxconsume != rxproduce) { + rxproduce = (unsigned short)(readl((void *) + (ip3912->etn_base + ETN_RXPRODUCEINDEX))); + psize = (etn_rxstatus[rxconsume].info & 0x07ff) + 1; + if (psize > MAX_ETH_FRAME_SIZE) { + printf("dropping %d bytes frame (too large)!\n", + psize); + } else { + NetReceive(etn_rxdescriptor[rxconsume].packet, psize); + } + rxconsume = (rxconsume + 1) + % CONFIG_SYS_ETN_RX_DESCRIPTOR_NUMBER; + writel(rxconsume, + (void *)(ip3912->etn_base + ETN_RXCONSUMEINDEX)); + } + return psize; +} + +static void ip3912_halt(struct eth_device *netdev) +{ + struct ip3912_device *ip3912 = netdev->priv; + + /* disable rx-path, tx-path, host registers reset + * set FullDuplex, enable RMMI, disable rx+tx + * no flow control, no frames<64b + */ + writel(0x000006b8, (void *)(ip3912->etn_base + ETN_COMMAND)); +} + +int ip3912_eth_initialize(unsigned char nr, unsigned int etn_base, + unsigned int phy_base, unsigned char phy_addr, unsigned char rmii) +{ + struct ip3912_device *ip3912; + struct eth_device *netdev; + + netdev = malloc(sizeof(struct eth_device)); + ip3912 = malloc(sizeof(struct ip3912_device)); + if ((!ip3912) || (!netdev)) { + printf("Error: Failed to allocate memory for ETN%d\n", nr + 1); + return -1; + } + + memset(ip3912, 0, sizeof(struct ip3912_device)); + memset(netdev, 0, sizeof(struct eth_device)); + + ip3912->nr = nr; + ip3912->etn_base = etn_base; + ip3912->phy_base = phy_base; + ip3912->phy_addr = phy_addr; + ip3912->autonegotiate = 0; + ip3912->rmii = rmii; + ip3912->speed = 0; + ip3912->duplex = 0; + ip3912->netdev = netdev; + + sprintf(netdev->name, "ETN%d", nr + 1); + netdev->init = ip3912_init; + netdev->send = ip3912_send; + netdev->recv = ip3912_recv; + netdev->halt = ip3912_halt; + netdev->priv = (void *)ip3912; + + + eth_register(netdev); + ip3912_macreset(); + /* we have to set the mac address, because we have no SROM */ + ip3912_setmac(netdev); + + return 0; +} diff --git a/drivers/net/ip3912.h b/drivers/net/ip3912.h new file mode 100644 index 0000000..f6343a0 --- /dev/null +++ b/drivers/net/ip3912.h @@ -0,0 +1,174 @@ +/* + * ip3912 ethernet driver interface (PNX8181 / firetux) + * + * (C) Copyright 2007-2009, emlix GmbH, Germany + * Juergen Schoew js@emlix.com + * + * (C) Copyright 2008, DSPG Technologies GmbH, Germany + * (C) Copyright 2007, NXP Semiconductors Germany GmbH + * Matthias Wenzel, nxp@mazzoo.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 + */ + +/* exported ethernet functions */ +int mii_discover_phy(void); + +#define PHYADDR_TO_REG(x) (x << 8) + +/* data types */ + +/* rx */ +typedef struct{ + volatile void *packet; + volatile unsigned long control; +} rx_descriptor_t; + +typedef struct{ + volatile unsigned long info; /* RO */ + volatile unsigned long hashCRC; /* RO */ +} rx_status_t; + +/* tx */ +typedef struct{ + volatile void *packet; + volatile unsigned long control; +} tx_descriptor_t; + +typedef struct{ + volatile unsigned long info; /* RO */ +} tx_status_t; + +/* NXP's OUI registered @ IEEE */ +#define NXP_ETN_OUI 0x006037 + +/* ip3912 ETN registers */ +#define ETN1_BASE CONFIG_IP3912_ETN1_BASE +#define ETN2_BASE CONFIG_IP3912_ETN2_BASE + +/* offsets to base address */ +#define ETN_MAC1 0x0000 +#define ETN_MAC2 0x0004 +#define ETN_IPGT 0x0008 +#define ETN_IPGR 0x000c +#define ETN_CLRT 0x0010 +#define ETN_MAXF 0x0014 +#define ETN_SUPP 0x0018 +#define ETN_TEST 0x001c +#define ETN_MCFG 0x0020 +#define ETN_MCMD 0x0024 +#define ETN_MADR 0x0028 +#define ETN_MWTD 0x002c +#define ETN_MRDD 0x0030 +#define ETN_MIND 0x0034 +#define ETN_SA0 0x0040 +#define ETN_SA1 0x0044 +#define ETN_SA2 0x0048 +#define ETN_COMMAND 0x0100 +#define ETN_STATUS 0x0104 +#define ETN_RXDESCRIPTOR 0x0108 +#define ETN_RXSTATUS 0x010c +#define ETN_RXDESCRIPTORNUMBER 0x0110 +#define ETN_RXPRODUCEINDEX 0x0114 +#define ETN_RXCONSUMEINDEX 0x0118 +#define ETN_TXDESCRIPTOR 0x011c +#define ETN_TXSTATUS 0x0120 +#define ETN_TXDESCRIPTORNUMBER 0x0124 +#define ETN_TXPRODUCEINDEX 0x0128 +#define ETN_TXCONSUMEINDEX 0x012c +#define ETN_TXRTDESCRIPTOR 0x0130 +#define ETN_TXRTSTATUS 0x0134 +#define ETN_TXRTDESCRIPTORNUMBER 0x0138 +#define ETN_TXRTPRODUCEINDEX 0x013c +#define ETN_TXRTCONSUMEINDEX 0x0140 +#define ETN_QOSTIMEOUT 0x0148 +#define ETN_TSV0 0x0158 +#define ETN_TSV1 0x015c +#define ETN_RSV 0x0160 +#define ETN_FLOWCONTROLCOUNTER 0x0170 +#define ETN_FLOWCONTROLSTATUS 0x0174 +#define ETN_RXFILTERCTRL 0x0200 +#define ETN_RXFILTERWOLSTATUS 0x0204 +#define ETN_RXFILTERWOLCLEAR 0x0208 +#define ETN_HASHFILTERL 0x0210 +#define ETN_HASHFILTERH 0x0214 +#define ETN_INTSTATUS 0x0fe0 +#define ETN_INTENABLE 0x0fe4 +#define ETN_INTCLEAR 0x0fe8 +#define ETN_INTSET 0x0fec +#define ETN_POWERDOWN 0x0ff4 +#define ETN_MODULEID 0x0ffc + +/* values for control */ +#define ETN_CONTROL_INTERRUPT 0x80000000 +#define ETN_CONTROL_LAST 0x40000000 +#define ETN_CONTROL_CRC 0x20000000 +#define ETN_CONTROL_PAD 0x10000000 +#define ETN_CONTROL_HUGE 0x08000000 +#define ETN_CONTROL_OVERRIDE 0x04000000 + +/* registers in the SMSC LAN8700 PHY */ +/* +00 Basic Control Register Basic +01 Basic Status Register Basic +02 PHY Identifier 1 Extended +03 PHY Identifier 2 Extended +04 Auto-Negotiation Advertisement Register Extended +05 Auto-Negotiation Link Partner Ability Register Extended +06 Auto-Negotiation Expansion Register Extended +16 Silicon Revision Register Vendor-specific +17 Mode Control/Status Register Vendor-specific +18 Special Modes Vendor-specific +20 Reserved Vendor-specific +21 Reserved Vendor-specific +22 Reserved Vendor-specific +23 Reserved Vendor-specific +27 Control / Status Indication Register Vendor-specific +28 Special internal testability controls Vendor-specific +29 Interrupt Source Register Vendor-specific +30 Interrupt Mask Register Vendor-specific +31 PHY Special Control/Status Register Vendor-specific +*/ +#define ETN_PHY_BASIC_CONTROL 0x00 +#define ETN_PHY_BASIC_STATUS 0x01 +#define ETN_PHY_ID1 0x02 +#define ETN_PHY_ID2 0x03 +#define ETN_PHY_AUTONEG_ADV 0x04 +#define ETN_PHY_AUTONEG_LINK 0x05 +#define ETN_PHY_AUTONEG_EXP 0x06 +#define ETN_PHY_SILICON 0x10 +#define ETN_PHY_MODE_CONTROL_STATUS 0x11 +#define ETN_PHY_SPECIAL_MODES 0x12 +#define ETN_PHY_CONTROL_STATUS_INDICATION 0x1b +#define ETN_PHY_INTERNAL_TESTABILITY 0x1c +#define ETN_PHY_INTERRUPT_SOURCE 0x1d +#define ETN_PHY_INTERRUPT_MASK 0x1e +#define ETN_PHY_SPECIAL_MODE_CONTROL_STATUS 0x1f + +/* PHY identification */ +#define PHY_ID_LXT970 0x78100000 /* LXT970 */ +#define PHY_ID_LXT971 0x001378e0 /* LXT971 and 972 */ +#define PHY_ID_82555 0x02a80150 /* Intel 82555 */ +#define PHY_ID_QS6612 0x01814400 /* QS6612 */ +#define PHY_ID_AMD79C784 0x00225610 /* AMD 79C784 */ +#define PHY_ID_LSI80225 0x0016f870 /* LSI 80225 */ +#define PHY_ID_LSI80225B 0x0016f880 /* LSI 80225/B */ +#define PHY_ID_DM9161 0x0181B880 /* Davicom DM9161 */ +#define PHY_ID_KSM8995M 0x00221450 /* MICREL KS8995MA */ +#define PHY_ID_SMSC8700 0x0007C0C0 /* SMSC LAN 8700 */

On 22:56 Sun 04 Jan , Jürgen Schöw wrote:
drivers/net/Makefile | 1 + drivers/net/ip3912.c | 659 ++++++++++++++++++++++++++++++++++++ drivers/net/ip3912.h | 174 ++++++++++
diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 631336a..7c82880 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -69,6 +69,7 @@ COBJS-$(CONFIG_VSC7385_ENET) += vsc7385.o COBJS-$(CONFIG_XILINX_EMAC) += xilinx_emac.o COBJS-$(CONFIG_XILINX_EMACLITE) += xilinx_emaclite.o COBJS-$(CONFIG_SH_ETHER) += sh_eth.o +COBJS-$(CONFIG_IP3912_ETHER) += ip3912.o
please keep list sorted
Ben could you take a look please
Best Regards, J.

Jean-Christophe PLAGNIOL-VILLARD wrote:
On 22:56 Sun 04 Jan , Jürgen Schöw wrote:
drivers/net/Makefile | 1 + drivers/net/ip3912.c | 659 ++++++++++++++++++++++++++++++++++++ drivers/net/ip3912.h | 174 ++++++++++
diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 631336a..7c82880 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -69,6 +69,7 @@ COBJS-$(CONFIG_VSC7385_ENET) += vsc7385.o COBJS-$(CONFIG_XILINX_EMAC) += xilinx_emac.o COBJS-$(CONFIG_XILINX_EMACLITE) += xilinx_emaclite.o COBJS-$(CONFIG_SH_ETHER) += sh_eth.o +COBJS-$(CONFIG_IP3912_ETHER) += ip3912.o
please keep list sorted
Ben could you take a look please
Best Regards, J.
I started looking and got pulled into something else. Will provide feedback over the weekend.
regards, Ben

Am Fri, 6 Feb 2009 23:19:55 +0100 schrieb Jean-Christophe PLAGNIOL-VILLARD plagnioj@jcrosoft.com:
On 22:56 Sun 04 Jan , Jürgen Schöw wrote:
drivers/net/Makefile | 1 + drivers/net/ip3912.c | 659 ++++++++++++++++++++++++++++++++++++ drivers/net/ip3912.h | 174 ++++++++++
diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 631336a..7c82880 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -69,6 +69,7 @@ COBJS-$(CONFIG_VSC7385_ENET) += vsc7385.o COBJS-$(CONFIG_XILINX_EMAC) += xilinx_emac.o COBJS-$(CONFIG_XILINX_EMACLITE) += xilinx_emaclite.o COBJS-$(CONFIG_SH_ETHER) += sh_eth.o +COBJS-$(CONFIG_IP3912_ETHER) += ip3912.o
please keep list sorted
OK, sorting is important, I missed it, sorry.
Ben could you take a look please
I will wait, for Bens comment, before I will send the next patchset. BTW: I detected that there is sometimes a problem with initialisation of the chip. Therefore I will have to find to bug and correct. So testing will go on on Monday night. :-)
Regards
Jürgen Schöw

Hi Jurgen,
Sorry for taking so long to review :(
Jürgen Schöw wrote:
drivers/net/Makefile | 1 + drivers/net/ip3912.c | 659 ++++++++++++++++++++++++++++++++++++ drivers/net/ip3912.h | 174 ++++++++++
diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 631336a..7c82880 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -69,6 +69,7 @@ COBJS-$(CONFIG_VSC7385_ENET) += vsc7385.o COBJS-$(CONFIG_XILINX_EMAC) += xilinx_emac.o COBJS-$(CONFIG_XILINX_EMACLITE) += xilinx_emaclite.o COBJS-$(CONFIG_SH_ETHER) += sh_eth.o +COBJS-$(CONFIG_IP3912_ETHER) += ip3912.o
Please use alphabetical order. Would you mind putting the SH one in its proper place while there?
COBJS := $(COBJS-y) SRCS := $(COBJS:.o=.c) diff --git a/drivers/net/ip3912.c b/drivers/net/ip3912.c new file mode 100644 index 0000000..399f0b7 --- /dev/null +++ b/drivers/net/ip3912.c @@ -0,0 +1,659 @@ +/*
- ip3912 ethernet driver (PNX8181 / firetux)
- (C) Copyright 2007-2009, emlix GmbH, Germany
- Juergen Schoew js@emlix.com
- (C) Copyright 2008, DSPG Technologies GmbH, Germany
- (C) Copyright 2007, NXP Semiconductors Germany GmbH
- Matthias Wenzel, nxp@mazzoo.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 <common.h> +#include <net.h> +#include <malloc.h>
+#include <asm/io.h>
+#include "ip3912.h" +#include <miiphy.h>
+#define ALIGN8 __attribute__ ((aligned(8))) +#define ALIGN4 __attribute__ ((aligned(4)))
+/* globals */ +/* ETN rx */ +ALIGN8 rx_descriptor_t etn_rxdescriptor[CONFIG_SYS_ETN_RX_DESCRIPTOR_NUMBER]; +ALIGN8 rx_status_t etn_rxstatus[CONFIG_SYS_ETN_RX_DESCRIPTOR_NUMBER];
+/* ETN tx */ +ALIGN8 tx_descriptor_t etn_txdescriptor[CONFIG_SYS_ETN_TX_DESCRIPTOR_NUMBER]; +ALIGN4 tx_status_t etn_txstatus[CONFIG_SYS_ETN_TX_DESCRIPTOR_NUMBER];
+struct ip3912_device {
- unsigned int etn_base;
- unsigned int phy_base;
- unsigned char nr;
What is this 'nr' field? I gather that it's some kind of overall ethernet device index?
- unsigned char phy_addr;
- unsigned char autonegotiate;
- unsigned char speed;
- unsigned char duplex;
- unsigned char rmii;
- const struct device *dev;
- struct eth_device *netdev;
+};
+int ip3912_miiphy_write(char *devname, unsigned char addr,
unsigned char reg, unsigned short value)
+{
- int status = 1;
- int i = 0;
- struct eth_device *netdev;
- struct ip3912_device *ip3912;
- netdev = eth_get_dev();
- ip3912 = netdev->priv;
- reg &= 0x001f; /* 5 bit PHY register address */
- writel(PHYADDR_TO_REG(addr) | reg, (void *)(ip3912->phy_base
+ ETN_MADR));
- writel(value, (void *)(ip3912->phy_base + ETN_MWTD));
I find your format of writel(val, addr) to be counter-intuitive. These functions usually are like: writel(addr, val)
- /* poll for done, max 100ms */
- while (status && i < 100000) {
status = readl((void *)(ip3912->phy_base + ETN_MIND)) & 0x7;
udelay(1);
i++;
- }
- if (status) {
printf("ERROR: ip3912_miiphy_write(%d) = "
"0x%x [phy_addr=%x]\n", reg, status, addr);
Some print formatting trivia: What does "%#04x" do? Try it - I've been programming C for a long time and just found out about this one.
return -1;
- } else {
debug("### ip3912_miiphy_write(%2.d, 0x%4.4x) success after"
" %d cycles [phy_addr=%x]###\n", reg, value, i, addr);
- }
- return 0;
+}
+int ip3912_miiphy_read(char *devname, unsigned char addr,
unsigned char reg, unsigned short *value)
+{
- int i = 0, status = 1;
- struct eth_device *netdev;
- struct ip3912_device *ip3912;
- netdev = eth_get_dev();
- ip3912 = netdev->priv;
- reg &= 0x001f; /* 5 bit PHY register address */
- writel(PHYADDR_TO_REG(addr) | reg, (void *)(ip3912->phy_base
+ ETN_MADR));
- writel(0x00000001, (void *)(ip3912->phy_base + ETN_MCMD));
- /* poll for done, max 100ms */
- while (status && i < 100000) {
status = readl((void *)(ip3912->phy_base + ETN_MIND)) & 0x7;
udelay(1);
i++;
- }
- *value = (unsigned short)readl((void *)(ip3912->phy_base + ETN_MRDD));
- writel(0, (void *)(ip3912->phy_base + ETN_MCMD)); /* stop MII */
- if (status) {
printf("ERROR: ip3912_miiphy_read(%d) = 0x%x after %d cycles "
"[phy_addr=%x]\n", reg, *value, i, ip3912->phy_addr);
return -1;
- } else {
debug("### ip3912_phy_read(%2.d)=0x%4.4x success after %d "
"cycles [phy_addr=%x]###\n",
reg, *value, i, ip3912->phy_addr);
- }
- return 0;
+}
+#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) +int ip3912_mii_negotiate_phy(void) +{
- char *mode;
- int i;
- unsigned short value;
- struct eth_device *netdev;
- struct ip3912_device *ip3912;
- netdev = eth_get_dev();
- ip3912 = netdev->priv;
- /* only set phy if exists */
- ip3912_miiphy_read(netdev->name, ip3912->phy_addr,
PHY_PHYIDR1, &value);
- if (value == 0xffff)
return -1;
- /* get mode from environment */
- mode = getenv("phymode");
You use the environment for storing a forced PHY mode? Other parts of this driver indicate that there can either be more than one or that it can exist with other controllers. In that case, "phymode" isn't a very good name.
- if (mode != NULL) {
if (0 == strcmp(mode, "auto")) {
ip3912->autonegotiate = 1;
ip3912->speed = 100;
ip3912->duplex = 1;
} else {
if (0 == strcmp(mode, "100FD")) {
ip3912->speed = 100;
ip3912->duplex = 1;
}
if (0 == strcmp(mode, "100HD")) {
ip3912->speed = 100;
ip3912->duplex = 0;
}
if (0 == strcmp(mode, "10FD")) {
ip3912->speed = 10;
ip3912->duplex = 1;
}
if (0 == strcmp(mode, "10HD")) {
ip3912->speed = 10;
ip3912->duplex = 0;
}
ip3912->autonegotiate = 0;
}
- } else {
/* we use 10Mbit FD as fallback */
ip3912->autonegotiate = 0;
ip3912->speed = 10;
ip3912->duplex = 1;
- }
Wouldn't autonegotiation be the default?
- /* do autonegotiation */
- if (ip3912->autonegotiate) {
/* 10/100 and FD/HD mode supported, ieee802.3 */
ip3912_miiphy_write(netdev->name, ip3912->phy_addr,
ETN_PHY_AUTONEG_ADV, ((0xf << 5) | 1));
/* force autorenegotiation */
ip3912_miiphy_write(netdev->name, ip3912->phy_addr,
ETN_PHY_BASIC_CONTROL, ((1 << 13) | (1 << 12) |
(1 << 9) | (1 << 8)));
- } else {
/* only advertise the selected mode */
i = 0x1e0;
if (ip3912->speed == 100)
i &= 0x180;
else
i &= 0x060;
if (ip3912->duplex)
i &= 0x140;
else
i &= 0x0a0;
What are all these magic numbers?
/* set advertise mode */
ip3912_miiphy_write(netdev->name, ip3912->phy_addr,
ETN_PHY_AUTONEG_ADV, (i|1));
/* we set the phy parameter */
ip3912_miiphy_write(netdev->name, ip3912->phy_addr,
ETN_PHY_BASIC_CONTROL, ((ip3912->duplex ? (1<<8) : 0)
| (1 << 9) | ((ip3912->speed == 100) ? (1 << 13) : 0)));
- }
- /* wait for negotiation finished (max 3.5s) */
- i = 0;
- ip3912_miiphy_read(netdev->name, ip3912->phy_addr, ETN_PHY_BASIC_STATUS,
&value);
- while (((value & (1 << 5)) == 0) && (i < 350)) {
udelay(10000);
i++;
ip3912_miiphy_read(netdev->name, ip3912->phy_addr,
ETN_PHY_BASIC_STATUS, &value);
- }
- if (i == 350)
puts("link negotiation timed out\n");
- /* check for link */
- if (value & (1 << 2)) {
/* OK link present */
ip3912_miiphy_read(netdev->name, ip3912->phy_addr,
ETN_PHY_SPECIAL_MODE_CONTROL_STATUS, &value);
ip3912->speed = (value & (1 << 2)) ? 10 : 100;
ip3912->duplex = (value & (1 << 4)) ? 1 : 0;
- }
- /* program the mac */
- writel((readl((void *)(ip3912->etn_base + ETN_SUPP)) & 0x000018fb) |
((ip3912->speed == 100) ? (1 << 8) : 0),
(void *)(ip3912->etn_base + ETN_SUPP));
- writel((readl((void *)(ip3912->etn_base + ETN_MAC2)) & 0x000073fe) |
ip3912->duplex, (void *)(ip3912->etn_base + ETN_MAC2))
Lots more magic numbers. Please define in your header.
;
- /*
* release rx-path, tx-path, host registers reset
* set Duplex, enable RMII, enable rx+tx
* no flow control, no frames<64b
*/
- writel(0x00000283 | (ip3912->duplex ? (1 << 10) : 0),
(void *)(ip3912->etn_base + ETN_COMMAND));
- udelay(100000); /* the mac still needs some time to settle 100ms */
- ip3912_miiphy_read(netdev->name, ip3912->phy_addr,
ETN_PHY_SPECIAL_MODE_CONTROL_STATUS, &value);
- printf(" %s %s negotiation", netdev->name,
(value & (1 << 12)) ? "Auto" : "Manual");
- printf(" (10%s Mbit", (value & (1 << 3)) ? "0" : "");
- printf(" %sD", (value & (1 << 4)) ? "F" : "H");
- ip3912_miiphy_read(netdev->name, ip3912->phy_addr, ETN_PHY_BASIC_STATUS,
&value);
- printf(" (%s)\n", (value & 1<<2)
? "Link detected" : "No Link detected, trying anyway");
- return 0;
+}
+#if defined(CONFIG_DISCOVER_PHY) +int mii_discover_phy(void) +{
- unsigned short id1, id2;
- int phytype, phyno;
- struct eth_device *netdev;
- struct ip3912_device *ip3912;
- netdev = eth_get_dev();
- ip3912 = netdev->priv;
- for (phyno = 0; phyno <= 31 ; ++phyno) {
ip3912_miiphy_read(netdev->name, phyno, PHY_PHYIDR1, &id1);
if (id1 != 0xffff) {
ip3912_miiphy_read(netdev->name, phyno, PHY_PHYIDR2,
&id2);
phytype = ((id1 << 16) | id2);
puts("Using Transceiver: ");
switch (phytype & 0xfffffff0) {
case PHY_ID_LXT970:
puts("LXT970");
break;
case PHY_ID_LXT971:
puts("LXT971");
break;
case PHY_ID_82555:
puts("82555");
break;
case PHY_ID_QS6612:
puts("QS6612");
break;
case PHY_ID_AMD79C784:
puts("AMD79C784");
break;
case PHY_ID_LSI80225:
puts("LSI L80225");
break;
case PHY_ID_LSI80225B:
puts("LSI L80225/B");
break;
case PHY_ID_DM9161:
puts("Davicom DM9161");
break;
case PHY_ID_KSM8995M:
puts("MICREL KS8995M");
break;
case PHY_ID_SMSC8700:
puts("SMSC Lan 8700");
break;
default:
printf("0x%08x", phytype);
break;
}
}
- }
- return 0;
+} +#endif /* CONFIG_DISCOVER_PHY */
+#endif /* defined(CONFIG_MII) || defined(CONFIG_CMD_MII) */
+int ip3912_miiphy_initialize(bd_t *bis) +{ +#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
- miiphy_register("ip3912", ip3912_miiphy_read, ip3912_miiphy_write);
+#endif
- return 0;
+}
+static int ip3912_init_descriptors(struct eth_device *netdev) +{
- struct ip3912_device *ip3912;
- static void *rxbuf;
- int i;
- ip3912 = netdev->priv;
- /* fill in pointer in regs */
- writel((unsigned long)etn_rxdescriptor, (void *)(ip3912->etn_base
+ ETN_RXDESCRIPTOR));
- writel((unsigned long)etn_rxstatus, (void *)(ip3912->etn_base
+ ETN_RXSTATUS));
- writel(0x00000000, (void *)(ip3912->etn_base + ETN_RXCONSUMEINDEX));
- writel(CONFIG_SYS_ETN_RX_DESCRIPTOR_NUMBER - 1,
(void *)(ip3912->etn_base
+ ETN_RXDESCRIPTORNUMBER));
- writel((unsigned long)etn_txdescriptor, (void *)(ip3912->etn_base
+ ETN_TXDESCRIPTOR));
- writel((unsigned long)etn_txstatus, (void *)(ip3912->etn_base
+ ETN_TXSTATUS));
- writel(0x00000000, (void *)(ip3912->etn_base + ETN_TXPRODUCEINDEX));
- writel(CONFIG_SYS_ETN_TX_DESCRIPTOR_NUMBER - 1,
(void *)(ip3912->etn_base + ETN_TXDESCRIPTORNUMBER));
- /* allocate rx-buffers, but only once, we're called multiple times! */
- if (!rxbuf)
rxbuf = malloc(MAX_ETH_FRAME_SIZE
* CONFIG_SYS_ETN_RX_DESCRIPTOR_NUMBER);
- if (!rxbuf) {
puts("ERROR: couldn't allocate rx buffers!\n");
return -1;
- }
- for (i = 0; i < CONFIG_SYS_ETN_RX_DESCRIPTOR_NUMBER; i++) {
etn_rxdescriptor[i].packet = rxbuf + i * MAX_ETH_FRAME_SIZE;
etn_rxdescriptor[i].control = MAX_ETH_FRAME_SIZE
- sizeof(unsigned long);
etn_rxstatus[i].info = 0;
etn_rxstatus[i].hashCRC = 0;
- }
- for (i = 0; i < CONFIG_SYS_ETN_TX_DESCRIPTOR_NUMBER; i++) {
etn_txdescriptor[i].packet = 0;
etn_txdescriptor[i].control = 0;
etn_txstatus[i].info = 0;
- }
- return 0;
+}
+void ip3912_setmac(struct eth_device *netdev) +{
struct ip3912_device *ip3912;
unsigned char i, use_etn1addr = 0;
char *mac_string, *pmac, *end;
char tmp[18];
ip3912 = netdev->priv;
mac_string = getenv("ethaddr");
if (ip3912->nr) {
/* we use ETN2 */
mac_string = getenv("eth1addr");
if (!mac_string) {
mac_string = getenv("ethaddr");
Why would you allow this?
use_etn1addr = 1;
}
- }
- pmac = mac_string;
- for (i = 0; i < 6; i++) {
netdev->enetaddr[i] = pmac ? simple_strtoul(pmac, &end, 16) : 0;
if (pmac)
pmac = (*end) ? end + 1 : end;
- }
- if (use_etn1addr) {
/* flip last bit of mac address */
debug("ip3912_setmac %s flipping last bit\n", netdev->name);
if (netdev->enetaddr[5] & 1)
netdev->enetaddr[5] &= 0xfe;
else
netdev->enetaddr[5] |= 0x01;
What's this all about? Please add comments to explain why you're flipping this bit.
sprintf(tmp, "%02X:%02X:%02X:%02X:%02X:%02X",
netdev->enetaddr[0], netdev->enetaddr[1],
netdev->enetaddr[2], netdev->enetaddr[3],
netdev->enetaddr[4], netdev->enetaddr[5]);
setenv("eth1addr", tmp);
mac_string = tmp;
- }
- debug("ip3912_setmac set %s to address %s\n", netdev->name, mac_string);
- writel((netdev->enetaddr[5] << 8) | netdev->enetaddr[4],
(void *)(ip3912->etn_base + ETN_SA0));
- writel((netdev->enetaddr[3] << 8) | netdev->enetaddr[2],
(void *)(ip3912->etn_base + ETN_SA1));
- writel((netdev->enetaddr[1] << 8) | netdev->enetaddr[0],
(void *)(ip3912->etn_base + ETN_SA2));
+}
+int ip3912_macreset(void) +{
- struct eth_device *netdev;
- struct ip3912_device *ip3912;
- netdev = eth_get_dev();
- ip3912 = netdev->priv;
- debug("ip3912_macreset resetting %s\n", netdev->name);
- /* reset MAC layer */
- writel(0x0000cf00, (void *)(ip3912->etn_base + ETN_MAC1));
- /* release MAC soft reset */
- writel(0x00000000, (void *)(ip3912->etn_base + ETN_MAC1));
- /* reset rx-path, tx-path, host registers */
- writel(0x00000038, (void *)(ip3912->etn_base + ETN_COMMAND));
- /* reset RMII, 100Mbps MAC, 10Mbps MAC */
- writel(0x1888, (void *)(ip3912->etn_base + ETN_SUPP));
- writel(0x1000, (void *)(ip3912->etn_base + ETN_SUPP));
- return 0;
+}
+static int ip3912_init(struct eth_device *netdev, bd_t *bd) +{
- unsigned char i;
- struct ip3912_device *ip3912 = netdev->priv;
- /* update mac address in boardinfo */
- ip3912_setmac(netdev);
- for (i = 0; i < 6 ; i++)
bd->bi_enetaddr[i] = netdev->enetaddr[i];
- /* before enabling the rx-path we need to set up rx-descriptors */
- if (ip3912_init_descriptors(netdev))
return -1;
- /* set max packet length to 1536 bytes */
- writel(MAX_ETH_FRAME_SIZE, (void *)(ip3912->etn_base + ETN_MAXF));
- /* full duplex */
- writel(0x00000023, (void *)(ip3912->etn_base + ETN_MAC2));
- /* inter packet gap register */
- writel(0x15, (void *)(ip3912->etn_base + ETN_IPGT));
- writel(0x12, (void *)(ip3912->etn_base + ETN_IPGR));
- /* enable rx, receive all frames */
- writel(0x00000003, (void *)(ip3912->etn_base + ETN_MAC1));
- /* accept all multicast, broadcast and station packets */
- writel(0x00000026, (void *)(ip3912->etn_base + ETN_RXFILTERCTRL));
- /* reset MII mgmt, set MII clock */
- writel(0x0000801c, (void *)(ip3912->etn_base + ETN_MCFG));
- writel(0x0000001c, (void *)(ip3912->etn_base + ETN_MCFG));
- /* release rx-path, tx-path, host registers reset
* set FullDuplex, enable RMMI, enable rx+tx
* no flow control, no frames<64b
*/
- writel(0x00000683, (void *)(ip3912->etn_base + ETN_COMMAND));
- ip3912_init_descriptors(netdev);
+#ifdef CONFIG_DISCOVER_PHY
- mii_discover_phy();
+#endif +#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
- /* check autonegotiation */
- ip3912_mii_negotiate_phy();
+#endif
- return 0;
+}
+/* Send a packet */ +static int ip3912_send(struct eth_device *netdev, volatile void *packet,
int length)
+{
- struct ip3912_device *ip3912 = netdev->priv;
- uint32_t next_packet;
- uint32_t this_packet;
- uint32_t last_packet;
- if ((length > MAX_ETH_FRAME_SIZE) || (length <= 0)) {
printf("ERROR: cannot transmit a %d bytes frame!\n", length);
return -1;
- }
- this_packet = readl((void *)(ip3912->etn_base + ETN_TXPRODUCEINDEX));
- next_packet = (this_packet + 1) % CONFIG_SYS_ETN_TX_DESCRIPTOR_NUMBER;
- last_packet = readl((void *)(ip3912->etn_base + ETN_TXCONSUMEINDEX));
+#define ETN_TX_MAX_RETRY 1000000
- int i = 0;
- /* wait until the FIFO is ready to accept a new packet */
- while ((this_packet == ((last_packet +
CONFIG_SYS_ETN_TX_DESCRIPTOR_NUMBER - 1)
% CONFIG_SYS_ETN_TX_DESCRIPTOR_NUMBER))
&& (i < ETN_TX_MAX_RETRY)) {
+#ifdef ET_DEBUG
/* debug print when FIFO full*/
if ((i > 50000) && (!(i % 50000))) {
this_packet =
readl((void *)(ip3912->etn_base
+ ETN_TXPRODUCEINDEX));
last_packet =
readl((void *)(ip3912->etn_base
+ ETN_TXCONSUMEINDEX));
printf("this=%3.d, last=%3.d, i=%d\n",
this_packet, last_packet, i);
}
+#endif
i++;
last_packet = readl((void *)(ip3912->etn_base
+ ETN_TXCONSUMEINDEX));
- }
- if (i == ETN_TX_MAX_RETRY) {
printf("tx FAILED after %d cycles\n", i);
return -1;
- }
- if (i)
printf("tx after %d cycles\n", i);
- etn_txdescriptor[this_packet].packet = packet;
- etn_txdescriptor[this_packet].control = (length - 1) |
ETN_CONTROL_INTERRUPT | ETN_CONTROL_LAST;
- /* let the HW know a new packet is ready */
- writel(next_packet, (void *)(ip3912->etn_base + ETN_TXPRODUCEINDEX));
- return 0;
+}
+/* Check for received packets */ +static int ip3912_recv(struct eth_device *netdev) +{
- struct ip3912_device *ip3912 = netdev->priv;
- unsigned short rxconsume = (unsigned short)
(readl((void *)(ip3912->etn_base + ETN_RXCONSUMEINDEX)));
- unsigned short rxproduce = (unsigned short)
(readl((void *)(ip3912->etn_base + ETN_RXPRODUCEINDEX)));
- unsigned short psize = 0;
- debug("eth_rx: receive_rsv 0x%08x\n",
readl((void *)(ip3912->etn_base + ETN_RSV)));
- debug("eth_rx: consume 0x%04x produce 0x%04x\n",
rxconsume, rxproduce);
- while (rxconsume != rxproduce) {
rxproduce = (unsigned short)(readl((void *)
(ip3912->etn_base + ETN_RXPRODUCEINDEX)));
psize = (etn_rxstatus[rxconsume].info & 0x07ff) + 1;
if (psize > MAX_ETH_FRAME_SIZE) {
printf("dropping %d bytes frame (too large)!\n",
psize);
} else {
NetReceive(etn_rxdescriptor[rxconsume].packet, psize);
}
rxconsume = (rxconsume + 1)
% CONFIG_SYS_ETN_RX_DESCRIPTOR_NUMBER;
writel(rxconsume,
(void *)(ip3912->etn_base + ETN_RXCONSUMEINDEX));
- }
- return psize;
+}
+static void ip3912_halt(struct eth_device *netdev) +{
- struct ip3912_device *ip3912 = netdev->priv;
- /* disable rx-path, tx-path, host registers reset
* set FullDuplex, enable RMMI, disable rx+tx
* no flow control, no frames<64b
*/
- writel(0x000006b8, (void *)(ip3912->etn_base + ETN_COMMAND));
I know you comment it, but OR-ing bitfields is much easier to read than magic numbers
+}
+int ip3912_eth_initialize(unsigned char nr, unsigned int etn_base,
- unsigned int phy_base, unsigned char phy_addr, unsigned char rmii)
+{
- struct ip3912_device *ip3912;
- struct eth_device *netdev;
- netdev = malloc(sizeof(struct eth_device));
- ip3912 = malloc(sizeof(struct ip3912_device));
- if ((!ip3912) || (!netdev)) {
printf("Error: Failed to allocate memory for ETN%d\n", nr + 1);
return -1;
- }
- memset(ip3912, 0, sizeof(struct ip3912_device));
- memset(netdev, 0, sizeof(struct eth_device));
- ip3912->nr = nr;
- ip3912->etn_base = etn_base;
- ip3912->phy_base = phy_base;
- ip3912->phy_addr = phy_addr;
- ip3912->autonegotiate = 0;
- ip3912->rmii = rmii;
- ip3912->speed = 0;
- ip3912->duplex = 0;
- ip3912->netdev = netdev;
- sprintf(netdev->name, "ETN%d", nr + 1);
- netdev->init = ip3912_init;
- netdev->send = ip3912_send;
- netdev->recv = ip3912_recv;
- netdev->halt = ip3912_halt;
- netdev->priv = (void *)ip3912;
- eth_register(netdev);
- ip3912_macreset();
- /* we have to set the mac address, because we have no SROM */
- ip3912_setmac(netdev);
- return 0;
+} diff --git a/drivers/net/ip3912.h b/drivers/net/ip3912.h new file mode 100644 index 0000000..f6343a0 --- /dev/null +++ b/drivers/net/ip3912.h @@ -0,0 +1,174 @@ +/*
- ip3912 ethernet driver interface (PNX8181 / firetux)
- (C) Copyright 2007-2009, emlix GmbH, Germany
- Juergen Schoew js@emlix.com
- (C) Copyright 2008, DSPG Technologies GmbH, Germany
- (C) Copyright 2007, NXP Semiconductors Germany GmbH
- Matthias Wenzel, nxp@mazzoo.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
- */
+/* exported ethernet functions */ +int mii_discover_phy(void);
+#define PHYADDR_TO_REG(x) (x << 8)
+/* data types */
+/* rx */ +typedef struct{
- volatile void *packet;
- volatile unsigned long control;
+} rx_descriptor_t;
+typedef struct{
- volatile unsigned long info; /* RO */
- volatile unsigned long hashCRC; /* RO */
+} rx_status_t;
+/* tx */ +typedef struct{
- volatile void *packet;
- volatile unsigned long control;
+} tx_descriptor_t;
+typedef struct{
- volatile unsigned long info; /* RO */
+} tx_status_t;
+/* NXP's OUI registered @ IEEE */ +#define NXP_ETN_OUI 0x006037
+/* ip3912 ETN registers */ +#define ETN1_BASE CONFIG_IP3912_ETN1_BASE +#define ETN2_BASE CONFIG_IP3912_ETN2_BASE
+/* offsets to base address */ +#define ETN_MAC1 0x0000 +#define ETN_MAC2 0x0004 +#define ETN_IPGT 0x0008 +#define ETN_IPGR 0x000c +#define ETN_CLRT 0x0010 +#define ETN_MAXF 0x0014 +#define ETN_SUPP 0x0018 +#define ETN_TEST 0x001c +#define ETN_MCFG 0x0020 +#define ETN_MCMD 0x0024 +#define ETN_MADR 0x0028 +#define ETN_MWTD 0x002c +#define ETN_MRDD 0x0030 +#define ETN_MIND 0x0034 +#define ETN_SA0 0x0040 +#define ETN_SA1 0x0044 +#define ETN_SA2 0x0048 +#define ETN_COMMAND 0x0100 +#define ETN_STATUS 0x0104 +#define ETN_RXDESCRIPTOR 0x0108 +#define ETN_RXSTATUS 0x010c +#define ETN_RXDESCRIPTORNUMBER 0x0110 +#define ETN_RXPRODUCEINDEX 0x0114 +#define ETN_RXCONSUMEINDEX 0x0118 +#define ETN_TXDESCRIPTOR 0x011c +#define ETN_TXSTATUS 0x0120 +#define ETN_TXDESCRIPTORNUMBER 0x0124 +#define ETN_TXPRODUCEINDEX 0x0128 +#define ETN_TXCONSUMEINDEX 0x012c +#define ETN_TXRTDESCRIPTOR 0x0130 +#define ETN_TXRTSTATUS 0x0134 +#define ETN_TXRTDESCRIPTORNUMBER 0x0138 +#define ETN_TXRTPRODUCEINDEX 0x013c +#define ETN_TXRTCONSUMEINDEX 0x0140 +#define ETN_QOSTIMEOUT 0x0148 +#define ETN_TSV0 0x0158 +#define ETN_TSV1 0x015c +#define ETN_RSV 0x0160 +#define ETN_FLOWCONTROLCOUNTER 0x0170 +#define ETN_FLOWCONTROLSTATUS 0x0174 +#define ETN_RXFILTERCTRL 0x0200 +#define ETN_RXFILTERWOLSTATUS 0x0204 +#define ETN_RXFILTERWOLCLEAR 0x0208 +#define ETN_HASHFILTERL 0x0210 +#define ETN_HASHFILTERH 0x0214 +#define ETN_INTSTATUS 0x0fe0 +#define ETN_INTENABLE 0x0fe4 +#define ETN_INTCLEAR 0x0fe8 +#define ETN_INTSET 0x0fec +#define ETN_POWERDOWN 0x0ff4 +#define ETN_MODULEID 0x0ffc
+/* values for control */ +#define ETN_CONTROL_INTERRUPT 0x80000000 +#define ETN_CONTROL_LAST 0x40000000 +#define ETN_CONTROL_CRC 0x20000000 +#define ETN_CONTROL_PAD 0x10000000 +#define ETN_CONTROL_HUGE 0x08000000 +#define ETN_CONTROL_OVERRIDE 0x04000000
+/* registers in the SMSC LAN8700 PHY */ +/* +00 Basic Control Register Basic +01 Basic Status Register Basic +02 PHY Identifier 1 Extended +03 PHY Identifier 2 Extended +04 Auto-Negotiation Advertisement Register Extended +05 Auto-Negotiation Link Partner Ability Register Extended +06 Auto-Negotiation Expansion Register Extended +16 Silicon Revision Register Vendor-specific +17 Mode Control/Status Register Vendor-specific +18 Special Modes Vendor-specific +20 Reserved Vendor-specific +21 Reserved Vendor-specific +22 Reserved Vendor-specific +23 Reserved Vendor-specific +27 Control / Status Indication Register Vendor-specific +28 Special internal testability controls Vendor-specific +29 Interrupt Source Register Vendor-specific +30 Interrupt Mask Register Vendor-specific +31 PHY Special Control/Status Register Vendor-specific +*/ +#define ETN_PHY_BASIC_CONTROL 0x00 +#define ETN_PHY_BASIC_STATUS 0x01 +#define ETN_PHY_ID1 0x02 +#define ETN_PHY_ID2 0x03 +#define ETN_PHY_AUTONEG_ADV 0x04 +#define ETN_PHY_AUTONEG_LINK 0x05 +#define ETN_PHY_AUTONEG_EXP 0x06 +#define ETN_PHY_SILICON 0x10 +#define ETN_PHY_MODE_CONTROL_STATUS 0x11 +#define ETN_PHY_SPECIAL_MODES 0x12 +#define ETN_PHY_CONTROL_STATUS_INDICATION 0x1b +#define ETN_PHY_INTERNAL_TESTABILITY 0x1c +#define ETN_PHY_INTERRUPT_SOURCE 0x1d +#define ETN_PHY_INTERRUPT_MASK 0x1e +#define ETN_PHY_SPECIAL_MODE_CONTROL_STATUS 0x1f
+/* PHY identification */ +#define PHY_ID_LXT970 0x78100000 /* LXT970 */ +#define PHY_ID_LXT971 0x001378e0 /* LXT971 and 972 */ +#define PHY_ID_82555 0x02a80150 /* Intel 82555 */ +#define PHY_ID_QS6612 0x01814400 /* QS6612 */ +#define PHY_ID_AMD79C784 0x00225610 /* AMD 79C784 */ +#define PHY_ID_LSI80225 0x0016f870 /* LSI 80225 */ +#define PHY_ID_LSI80225B 0x0016f880 /* LSI 80225/B */ +#define PHY_ID_DM9161 0x0181B880 /* Davicom DM9161 */ +#define PHY_ID_KSM8995M 0x00221450 /* MICREL KS8995MA */ +#define PHY_ID_SMSC8700 0x0007C0C0 /* SMSC LAN 8700 */
regards, Ben

Dear =?UTF-8?B?SsO8cmdlbiBTY2jDtnc=?=,
In message 20090104225616.40274804@schleppi.schoew.net you wrote:
--===============0063675513== Content-Type: multipart/signed; boundary="Sig_/p.d_N5rCt+xwh6DxRb9e5B9"; protocol="application/pgp-signature"; micalg=PGP-SHA1
--Sig_/p.d_N5rCt+xwh6DxRb9e5B9 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: quoted-printable
drivers/net/Makefile | 1 + drivers/net/ip3912.c | 659 ++++++++++++++++++++++++++++++++> ++++ drivers/net/ip3912.h | 174 ++++++++++
Signed-off-by: line missing.
Best regards,
Wolfgang Denk

MAINTAINERS | 4 + MAKEALL | 1 + Makefile | 7 + board/dspg/firetux/Makefile | 59 ++++ board/dspg/firetux/boardrevision.c | 299 ++++++++++++++++ board/dspg/firetux/config.mk | 44 +++ board/dspg/firetux/firetux.c | 413 ++++++++++++++++++++++ board/dspg/firetux/firetux.h | 144 ++++++++ board/dspg/firetux/gpio.c | 134 ++++++++ board/dspg/firetux/led.c | 169 +++++++++ board/dspg/firetux/lowlevel_init.S | 404 ++++++++++++++++++++++ board/dspg/firetux/memsetup.S | 381 +++++++++++++++++++++ board/dspg/firetux/nand.c | 68 ++++ board/dspg/firetux/relocate.S | 252 ++++++++++++++ board/dspg/firetux/u-boot.lds | 57 +++ include/configs/firetux.h | 454 +++++++++++++++++++++++++
diff --git a/MAINTAINERS b/MAINTAINERS index f048795..6764085 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -581,6 +581,10 @@ Stefan Roese sr@denx.de pdnb3 xscale scpu xscale
+Juergen Schoew js@emlix.com + + firetux ARM926EJS (PNX8181) + Robert Schwebel r.schwebel@pengutronix.de
csb226 xscale diff --git a/MAKEALL b/MAKEALL index cc49a98..1b8a640 100755 --- a/MAKEALL +++ b/MAKEALL @@ -492,6 +492,7 @@ LIST_ARM9=" \ cp926ejs \ cp946es \ cp966 \ + firetux \ lpd7a400 \ mx1ads \ mx1fs2 \ diff --git a/Makefile b/Makefile index 4df4812..59a887d 100644 --- a/Makefile +++ b/Makefile @@ -2808,6 +2808,13 @@ voiceblue_config: unconfig @$(MKCONFIG) $(@:_config=) arm arm925t voiceblue
######################################################################### +## DSPG "firetux" NXP PNX8181 +######################################################################### + +firetux_config: unconfig + @$(MKCONFIG) $(@:_config=) arm arm926ejs firetux dspg pnx8181 + +######################################################################### ## S3C44B0 Systems #########################################################################
diff --git a/board/dspg/firetux/Makefile b/board/dspg/firetux/Makefile new file mode 100644 index 0000000..c4c86e5 --- /dev/null +++ b/board/dspg/firetux/Makefile @@ -0,0 +1,59 @@ +# firetux makefile +# +# (C) Copyright 2007-2009, emlix GmbH, Germany +# Juergen Schoew js@emlix.com +# +# (C) Copyright 2008, DSPG Technologies GmbH, Germany +# (C) Copyright 2007, NXP Semiconductors Germany GmbH +# Matthias Wenzel, nxp@mazzoo.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-y += firetux.o boardrevision.o led.o gpio.o +COBJS-$(CONFIG_CMD_NAND) += nand.o +SOBJS-y += lowlevel_init.o memsetup.o relocate.o + +SRCS := $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c) +OBJS := $(addprefix $(obj),$(COBJS-y)) +SOBJS := $(addprefix $(obj),$(SOBJS-y)) + +all: $(LIB) + +$(LIB): $(obj).depend $(OBJS) $(SOBJS) + $(AR) $(ARFLAGS) $@ $(OBJS) $(SOBJS) + +clean: + rm -f $(SOBJS) $(OBJS) + +distclean: clean + rm -f $(LIB) core *.bak .depend + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/board/dspg/firetux/boardrevision.c b/board/dspg/firetux/boardrevision.c new file mode 100644 index 0000000..3119090 --- /dev/null +++ b/board/dspg/firetux/boardrevision.c @@ -0,0 +1,299 @@ +/* + * firetux board detection + * + * (C) Copyright 2007-2009, emlix GmbH, Germany + * Juergen Schoew js@emlix.com + * (C) Copyright 2008, Sebastian Hess, emlix GmbH sh@emlix.com + * + * (C) Copyright 2008, DSPG Technologies GmbH, Germany + * (C) Copyright 2007, NXP Semiconductors Germany GmbH + * Matthias Wenzel, nxp@mazzoo.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 + */ + +/* + * These VEGA boards are very similair to each other. The main difference + * is the phy address of the network, CPU revision, number of leds and keys. + */ + +#include <common.h> +#include <asm/io.h> +#include "firetux.h" + +#ifndef CONFIG_IP3912_ETN1_BASE +#define CONFIG_IP3912_ETN1_BASE 0xC1600000 +#endif +#ifndef CONFIG_IP3912_ETN2_BASE +#define CONFIG_IP3912_ETN2_BASE 0xC1700000 +#endif + +/* ip3912 / pnx8181 ETN registers */ +#define ETN1_BASE CONFIG_IP3912_ETN1_BASE +#define ETN2_BASE CONFIG_IP3912_ETN2_BASE + +#define ETN_MAC1 0x0000 +#define ETN_SUPP 0x0018 +#define ETN_MCFG 0x0020 +#define ETN_MADR 0x0028 +#define ETN_MCMD 0x0024 +#define ETN_MWTD 0x002c +#define ETN_MRDD 0x0030 +#define ETN_MIND 0x0034 +#define ETN_COMMAND 0x0100 + +static char firetux_boardrevision = UNKNOWN_PNX8181; + +char get_boardrevision(void) +{ + return firetux_boardrevision; +} + +static void detect_etn_start(void) +{ + debug("board detect: initialize ETN\n"); + /* reset MII mgmt, set MII clock */ + writel(0x0000801c, (void *)(ETN1_BASE + ETN_MCFG)); + writel(0x0000001c, (void *)(ETN1_BASE + ETN_MCFG)); + + /* enable RMMI */ + writel(0x00000600, (void *)(ETN1_BASE + ETN_COMMAND)); + + /* reset MAC layer */ + writel(0x0000cf00, (void *)(ETN1_BASE + ETN_MAC1)); + /* release MAC soft reset */ + writel(0x00000000, (void *)(ETN1_BASE + ETN_MAC1)); + /* reset rx-path, tx-path, host registers */ + writel(0x00000638, (void *)(ETN1_BASE + ETN_COMMAND)); + /* reset RMII, 100Mbps MAC, 10Mbps MAC */ + writel(0x1888, (void *)(ETN1_BASE + ETN_SUPP)); + writel(0x1000, (void *)(ETN1_BASE + ETN_SUPP)); +} + +/* Wait for the ETN engine to be ready */ +static void detect_phy_wait(void) +{ + int i, status; + for (i = 0; i < 1000; i++) { + status = readl((void *)(ETN1_BASE + ETN_MIND)) & 0x7; + if (!status) + return; + udelay(1); + } + debug("board detect: wait PHY timed out!\n"); +} + +/* write to phy */ +static void detect_phy_write(u8 address, u8 reg, u16 data) +{ + writel((address << 8) | reg, (void *)(ETN1_BASE + ETN_MADR)); + writel(data, (ETN1_BASE + ETN_MWTD)); + detect_phy_wait(); +} + +/* read from phy */ +static u16 detect_phy_read(u8 address, u8 reg) +{ + u16 value; + writel((address << 8) | reg, (void *)(ETN1_BASE + ETN_MADR)); + writel(0x00000001, (void *)(ETN1_BASE + ETN_MCMD)); + detect_phy_wait(); + + value = readl((void *)(ETN1_BASE + ETN_MRDD)); + writel(0x00000000, (void *)(ETN1_BASE + ETN_MCMD)); + return value; +} + +/* do a software reset on the phy */ +static int detect_phy_softreset(u8 phyaddr) +{ + int i, rc; + + debug("board detect: softreset PHY @0x%02x ", phyaddr); + + /* + * reset power down bit and set autonegotiation in + * phy basic control register 0 + */ + detect_phy_write(phyaddr, 0x00, 0x1200); + + /* set reset bit in phy basic control register */ + detect_phy_write(phyaddr, 0x00, detect_phy_read(phyaddr, 0x00) + | (1 << 15)); + udelay(260); /* HW ref (pg. 51): 256us, IEEE <= 500ms */ + + /* Check for bit reset */ + for (i = 0; i < 1000; i++) { + rc = detect_phy_read(phyaddr, 0x00); + if (!(rc & (1 < 11))) { + debug("OK\n"); + return 0; + } + } + + debug("timed out!\n"); + return -1; +} + +/* pull the hardware reset line of the phy */ +static int detect_phy_hardreset(int gpio) +{ + /* strobe the reset pin */ + debug("board detect: hardreset PHY with GPIO %d\n", gpio); + clear_gpioa(gpio); + udelay(120); /* min 100us */ + set_gpioa(gpio); + udelay(1); /* min 800ns */ + + return 0; +} + +/* write the phy address to the special function register */ +static int detect_phy_init(int phyaddr) +{ + int i; + u16 status, check_status = 0x40e0 | (phyaddr & 0x1f); + + debug("board detect: PHY @0x%02x init ", phyaddr); + + for (i = 0; i < 1000; i++) { + /* Set the special function register (Reg 18) */ + detect_phy_write(phyaddr, 0x12, check_status); + + /* Read back the Register */ + status = detect_phy_read(phyaddr, 0x12); + if ((status & 0x40ff) == check_status) { + debug("powerdown disabled\n"); + return detect_phy_softreset(phyaddr); + } + udelay(10); + } + debug("disable powerdown failed\n"); + return -1; +} + +static int detect_eth_check_vega_phy(void) +{ + int status, scon_sysver, cpuversion; + + detect_etn_start(); + + /* Check for the CPU revision */ + scon_sysver = readw(PNX8181_REG_SC_SYSVER); + + if (scon_sysver == 0x4111) { + cpuversion = 1; /* a revision 1 CPU */ + debug("board detect: PNX8181 V1 CPU found\n"); + } else if ((scon_sysver == 0x4121) || (scon_sysver == 0x4122)) { + cpuversion = 2; /* a revision 2 CPU */ + debug("board detect: PNX8181 V2 CPU found\n"); + + /* a V2 cpu can only be on IIIb or IIIc boards */ + goto cpu_v2; + } else { + cpuversion = 0; + debug("board detect: unknown PNX8181 CPU revision\n"); + + return UNKNOWN_PNX8181; + } + +cpu_v1: + /* phy reset for IIIa and IIIb is on GPIO A12 */ + config_gpioa(12, SYSMUX_GPIOA, GPIOA_DIR_OUTPUT, SYSPAD_PULL_UP, 1); + detect_phy_hardreset(12); + + /* If both phy 1 and 2 are ok: III-a Board*/ + status = detect_phy_init(0x01); + if (!status && !detect_phy_init(0x02)) + return VEGA_BASESTATION_IIIA; + + /* + * A V1 cpu can only be on EZ-MCP or IIIa boards, but this board uses + * an unknown phys configuration, therefore it is an unknown board + */ + debug("board detect: unknown board with V1 CPU\n"); + return UNKNOWN_PNX8181; + +cpu_v2: + /* set gpioA3 to 0 to hold possible IIIc phy in reset */ + config_gpioa(3, SYSMUX_GPIOA, GPIOA_DIR_OUTPUT, SYSPAD_PULL_UP, 0); + + /* Phy 29 and 30 are ok: III-b Board */ + config_gpioa(12, SYSMUX_GPIOA, GPIOA_DIR_OUTPUT, SYSPAD_PULL_UP, 1); + detect_phy_hardreset(12); + debug("board detect: checking for VEGA Basestation IIIb\n"); + status = detect_phy_init(0x1d); + if (!status && !detect_phy_init(0x1e)) + return VEGA_BASESTATION_IIIB; + + /* for IIIC we need to set some pull-up / pull-down */ + writel((readl((void *)(PNX8181_SCON_BASE + PNX8181_SYSPAD4)) + & 0xf7f5755f) | 0x080a8aa0, + (void *)PNX8181_SCON_BASE + PNX8181_SYSPAD4); + + /* phy reset for IIIc is on GPIO A3, hold GPIO A12 low */ + clear_gpioa(12); + detect_phy_hardreset(3); + + /* Phy 29 and 30 are ok: III-c Board */ + debug("board detect: checking for VEGA Basestation IIIc\n"); + status = detect_phy_init(0x1d); + if (!status && !detect_phy_init(0x1e)) + return VEGA_BASESTATION_IIIC; + + debug("board detect: unknown board with V2 CPU\n"); + return UNKNOWN_PNX8181; +} + +void board_detect(void) +{ + int cgu_sccon; + + debug("board detection "); + /* simple board detection */ + cgu_sccon = readw((void *)PNX8181_REG_CGU_SCCON); + cgu_sccon = ((cgu_sccon >> 3) & 0x3f); + + /* The easy case, only the EZ_MCP ist clocked slow */ + if (cgu_sccon == 11) { + /* ez_mcp_pnx8181 */ + firetux_boardrevision = EZ_MCP_PNX8181; + debug("found EZ_MCP_PNX8181\n"); + /* just be sure to set the phy to a known state */ + config_gpioa(12, SYSMUX_GPIOA, GPIOA_DIR_OUTPUT, + SYSPAD_PULL_UP, 1); + detect_phy_hardreset(12); + detect_phy_init(0x01); + detect_phy_init(0x02); + return; + } + + if (cgu_sccon == 14) { + /* + * vega_pnx8181_basestation Platform III a, b, c + * we need futher inevestigation by network test + */ + firetux_boardrevision = VEGA_BASESTATION_IIIA; + debug("clock 208MHz, need further investigation\n"); + } + + /* ... check the phy to differ between V1 and V2 Boards */ + if (firetux_boardrevision == VEGA_BASESTATION_IIIA) + firetux_boardrevision = detect_eth_check_vega_phy(); +} diff --git a/board/dspg/firetux/config.mk b/board/dspg/firetux/config.mk new file mode 100644 index 0000000..035946a --- /dev/null +++ b/board/dspg/firetux/config.mk @@ -0,0 +1,44 @@ +# firetux compiler config +# +# (C) Copyright 2007-2009, emlix GmbH, Germany +# Juergen Schoew js@emlix.com +# +# (C) Copyright 2008, DSPG Technologies GmbH, Germany +# (C) Copyright 2007, NXP Semiconductors Germany GmbH +# Matthias Wenzel, nxp@mazzoo.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 +# + + +ifndef CONFIG_SYS_PSRAM +# SDRAM +TEXT_BASE = 0x20780000 +else +# mobile pSRAM +TEXT_BASE = 0x90700000 +endif + +PLATFORM_CPPFLAGS += -fPIC -fPIE -fno-jump-tables # -msingle-pic-base + +ifneq ($(OBJTREE),$(SRCTREE)) +# We are building u-boot in a separate directory, use generated +# .lds script from OBJTREE directory. +LDSCRIPT := $(OBJTREE)/board/$(BOARDDIR)/u-boot.lds +endif diff --git a/board/dspg/firetux/firetux.c b/board/dspg/firetux/firetux.c new file mode 100644 index 0000000..52f0ad1 --- /dev/null +++ b/board/dspg/firetux/firetux.c @@ -0,0 +1,413 @@ +/* + * firetux board specific setup + * + * (C) Copyright 2007-2009, emlix GmbH, Germany + * Juergen Schoew js@emlix.com + * + * (C) Copyright 2008, DSPG Technologies GmbH, Germany + * (C) Copyright 2007, NXP Semiconductors Germany GmbH + * Matthias Wenzel, nxp@mazzoo.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 <common.h> +#include <asm/io.h> +#include <status_led.h> +#include "firetux.h" + +DECLARE_GLOBAL_DATA_PTR; + +/* functions for ethernet initialization */ +extern int ip3912_eth_initialize(unsigned char nr, unsigned int etn_base, + unsigned int phy_base, unsigned char phy_addr, unsigned char rmii); +extern int ip3912_miiphy_initialize(bd_t *bis); + +#ifdef CONFIG_SHOW_BOOT_PROGRESS +void show_boot_progress(int progress) +{ + printf("Boot reached stage %d\n", progress); +} +#endif + +void firetux_gpio_init(void) +{ + if (get_boardrevision() < 2) /* EZ_MCP has no keys or leds */ + return; + + /* set GPIOA10 and GPIOA2 for key input */ + config_gpioa(10, SYSMUX_GPIOA, GPIOA_DIR_INPUT, SYSPAD_PULL_UP, -1); + config_gpioa(2, SYSMUX_GPIOA, GPIOA_DIR_INPUT, SYSPAD_PULL_UP, -1); + + switch (get_boardrevision()) { + case 2: + /* Baseboard IIIa: set GPIO A3 A9 A16 A31 for LED output */ + config_gpioa(3, SYSMUX_GPIOA, GPIOA_DIR_OUTPUT, + SYSPAD_PULL_UP, 1); + config_gpioa(9, SYSMUX_GPIOA, GPIOA_DIR_OUTPUT, + SYSPAD_PULL_UP, 1); + config_gpioa(16, SYSMUX_GPIOA, GPIOA_DIR_OUTPUT, + SYSPAD_PULL_UP, 1); + config_gpioa(31, SYSMUX_GPIOA, GPIOA_DIR_OUTPUT, + SYSPAD_PULL_UP, 1); + break; + case 3: + case 4: + /* set GPIOA9 and GPIOA0 for LED output */ + config_gpioa(9, SYSMUX_GPIOA, GPIOA_DIR_OUTPUT, + SYSPAD_PULL_UP, 1); + config_gpioa(0, SYSMUX_GPIOA, GPIOA_DIR_OUTPUT, + SYSPAD_PULL_UP, 1); + break; + default: + break; + } +} + +#ifdef CONFIG_CMD_NAND +void firetux_nandflash_init(void) +{ + /* + * Hardware configuration + * setup GPIOB18 / FMP40 to GPIO input with internal pullup + */ + writel(readl((void *)(PNX8181_SCON_BASE + PNX8181_SYSMUX3)) & ~(0x30), + (void *)(PNX8181_SCON_BASE + PNX8181_SYSMUX3)); + /* set FPM40 to GPIOb18 */ + writel(readl((void *)(PNX8181_SCON_BASE + PNX8181_SYSMUX3)) |= 0x10, + (void *)(PNX8181_SCON_BASE + PNX8181_SYSMUX3)); + /* set to input */ + writel(readl((void *)PNX8181_GPIOB_DIRECTION) + & ~(1 << CONFIG_SYS_NAND_RB_BIT), + (void *)PNX8181_GPIOB_DIRECTION); + /* set pull up */ + writel(readl((void *)(PNX8181_SCON_BASE + PNX8181_SYSPAD2)) + & ~(3 << 20), + (void *)(PNX8181_SCON_BASE + PNX8181_SYSPAD2)); + + /* setup access timing for CS0 / 16bit */ + writel(0x0001, (void *)(PNX8181_REG_EBI1_CS0 + PNX8181_EBI_MAIN_OFF)); + writel(0x1FFFF, (void *)(PNX8181_REG_EBI1_CS0 + PNX8181_EBI_READ_OFF)); + writel(0x1FFFF, (void *)(PNX8181_REG_EBI1_CS0 + PNX8181_EBI_WRITE_OFF)); + writel(0x0CF8, (void *)(PNX8181_REG_EBI1_CS0 + PNX8181_EBI_BURST_OFF)); +} +#else +void firetux_norflash_init(void) +{ +#ifdef CONFIG_SYS_OPTIMIZE_NORFLASH + /* optimize access speed */ + writel(0x9, (void *)(PNX8181_REG_EBI1_CS0 + PNX8181_EBI_MAIN_OFF)); + writel(0x22D88, (void *)(PNX8181_REG_EBI1_CS0 + PNX8181_EBI_READ_OFF)); + writel(0x22D88, (void *)(PNX8181_REG_EBI1_CS0 + PNX8181_EBI_WRITE_OFF)); + writel(0x0000, (void *)(PNX8181_REG_EBI1_CS0 + PNX8181_EBI_BURST_OFF)); +#endif +} +#endif + +void firetux_irq_disable(void) +{ + int i; + + writel(31, (void *)PNX8181_INTC_PRIOMASK_IRQ); + writel(31, (void *)PNX8181_INTC_PRIOMASK_FIQ); + + for (i = 1; i < 67; i++) + PNX8181_DISABLEIRQ(i); + + writel(readl((void *)PNX8181_CGU_GATESC) & 0xfdd7becd, + (void *)PNX8181_CGU_GATESC); +} + +/* Ethernet */ +void firetux_sysmux_config_rmii(void) +{ + /* config gpio c15 and c16 for RMII */ + writel((readl((void *)(PNX8181_SCON_BASE + PNX8181_SYSMUX4)) + & ~(0x3 << 0)), (void *)(PNX8181_SCON_BASE + PNX8181_SYSMUX4)); + writel((readl((void *)(PNX8181_SCON_BASE + PNX8181_SYSMUX5)) + & ~(0x3 << 30)), (void *)(PNX8181_SCON_BASE + PNX8181_SYSMUX5)); +} + +void firetux_sysmux_config_etn1(void) +{ + /* config gpio c0 and c6 for ETN1 */ + writel((readl((void *)(PNX8181_SCON_BASE + PNX8181_SYSMUX4)) + & 0xffffc000), (void *)(PNX8181_SCON_BASE + PNX8181_SYSMUX4)); +} + +void firetux_sysmux_config_etn2(void) +{ + /* config gpio c7 and c13 for ETN2 (alternative config for sd-card) */ + writel((readl((void *)(PNX8181_SCON_BASE + PNX8181_SYSMUX4)) + & 0xf0003fff), (void *)(PNX8181_SCON_BASE + PNX8181_SYSMUX4)); +} + +int board_eth_init(bd_t *bis) +{ + int rc = 0; + +/* + * priority setting for ETN over CPU for SDRAM access + * enable port-aging with priority for ETN + */ +#ifdef CONFIG_SYS_ETHER_FAIR_SCHEDULE + /* + * be fair: ETN and CPU are both high priority, but ETN gets + * higher priority and a much lower ageing penatly to get + * much more accesses to RAM + */ + writel(0x80000121, (void *)(PNX8181_SDI_SCHED + PNX8181_SCHED0)); + writel(0xffff0100, (void *)(PNX8181_SDI_SCHED + PNX8181_SCHED1)); + writel(0x00030131, (void *)(PNX8181_SDI_SCHED + PNX8181_SCHED2)); +#else + /* + * highly prioritise the ETN engine and lower CPU priority + * to archive a better network thoughput + */ + writel(0xffff0020, (void *)(PNX8181_SDI_SCHED + PNX8181_SCHED0)); + writel(0xffff0000, (void *)(PNX8181_SDI_SCHED + PNX8181_SCHED1)); + writel(0xffff0031, (void *)(PNX8181_SDI_SCHED + PNX8181_SCHED2)); +#endif + + /* increase priority for SCRAM access at AHB of descriptors */ + writew(7, (void *)(PNX8181_SC_ARB_BASE + PNX8181_SC_ARB_CFG2)); + writew(7, (void *)(PNX8181_SC_ARB_BASE + PNX8181_SC_ARB_CFG3)); + + /* + * init ETN clocks + * + * set ETNREFCLK to internal CGU clock, assuming a 13.824MHz crystal + * for other xtals see NXP's validation tests, + * lib/tools/source/swift_tools.c + */ + writel((15 << 9) | (62 << 3) | 3, (void *)PNX8181_CGU_PER2CON); + + /* turn on PLL */ + writel(readl((void *)PNX8181_CGU_PER2CON) | 0x00010000, + (void *)PNX8181_CGU_PER2CON); + /* wait for PLL lock */ + while (!(readl((void *)PNX8181_CGU_PER2CON) & 0x00020000)) + ; + + /* ungate ETN clocks */ + writel(readl((void *)PNX8181_CGU_PER2CON) | 0x00802000, + (void *)PNX8181_CGU_PER2CON); + + /* register ip3912 mii interface */ + ip3912_miiphy_initialize(gd->bd); + + /* register ethernet devices */ + switch (get_boardrevision()) { + case 1: + case 2: + firetux_sysmux_config_rmii(); + firetux_sysmux_config_etn1(); + firetux_sysmux_config_etn2(); + /* phys are at addr 0x1 & 0x2 at RMII phybus */ + rc |= ip3912_eth_initialize(0, CONFIG_IP3912_ETN1_BASE, + CONFIG_IP3912_ETN1_BASE, 0x01, 1); + rc |= ip3912_eth_initialize(1, CONFIG_IP3912_ETN2_BASE, + CONFIG_IP3912_ETN1_BASE, 0x02, 1); + break; + case 3: + case 4: + firetux_sysmux_config_rmii(); + firetux_sysmux_config_etn1(); + firetux_sysmux_config_etn2(); + /* phys are at addr 0x1e & 0x1d at RMII phybus */ + rc |= ip3912_eth_initialize(0, CONFIG_IP3912_ETN1_BASE, + CONFIG_IP3912_ETN1_BASE, 0x1e, 1); + rc |= ip3912_eth_initialize(1, CONFIG_IP3912_ETN2_BASE, + CONFIG_IP3912_ETN1_BASE, 0x1d, 1); + break; + default: + return -1; + } + return rc; +} + +/* + * Miscellaneous platform dependent initialisations + */ + +int board_init(void) +{ + /* arch number of Firetux Platform Boards */ + gd->bd->bi_arch_number = MACH_TYPE_PNX8181; + + /* adress of boot parameters / atags */ + gd->bd->bi_boot_params = PHYS_SDRAM_1 + 0x100; + + /* release the RSTAPU and RSTEXT signal which keeps the PHYs in reset */ + writel(readw((void *)PNX8181_WDRUCON) | 0x0009, + (void *)PNX8181_WDRUCON); + /* lower VDDIO to Vbgp * 2.44 (typ. 3.05V) */ + writel(0x0079, (void *)PNX8181_DAIF_RVDDC); + + /* select TXD2 for GPIOa11 and select RXD2 for GPIOa1 */ + writel(((readl((void *)(PNX8181_SCON_BASE + PNX8181_SYSMUX0)) + & 0xff3ffff3) | 0x00400004), + (void *)(PNX8181_SCON_BASE + PNX8181_SYSMUX0)); + /* select ETN for GPIOc0-16 */ + writel(readl((void *)(PNX8181_SCON_BASE + PNX8181_SYSMUX5)) + & 0xfffffffc, + (void *)(PNX8181_SCON_BASE + PNX8181_SYSMUX5)); + writel(readl((void *)(PNX8181_SCON_BASE + PNX8181_SYSMUX4)) + & 0x30000000, + (void *)(PNX8181_SCON_BASE + PNX8181_SYSMUX4)); + + /* use clk26m and fract-n for UART2 */ + writew(((1 << 7) | (1 << 1)), + (void *)(PNX8181_UART2_BASE + PNX8181_UART_FDIV_CTRL)); + writew(0x5F37, (void *)(PNX8181_UART2_BASE + PNX8181_UART_FDIV_M)); + writew(0x32C8, (void *)(PNX8181_UART2_BASE + PNX8181_UART_FDIV_N)); + + board_detect(); + + firetux_gpio_init(); + + icache_enable(); + dcache_enable(); + +#ifdef CONFIG_CMD_NAND + firetux_nandflash_init(); +#else + firetux_norflash_init(); +#endif + + firetux_irq_disable(); + + return 0; +} + +int firetux_keystatus(int key) +{ + int ret = 0; + + switch (key) { + case 1: /* GPIOA2 */ + ret = get_gpioa(2); + break; + case 2: /* GPIOA10 */ + ret = get_gpioa(10); + break; + default: + ret = -1; + break; + } + + return ret; +} + +void firetux_check_bootkey(void) +{ + int i = 0, abort = 0; + + while ((abort == 0) && (i < 500)) { + if (firetux_keystatus(2) == 1) { + setenv("bootcmd", "run bootcmd1"); + firetux_set_led(2, 0); + abort = 1; + } + i++; + udelay(10000); + } + if (abort == 0) { + setenv("bootcmd", "run bootcmd2"); + puts("using alternative bootcmd\n"); + firetux_set_led(2, 1); + } +} + +int misc_init_r(void) +{ + if (get_boardrevision() > 1) /* ez_mcp_pnx8181 has no keys */ + firetux_check_bootkey(); + + setenv("verify", "n"); + return 0; +} + +#if defined(CONFIG_DISPLAY_CPUINFO) +int print_cpuinfo(void) +{ + unsigned int sysver, cgu_sccon, armclk, hclk; + + puts("CPU: "); + sysver = readw((void *)PNX8181_REG_SC_SYSVER); + printf("PNX8181-%d%c %s-ARM926EJ-S(ARMv5TEJ) ", + ((sysver >> 4) & 0xf), ((sysver & 0xf) + 64), + (((sysver >> 8) & 0xf) == 1) ? "OM6xxx" : "unknown"); + + cgu_sccon = readw((void *)PNX8181_CGU_SCCON); + + /* armclk = bbcki * nsc / msc / ksc */ + armclk = 13824 * (((cgu_sccon >> 3) & 0x3f) + 1) + / ((cgu_sccon & 0x7) + 1) + / (((cgu_sccon >> 10) & 0x3) + 1); + hclk = armclk / (((cgu_sccon >> 12) & 0xf) + 1); + + printf("@ %dMHz(armclk), %dMHz(hclk)\n", + (armclk / 1000), (hclk / 1000)); + return 0; +} +#endif + +#if defined(CONFIG_DISPLAY_BOARDINFO) +int checkboard(void) +{ + puts("Board: "); + + switch (get_boardrevision()) { + case 1: + puts("EZ_MCP_PNX8181\n"); + break; + case 2: + puts("Vega_PNX8181_BaseStation Platform III-a\n"); + break; + case 3: + puts("Vega_PNX8181_BaseStation Platform III-b\n"); + break; + case 4: + puts("Vega_PNX8181_BaseStation Platform III-c\n"); + break; + case 0: + default: + puts("unknown PNX8181 board\n"); + break; + } + + return 0; +} +#endif + +int dram_init(void) +{ + int reg; + + reg = readl((void *)PNX8181_SDI_CFG_1); + gd->bd->bi_dram[0].start = PHYS_SDRAM_1; + gd->bd->bi_dram[0].size = 1 << ( + (reg & 0x3) + /* dram width 8, 16, 32, 64 */ + (((reg & 0x30) >> 4) + 8) + /* columns 8, 9, 10, 11 */ + (((reg & 0x700) >> 8) + 9) + /* rows 9 .. 16 */ + ((reg & 0x3000) >> 12)); /* nr banks 1, 2, 4 */ + + return 0; +} diff --git a/board/dspg/firetux/firetux.h b/board/dspg/firetux/firetux.h new file mode 100644 index 0000000..0196197 --- /dev/null +++ b/board/dspg/firetux/firetux.h @@ -0,0 +1,144 @@ +/* + * firetux board specific defines + * + * (C) Copyright 2007-2009, emlix GmbH, Germany + * Juergen Schoew js@emlix.com + * + * (C) Copyright 2008, DSPG Technologies GmbH, Germany + * (C) Copyright 2007, NXP Semiconductors Germany GmbH + * Matthias Wenzel, nxp@mazzoo.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 + */ + +/* + * Boardrevisions: + * 0: unknown PNX8181 board + * 1: EZ_MCP_PNX8181 + * 2: Vega_PNX8181_BaseStation Platform III-a + * 3: Vega_PNX8181_BaseStation Platform III-b + * 4: Vega_PNX8181_BaseStation Platform III-c + */ +#define CONFIG_MAX_BOARDREVISIONS 4 +enum firetux_revisions { + Any_PNX8181_BaseStation = -1, + UNKNOWN_PNX8181 = 0, + EZ_MCP_PNX8181, + VEGA_BASESTATION_IIIA, + VEGA_BASESTATION_IIIB, + VEGA_BASESTATION_IIIC, +}; + +/* watchdog control register */ +#define PNX8181_WDRUCON 0xc2203000 + +/* digital to analog interface */ +#define PNX8181_DAIF_RVDDC 0xc2000000 + +/* console port */ +#define PNX8181_UART2_BASE 0xc2005000 +#define PNX8181_UART_FDIV_CTRL 0xc00 +#define PNX8181_UART_FDIV_M 0xc04 +#define PNX8181_UART_FDIV_N 0xc08 + +/* gpio settings */ +#define PNX8181_SCON_BASE 0xC2204000 +#define PNX8181_REG_SC_SYSVER (PNX8181_SCON_BASE + 0x0) +#define PNX8181_SYSMUX0 0x0C +#define PNX8181_SYSMUX1 0x10 +#define PNX8181_SYSMUX2 0x14 +#define PNX8181_SYSMUX3 0x18 +#define PNX8181_SYSMUX4 0x1C +#define PNX8181_SYSMUX5 0x20 +#define PNX8181_SYSPAD0 0x34 +#define PNX8181_SYSPAD1 0x38 +#define PNX8181_SYSPAD2 0x3c +#define PNX8181_SYSPAD3 0x40 +#define PNX8181_SYSPAD4 0x44 +#define PNX8181_SYSPAD5 0x48 + +#define SYSMUX_GPIOA 0x0 + +#define SYSPAD_PULL_UP 0x0 +#define SYSPAD_REPEATER 0x1 +#define SYSPAD_PLAIN_INPUT 0x2 +#define SYSPAD_PULL_DOWN 0x3 + +#define PNX8181_GPIOA_PINS 0xc2104000 +#define PNX8181_GPIOA_OUTPUT 0xc2104004 +#define PNX8181_GPIOA_DIRECTION 0xc2104008 + +#define PNX8181_GPIOB_DIRECTION 0xc2104208 + +#define GPIOA_DIR_OUTPUT 1 +#define GPIOA_DIR_INPUT 0 + +/* timing for CS0 (NAND) */ +#define PNX8181_REG_EBI1_BASE 0xBC000000 +#define PNX8181_REG_EBI1_CS0 (PNX8181_REG_EBI1_BASE + 0x00) +#define PNX8181_EBI_MAIN_OFF 0x00 +#define PNX8181_EBI_READ_OFF 0x04 +#define PNX8181_EBI_WRITE_OFF 0x08 +#define PNX8181_EBI_BURST_OFF 0x0C + +/* irq resetting */ +#define PNX8181_INTC_REQUEST 0xC1100400 + +#define PNX8181_DISABLEIRQ(IRQ) writel((0x1f << 25), \ + (void *)PNX8181_INTC_REQUEST + (4 * IRQ)); + +#define PNX8181_INTC_PRIOMASK_IRQ 0xC1100000 +#define PNX8181_INTC_PRIOMASK_FIQ 0xC1100004 + +/* clock speed */ +#define PNX8181_CGU_SCCON 0xC2200004 +/* clock gate */ +#define PNX8181_CGU_GATESC 0xC2200008 +#define PNX8181_CGU_PER2CON 0xC2200018 + +/* priority for ETN over CPU for SDRAM access */ +#define PNX8181_SDI_SCHED 0xC1200100 +#define PNX8181_SCHED0 0x00 +#define PNX8181_SCHED1 0x04 +#define PNX8181_SCHED2 0x08 + +/* priority for SCRAM access at AHB */ +#define PNX8181_SC_ARB_BASE 0xc200ea00 +#define PNX8181_SC_ARB_CFG2 0x08 +#define PNX8181_SC_ARB_CFG3 0x0c + +/* clock settings */ +#define PNX8181_REG_CGU_SCCON 0xC2200004 + +/* sdram configuration */ +#define PNX8181_SDI_CFG_1 0xC1200000 + +/* external functions */ +extern unsigned char get_gpioa(unsigned char gpionr); +extern void set_gpioa(unsigned char gpionr); +extern void clear_gpioa(unsigned char gpionr); +extern void toggle_gpioa(unsigned char gpionr); +extern void set_direction_gpioa(unsigned char gpionr, unsigned char dir); +extern void set_syspad_gpioa(unsigned char gpionr, unsigned char pad); +extern void set_sysmux_gpioa(unsigned char gpionr, unsigned char mux); +extern void config_gpioa(unsigned char gpionr, unsigned char mux, + unsigned char dir, unsigned char pad, unsigned char value); + +extern char get_boardrevision(void); +extern void board_detect(void); diff --git a/board/dspg/firetux/gpio.c b/board/dspg/firetux/gpio.c new file mode 100644 index 0000000..425d9df --- /dev/null +++ b/board/dspg/firetux/gpio.c @@ -0,0 +1,134 @@ +/* + * firetux gpio driver + * + * (C) Copyright 2008-2009, emlix GmbH, Germany + * Juergen Schoew js@emlix.com + * + * (C) Copyright 2008, DSPG Technologies GmbH, Germany + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <asm/io.h> +#include "firetux.h" + +/* this library only supports GPIO A, because only this port is linear */ + +unsigned char get_gpioa(unsigned char gpionr) +{ + if ((gpionr < 0) || (gpionr > 31)) + return -1; + return (readl((void *)PNX8181_GPIOA_PINS) >> gpionr) & 1; +} + +void set_gpioa(unsigned char gpionr) +{ + if ((gpionr < 0) || (gpionr > 31)) + return; + writel((readl((void *)PNX8181_GPIOA_OUTPUT) | (1 << gpionr)), + (void *)PNX8181_GPIOA_OUTPUT); +} + +void clear_gpioa(unsigned char gpionr) +{ + if ((gpionr < 0) || (gpionr > 31)) + return; + writel((readl((void *)PNX8181_GPIOA_OUTPUT) & ~(1 << gpionr)), + (void *)PNX8181_GPIOA_OUTPUT); +} + +void toggle_gpioa(unsigned char gpionr) +{ + if ((gpionr < 0) || (gpionr > 31)) + return; + if (get_gpioa(gpionr)) + clear_gpioa(gpionr); + else + set_gpioa(gpionr); +} + +void set_direction_gpioa(unsigned char gpionr, unsigned char dir) +{ + if ((gpionr < 0) || (gpionr > 31)) + return; + if (dir) + writel(readl((void *)PNX8181_GPIOA_DIRECTION) | (1 << gpionr), + (void *)PNX8181_GPIOA_DIRECTION); + else + writel(readl((void *)PNX8181_GPIOA_DIRECTION) & ~(1 << gpionr), + (void *)PNX8181_GPIOA_DIRECTION); +} + +void set_syspad_gpioa(unsigned char gpionr, unsigned char pad) +{ + if ((gpionr < 0) || (gpionr > 31)) + return; + pad &= 0x3; + if (gpionr < 16) { + writel(readl((void *)(PNX8181_SCON_BASE + PNX8181_SYSPAD0)) + | (pad << (2 * gpionr)), + (void *)(PNX8181_SCON_BASE + PNX8181_SYSPAD0)); + } else { + gpionr -= 16; + writel(readl((void *)(PNX8181_SCON_BASE + PNX8181_SYSPAD1)) + | (pad << (2 * gpionr)), + (void *)(PNX8181_SCON_BASE + PNX8181_SYSPAD1)); + } +} + +void set_sysmux_gpioa(unsigned char gpionr, unsigned char mux) +{ + if ((gpionr < 0) || (gpionr > 31)) + return; + mux &= 0x3; + if (gpionr < 16) { + writel(readl((void *)(PNX8181_SCON_BASE + PNX8181_SYSMUX0)) + | (mux << (2 * gpionr)), + (void *)(PNX8181_SCON_BASE + PNX8181_SYSMUX0)); + } else { + gpionr -= 16; + writel(readl((void *)(PNX8181_SCON_BASE + PNX8181_SYSMUX1)) + | (mux << (2 * gpionr)), + (void *)(PNX8181_SCON_BASE + PNX8181_SYSMUX1)); + } +} + +void config_gpioa(unsigned char gpionr, unsigned char mux, unsigned char dir, + unsigned char pad, unsigned char value) +{ + if ((gpionr < 0) || (gpionr > 31)) + return; + + if (mux >= 0) + set_sysmux_gpioa(gpionr, mux); + + if (dir >= 0) + set_direction_gpioa(gpionr, dir); + + if (pad >= 0) + set_syspad_gpioa(gpionr, pad); + + if ((dir == GPIOA_DIR_OUTPUT) && (value >= 0)) { + if (value) + set_gpioa(gpionr); + else + clear_gpioa(gpionr); + } +} diff --git a/board/dspg/firetux/led.c b/board/dspg/firetux/led.c new file mode 100644 index 0000000..0a6636a --- /dev/null +++ b/board/dspg/firetux/led.c @@ -0,0 +1,169 @@ +/* + * firetux led support + * + * (C) Copyright 2008-2009, emlix GmbH, Germany + * Juergen Schoew js@emlix.com + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <asm/io.h> +#include <status_led.h> +#include "firetux.h" + +void firetux_set_led_VEGA_BASESTATION_IIIA(int led, int brightness) +{ + switch (led) { + case 1: /* GPIO A9 */ + if (brightness) + clear_gpioa(9); + else + set_gpioa(9); + break; + case 2: /* GPIO A31 */ + if (brightness) + clear_gpioa(31); + else + set_gpioa(31); + break; + case 3: /* GPIO A16 */ + if (brightness) + clear_gpioa(16); + else + set_gpioa(16); + break; + case 4: /* GPIO A3 */ + if (brightness) + clear_gpioa(3); + else + set_gpioa(3); + break; + default: + break; + } +} + +void firetux_led_toggle_VEGA_BASESTATION_IIIA(led_id_t mask) +{ + switch (mask) { + case 1: + toggle_gpioa(9); + break; + case 2: + /* GPIO A31 */ + toggle_gpioa(31); + break; + case 3: + /* only Board IIIa has this led */ + toggle_gpioa(16); + break; + case 4: + /* only Board IIIa has this led */ + toggle_gpioa(3); + break; + default: + break; + } +} + +void firetux_set_led_VEGA_BASESTATION_IIIB(int led, int brightness) +{ + switch (led) { + case 1: /* GPIO A9 */ + if (brightness) + clear_gpioa(9); + else + set_gpioa(9); + break; + case 2: /* GPIO A0 */ + if (brightness) + clear_gpioa(0); + else + set_gpioa(0); + break; + default: + break; + } +} + + +void firetux_led_toggle_VEGA_BASESTATION_IIIB(led_id_t mask) +{ + switch (mask) { + case 1: + toggle_gpioa(9); + break; + case 2: + /* GPIO A0 */ + toggle_gpioa(0); + break; + default: + break; + } +} + +void firetux_set_led(int led, int brightness) +{ + switch (get_boardrevision()) { + case 0: + case 1: + /* unknown and EZ_MCP does not have leds */ + break; + case 2: + firetux_set_led_VEGA_BASESTATION_IIIA(led, brightness); + break; + case 3: + case 4: + /* VEGA_BASESTATION_IIIB and VEGA_BASESTATION_IIIC */ + firetux_set_led_VEGA_BASESTATION_IIIB(led, brightness); + break; + default: + break; + } +} + +void __led_toggle(led_id_t mask) +{ + switch (get_boardrevision()) { + case 0: + case 1: + /* unknown and EZ_MCP does not have leds */ + break; + case 2: + firetux_led_toggle_VEGA_BASESTATION_IIIA(mask); + break; + case 3: + case 4: + /* VEGA_BASESTATION_IIIB and VEGA_BASESTATION_IIIC */ + firetux_led_toggle_VEGA_BASESTATION_IIIB(mask); + break; + default: + break; + } +} + +void __led_init(led_id_t mask, int state) +{ +} + +void __led_set(led_id_t mask, int state) +{ + firetux_set_led(mask, state); +} diff --git a/board/dspg/firetux/lowlevel_init.S b/board/dspg/firetux/lowlevel_init.S new file mode 100644 index 0000000..178a2d7 --- /dev/null +++ b/board/dspg/firetux/lowlevel_init.S @@ -0,0 +1,404 @@ +/* + * firetux board specific setup + * + * (C) Copyright 2007-2009, emlix GmbH, Germany + * Juergen Schoew, js@emlix.com + * + * (C) Copyright 2008, DSPG Technologies GmbH, Germany + * (C) Copyright 2007, NXP Semiconductors Germany GmbH + * Matthias Wenzel, nxp@mazzoo.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 <config.h> +#include <version.h> + +#define RESET_ADDRESS 0xffff0000 + +.global reset_cpu +reset_cpu: + ldr lr, =RESET_ADDRESS + mov pc, lr + +/* address/register map */ + +#define RAM_BASE 0x90000000 + +/* EBI */ +#define REG_EBI1_BASE 0xBC000000 + +#define REG_EBI1_CS0_V1 (REG_EBI1_BASE + 0x00) +#define REG_EBI1_CS1_V1 (REG_EBI1_BASE + 0x10) +#define REG_EBI1_CS2_V1 (REG_EBI1_BASE + 0x20) +#define REG_EBI1_CS3_V1 (REG_EBI1_BASE + 0x30) +#define REG_EBI1_CS4_V1 (REG_EBI1_BASE + 0x40) +#define REG_EBI1_CS5_V1 (REG_EBI1_BASE + 0x50) +#define REG_EBI1_IPID_V1 (REG_EBI1_BASE + 0xF0) + +#define REG_EBI1_CS0 (REG_EBI1_BASE + 0x00) +#define REG_EBI1_CS1 (REG_EBI1_BASE + 0x20) +#define REG_EBI1_CS2 (REG_EBI1_BASE + 0x40) +#define REG_EBI1_CS3 (REG_EBI1_BASE + 0x60) +#define REG_EBI1_CS4 (REG_EBI1_BASE + 0x80) +#define REG_EBI1_CS5 (REG_EBI1_BASE + 0xA0) +#define REG_EBI1_IPID (REG_EBI1_BASE + 0xFFC) + +/* read-only values identifying silicon version */ +#define REG_SCON_SYSVER 0xC2204000 +#define VAL_SYSVER_1 0x4111 +#define VAL_SYSVER_2A 0x4121 +#define VAL_SYSVER_2B 0x4122 /* 2B is a metalfix version */ + +#define VAL_EBI1_IPID_V1 0xB0503101 +#define VAL_EBI1_IPID_V2 0x20165100 /* value of datasheet */ +#define VAL_EBI1_IPID_V2a 0x20165000 /* value of hardware */ + +#define REG_EBI2_BASE 0xC0380000 + +#define REG_EBI2_CS0_V1 (REG_EBI2_BASE + 0x00) +#define REG_EBI2_CS1_V1 (REG_EBI2_BASE + 0x10) +#define REG_EBI2_CS2_V1 (REG_EBI2_BASE + 0x20) +#define REG_EBI2_CS3_V1 (REG_EBI2_BASE + 0x30) +#define REG_EBI2_CS4_V1 (REG_EBI2_BASE + 0x40) +#define REG_EBI2_CS5_V1 (REG_EBI2_BASE + 0x50) +#define REG_EBI2_IPID_V1 (REG_EBI2_BASE + 0xF0) + +#define REG_EBI2_CS0 (REG_EBI2_BASE + 0x00) +#define REG_EBI2_CS1 (REG_EBI2_BASE + 0x20) +#define REG_EBI2_CS2 (REG_EBI2_BASE + 0x40) +#define REG_EBI2_CS3 (REG_EBI2_BASE + 0x60) +#define REG_EBI2_CS4 (REG_EBI2_BASE + 0x80) +#define REG_EBI2_CS5 (REG_EBI2_BASE + 0xA0) +#define REG_EBI2_IPID (REG_EBI2_BASE + 0xFFC) + +#define EBI_MAIN_OFF 0x00 +#define EBI_READ_OFF 0x04 +#define EBI_WRITE_OFF 0x08 +#define EBI_BURST_OFF 0x0C + +/* CGU */ +/* Register definitions */ +#define REG_CGU_BASE 0xC2200000 +#define REG_CGU_DSPCON 0xC2200000 +#define REG_CGU_SCCON 0xC2200004 +#define REG_CGU_GATESC 0xC2200008 +#define REG_CGU_SLEEPSC 0xC220000C +#define REG_CGU_FDIV 0xC2200010 +#define REG_CGU_PER1CON 0xC2200014 +#define REG_CGU_PER2CON 0xC2200018 +#define REG_CGU_PER2BWCON 0xC220001C +#define REG_CGU_FIXCON 0xC2200020 +#define REG_CGU_DIVCON 0xC2200024 + + +#ifdef CONFIG_FIRETUX_HAS_CGU_SCCON_MSC_BUG +/* on some early PNX8181 V1 CPUs a sporadic bug on the silicon doesn't allow + * writing values > 3 to the msc field of SCCON, still the reset value is 5 + */ +# define SCCON 0x0011005b +#else +# define SCCON 0x0011005d +#endif +/* default reset value */ +#define PER1CON 0x00601be2 +#define PER2CON 0x01801ff3 +#define PER2BWCON 0x0000038d +#define FIXCON 0x000f07cf +#define DIVCON 0x102335e8 +/* clock gate: + * disabled: ebi2 fir usb fci usim pwm[123] kbs uart1 i2s ipint spi[12] + * enabled: ebi1 sdi adpcm etn[12] daif dmau drt gpio bmp uart2 i2c + * sctu extint intc + */ +#define GATESC 0x7ef803a7 +#define SLEEPSC 0x00000000 +#define FDIV 0x25ed097c + + +/* Set up the platform, once the cpu has been initialized */ +.globl lowlevel_init +lowlevel_init: + +/* with nandflash we have to skip the lowlevelinit */ +/* all setup is done with preloader of nandboot */ +#if !defined(CONFIG_NANDFLASH) && !defined(CONFIG_SKIP_RELOCATE_UBOOT) + + /* currently we run from flash, via EBI1/CS0 */ + + /* accesses to addresses not decoded result in hang */ + /* check for V2 CPU */ +check_for_v1_core: + ldr r2, =REG_SCON_SYSVER + ldr r0, [r2] + ldr r1, =VAL_SYSVER_1 + cmp r0, r1 + bne check_for_v2_core /* if not v1 core check for v2 */ + + /* validate EBI1 silicon version */ + ldr r2, =REG_EBI1_IPID_V1 + ldr r0, [r2] + ldr r1, =VAL_EBI1_IPID_V1 + cmp r0, r1 + beq pnx8181_v1_init /* v1 core has only one ebi version */ + b reset_cpu + +check_for_v2_core: + ldr r2, =REG_SCON_SYSVER + ldr r0, [r2] + ldr r1, =VAL_SYSVER_2A + cmp r0, r1 + beq is_v2_core + + ldr r1, =VAL_SYSVER_2B + cmp r0, r1 + beq is_v2_core + b reset_cpu /* if not v2 core jump to reset */ + +is_v2_core: + ldr r2, =REG_EBI1_IPID + ldr r0, [r2] + ldr r1, =VAL_EBI1_IPID_V2 + cmp r0, r1 + beq pnx8181_v2_init /* v2 core has only one ebi version */ + ldr r1, =VAL_EBI1_IPID_V2a + cmp r0, r1 + beq pnx8181_v2_init /* v2 core has only one ebi version */ + b reset_cpu + +pnx8181_v1_init: + /* configure flash (CS0) for minimum wait states */ + ldr r2, =(REG_EBI1_CS0_V1 + EBI_MAIN_OFF) + ldr r1, =0x0001 + str r1, [r2] + ldr r2, =(REG_EBI1_CS0_V1 + EBI_READ_OFF) + ldr r1, =0x22D8C + str r1, [r2] + ldr r2, =(REG_EBI1_CS0_V1 + EBI_WRITE_OFF) + ldr r1, =0x22D8C + str r1, [r2] + ldr r2, =(REG_EBI1_CS0_V1 + EBI_BURST_OFF) + ldr r1, =0x05b5 + str r1, [r2] + + /* configure pSRAM (CS1) for minimum wait states */ + ldr r2, =(REG_EBI1_CS1_V1 + EBI_MAIN_OFF) + ldr r1, =0x0001 + str r1, [r2] + ldr r2, =(REG_EBI1_CS1_V1 + EBI_READ_OFF) + ldr r1, =0x22D88 + str r1, [r2] + ldr r2, =(REG_EBI1_CS1_V1 + EBI_WRITE_OFF) + ldr r1, =0x22D88 + str r1, [r2] + ldr r2, =(REG_EBI1_CS1_V1 + EBI_BURST_OFF) + ldr r1, =0x0000 + str r1, [r2] + b ez_mcp_memtest + +pnx8181_v2_init: + /* configure flash (CS0) for minimum wait states */ + ldr r2, =(REG_EBI1_CS0 + EBI_MAIN_OFF) + ldr r1, =0x0001 + str r1, [r2] + ldr r2, =(REG_EBI1_CS0 + EBI_READ_OFF) + ldr r1, =0x22D8C + str r1, [r2] + ldr r2, =(REG_EBI1_CS0 + EBI_WRITE_OFF) + ldr r1, =0x22D8C + str r1, [r2] + ldr r2, =(REG_EBI1_CS0 + EBI_BURST_OFF) + ldr r1, =0x05b5 + str r1, [r2] + + /* configure pSRAM (CS1) for minimum wait states */ + ldr r2, =(REG_EBI1_CS1 + EBI_MAIN_OFF) + ldr r1, =0x0001 + str r1, [r2] + ldr r2, =(REG_EBI1_CS1 + EBI_READ_OFF) + ldr r1, =0x22D88 + str r1, [r2] + ldr r2, =(REG_EBI1_CS1 + EBI_WRITE_OFF) + ldr r1, =0x22D88 + str r1, [r2] + ldr r2, =(REG_EBI1_CS1 + EBI_BURST_OFF) + ldr r1, =0x0000 + str r1, [r2] + + /* try to determine if we are on a EZ_MCP_PNX8181 */ + /* we assume that all EZ boards have a PSRAM @0x90000000 */ +ez_mcp_memtest: + mov r1, #100 + mov r2, #0x90000000 +1: + str r2, [r2] + add r2, r2, #4 + sub r1, r1, #1 + cmp r1, #0 + bgt 1b + + mov r1, #100 + mov r2, #0x90000000 +1: + ldr r0, [r2] + cmp r0, r2 + bne vega_detected + add r2, r2, #4 + sub r1, r1, #1 + cmp r1, #0 + bgt 1b + b ez_mcp_detected + +vega_detected: + mov r0, #1 + b 1f + +ez_mcp_detected: + mov r0, #0 + b 1f + nop + nop + +1: + /* setup Clock Generation Unit CGU */ + /* setting default values */ + ldr r2, =REG_CGU_FDIV + ldr r1, =FDIV + str r1, [r2] + ldr r2, =REG_CGU_FIXCON + ldr r1, =FIXCON + str r1, [r2] + ldr r2, =REG_CGU_DIVCON + ldr r1, =DIVCON + str r1, [r2] + ldr r2, =REG_CGU_PER1CON + ldr r1, =PER1CON + str r1, [r2] + ldr r2, =REG_CGU_GATESC + ldr r1, =GATESC + str r1, [r2] + ldr r2, =REG_CGU_SLEEPSC + ldr r1, =SLEEPSC + str r1, [r2] + + /* in case we already run on PLL_SC (e.g. when we don't start from + * a power cycle) we need to enable and switch back to PLL_FIX */ + ldr r2, =REG_CGU_SCCON + ldr r1, [r2] /* read sccon */ + ands r1, r1, #(1<<16) /* mask scby */ + bne sccon_reset + +switch_to_pll_fix: + ldr r1, [r2] /* read sccon */ + orr r1, r1, #(1<<16) /* switch to pll_fix */ + str r1, [r2] + +sccon_reset: + /* reset value, see CONFIG_FIRETUX_HAS_CGU_SCCON_MSC_BUG */ + ldr r1, =SCCON + str r1, [r2] + + + /* check for vega or ez_mcp */ + cmp r0, #0 + beq ez_mcp_settings + +vega_settings: + /* vega settings */ + /* SC: armclk=208Mhz, hclk,pclk=104MHz */ + orr r1, r1, #(1<<16) /* use pll_fix */ + str r1, [r2] + bic r1, r1, #(0x7f<<3) /* clear nsc */ + bic r1, r1, #(3<<10) /* clear ksc */ + orr r1, r1, #(14<<3) /* nsc=14, ksc=0 */ + str r1, [r2] + orr r1, r1, #(1<<18) /* enable pll_sc */ + str r1, [r2] + b speed_ok + +ez_mcp_settings: + /* ez_mcp settings */ + /* reduced clock because of hardware constrains */ + /* SC: armclk=165MHz, hclk,pclk=83MHz */ + orr r1, r1, #(1<<16) /* use pll_fix */ + str r1, [r2] + bic r1, r1, #(0x7f<<3) /* clear nsc */ + bic r1, r1, #(3<<10) /* clear ksc */ + orr r1, r1, #(11<<3) /* nsc=11, ksc=0 */ + str r1, [r2] + orr r1, r1, #(1<<18) /* enable pll_sc */ + str r1, [r2] + +speed_ok: + mov r0, #(0x29<<8) /* wait max 250us */ + /* roughly calculated 208MHz, + -> 52000ticks, + 5intructions -> 10400 */ +wait_scpll: /* wait for pll lock */ + ldr r1, [r2] + ands r1, r1, #(1<<19) + bne scpll_ok + subs r0, r0, #1 + bne wait_scpll + +scpll_ok: + ldr r1, [r2] + bic r1, r1, #(0xf<<12) /* clear mahb */ + orr r1, r1, #(1<<12) /* mahb=1 hclk,pclk1=armclk/2 */ + bic r1, r1, #(0x7) /* clear msc */ + str r1, [r2] + bic r1, r1, #(1<<16) /* switch to SC */ + str r1, [r2] + + /* per2: etnrefclk 50MHz */ + ldr r2, =REG_CGU_PER2CON + ldr r1, =PER2CON /* reset value */ + str r1, [r2] + mov r1, #0 + orr r1, r1, #(15<<9) + orr r1, r1, #(63<<3) + orr r1, r1, #(3) + orr r1, r1, #(1<<19) + bic r1, r1, #(1<<21) + str r1, [r2] + orr r1, r1, #(1<<16) /* enable pll_per2 */ + str r1, [r2] + mov r0, #(0x29<<8) /* wait max 250us */ +wait_per2pll: /* wait for pll lock */ + ldr r1, [r2] + ands r1, r1, #(1<<17) + bne per2pll_ok + subs r0, r0, #1 + bne wait_per2pll +per2pll_ok: + ldr r1, [r2] + orr r1, r1, #(1<<23) + orr r1, r1, #(1<<13) + str r1, [r2] + + ldr r2, =REG_CGU_PER2BWCON /* set default value */ + ldr r1, =PER2BWCON + str r1, [r2] + + +#endif + /* setup memory controller */ + b memsetup /* jump to the next assembler code */ + /* board/firetux/memsetup.S */ + diff --git a/board/dspg/firetux/memsetup.S b/board/dspg/firetux/memsetup.S new file mode 100644 index 0000000..79a9180 --- /dev/null +++ b/board/dspg/firetux/memsetup.S @@ -0,0 +1,381 @@ +/* + * Memory setup for PNX8181 + * + * (C) Copyright 2007-2009, emlix GmbH, Germany + * Juergen Schoew, js@emlix.com + * + * (C) Copyright 2008, DSPG Technologies GmbH, Germany + * + * 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 + */ + +/* + * Memory setup + * - the reset defaults are assumed sufficient + */ + +#include <config.h> +#include <version.h> + +#ifndef CONFIG_NANDFLASH /* with nandflash we have to skip memconfig */ + +/* SDI */ +#define REG_SDI_CFG1 0xC1200000 /* SDRAM controller configuration 1 */ +#define REG_SDI_PWR_CTL 0xC1200004 /* Power savings parameters */ +#define REG_SDI_RFRSH1 0xC1200008 /* Refresh parameters 1 */ +#define REG_SDI_RFRSH2 0xC120000C /* Refresh parameters 2 */ +#define REG_SDI_TIM1 0xC1200010 /* Timings parameters 1 */ +#define REG_SDI_TIM2 0xC1200014 /* Timings parameters 2 */ +#define REG_SDI_MODE 0xC1200018 /* Mode */ +#define REG_SDI_EXT_MOD 0xC120001C /* Extended mode */ +#define REG_SDI_CFG2 0xC1200020 /* SDRAM controller configuration 2 */ +#define REG_SDI_SCHED0 0xC1200100 /* Data port #0 scheduler */ +#define REG_SDI_SCHED1 0xC1200104 /* Data port #1 scheduler */ +#define REG_SDI_SCHED2 0xC1200108 /* Data port #2 scheduler */ +#define REG_SDI_WTAG0 0xC1200300 /* Data port #0 write tag enable */ +#define REG_SDI_WTAG1 0xC1200304 /* Data port #1 write tag enable */ +#define REG_SDI_WTAG2 0xC1200308 /* Data port #2 write tag enable */ +#define REG_SDI_TAM 0xC1200310 /* Tag address mask */ +#define REG_SDI_SW_CTRL 0xC1200400 /* Software control register */ +#define REG_SDI_STAT 0xC1200800 /* Status register */ +#define REG_SDI_IP_ID 0xC1200FFC /* IP identification */ + +/* table offsets */ +#define SDI_CFG1 0x00 +#define SDI_CFG2 0x04 +#define SDI_PWR_CTRL 0x08 +#define SDI_RFRSH1 0x0c +#define SDI_RFRSH2 0x10 +#define SDI_TIM1 0x14 +#define SDI_TIM2 0x18 +#define SDI_MODE 0x1c +#define SDI_EXT_MODE 0x20 +#define SDI_SCHED0 0x24 +#define SDI_SCHED1 0x28 +#define SDI_SCHED2 0x2c +#define SDI_WTAG0 0x30 +#define SDI_WTAG1 0x34 +#define SDI_WTAG2 0x38 +#define SDI_TAM 0x3c + +#define REG_CGU_SCCON 0xC2200004 /* SC Controller for hclk */ + +/* table for memory settings */ + .align 4 +memsetting_EZ_MCP_PNX8181_89MHZ: +/* + * settings for Samsung K4M64163PK + * 8MB @hclk=89.86MHz + */ + .long 0x22301 /* define SDI_CFG1 */ + .long 0x100 /* define SDI_CFG2 */ + .long 0x1000000 /* define SDI_PWR_CTRL */ + .long 0x579 /* define SDI_RFRSH1 */ + .long 0x0 /* define SDI_RFRSH2 */ + .long 0x1131242 /* define SDI_TIM1 */ + .long 0xb08 /* define SDI_TIM2 */ + .long 0x23 /* define SDI_MODE */ + .long 0x18 /* define SDI_EXT_MODE */ + .long 0x80000121 /* define SDI_SCHED0 */ + .long 0xffff0100 /* define SDI_SCHED1 */ + .long 0x00030131 /* define SDI_SCHED2 */ + .long 0xf /* define SDI_WTAG0 */ + .long 0xf /* define SDI_WTAG1 */ + .long 0xf /* define SDI_WTAG2 */ + .long 0x0 /* define SDI_TAM */ + + .align 4 +memsetting_EZ_MCP_PNX8181_103MHZ: +/* + * settings for Samsung K4M64163PK + * 8MB @hclk=103.68MHz + */ + .long 0x22301 /* define SDI_CFG1 */ + .long 0x100 /* define SDI_CFG2 */ + .long 0x1000000 /* define SDI_PWR_CTRL */ + .long 0x651 /* define SDI_RFRSH1 */ + .long 0x0 /* define SDI_RFRSH2 */ + .long 0x1131262 /* define SDI_TIM1 */ + .long 0xc0a /* define SDI_TIM2 */ + .long 0x23 /* define SDI_MODE */ + .long 0x18 /* define SDI_EXT_MODE */ + .long 0x80000121 /* define SDI_SCHED0 */ + .long 0xffff0100 /* define SDI_SCHED1 */ + .long 0x00030131 /* define SDI_SCHED2 */ + .long 0xf /* define SDI_WTAG0 */ + .long 0xf /* define SDI_WTAG1 */ + .long 0xf /* define SDI_WTAG2 */ + .long 0x0 /* define SDI_TAM */ + + .align 4 +memsetting_VEGA_PNX8181_BASESTATION_III_a: +/* + * settings for Micron MT48LC8M16A2 + * 16MB @hclk=103.68MHz + */ + .long 0x22311 /* define SDI_CFG1 */ + .long 0x100 /* define SDI_CFG2 */ + .long 0x1000000 /* define SDI_PWR_CTRL */ + .long 0x651 /* define SDI_RFRSH1 */ + .long 0x0 /* define SDI_RFRSH2 */ + .long 0x1131262 /* define SDI_TIM1 */ + .long 0xc0a /* define SDI_TIM2 */ + .long 0x23 /* define SDI_MODE */ + .long 0x18 /* define SDI_EXT_MODE */ + .long 0x80000121 /* define SDI_SCHED0 */ + .long 0xffff0100 /* define SDI_SCHED1 */ + .long 0x00030131 /* define SDI_SCHED2 */ + .long 0xf /* define SDI_WTAG0 */ + .long 0xf /* define SDI_WTAG1 */ + .long 0xf /* define SDI_WTAG2 */ + .long 0x0 /* define SDI_TAM */ + + .align 4 +memsetting_VEGA_PNX8181_BASESTATION_III_b: +/* + * settings for Micron MT48LC16M16A2 + * 32MB @hclk=103.68MHz + */ + .long 0x22411 /* define SDI_CFG1 */ + .long 0x100 /* define SDI_CFG2 */ + .long 0x1000000 /* define SDI_PWR_CTRL */ + .long 0x651 /* define SDI_RFRSH1 */ + .long 0x0 /* define SDI_RFRSH2 */ + .long 0x1131262 /* define SDI_TIM1 */ + .long 0xc0a /* define SDI_TIM2 */ + .long 0x23 /* define SDI_MODE */ + .long 0x18 /* define SDI_EXT_MODE */ + .long 0x80000121 /* define SDI_SCHED0 */ + .long 0xffff0100 /* define SDI_SCHED1 */ + .long 0x00030131 /* define SDI_SCHED2 */ + .long 0xf /* define SDI_WTAG0 */ + .long 0xf /* define SDI_WTAG1 */ + .long 0xf /* define SDI_WTAG2 */ + .long 0x0 /* define SDI_TAM */ + +#endif + +.globl memsetup +memsetup: +/* with nandflash we have to skip memconfig */ +#if !defined(CONFIG_NANDFLASH) && !defined(CONFIG_SKIP_RELOCATE_UBOOT) + /* check 32MB of Vega III-b / III-c */ + adr r3, memsetting_VEGA_PNX8181_BASESTATION_III_b + mov r4, lr + bl do_memsetup + mov lr, r4 +#endif + mov r3, #(32<<20) /* check for 32MB */ +/* with nandflash we have to skip memconfig */ +#if !defined(CONFIG_NANDFLASH) && !defined(CONFIG_SKIP_RELOCATE_UBOOT) + bl memtest + mov lr, r4 + cmp r3, #0 + bne 2f + + /* check 16MB of Vega III-a */ + adr r3, memsetting_VEGA_PNX8181_BASESTATION_III_a + mov r4, lr + bl do_memsetup + mov lr, r4 + mov r3, #(16<<20) /* check for 16MB */ + bl memtest + mov lr, r4 + cmp r3, #0 + bne 2f + + /* fallback, check for 8MB of EZ_MCP */ + adr r3, memsetting_EZ_MCP_PNX8181_103MHZ + ldr r1, =REG_CGU_SCCON + ldr r0, [r1] + mov r1, #(0x7f<<3) + ands r0, r0, r1 + cmp r0, #(14<<3) /* check for hclk=103 */ + bge 1f + /* OK, we do not have 103MHz, so chosse other setting */ + adr r3, memsetting_EZ_MCP_PNX8181_89MHZ +1: + mov r4, lr + bl do_memsetup + + mov r1, #0x01 /* precharge all */ + ldr r2, =REG_SDI_SW_CTRL + str r1, [r2] + mov r1, #0x09 /* load extended mode register */ + ldr r2, =REG_SDI_SW_CTRL + str r1, [r2] + + mov lr, r4 + mov r3, #(8<<20) /* check for 8MB */ + bl memtest + mov lr, r4 + cmp r3, #0 + bne 2f + nop + nop +2: /* setup done */ +#endif + mov r4, r3 /* r3 holds the memory size */ + /* save a copy in r4 */ + b firetux_relocate_code /* jump to the next assembler code */ + /* board/firetux/relocate.S */ + + + +/* Fill the sdram controller with the values from the table */ + +do_memsetup: +/* with nandflash we have to skip memconfig */ +#if !defined(CONFIG_NANDFLASH) && !defined(CONFIG_SKIP_RELOCATE_UBOOT) + /* + * CGU setup + * pin multiplexing + * SDRAM config + */ + mov r1, #0x00 /* NOP */ + ldr r2, =REG_SDI_SW_CTRL + str r1, [r2] + + mov r0, #(0x50<<8) /* wait 200us */ + /* + * roughly calculated 208MHz, + * 40960ticks, + * 2 instructions per loop + */ +1: + subs r0, r0, #1 + bne 1b + + mov r1, #0x07 /* exit power down */ + ldr r2, =REG_SDI_SW_CTRL + str r1, [r2] + + mov r0, #(0x50<<8) /* wait 200us */ +1: + subs r0, r0, #1 + bne 1b + + ldr r2, =REG_SDI_CFG1 + ldr r1, [r3, #SDI_CFG1] + str r1, [r2] + ldr r2, =REG_SDI_CFG2 + ldr r1, [r3, #SDI_CFG2] + str r1, [r2] + ldr r2, =REG_SDI_PWR_CTL + ldr r1, [r3, #SDI_PWR_CTRL] + str r1, [r2] + ldr r2, =REG_SDI_RFRSH1 + ldr r1, [r3, #SDI_RFRSH1] + str r1, [r2] + mov r0, #(0x50<<8) /* wait 200us */ +1: + subs r0, r0, #1 + bne 1b + orr r1, r1, #(1<<24) /* enable auto refresh generation */ + str r1, [r2] + ldr r2, =REG_SDI_MODE + ldr r1, [r3, #SDI_MODE] + str r1, [r2] + ldr r2, =REG_SDI_EXT_MOD + ldr r1, [r3, #SDI_EXT_MODE] + str r1, [r2] + ldr r2, =REG_SDI_RFRSH2 + ldr r1, [r3, #SDI_RFRSH2] + str r1, [r2] + ldr r2, =REG_SDI_TIM1 + ldr r1, [r3, #SDI_TIM1] + str r1, [r2] + ldr r2, =REG_SDI_TIM2 + ldr r1, [r3, #SDI_TIM2] + str r1, [r2] + ldr r2, =REG_SDI_SCHED0 + ldr r1, [r3, #SDI_SCHED0] + str r1, [r2] + ldr r2, =REG_SDI_SCHED1 + ldr r1, [r3, #SDI_SCHED1] + str r1, [r2] + ldr r2, =REG_SDI_SCHED2 + ldr r1, [r3, #SDI_SCHED2] + str r1, [r2] + ldr r2, =REG_SDI_WTAG0 + ldr r1, [r3, #SDI_WTAG0] + str r1, [r2] + ldr r2, =REG_SDI_WTAG1 + ldr r1, [r3, #SDI_WTAG1] + str r1, [r2] + ldr r2, =REG_SDI_WTAG2 + ldr r1, [r3, #SDI_WTAG2] + str r1, [r2] + ldr r2, =REG_SDI_TAM + ldr r1, [r3, #SDI_TAM] + str r1, [r2] + + /* send power-up info */ + mov r1, #0x01 /* precharge all */ + ldr r2, =REG_SDI_SW_CTRL + str r1, [r2] + + mov r0, #8 /* 8 times */ +1: + mov r1, #0x03 /* auto refresh */ + ldr r2, =REG_SDI_SW_CTRL + str r1, [r2] + subs r0, r0, #1 + bne 1b + + mov r1, #0x08 /* load mode register */ + ldr r2, =REG_SDI_SW_CTRL + str r1, [r2] + mov pc,lr + + +/* check if the memory is working */ + +memtest: + mov r1, r3 +1: + ldr r2, =CONFIG_SYS_SDRAM_BASE + add r2, r2, r1 + sub r2, r2, #4 + str r1, [r2] + mov r1, r1, LSR #1 + cmp r1, #4 + bgt 1b + mov r1, r3 +1: + ldr r2, =CONFIG_SYS_SDRAM_BASE + add r2, r2, r1 + sub r2, r2, #4 + ldr r0, [r2] + cmp r0, r1 + bne 2f + mov r1, r1, LSR #1 + cmp r1, #4 + bgt 1b + mov pc, lr +2: + mov r3, #0 + mov pc, lr + + nop + nop + nop + nop + +#endif diff --git a/board/dspg/firetux/nand.c b/board/dspg/firetux/nand.c new file mode 100644 index 0000000..f354252 --- /dev/null +++ b/board/dspg/firetux/nand.c @@ -0,0 +1,68 @@ +/* + * pnx8181 nandflash driver + * + * (C) Copyright 2008-2009, emlix GmbH, Germany + * Juergen Schoew js@emlix.com + * + * (C) Copyright 2008, DSPG Technologies GmbH, Germany + * + * 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 <nand.h> +#include <asm/io.h> + +static void firetux_nand_hwcontrol(struct mtd_info *mtd, int dat, + unsigned int ctrl) +{ + struct nand_chip *chip = mtd->priv; + void *IO_ADDR_W = chip->IO_ADDR_W; + + if (ctrl & NAND_CLE) + IO_ADDR_W += CONFIG_SYS_NAND_CLE_ADDR; + + if (ctrl & NAND_ALE) + IO_ADDR_W += CONFIG_SYS_NAND_ALE_ADDR; + + if (dat != NAND_CMD_NONE) { + if (chip->options & NAND_BUSWIDTH_16) + writew((unsigned short)dat, IO_ADDR_W); + else + writeb((unsigned char)dat, IO_ADDR_W); + } +} + + +static int firetux_nand_readybusy(struct mtd_info *mtd) +{ + return (readl((void *)CONFIG_SYS_NAND_RB_PORT) + >> CONFIG_SYS_NAND_RB_BIT) & 1; +} + + +int board_nand_init(struct nand_chip *nand) +{ + nand->cmd_ctrl = firetux_nand_hwcontrol; + nand->dev_ready = firetux_nand_readybusy; + nand->chip_delay = 20; + nand->ecc.mode = NAND_ECC_SOFT; + nand->options = NAND_USE_FLASH_BBT; + return 0; +} diff --git a/board/dspg/firetux/relocate.S b/board/dspg/firetux/relocate.S new file mode 100644 index 0000000..86fd6e0 --- /dev/null +++ b/board/dspg/firetux/relocate.S @@ -0,0 +1,252 @@ +/* + * firetux board specific setup + * based on cpu/arm926ejs/start.S + * modified to relocate the u-boot code at end of RAM + * + * (C) Copyright 2007-2009, emlix GmbH, Germany + * Juergen Schoew, js@emlix.com + * + * (C) Copyright 2008, DSPG Technologies GmbH, Germany + * (C) Copyright 2007, NXP Semiconductors Germany GmbH + * Matthias Wenzel, nxp@mazzoo.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 <config.h> +#include <version.h> + +/* external labels needed for calculation */ +.extern _start +.extern _armboot_start +.extern _bss_start +.extern _bss_end + +/* these are defined in the board-specific linker script */ +.global _relocation_table +_relocation_table: + .word __relocation_table +.global _got +_got: + .word _GLOBAL_OFFSET_TABLE_ + +/* local labels */ +_start_armboot: + .word start_armboot +__start: + .word _start +_armbootstart: + .word _armboot_start +_bssstart: + .word _bss_start +_bssend: + .word _bss_end +_rel_offset: + .word . + + +.global firetux_relocate_code +firetux_relocate_code: + +/* input from memsetup: + r3 and r4 hold the size of the installed memory */ + + +/* with nandflash we skipped the lowlevelinit and memsetup */ +/* but we have to provide the memory settings here */ +#if defined(CONFIG_NANDFLASH) || defined(CONFIG_SKIP_RELOCATE_UBOOT) + +/* read sdram settings from the controller */ +#define REG_SDI_CFG1 0xC1200000 /* SDRAM controller configuration 1 */ + ldr r1, =REG_SDI_CFG1 + ldr r2, [r1] + ands r0, r2, #0x3 /* dram width 8, 16, 32, 64bit */ + lsr r2, r2, #4 + ands r4, r2, #0x3 /* columns 8, 9, 10, 11 */ + add r4, r4, #8 + add r0, r0, r4 + lsr r2, r2, #4 + ands r4, r2, #0x7 /* rows 9 .. 16 */ + add r4, r4, #9 + add r0, r0, r4 + lsr r2, r2, #4 + ands r4, r2, #0x3 /* nr banks 1, 2, 4 */ + add r0, r0, r4 + mov r2, #1 + lsl r3, r2, r0 + mov r4, r3 /* save size in r3 and r4 */ +#endif + +/* calculate address offset */ + adr r0, _rel_offset + ldr r1, =_rel_offset + sub r2, r0, r1 + mov r12, r2 /* offset to _start saved in r12 */ + +/* if running from sdram, skip relocating */ +#ifndef CONFIG_SKIP_RELOCATE_UBOOT + ldr r0, =_start /* original start */ + add r0, r0, r12 /* r0 <- current position of code */ + mov r2, r0 /* save in r2 */ + mov r1, #PHYS_SDRAM_1 /* test if we run from flash or RAM */ + and r0, r0, #0xf0000000 /* check if segment addr match */ + and r1, r1, #0xf0000000 /* check if segment addr match */ +#ifndef CONFIG_NANDFLASH /* if coming from NAND we do */ + /* relocate, because loader copied */ + /* us into middle of RAM */ + cmp r0, r1 /* don't reloc when already in ram */ + bne firetux_relocate + mov r4, r2 /* if not relocated, start of uboot */ + /* need to be in r4 for stack setup */ + b firetux_stack_setup +#endif + +/* relocation code */ +firetux_relocate: /* relocate U-Boot to RAM */ + ldr r3, _bssend /* address of label */ + ldr r3, [r3, r12] /* address of _bss_end */ + ldr r2, __start /* address of _start */ + sub r3, r3, r2 /* space needed for uboot with bss */ + mov r2, #PHYS_SDRAM_1 /* ram start */ + add r2, r2, r4 /* add ram_size (memsetup.S) */ + sub r2, r2, #4 /* adjust off by one opcode */ + sub r2, r2, r3 /* sub size of uboot */ + mvn r1, #0xff /* load 0xffffff00 */ + and r1, r2, r1 /* clear last 8bit to get alignment */ + /* r1 <- destination address */ + ldr r0, __start + add r0, r0, r12 /* r0 <- current position of code */ + /* source address */ + mov r4, r1 /* save destination addr */ + ldr r2, __start /* address of _start */ + ldr r3, _bssstart /* address of label */ + ldr r3, [r3, r12] /* address of _bss_start */ + sub r2, r3, r2 /* r2 <- size of armboot without bss */ + add r2, r0, r2 /* r2 <- end of source address */ + +firetux_copy_loop: + ldmia r0!, {r5-r10} /* copy from source address [r0] */ + stmia r1!, {r5-r10} /* copy to target address [r1] */ + cmp r0, r2 /* until source end addreee [r2] */ + ble firetux_copy_loop + b firetux_stack_setup +#endif /* CONFIG_SKIP_RELOCATE_UBOOT */ + ldr r4, =_start /* if not relocated, start of uboot */ + add r0, r0, r12 /* r0 <- current position of code */ + /* need to be in r4 for stack setup */ + + /* Set up the stack */ +firetux_stack_setup: + mov r0, r4 /* relocated uboot */ + sub r0, r0, #CONFIG_SYS_MALLOC_LEN /* malloc area */ + sub r0, r0, #CONFIG_SYS_GBL_DATA_SIZE /* bdinfo */ +#ifdef CONFIG_USE_IRQ + sub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ) +#endif + sub sp, r0, #12 /* leave 3 words for abort-stack */ + +firetux_clear_bss: + mov r0, r4 /* start address of relocated uboot */ + ldr r2, __start /* address of _start */ + ldr r3, _bssstart /* address of label */ + ldr r3, [r3, r12] /* address of _bss_start */ + sub r2, r3, r2 /* offset from start */ + add r0, r0, r2 /* new bss_start in ram */ + /* r0 <- new _bss_start */ + ldr r1, _bssstart /* address of label */ + ldr r1, [r1, r12] /* address of _bss_start */ + ldr r2, _bssend /* address of label */ + ldr r2, [r2, r12] /* address of _bss_end */ + sub r1, r2, r1 /* calc length of bss */ + add r1, r0, r1 /* r1 <- new bss_end in ram */ + mov r2, #0x00000000 /* clear */ + +firetux_clbss_l: + str r2, [r0] /* clear loop... */ + add r0, r0, #4 + cmp r0, r1 + ble firetux_clbss_l + +#ifndef CONFIG_SKIP_RELOCATE_UBOOT +relocate_variables: + /* we need to relocate the _armboot_start, _bss_start and _bss_end + * variables to the new u-boot location, which is needed for + * lib_arm/board.c for the caculation of the memory locations for + * board setup */ + ldr r0, __start /* start of old code */ + sub r3, r4, r0 /* calculate offset between old/new */ + /* r3 <- value to add */ + ldr r0, _armbootstart /* start of old code */ + ldr r2, [r0, r12] /* read value */ + add r2, r2, r3 /* add offset */ + str r2, [r0, r3] /* store new value */ + ldr r0, _bssstart /* get old address */ + ldr r2, [r0, r12] /* read value */ + add r2, r2, r3 /* add offset */ + str r2, [r0, r3] /* store new value */ + ldr r0, _bssend /* get old address */ + ldr r2, [r0, r12] /* read value */ + add r2, r2, r3 /* add offset */ + str r2, [r0, r3] /* store new value */ + + /* OK, we need to fix the whole GLOBAL_OFFSET_TABLE till bss section */ +fix_global_offset_table: + ldr r0, __start /* get old starting point */ + mov r3, r0 /* r3 <- save for compare lower limit */ + sub r0, r4, r0 /* r0 <- calculate offset to new start*/ + ldr r1, _relocation_table /* get old table address */ + add r1, r1, r0 /* r1 <- calculate new table address */ + ldr r2, _bssend /* get label address */ + ldr r2, [r2, r12] /* get old table end */ + mov r5, r2 /* r5 <- save for compare upper limit */ + sub r2, r2, #4 + add r2, r2, r0 /* r2 <- calculate new end address */ + +2: ldr r6, [r1] /* load table value */ + cmp r6, r3 /* check for lower value */ + blt 1f + cmp r6, r5 /* check for upper limit */ + bgt 1f + add r6, r6, r0 + str r6, [r1] +1: add r1, r1, #4 /* increase address */ + cmp r1, r2 /* compare with end address */ + ble 2b +#endif /* CONFIG_SKIP_RELOCATE_UBOOT */ + + /* calculate addr for start_armboot, because jump maybe more than 32MB*/ + ldr r0, __start /* start of code */ + ldr r1, _start_armboot /* start of c-function */ + sub r0, r1, r0 /* offset from beginning */ + add r0, r0, r4 /* calculate new addr in ram */ + mov lr, r0 /* save start addr in lr */ + + /* set PIC offset register (sl/r10) */ + ldr r1, __start + add r1, r1, r12 /* addr of original u-boot */ + adr r2, _got /* addr of _got label */ + sub r1, r2, r1 /* offset from _start */ + + ldr sl, _got /* get got offset from _got */ + add sl, sl, r1 /* add offset of _got */ + add sl, sl, r4 /* add start + offset for new got */ + + mov pc, r0 /* jump into C code start_armboot */ + /* lib_arm/board.c */ diff --git a/board/dspg/firetux/u-boot.lds b/board/dspg/firetux/u-boot.lds new file mode 100644 index 0000000..a57f091 --- /dev/null +++ b/board/dspg/firetux/u-boot.lds @@ -0,0 +1,57 @@ +/* + * (C) Copyright 2007-2009, emlix GmbH, Germany + * Juergen Schoew js@emlix.com + * + * (C) Copyright 2008, DSPG Technologies GmbH, Germany + * (C) Copyright 2007, NXP Semiconductors Germany GmbH + * Matthias Wenzel, nxp@mazzoo.de + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ + . = 0x00000000; + . = ALIGN(4); + .text : + { + cpu/arm926ejs/start.o (.text) + *(.text) + } + .rodata : { *(.rodata) } + . = ALIGN(4); + .data : { *(.data) + __relocation_table = .; + } + . = ALIGN(4); + .got : { *(.got) } + + . = .; + __u_boot_cmd_start = .; + .u_boot_cmd : { *(.u_boot_cmd) } + __u_boot_cmd_end = .; + + . = ALIGN(4); + __bss_start = .; + .bss (NOLOAD) : { *(.bss) } + _end = .; +} diff --git a/include/configs/firetux.h b/include/configs/firetux.h new file mode 100644 index 0000000..36db126 --- /dev/null +++ b/include/configs/firetux.h @@ -0,0 +1,454 @@ +/* + * firetux board configuration + * + * (C) Copyright 2007-2009 emlix GmbH + * Juergen Schoew js@emlix.com + * + * (C) Copyright 2008, DSPG Technologies GmbH, Germany + * (C) Copyright 2007, NXP Semiconductors Germany GmbH + * Matthias Wenzel, nxp@mazzoo.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 + */ + +#ifndef __CONFIG_H +#define __CONFIG_H + +#define CONFIG_FIRETUX 1 +#define CONFIG_ARCH_FIRETUX 1 +#define CONFIG_ARM926EJS 1 +#define CONFIG_IP3912_ETHER 1 +#define CONFIG_IP3912_ETN1_BASE 0xC1600000 +#define CONFIG_IP3912_ETN2_BASE 0xC1700000 + +/* we can have nand _or_ nor flash */ +/* #define CONFIG_NANDFLASH 1 */ + +/* #define CONFIG_SHOW_BOOT_PROGRESS 1 */ +#define CONFIG_DISPLAY_CPUINFO 1 +#define CONFIG_DISPLAY_BOARDINFO 1 + +#define CONFIG_BOOT_LINUX 1 + +/* #define CONFIG_USE_IRQ 1 */ + +/* #define CONFIG_SKIP_LOWLEVEL_INIT 1 */ +/* #define CONFIG_SKIP_RELOCATE_UBOOT 1 */ + +#define CONFIG_SYS_ARM_DEBUG_MEM 1 + +/* MWe has a buggy piece of silicon */ +/* #define CONFIG_FIRETUX_HAS_CGU_SCCON_MSC_BUG 1 */ + +/* + * High Level Configuration Options + * (easy to change) + */ +/* Timer 1 is clocked at 1Mhz */ +#define CONFIG_SYS_HZ 1000000 + +/* enable passing of ATAGs */ +#define CONFIG_CMDLINE_TAG 1 +#define CONFIG_SETUP_MEMORY_TAGS 1 +/* call misc_init_r during start up */ +#define CONFIG_MISC_INIT_R 1 +#define CONFIG_INITRD_TAG 1 +/* mount rootfs read-only */ +#define CONFIG_ROOT_RDONLY 1 +#define CONFIG_STATUS_LED 1 +#define CONFIG_BOARD_SPECIFIC_LED 1 +#define STATUS_LED_BIT 1 +#define STATUS_LED_PERIOD (CONFIG_SYS_HZ / 2) +#define STATUS_LED_STATE STATUS_LED_BLINKING +#define STATUS_LED_ACTIVE 1 +#define STATUS_LED_BOOT 1 + +/* BZIP2 needs 4MB Malloc Size */ +/* #define CONFIG_BZIP2 1 */ +#define CONFIG_LZMA 1 + +/* + * ethernet + */ + +/* #define ET_DEBUG 1 */ +#define CONFIG_NET_RETRY_COUNT 7 +#define CONFIG_NET_MULTI 1 +#define CONFIG_MII 1 +/* #define CONFIG_DISCOVER_PHY 1 */ + +/* allow to overwrite serial and ethaddr */ +#define CONFIG_ENV_OVERWRITE 1 +#ifdef CONFIG_NANDFLASH +#define CONFIG_EXTRA_ENV_SETTINGS \ + "ethaddr=00:60:37:C0:FF:EE\0" \ + "netmask=255.255.255.0\0" \ + "ipaddr=192.168.3.183\0" \ + "serverip=192.168.3.60\0" \ + "bootfile=firetux.kernel\0" \ + "bootcmd=run bootcmd1\0" \ + "bootcmd1=nboot 0x20200000 0 0x80000 " \ + "&& bootm 0x20200000\0" \ + "bootcmd2=tftpboot 0x20200000 firetux.kernel " \ + "&& bootm 0x20200000\0" \ + "ethact=ETN1\0" \ + "phymode=auto\0" \ + "mtdids=nor0=firetux\0" \ + "mtdparts=mtdparts=firetux:" \ + "384k(U-Boot)," \ + "128k(U-Bootenv)," \ + "1536k(kernel)," \ + "1M(config)," \ + "2M(data)," \ + "-(rootfs)\0" \ + "partition=nor0,5\0" \ + "unlock=yes\0" \ + "update.eeprom=echo Update eeprom " \ + "&& tftpboot 0x20000000 firetux.eeprom " \ + "&& eeprom write 0x20000000 0x0 ${filesize}\0" \ + "update.uboot=echo Update u-boot " \ + "&& tftpboot 0x20000000 firetux.nandboot.flash " \ + "&& nand erase 0x0 0x03ffff " \ + "&& nand write.jffs2 0x20000000 0x0 ${filesize}\0" \ + "update.kernel=echo Update kernel " \ + "&& tftpboot 0x20000000 firetux.kernel " \ + "&& nand erase 0x80000 0x17ffff " \ + "&& nand write.jffs2 20000000 0x80000 ${filesize}\0" \ + "update.config=echo Update config " \ + "&& tftpboot 0x20000000 firetux.config " \ + "&& nand erase clean 0x200000 0xfffff " \ + "&& nand write.jffs2 20000000 0x200000 ${filesize}\0" \ + "update.data=echo Update data " \ + "&& tftpboot 0x20000000 firetux.data " \ + "&& nand erase clean 0x300000 0x1fffff " \ + "&& nand write.jffs2 20000000 0x300000 ${filesize}\0" \ + "update.rootfs=echo Update rootfs " \ + "&& tftpboot 0x20000000 firetux.targetfs " \ + "&& nand erase clean 0x500000 " \ + "&& nand write.jffs2 20000000 0x500000 ${filesize}\0" \ + "update.user=run update.rootfs " \ + "&& run update.data " \ + "&& run update.config\0" \ + "update.linux=run update.kernel " \ + "&& run update.user\0" \ + "update.all=run update.uboot " \ + "&& run update.linux\0" \ + "" +#else +#define CONFIG_EXTRA_ENV_SETTINGS \ + "ethaddr=00:60:37:C0:FF:EE\0" \ + "netmask=255.255.255.0\0" \ + "ipaddr=192.168.3.183\0" \ + "serverip=192.168.3.60\0" \ + "bootfile=firetux.kernel\0" \ + "bootcmd=run bootcmd1\0" \ + "bootcmd1=bootm 0x80080000\0" \ + "bootcmd2=tftp 20200000 firetux.kernel " \ + "&& bootm 20200000\0" \ + "ethact=ETN1\0" \ + "phymode=auto\0" \ + "mtdids=nor0=firetux\0" \ + "mtdparts=mtdparts=firetux:" \ + "384k(U-Boot)," \ + "128k(U-Bootenv)," \ + "1536k(kernel)," \ + "1M(config)," \ + "2M(data)," \ + "-(rootfs)\0" \ + "partition=nor0,5\0" \ + "unlock=yes\0" \ + "update.uboot=echo Update u-boot " \ + "&& tftpboot 0x20000000 firetux.uboot " \ + "&& protect off 0x80000000 0x8005ffff " \ + "&& erase 0x80000000 0x8005ffff " \ + "&& cp.b 0x20000000 0x80000000 ${filesize}\0" \ + "update.kernel=echo Update kernel " \ + "&& tftpboot 0x20000000 firetux.kernel " \ + "&& erase 0x80080000 0x801fffff " \ + "&& cp.b 20000000 0x80080000 ${filesize}\0" \ + "update.config=echo Update config " \ + "&& tftpboot 0x20000000 firetux.config " \ + "&& erase 0x80200000 0x802fffff " \ + "&& cp.b 20000000 0x80200000 ${filesize}\0" \ + "update.data=echo Update data " \ + "&& tftpboot 0x20000000 firetux.data " \ + "&& erase 0x80300000 0x804fffff " \ + "&& cp.b 20000000 0x80300000 ${filesize}\0" \ + "update.rootfs=echo Update rootfs " \ + "&& tftpboot 0x20000000 firetux.targetfs " \ + "&& erase 0x80500000 0x81ffffff " \ + "&& cp.b 20000000 0x80500000 ${filesize}\0" \ + "update.user=run update.rootfs " \ + "&& run update.data " \ + "&& run update.config\0" \ + "update.linux=run update.kernel " \ + "&& run update.user\0" \ + "update.all=run update.uboot " \ + "&& run update.linux\0" \ + "" +#endif + /* better not set "gatewayip" */ + +/* #define CONFIG_SYS_ETHER_FAIR_SCHEDULE 1 */ /* Use fair or eth schedule */ +#define CONFIG_SYS_ETN_RX_DESCRIPTOR_NUMBER 16 +#define CONFIG_SYS_ETN_TX_DESCRIPTOR_NUMBER 16 + +#define MAX_ETH_FRAME_SIZE 1536 + +#define CONFIG_ENV_SIZE 0x20000 /* 128KB */ + +/* Size of malloc() pool */ +#define CONFIG_SYS_MALLOC_LEN_ETN (CONFIG_SYS_ETN_RX_DESCRIPTOR_NUMBER \ + * MAX_ETH_FRAME_SIZE) +#define CONFIG_SYS_MALLOC_LEN (4*128*1024 + CONFIG_ENV_SIZE + \ + CONFIG_SYS_MALLOC_LEN_ETN) +/* min 4MB for bzip2 */ +/* #define CONFIG_SYS_MALLOC_LEN (4 * 1024 * 1024)*/ +/* #define CONFIG_SYS_MALLOC_LEN 0x70000 */ + +/* size in bytes reserved for initial data */ +#define CONFIG_SYS_GBL_DATA_SIZE 128 + + +/* + * Hardware drivers + */ + +/* + * NS16550 Configuration + */ +#define CONFIG_SYS_NS16550 1 +#define CONFIG_SYS_NS16550_SERIAL 1 +#define CONFIG_CONS_INDEX 2 +#define CONFIG_BAUDRATE 115200 +#define CONFIG_SYS_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200 } +#define CONFIG_SYS_SERIAL0 0xC2004000 +#define CONFIG_SYS_SERIAL1 0xC2005000 +#define CONFIG_SYS_NS16550_COM1 CONFIG_SYS_SERIAL0 +#define CONFIG_SYS_NS16550_COM2 CONFIG_SYS_SERIAL1 +#define CONFIG_SYS_NS16550_REG_SIZE 4 +/* fclk=27.648==clk26m, uclk=14.756 */ +#define CONFIG_SYS_NS16550_CLK 14745600 + +#define CONFIG_CRC32_VERIFY 1 + +#define CONFIG_CMDLINE_EDITING 1 +#define CONFIG_AUTO_COMPLETE 1 +#define CONFIG_MX_CYCLIC 1 + + + +/* + * command line + */ +#include <config_cmd_default.h> +#define CONFIG_CMD_IMI +#define CONFIG_CMD_XIMG +#define CONFIG_CMD_BDI +#define CONFIG_CMD_MEMORY +#define CONFIG_CMD_ENV +#define CONFIG_CMD_CACHE +#define CONFIG_CMD_RUN +#define CONFIG_CMD_MISC +#define CONFIG_CMD_LOADB +#define CONFIG_CMD_LOADS +#define CONFIG_CMD_ELF +#define CONFIG_CMD_CONSOLE +#define CONFIG_CMD_AUTOSCRIPT +#define CONFIG_CMD_ASKENV +#define CONFIG_CMD_NET +#define CONFIG_CMD_NFS +#define CONFIG_CMD_PING +#define CONFIG_CMD_MII +#define CONFIG_CMD_ECHO +#define CONFIG_CMD_BOOTD +#define CONFIG_CMD_DHCP +#define CONFIG_CMD_ITEST +#define CONFIG_CMD_I2C +#define CONFIG_CMD_EEPROM +#ifdef CONFIG_NANDFLASH +#define CONFIG_CMD_NAND +#undef CONFIG_CMD_IMLS +#undef CONFIG_CMD_FLASH +#else +#define CONFIG_CMD_IMLS +#define CONFIG_CMD_FLASH +#define CONFIG_CMD_JFFS2 +#define CONFIG_CMD_CRAMFS +#endif + +/* #define CONFIG_BOOTP_MASK CONFIG_BOOTP_DEFAULT */ + + +#define CONFIG_BOOTDELAY 10 +#define CONFIG_BOOTARGS "console=ttyS1,115200n8 " \ + "root=/dev/mtdblock5 rootfstype=jffs2" \ + " noalign" +#define CONFIG_BOOTCOMMAND "run bootcmd1" +#define CONFIG_TIMESTAMP 1 +#define CONFIG_TFTP_PORT 1 + +/* + * Physical Memory Map + */ +/* if we have psRAM and SDRAM */ +/* #define CONFIG_SYS_PSRAM 1 */ +#undef CONFIG_SYS_PSRAM + +#define CONFIG_NR_DRAM_BANKS 1 +#ifdef CONFIG_SYS_PSRAM + #define CONFIG_SYS_SDRAM_BASE 0x90000000 +#else + #define CONFIG_SYS_SDRAM_BASE 0x20000000 +#endif + +#define PHYS_SDRAM_1 CONFIG_SYS_SDRAM_BASE +#define PHYS_SDRAM_1_SIZE (8<<20) /* min 8 MB */ +#define CONFIG_SYS_MEMTEST_START PHYS_SDRAM_1 +#define CONFIG_SYS_MEMTEST_END (PHYS_SDRAM_1 + PHYS_SDRAM_1_SIZE - \ + (1<<20) - 1) /* ramsize - 1MB */ +#define CONFIG_SYS_ALT_MEMTEST 1 + +/* + * FLASH and environment organization + */ +#ifdef CONFIG_NANDFLASH + +#define NAND_MAX_CHIPS 1 +#define CONFIG_SYS_MAX_NAND_DEVICE 1 +#define CONFIG_SYS_NAND_BASE 0x80000000 +#define CONFIG_SYS_NAND_ALE_ADDR (1<<10) +#define CONFIG_SYS_NAND_CLE_ADDR (1<<12) +#define CONFIG_SYS_NAND_RB_PORT 0xC2104200 +#define CONFIG_SYS_NAND_RB_BIT 18 +#define CONFIG_SYS_NO_FLASH 1 + +#define CONFIG_ENV_IS_IN_NAND 1 +#define CONFIG_ENV_OFFSET 0x40000 +#define CONFIG_ENV_OFFSET_REDUND 0x60000 +#define CONFIG_ENV_OVERWRITE 1 + + +#else /* NOR-FLASH */ +/* set optimized access throug board_init */ +/* CONFIG_SYS_OPTIMIZE_NORFLASH 1 */ + +#define CONFIG_ENV_IS_IN_FLASH 1 +#define CONFIG_ENV_ADDR 0x80060000 +#define CONFIG_ENV_SECT_SIZE 0x20000 /* 128KB */ + +/* Use drivers/cfi_flash.c */ +#define CONFIG_FLASH_CFI_DRIVER 1 +/* Flash memory is CFI compliant */ +#define CONFIG_SYS_FLASH_CFI 1 +/* Use buffered writes (~20x faster) */ +#define CONFIG_SYS_FLASH_USE_BUFFER_WRITE 1 +/* Use hardware sector protection */ +#define CONFIG_SYS_FLASH_PROTECTION 1 +/* Use Spansion hardware sector protection */ +/* #define CONFIG_SYS_AMD_PPB_PROTECTION 1 */ + +#define CONFIG_SYS_FLASH_BASE 0x80000000 +#define CONFIG_SYS_FLASH_BANKS_LIST { CONFIG_SYS_FLASH_BASE } +#define CONFIG_SYS_FLASH_EMPTY_INFO 1 +/* see include/flash.h for details FLASH_CFI_8BIT */ +#define CONFIG_SYS_FLASH_CFI_WIDTH 0x1 +/* 4* 32K + 254* 128k + 4* 32k = 262 Sectors */ +#define CONFIG_SYS_MAX_FLASH_SECT 262 +/* max number of memory banks */ +#define CONFIG_SYS_MAX_FLASH_BANKS 1 + +/* Flash banks JFFS2 should use */ +#define CONFIG_SYS_JFFS_CUSTOM_PART 1 +#define CONFIG_SYS_JFFS2_SORT_FRAGMENTS 1 +#define CONFIG_JFFS2_CMDLINE 1 +#define CONFIG_JFFS2_LZO_LZARI 1 +#define CONFIG_JFFS2_DEV "firetux" +#define CONFIG_FLASH_SHOW_PROGRESS 45 +#define MTDIDS_DEFAULT "nor0=firetux" +#define MTDPARTS_DEFAULT "mtdparts=firetux:" \ + "384k(U-Boot)," \ + "128k(U-Bootenv)," \ + "1536k(kernel)," \ + "1M(config)," \ + "2M(data)," \ + "-(rootfs)" + +#ifndef CONFIG_SYS_JFFS_CUSTOM_PART +#define CONFIG_SYS_JFFS2_FIRST_BANK 0 +#define CONFIG_SYS_JFFS2_NUM_BANKS 1 +/* start addr 0x80500000 */ +#define CONFIG_SYS_JFFS2_FIRST_SECTOR 40 +#define CONFIG_SYS_JFFS_SINGLE_PART 1 +#endif + +#endif /* NOR-FLASH */ + +#define CONFIG_SYS_MONITOR_BASE CONFIG_SYS_FLASH_BASE +#define CONFIG_SYS_MONITOR_LEN 0x0005ffff + +/* + * Miscellaneous configurable options + */ +/* undef to save memory */ +#define CONFIG_SYS_LONGHELP 1 +#define CONFIG_SYS_HUSH_PARSER 1 +#define CONFIG_SYS_PROMPT_HUSH_PS2 "> " +/* Monitor Command Prompt */ +#define CONFIG_SYS_PROMPT "firetux # " +/* Console I/O Buffer Size*/ +#define CONFIG_SYS_CBSIZE 512 + +/* Print Buffer Size */ +#define CONFIG_SYS_PBSIZE (CONFIG_SYS_CBSIZE + \ + sizeof(CONFIG_SYS_PROMPT)+16) +/* max number of command args */ +#define CONFIG_SYS_MAXARGS 16 +/* Boot Argument Buffer Size*/ +#define CONFIG_SYS_BARGSIZE CONFIG_SYS_CBSIZE + +/* default load address, keep 2 MByte for u-boot/kernel */ +#define CONFIG_SYS_LOAD_ADDR (PHYS_SDRAM_1 + (2<<20)) + +#ifdef CONFIG_CMD_EEPROM +#define CONFIG_PNX8181_I2C 1 +#define CONFIG_SYS_EEPROM_WREN 1 +#undef CONFIG_SYS_I2C_MULTI_EEPROMS +#define CONFIG_SYS_I2C_EEPROM_ADDR_LEN 2 +#define CONFIG_SYS_I2C_EEPROM_ADDR 0x50 +#define CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS 1 +#define CONFIG_SYS_I2C_SPEED 100000 +#define CONFIG_SYS_I2C_SLAVE 0xfe +#define CONFIG_HARD_I2C 1 +#endif +/* + * Stack sizes + * + * The stack sizes are set up in start.S using the settings below + */ +/* regular stack */ +#define CONFIG_STACKSIZE (128*1024) +#ifdef CONFIG_USE_IRQ +/* IRQ stack */ +#define CONFIG_STACKSIZE_IRQ (4*1024) +/* FIQ stack */ +#define CONFIG_STACKSIZE_FIQ (4*1024) +#endif + +#endif /* __CONFIG_H */

+# 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-y += firetux.o boardrevision.o led.o gpio.o
please split it
+COBJS-$(CONFIG_CMD_NAND) += nand.o +SOBJS-y += lowlevel_init.o memsetup.o relocate.o
please split it
+SRCS := $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c) +OBJS := $(addprefix $(obj),$(COBJS-y)) +SOBJS := $(addprefix $(obj),$(SOBJS-y))
+all: $(LIB)
+$(LIB): $(obj).depend $(OBJS) $(SOBJS)
- $(AR) $(ARFLAGS) $@ $(OBJS) $(SOBJS)
+clean:
- rm -f $(SOBJS) $(OBJS)
+distclean: clean
- rm -f $(LIB) core *.bak .depend
+#########################################################################
+# defines $(obj).depend target +include $(SRCTREE)/rules.mk
+sinclude $(obj).depend
+######################################################################### diff --git a/board/dspg/firetux/boardrevision.c b/board/dspg/firetux/boardrevision.c new file mode 100644 index 0000000..3119090 --- /dev/null +++ b/board/dspg/firetux/boardrevision.c @@ -0,0 +1,299 @@ +/*
- firetux board detection
- (C) Copyright 2007-2009, emlix GmbH, Germany
- Juergen Schoew js@emlix.com
- (C) Copyright 2008, Sebastian Hess, emlix GmbH sh@emlix.com
- (C) Copyright 2008, DSPG Technologies GmbH, Germany
- (C) Copyright 2007, NXP Semiconductors Germany GmbH
- Matthias Wenzel, nxp@mazzoo.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
- */
+/*
- These VEGA boards are very similair to each other. The main difference
- is the phy address of the network, CPU revision, number of leds and keys.
- */
+#include <common.h> +#include <asm/io.h> +#include "firetux.h"
+#ifndef CONFIG_IP3912_ETN1_BASE +#define CONFIG_IP3912_ETN1_BASE 0xC1600000 +#endif +#ifndef CONFIG_IP3912_ETN2_BASE +#define CONFIG_IP3912_ETN2_BASE 0xC1700000 +#endif
+/* ip3912 / pnx8181 ETN registers */ +#define ETN1_BASE CONFIG_IP3912_ETN1_BASE +#define ETN2_BASE CONFIG_IP3912_ETN2_BASE
+#define ETN_MAC1 0x0000 +#define ETN_SUPP 0x0018 +#define ETN_MCFG 0x0020 +#define ETN_MADR 0x0028 +#define ETN_MCMD 0x0024 +#define ETN_MWTD 0x002c +#define ETN_MRDD 0x0030 +#define ETN_MIND 0x0034 +#define ETN_COMMAND 0x0100
please move to a heaser
+static char firetux_boardrevision = UNKNOWN_PNX8181;
+char get_boardrevision(void) +{
- return firetux_boardrevision;
+}
+static void detect_etn_start(void) +{
- debug("board detect: initialize ETN\n");
- /* reset MII mgmt, set MII clock */
- writel(0x0000801c, (void *)(ETN1_BASE + ETN_MCFG));
- writel(0x0000001c, (void *)(ETN1_BASE + ETN_MCFG));
- /* enable RMMI */
- writel(0x00000600, (void *)(ETN1_BASE + ETN_COMMAND));
- /* reset MAC layer */
- writel(0x0000cf00, (void *)(ETN1_BASE + ETN_MAC1));
- /* release MAC soft reset */
- writel(0x00000000, (void *)(ETN1_BASE + ETN_MAC1));
- /* reset rx-path, tx-path, host registers */
- writel(0x00000638, (void *)(ETN1_BASE + ETN_COMMAND));
- /* reset RMII, 100Mbps MAC, 10Mbps MAC */
- writel(0x1888, (void *)(ETN1_BASE + ETN_SUPP));
- writel(0x1000, (void *)(ETN1_BASE + ETN_SUPP));
+}
maybe you can add an ifdef arround to not compile it when the network is desable? and is these phy functions are board or soc specific?
+/* Wait for the ETN engine to be ready */ +static void detect_phy_wait(void) +{
- int i, status;
please an empty line
- for (i = 0; i < 1000; i++) {
status = readl((void *)(ETN1_BASE + ETN_MIND)) & 0x7;
if (!status)
return;
udelay(1);
- }
- debug("board detect: wait PHY timed out!\n");
+}
+/* write to phy */ +static void detect_phy_write(u8 address, u8 reg, u16 data) +{
- writel((address << 8) | reg, (void *)(ETN1_BASE + ETN_MADR));
- writel(data, (ETN1_BASE + ETN_MWTD));
- detect_phy_wait();
+}
+/* read from phy */ +static u16 detect_phy_read(u8 address, u8 reg) +{
- u16 value;
please an empty line
- writel((address << 8) | reg, (void *)(ETN1_BASE + ETN_MADR));
- writel(0x00000001, (void *)(ETN1_BASE + ETN_MCMD));
- detect_phy_wait();
- value = readl((void *)(ETN1_BASE + ETN_MRDD));
- writel(0x00000000, (void *)(ETN1_BASE + ETN_MCMD));
- return value;
+}
+/* do a software reset on the phy */ +static int detect_phy_softreset(u8 phyaddr) +{
- int i, rc;
- debug("board detect: softreset PHY @0x%02x ", phyaddr);
- /*
* reset power down bit and set autonegotiation in
* phy basic control register 0
*/
- detect_phy_write(phyaddr, 0x00, 0x1200);
- /* set reset bit in phy basic control register */
- detect_phy_write(phyaddr, 0x00, detect_phy_read(phyaddr, 0x00)
| (1 << 15));
- udelay(260); /* HW ref (pg. 51): 256us, IEEE <= 500ms */
- /* Check for bit reset */
- for (i = 0; i < 1000; i++) {
rc = detect_phy_read(phyaddr, 0x00);
if (!(rc & (1 < 11))) {
debug("OK\n");
return 0;
}
- }
- debug("timed out!\n");
- return -1;
+}
+# 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_SYS_PSRAM +# SDRAM +TEXT_BASE = 0x20780000 +else +# mobile pSRAM +TEXT_BASE = 0x90700000 +endif
+PLATFORM_CPPFLAGS += -fPIC -fPIE -fno-jump-tables # -msingle-pic-base
could you explain why?
+ifneq ($(OBJTREE),$(SRCTREE)) +# We are building u-boot in a separate directory, use generated +# .lds script from OBJTREE directory. +LDSCRIPT := $(OBJTREE)/board/$(BOARDDIR)/u-boot.lds +endif diff --git a/board/dspg/firetux/firetux.c b/board/dspg/firetux/firetux.c new file mode 100644 index 0000000..52f0ad1 --- /dev/null +++ b/board/dspg/firetux/firetux.c @@ -0,0 +1,413 @@ +/*
- firetux board specific setup
- (C) Copyright 2007-2009, emlix GmbH, Germany
- Juergen Schoew js@emlix.com
- (C) Copyright 2008, DSPG Technologies GmbH, Germany
- (C) Copyright 2007, NXP Semiconductors Germany GmbH
- Matthias Wenzel, nxp@mazzoo.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 <common.h> +#include <asm/io.h> +#include <status_led.h> +#include "firetux.h"
+DECLARE_GLOBAL_DATA_PTR;
+/* functions for ethernet initialization */ +extern int ip3912_eth_initialize(unsigned char nr, unsigned int etn_base,
- unsigned int phy_base, unsigned char phy_addr, unsigned char rmii);
+extern int ip3912_miiphy_initialize(bd_t *bis);
+#ifdef CONFIG_SHOW_BOOT_PROGRESS +void show_boot_progress(int progress) +{
- printf("Boot reached stage %d\n", progress);
+} +#endif
- writel(31, (void *)PNX8181_INTC_PRIOMASK_IRQ);
- writel(31, (void *)PNX8181_INTC_PRIOMASK_FIQ);
- for (i = 1; i < 67; i++)
PNX8181_DISABLEIRQ(i);
- writel(readl((void *)PNX8181_CGU_GATESC) & 0xfdd7becd,
(void *)PNX8181_CGU_GATESC);
+}
soc or board specifiy?
+/* Ethernet */ +void firetux_sysmux_config_rmii(void) +{
- /* config gpio c15 and c16 for RMII */
- writel((readl((void *)(PNX8181_SCON_BASE + PNX8181_SYSMUX4))
& ~(0x3 << 0)), (void *)(PNX8181_SCON_BASE + PNX8181_SYSMUX4));
- writel((readl((void *)(PNX8181_SCON_BASE + PNX8181_SYSMUX5))
& ~(0x3 << 30)), (void *)(PNX8181_SCON_BASE + PNX8181_SYSMUX5));
+}
soc or board specifiy?
+void firetux_sysmux_config_etn1(void) +{
- /* config gpio c0 and c6 for ETN1 */
- writel((readl((void *)(PNX8181_SCON_BASE + PNX8181_SYSMUX4))
& 0xffffc000), (void *)(PNX8181_SCON_BASE + PNX8181_SYSMUX4));
+}
soc or board specifiy?
+void firetux_sysmux_config_etn2(void) +{
- /* config gpio c7 and c13 for ETN2 (alternative config for sd-card) */
- writel((readl((void *)(PNX8181_SCON_BASE + PNX8181_SYSMUX4))
& 0xf0003fff), (void *)(PNX8181_SCON_BASE + PNX8181_SYSMUX4));
+}
soc or board specifiy?
+int board_eth_init(bd_t *bis)
soc or board specifiy?
+{
- int rc = 0;
+/*
- priority setting for ETN over CPU for SDRAM access
- enable port-aging with priority for ETN
- */
+#ifdef CONFIG_SYS_ETHER_FAIR_SCHEDULE
- /*
* be fair: ETN and CPU are both high priority, but ETN gets
* higher priority and a much lower ageing penatly to get
* much more accesses to RAM
*/
- writel(0x80000121, (void *)(PNX8181_SDI_SCHED + PNX8181_SCHED0));
- writel(0xffff0100, (void *)(PNX8181_SDI_SCHED + PNX8181_SCHED1));
- writel(0x00030131, (void *)(PNX8181_SDI_SCHED + PNX8181_SCHED2));
+#else
- /*
* highly prioritise the ETN engine and lower CPU priority
* to archive a better network thoughput
*/
- writel(0xffff0020, (void *)(PNX8181_SDI_SCHED + PNX8181_SCHED0));
- writel(0xffff0000, (void *)(PNX8181_SDI_SCHED + PNX8181_SCHED1));
- writel(0xffff0031, (void *)(PNX8181_SDI_SCHED + PNX8181_SCHED2));
+#endif
- /* increase priority for SCRAM access at AHB of descriptors */
- writew(7, (void *)(PNX8181_SC_ARB_BASE + PNX8181_SC_ARB_CFG2));
- writew(7, (void *)(PNX8181_SC_ARB_BASE + PNX8181_SC_ARB_CFG3));
- /*
* init ETN clocks
*
* set ETNREFCLK to internal CGU clock, assuming a 13.824MHz crystal
* for other xtals see NXP's validation tests,
* lib/tools/source/swift_tools.c
*/
- writel((15 << 9) | (62 << 3) | 3, (void *)PNX8181_CGU_PER2CON);
- /* turn on PLL */
- writel(readl((void *)PNX8181_CGU_PER2CON) | 0x00010000,
(void *)PNX8181_CGU_PER2CON);
- /* wait for PLL lock */
- while (!(readl((void *)PNX8181_CGU_PER2CON) & 0x00020000))
;
- /* ungate ETN clocks */
- writel(readl((void *)PNX8181_CGU_PER2CON) | 0x00802000,
(void *)PNX8181_CGU_PER2CON);
- /* register ip3912 mii interface */
- ip3912_miiphy_initialize(gd->bd);
- /* register ethernet devices */
- switch (get_boardrevision()) {
- case 1:
- case 2:
firetux_sysmux_config_rmii();
firetux_sysmux_config_etn1();
firetux_sysmux_config_etn2();
/* phys are at addr 0x1 & 0x2 at RMII phybus */
rc |= ip3912_eth_initialize(0, CONFIG_IP3912_ETN1_BASE,
CONFIG_IP3912_ETN1_BASE, 0x01, 1);
rc |= ip3912_eth_initialize(1, CONFIG_IP3912_ETN2_BASE,
CONFIG_IP3912_ETN1_BASE, 0x02, 1);
break;
- case 3:
- case 4:
firetux_sysmux_config_rmii();
firetux_sysmux_config_etn1();
firetux_sysmux_config_etn2();
/* phys are at addr 0x1e & 0x1d at RMII phybus */
rc |= ip3912_eth_initialize(0, CONFIG_IP3912_ETN1_BASE,
CONFIG_IP3912_ETN1_BASE, 0x1e, 1);
rc |= ip3912_eth_initialize(1, CONFIG_IP3912_ETN2_BASE,
CONFIG_IP3912_ETN1_BASE, 0x1d, 1);
break;
- default:
return -1;
- }
- return rc;
+}
+/*
- Miscellaneous platform dependent initialisations
- */
+int board_init(void) +{
- /* arch number of Firetux Platform Boards */
- gd->bd->bi_arch_number = MACH_TYPE_PNX8181;
- /* adress of boot parameters / atags */
- gd->bd->bi_boot_params = PHYS_SDRAM_1 + 0x100;
- /* release the RSTAPU and RSTEXT signal which keeps the PHYs in reset */
- writel(readw((void *)PNX8181_WDRUCON) | 0x0009,
(void *)PNX8181_WDRUCON);
- /* lower VDDIO to Vbgp * 2.44 (typ. 3.05V) */
- writel(0x0079, (void *)PNX8181_DAIF_RVDDC);
- /* select TXD2 for GPIOa11 and select RXD2 for GPIOa1 */
- writel(((readl((void *)(PNX8181_SCON_BASE + PNX8181_SYSMUX0))
& 0xff3ffff3) | 0x00400004),
(void *)(PNX8181_SCON_BASE + PNX8181_SYSMUX0));
- /* select ETN for GPIOc0-16 */
- writel(readl((void *)(PNX8181_SCON_BASE + PNX8181_SYSMUX5))
& 0xfffffffc,
(void *)(PNX8181_SCON_BASE + PNX8181_SYSMUX5));
- writel(readl((void *)(PNX8181_SCON_BASE + PNX8181_SYSMUX4))
& 0x30000000,
(void *)(PNX8181_SCON_BASE + PNX8181_SYSMUX4));
- /* use clk26m and fract-n for UART2 */
- writew(((1 << 7) | (1 << 1)),
(void *)(PNX8181_UART2_BASE + PNX8181_UART_FDIV_CTRL));
- writew(0x5F37, (void *)(PNX8181_UART2_BASE + PNX8181_UART_FDIV_M));
- writew(0x32C8, (void *)(PNX8181_UART2_BASE + PNX8181_UART_FDIV_N));
- board_detect();
- firetux_gpio_init();
- icache_enable();
- dcache_enable();
+#ifdef CONFIG_CMD_NAND
- firetux_nandflash_init();
+#else
- firetux_norflash_init();
+#endif
- firetux_irq_disable();
- return 0;
+}
+int firetux_keystatus(int key) +{
- int ret = 0;
- switch (key) {
- case 1: /* GPIOA2 */
ret = get_gpioa(2);
break;
- case 2: /* GPIOA10 */
ret = get_gpioa(10);
break;
- default:
ret = -1;
break;
- }
- return ret;
+}
+void firetux_check_bootkey(void) +{
- int i = 0, abort = 0;
- while ((abort == 0) && (i < 500)) {
if (firetux_keystatus(2) == 1) {
setenv("bootcmd", "run bootcmd1");
firetux_set_led(2, 0);
abort = 1;
}
i++;
udelay(10000);
- }
- if (abort == 0) {
setenv("bootcmd", "run bootcmd2");
puts("using alternative bootcmd\n");
firetux_set_led(2, 1);
- }
+}
+int misc_init_r(void) +{
- if (get_boardrevision() > 1) /* ez_mcp_pnx8181 has no keys */
firetux_check_bootkey();
- setenv("verify", "n");
- return 0;
+}
+#if defined(CONFIG_DISPLAY_CPUINFO) +int print_cpuinfo(void)
soc or board specifiy?
+{
- unsigned int sysver, cgu_sccon, armclk, hclk;
- puts("CPU: ");
- sysver = readw((void *)PNX8181_REG_SC_SYSVER);
- printf("PNX8181-%d%c %s-ARM926EJ-S(ARMv5TEJ) ",
((sysver >> 4) & 0xf), ((sysver & 0xf) + 64),
(((sysver >> 8) & 0xf) == 1) ? "OM6xxx" : "unknown");
- cgu_sccon = readw((void *)PNX8181_CGU_SCCON);
- /* armclk = bbcki * nsc / msc / ksc */
- armclk = 13824 * (((cgu_sccon >> 3) & 0x3f) + 1)
/ ((cgu_sccon & 0x7) + 1)
/ (((cgu_sccon >> 10) & 0x3) + 1);
- hclk = armclk / (((cgu_sccon >> 12) & 0xf) + 1);
- printf("@ %dMHz(armclk), %dMHz(hclk)\n",
(armclk / 1000), (hclk / 1000));
- return 0;
+} +#endif
+#if defined(CONFIG_DISPLAY_BOARDINFO) +int checkboard(void) +{
- puts("Board: ");
- switch (get_boardrevision()) {
- case 1:
puts("EZ_MCP_PNX8181\n");
break;
- case 2:
puts("Vega_PNX8181_BaseStation Platform III-a\n");
break;
- case 3:
puts("Vega_PNX8181_BaseStation Platform III-b\n");
break;
- case 4:
puts("Vega_PNX8181_BaseStation Platform III-c\n");
break;
- case 0:
- default:
puts("unknown PNX8181 board\n");
break;
- }
- return 0;
+} +#endif
+int dram_init(void) +{
- int reg;
- reg = readl((void *)PNX8181_SDI_CFG_1);
- gd->bd->bi_dram[0].start = PHYS_SDRAM_1;
- gd->bd->bi_dram[0].size = 1 << (
(reg & 0x3) + /* dram width 8, 16, 32, 64 */
(((reg & 0x30) >> 4) + 8) + /* columns 8, 9, 10, 11 */
(((reg & 0x700) >> 8) + 9) + /* rows 9 .. 16 */
((reg & 0x3000) >> 12)); /* nr banks 1, 2, 4 */
- return 0;
+} diff --git a/board/dspg/firetux/firetux.h b/board/dspg/firetux/firetux.h new file mode 100644 index 0000000..0196197 --- /dev/null +++ b/board/dspg/firetux/firetux.h @@ -0,0 +1,144 @@ +/*
- firetux board specific defines
- (C) Copyright 2007-2009, emlix GmbH, Germany
- Juergen Schoew js@emlix.com
- (C) Copyright 2008, DSPG Technologies GmbH, Germany
- (C) Copyright 2007, NXP Semiconductors Germany GmbH
- Matthias Wenzel, nxp@mazzoo.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
- */
+/*
- Boardrevisions:
- 0: unknown PNX8181 board
- 1: EZ_MCP_PNX8181
- 2: Vega_PNX8181_BaseStation Platform III-a
- 3: Vega_PNX8181_BaseStation Platform III-b
- 4: Vega_PNX8181_BaseStation Platform III-c
- */
+#define CONFIG_MAX_BOARDREVISIONS 4 +enum firetux_revisions {
- Any_PNX8181_BaseStation = -1,
- UNKNOWN_PNX8181 = 0,
- EZ_MCP_PNX8181,
- VEGA_BASESTATION_IIIA,
- VEGA_BASESTATION_IIIB,
- VEGA_BASESTATION_IIIC,
+};
+/* watchdog control register */ +#define PNX8181_WDRUCON 0xc2203000
soc or board specifiy?
+/* digital to analog interface */ +#define PNX8181_DAIF_RVDDC 0xc2000000
soc or board specifiy? and so on please check
btw could you split this patch to simplify it's review
Best Regards, J.

Dear =?UTF-8?B?SsO8cmdlbiBTY2jDtnc=?=,
In message 20090104225830.7e936eca@schleppi.schoew.net you wrote:
--===============1974869777== Content-Type: multipart/signed; boundary="Sig_/7=Xl+9NRIJIvmVYW4MQsT9k"; protocol="application/pgp-signature"; micalg=PGP-SHA1
--Sig_/7=Xl+9NRIJIvmVYW4MQsT9k Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: quoted-printable
MAINTAINERS | 4 + MAKEALL | 1 + Makefile | 7 + board/dspg/firetux/Makefile | 59 ++++ board/dspg/firetux/boardrevision.c | 299 ++++++++++++++++ board/dspg/firetux/config.mk | 44 +++ board/dspg/firetux/firetux.c | 413 ++++++++++++++++++++++ board/dspg/firetux/firetux.h | 144 ++++++++ board/dspg/firetux/gpio.c | 134 ++++++++ board/dspg/firetux/led.c | 169 +++++++++ board/dspg/firetux/lowlevel_init.S | 404 ++++++++++++++++++++++ board/dspg/firetux/memsetup.S | 381 +++++++++++++++++++++ board/dspg/firetux/nand.c | 68 ++++ board/dspg/firetux/relocate.S | 252 ++++++++++++++ board/dspg/firetux/u-boot.lds | 57 +++ include/configs/firetux.h | 454 +++++++++++++++++++++++++
Here, like it seems in all your patches, there is no signed-off-by line.
We cannot accept patches that are missing the SoB.
Best regards,
Wolfgang Denk

Hello Wolfgang Denk,
Am Mon, 09 Feb 2009 21:07:29 +0100 schrieb Wolfgang Denk wd@denx.de:
Dear =?UTF-8?B?SsO8cmdlbiBTY2jDtnc=?=,
In message 20090104225830.7e936eca@schleppi.schoew.net you wrote:
--===============1974869777== Content-Type: multipart/signed; boundary="Sig_/7=Xl+9NRIJIvmVYW4MQsT9k"; protocol="application/pgp-signature"; micalg=PGP-SHA1
--Sig_/7=Xl+9NRIJIvmVYW4MQsT9k Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: quoted-printable
MAINTAINERS | 4 + MAKEALL | 1 + Makefile | 7 + board/dspg/firetux/Makefile | 59 ++++ board/dspg/firetux/boardrevision.c | 299 ++++++++++++++++ board/dspg/firetux/config.mk | 44 +++ board/dspg/firetux/firetux.c | 413 ++++++++++++++++++++++ board/dspg/firetux/firetux.h | 144 ++++++++ board/dspg/firetux/gpio.c | 134 ++++++++ board/dspg/firetux/led.c | 169 +++++++++ board/dspg/firetux/lowlevel_init.S | 404 ++++++++++++++++++++++ board/dspg/firetux/memsetup.S | 381 +++++++++++++++++++++ board/dspg/firetux/nand.c | 68 ++++ board/dspg/firetux/relocate.S | 252 ++++++++++++++ board/dspg/firetux/u-boot.lds | 57 +++ include/configs/firetux.h | 454 +++++++++++++++++++++++++
Here, like it seems in all your patches, there is no signed-off-by line.
We cannot accept patches that are missing the SoB.
I sure can understand that you cannot accept messages without SoB. Isn't it sufficient to have them in the first mail ( [0/3] ) of the patchset? There have been the following lines: Signed-off-by: Jürgen Schöw js@emlix.com Signed-off-by: Sebastian Hess sh@emlix.com Signed-off-by: Matthias Mwenzel nxp@mazzoo.de Signed-off-by: Dirk Hörner dirk.hoerner@dspg.com Signed-off-by: Andreas Weißel andreas.weissel@dspg.com But I can make them appear in every patch, if you need them repeated. All patches have been acked by the people. Sorry this was my first split patchset, with a lot of connectivity problems during holiday. Will try to improve the next mails.
Regards
Jürgen Schöw

Dear =?UTF-8?B?SsO8cmdlbiBTY2jDtnc=?=,
In message 20090210005626.7db69110@schleppi.schoew.net you wrote:
I sure can understand that you cannot accept messages without SoB. Isn't it sufficient to have them in the first mail ( [0/3] ) of the patchset? There have been the following lines:
No, of course this is NOT sufficient, because auch a summary does not actually go into the repository, and we need to be able to see the SoB for each commit that goes in - thus these must be present in each and every patch. You can omit it in the summary, though - there it is really not needed.
Will try to improve the next mails.
np.
Best regards,
Wolfgang Denk
participants (4)
-
Ben Warren
-
Jean-Christophe PLAGNIOL-VILLARD
-
Jürgen Schöw
-
Wolfgang Denk