From mboxrd@z Thu Jan 1 00:00:00 1970 From: Przemyslaw Marczak Date: Thu, 26 Mar 2015 14:18:28 +0100 Subject: [U-Boot] [PATCH 1/3] dm: i2c soft: enable driver model for software i2c driver In-Reply-To: <5510FDBD.2020109@denx.de> References: <1425983444-18565-1-git-send-email-p.marczak@samsung.com> <1425983444-18565-2-git-send-email-p.marczak@samsung.com> <5510FDBD.2020109@denx.de> Message-ID: <55140724.8060304@samsung.com> List-Id: MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: u-boot@lists.denx.de Hello, On 03/24/2015 07:01 AM, Heiko Schocher wrote: > Hello Simon, Przemyslaw, > > Am 24.03.2015 00:38, schrieb Simon Glass: >> Hi Przemyslaw, >> >> On 10 March 2015 at 04:30, Przemyslaw Marczak >> 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 at 13500000"; >>> i2c6 = "/soft-i2c at 1"; >>> [...] >>> }; >>> >>> /* Define the basic bus attributes */ >>> soft-i2c at 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 at 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? > Ok, I will do this for v2. >>> Signed-off-by: Przemyslaw Marczak >>> Cc: Masahiro Yamada >>> Cc: Mike Frysinger >>> Cc: Simon Glass >>> Cc: Heiko Schocher > > 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 >>> + * >>> * (C) Copyright 2009 >>> * Heiko Schocher, DENX Software Engineering, hs at denx.de. >>> * Changes for multibus/multiadapter I2C support. >>> @@ -14,6 +17,11 @@ >>> */ >>> >>> #include >>> +#include >>> +#include >>> +#include >>> +#include >>> +#include >>> #ifdef CONFIG_MPC8260 /* only valid for MPC8260 */ >>> #include >>> #include >>> @@ -32,11 +40,9 @@ >>> #if defined(CONFIG_MPC852T) || defined(CONFIG_MPC866) >>> #include >>> #endif >>> -#include >>> >>> +#if defined(CONFIG_SYS_I2C) >>> #if defined(CONFIG_SOFT_I2C_GPIO_SCL) >>> -# include >>> - >>> # 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 >>> * 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 Yes, I will make the new file. Best regards, -- Przemyslaw Marczak Samsung R&D Institute Poland Samsung Electronics p.marczak at samsung.com