[U-Boot] [PATCH 1/3] dm: i2c soft: enable driver model for software i2c driver
Przemyslaw Marczak
p.marczak at samsung.com
Thu Mar 26 14:18:28 CET 2015
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 <p.marczak at 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 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 <p.marczak at samsung.com>
>>> Cc: Masahiro Yamada <yamada.m at jp.panasonic.com>
>>> Cc: Mike Frysinger <vapier at gentoo.org>
>>> Cc: Simon Glass <sjg at chromium.org>
>>> Cc: Heiko Schocher <hs at 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.marczak at samsung.com>
>>> + *
>>> * (C) Copyright 2009
>>> * Heiko Schocher, DENX Software Engineering, hs at 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
Yes, I will make the new file.
Best regards,
--
Przemyslaw Marczak
Samsung R&D Institute Poland
Samsung Electronics
p.marczak at samsung.com
More information about the U-Boot
mailing list