[U-Boot] [PATCH 0/11] Update gdsys ppc4xx-based boards

Dirk Eibach (11): powerpc/ppc4xx: Add generic accessor functions for gdsys FPGA powerpc/ppc4xx: Add gdsys mclink interface powerpc/ppc4xx: Add fpgad command for dumping gdsys fpga registers powerpc/ppc4xx: Add bitbang i2c interface for gdsys boards powerpc/ppc4xx: Use generic FPGA accessors in gdsys common code powerpc/ppc4xx: Support gdsys multichannel iocon hardware powerpc/ppc4xx: Use generic FPGA accessors on all gdsys 405ep/ex boards powerpc/ppc4xx: Fixup phy erratum on gdsys iocon hardware powerpc/ppc4xx: Increase timeout for gdsys mclink bus startup powerpc/ppc4xx: Consider gdsys FPGA OSD size powerpc/ppc4xx: Remove CONFIG_SYS_FLASH_PROTECTION from gdsys boards
board/gdsys/405ep/405ep.c | 12 +- board/gdsys/405ep/dlvision-10g.c | 20 +- board/gdsys/405ep/io.c | 20 +- board/gdsys/405ep/iocon.c | 467 ++++++++++++++++++++++++++++++++++---- board/gdsys/405ep/neo.c | 17 +- board/gdsys/405ex/405ex.c | 14 +- board/gdsys/405ex/io64.c | 38 ++-- board/gdsys/common/Makefile | 2 +- board/gdsys/common/bb_i2c.c | 304 +++++++++++++++++++++++++ board/gdsys/common/bb_i2c.h | 76 +++++++ board/gdsys/common/cmd_fpga.c | 94 ++++++++ board/gdsys/common/mclink.c | 142 ++++++++++++ board/gdsys/common/mclink.h | 31 +++ board/gdsys/common/osd.c | 105 +++++---- include/configs/dlvision-10g.h | 3 +- include/configs/dlvision.h | 3 +- include/configs/io.h | 3 +- include/configs/iocon.h | 43 ++-- include/configs/neo.h | 3 +- include/gdsys_fpga.h | 20 +- 20 files changed, 1249 insertions(+), 168 deletions(-) create mode 100644 board/gdsys/common/bb_i2c.c create mode 100644 board/gdsys/common/bb_i2c.h create mode 100644 board/gdsys/common/cmd_fpga.c create mode 100644 board/gdsys/common/mclink.c create mode 100644 board/gdsys/common/mclink.h

A set of accessor functions was added to be able to access not only memory mapped FPGA in a generic way.
Signed-off-by: Dirk Eibach eibach@gdsys.de --- include/gdsys_fpga.h | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/include/gdsys_fpga.h b/include/gdsys_fpga.h index 1758d74..c12a31d 100644 --- a/include/gdsys_fpga.h +++ b/include/gdsys_fpga.h @@ -32,9 +32,14 @@ enum { FPGA_STATE_PLATFORM = 1 << 2, };
+#define REG(reg) offsetof(struct ihs_fpga, reg) + int get_fpga_state(unsigned dev); void print_fpga_state(unsigned dev);
+void fpga_set_reg(unsigned int fpga, u16 reg, u16 data); +u16 fpga_get_reg(unsigned int fpga, u16 reg); + struct ihs_gpio { u16 read; u16 clear;

mclink is a serial interface for communication between gdsys FPGA.
Signed-off-by: Dirk Eibach eibach@gdsys.de --- board/gdsys/common/Makefile | 2 +- board/gdsys/common/mclink.c | 140 +++++++++++++++++++++++++++++++++++++++++++ board/gdsys/common/mclink.h | 31 ++++++++++ 3 files changed, 172 insertions(+), 1 deletion(-) create mode 100644 board/gdsys/common/mclink.c create mode 100644 board/gdsys/common/mclink.h
diff --git a/board/gdsys/common/Makefile b/board/gdsys/common/Makefile index 05dd65d..6f09550 100644 --- a/board/gdsys/common/Makefile +++ b/board/gdsys/common/Makefile @@ -31,7 +31,7 @@ LIB = $(obj)lib$(VENDOR).o
COBJS-$(CONFIG_IO) += miiphybb.o COBJS-$(CONFIG_IO64) += miiphybb.o -COBJS-$(CONFIG_IOCON) += osd.o +COBJS-$(CONFIG_IOCON) += osd.o mclink.o COBJS-$(CONFIG_DLVISION_10G) += osd.o
COBJS := $(COBJS-y) diff --git a/board/gdsys/common/mclink.c b/board/gdsys/common/mclink.c new file mode 100644 index 0000000..6c86145 --- /dev/null +++ b/board/gdsys/common/mclink.c @@ -0,0 +1,140 @@ +/* + * (C) Copyright 2012 + * Dirk Eibach, Guntermann & Drunck GmbH, eibach@gdsys.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 <errno.h> + +#include <gdsys_fpga.h> + +enum { + MCINT_SLAVE_LINK_CHANGED_EV = 1 << 7, + MCINT_TX_ERROR_EV = 1 << 9, + MCINT_TX_BUFFER_FREE = 1 << 10, + MCINT_TX_PACKET_TRANSMITTED_EV = 1 << 11, + MCINT_RX_ERROR_EV = 1 << 13, + MCINT_RX_CONTENT_AVAILABLE = 1 << 14, + MCINT_RX_PACKET_RECEIVED_EV = 1 << 15, +}; + +int mclink_probe(void) +{ + unsigned int k; + unsigned int ctr = 0; + int slaves = 0; + + for (k = 0; k < CONFIG_SYS_MCLINK_MAX; ++k) { + int timeout = 0; + + if (!(fpga_get_reg(k, REG(mc_status)) & (1 << 15))) + break; + + fpga_set_reg(k, REG(mc_control), 0x8000); + + while (!(fpga_get_reg(k, REG(mc_status)) & (1 << 14))) { + udelay(100); + if (ctr++ > 3) { + timeout = 1; + break; + } + } + if (timeout) + break; + + slaves++; + } + + return slaves; +} + +int mclink_send(u8 slave, u16 addr, u16 data) +{ + unsigned int ctr = 0; + u16 int_status; + u16 rx_cmd_status; + u16 rx_cmd; + + /* reset interrupt status */ + int_status = fpga_get_reg(0, REG(mc_int)); + fpga_set_reg(0, REG(mc_int), int_status); + + /* send */ + fpga_set_reg(0, REG(mc_tx_address), addr); + fpga_set_reg(0, REG(mc_tx_data), data); + fpga_set_reg(0, REG(mc_tx_cmd), (slave & 0x03) << 14); + fpga_set_reg(0, REG(mc_control), 0x8001); + + /* wait for reply */ + while (!(fpga_get_reg(0, REG(mc_int)) & MCINT_RX_PACKET_RECEIVED_EV)) { + udelay(100); + if (ctr++ > 3) + return -ETIMEDOUT; + } + + rx_cmd_status = fpga_get_reg(0, REG(mc_rx_cmd_status)); + rx_cmd = (rx_cmd_status >> 12) & 0x03; + if (rx_cmd != 0) + printf("mclink_send: received cmd %d, expected %d\n", rx_cmd, + 0); + + return 0; +} + +int mclink_receive(u8 slave, u16 addr, u16 *data) +{ + u16 rx_cmd_status; + u16 rx_cmd; + unsigned int ctr = 0; + + /* send read request */ + fpga_set_reg(0, REG(mc_tx_address), addr); + fpga_set_reg(0, REG(mc_tx_cmd), + ((slave & 0x03) << 14) | (1 << 12) | (1 << 0)); + fpga_set_reg(0, REG(mc_control), 0x8001); + + /* wait for reply */ + while (!(fpga_get_reg(0, REG(mc_int)) & MCINT_RX_CONTENT_AVAILABLE)) { + udelay(100); + if (ctr++ > 3) + return -ETIMEDOUT; + } + + /* check reply */ + rx_cmd_status = fpga_get_reg(0, REG(mc_rx_cmd_status)); + if ((rx_cmd_status >> 14) != slave) { + printf("mclink_receive: reply from slave %d, expected %d\n", + rx_cmd_status >> 14, slave); + return -EINVAL; + } + + rx_cmd = (rx_cmd_status >> 12) & 0x03; + if (rx_cmd != 1) { + printf("mclink_send: received cmd %d, expected %d\n", + rx_cmd, 1); + return -EIO; + } + + *data = fpga_get_reg(0, REG(mc_rx_data)); + + return 0; +} diff --git a/board/gdsys/common/mclink.h b/board/gdsys/common/mclink.h new file mode 100644 index 0000000..af3d667 --- /dev/null +++ b/board/gdsys/common/mclink.h @@ -0,0 +1,31 @@ +/* + * (C) Copyright 2012 + * Dirk Eibach, Guntermann & Drunck GmbH, eibach@gdsys.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 _MCLINK_H_ +#define _MCLINK_H_ + +int mclink_probe(void); +int mclink_send(u8 slave, u16 addr, u16 data); +int mclink_receive(u8 slave, u16 addr, u16 *data); + +#endif

Signed-off-by: Dirk Eibach eibach@gdsys.de --- board/gdsys/common/Makefile | 2 +- board/gdsys/common/cmd_fpga.c | 94 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 95 insertions(+), 1 deletion(-) create mode 100644 board/gdsys/common/cmd_fpga.c
diff --git a/board/gdsys/common/Makefile b/board/gdsys/common/Makefile index 6f09550..aa15c15 100644 --- a/board/gdsys/common/Makefile +++ b/board/gdsys/common/Makefile @@ -31,7 +31,7 @@ LIB = $(obj)lib$(VENDOR).o
COBJS-$(CONFIG_IO) += miiphybb.o COBJS-$(CONFIG_IO64) += miiphybb.o -COBJS-$(CONFIG_IOCON) += osd.o mclink.o +COBJS-$(CONFIG_IOCON) += osd.o mclink.o cmd_fpga.o COBJS-$(CONFIG_DLVISION_10G) += osd.o
COBJS := $(COBJS-y) diff --git a/board/gdsys/common/cmd_fpga.c b/board/gdsys/common/cmd_fpga.c new file mode 100644 index 0000000..b73e599 --- /dev/null +++ b/board/gdsys/common/cmd_fpga.c @@ -0,0 +1,94 @@ +/* + * (C) Copyright 2012 + * Dirk Eibach, Guntermann & Drunck GmbH, eibach@gdsys.de + * + * based on cmd_mem.c + * (C) Copyright 2000 + * 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 <common.h> +#include <command.h> + +#include <gdsys_fpga.h> + +static uint dp_last_fpga; +static uint dp_last_addr; +static uint dp_last_length = 0x40; + +/* Memory Display + * + * Syntax: + * fpgad {fpga} {addr} {len} + */ +#define DISP_LINE_LEN 16 +int do_fpga_md(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + unsigned int k; + unsigned int fpga; + ulong addr, length; + int rc = 0; + u16 linebuf[DISP_LINE_LEN/sizeof(u16)]; + + /* We use the last specified parameters, unless new ones are + * entered. + */ + fpga = dp_last_fpga; + addr = dp_last_addr; + length = dp_last_length; + + if (argc < 3) + return CMD_RET_USAGE; + + if ((flag & CMD_FLAG_REPEAT) == 0) { + /* FPGA is specified since argc > 2 + */ + fpga = simple_strtoul(argv[1], NULL, 16); + + /* Address is specified since argc > 2 + */ + addr = simple_strtoul(argv[2], NULL, 16); + + /* If another parameter, it is the length to display. + * Length is the number of objects, not number of bytes. + */ + if (argc > 3) + length = simple_strtoul(argv[3], NULL, 16); + } + + /* Print the lines. */ + for (k = 0; k < DISP_LINE_LEN / sizeof(u16); ++k) + linebuf[k] = fpga_get_reg(fpga, addr + k * sizeof(u16)); + print_buffer(addr, (void *)linebuf, sizeof(u16), + length, DISP_LINE_LEN / sizeof(u16)); + addr += sizeof(u16)*length; + + dp_last_fpga = fpga; + dp_last_addr = addr; + dp_last_length = length; + return rc; +} + +U_BOOT_CMD( + fpgad, 4, 1, do_fpga_md, + "fpga register display", + "fpga address [# of objects]" +);

On Mon, Apr 22, 2013 at 01:16:04PM +0200, Dirk Eibach wrote:
Signed-off-by: Dirk Eibach eibach@gdsys.de
board/gdsys/common/Makefile | 2 +- board/gdsys/common/cmd_fpga.c | 94 +++++++++++++++++++++++++++++++++++++++++
There's checkpatch warning I'm guessing since I can spot some spacing issues. Also, this is a generic command, lets move it into top-level common, call it cmd_fpad.c, modify top-level README. Oh, and /* * Multiline comments go like this. */
Thanks!

Hi Tom,
... There's checkpatch warning I'm guessing since I can spot some spacing issues. ...
Hmm, interesting, it's checkpatch clean. Maybe this tool can still get even more annoying :) Will fix issues asap.
Cheers Dirk ------------------------------------------------------------------------------------------------ Besuchen Sie unseren Blog auf http://blog.gdsys.de
oder folgen Sie uns auf: twitter: http://twitter.com/#!/gdsys facebook: http://www.facebook.com/pages/Guntermann-Drunck-GmbH/318396891518396 Google+ : https://plus.google.com/100228872787564309232/ YouTube: http://www.youtube.com/user/GuntermannDrunck ------------------------------------------------------------------------------------------------ -------------------------------------------------------------------------- Guntermann & Drunck GmbH Systementwicklung Dortmunder Str. 4a D-57234 Wilnsdorf - Germany Tel: +49 (0) 27 39 / 89 01 - 100 Fax: +49 (0) 27 39 / 89 01 - 120 E-Mail: mailto:sales@gdsys.de Web: http://www.gdsys.de -------------------------------------------------------------------------- Geschaeftsfuehrer: Udo Guntermann - Martin Drunck - Reiner Ruelmann HRB 2884, Amtsgericht Siegen - WEEE-Reg.-Nr. DE30763240 USt.-Id.-Nr. DE 126575222 - Steuer-Nr. 342 / 5835 / 1041 -------------------------------------------------------------------------- DQS-zertifiziert nach ISO 9001:2008 --------------------------------------------------------------------------

-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
On 04/23/2013 05:53 AM, Eibach, Dirk wrote:
Hi Tom,
... There's checkpatch warning I'm guessing since I can spot some spacing issues. ...
Hmm, interesting, it's checkpatch clean. Maybe this tool can still get even more annoying :) Will fix issues asap.
Maybe checkpatch missed 'em, but I swear I saw space-not-tab indentation (since it was just one or two lines that looked wrong).
- -- Tom

This adds an i2c bitbang interface that can coexist with processor i2c.
Signed-off-by: Dirk Eibach eibach@gdsys.de --- board/gdsys/common/Makefile | 2 +- board/gdsys/common/bb_i2c.c | 304 +++++++++++++++++++++++++++++++++++++++++++ board/gdsys/common/bb_i2c.h | 76 +++++++++++ 3 files changed, 381 insertions(+), 1 deletion(-) create mode 100644 board/gdsys/common/bb_i2c.c create mode 100644 board/gdsys/common/bb_i2c.h
diff --git a/board/gdsys/common/Makefile b/board/gdsys/common/Makefile index aa15c15..b217d97 100644 --- a/board/gdsys/common/Makefile +++ b/board/gdsys/common/Makefile @@ -31,7 +31,7 @@ LIB = $(obj)lib$(VENDOR).o
COBJS-$(CONFIG_IO) += miiphybb.o COBJS-$(CONFIG_IO64) += miiphybb.o -COBJS-$(CONFIG_IOCON) += osd.o mclink.o cmd_fpga.o +COBJS-$(CONFIG_IOCON) += osd.o mclink.o cmd_fpga.o bb_i2c.o COBJS-$(CONFIG_DLVISION_10G) += osd.o
COBJS := $(COBJS-y) diff --git a/board/gdsys/common/bb_i2c.c b/board/gdsys/common/bb_i2c.c new file mode 100644 index 0000000..a816514 --- /dev/null +++ b/board/gdsys/common/bb_i2c.c @@ -0,0 +1,304 @@ +/* + * (C) Copyright 2012 + * Dirk Eibach, Guntermann & Drunck GmbH, eibach@gdsys.de + * + * based on soft_i2c.c + * (C) Copyright 2001, 2002 + * 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 + * + * This has been changed substantially by Gerald Van Baren, Custom IDEAS, + * vanbaren@cideas.com. It was heavily influenced by LiMon, written by + * Neil Russell. + */ + +#include <common.h> + +/*----------------------------------------------------------------------- + * Definitions + */ + +#define RETRIES 0 + +#define BB_I2C_ACK 0 /* PD_SDA level to ack a byte */ +#define BB_I2C_NOACK 1 /* PD_SDA level to noack a byte */ + +/*----------------------------------------------------------------------- + * Local functions + */ +static void send_reset(unsigned int bus); +static void send_start(unsigned int bus); +static void send_stop(unsigned int bus); +static void send_ack(unsigned int bus, int ack); +static int write_byte(unsigned int bus, uchar byte); +static uchar read_byte(unsigned int bus, int ack); + +/*----------------------------------------------------------------------- + * Send a reset sequence consisting of 9 clocks with the data signal high + * to clock any confused device back into an idle state. Also send a + * <stop> at the end of the sequence for belts & suspenders. + */ +static void send_reset(unsigned int bus) +{ + BB_I2C_SOFT_DECLARATIONS(bus) /* intentional without ';' */ + int j; + + BB_I2C_SCL(bus, 1); + BB_I2C_SDA(bus, 1); + BB_I2C_TRISTATE(bus); + for (j = 0; j < 9; j++) { + BB_I2C_SCL(bus, 0); + BB_I2C_DELAY(bus); + BB_I2C_DELAY(bus); + BB_I2C_SCL(bus, 1); + BB_I2C_DELAY(bus); + BB_I2C_DELAY(bus); + } + send_stop(bus); + BB_I2C_TRISTATE(bus); +} + +/*----------------------------------------------------------------------- + * START: High -> Low on SDA while SCL is High + */ +static void send_start(unsigned int bus) +{ + BB_I2C_SOFT_DECLARATIONS(bus) /* intentional without ';' */ + + BB_I2C_DELAY(bus); + BB_I2C_SDA(bus, 1); + BB_I2C_ACTIVE(bus); + BB_I2C_DELAY(bus); + BB_I2C_SCL(bus, 1); + BB_I2C_DELAY(bus); + BB_I2C_SDA(bus, 0); + BB_I2C_DELAY(bus); +} + +/*----------------------------------------------------------------------- + * STOP: Low -> High on SDA while SCL is High + */ +static void send_stop(unsigned int bus) +{ + BB_I2C_SOFT_DECLARATIONS(bus) /* intentional without ';' */ + + BB_I2C_SCL(bus, 0); + BB_I2C_DELAY(bus); + BB_I2C_SDA(bus, 0); + BB_I2C_ACTIVE(bus); + BB_I2C_DELAY(bus); + BB_I2C_SCL(bus, 1); + BB_I2C_DELAY(bus); + BB_I2C_SDA(bus, 1); + BB_I2C_DELAY(bus); + BB_I2C_TRISTATE(bus); +} + +/*----------------------------------------------------------------------- + * ack should be BB_I2C_ACK or BB_I2C_NOACK + */ +static void send_ack(unsigned int bus, int ack) +{ + BB_I2C_SOFT_DECLARATIONS(bus) /* intentional without ';' */ + + BB_I2C_SCL(bus, 0); + BB_I2C_DELAY(bus); + BB_I2C_ACTIVE(bus); + BB_I2C_SDA(bus, ack); + BB_I2C_DELAY(bus); + BB_I2C_SCL(bus, 1); + BB_I2C_DELAY(bus); + BB_I2C_DELAY(bus); + BB_I2C_SCL(bus, 0); + BB_I2C_DELAY(bus); +} + +/*----------------------------------------------------------------------- + * Send 8 bits and look for an acknowledgement. + */ +static int write_byte(unsigned int bus, uchar data) +{ + BB_I2C_SOFT_DECLARATIONS(bus) /* intentional without ';' */ + int j; + int nack; + + BB_I2C_ACTIVE(bus); + for (j = 0; j < 8; j++) { + BB_I2C_SCL(bus, 0); + BB_I2C_DELAY(bus); + BB_I2C_SDA(bus, data & 0x80); + BB_I2C_DELAY(bus); + BB_I2C_SCL(bus, 1); + BB_I2C_DELAY(bus); + BB_I2C_DELAY(bus); + + data <<= 1; + } + + /* + * Look for an <ACK>(negative logic) and return it. + */ + BB_I2C_SCL(bus, 0); + BB_I2C_DELAY(bus); + BB_I2C_SDA(bus, 1); + BB_I2C_TRISTATE(bus); + BB_I2C_DELAY(bus); + BB_I2C_SCL(bus, 1); + BB_I2C_DELAY(bus); + BB_I2C_DELAY(bus); + nack = BB_I2C_READ(bus); + BB_I2C_SCL(bus, 0); + BB_I2C_DELAY(bus); + BB_I2C_ACTIVE(bus); + + return nack; /* not a nack is an ack */ +} + +/*----------------------------------------------------------------------- + * if ack == BB_I2C_ACK, ACK the byte so can continue reading, else + * send BB_I2C_NOACK to end the read. + */ +static uchar read_byte(unsigned int bus, int ack) +{ + BB_I2C_SOFT_DECLARATIONS(bus) /* intentional without ';' */ + int data; + int j; + + /* + * Read 8 bits, MSB first. + */ + BB_I2C_TRISTATE(bus); + BB_I2C_SDA(bus, 1); + data = 0; + for (j = 0; j < 8; j++) { + BB_I2C_SCL(bus, 0); + BB_I2C_DELAY(bus); + BB_I2C_SCL(bus, 1); + BB_I2C_DELAY(bus); + data <<= 1; + data |= BB_I2C_READ(bus); + BB_I2C_DELAY(bus); + } + send_ack(bus, ack); + + return data; +} + +/*=====================================================================*/ +/* Public Functions */ +/*=====================================================================*/ + +/*----------------------------------------------------------------------- + * Initialization + */ +void bb_i2c_init(unsigned int bus, int speed, int slaveaddr) +{ + send_reset(bus); +} + +/*----------------------------------------------------------------------- + * Probe to see if a chip is present. Also good for checking for the + * completion of EEPROM writes since the chip stops responding until + * the write completes (typically 10mSec). + */ +int bb_i2c_probe(unsigned int bus, uchar addr) +{ + int rc; + + /* + * perform 1 byte write transaction with just address byte + * (fake write) + */ + send_start(bus); + rc = write_byte(bus, (addr << 1) | 0); + send_stop(bus); + + return rc ? 1 : 0; +} + +/*----------------------------------------------------------------------- + * Read bytes + */ +int bb_i2c_read(unsigned int bus, uchar chip, uint addr, int alen, + uchar *buffer, int len) +{ + int shift; + + /* + * Do the addressing portion of a write cycle to set the + * chip's address pointer. If the address length is zero, + * don't do the normal write cycle to set the address pointer, + * there is no address pointer in this chip. + */ + send_start(bus); + if (alen > 0) { + if (write_byte(bus, chip << 1)) { /* write cycle */ + send_stop(bus); + return 1; + } + shift = (alen-1) * 8; + while (alen-- > 0) { + if (write_byte(bus, addr >> shift)) + return 1; + shift -= 8; + } + + send_stop(bus); + send_start(bus); + } + /* + * Send the chip address again, this time for a read cycle. + * Then read the data. On the last byte, we do a NACK instead + * of an ACK(len == 0) to terminate the read. + */ + write_byte(bus, (chip << 1) | 1); /* read cycle */ + while (len-- > 0) + *buffer++ = read_byte(bus, len == 0); + send_stop(bus); + return 0; +} + +/*----------------------------------------------------------------------- + * Write bytes + */ +int bb_i2c_write(unsigned int bus, uchar chip, uint addr, int alen, + uchar *buffer, int len) +{ + int shift, failures = 0; + + send_start(bus); + if (write_byte(bus, chip << 1)) { /* write cycle */ + send_stop(bus); + return 1; + } + shift = (alen-1) * 8; + while (alen-- > 0) { + if (write_byte(bus, addr >> shift)) + return 1; + shift -= 8; + } + + while (len-- > 0) { + if (write_byte(bus, *buffer++)) + failures++; + } + send_stop(bus); + return failures; +} diff --git a/board/gdsys/common/bb_i2c.h b/board/gdsys/common/bb_i2c.h new file mode 100644 index 0000000..34f4c0f --- /dev/null +++ b/board/gdsys/common/bb_i2c.h @@ -0,0 +1,76 @@ +/* + * (C) Copyright 2012 + * Dirk Eibach, Guntermann & Drunck GmbH, eibach@gdsys.de + * + * based on i2c.h + * (C) Copyright 2001 + * Gerald Van Baren, Custom IDEAS, vanbaren@cideas.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 + * + * The original I2C interface was + * (C) 2000 by Paolo Scaffardi (arsenio@tin.it) + * AIRVENT SAM s.p.a - RIMINI(ITALY) + * but has been changed substantially. + */ + +#ifndef _BB_I2C_H_ +#define _BB_I2C_H_ + +/* + * Probe the given I2C chip address. Returns 0 if a chip responded, + * not 0 on failure. + */ +int bb_i2c_probe(unsigned int bus, uchar chip); + +/* + * Read/Write interface: + * chip: I2C chip address, range 0..127 + * addr: Memory (register) address within the chip + * alen: Number of bytes to use for addr (typically 1, 2 for larger + * memories, 0 for register type devices with only one + * register) + * buffer: Where to read/write the data + * len: How many bytes to read/write + * + * Returns: 0 on success, not 0 on failure + */ +int bb_i2c_read(unsigned int bus, uchar chip, uint addr, int alen, + uchar *buffer, int len); +int bb_i2c_write(unsigned int bus, uchar chip, uint addr, int alen, + uchar *buffer, int len); + +/* + * Utility routines to read/write registers. + */ +static inline u8 bb_i2c_reg_read(unsigned int bus, u8 addr, u8 reg) +{ + u8 buf; + + bb_i2c_read(bus, addr, reg, 1, &buf, 1); + + return buf; +} + +static inline void bb_i2c_reg_write(unsigned int bus, u8 addr, u8 reg, u8 val) +{ + bb_i2c_write(bus, addr, reg, 1, &val, 1); +} + +#endif /* _BB_I2C_H_ */

Hi Dirk!
(Added Heiko as I2C custodian to Cc)
On 22.04.2013 13:16, Dirk Eibach wrote:
This adds an i2c bitbang interface that can coexist with processor i2c.
Signed-off-by: Dirk Eibach eibach@gdsys.de
board/gdsys/common/Makefile | 2 +- board/gdsys/common/bb_i2c.c | 304 +++++++++++++++++++++++++++++++++++++++++++ board/gdsys/common/bb_i2c.h | 76 +++++++++++ 3 files changed, 381 insertions(+), 1 deletion(-) create mode 100644 board/gdsys/common/bb_i2c.c create mode 100644 board/gdsys/common/bb_i2c.h
Just checking: Is it really not possible to use multiple different I2C interfaces (e.g. PPC4xx I2C and GPIO bitbang I2C)? Heiko, whats the current status here?
Thanks, Stefan

Hello Stefan,
Am 23.04.2013 08:45, schrieb Stefan Roese:
Hi Dirk!
(Added Heiko as I2C custodian to Cc)
On 22.04.2013 13:16, Dirk Eibach wrote:
This adds an i2c bitbang interface that can coexist with processor i2c.
Huh... missed this EMail...
Signed-off-by: Dirk Eibach eibach@gdsys.de
board/gdsys/common/Makefile | 2 +- board/gdsys/common/bb_i2c.c | 304 +++++++++++++++++++++++++++++++++++++++++++ board/gdsys/common/bb_i2c.h | 76 +++++++++++ 3 files changed, 381 insertions(+), 1 deletion(-) create mode 100644 board/gdsys/common/bb_i2c.c create mode 100644 board/gdsys/common/bb_i2c.h
Just checking: Is it really not possible to use multiple different I2C interfaces (e.g. PPC4xx I2C and GPIO bitbang I2C)? Heiko, whats the current status here?
If this is needed, we should merge the multibus/multiadapter approach finally to mainline, found here:
http://git.denx.de/?p=u-boot/u-boot-i2c.git;a=shortlog;h=refs/heads/20130416...
Yeah, waiting for such a chance for some years ;-)
I am not happy to have boardspecific approaches here! Dirk, could you give the above sources a try? I must admit that the sources are just rebased without doing big tests on several plattforms ... but the branch compiles clean for arm and powerpc. If it works for you, we can try to bring it in the next merge window in mainline...
- steps to do (for you): - port the ppc4xx i2c driver to the new framework There is an older branch, where I did this for an older version of the multibus/multiadapter approach, see here: http://git.denx.de/?p=u-boot/u-boot-i2c.git;a=shortlog;h=refs/heads/multibus...
It gives you maybe an idea how to do this.
- for adding a soft i2c driver you should do something like:
+#define CONFIG_SYS_I2C_SOFT /* I2C bit-banged */ +#define CONFIG_SYS_I2C_SOFT_SPEED Your speed +#define CONFIG_SYS_I2C_SOFT_SLAVE Your slave addr
+#define I2C_TRISTATE i2c_soft_tristate() +#define I2C_READ i2c_soft_read() +#define I2C_ACTIVE i2c_soft_delay() +#define I2C_SCL(bit) i2c_soft_scl(bit) +#define I2C_SDA(bit) i2c_soft_sda(bit) +#define I2C_DELAY i2c_soft_delay() +#define I2C_INIT i2c_soft_init()
and in your board code define the above functions:
+#if defined(CONFIG_SYS_I2C_SOFT) +#include <i2c.h> + +void i2c_soft_init(void) +{ + printf("init: %d\n", I2C_ADAP_HWNR); +} + +void i2c_soft_active(void) +{ + printf("active: %d\n", I2C_ADAP_HWNR); +} + +void i2c_soft_tristate(void) +{ + printf("tristate: %d\n", I2C_ADAP_HWNR); +} + +int i2c_soft_read(void) +{ + return 1; +} + +void i2c_soft_sda(int bit) +{ + printf("sda: %d\n", I2C_ADAP_HWNR); +} + +void i2c_soft_scl(int bit) +{ + printf("scl: %d\n", I2C_ADAP_HWNR); +} + +void i2c_soft_delay(void) +{ + printf("delay: %d\n", I2C_ADAP_HWNR); +} + +#endif
You can have more than one soft i2c adapter by defining the defines I2C_SOFT_DECLARATIONS2, I2C_SOFT_DECLARATIONS3 ... and switch between them by interpreting the I2C_ADAP_HWNR in the above functions ...
bye, Heiko

Hi, experts: I found an example for burst transaction test in examples\standalone directory. I think it's very useful. But it's for power pc. Is there an example on ARM platform?
Best wishes,

Dear TigerLiu@viatech.com.cn,
In message FE7ADED5C2218B4786C09CD97DC4C49F87C8CC@exchbj02.viatech.com.bj you wrote:
I found an example for burst transaction test in examples\standalone directory. I think it's very useful.
Actually it is not. If you want to stress test a board, boot Linux with root file system mounted over NFS, and compile a Linux kernel natively on the target.
But it's for power pc. Is there an example on ARM platform?
None that I know of. But following the example should be relatively straight-forward. Just don't expect any useful results.
Best regards,
Wolfgang Denk

Signed-off-by: Dirk Eibach dirk.eibach@gdsys.cc Cc: Heiko Schocher hs@denx.de Cc: Stefan Roese sr@denx.de --- drivers/i2c/Makefile | 2 +- drivers/i2c/ppc4xx_i2c.c | 193 +++++++++++++++++++++++----------------------- 2 files changed, 97 insertions(+), 98 deletions(-)
diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile index 564d061..0298e3e 100644 --- a/drivers/i2c/Makefile +++ b/drivers/i2c/Makefile @@ -36,7 +36,6 @@ COBJS-$(CONFIG_DRIVER_OMAP1510_I2C) += omap1510_i2c.o COBJS-$(CONFIG_DRIVER_OMAP24XX_I2C) += omap24xx_i2c.o COBJS-$(CONFIG_DRIVER_OMAP34XX_I2C) += omap24xx_i2c.o COBJS-$(CONFIG_PCA9564_I2C) += pca9564_i2c.o -COBJS-$(CONFIG_PPC4XX_I2C) += ppc4xx_i2c.o COBJS-$(CONFIG_DRIVER_S3C24X0_I2C) += s3c24x0_i2c.o COBJS-$(CONFIG_S3C44B0_I2C) += s3c44b0_i2c.o COBJS-$(CONFIG_TSI108_I2C) += tsi108_i2c.o @@ -45,6 +44,7 @@ COBJS-$(CONFIG_SH_I2C) += sh_i2c.o COBJS-$(CONFIG_SH_SH7734_I2C) += sh_sh7734_i2c.o COBJS-$(CONFIG_SYS_I2C) += i2c_core.o COBJS-$(CONFIG_SYS_I2C_FSL) += fsl_i2c.o +COBJS-$(CONFIG_SYS_I2C_PPC4XX) += ppc4xx_i2c.o COBJS-$(CONFIG_SYS_I2C_SOFT) += soft_i2c.o COBJS-$(CONFIG_SYS_I2C_TEGRA) += tegra_i2c.o
diff --git a/drivers/i2c/ppc4xx_i2c.c b/drivers/i2c/ppc4xx_i2c.c index 53fedd5..c924874 100644 --- a/drivers/i2c/ppc4xx_i2c.c +++ b/drivers/i2c/ppc4xx_i2c.c @@ -32,27 +32,29 @@ #include <i2c.h> #include <asm/io.h>
-#ifdef CONFIG_HARD_I2C - DECLARE_GLOBAL_DATA_PTR;
-#if defined(CONFIG_I2C_MULTI_BUS) -/* - * Initialize the bus pointer to whatever one the SPD EEPROM is on. - * Default is bus 0. This is necessary because the DDR initialization - * runs from ROM, and we can't switch buses because we can't modify - * the global variables. - */ -#ifndef CONFIG_SYS_SPD_BUS_NUM -#define CONFIG_SYS_SPD_BUS_NUM 0 +static inline struct ppc4xx_i2c *ppc4xx_get_i2c(int hwadapnr) +{ + unsigned long base; + +#if defined(CONFIG_440EP) || defined(CONFIG_440GR) || \ + defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \ + defined(CONFIG_460EX) || defined(CONFIG_460GT) + base = CONFIG_SYS_PERIPHERAL_BASE + 0x00000700 + (hwadapnr * 0x100); +#elif defined(CONFIG_440) || defined(CONFIG_405EX) +/* all remaining 440 variants */ + base = CONFIG_SYS_PERIPHERAL_BASE + 0x00000400 + (hwadapnr * 0x100); +#else +/* all 405 variants */ + base = 0xEF600500 + (hwadapnr * 0x100); #endif -static unsigned int i2c_bus_num __attribute__ ((section (".data"))) = - CONFIG_SYS_SPD_BUS_NUM; -#endif /* CONFIG_I2C_MULTI_BUS */ + return (struct ppc4xx_i2c *)base; +}
-static void _i2c_bus_reset(void) +static void _i2c_bus_reset(struct i2c_adapter *adap) { - struct ppc4xx_i2c *i2c = (struct ppc4xx_i2c *)I2C_BASE_ADDR; + struct ppc4xx_i2c *i2c = ppc4xx_get_i2c(adap->hwadapnr); int i; u8 dc;
@@ -91,11 +93,10 @@ static void _i2c_bus_reset(void) out_8(&i2c->xtcntlss, 0); }
-void i2c_init(int speed, int slaveaddr) +static void ppc4xx_i2c_init(struct i2c_adapter *adap, int speed, int slaveaddr) { - struct ppc4xx_i2c *i2c; + struct ppc4xx_i2c *i2c = ppc4xx_get_i2c(adap->hwadapnr); int val, divisor; - int bus;
#ifdef CONFIG_SYS_I2C_INIT_BOARD /* @@ -106,67 +107,57 @@ void i2c_init(int speed, int slaveaddr) i2c_init_board(); #endif
- for (bus = 0; bus < CONFIG_SYS_MAX_I2C_BUS; bus++) { - I2C_SET_BUS(bus); - - /* Set i2c pointer after calling I2C_SET_BUS() */ - i2c = (struct ppc4xx_i2c *)I2C_BASE_ADDR; - - /* Handle possible failed I2C state */ - /* FIXME: put this into i2c_init_board()? */ - _i2c_bus_reset(); + /* Handle possible failed I2C state */ + /* FIXME: put this into i2c_init_board()? */ + _i2c_bus_reset(adap);
- /* clear lo master address */ - out_8(&i2c->lmadr, 0); + /* clear lo master address */ + out_8(&i2c->lmadr, 0);
- /* clear hi master address */ - out_8(&i2c->hmadr, 0); - - /* clear lo slave address */ - out_8(&i2c->lsadr, 0); + /* clear hi master address */ + out_8(&i2c->hmadr, 0);
- /* clear hi slave address */ - out_8(&i2c->hsadr, 0); + /* clear lo slave address */ + out_8(&i2c->lsadr, 0);
- /* Clock divide Register */ - /* set divisor according to freq_opb */ - divisor = (get_OPB_freq() - 1) / 10000000; - if (divisor == 0) - divisor = 1; - out_8(&i2c->clkdiv, divisor); + /* clear hi slave address */ + out_8(&i2c->hsadr, 0);
- /* no interrupts */ - out_8(&i2c->intrmsk, 0); + /* Clock divide Register */ + /* set divisor according to freq_opb */ + divisor = (get_OPB_freq() - 1) / 10000000; + if (divisor == 0) + divisor = 1; + out_8(&i2c->clkdiv, divisor);
- /* clear transfer count */ - out_8(&i2c->xfrcnt, 0); + /* no interrupts */ + out_8(&i2c->intrmsk, 0);
- /* clear extended control & stat */ - /* write 1 in SRC SRS SWC SWS to clear these fields */ - out_8(&i2c->xtcntlss, 0xF0); + /* clear transfer count */ + out_8(&i2c->xfrcnt, 0);
- /* Mode Control Register - Flush Slave/Master data buffer */ - out_8(&i2c->mdcntl, IIC_MDCNTL_FSDB | IIC_MDCNTL_FMDB); + /* clear extended control & stat */ + /* write 1 in SRC SRS SWC SWS to clear these fields */ + out_8(&i2c->xtcntlss, 0xF0);
- val = in_8(&i2c->mdcntl); + /* Mode Control Register + Flush Slave/Master data buffer */ + out_8(&i2c->mdcntl, IIC_MDCNTL_FSDB | IIC_MDCNTL_FMDB);
- /* Ignore General Call, slave transfers are ignored, - * disable interrupts, exit unknown bus state, enable hold - * SCL 100kHz normaly or FastMode for 400kHz and above - */ + val = in_8(&i2c->mdcntl);
- val |= IIC_MDCNTL_EUBS | IIC_MDCNTL_HSCL; - if (speed >= 400000) - val |= IIC_MDCNTL_FSM; - out_8(&i2c->mdcntl, val); + /* Ignore General Call, slave transfers are ignored, + * disable interrupts, exit unknown bus state, enable hold + * SCL 100kHz normaly or FastMode for 400kHz and above + */
- /* clear control reg */ - out_8(&i2c->cntl, 0x00); - } + val |= IIC_MDCNTL_EUBS | IIC_MDCNTL_HSCL; + if (speed >= 400000) + val |= IIC_MDCNTL_FSM; + out_8(&i2c->mdcntl, val);
- /* set to SPD bus as default bus upon powerup */ - I2C_SET_BUS(CONFIG_SYS_SPD_BUS_NUM); + /* clear control reg */ + out_8(&i2c->cntl, 0x00); }
/* @@ -194,14 +185,15 @@ void i2c_init(int speed, int slaveaddr) * * It does not check XFRCNT. */ -static int i2c_transfer(unsigned char cmd_type, +static int _i2c_transfer(struct i2c_adapter *adap, + unsigned char cmd_type, unsigned char chip, unsigned char addr[], unsigned char addr_len, unsigned char data[], unsigned short data_len) { - struct ppc4xx_i2c *i2c = (struct ppc4xx_i2c *)I2C_BASE_ADDR; + struct ppc4xx_i2c *i2c = ppc4xx_get_i2c(adap->hwadapnr); u8 *ptr; int reading; int tran, cnt; @@ -345,7 +337,7 @@ static int i2c_transfer(unsigned char cmd_type, return result; }
-int i2c_probe(uchar chip) +static int ppc4xx_i2c_probe(struct i2c_adapter *adap, uchar chip) { uchar buf[1];
@@ -356,11 +348,11 @@ int i2c_probe(uchar chip) * address was <ACK>ed (i.e. there was a chip at that address which * drove the data line low). */ - return (i2c_transfer(1, chip << 1, 0, 0, buf, 1) != 0); + return (_i2c_transfer(adap, 1, chip << 1, 0, 0, buf, 1) != 0); }
-static int ppc4xx_i2c_transfer(uchar chip, uint addr, int alen, uchar *buffer, - int len, int read) +static int ppc4xx_i2c_transfer(struct i2c_adapter *adap, uchar chip, uint addr, + int alen, uchar *buffer, int len, int read) { uchar xaddr[4]; int ret; @@ -394,43 +386,50 @@ static int ppc4xx_i2c_transfer(uchar chip, uint addr, int alen, uchar *buffer, chip |= ((addr >> (alen * 8)) & CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW); #endif - if ((ret = i2c_transfer(read, chip << 1, &xaddr[4 - alen], alen, - buffer, len)) != 0) { + ret = _i2c_transfer(adap, read, chip << 1, &xaddr[4 - alen], alen, + buffer, len); + if (ret) { printf("I2C %s: failed %d\n", read ? "read" : "write", ret); - return 1; }
return 0; }
-int i2c_read(uchar chip, uint addr, int alen, uchar * buffer, int len) +static int ppc4xx_i2c_read(struct i2c_adapter *adap, uchar chip, uint addr, + int alen, uchar *buffer, int len) { - return ppc4xx_i2c_transfer(chip, addr, alen, buffer, len, 1); + return ppc4xx_i2c_transfer(adap, chip, addr, alen, buffer, len, 1); }
-int i2c_write(uchar chip, uint addr, int alen, uchar * buffer, int len) +static int ppc4xx_i2c_write(struct i2c_adapter *adap, uchar chip, uint addr, + int alen, uchar *buffer, int len) { - return ppc4xx_i2c_transfer(chip, addr, alen, buffer, len, 0); + return ppc4xx_i2c_transfer(adap, chip, addr, alen, buffer, len, 0); }
-#if defined(CONFIG_I2C_MULTI_BUS) -/* - * Functions for multiple I2C bus handling - */ -unsigned int i2c_get_bus_num(void) +static unsigned int ppc4xx_i2c_set_bus_speed(struct i2c_adapter *adap, + unsigned int speed) { - return i2c_bus_num; -} - -int i2c_set_bus_num(unsigned int bus) -{ - if (bus >= CONFIG_SYS_MAX_I2C_BUS) + if (speed != adap->speed) return -1; - - i2c_bus_num = bus; - - return 0; + return speed; } -#endif /* CONFIG_I2C_MULTI_BUS */ -#endif /* CONFIG_HARD_I2C */ + +/* + * Register ppc4xx i2c adapters + */ +#ifdef CONFIG_SYS_I2C_PPC4XX_CH0 +U_BOOT_I2C_ADAP_COMPLETE(ppc4xx_0, ppc4xx_i2c_init, ppc4xx_i2c_probe, + ppc4xx_i2c_read, ppc4xx_i2c_write, + ppc4xx_i2c_set_bus_speed, + CONFIG_SYS_I2C_PPC4XX_SPEED_0, + CONFIG_SYS_I2C_PPC4XX_SLAVE_0, 0) +#endif +#ifdef CONFIG_SYS_I2C_PPC4XX_CH1 +U_BOOT_I2C_ADAP_COMPLETE(ppc4xx_1, ppc4xx_i2c_init, ppc4xx_i2c_probe, + ppc4xx_i2c_read, ppc4xx_i2c_write, + ppc4xx_i2c_set_bus_speed, + CONFIG_SYS_I2C_PPC4XX_SPEED_1, + CONFIG_SYS_I2C_PPC4XX_SLAVE_1, 1) +#endif

Hello Dirk,
On 24.04.2013 13:43, Dirk Eibach wrote:
Signed-off-by: Dirk Eibach dirk.eibach@gdsys.cc Cc: Heiko Schocher hs@denx.de Cc: Stefan Roese sr@denx.de
drivers/i2c/Makefile | 2 +- drivers/i2c/ppc4xx_i2c.c | 193 +++++++++++++++++++++++----------------------- 2 files changed, 97 insertions(+), 98 deletions(-)
Did you tried this patch with the mutlibus/multiadapter framework?
When switching one i2c driver to this new Framework, you must adapt all config files, which use this driver ... Sorry, some stupid work, but it must be done, without this I will bet, MAKEALL fails ...
[...]
diff --git a/drivers/i2c/ppc4xx_i2c.c b/drivers/i2c/ppc4xx_i2c.c index 53fedd5..c924874 100644 --- a/drivers/i2c/ppc4xx_i2c.c +++ b/drivers/i2c/ppc4xx_i2c.c
[...]
+#ifdef CONFIG_SYS_I2C_PPC4XX_CH0
You introduce here new defines, please document them in the README, thanks!
+U_BOOT_I2C_ADAP_COMPLETE(ppc4xx_0, ppc4xx_i2c_init, ppc4xx_i2c_probe,
ppc4xx_i2c_read, ppc4xx_i2c_write,
ppc4xx_i2c_set_bus_speed,
CONFIG_SYS_I2C_PPC4XX_SPEED_0,
CONFIG_SYS_I2C_PPC4XX_SLAVE_0, 0)
+#endif +#ifdef CONFIG_SYS_I2C_PPC4XX_CH1 +U_BOOT_I2C_ADAP_COMPLETE(ppc4xx_1, ppc4xx_i2c_init, ppc4xx_i2c_probe,
ppc4xx_i2c_read, ppc4xx_i2c_write,
ppc4xx_i2c_set_bus_speed,
CONFIG_SYS_I2C_PPC4XX_SPEED_1,
CONFIG_SYS_I2C_PPC4XX_SLAVE_1, 1)
+#endif
beside of this, your patch looks good ...
bye, Heiko

Hello Heiko,
On 24.04.2013 13:43, Dirk Eibach wrote:
Signed-off-by: Dirk Eibach dirk.eibach@gdsys.cc Cc: Heiko Schocher hs@denx.de Cc: Stefan Roese sr@denx.de
drivers/i2c/Makefile | 2 +- drivers/i2c/ppc4xx_i2c.c | 193 +++++++++++++++++++++++----------------------- 2 files changed, 97 insertions(+), 98 deletions(-)
Did you tried this patch with the mutlibus/multiadapter framework?
sure. This RFC is based on 20130416_multibus_v2.
When switching one i2c driver to this new Framework, you must adapt all config files, which use this driver ... Sorry, some stupid work, but it must be done, without this I will bet, MAKEALL fails ...
Certainly. But before starting this, I wanted to make sure, that the basic implementation is allright.
[...]
diff --git a/drivers/i2c/ppc4xx_i2c.c b/drivers/i2c/ppc4xx_i2c.c index 53fedd5..c924874 100644 --- a/drivers/i2c/ppc4xx_i2c.c +++ b/drivers/i2c/ppc4xx_i2c.c
[...]
+#ifdef CONFIG_SYS_I2C_PPC4XX_CH0
You introduce here new defines, please document them in the README, thanks!
OK.
+U_BOOT_I2C_ADAP_COMPLETE(ppc4xx_0, ppc4xx_i2c_init, ppc4xx_i2c_probe,
ppc4xx_i2c_read, ppc4xx_i2c_write,
ppc4xx_i2c_set_bus_speed,
CONFIG_SYS_I2C_PPC4XX_SPEED_0,
CONFIG_SYS_I2C_PPC4XX_SLAVE_0, 0)
+#endif +#ifdef CONFIG_SYS_I2C_PPC4XX_CH1 +U_BOOT_I2C_ADAP_COMPLETE(ppc4xx_1, ppc4xx_i2c_init, ppc4xx_i2c_probe,
ppc4xx_i2c_read, ppc4xx_i2c_write,
ppc4xx_i2c_set_bus_speed,
CONFIG_SYS_I2C_PPC4XX_SPEED_1,
CONFIG_SYS_I2C_PPC4XX_SLAVE_1, 1)
+#endif
beside of this, your patch looks good ...
Fine, so I will start adapting all dependent boards. Should the patch be based on 20130416_multibus_v2 or should I post a series based on v2013.04 that includes the 20130416_multibus_v2 changes?
Cheers Dirk

Hello Dirk,
On 24.04.2013 15:00, Dirk Eibach wrote:
Hello Heiko,
On 24.04.2013 13:43, Dirk Eibach wrote:
Signed-off-by: Dirk Eibach dirk.eibach@gdsys.cc Cc: Heiko Schocher hs@denx.de Cc: Stefan Roese sr@denx.de
drivers/i2c/Makefile | 2 +- drivers/i2c/ppc4xx_i2c.c | 193 +++++++++++++++++++++++----------------------- 2 files changed, 97 insertions(+), 98 deletions(-)
Did you tried this patch with the mutlibus/multiadapter framework?
sure. This RFC is based on 20130416_multibus_v2.
Great! :-)
Also with soft_i2c driver in use?
When switching one i2c driver to this new Framework, you must adapt all config files, which use this driver ... Sorry, some stupid work, but it must be done, without this I will bet, MAKEALL fails ...
Certainly. But before starting this, I wanted to make sure, that the basic implementation is allright.
Yep, looks fine too me.
[...]
diff --git a/drivers/i2c/ppc4xx_i2c.c b/drivers/i2c/ppc4xx_i2c.c index 53fedd5..c924874 100644 --- a/drivers/i2c/ppc4xx_i2c.c +++ b/drivers/i2c/ppc4xx_i2c.c
[...]
+#ifdef CONFIG_SYS_I2C_PPC4XX_CH0
You introduce here new defines, please document them in the README, thanks!
OK.
Thanks!
+U_BOOT_I2C_ADAP_COMPLETE(ppc4xx_0, ppc4xx_i2c_init, ppc4xx_i2c_probe,
ppc4xx_i2c_read, ppc4xx_i2c_write,
ppc4xx_i2c_set_bus_speed,
CONFIG_SYS_I2C_PPC4XX_SPEED_0,
CONFIG_SYS_I2C_PPC4XX_SLAVE_0, 0)
+#endif +#ifdef CONFIG_SYS_I2C_PPC4XX_CH1 +U_BOOT_I2C_ADAP_COMPLETE(ppc4xx_1, ppc4xx_i2c_init, ppc4xx_i2c_probe,
ppc4xx_i2c_read, ppc4xx_i2c_write,
ppc4xx_i2c_set_bus_speed,
CONFIG_SYS_I2C_PPC4XX_SPEED_1,
CONFIG_SYS_I2C_PPC4XX_SLAVE_1, 1)
+#endif
beside of this, your patch looks good ...
Fine, so I will start adapting all dependent boards. Should the patch be based on 20130416_multibus_v2 or should I post a series based on v2013.04 that includes the 20130416_multibus_v2 changes?
Against 20130416_multibus_v2 and if the merge window opens I post this patch with the other patches for this new i2c framework on the ML.
bye, Heiko

Hi Heiko,
On 24.04.2013 15:04, Heiko Schocher wrote:
Fine, so I will start adapting all dependent boards. Should the patch be based on 20130416_multibus_v2 or should I post a series based on v2013.04 that includes the 20130416_multibus_v2 changes?
Against 20130416_multibus_v2 and if the merge window opens I post this patch with the other patches for this new i2c framework on the ML.
The merge window is already open. :)
Thanks, Stefan

Hello Heiko,
On 24.04.2013 15:00, Dirk Eibach wrote:
Hello Heiko,
On 24.04.2013 13:43, Dirk Eibach wrote:
Signed-off-by: Dirk Eibach dirk.eibach@gdsys.cc Cc: Heiko Schocher hs@denx.de Cc: Stefan Roese sr@denx.de
drivers/i2c/Makefile | 2 +- drivers/i2c/ppc4xx_i2c.c | 193 +++++++++++++++++++++++----------------------- 2 files changed, 97 insertions(+), 98 deletions(-)
Did you tried this patch with the mutlibus/multiadapter framework?
sure. This RFC is based on 20130416_multibus_v2.
Great! :-)
Also with soft_i2c driver in use?
nearly forgot about this one. Yeah, one ppc4xx hardware bus and four soft busses playing nicely together.
Cheers Dirk

Hello Dirk,
On 25.04.2013 15:21, Dirk Eibach wrote:
Hello Heiko,
On 24.04.2013 15:00, Dirk Eibach wrote:
Hello Heiko,
On 24.04.2013 13:43, Dirk Eibach wrote:
Signed-off-by: Dirk Eibach dirk.eibach@gdsys.cc Cc: Heiko Schocher hs@denx.de Cc: Stefan Roese sr@denx.de
drivers/i2c/Makefile | 2 +- drivers/i2c/ppc4xx_i2c.c | 193 +++++++++++++++++++++++----------------------- 2 files changed, 97 insertions(+), 98 deletions(-)
Did you tried this patch with the mutlibus/multiadapter framework?
sure. This RFC is based on 20130416_multibus_v2.
Great! :-)
Also with soft_i2c driver in use?
nearly forgot about this one. Yeah, one ppc4xx hardware bus and four soft busses playing nicely together.
Great news ... so, as the merge window is open, I must look for some time, to post this new framework ;-)
bye, Heiko

Signed-off-by: Dirk Eibach eibach@gdsys.de --- board/gdsys/405ep/405ep.c | 12 ++++---- board/gdsys/common/osd.c | 70 +++++++++++++++++++++------------------------ 2 files changed, 38 insertions(+), 44 deletions(-)
diff --git a/board/gdsys/405ep/405ep.c b/board/gdsys/405ep/405ep.c index 6221171..e5fbd2e 100644 --- a/board/gdsys/405ep/405ep.c +++ b/board/gdsys/405ep/405ep.c @@ -106,22 +106,20 @@ int board_early_init_r(void) gd405ep_set_fpga_reset(0);
for (k = 0; k < CONFIG_SYS_FPGA_COUNT; ++k) { - struct ihs_fpga *fpga = - (struct ihs_fpga *)CONFIG_SYS_FPGA_BASE(k); #ifdef CONFIG_SYS_FPGA_NO_RFL_HI - u16 *reflection_target = &fpga->reflection_low; + u16 reflection_target = REG(reflection_low); #else - u16 *reflection_target = &fpga->reflection_high; + u16 reflection_target = REG(reflection_high); #endif /* * wait for fpga out of reset */ ctr = 0; while (1) { - out_le16(&fpga->reflection_low, - REFLECTION_TESTPATTERN); + fpga_set_reg(k, REG(reflection_low), + REFLECTION_TESTPATTERN);
- if (in_le16(reflection_target) == + if (fpga_get_reg(k, reflection_target) == REFLECTION_TESTPATTERN_INV) break;
diff --git a/board/gdsys/common/osd.c b/board/gdsys/common/osd.c index a192c98..81c8136 100644 --- a/board/gdsys/common/osd.c +++ b/board/gdsys/common/osd.c @@ -22,7 +22,7 @@ */
#include <common.h> -#include <i2c.h> +#include "bb_i2c.h" #include <asm/io.h>
#include <gdsys_fpga.h> @@ -67,37 +67,34 @@ enum { CH7301_DSP = 0x56, /* DVI Sync polarity Register */ };
+unsigned int max_osd_screen = CONFIG_SYS_OSD_SCREENS - 1; + #if defined(CONFIG_SYS_ICS8N3QV01) || defined(CONFIG_SYS_SIL1178) static void fpga_iic_write(unsigned screen, u8 slave, u8 reg, u8 data) { - struct ihs_fpga *fpga = (struct ihs_fpga *)CONFIG_SYS_FPGA_BASE(screen); - struct ihs_i2c *i2c = &fpga->i2c; - - while (in_le16(&fpga->extended_interrupt) & (1 << 12)) + while (fpga_get_reg(screen, REG(extended_interrupt)) & (1 << 12)) ; - out_le16(&i2c->write_mailbox_ext, reg | (data << 8)); - out_le16(&i2c->write_mailbox, 0xc400 | (slave << 1)); + fpga_set_reg(screen, REG(i2c.write_mailbox_ext), reg | (data << 8)); + fpga_set_reg(screen, REG(i2c.write_mailbox), 0xc400 | (slave << 1)); }
static u8 fpga_iic_read(unsigned screen, u8 slave, u8 reg) { - struct ihs_fpga *fpga = (struct ihs_fpga *)CONFIG_SYS_FPGA_BASE(screen); - struct ihs_i2c *i2c = &fpga->i2c; unsigned int ctr = 0;
- while (in_le16(&fpga->extended_interrupt) & (1 << 12)) + while (fpga_get_reg(screen, REG(extended_interrupt)) & (1 << 12)) ; - out_le16(&fpga->extended_interrupt, 1 << 14); - out_le16(&i2c->write_mailbox_ext, reg); - out_le16(&i2c->write_mailbox, 0xc000 | (slave << 1)); - while (!(in_le16(&fpga->extended_interrupt) & (1 << 14))) { + fpga_set_reg(screen, REG(extended_interrupt), 1 << 14); + fpga_set_reg(screen, REG(i2c.write_mailbox_ext), reg); + fpga_set_reg(screen, REG(i2c.write_mailbox), 0xc000 | (slave << 1)); + while (!(fpga_get_reg(screen, REG(extended_interrupt)) & (1 << 14))) { udelay(100000); if (ctr++ > 5) { printf("iic receive timeout\n"); break; } } - return in_le16(&i2c->read_mailbox_ext) >> 8; + return fpga_get_reg(screen, REG(i2c.read_mailbox_ext)) >> 8; } #endif
@@ -129,7 +126,6 @@ static void mpc92469ac_calc_parameters(unsigned int fout,
static void mpc92469ac_set(unsigned screen, unsigned int fout) { - struct ihs_fpga *fpga = (struct ihs_fpga *)CONFIG_SYS_FPGA_BASE(screen); unsigned int n; unsigned int m; unsigned int bitval = 0; @@ -150,7 +146,7 @@ static void mpc92469ac_set(unsigned screen, unsigned int fout) break; }
- out_le16(&fpga->mpc3w_control, (bitval << 9) | m); + fpga_set_reg(screen, REG(mpc3w_control), (bitval << 9) | m); } #endif
@@ -265,14 +261,13 @@ static void ics8n3qv01_set(unsigned screen, unsigned int fout) static int osd_write_videomem(unsigned screen, unsigned offset, u16 *data, size_t charcount) { - struct ihs_fpga *fpga = - (struct ihs_fpga *) CONFIG_SYS_FPGA_BASE(screen); unsigned int k;
for (k = 0; k < charcount; ++k) { if (offset + k >= BUFSIZE) return -1; - out_le16(&fpga->videomem + offset + k, data[k]); + fpga_set_reg(screen, REG(videomem) + sizeof(u16) * (offset + k), + data[k]); }
return charcount; @@ -282,7 +277,7 @@ static int osd_print(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { unsigned screen;
- for (screen = 0; screen < CONFIG_SYS_OSD_SCREENS; ++screen) { + for (screen = 0; screen <= max_osd_screen; ++screen) { unsigned x; unsigned y; unsigned charcount; @@ -318,10 +313,8 @@ static int osd_print(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
int osd_probe(unsigned screen) { - struct ihs_fpga *fpga = (struct ihs_fpga *)CONFIG_SYS_FPGA_BASE(screen); - struct ihs_osd *osd = &fpga->osd; - u16 version = in_le16(&osd->version); - u16 features = in_le16(&osd->features); + u16 version = fpga_get_reg(screen, REG(osd.version)); + u16 features = fpga_get_reg(screen, REG(osd.features)); unsigned width; unsigned height; u8 value; @@ -333,16 +326,16 @@ int osd_probe(unsigned screen) screen, version/100, version%100, width, height);
#ifdef CONFIG_SYS_CH7301 - value = i2c_reg_read(CH7301_I2C_ADDR, CH7301_DID); + value = bb_i2c_reg_read(screen, CH7301_I2C_ADDR, CH7301_DID); if (value != 0x17) { printf(" Probing CH7301 failed, DID %02x\n", value); return -1; } - i2c_reg_write(CH7301_I2C_ADDR, CH7301_TPCP, 0x08); - i2c_reg_write(CH7301_I2C_ADDR, CH7301_TPD, 0x16); - i2c_reg_write(CH7301_I2C_ADDR, CH7301_TPF, 0x60); - i2c_reg_write(CH7301_I2C_ADDR, CH7301_DC, 0x09); - i2c_reg_write(CH7301_I2C_ADDR, CH7301_PM, 0xc0); + bb_i2c_reg_write(screen, CH7301_I2C_ADDR, CH7301_TPCP, 0x08); + bb_i2c_reg_write(screen, CH7301_I2C_ADDR, CH7301_TPD, 0x16); + bb_i2c_reg_write(screen, CH7301_I2C_ADDR, CH7301_TPF, 0x60); + bb_i2c_reg_write(screen, CH7301_I2C_ADDR, CH7301_DC, 0x09); + bb_i2c_reg_write(screen, CH7301_I2C_ADDR, CH7301_PM, 0xc0); #endif
#ifdef CONFIG_SYS_MPC92469AC @@ -372,12 +365,15 @@ int osd_probe(unsigned screen) fpga_iic_write(screen, SIL1178_MASTER_I2C_ADDRESS, 0x08, 0x37); #endif
- out_le16(&fpga->videocontrol, 0x0002); - out_le16(&osd->control, 0x0049); + fpga_set_reg(screen, REG(videocontrol), 0x0002); + fpga_set_reg(screen, REG(osd.control), 0x0049); + + fpga_set_reg(screen, REG(osd.xy_size), ((32 - 1) << 8) | (16 - 1)); + fpga_set_reg(screen, REG(osd.x_pos), 0x007f); + fpga_set_reg(screen, REG(osd.y_pos), 0x005f);
- out_le16(&osd->xy_size, ((32 - 1) << 8) | (16 - 1)); - out_le16(&osd->x_pos, 0x007f); - out_le16(&osd->y_pos, 0x005f); + if (screen > max_osd_screen) + max_osd_screen = screen;
return 0; } @@ -386,7 +382,7 @@ int osd_write(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { unsigned screen;
- for (screen = 0; screen < CONFIG_SYS_OSD_SCREENS; ++screen) { + for (screen = 0; screen <= max_osd_screen; ++screen) { unsigned x; unsigned y; unsigned k;

Signed-off-by: Dirk Eibach eibach@gdsys.de --- board/gdsys/405ep/iocon.c | 253 ++++++++++++++++++++++++++++++++++++++------- include/configs/iocon.h | 37 ++++--- include/gdsys_fpga.h | 15 ++- 3 files changed, 248 insertions(+), 57 deletions(-)
diff --git a/board/gdsys/405ep/iocon.c b/board/gdsys/405ep/iocon.c index 0fc7db2..ece45d6 100644 --- a/board/gdsys/405ep/iocon.c +++ b/board/gdsys/405ep/iocon.c @@ -23,6 +23,7 @@
#include <common.h> #include <command.h> +#include <errno.h> #include <asm/processor.h> #include <asm/io.h> #include <asm/ppc4xx-gpio.h> @@ -31,6 +32,13 @@ #include <gdsys_fpga.h>
#include "../common/osd.h" +#include "../common/mclink.h" + +#include <i2c.h> +#include <pca953x.h> +#include <pca9698.h> + +DECLARE_GLOBAL_DATA_PTR;
#define LATCH0_BASE (CONFIG_SYS_LATCH_BASE) #define LATCH1_BASE (CONFIG_SYS_LATCH_BASE + 0x100) @@ -47,11 +55,20 @@ enum { HWVER_100 = 0, HWVER_104 = 1, HWVER_110 = 2, + HWVER_120 = 3, + HWVER_200 = 4, + HWVER_210 = 5, +}; + +enum { + FPGA_HWVER_200 = 0, + FPGA_HWVER_210 = 1, };
enum { COMPRESSION_NONE = 0, - COMPRESSION_TYPE1_DELTA, + COMPRESSION_TYPE1_DELTA = 1, + COMPRESSION_TYPE1_TYPE2_DELTA = 3, };
enum { @@ -67,8 +84,56 @@ enum {
enum { RAM_DDR2_32 = 0, + RAM_DDR3_32 = 1, +}; + +enum { + MCFPGA_DONE = 1 << 0, + MCFPGA_INIT_N = 1 << 1, + MCFPGA_PROGRAM_N = 1 << 2, + MCFPGA_UPDATE_ENABLE_N = 1 << 3, + MCFPGA_RESET_N = 1 << 4, };
+unsigned int mclink_fpgacount; + +void fpga_set_reg(unsigned int fpga, u16 reg, u16 data) +{ + int res; + struct ihs_fpga *fpga_0 = (struct ihs_fpga *)CONFIG_SYS_FPGA_BASE(0); + + switch (fpga) { + case 0: + out_le16((u16 *)fpga_0 + reg / sizeof(u16), data); + break; + default: + res = mclink_send(fpga - 1, reg, data); + if (res < 0) + printf("mclink_send reg %02x data %04x returned %d\n", + reg, data, res); + break; + } +} + +u16 fpga_get_reg(unsigned int fpga, u16 reg) +{ + int res; + u16 data; + struct ihs_fpga *fpga_0 = (struct ihs_fpga *)CONFIG_SYS_FPGA_BASE(0); + + switch (fpga) { + case 0: + return in_le16((u16 *)fpga_0 + reg / sizeof(u16)); + default: + if (fpga > mclink_fpgacount) + return -EINVAL; + res = mclink_receive(fpga - 1, reg, &data); + if (res < 0) + printf("mclink_receive returned %d\n", res); + return data; + } +} + /* * Check Board Identity: */ @@ -90,12 +155,11 @@ int checkboard(void) return 0; }
-static void print_fpga_info(void) +static void print_fpga_info(unsigned int fpga) { - struct ihs_fpga *fpga = (struct ihs_fpga *) CONFIG_SYS_FPGA_BASE(0); - u16 versions = in_le16(&fpga->versions); - u16 fpga_version = in_le16(&fpga->fpga_version); - u16 fpga_features = in_le16(&fpga->fpga_features); + u16 versions = fpga_get_reg(fpga, REG(versions)); + u16 fpga_version = fpga_get_reg(fpga, REG(fpga_version)); + u16 fpga_features = fpga_get_reg(fpga, REG(fpga_features)); unsigned unit_type; unsigned hardware_version; unsigned feature_compression; @@ -105,9 +169,9 @@ static void print_fpga_info(void) unsigned feature_ramconfig; unsigned feature_carriers; unsigned feature_video_channels; + int legacy = get_fpga_state(0) & FPGA_STATE_PLATFORM;
unit_type = (versions & 0xf000) >> 12; - hardware_version = versions & 0x000f; feature_compression = (fpga_features & 0xe000) >> 13; feature_osd = fpga_features & (1<<11); feature_audio = (fpga_features & 0x0600) >> 9; @@ -116,6 +180,9 @@ static void print_fpga_info(void) feature_carriers = (fpga_features & 0x000c) >> 2; feature_video_channels = fpga_features & 0x0003;
+ if (legacy) + printf("legacy "); + switch (unit_type) { case UNITTYPE_MAIN_USER: printf("Mainchannel"); @@ -130,27 +197,68 @@ static void print_fpga_info(void) break; }
- switch (hardware_version) { - case HWVER_100: - printf(" HW-Ver 1.00\n"); - break; - - case HWVER_104: - printf(" HW-Ver 1.04\n"); - break; - - case HWVER_110: - printf(" HW-Ver 1.10\n"); - break; + if (unit_type == UNITTYPE_MAIN_USER) { + if (legacy) + hardware_version = + (in_le16((void *)LATCH2_BASE)>>8) & 0x0f; + else + hardware_version = + (!!pca9698_get_value(0x20, 24) << 0) + | (!!pca9698_get_value(0x20, 25) << 1) + | (!!pca9698_get_value(0x20, 26) << 2) + | (!!pca9698_get_value(0x20, 27) << 3); + switch (hardware_version) { + case HWVER_100: + printf(" HW-Ver 1.00,"); + break; + + case HWVER_104: + printf(" HW-Ver 1.04,"); + break; + + case HWVER_110: + printf(" HW-Ver 1.10,"); + break; + + case HWVER_120: + printf(" HW-Ver 1.20-1.21,"); + break; + + case HWVER_200: + printf(" HW-Ver 2.00,"); + break; + + case HWVER_210: + printf(" HW-Ver 2.10,"); + break; + + default: + printf(" HW-Ver %d(not supported),", + hardware_version); + break; + } + }
- default: - printf(" HW-Ver %d(not supported)\n", - hardware_version); - break; + if (unit_type == UNITTYPE_VIDEO_USER) { + hardware_version = versions & 0x000f; + switch (hardware_version) { + case FPGA_HWVER_200: + printf(" HW-Ver 2.00,"); + break; + + case FPGA_HWVER_210: + printf(" HW-Ver 2.10,"); + break; + + default: + printf(" HW-Ver %d(not supported),", + hardware_version); + break; + } }
- printf(" FPGA V %d.%02d, features:", - fpga_version / 100, fpga_version % 100); + printf(" FPGA V %d.%02d\n features:", + fpga_version / 100, fpga_version % 100);
switch (feature_compression) { @@ -162,6 +270,10 @@ static void print_fpga_info(void) printf(" type1-deltacompression"); break;
+ case COMPRESSION_TYPE1_TYPE2_DELTA: + printf(" type1-deltacompression, type2-inlinecompression"); + break; + default: printf(" compression %d(not supported)", feature_compression); break; @@ -208,6 +320,10 @@ static void print_fpga_info(void) printf(", RAM 32 bit DDR2"); break;
+ case RAM_DDR3_32: + printf(", RAM 32 bit DDR3"); + break; + default: printf(", RAM %d(not supported)", feature_ramconfig); break; @@ -220,41 +336,94 @@ static void print_fpga_info(void)
int last_stage_init(void) { - print_fpga_info(); + int slaves; + unsigned int k; + unsigned char mclink_controllers[] = { 0x24, 0x25, 0x26 }; + + print_fpga_info(0); + osd_probe(0); + + /* wait for FPGA done */ + for (k = 0; k < ARRAY_SIZE(mclink_controllers); ++k) { + unsigned int ctr = 0; + + if (i2c_probe(mclink_controllers[k])) + continue; + + while (!(pca953x_get_val(mclink_controllers[k]) + & MCFPGA_DONE)) { + udelay(100000); + if (ctr++ > 5) { + printf("no done for mclink_controller %d\n", k); + break; + } + } + } + + /* wait for slave-PLLs to be up and running */ + udelay(500000); + + mclink_fpgacount = CONFIG_SYS_MCLINK_MAX; + slaves = mclink_probe(); + mclink_fpgacount = 0; + + if (slaves <= 0) + return 0; + + mclink_fpgacount = slaves; + + for (k = 1; k <= slaves; ++k) { + print_fpga_info(k); + osd_probe(k); + }
- return osd_probe(0); + return 0; }
/* * provide access to fpga gpios (for I2C bitbang) */ -void fpga_gpio_set(int pin) +void fpga_gpio_set(unsigned int bus, int pin) { - out_le16((void *)(CONFIG_SYS_FPGA0_BASE + 0x18), pin); + fpga_set_reg(bus, REG(gpio.set), pin); }
-void fpga_gpio_clear(int pin) +void fpga_gpio_clear(unsigned int bus, int pin) { - out_le16((void *)(CONFIG_SYS_FPGA0_BASE + 0x16), pin); + fpga_set_reg(bus, REG(gpio.clear), pin); }
-int fpga_gpio_get(int pin) +int fpga_gpio_get(unsigned int bus, int pin) { - return in_le16((void *)(CONFIG_SYS_FPGA0_BASE + 0x14)) & pin; + return fpga_get_reg(bus, REG(gpio.read)) & pin; }
void gd405ep_init(void) { + unsigned int k; + + if (i2c_probe(0x20)) { /* i2c_probe returns 0 on success */ + for (k = 0; k < CONFIG_SYS_FPGA_COUNT; ++k) + gd->fpga_state[k] |= FPGA_STATE_PLATFORM; + } else { + pca9698_direction_output(0x20, 4, 1); + } }
void gd405ep_set_fpga_reset(unsigned state) { - if (state) { - out_le16((void *)LATCH0_BASE, CONFIG_SYS_LATCH0_RESET); - out_le16((void *)LATCH1_BASE, CONFIG_SYS_LATCH1_RESET); + int legacy = get_fpga_state(0) & FPGA_STATE_PLATFORM; + + if (legacy) { + if (state) { + out_le16((void *)LATCH0_BASE, CONFIG_SYS_LATCH0_RESET); + out_le16((void *)LATCH1_BASE, CONFIG_SYS_LATCH1_RESET); + } else { + out_le16((void *)LATCH0_BASE, CONFIG_SYS_LATCH0_BOOT); + out_le16((void *)LATCH1_BASE, CONFIG_SYS_LATCH1_BOOT); + } } else { - out_le16((void *)LATCH0_BASE, CONFIG_SYS_LATCH0_BOOT); - out_le16((void *)LATCH1_BASE, CONFIG_SYS_LATCH1_BOOT); + pca9698_set_value(0x20, 4, state ? 0 : 1); } }
@@ -269,5 +438,11 @@ void gd405ep_setup_hw(void)
int gd405ep_get_fpga_done(unsigned fpga) { - return in_le16((void *)LATCH2_BASE) & CONFIG_SYS_FPGA_DONE(fpga); + int legacy = get_fpga_state(0) & FPGA_STATE_PLATFORM; + + if (legacy) + return in_le16((void *)LATCH2_BASE) + & CONFIG_SYS_FPGA_DONE(fpga); + else + return pca9698_get_value(0x20, 20); } diff --git a/include/configs/iocon.h b/include/configs/iocon.h index 7f8825b..e99efa6 100644 --- a/include/configs/iocon.h +++ b/include/configs/iocon.h @@ -112,28 +112,31 @@ */ #define CONFIG_SYS_I2C_SPEED 400000
-/* enable I2C and select the hardware/software driver */ -#undef CONFIG_HARD_I2C /* I2C with hardware support */ -#define CONFIG_SOFT_I2C 1 /* I2C bit-banged */ - +#define CONFIG_PCA953X /* NXP PCA9554 */ +#define CONFIG_PCA9698 /* NXP PCA9698 */ /* * Software (bit-bang) I2C driver configuration */
#ifndef __ASSEMBLY__ -void fpga_gpio_set(int pin); -void fpga_gpio_clear(int pin); -int fpga_gpio_get(int pin); +void fpga_gpio_set(unsigned int bus, int pin); +void fpga_gpio_clear(unsigned int bus, int pin); +int fpga_gpio_get(unsigned int bus, int pin); #endif
-#define I2C_ACTIVE { } -#define I2C_TRISTATE { } -#define I2C_READ fpga_gpio_get(0x0040) ? 1 : 0 -#define I2C_SDA(bit) if (bit) fpga_gpio_set(0x0040); \ - else fpga_gpio_clear(0x0040) -#define I2C_SCL(bit) if (bit) fpga_gpio_set(0x0020); \ - else fpga_gpio_clear(0x0020) -#define I2C_DELAY udelay(25) /* 1/4 I2C clock duration */ +#define BB_I2C_SOFT_DECLARATIONS(bus) +#define BB_I2C_ACTIVE(bus) { } +#define BB_I2C_TRISTATE(bus) { } +#define BB_I2C_READ(bus) fpga_gpio_get(bus, 0x0040) ? 1 : 0 +#define BB_I2C_SDA(bus, bit) if (bit) \ + fpga_gpio_set(bus, 0x0040); \ + else \ + fpga_gpio_clear(bus, 0x0040) +#define BB_I2C_SCL(bus, bit) if (bit) \ + fpga_gpio_set(bus, 0x0020); \ + else \ + fpga_gpio_clear(bus, 0x0020) +#define BB_I2C_DELAY(bus) udelay(25) /* 1/4 I2C clock duration */
/* * OSD hardware @@ -252,6 +255,8 @@ int fpga_gpio_get(int pin);
#define CONFIG_SYS_FPGA_COUNT 1
+#define CONFIG_SYS_MCLINK_MAX 3 + /* Memory Bank 3 (Latches) initialization */ #define CONFIG_SYS_LATCH_BASE 0x7f200000 #define CONFIG_SYS_EBC_PB3AP 0x02025080 @@ -267,6 +272,6 @@ int fpga_gpio_get(int pin); */ #define CONFIG_SYS_MPC92469AC #define CONFIG_SYS_CH7301 -#define CONFIG_SYS_OSD_SCREENS CONFIG_SYS_FPGA_COUNT +#define CONFIG_SYS_OSD_SCREENS 1
#endif /* __CONFIG_H */ diff --git a/include/gdsys_fpga.h b/include/gdsys_fpga.h index c12a31d..b246f2f 100644 --- a/include/gdsys_fpga.h +++ b/include/gdsys_fpga.h @@ -117,10 +117,21 @@ struct ihs_fpga { u16 mpc3w_control; /* 0x001a */ u16 reserved_1[19]; /* 0x001c */ u16 videocontrol; /* 0x0042 */ - u16 reserved_2[93]; /* 0x0044 */ + u16 reserved_2[14]; /* 0x0044 */ + u16 mc_int; /* 0x0060 */ + u16 mc_int_en; /* 0x0062 */ + u16 mc_status; /* 0x0064 */ + u16 mc_control; /* 0x0066 */ + u16 mc_tx_data; /* 0x0068 */ + u16 mc_tx_address; /* 0x006a */ + u16 mc_tx_cmd; /* 0x006c */ + u16 mc_res; /* 0x006e */ + u16 mc_rx_cmd_status; /* 0x0070 */ + u16 mc_rx_data; /* 0x0072 */ + u16 reserved_3[69]; /* 0x0074 */ u16 reflection_high; /* 0x00fe */ struct ihs_osd osd; /* 0x0100 */ - u16 reserved_3[889]; /* 0x010e */ + u16 reserved_4[889]; /* 0x010e */ u16 videomem; /* 0x0800 */ }; #endif

Signed-off-by: Dirk Eibach eibach@gdsys.de --- board/gdsys/405ep/dlvision-10g.c | 20 ++++++++++++++------ board/gdsys/405ep/io.c | 20 ++++++++++++++------ board/gdsys/405ep/neo.c | 17 +++++++++++++---- board/gdsys/405ex/405ex.c | 14 ++++++-------- board/gdsys/405ex/io64.c | 38 ++++++++++++++++++++++---------------- 5 files changed, 69 insertions(+), 40 deletions(-)
diff --git a/board/gdsys/405ep/dlvision-10g.c b/board/gdsys/405ep/dlvision-10g.c index 644493b..4d1a02e 100644 --- a/board/gdsys/405ep/dlvision-10g.c +++ b/board/gdsys/405ep/dlvision-10g.c @@ -71,6 +71,16 @@ enum { RAM_DDR2_64 = 2, };
+void fpga_set_reg(unsigned int fpga, u16 reg, u16 data) +{ + out_le16((u16 *)CONFIG_SYS_FPGA_BASE(fpga) + reg / sizeof(u16), data); +} + +u16 fpga_get_reg(unsigned int fpga, u16 reg) +{ + return in_le16((u16 *)CONFIG_SYS_FPGA_BASE(fpga) + reg / sizeof(u16)); +} + int misc_init_r(void) { /* startup fans */ @@ -95,10 +105,9 @@ static unsigned int get_mc2_present(void)
static void print_fpga_info(unsigned dev) { - struct ihs_fpga *fpga = (struct ihs_fpga *) CONFIG_SYS_FPGA_BASE(dev); - u16 versions = in_le16(&fpga->versions); - u16 fpga_version = in_le16(&fpga->fpga_version); - u16 fpga_features = in_le16(&fpga->fpga_features); + u16 versions = fpga_get_reg(dev, REG(versions)); + u16 fpga_version = fpga_get_reg(dev, REG(fpga_version)); + u16 fpga_features = fpga_get_reg(dev, REG(fpga_features)); unsigned unit_type; unsigned hardware_version; unsigned feature_rs232; @@ -263,8 +272,7 @@ int checkboard(void)
int last_stage_init(void) { - struct ihs_fpga *fpga = (struct ihs_fpga *) CONFIG_SYS_FPGA_BASE(0); - u16 versions = in_le16(&fpga->versions); + u16 versions = fpga_get_reg(0, REG(versions));
print_fpga_info(0); if (get_mc2_present()) diff --git a/board/gdsys/405ep/io.c b/board/gdsys/405ep/io.c index 070dcbb..dbaf9d6 100644 --- a/board/gdsys/405ep/io.c +++ b/board/gdsys/405ep/io.c @@ -53,6 +53,16 @@ enum { HWVER_122 = 3, };
+void fpga_set_reg(unsigned int fpga, u16 reg, u16 data) +{ + out_le16((u16 *)CONFIG_SYS_FPGA_BASE(fpga) + reg / sizeof(u16), data); +} + +u16 fpga_get_reg(unsigned int fpga, u16 reg) +{ + return in_le16((u16 *)CONFIG_SYS_FPGA_BASE(fpga) + reg / sizeof(u16)); +} + int misc_init_r(void) { /* startup fans */ @@ -117,10 +127,9 @@ int checkboard(void)
static void print_fpga_info(void) { - struct ihs_fpga *fpga = (struct ihs_fpga *) CONFIG_SYS_FPGA_BASE(0); - u16 versions = in_le16(&fpga->versions); - u16 fpga_version = in_le16(&fpga->fpga_version); - u16 fpga_features = in_le16(&fpga->fpga_features); + u16 versions = fpga_get_reg(0, REG(versions)); + u16 fpga_version = fpga_get_reg(0, REG(fpga_version)); + u16 fpga_features = fpga_get_reg(0, REG(fpga_features)); unsigned unit_type; unsigned hardware_version; unsigned feature_channels; @@ -179,7 +188,6 @@ static void print_fpga_info(void) */ int last_stage_init(void) { - struct ihs_fpga *fpga = (struct ihs_fpga *) CONFIG_SYS_FPGA_BASE(0); unsigned int k;
print_fpga_info(); @@ -191,7 +199,7 @@ int last_stage_init(void) configure_gbit_phy(k);
/* take fpga serdes blocks out of reset */ - out_le16(&fpga->quad_serdes_reset, 0); + fpga_set_reg(0, REG(quad_serdes_reset), 0);
return 0; } diff --git a/board/gdsys/405ep/neo.c b/board/gdsys/405ep/neo.c index d336e55..f06a280 100644 --- a/board/gdsys/405ep/neo.c +++ b/board/gdsys/405ep/neo.c @@ -44,6 +44,16 @@ enum { HWVER_300 = 3, };
+void fpga_set_reg(unsigned int fpga, u16 reg, u16 data) +{ + out_le16((u16 *)CONFIG_SYS_FPGA_BASE(fpga) + reg / sizeof(u16), data); +} + +u16 fpga_get_reg(unsigned int fpga, u16 reg) +{ + return in_le16((u16 *)CONFIG_SYS_FPGA_BASE(fpga) + reg / sizeof(u16)); +} + int misc_init_r(void) { /* startup fans */ @@ -70,10 +80,9 @@ int checkboard(void)
static void print_fpga_info(void) { - struct ihs_fpga *fpga = (struct ihs_fpga *) CONFIG_SYS_FPGA_BASE(0); - u16 versions = in_le16(&fpga->versions); - u16 fpga_version = in_le16(&fpga->fpga_version); - u16 fpga_features = in_le16(&fpga->fpga_features); + u16 versions = fpga_get_reg(0, REG(versions)); + u16 fpga_version = fpga_get_reg(0, REG(fpga_version)); + u16 fpga_features = fpga_get_reg(0, REG(fpga_features)); int fpga_state = get_fpga_state(0); unsigned unit_type; unsigned hardware_version; diff --git a/board/gdsys/405ex/405ex.c b/board/gdsys/405ex/405ex.c index 32e24c0..b7e9802 100644 --- a/board/gdsys/405ex/405ex.c +++ b/board/gdsys/405ex/405ex.c @@ -220,23 +220,21 @@ int board_early_init_r(void) gd405ex_set_fpga_reset(0);
for (k = 0; k < CONFIG_SYS_FPGA_COUNT; ++k) { - struct ihs_fpga *fpga = - (struct ihs_fpga *)CONFIG_SYS_FPGA_BASE(k); #ifdef CONFIG_SYS_FPGA_NO_RFL_HI - u16 *reflection_target = &fpga->reflection_low; + u16 reflection_target = REG(reflection_low); #else - u16 *reflection_target = &fpga->reflection_high; + u16 reflection_target = REG(reflection_high); #endif /* * wait for fpga out of reset */ ctr = 0; while (1) { - out_le16(&fpga->reflection_low, - REFLECTION_TESTPATTERN); + fpga_set_reg(k, REG(reflection_low), + REFLECTION_TESTPATTERN);
- if (in_le16(reflection_target) == - REFLECTION_TESTPATTERN_INV) + if (fpga_get_reg(k, reflection_target) == + REFLECTION_TESTPATTERN_INV) break;
udelay(100000); diff --git a/board/gdsys/405ex/io64.c b/board/gdsys/405ex/io64.c index 7d2899d..f0f4241 100644 --- a/board/gdsys/405ex/io64.c +++ b/board/gdsys/405ex/io64.c @@ -67,6 +67,16 @@ enum { HWVER_110 = 1, };
+void fpga_set_reg(unsigned int fpga, u16 reg, u16 data) +{ + out_le16((u16 *)CONFIG_SYS_FPGA_BASE(fpga) + reg / sizeof(u16), data); +} + +u16 fpga_get_reg(unsigned int fpga, u16 reg) +{ + return in_le16((u16 *)CONFIG_SYS_FPGA_BASE(fpga) + reg / sizeof(u16)); +} + static inline void blank_string(int size) { int i; @@ -100,10 +110,9 @@ int misc_init_r(void)
static void print_fpga_info(unsigned dev) { - struct ihs_fpga *fpga = (struct ihs_fpga *) CONFIG_SYS_FPGA_BASE(dev); - u16 versions = in_le16(&fpga->versions); - u16 fpga_version = in_le16(&fpga->fpga_version); - u16 fpga_features = in_le16(&fpga->fpga_features); + u16 versions = fpga_get_reg(dev, REG(versions)); + u16 fpga_version = fpga_get_reg(dev, REG(fpga_version)); + u16 fpga_features = fpga_get_reg(dev, REG(fpga_features)); int fpga_state = get_fpga_state(dev);
unsigned unit_type; @@ -242,8 +251,6 @@ int last_stage_init(void) { unsigned int k; unsigned int fpga; - struct ihs_fpga *fpga0 = (struct ihs_fpga *) CONFIG_SYS_FPGA_BASE(0); - struct ihs_fpga *fpga1 = (struct ihs_fpga *) CONFIG_SYS_FPGA_BASE(1); int failed = 0; char str_phys[] = "Setup PHYs -"; char str_serdes[] = "Start SERDES blocks"; @@ -281,17 +288,16 @@ int last_stage_init(void) /* take fpga serdes blocks out of reset */ puts(str_serdes); udelay(500000); - out_le16(&fpga0->quad_serdes_reset, 0); - out_le16(&fpga1->quad_serdes_reset, 0); + fpga_set_reg(0, REG(quad_serdes_reset), 0); + fpga_set_reg(1, REG(quad_serdes_reset), 0); blank_string(strlen(str_serdes));
/* take channels out of reset */ puts(str_channels); udelay(500000); for (fpga = 0; fpga < 2; ++fpga) { - u16 *ch0_config_int = &(fpga ? fpga1 : fpga0)->ch0_config_int; for (k = 0; k < 32; ++k) - out_le16(ch0_config_int + 4 * k, 0); + fpga_set_reg(fpga, REG(ch0_config_int) + 8 * k, 0); } blank_string(strlen(str_channels));
@@ -299,16 +305,16 @@ int last_stage_init(void) puts(str_locks); udelay(500000); for (fpga = 0; fpga < 2; ++fpga) { - u16 *ch0_status_int = &(fpga ? fpga1 : fpga0)->ch0_status_int; for (k = 0; k < 32; ++k) { - u16 status = in_le16(ch0_status_int + 4*k); + u16 status = + fpga_get_reg(fpga, REG(ch0_status_int) + 8 * k); if (!(status & (1 << 4))) { failed = 1; printf("fpga %d channel %d: no serdes lock\n", fpga, k); } /* reset events */ - out_le16(ch0_status_int + 4*k, status); + fpga_set_reg(fpga, REG(ch0_status_int) + 8 * k, 0); } } blank_string(strlen(str_locks)); @@ -316,14 +322,14 @@ int last_stage_init(void) /* verify hicb_status */ puts(str_hicb); for (fpga = 0; fpga < 2; ++fpga) { - u16 *ch0_hicb_status_int = &(fpga ? fpga1 : fpga0)->ch0_hicb_status_int; for (k = 0; k < 32; ++k) { - u16 status = in_le16(ch0_hicb_status_int + 4*k); + u16 status = + fpga_get_reg(fpga, REG(ch0_status_int) + 8 * k); if (status) printf("fpga %d hicb %d: hicb status %04x\n", fpga, k, status); /* reset events */ - out_le16(ch0_hicb_status_int + 4*k, status); + fpga_set_reg(fpga, REG(ch0_status_int) + 8 * k, 0); } } blank_string(strlen(str_hicb));

Marvell 88E1518 has an erratum that requires fixing up. This patch checks for presence of this phy and adds code for fixup.
Signed-off-by: Dirk Eibach eibach@gdsys.de --- board/gdsys/405ep/iocon.c | 214 +++++++++++++++++++++++++++++++++++++++++++++ include/configs/iocon.h | 3 + 2 files changed, 217 insertions(+)
diff --git a/board/gdsys/405ep/iocon.c b/board/gdsys/405ep/iocon.c index ece45d6..45c5b36 100644 --- a/board/gdsys/405ep/iocon.c +++ b/board/gdsys/405ep/iocon.c @@ -38,6 +38,8 @@ #include <pca953x.h> #include <pca9698.h>
+#include <miiphy.h> + DECLARE_GLOBAL_DATA_PTR;
#define LATCH0_BASE (CONFIG_SYS_LATCH_BASE) @@ -95,8 +97,16 @@ enum { MCFPGA_RESET_N = 1 << 4, };
+enum { + GPIO_MDC = 1 << 14, + GPIO_MDIO = 1 << 15, +}; + unsigned int mclink_fpgacount;
+static int setup_88e1518(const char *bus, unsigned char addr); +static int verify_88e1518(const char *bus, unsigned char addr); + void fpga_set_reg(unsigned int fpga, u16 reg, u16 data) { int res; @@ -339,6 +349,7 @@ int last_stage_init(void) int slaves; unsigned int k; unsigned char mclink_controllers[] = { 0x24, 0x25, 0x26 }; + int legacy = get_fpga_state(0) & FPGA_STATE_PLATFORM;
print_fpga_info(0); osd_probe(0); @@ -360,6 +371,16 @@ int last_stage_init(void) } }
+ if (!legacy) { + miiphy_register(bb_miiphy_buses[0].name, bb_miiphy_read, + bb_miiphy_write); + if (!verify_88e1518(bb_miiphy_buses[0].name, 0)) { + printf("Fixup 88e1518 erratum on %s\n", + bb_miiphy_buses[0].name); + setup_88e1518(bb_miiphy_buses[0].name, 0); + } + } + /* wait for slave-PLLs to be up and running */ udelay(500000);
@@ -375,6 +396,13 @@ int last_stage_init(void) for (k = 1; k <= slaves; ++k) { print_fpga_info(k); osd_probe(k); + miiphy_register(bb_miiphy_buses[k].name, + bb_miiphy_read, bb_miiphy_write); + if (!verify_88e1518(bb_miiphy_buses[k].name, 0)) { + printf("Fixup 88e1518 erratum on %s\n", + bb_miiphy_buses[k].name); + setup_88e1518(bb_miiphy_buses[k].name, 0); + } }
return 0; @@ -446,3 +474,189 @@ int gd405ep_get_fpga_done(unsigned fpga) else return pca9698_get_value(0x20, 20); } + +/* + * FPGA MII bitbang implementation + */ + +struct fpga_mii { + unsigned fpga; + int mdio; +} fpga_mii[] = { + { 0, 1}, + { 1, 1}, + { 2, 1}, + { 3, 1}, +}; + +static int mii_dummy_init(struct bb_miiphy_bus *bus) +{ + return 0; +} + +static int mii_mdio_active(struct bb_miiphy_bus *bus) +{ + struct fpga_mii *fpga_mii = bus->priv; + + if (fpga_mii->mdio) + fpga_set_reg(fpga_mii->fpga, REG(gpio.set), GPIO_MDIO); + else + fpga_set_reg(fpga_mii->fpga, REG(gpio.clear), GPIO_MDIO); + + return 0; +} + +static int mii_mdio_tristate(struct bb_miiphy_bus *bus) +{ + struct fpga_mii *fpga_mii = bus->priv; + + fpga_set_reg(fpga_mii->fpga, REG(gpio.set), GPIO_MDIO); + + return 0; +} + +static int mii_set_mdio(struct bb_miiphy_bus *bus, int v) +{ + struct fpga_mii *fpga_mii = bus->priv; + + if (v) + fpga_set_reg(fpga_mii->fpga, REG(gpio.set), GPIO_MDIO); + else + fpga_set_reg(fpga_mii->fpga, REG(gpio.clear), GPIO_MDIO); + + fpga_mii->mdio = v; + + return 0; +} + +static int mii_get_mdio(struct bb_miiphy_bus *bus, int *v) +{ + struct fpga_mii *fpga_mii = bus->priv; + + *v = ((fpga_get_reg(fpga_mii->fpga, REG(gpio.read)) & GPIO_MDIO) != 0); + + return 0; +} + +static int mii_set_mdc(struct bb_miiphy_bus *bus, int v) +{ + struct fpga_mii *fpga_mii = bus->priv; + + if (v) + fpga_set_reg(fpga_mii->fpga, REG(gpio.set), GPIO_MDC); + else + fpga_set_reg(fpga_mii->fpga, REG(gpio.clear), GPIO_MDC); + + return 0; +} + +static int mii_delay(struct bb_miiphy_bus *bus) +{ + udelay(1); + + return 0; +} + +struct bb_miiphy_bus bb_miiphy_buses[] = { + { + .name = "trans1", + .init = mii_dummy_init, + .mdio_active = mii_mdio_active, + .mdio_tristate = mii_mdio_tristate, + .set_mdio = mii_set_mdio, + .get_mdio = mii_get_mdio, + .set_mdc = mii_set_mdc, + .delay = mii_delay, + .priv = &fpga_mii[0], + }, + { + .name = "trans2", + .init = mii_dummy_init, + .mdio_active = mii_mdio_active, + .mdio_tristate = mii_mdio_tristate, + .set_mdio = mii_set_mdio, + .get_mdio = mii_get_mdio, + .set_mdc = mii_set_mdc, + .delay = mii_delay, + .priv = &fpga_mii[1], + }, + { + .name = "trans3", + .init = mii_dummy_init, + .mdio_active = mii_mdio_active, + .mdio_tristate = mii_mdio_tristate, + .set_mdio = mii_set_mdio, + .get_mdio = mii_get_mdio, + .set_mdc = mii_set_mdc, + .delay = mii_delay, + .priv = &fpga_mii[2], + }, + { + .name = "trans4", + .init = mii_dummy_init, + .mdio_active = mii_mdio_active, + .mdio_tristate = mii_mdio_tristate, + .set_mdio = mii_set_mdio, + .get_mdio = mii_get_mdio, + .set_mdc = mii_set_mdc, + .delay = mii_delay, + .priv = &fpga_mii[3], + }, +}; + +int bb_miiphy_buses_num = sizeof(bb_miiphy_buses) / + sizeof(bb_miiphy_buses[0]); + +/* + * Workaround for erratum mentioned in 88E1518 release notes + */ + +static int verify_88e1518(const char *bus, unsigned char addr) +{ + u16 phy_id1, phy_id2; + + if (miiphy_read(bus, addr, 2, &phy_id1) || + miiphy_read(bus, addr, 3, &phy_id2)) { + printf("Error reading from the PHY addr=%02x\n", addr); + return -EIO; + } + + if ((phy_id1 != 0x0141) || ((phy_id2 & 0xfff0) != 0x0dd0)) + return -EINVAL; + + return 0; +} + +struct regfix_88e1518 { + u8 reg; + u16 data; +} regfix_88e1518[] = { + { 22, 0x00ff }, + { 17, 0x214b }, + { 16, 0x2144 }, + { 17, 0x0c28 }, + { 16, 0x2146 }, + { 17, 0xb233 }, + { 16, 0x214d }, + { 17, 0xcc0c }, + { 16, 0x2159 }, + { 22, 0x00fb }, + { 7, 0xc00d }, + { 22, 0x0000 }, +}; + +static int setup_88e1518(const char *bus, unsigned char addr) +{ + unsigned int k; + + for (k = 0; k < ARRAY_SIZE(regfix_88e1518); ++k) { + if (miiphy_write(bus, addr, + regfix_88e1518[k].reg, + regfix_88e1518[k].data)) { + printf("Error writing to the PHY addr=%02x\n", addr); + return -1; + } + } + + return 0; +} diff --git a/include/configs/iocon.h b/include/configs/iocon.h index e99efa6..441b37b 100644 --- a/include/configs/iocon.h +++ b/include/configs/iocon.h @@ -274,4 +274,7 @@ int fpga_gpio_get(unsigned int bus, int pin); #define CONFIG_SYS_CH7301 #define CONFIG_SYS_OSD_SCREENS 1
+#define CONFIG_BITBANGMII /* bit-bang MII PHY management */ +#define CONFIG_BITBANGMII_MULTI + #endif /* __CONFIG_H */

Signed-off-by: Dirk Eibach eibach@gdsys.de --- board/gdsys/common/mclink.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/board/gdsys/common/mclink.c b/board/gdsys/common/mclink.c index 6c86145..641a327 100644 --- a/board/gdsys/common/mclink.c +++ b/board/gdsys/common/mclink.c @@ -40,11 +40,11 @@ enum { int mclink_probe(void) { unsigned int k; - unsigned int ctr = 0; int slaves = 0;
for (k = 0; k < CONFIG_SYS_MCLINK_MAX; ++k) { int timeout = 0; + unsigned int ctr = 0;
if (!(fpga_get_reg(k, REG(mc_status)) & (1 << 15))) break; @@ -53,7 +53,7 @@ int mclink_probe(void)
while (!(fpga_get_reg(k, REG(mc_status)) & (1 << 14))) { udelay(100); - if (ctr++ > 3) { + if (ctr++ > 500) { timeout = 1; break; } @@ -61,6 +61,8 @@ int mclink_probe(void) if (timeout) break;
+ printf("waited %d us for mclink %d to come up\n", ctr * 100, k); + slaves++; }

OSD size was constant 32x16 characters. Now the size is set as announced by the FPGA.
Signed-off-by: Dirk Eibach eibach@gdsys.de --- board/gdsys/common/osd.c | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-)
diff --git a/board/gdsys/common/osd.c b/board/gdsys/common/osd.c index 81c8136..d557a2e 100644 --- a/board/gdsys/common/osd.c +++ b/board/gdsys/common/osd.c @@ -22,6 +22,7 @@ */
#include <common.h> +#include <malloc.h> #include "bb_i2c.h" #include <asm/io.h>
@@ -42,10 +43,6 @@
#define PIXCLK_640_480_60 25180000
-#define BASE_WIDTH 32 -#define BASE_HEIGHT 16 -#define BUFSIZE (BASE_WIDTH * BASE_HEIGHT) - enum { CH7301_CM = 0x1c, /* Clock Mode Register */ CH7301_IC = 0x1d, /* Input Clock Register */ @@ -67,6 +64,11 @@ enum { CH7301_DSP = 0x56, /* DVI Sync polarity Register */ };
+unsigned int base_width; +unsigned int base_height; +size_t bufsize; +u16 *buf; + unsigned int max_osd_screen = CONFIG_SYS_OSD_SCREENS - 1;
#if defined(CONFIG_SYS_ICS8N3QV01) || defined(CONFIG_SYS_SIL1178) @@ -264,7 +266,7 @@ static int osd_write_videomem(unsigned screen, unsigned offset, unsigned int k;
for (k = 0; k < charcount; ++k) { - if (offset + k >= BUFSIZE) + if (offset + k >= bufsize) return -1; fpga_set_reg(screen, REG(videomem) + sizeof(u16) * (offset + k), data[k]); @@ -284,7 +286,6 @@ static int osd_print(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) unsigned len; u8 color; unsigned int k; - u16 buf[BUFSIZE]; char *text; int res;
@@ -298,12 +299,12 @@ static int osd_print(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) color = simple_strtoul(argv[3], NULL, 16); text = argv[4]; charcount = strlen(text); - len = (charcount > BUFSIZE) ? BUFSIZE : charcount; + len = (charcount > bufsize) ? bufsize : charcount;
for (k = 0; k < len; ++k) buf[k] = (text[k] << 8) | color;
- res = osd_write_videomem(screen, y * BASE_WIDTH + x, buf, len); + res = osd_write_videomem(screen, y * base_width + x, buf, len); if (res < 0) return res; } @@ -315,15 +316,17 @@ int osd_probe(unsigned screen) { u16 version = fpga_get_reg(screen, REG(osd.version)); u16 features = fpga_get_reg(screen, REG(osd.features)); - unsigned width; - unsigned height; u8 value;
- width = ((features & 0x3f00) >> 8) + 1; - height = (features & 0x001f) + 1; + base_width = ((features & 0x3f00) >> 8) + 1; + base_height = (features & 0x001f) + 1; + bufsize = base_width * base_height; + buf = malloc(sizeof(u16) * bufsize); + if (!buf) + return -1;
printf("OSD%d: Digital-OSD version %01d.%02d, %d" "x%d characters\n", - screen, version/100, version%100, width, height); + screen, version/100, version%100, base_width, base_height);
#ifdef CONFIG_SYS_CH7301 value = bb_i2c_reg_read(screen, CH7301_I2C_ADDR, CH7301_DID); @@ -386,7 +389,7 @@ int osd_write(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) unsigned x; unsigned y; unsigned k; - u16 buffer[BASE_WIDTH]; + u16 buffer[base_width]; char *rp; u16 *wp = buffer; unsigned count = (argc > 4) ? @@ -411,13 +414,13 @@ int osd_write(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
rp += 4; wp++; - if (wp - buffer > BASE_WIDTH) + if (wp - buffer > base_width) break; }
for (k = 0; k < count; ++k) { unsigned offset = - y * BASE_WIDTH + x + k * (wp - buffer); + y * base_width + x + k * (wp - buffer); osd_write_videomem(screen, offset, buffer, wp - buffer); }

CONFIG_SYS_FLASH_PROTECTION was active on most gdsys boards by default, while hardware flash protection was not implemented. Hardware support was added recently and we get into trouble because backward compatibility is broken (u-boot can't unprotect the protected flash after a downgrade). So we decided to disable hardware flash protection for all our boards.
Signed-off-by: Dirk Eibach eibach@gdsys.de
--- include/configs/dlvision-10g.h | 3 +-- include/configs/dlvision.h | 3 +-- include/configs/io.h | 3 +-- include/configs/iocon.h | 3 +-- include/configs/neo.h | 3 +-- 5 files changed, 5 insertions(+), 10 deletions(-)
diff --git a/include/configs/dlvision-10g.h b/include/configs/dlvision-10g.h index 2cd2027..1f82d7c 100644 --- a/include/configs/dlvision-10g.h +++ b/include/configs/dlvision-10g.h @@ -34,7 +34,7 @@ * Include common defines/options for all AMCC eval boards */ #define CONFIG_HOSTNAME dlvsion-10g -#define CONFIG_IDENT_STRING " dlvision-10g 0.03" +#define CONFIG_IDENT_STRING " dlvision-10g 0.04" #include "amcc-common.h"
#define CONFIG_BOARD_EARLY_INIT_F @@ -161,7 +161,6 @@ #define CONFIG_SYS_FLASH_WRITE_TOUT 500 /* Timeout for Flash Write/ms */
#define CONFIG_SYS_FLASH_USE_BUFFER_WRITE 1 /* use buff'd writes */ -#define CONFIG_SYS_FLASH_PROTECTION 1 /* use hardware flash protect */
#define CONFIG_SYS_FLASH_EMPTY_INFO /* 'E' for empty sector on flinfo */ #define CONFIG_SYS_FLASH_QUIET_TEST 1 /* no warn upon unknown flash */ diff --git a/include/configs/dlvision.h b/include/configs/dlvision.h index c490ff6..6d922f2 100644 --- a/include/configs/dlvision.h +++ b/include/configs/dlvision.h @@ -34,7 +34,7 @@ * Include common defines/options for all AMCC eval boards */ #define CONFIG_HOSTNAME dlvision -#define CONFIG_IDENT_STRING " dlvision 0.01" +#define CONFIG_IDENT_STRING " dlvision 0.02" #include "amcc-common.h"
#define CONFIG_BOARD_EARLY_INIT_F /* call board_early_init_f */ @@ -125,7 +125,6 @@ #define CONFIG_SYS_FLASH_WRITE_TOUT 500 /* Timeout for Flash Write/ms */
#define CONFIG_SYS_FLASH_USE_BUFFER_WRITE 1 /* use buff'd writes */ -#define CONFIG_SYS_FLASH_PROTECTION 1 /* use hardware flash protect */
#define CONFIG_SYS_FLASH_EMPTY_INFO /* 'E' for empty sector on flinfo */ #define CONFIG_SYS_FLASH_QUIET_TEST 1 /* no warn upon unknown flash */ diff --git a/include/configs/io.h b/include/configs/io.h index 03661cc..b4558e4 100644 --- a/include/configs/io.h +++ b/include/configs/io.h @@ -34,7 +34,7 @@ * Include common defines/options for all AMCC eval boards */ #define CONFIG_HOSTNAME io -#define CONFIG_IDENT_STRING " io 0.05" +#define CONFIG_IDENT_STRING " io 0.06" #include "amcc-common.h"
#define CONFIG_BOARD_EARLY_INIT_F @@ -139,7 +139,6 @@ #define CONFIG_SYS_FLASH_WRITE_TOUT 500 /* Timeout for Flash Write/ms */
#define CONFIG_SYS_FLASH_USE_BUFFER_WRITE 1 /* use buff'd writes */ -#define CONFIG_SYS_FLASH_PROTECTION 1 /* use hardware flash protect */
#define CONFIG_SYS_FLASH_EMPTY_INFO /* 'E' for empty sector on flinfo */ #define CONFIG_SYS_FLASH_QUIET_TEST 1 /* no warn upon unknown flash */ diff --git a/include/configs/iocon.h b/include/configs/iocon.h index 441b37b..f10e929 100644 --- a/include/configs/iocon.h +++ b/include/configs/iocon.h @@ -34,7 +34,7 @@ * Include common defines/options for all AMCC eval boards */ #define CONFIG_HOSTNAME iocon -#define CONFIG_IDENT_STRING " iocon 0.04" +#define CONFIG_IDENT_STRING " iocon 0.05" #include "amcc-common.h"
#define CONFIG_BOARD_EARLY_INIT_F @@ -160,7 +160,6 @@ int fpga_gpio_get(unsigned int bus, int pin); #define CONFIG_SYS_FLASH_WRITE_TOUT 500 /* Timeout for Flash Write/ms */
#define CONFIG_SYS_FLASH_USE_BUFFER_WRITE 1 /* use buff'd writes */ -#define CONFIG_SYS_FLASH_PROTECTION 1 /* use hardware flash protect */
#define CONFIG_SYS_FLASH_EMPTY_INFO /* 'E' for empty sector on flinfo */ #define CONFIG_SYS_FLASH_QUIET_TEST 1 /* no warn upon unknown flash */ diff --git a/include/configs/neo.h b/include/configs/neo.h index 38b5bec..59d7820 100644 --- a/include/configs/neo.h +++ b/include/configs/neo.h @@ -35,7 +35,7 @@ * Include common defines/options for all AMCC eval boards */ #define CONFIG_HOSTNAME neo -#define CONFIG_IDENT_STRING " neo 0.01" +#define CONFIG_IDENT_STRING " neo 0.02" #include "amcc-common.h"
#define CONFIG_BOARD_EARLY_INIT_F @@ -146,7 +146,6 @@ #define CONFIG_SYS_FLASH_WRITE_TOUT 500 /* Timeout for Flash Write (in ms) */
#define CONFIG_SYS_FLASH_USE_BUFFER_WRITE 1 /* use buffered writes (20x faster) */ -#define CONFIG_SYS_FLASH_PROTECTION 1 /* use hardware flash protection */
#define CONFIG_SYS_FLASH_EMPTY_INFO /* print 'E' for empty sector on flinfo */ #define CONFIG_SYS_FLASH_QUIET_TEST 1 /* don't warn upon unknown flash */
participants (8)
-
Dirk Eibach
-
Dirk Eibach
-
Eibach, Dirk
-
Heiko Schocher
-
Stefan Roese
-
TigerLiu@viatech.com.cn
-
Tom Rini
-
Wolfgang Denk