Hello Simon, Przemyslaw,

Am 24.03.2015 00:38, schrieb Simon Glass:
Hi Przemyslaw,

On 10 March 2015 at 04:30, Przemyslaw Marczak <p.marc...@samsung.com> wrote:
This change adds driver model support to software emulated
i2c bus driver. To bind the driver, proper device-tree node
must be defined, with the following attributes:
- alias: to keep proper bus order
- compatible: 'soft-i2c'
- clock-frequency [Hz]
- clock-pin, data-pin: gpio phandles

/* Define the alias number to keep bus numbering order */
aliases {
         [...]
         i2c5 = "/i2c@13500000";
         i2c6 = "/soft-i2c@1";
         [...]
};

/* Define the basic bus attributes */
soft-i2c@1 {
         #address-cells = <1>;
         #size-cells = <0>;
         compatible = "soft-i2c";
         clock-frequency = <50000>;

         /* Define the proper GPIO pins */
         clock-pin = <&gpa0 0 GPIO_ACTIVE_HIGH>;
         data-pin = <&gpa0 1 GPIO_ACTIVE_HIGH>;

         /* Optionally, define some driver node (bus child) */
         somedev@0x44 {
                 compatible = "somedev";
                 reg = <0x44>;
                 [...]
         };
};

The device can be accessed by the i2c command:
  i2c dev 8                   (bus number set by alias)
  i2c probe <0x44>            (address is optionally)
  i2c md 0x44 0x0             (dump dev registers at address 0x0)
  Valid chip addresses: 0x44  (success!)
  ...

The previous driver functionality stays unchanged. Driving the bus lines
is done by dm gpio calls in the preprocessor macros. Each, can be redefined
by the user as previous.

Tested on Trats2 and Odroid U3.

Is the intention to retire the old (non-driver-model) code? What boards use it?

I think not ... Hmm ... maybe you move the new code into
a new file?

Signed-off-by: Przemyslaw Marczak <p.marc...@samsung.com>
Cc: Masahiro Yamada <yamad...@jp.panasonic.com>
Cc: Mike Frysinger <vap...@gentoo.org>
Cc: Simon Glass <s...@chromium.org>
Cc: Heiko Schocher <h...@denx.de>

Hups... seems I missed this patches ...

---
  drivers/i2c/Makefile   |   1 +
  drivers/i2c/soft_i2c.c | 410 +++++++++++++++++++++++++++++++++++++++++++++++--
  2 files changed, 400 insertions(+), 11 deletions(-)

Thanks for this work!

diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile
index 774bc94..7039b6d 100644
--- a/drivers/i2c/Makefile
+++ b/drivers/i2c/Makefile
@@ -6,6 +6,7 @@
  #
  obj-$(CONFIG_DM_I2C) += i2c-uclass.o
  obj-$(CONFIG_DM_I2C_COMPAT) += i2c-uclass-compat.o
+obj-$(CONFIG_DM_I2C_SOFT) += soft_i2c.o

  obj-$(CONFIG_SYS_I2C_ADI) += adi_i2c.o
  obj-$(CONFIG_I2C_MV) += mv_i2c.o
diff --git a/drivers/i2c/soft_i2c.c b/drivers/i2c/soft_i2c.c
index db9b402..7afae0b 100644
--- a/drivers/i2c/soft_i2c.c
+++ b/drivers/i2c/soft_i2c.c
@@ -1,4 +1,7 @@
  /*
+ * (C) Copyright 2015, Samsung Electronics
+ * Przemyslaw Marczak <p.marc...@samsung.com>
+ *
   * (C) Copyright 2009
   * Heiko Schocher, DENX Software Engineering, h...@denx.de.
   * Changes for multibus/multiadapter I2C support.
@@ -14,6 +17,11 @@
   */

  #include <common.h>
+#include <errno.h>
+#include <dm.h>
+#include <i2c.h>
+#include <div64.h>
+#include <asm/gpio.h>
  #ifdef CONFIG_MPC8260                  /* only valid for MPC8260 */
  #include <ioports.h>
  #include <asm/io.h>
@@ -32,11 +40,9 @@
  #if defined(CONFIG_MPC852T) || defined(CONFIG_MPC866)
  #include <asm/io.h>
  #endif
-#include <i2c.h>

+#if defined(CONFIG_SYS_I2C)
  #if defined(CONFIG_SOFT_I2C_GPIO_SCL)
-# include <asm/gpio.h>
-
  # ifndef I2C_GPIO_SYNC
  #  define I2C_GPIO_SYNC
  # endif
@@ -85,6 +91,7 @@
  # endif

  #endif
+#endif

  /* #define     DEBUG_I2C       */

@@ -109,6 +116,65 @@ DECLARE_GLOBAL_DATA_PTR;
  #define CONFIG_SYS_I2C_SOFT_SLAVE CONFIG_SYS_I2C_SLAVE
  #endif

+/* DM SOFT I2C */
+#ifdef CONFIG_DM_I2C_SOFT
+# ifndef I2C_GPIO_SYNC
+#  define I2C_GPIO_SYNC(gpio)
+# endif
+
+# ifndef I2C_INIT
+#  define I2C_INIT(scl, sda)  \
+       do { } while (0)
+# endif
+
+# ifndef I2C_ACTIVE
+#  define I2C_ACTIVE(sda) \
+       do { } while (0)
+# endif
+
+# ifndef I2C_TRISTATE
+#  define I2C_TRISTATE(sda) \
+       do { } while (0)
+# endif
+
+# ifndef I2C_READ
+#  define I2C_READ(sda) dm_gpio_get_value(sda);
+# endif
+
+# ifndef I2C_SDA
+#  define I2C_SDA(sda, bit) \
+       do { \
+               if (bit) { \
+                       sda->flags &= ~GPIOD_IS_OUT; \
+                       sda->flags |= GPIOD_IS_IN; \
+                       dm_gpio_set_dir(sda); \
+               } else { \
+                       sda->flags &= ~GPIOD_IS_IN; \
+                       sda->flags |= GPIOD_IS_OUT; \
+                       dm_gpio_set_dir(sda); \
+                       dm_gpio_set_value(sda, 0); \
+               } \
+               I2C_GPIO_SYNC(sda); \
+       } while (0)
+# endif
+
+# ifndef I2C_SCL
+#  define I2C_SCL(scl, bit) \
+       do { \
+               scl->flags &= ~GPIOD_IS_IN; \
+               scl->flags |= GPIOD_IS_OUT; \
+               dm_gpio_set_dir(scl); \
+               dm_gpio_set_value(scl, bit); \
+               I2C_GPIO_SYNC(scl); \
+       } while (0)
+# endif
+
+# ifndef I2C_DELAY
+#  define I2C_DELAY(us) udelay(us)     /* 1/4 I2C clock duration */
+# endif
+
+#endif /* CONFIG_DM_I2C_SOFT */
+
  /*-----------------------------------------------------------------------
   * Definitions
   */
@@ -117,7 +183,6 @@ DECLARE_GLOBAL_DATA_PTR;
  #define I2C_ACK                0               /* PD_SDA level to ack a byte 
*/
  #define I2C_NOACK      1               /* PD_SDA level to noack a byte */

-
  #ifdef DEBUG_I2C
  #define PRINTD(fmt,args...)    do {    \
                 printf (fmt ,##args);   \
@@ -129,21 +194,30 @@ DECLARE_GLOBAL_DATA_PTR;
  /*-----------------------------------------------------------------------
   * Local functions
   */
+#ifdef CONFIG_SYS_I2C
  #if !defined(CONFIG_SYS_I2C_INIT_BOARD)
-static void  send_reset        (void);
+static void send_reset(void);
+#endif
+static void send_start(void);
+static void send_stop(void);
+static void send_ack(int);
+static int write_byte(uchar byte);
+static uchar read_byte(int);
+#else
+static void send_reset(struct gpio_desc *, struct gpio_desc *, int);
+static void send_start(struct gpio_desc *, struct gpio_desc *, int);
+static void send_stop(struct gpio_desc *, struct gpio_desc *, int);
+static void send_ack(struct gpio_desc *, struct gpio_desc *, int, int);
+static int write_byte(struct gpio_desc *, struct gpio_desc *, int, uchar);
+static uchar read_byte(struct gpio_desc *, struct gpio_desc *, int, int);
  #endif
-static void  send_start        (void);
-static void  send_stop (void);
-static void  send_ack  (int);
-static int   write_byte        (uchar byte);
-static uchar read_byte (int);
-
  #if !defined(CONFIG_SYS_I2C_INIT_BOARD)
  /*-----------------------------------------------------------------------
   * 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.
   */
+#ifdef CONFIG_SYS_I2C_SOFT
  static void send_reset(void)
  {
         I2C_SOFT_DECLARATIONS   /* intentional without ';' */
@@ -166,11 +240,36 @@ static void send_reset(void)
         send_stop();
         I2C_TRISTATE;
  }
+#else
+static void send_reset(struct gpio_desc *scl, struct gpio_desc *sda, int delay)
+{
+       I2C_SOFT_DECLARATIONS   /* intentional without ';' */
+       int j;
+
+       I2C_SCL(scl, 1);
+       I2C_SDA(sda, 1);
+#ifdef I2C_INIT
+       I2C_INIT(scl, sda);
+#endif
+       I2C_TRISTATE(sda);
+       for (j = 0; j < 9; j++) {
+               I2C_SCL(scl, 0);
+               I2C_DELAY(delay);
+               I2C_DELAY(delay);
+               I2C_SCL(scl, 1);
+               I2C_DELAY(delay);
+               I2C_DELAY(delay);
+       }
+       send_stop(scl, sda, delay);
+       I2C_TRISTATE(sda);

For the new code I would much prefer that these become functions
rather than macros. What is the benefit of using a macro?

I do not know the real reason, but I think it comes from powerpc
times, where we had not yet such powerful SoCs and it saved some
instructions ... I tend to say, lets move the dm part into a new
file ... and let it us do like linux ...

@Simon: Do you pick up this patches through DM tree, or should
I pick them up?

bye,
Heiko
+}
+#endif /* CONFIG_SYS_I2C_SOFT */
  #endif

  /*-----------------------------------------------------------------------
   * START: High -> Low on SDA while SCL is High
   */
+#ifdef CONFIG_SYS_I2C_SOFT
  static void send_start(void)
  {
         I2C_SOFT_DECLARATIONS   /* intentional without ';' */
@@ -184,10 +283,25 @@ static void send_start(void)
         I2C_SDA(0);
         I2C_DELAY;
  }
+#else
+static void send_start(struct gpio_desc *scl, struct gpio_desc *sda, int delay)
+{
+       I2C_SOFT_DECLARATIONS   /* intentional without ';' */

+       I2C_DELAY(delay);
+       I2C_SDA(sda, 1);
+       I2C_ACTIVE(sda);
+       I2C_DELAY(delay);
+       I2C_SCL(scl, 1);
+       I2C_DELAY(delay);
+       I2C_SDA(sda, 0);
+       I2C_DELAY(delay);
+}
+#endif /* CONFIG_SYS_I2C_SOFT */
  /*-----------------------------------------------------------------------
   * STOP: Low -> High on SDA while SCL is High
   */
+#ifdef CONFIG_SYS_I2C_SOFT
  static void send_stop(void)
  {
         I2C_SOFT_DECLARATIONS   /* intentional without ';' */
@@ -203,10 +317,28 @@ static void send_stop(void)
         I2C_DELAY;
         I2C_TRISTATE;
  }
+#else
+static void send_stop(struct gpio_desc *scl, struct gpio_desc *sda, int delay)
+{
+       I2C_SOFT_DECLARATIONS   /* intentional without ';' */
+
+       I2C_SCL(scl, 0);
+       I2C_DELAY(delay);
+       I2C_SDA(sda, 0);
+       I2C_ACTIVE(sda);
+       I2C_DELAY(delay);
+       I2C_SCL(scl, 1);
+       I2C_DELAY(delay);
+       I2C_SDA(sda, 1);
+       I2C_DELAY(delay);
+       I2C_TRISTATE(sda);
+}
+#endif /* CONFIG_SYS_I2C_SOFT */

  /*-----------------------------------------------------------------------
   * ack should be I2C_ACK or I2C_NOACK
   */
+#ifdef CONFIG_SYS_I2C_SOFT
  static void send_ack(int ack)
  {
         I2C_SOFT_DECLARATIONS   /* intentional without ';' */
@@ -222,10 +354,29 @@ static void send_ack(int ack)
         I2C_SCL(0);
         I2C_DELAY;
  }
+#else
+static void send_ack(struct gpio_desc *scl, struct gpio_desc *sda,
+                    int delay, int ack)
+{
+       I2C_SOFT_DECLARATIONS   /* intentional without ';' */
+
+       I2C_SCL(scl, 0);
+       I2C_DELAY(delay);
+       I2C_ACTIVE(sda);
+       I2C_SDA(sda, ack);
+       I2C_DELAY(delay);
+       I2C_SCL(scl, 1);
+       I2C_DELAY(delay);
+       I2C_DELAY(delay);
+       I2C_SCL(scl, 0);
+       I2C_DELAY(delay);
+}
+#endif

  /*-----------------------------------------------------------------------
   * Send 8 bits and look for an acknowledgement.
   */
+#ifdef CONFIG_SYS_I2C_SOFT
  static int write_byte(uchar data)
  {
         I2C_SOFT_DECLARATIONS   /* intentional without ';' */
@@ -263,11 +414,52 @@ static int write_byte(uchar data)

         return(nack);   /* not a nack is an ack */
  }
+#else
+static int write_byte(struct gpio_desc *scl, struct gpio_desc *sda,
+                     int delay, uchar data)
+{
+       I2C_SOFT_DECLARATIONS   /* intentional without ';' */
+       int j;
+       int nack;
+
+       I2C_ACTIVE(sda);
+       for (j = 0; j < 8; j++) {
+               I2C_SCL(scl, 0);
+               I2C_DELAY(delay);
+               I2C_SDA(sda, data & 0x80);
+               I2C_DELAY(delay);
+               I2C_SCL(scl, 1);
+               I2C_DELAY(delay);
+               I2C_DELAY(delay);
+
+               data <<= 1;
+       }
+
+       /*
+        * Look for an <ACK>(negative logic) and return it.
+        */
+       I2C_SCL(scl, 0);
+       I2C_DELAY(delay);
+       I2C_SDA(sda, 1);
+       I2C_TRISTATE(sda);
+       I2C_DELAY(delay);
+       I2C_SCL(scl, 1);
+       I2C_DELAY(delay);
+       I2C_DELAY(delay);
+       nack = I2C_READ(sda);
+       I2C_SCL(scl, 0);
+       I2C_DELAY(delay);
+       I2C_ACTIVE(sda);
+
+       return nack;    /* not a nack is an ack */
+}
+#endif

  /*-----------------------------------------------------------------------
   * if ack == I2C_ACK, ACK the byte so can continue reading, else
   * send I2C_NOACK to end the read.
   */
+#ifdef CONFIG_SYS_I2C_SOFT
  static uchar read_byte(int ack)
  {
         I2C_SOFT_DECLARATIONS   /* intentional without ';' */
@@ -293,10 +485,38 @@ static uchar read_byte(int ack)

         return(data);
  }
+#else
+static uchar read_byte(struct gpio_desc *scl, struct gpio_desc *sda,
+                      int delay, int ack)
+{
+       I2C_SOFT_DECLARATIONS   /* intentional without ';' */
+       int  data;
+       int  j;
+
+       /*
+        * Read 8 bits, MSB first.
+        */
+       I2C_TRISTATE(sda);
+       I2C_SDA(sda, 1);
+       data = 0;
+       for (j = 0; j < 8; j++) {
+               I2C_SCL(scl, 0);
+               I2C_DELAY(delay);
+               I2C_SCL(scl, 1);
+               I2C_DELAY(delay);
+               data <<= 1;
+               data |= I2C_READ(sda);
+               I2C_DELAY(delay);
+       }
+       send_ack(scl, sda, delay, ack);

+       return data;
+}
+#endif /* CONFIG_SYS_I2C_SOFT */
  /*-----------------------------------------------------------------------
   * Initialization
   */
+#ifdef CONFIG_SYS_I2C_SOFT
  static void soft_i2c_init(struct i2c_adapter *adap, int speed, int slaveaddr)
  {
  #if defined(CONFIG_SYS_I2C_INIT_BOARD)
@@ -314,12 +534,14 @@ static void soft_i2c_init(struct i2c_adapter *adap, int 
speed, int slaveaddr)
         send_reset ();
  #endif
  }
+#endif

  /*-----------------------------------------------------------------------
   * 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).
   */
+#ifdef CONFIG_SYS_I2C_SOFT
  static int soft_i2c_probe(struct i2c_adapter *adap, uint8_t addr)
  {
         int rc;
@@ -334,10 +556,12 @@ static int soft_i2c_probe(struct i2c_adapter *adap, 
uint8_t addr)

         return (rc ? 1 : 0);
  }
+#endif

  /*-----------------------------------------------------------------------
   * Read bytes
   */
+#ifdef CONFIG_SYS_I2C_SOFT
  static int  soft_i2c_read(struct i2c_adapter *adap, uchar chip, uint addr,
                         int alen, uchar *buffer, int len)
  {
@@ -409,10 +633,12 @@ static int  soft_i2c_read(struct i2c_adapter *adap, uchar 
chip, uint addr,
         send_stop();
         return(0);
  }
+#endif

  /*-----------------------------------------------------------------------
   * Write bytes
   */
+#ifdef CONFIG_SYS_I2C_SOFT
  static int  soft_i2c_write(struct i2c_adapter *adap, uchar chip, uint addr,
                         int alen, uchar *buffer, int len)
  {
@@ -444,10 +670,12 @@ static int  soft_i2c_write(struct i2c_adapter *adap, 
uchar chip, uint addr,
         send_stop();
         return(failures);
  }
+#endif

  /*
   * Register soft i2c adapters
   */
+#ifdef CONFIG_SYS_I2C_SOFT
  U_BOOT_I2C_ADAP_COMPLETE(soft0, soft_i2c_init, soft_i2c_probe,
                          soft_i2c_read, soft_i2c_write, NULL,
                          CONFIG_SYS_I2C_SOFT_SPEED, CONFIG_SYS_I2C_SOFT_SLAVE,
@@ -473,3 +701,163 @@ U_BOOT_I2C_ADAP_COMPLETE(soft3, soft_i2c_init, 
soft_i2c_probe,
                          CONFIG_SYS_I2C_SOFT_SLAVE_4,
                          3)
  #endif
+#endif /* CONFIG_SYS_I2C_SOFT */
+
+#ifdef CONFIG_DM_I2C_SOFT
+struct soft_i2c_bus {
+       unsigned int speed;
+       unsigned long delay;
+       struct gpio_desc scl;
+       struct gpio_desc sda;
+};
+
+static int i2c_write_data(struct soft_i2c_bus *i2c_bus, uchar chip,
+                         uchar *buffer, int len, bool end_with_repeated_start)
+{
+       struct gpio_desc *scl = &i2c_bus->scl;
+       struct gpio_desc *sda = &i2c_bus->sda;
+       unsigned int delay = i2c_bus->delay;
+       int failures = 0;
+
+       PRINTD("%s: chip %x buffer %p len %d\n", __func__, chip, buffer, len);
+
+       send_start(scl, sda, delay);
+       if (write_byte(scl, sda, delay, chip << 1)) {
+               send_stop(scl, sda, delay);
+               PRINTD("i2c_write, no chip responded %02X\n", chip);
+               return -ENODEV;

-EIO I think

+       }
+
+       while (len-- > 0) {
+               if (write_byte(scl, sda, delay, *buffer++))
+                       failures++;
+       }
+
+       send_stop(scl, sda, delay);
+
+       return failures;
+}
+
+static int i2c_read_data(struct soft_i2c_bus *i2c_bus, uchar chip,
+                        uchar *buffer, int len)
+{
+       struct gpio_desc *scl = &i2c_bus->scl;
+       struct gpio_desc *sda = &i2c_bus->sda;
+       unsigned int delay = i2c_bus->delay;
+
+       PRINTD("%s: chip %x buffer: %x len %d\n", __func__, chip, buffer, len);
+
+       send_start(scl, sda, delay);
+       write_byte(scl, sda, delay, (chip << 1) | 1);   /* read cycle */
+
+       while (len-- > 0)
+               *buffer++ = read_byte(scl, sda, delay, len == 0);
+
+       send_stop(scl, sda, delay);
+
+       return 0;
+}
+
+static int soft_i2c_xfer(struct udevice *dev, struct i2c_msg *msg, int nmsgs)
+{
+       struct soft_i2c_bus *i2c_bus = dev_get_priv(dev);
+       int ret;
+
+       for (; nmsgs > 0; nmsgs--, msg++) {
+               bool next_is_read = nmsgs > 1 && (msg[1].flags & I2C_M_RD);
+               if (msg->flags & I2C_M_RD) {
+                       ret = i2c_read_data(i2c_bus, msg->addr, msg->buf,
+                                           msg->len);
+               } else {
+                       ret = i2c_write_data(i2c_bus, msg->addr, msg->buf,
+                                            msg->len, next_is_read);
+               }
+               if (ret)
+                       return -EREMOTEIO;
+       }
+
+       return 0;
+}
+
+static int soft_i2c_probe(struct udevice *dev, uint chip, uint chip_flags)
+{
+       struct soft_i2c_bus *i2c_bus = dev_get_priv(dev);
+       struct gpio_desc *scl = &i2c_bus->scl;
+       struct gpio_desc *sda = &i2c_bus->sda;
+       unsigned int delay = i2c_bus->delay;
+       int ret;
+
+       send_start(scl, sda, delay);
+       ret = write_byte(scl, sda, delay, (chip << 1) | 0);
+       send_stop(scl, sda, delay);
+
+       PRINTD("%s: bus: %d (%s) chip: %x flags: %x ret: %d\n",
+              __func__, dev->seq, dev->name, chip, chip_flags, ret);
+
+       return ret;
+}
+
+static int soft_i2c_set_bus_speed(struct udevice *dev, unsigned int speed)
+{
+       struct soft_i2c_bus *i2c_bus = dev_get_priv(dev);
+       struct gpio_desc *scl = &i2c_bus->scl;
+       struct gpio_desc *sda = &i2c_bus->sda;
+
+       i2c_bus->speed = speed;
+       i2c_bus->delay = lldiv(1000000, speed << 2);
+
+       (scl, sda, i2c_bus->delay);
+
+       PRINTD("%s: bus: %d (%s) speed: %u Hz (1/4 of period: %lu us)\n",
+              __func__, dev->seq, dev->name, speed, i2c_bus->delay);
+
+       return 0;
+}
+
+static int soft_i2c_ofdata_to_platdata(struct udevice *dev)
+{
+       struct soft_i2c_bus *i2c_bus = dev_get_priv(dev);
+       const void *blob = gd->fdt_blob;
+       char *pin_name;
+       int ret;
+
+       pin_name = "clock-pin";

nit: You don't need this variable

+       ret = gpio_request_by_name_nodev(blob, dev->of_offset, pin_name,
+                                        0, &i2c_bus->scl, GPIOD_IS_OUT);

You should not use the nodev version when you have a device. Also below.

+       if (ret)
+               goto error;
+
+       pin_name = "data-pin";

nit: or here

+       ret = gpio_request_by_name_nodev(blob, dev->of_offset, pin_name,
+                                        0, &i2c_bus->sda, GPIOD_IS_OUT);
+       if (ret)
+               goto error;
+
+       PRINTD("%s: bus: %d (%s) fdt node ok\n", __func__, dev->seq, dev->name);
+
+       return 0;
+error:
+       error("Can't get %s for soft i2c dev: %s", pin_name, dev->name);
+       return ret;
+}
+
+static const struct dm_i2c_ops soft_i2c_ops = {
+       .xfer           = soft_i2c_xfer,
+       .probe_chip     = soft_i2c_probe,
+       .set_bus_speed  = soft_i2c_set_bus_speed,
+};
+
+static const struct udevice_id soft_i2c_ids[] = {
+       { .compatible = "soft-i2c" },
+       { }
+};
+
+U_BOOT_DRIVER(soft_i2c) = {
+       .name   = "soft-i2c",
+       .id     = UCLASS_I2C,
+       .of_match = soft_i2c_ids,
+       .ofdata_to_platdata = soft_i2c_ofdata_to_platdata,
+       .priv_auto_alloc_size = sizeof(struct soft_i2c_bus),
+       .ops    = &soft_i2c_ops,
+};
+#endif /* CONFIG_DM_I2C_SOFT */
--
1.9.1


Regards,
Simon


--
DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot

Reply via email to