[U-Boot] [PATCH] i2c:gpio:s5p: I2C GPIO Software implementation

This commit adds I2C software support for Samsung's S5PC110 family of processors. The generic drivers/i2c/soft_i2c framework is used, with routines provided by this commit.
Signed-off-by: Lukasz Majewski l.majewski@samsung.com --- arch/arm/include/asm/arch-s5pc1xx/i2c-gpio.h | 52 +++++++++++ board/samsung/goni/goni.c | 33 +++++++- drivers/i2c/Makefile | 1 + drivers/i2c/s5p_gpio_i2c.c | 123 ++++++++++++++++++++++++++ include/configs/s5p_goni.h | 8 ++ 5 files changed, 216 insertions(+), 1 deletions(-) create mode 100644 arch/arm/include/asm/arch-s5pc1xx/i2c-gpio.h create mode 100644 drivers/i2c/s5p_gpio_i2c.c
diff --git a/arch/arm/include/asm/arch-s5pc1xx/i2c-gpio.h b/arch/arm/include/asm/arch-s5pc1xx/i2c-gpio.h new file mode 100644 index 0000000..83b8179 --- /dev/null +++ b/arch/arm/include/asm/arch-s5pc1xx/i2c-gpio.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2009 Samsung Electronics + * Minkyu Kang mk7.kang@samsung.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 + */ + +#ifndef __I2C_GPIO_H_ +#define __I2C_GPIO_H_ + +#ifndef __ASSEMBLY__ +struct i2c_gpio_bus_data { + unsigned int gpio_base; + unsigned int sda_pin; + unsigned int scl_pin; +}; + +struct i2c_gpio_bus { + struct i2c_gpio_bus_data *bus; +}; + +void i2c_gpio_init(struct i2c_gpio_bus *bus, int len, int index); +void i2c_gpio_dir(int dir); +void i2c_gpio_set(int line, int value); +int i2c_gpio_get(void); +void i2c_gpio_set_bus(int index); + +#define I2C_SDA(x) i2c_gpio_set(1, x) +#define I2C_SCL(x) i2c_gpio_set(0, x) +#define I2C_READ (!!i2c_gpio_get()) +#define I2C_ACTIVE i2c_gpio_dir(1) +#define I2C_TRISTATE i2c_gpio_dir(0) +#define I2C_DELAY udelay(5) + +#endif +#endif diff --git a/board/samsung/goni/goni.c b/board/samsung/goni/goni.c index 581935d..8149ebf 100644 --- a/board/samsung/goni/goni.c +++ b/board/samsung/goni/goni.c @@ -1,7 +1,8 @@ /* - * Copyright (C) 2008-2009 Samsung Electronics + * Copyright (C) 2008-2011 Samsung Electronics * Minkyu Kang mk7.kang@samsung.com * Kyungmin Park kyungmin.park@samsung.com + * Lukasz Majewski l.majewski@samsung.com * * See file CREDITS for list of people who contributed to this * project. @@ -23,6 +24,7 @@ */
#include <common.h> +#include <i2c.h> #include <asm/arch/gpio.h> #include <asm/arch/mmc.h>
@@ -96,3 +98,32 @@ int board_mmc_init(bd_t *bis) return s5p_mmc_init(0, 4); } #endif + +/* Define I2C parameters to handle usb transmission */ +enum { I2C_PMIC, I2C_NUM, }; + +/* + * i2c pmic + * SDA: GPJ4[0] + * SCL: GPJ4[3] + */ +static struct i2c_gpio_bus_data i2c_pmic = { + .sda_pin = 0, + .scl_pin = 3, +}; + +static struct i2c_gpio_bus i2c_gpio[] = { + { + .bus = &i2c_pmic, + }, +}; + +#define S5PC110_GPIO_J3 0XE02002C0 + +void i2c_init_board(void) +{ + i2c_gpio[I2C_PMIC].bus = &i2c_pmic; + i2c_gpio[I2C_PMIC].bus->gpio_base = S5PC110_GPIO_J3; + + i2c_gpio_init(i2c_gpio, I2C_NUM, I2C_PMIC); +} diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile index a48047a..47e9c56 100644 --- a/drivers/i2c/Makefile +++ b/drivers/i2c/Makefile @@ -42,6 +42,7 @@ COBJS-$(CONFIG_SOFT_I2C) += soft_i2c.o COBJS-$(CONFIG_SPEAR_I2C) += spr_i2c.o COBJS-$(CONFIG_TSI108_I2C) += tsi108_i2c.o COBJS-$(CONFIG_U8500_I2C) += u8500_i2c.o +COBJS-$(CONFIG_S5P_GPIO_I2C) += s5p_gpio_i2c.o
COBJS := $(COBJS-y) SRCS := $(COBJS:.o=.c) diff --git a/drivers/i2c/s5p_gpio_i2c.c b/drivers/i2c/s5p_gpio_i2c.c new file mode 100644 index 0000000..309bd4d --- /dev/null +++ b/drivers/i2c/s5p_gpio_i2c.c @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2009 Samsung Electronics + * Minkyu Kang mk7.kang@samsung.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 + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/gpio.h> +#include <asm/arch/i2c-gpio.h> +#include <i2c.h> + +#ifdef CONFIG_SOFT_I2C + +static struct i2c_gpio_bus *i2c_gpio; + +void i2c_gpio_init(struct i2c_gpio_bus *bus, int len, int index) +{ + int i; + struct s5p_gpio_bank *bank; + + i2c_gpio = bus; + + /* init all i2c gpio buses */ + for (i = 0; i < len; i++) { + if (!i2c_gpio[i].bus) + continue; + + bank = (struct s5p_gpio_bank *)i2c_gpio[i].bus->gpio_base; + if (!bank) + continue; + + /* SDA */ + gpio_direction_output(bank, + i2c_gpio[i].bus->sda_pin, 1); + + /* SCL */ + gpio_direction_output(bank, + i2c_gpio[i].bus->scl_pin, 1); + } + + /* set default bus */ + i2c_set_bus_num(index); +} + +void i2c_gpio_set(int line, int value) +{ + struct s5p_gpio_bank *bank; + unsigned int bus_index; + + bus_index = i2c_get_bus_num(); + + if (!i2c_gpio[bus_index].bus) + return; + + bank = (struct s5p_gpio_bank *)i2c_gpio[bus_index].bus->gpio_base; + if (!bank) + return; + + if (line) + line = i2c_gpio[bus_index].bus->sda_pin; + else + line = i2c_gpio[bus_index].bus->scl_pin; + + gpio_set_value(bank, line, value); +} + +int i2c_gpio_get(void) +{ + struct s5p_gpio_bank *bank; + unsigned int bus_index; + + bus_index = i2c_get_bus_num(); + if (!i2c_gpio[bus_index].bus) + return 0; + + bank = (struct s5p_gpio_bank *)i2c_gpio[bus_index].bus->gpio_base; + if (!bank) + return 0; + + return gpio_get_value(bank, i2c_gpio[bus_index].bus->sda_pin); +} + +void i2c_gpio_dir(int dir) +{ + struct s5p_gpio_bank *bank; + unsigned int bus_index; + + bus_index = i2c_get_bus_num(); + if (!i2c_gpio[bus_index].bus) + return; + + bank = (struct s5p_gpio_bank *)i2c_gpio[bus_index].bus->gpio_base; + if (!bank) + return; + + if (dir) { + gpio_direction_output(bank, + i2c_gpio[bus_index].bus->sda_pin, 0); + } else { + gpio_direction_input(bank, + i2c_gpio[bus_index].bus->sda_pin); + } +} + +#endif /* CONFIG_SOFT_I2C */ diff --git a/include/configs/s5p_goni.h b/include/configs/s5p_goni.h index d648ce8..50726f7 100644 --- a/include/configs/s5p_goni.h +++ b/include/configs/s5p_goni.h @@ -221,4 +221,12 @@
#define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SYS_LOAD_ADDR - 0x1000000)
+/* I2C Soft */ +#include <asm/arch/i2c-gpio.h> +#define CONFIG_S5P_GPIO_I2C 1 +#define CONFIG_SOFT_I2C 1 +#define CONFIG_SYS_I2C_INIT_BOARD +#define CONFIG_SYS_I2C_SPEED 50000 +#define CONFIG_I2C_MULTI_BUS +#define CONFIG_SYS_MAX_I2C_BUS 7 #endif /* __CONFIG_H */

On Tuesday, July 05, 2011 08:23:41 Lukasz Majewski wrote:
This commit adds I2C software support for Samsung's S5PC110 family of processors. The generic drivers/i2c/soft_i2c framework is used, with routines provided by this commit.
if you simply implemented the generic gpio layer (asm/gpio.h), the soft_i2c.c code already handles gluing to GPIO pins. then you wouldnt need a sep driver at all. you can see the bf561-ezkit already using this code. -mike

Hello Mike,
Mike Frysinger wrote:
On Tuesday, July 05, 2011 08:23:41 Lukasz Majewski wrote:
This commit adds I2C software support for Samsung's S5PC110 family of processors. The generic drivers/i2c/soft_i2c framework is used, with routines provided by this commit.
if you simply implemented the generic gpio layer (asm/gpio.h), the soft_i2c.c code already handles gluing to GPIO pins. then you wouldnt need a sep driver at all. you can see the bf561-ezkit already using this code. -mike
Yes, that was my thought too. No seperate i2c driver should be needed here.
bye, Heiko

On Wed, 06 Jul 2011 07:56:20 +0200 Heiko Schocher hs@denx.de wrote:
Hello Mike,
Mike Frysinger wrote:
On Tuesday, July 05, 2011 08:23:41 Lukasz Majewski wrote:
This commit adds I2C software support for Samsung's S5PC110 family of processors. The generic drivers/i2c/soft_i2c framework is used, with routines provided by this commit.
if you simply implemented the generic gpio layer (asm/gpio.h), the soft_i2c.c code already handles gluing to GPIO pins. then you wouldnt need a sep driver at all. you can see the bf561-ezkit already using this code. -mike
Yes, that was my thought too. No seperate i2c driver should be needed here.
bye, Heiko
Thanks Mike and Heiko for reply.
However I've got some extra question.
In the bf651-ezkit.h file I can see the I2C definition:
#define CONFIG_SOFT_I2C #define CONFIG_SOFT_I2C_GPIO_SCL GPIO_PF0 #define CONFIG_SOFT_I2C_GPIO_SDA GPIO_PF1
My concern is about the situation when SoC needs more than one Software I2C run via GPIO?
Please consider following scenario: One sensor is connected to pins 1(SCL) and 3(SDA) and another to 4(SCL) and 5(SDA) in a GPIO port.
As fair as I've understood the software_i2c framework, it is supposed to run only one instance of GPIO I2C.
Is there any way to "instantiate" more than one I2C GPIO interface via software_i2c?

Hello Lukasz,
Lukasz Majewski wrote:
On Wed, 06 Jul 2011 07:56:20 +0200 Heiko Schocher hs@denx.de wrote:
Hello Mike,
Mike Frysinger wrote:
On Tuesday, July 05, 2011 08:23:41 Lukasz Majewski wrote:
This commit adds I2C software support for Samsung's S5PC110 family of processors. The generic drivers/i2c/soft_i2c framework is used, with routines provided by this commit.
if you simply implemented the generic gpio layer (asm/gpio.h), the soft_i2c.c code already handles gluing to GPIO pins. then you wouldnt need a sep driver at all. you can see the bf561-ezkit already using this code. -mike
Yes, that was my thought too. No seperate i2c driver should be needed here.
bye, Heiko
Thanks Mike and Heiko for reply.
However I've got some extra question.
In the bf651-ezkit.h file I can see the I2C definition:
#define CONFIG_SOFT_I2C #define CONFIG_SOFT_I2C_GPIO_SCL GPIO_PF0 #define CONFIG_SOFT_I2C_GPIO_SDA GPIO_PF1
My concern is about the situation when SoC needs more than one Software I2C run via GPIO?
Please consider following scenario: One sensor is connected to pins 1(SCL) and 3(SDA) and another to 4(SCL) and 5(SDA) in a GPIO port.
As fair as I've understood the software_i2c framework, it is supposed to run only one instance of GPIO I2C.
Is there any way to "instantiate" more than one I2C GPIO interface via software_i2c?
It should be possible (not tested), but not very nice:
First, you have to define CONFIG_I2C_MULTI_BUS and CONFIG_SYS_MAX_I2C_BUS
Then your CONFIG_SOFT_I2C_GPIO_SDA and CONFIG_SOFT_I2C_GPIO_SCL should look something like this:
#define CONFIG_SOFT_I2C_GPIO_SDA get_sda_pin
with
int get_sda_pin(void) { int busnr = i2c_get_bus_num(); switch (busnr) { case 0: return 3; break; case 1: return 5; break; [...] } }
Cleaner would be to get the i2c multibus branch to mainline, see: http://git.denx.de/?p=u-boot/u-boot-i2c.git;a=shortlog;h=refs/heads/multibus...
bye, Heiko
participants (3)
-
Heiko Schocher
-
Lukasz Majewski
-
Mike Frysinger