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);