All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH 0/8 V2] EXYNOS5: Enable I2C support
@ 2012-06-07  6:09 Rajeshwari Shinde
  2012-06-07  6:09 ` [U-Boot] [PATCH 1/8 V2] EXYNOS: CLK: Add i2c clock Rajeshwari Shinde
                   ` (7 more replies)
  0 siblings, 8 replies; 19+ messages in thread
From: Rajeshwari Shinde @ 2012-06-07  6:09 UTC (permalink / raw)
  To: u-boot

This patch set enables I2C support for EXYNOS5.
This patchset modifies the s3c24x0 I2C driver to use same for EXYNOS5.
Multichannel support has been added to the s3c24x0 I2C driver.
s3c24x0_i2c struct has been moved to a common place as it can used
by different SOC's.

Changes in V2:
	- Incorporated review comments from Simon Glass.
	- Aligned the pinmux functionality as per latest comments.

This patchset depends on the following patch:
"[U-Boot] [PATCH 1/2 V6] EXYNOS5: PINMUX: Added default pinumx settings"

Rajeshwari Shinde (8):
  EXYNOS: CLK: Add i2c clock
  EXYNOS: Add I2C base address.
  EXYNOS: PINMUX: Add pinmux support for I2C
  I2C: Move struct s3c24x0_i2c to a common place.
  I2C: S3C24X0: Add offset to calculate next i2c channel base address
  I2C: Modify the I2C driver for EXYNOS5
  I2C: Add support for Multi channel
  CONFIG: SMDK5250: I2C: Enable I2C

 arch/arm/cpu/armv7/exynos/clock.c           |   33 +++
 arch/arm/cpu/armv7/exynos/pinmux.c          |   52 +++++
 arch/arm/include/asm/arch-exynos/clk.h      |    1 +
 arch/arm/include/asm/arch-exynos/cpu.h      |    3 +
 arch/arm/include/asm/arch-exynos/periph.h   |    8 +
 arch/arm/include/asm/arch-s3c24x0/s3c24x0.h |   10 -
 drivers/i2c/s3c24x0_i2c.c                   |  281 ++++++++++++++++++++-------
 drivers/i2c/s3c24x0_i2c.h                   |   39 ++++
 include/configs/smdk5250.h                  |    8 +
 9 files changed, 352 insertions(+), 83 deletions(-)
 create mode 100644 drivers/i2c/s3c24x0_i2c.h

-- 
1.7.4.4

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [U-Boot] [PATCH 1/8 V2] EXYNOS: CLK: Add i2c clock
  2012-06-07  6:09 [U-Boot] [PATCH 0/8 V2] EXYNOS5: Enable I2C support Rajeshwari Shinde
@ 2012-06-07  6:09 ` Rajeshwari Shinde
  2012-06-12  5:46   ` Simon Glass
  2012-06-07  6:09 ` [U-Boot] [PATCH 2/8 V2] EXYNOS: Add I2C base address Rajeshwari Shinde
                   ` (6 subsequent siblings)
  7 siblings, 1 reply; 19+ messages in thread
From: Rajeshwari Shinde @ 2012-06-07  6:09 UTC (permalink / raw)
  To: u-boot

This adds i2c clock information for EXYNOS5.

Signed-off-by: Alim Akhtar <alim.akhtar@samsung.com>
Signed-off-by: Doug Anderson <dianders@chromium.org>
Signed-off-by: Rajeshwari Shinde <rajeshwari.s@samsung.com>
Acked-by: Simon Glass <sjg@chromium.org>
---
changes in V2:
	- Incorporated comments from Simon Glass which are removed extra 
	braces around (readl(&clk->div_top1)) >> 24 and	gave a tab space for 
	return statement.
 arch/arm/cpu/armv7/exynos/clock.c      |   33 ++++++++++++++++++++++++++++++++
 arch/arm/include/asm/arch-exynos/clk.h |    1 +
 2 files changed, 34 insertions(+), 0 deletions(-)

diff --git a/arch/arm/cpu/armv7/exynos/clock.c b/arch/arm/cpu/armv7/exynos/clock.c
index 330bd75..a80928b 100644
--- a/arch/arm/cpu/armv7/exynos/clock.c
+++ b/arch/arm/cpu/armv7/exynos/clock.c
@@ -578,6 +578,29 @@ void exynos4_set_mipi_clk(void)
 	writel(cfg, &clk->div_lcd0);
 }
 
+/*
+ * I2C
+ *
+ * exynos5: obtaining the I2C clock
+ */
+static unsigned long exynos5_get_i2c_clk(void)
+{
+	struct exynos5_clock *clk =
+		(struct exynos5_clock *)samsung_get_base_clock();
+	unsigned long aclk_66, aclk_66_pre, sclk;
+	unsigned int ratio;
+
+	sclk = get_pll_clk(MPLL);
+
+	ratio = (readl(&clk->div_top1)) >> 24;
+	ratio &= (0x7);
+	aclk_66_pre = sclk/(ratio+1);
+	ratio = readl(&clk->div_top0);
+	ratio &= (0x7);
+	aclk_66 = aclk_66_pre/(ratio+1);
+	return aclk_66;
+}
+
 unsigned long get_pll_clk(int pllreg)
 {
 	if (cpu_is_exynos5())
@@ -594,6 +617,16 @@ unsigned long get_arm_clk(void)
 		return exynos4_get_arm_clk();
 }
 
+unsigned long get_i2c_clk(void)
+{
+	if (cpu_is_exynos5()) {
+		return exynos5_get_i2c_clk();
+	} else {
+		debug("I2C clock is not set for this CPU\n");
+		return 0;
+	}
+}
+
 unsigned long get_pwm_clk(void)
 {
 	if (cpu_is_exynos5())
diff --git a/arch/arm/include/asm/arch-exynos/clk.h b/arch/arm/include/asm/arch-exynos/clk.h
index 637fb4b..72dc655 100644
--- a/arch/arm/include/asm/arch-exynos/clk.h
+++ b/arch/arm/include/asm/arch-exynos/clk.h
@@ -30,6 +30,7 @@
 
 unsigned long get_pll_clk(int pllreg);
 unsigned long get_arm_clk(void);
+unsigned long get_i2c_clk(void);
 unsigned long get_pwm_clk(void);
 unsigned long get_uart_clk(int dev_index);
 void set_mmc_clk(int dev_index, unsigned int div);
-- 
1.7.4.4

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [U-Boot] [PATCH 2/8 V2] EXYNOS: Add I2C base address.
  2012-06-07  6:09 [U-Boot] [PATCH 0/8 V2] EXYNOS5: Enable I2C support Rajeshwari Shinde
  2012-06-07  6:09 ` [U-Boot] [PATCH 1/8 V2] EXYNOS: CLK: Add i2c clock Rajeshwari Shinde
@ 2012-06-07  6:09 ` Rajeshwari Shinde
  2012-06-07  6:09 ` [U-Boot] [PATCH 3/8 V2] EXYNOS: PINMUX: Add pinmux support for I2C Rajeshwari Shinde
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 19+ messages in thread
From: Rajeshwari Shinde @ 2012-06-07  6:09 UTC (permalink / raw)
  To: u-boot

This patch adds the base address for I2C.

Signed-off-by: Alim Akhtar <alim.akhtar@samsung.com>
Signed-off-by: Rajeshwari Shinde <rajeshwari.s@samsung.com>
Acked-by: Simon Glass <sjg@chromium.org>
---
 arch/arm/include/asm/arch-exynos/cpu.h |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/arch/arm/include/asm/arch-exynos/cpu.h b/arch/arm/include/asm/arch-exynos/cpu.h
index b1e22f2..093bcc1 100644
--- a/arch/arm/include/asm/arch-exynos/cpu.h
+++ b/arch/arm/include/asm/arch-exynos/cpu.h
@@ -48,6 +48,7 @@
 #define EXYNOS4_SROMC_BASE		0x12570000
 #define EXYNOS4_USBPHY_BASE		0x125B0000
 #define EXYNOS4_UART_BASE		0x13800000
+#define EXYNOS4_I2C_BASE		0x13860000
 #define EXYNOS4_ADC_BASE		0x13910000
 #define EXYNOS4_PWMTIMER_BASE		0x139D0000
 #define EXYNOS4_MODEM_BASE		0x13A00000
@@ -74,6 +75,7 @@
 #define EXYNOS5_USBOTG_BASE		0x12480000
 #define EXYNOS5_USBPHY_BASE		0x12480000
 #define EXYNOS5_UART_BASE		0x12C00000
+#define EXYNOS5_I2C_BASE		0x12C60000
 #define EXYNOS5_PWMTIMER_BASE		0x12DD0000
 #define EXYNOS5_GPIO_PART2_BASE		0x13400000
 #define EXYNOS5_FIMD_BASE		0x14400000
@@ -146,6 +148,7 @@ SAMSUNG_BASE(adc, ADC_BASE)
 SAMSUNG_BASE(clock, CLOCK_BASE)
 SAMSUNG_BASE(sysreg, SYSREG_BASE)
 SAMSUNG_BASE(fimd, FIMD_BASE)
+SAMSUNG_BASE(i2c, I2C_BASE)
 SAMSUNG_BASE(mipi_dsim, MIPI_DSIM_BASE)
 SAMSUNG_BASE(gpio_part1, GPIO_PART1_BASE)
 SAMSUNG_BASE(gpio_part2, GPIO_PART2_BASE)
-- 
1.7.4.4

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [U-Boot] [PATCH 3/8 V2] EXYNOS: PINMUX: Add pinmux support for I2C
  2012-06-07  6:09 [U-Boot] [PATCH 0/8 V2] EXYNOS5: Enable I2C support Rajeshwari Shinde
  2012-06-07  6:09 ` [U-Boot] [PATCH 1/8 V2] EXYNOS: CLK: Add i2c clock Rajeshwari Shinde
  2012-06-07  6:09 ` [U-Boot] [PATCH 2/8 V2] EXYNOS: Add I2C base address Rajeshwari Shinde
@ 2012-06-07  6:09 ` Rajeshwari Shinde
  2012-06-12  5:47   ` Simon Glass
  2012-06-07  6:09 ` [U-Boot] [PATCH 4/8 V2] I2C: Move struct s3c24x0_i2c to a common place Rajeshwari Shinde
                   ` (4 subsequent siblings)
  7 siblings, 1 reply; 19+ messages in thread
From: Rajeshwari Shinde @ 2012-06-07  6:09 UTC (permalink / raw)
  To: u-boot

This patch adds pinmux code for I2C.

Signed-off-by: Rajeshwari Shinde <rajeshwari.s@samsung.com>
Acked-by: Simon Glass <sjg@chromium.org>
---
Changes in V2:
	- Aligned the pinmux functionality as per the latest comments.
This patch depends on the following patch:
"[U-Boot] [PATCH 1/2 V6] EXYNOS5: PINMUX: Added default pinumx settings"
 arch/arm/cpu/armv7/exynos/pinmux.c        |   52 +++++++++++++++++++++++++++++
 arch/arm/include/asm/arch-exynos/periph.h |    8 ++++
 2 files changed, 60 insertions(+), 0 deletions(-)

diff --git a/arch/arm/cpu/armv7/exynos/pinmux.c b/arch/arm/cpu/armv7/exynos/pinmux.c
index 597e487..d3314a1 100644
--- a/arch/arm/cpu/armv7/exynos/pinmux.c
+++ b/arch/arm/cpu/armv7/exynos/pinmux.c
@@ -182,6 +182,48 @@ static void exynos5_sromc_config(int flags)
 	}
 }
 
+static void exynos5_i2c_config(int peripheral, int flags)
+{
+
+	struct exynos5_gpio_part1 *gpio1 =
+		(struct exynos5_gpio_part1 *) samsung_get_base_gpio_part1();
+
+	switch (peripheral) {
+	case PERIPH_ID_I2C0:
+		s5p_gpio_cfg_pin(&gpio1->b3, 0, GPIO_FUNC(0x2));
+		s5p_gpio_cfg_pin(&gpio1->b3, 1, GPIO_FUNC(0x2));
+		break;
+	case PERIPH_ID_I2C1:
+		s5p_gpio_cfg_pin(&gpio1->b3, 2, GPIO_FUNC(0x2));
+		s5p_gpio_cfg_pin(&gpio1->b3, 3, GPIO_FUNC(0x2));
+		break;
+	case PERIPH_ID_I2C2:
+		s5p_gpio_cfg_pin(&gpio1->a0, 6, GPIO_FUNC(0x3));
+		s5p_gpio_cfg_pin(&gpio1->a0, 7, GPIO_FUNC(0x3));
+		break;
+	case PERIPH_ID_I2C3:
+		s5p_gpio_cfg_pin(&gpio1->a1, 2, GPIO_FUNC(0x3));
+		s5p_gpio_cfg_pin(&gpio1->a1, 3, GPIO_FUNC(0x3));
+		break;
+	case PERIPH_ID_I2C4:
+		s5p_gpio_cfg_pin(&gpio1->a2, 0, GPIO_FUNC(0x3));
+		s5p_gpio_cfg_pin(&gpio1->a2, 1, GPIO_FUNC(0x3));
+		break;
+	case PERIPH_ID_I2C5:
+		s5p_gpio_cfg_pin(&gpio1->a2, 2, GPIO_FUNC(0x3));
+		s5p_gpio_cfg_pin(&gpio1->a2, 3, GPIO_FUNC(0x3));
+		break;
+	case PERIPH_ID_I2C6:
+		s5p_gpio_cfg_pin(&gpio1->b1, 3, GPIO_FUNC(0x4));
+		s5p_gpio_cfg_pin(&gpio1->b1, 4, GPIO_FUNC(0x4));
+		break;
+	case PERIPH_ID_I2C7:
+		s5p_gpio_cfg_pin(&gpio1->b2, 2, GPIO_FUNC(0x3));
+		s5p_gpio_cfg_pin(&gpio1->b2, 3, GPIO_FUNC(0x3));
+		break;
+	}
+}
+
 static int exynos5_pinmux_config(int peripheral, int flags)
 {
 	switch (peripheral) {
@@ -200,6 +242,16 @@ static int exynos5_pinmux_config(int peripheral, int flags)
 	case PERIPH_ID_SROMC:
 		exynos5_sromc_config(flags);
 		break;
+	case PERIPH_ID_I2C0:
+	case PERIPH_ID_I2C1:
+	case PERIPH_ID_I2C2:
+	case PERIPH_ID_I2C3:
+	case PERIPH_ID_I2C4:
+	case PERIPH_ID_I2C5:
+	case PERIPH_ID_I2C6:
+	case PERIPH_ID_I2C7:
+		exynos5_i2c_config(peripheral, flags);
+		break;
 	default:
 		debug("%s: invalid peripheral %d", __func__, peripheral);
 		return -1;
diff --git a/arch/arm/include/asm/arch-exynos/periph.h b/arch/arm/include/asm/arch-exynos/periph.h
index 5db25aa..b861d7d 100644
--- a/arch/arm/include/asm/arch-exynos/periph.h
+++ b/arch/arm/include/asm/arch-exynos/periph.h
@@ -30,6 +30,14 @@
  *
  */
 enum periph_id {
+	PERIPH_ID_I2C0,
+	PERIPH_ID_I2C1,
+	PERIPH_ID_I2C2,
+	PERIPH_ID_I2C3,
+	PERIPH_ID_I2C4,
+	PERIPH_ID_I2C5,
+	PERIPH_ID_I2C6,
+	PERIPH_ID_I2C7,
 	PERIPH_ID_SDMMC0,
 	PERIPH_ID_SDMMC1,
 	PERIPH_ID_SDMMC2,
-- 
1.7.4.4

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [U-Boot] [PATCH 4/8 V2] I2C: Move struct s3c24x0_i2c to a common place.
  2012-06-07  6:09 [U-Boot] [PATCH 0/8 V2] EXYNOS5: Enable I2C support Rajeshwari Shinde
                   ` (2 preceding siblings ...)
  2012-06-07  6:09 ` [U-Boot] [PATCH 3/8 V2] EXYNOS: PINMUX: Add pinmux support for I2C Rajeshwari Shinde
@ 2012-06-07  6:09 ` Rajeshwari Shinde
  2012-06-07  6:09 ` [U-Boot] [PATCH 5/8 V2] I2C: S3C24X0: Add offset to calculate next i2c channel base address Rajeshwari Shinde
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 19+ messages in thread
From: Rajeshwari Shinde @ 2012-06-07  6:09 UTC (permalink / raw)
  To: u-boot

struct s3c24x0_i2c is being moved to common local header file so that
the same can be used by s3c series and exynos series SoCs.

Signed-off-by: Alim Akhtar <alim.akhtar@samsung.com>
Signed-off-by: Doug Anderson <dianders@chromium.org>
Signed-off-by: Rajeshwari Shinde <rajeshwari.s@samsung.com>
Acked-by: Simon Glass <sjg@chromium.org>
---
 arch/arm/include/asm/arch-s3c24x0/s3c24x0.h |   10 --------
 drivers/i2c/s3c24x0_i2c.h                   |   33 +++++++++++++++++++++++++++
 2 files changed, 33 insertions(+), 10 deletions(-)
 create mode 100644 drivers/i2c/s3c24x0_i2c.h

diff --git a/arch/arm/include/asm/arch-s3c24x0/s3c24x0.h b/arch/arm/include/asm/arch-s3c24x0/s3c24x0.h
index ca978c9..0f75c31 100644
--- a/arch/arm/include/asm/arch-s3c24x0/s3c24x0.h
+++ b/arch/arm/include/asm/arch-s3c24x0/s3c24x0.h
@@ -343,16 +343,6 @@ struct s3c24x0_watchdog {
 	u32	wtcnt;
 };
 
-
-/* IIC (see manual chapter 20) */
-struct s3c24x0_i2c {
-	u32	iiccon;
-	u32	iicstat;
-	u32	iicadd;
-	u32	iicds;
-};
-
-
 /* IIS (see manual chapter 21) */
 struct s3c24x0_i2s {
 #ifdef __BIG_ENDIAN
diff --git a/drivers/i2c/s3c24x0_i2c.h b/drivers/i2c/s3c24x0_i2c.h
new file mode 100644
index 0000000..2dd4b06
--- /dev/null
+++ b/drivers/i2c/s3c24x0_i2c.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2012 Samsung Electronics
+ *
+ * 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 _S3C24X0_I2C_H
+#define _S3C24X0_I2C_H
+
+struct s3c24x0_i2c {
+	u32	iiccon;
+	u32	iicstat;
+	u32	iicadd;
+	u32	iicds;
+	u32	iiclc;
+};
+#endif /* _S3C24X0_I2C_H */
-- 
1.7.4.4

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [U-Boot] [PATCH 5/8 V2] I2C: S3C24X0: Add offset to calculate next i2c channel base address
  2012-06-07  6:09 [U-Boot] [PATCH 0/8 V2] EXYNOS5: Enable I2C support Rajeshwari Shinde
                   ` (3 preceding siblings ...)
  2012-06-07  6:09 ` [U-Boot] [PATCH 4/8 V2] I2C: Move struct s3c24x0_i2c to a common place Rajeshwari Shinde
@ 2012-06-07  6:09 ` Rajeshwari Shinde
  2012-06-07  6:09 ` [U-Boot] [PATCH 6/8 V2] I2C: Modify the I2C driver for EXYNOS5 Rajeshwari Shinde
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 19+ messages in thread
From: Rajeshwari Shinde @ 2012-06-07  6:09 UTC (permalink / raw)
  To: u-boot

As exynos has more than one i2c channels. This patch adds offset padding
for struct s3c24x0_i2c, in order to get the new base address of next i2c channel.

Signed-off-by: Alim Akhtar <alim.akhtar@samsung.com>
Signed-off-by: Rajeshwari Shinde <rajeshwari.s@samsung.com>
Acked-by: Simon Glass <sjg@chromium.org>
---
 drivers/i2c/s3c24x0_i2c.h |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/drivers/i2c/s3c24x0_i2c.h b/drivers/i2c/s3c24x0_i2c.h
index 2dd4b06..d357a0a 100644
--- a/drivers/i2c/s3c24x0_i2c.h
+++ b/drivers/i2c/s3c24x0_i2c.h
@@ -29,5 +29,8 @@ struct s3c24x0_i2c {
 	u32	iicadd;
 	u32	iicds;
 	u32	iiclc;
+#ifdef CONFIG_EXYNOS5
+	uchar	res1[0xffec];
+#endif
 };
 #endif /* _S3C24X0_I2C_H */
-- 
1.7.4.4

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [U-Boot] [PATCH 6/8 V2] I2C: Modify the I2C driver for EXYNOS5
  2012-06-07  6:09 [U-Boot] [PATCH 0/8 V2] EXYNOS5: Enable I2C support Rajeshwari Shinde
                   ` (4 preceding siblings ...)
  2012-06-07  6:09 ` [U-Boot] [PATCH 5/8 V2] I2C: S3C24X0: Add offset to calculate next i2c channel base address Rajeshwari Shinde
@ 2012-06-07  6:09 ` Rajeshwari Shinde
  2012-06-12  5:52   ` Simon Glass
  2012-06-15  7:10   ` Joonyoung Shim
  2012-06-07  6:09 ` [U-Boot] [PATCH 7/8 V2] I2C: Add support for Multi channel Rajeshwari Shinde
  2012-06-07  6:09 ` [U-Boot] [PATCH 8/8 V2] CONFIG: SMDK5250: I2C: Enable I2C Rajeshwari Shinde
  7 siblings, 2 replies; 19+ messages in thread
From: Rajeshwari Shinde @ 2012-06-07  6:09 UTC (permalink / raw)
  To: u-boot

This patch modifies the S3C I2C driver to suppport EXYNOS5.
The cahnges made to driver are as follows:
	- I2C base address is passed as a parameter to many
	functions to avoid multiple #ifdef
	- I2C init for Exynos5 is made as different function.
	- Channel initialisation is moved to a commom funation
	as it is required by both the i2c_init.
	- Separate functions written to get I2C base address,
	peripheral id for pinmux support.
	- Hardcoding for I2CCON_ACKGEN removed.
	- Replaced printf with debug.
	- Checkpatch issues resolved.

Signed-off-by: Alim Akhtar <alim.akhtar@samsung.com>
Signed-off-by: Doug Anderson <dianders@chromium.org>
Signed-off-by: Rajeshwari Shinde <rajeshwari.s@samsung.com>
Acked-by: Simon Glass <sjg@chromium.org>
---
Changes in V2:
	- Removed #define for I2C cahnnels from hearder file except for I2C0.
	- Incorporated review comments from Simon Glass.
 drivers/i2c/s3c24x0_i2c.c |  254 ++++++++++++++++++++++++++++++++-------------
 drivers/i2c/s3c24x0_i2c.h |    3 +
 2 files changed, 184 insertions(+), 73 deletions(-)

diff --git a/drivers/i2c/s3c24x0_i2c.c b/drivers/i2c/s3c24x0_i2c.c
index ba6f39b..a71f147 100644
--- a/drivers/i2c/s3c24x0_i2c.c
+++ b/drivers/i2c/s3c24x0_i2c.c
@@ -27,10 +27,17 @@
  */
 
 #include <common.h>
+#ifdef CONFIG_EXYNOS5
+#include <asm/arch/clk.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/pinmux.h>
+#else
 #include <asm/arch/s3c24x0_cpu.h>
-
+#endif
 #include <asm/io.h>
 #include <i2c.h>
+#include "s3c24x0_i2c.h"
 
 #ifdef CONFIG_HARD_I2C
 
@@ -45,6 +52,7 @@
 
 #define I2CSTAT_BSY	0x20	/* Busy bit */
 #define I2CSTAT_NACK	0x01	/* Nack bit */
+#define I2CCON_ACKGEN	0x80	/* Acknowledge generation */
 #define I2CCON_IRPND	0x10	/* Interrupt pending bit */
 #define I2C_MODE_MT	0xC0	/* Master Transmit Mode */
 #define I2C_MODE_MR	0x80	/* Master Receive Mode */
@@ -53,6 +61,44 @@
 
 #define I2C_TIMEOUT 1		/* 1 second */
 
+#ifdef CONFIG_EXYNOS5
+static unsigned int g_current_bus;	/* Stores Current I2C Bus */
+
+/* We should not rely on any particular ordering of these IDs */
+static enum periph_id periph_for_dev[] = {
+	PERIPH_ID_I2C0,
+	PERIPH_ID_I2C1,
+	PERIPH_ID_I2C2,
+	PERIPH_ID_I2C3,
+	PERIPH_ID_I2C4,
+	PERIPH_ID_I2C5,
+	PERIPH_ID_I2C6,
+	PERIPH_ID_I2C7,
+};
+
+static enum periph_id i2c_get_periph_id(unsigned dev_index)
+{
+	if (dev_index < ARRAY_SIZE(periph_for_dev))
+		return periph_for_dev[dev_index];
+
+	debug("%s: invalid bus %d", __func__, dev_index);
+
+	return PERIPH_ID_NONE;
+}
+
+static struct s3c24x0_i2c *get_base_i2c(int bus_idx)
+{
+	struct s3c24x0_i2c *i2c = (struct s3c24x0_i2c *)samsung_get_base_i2c();
+
+	return &i2c[bus_idx];
+}
+
+static inline struct exynos5_gpio_part1 *exynos_get_base_gpio1(void)
+{
+	return (struct exynos5_gpio_part1 *)(EXYNOS5_GPIO_PART1_BASE);
+}
+
+#else
 static int GetI2CSDA(void)
 {
 	struct s3c24x0_gpio *gpio = s3c24x0_get_base_gpio();
@@ -77,16 +123,17 @@ static void SetI2CSCL(int x)
 	struct s3c24x0_gpio *gpio = s3c24x0_get_base_gpio();
 
 #ifdef CONFIG_S3C2410
-	writel((readl(&gpio->gpedat) & ~0x4000) | (x & 1) << 14, &gpio->gpedat);
+	writel((readl(&gpio->gpedat) & ~0x4000) |
+					(x & 1) << 14, &gpio->gpedat);
 #endif
 #ifdef CONFIG_S3C2400
 	writel((readl(&gpio->pgdat) & ~0x0040) | (x & 1) << 6, &gpio->pgdat);
 #endif
 }
+#endif
 
-static int WaitForXfer(void)
+static int WaitForXfer(struct s3c24x0_i2c *i2c)
 {
-	struct s3c24x0_i2c *i2c = s3c24x0_get_base_i2c();
 	int i;
 
 	i = I2C_TIMEOUT * 10000;
@@ -98,25 +145,84 @@ static int WaitForXfer(void)
 	return (readl(&i2c->iiccon) & I2CCON_IRPND) ? I2C_OK : I2C_NOK_TOUT;
 }
 
-static int IsACK(void)
+static int IsACK(struct s3c24x0_i2c *i2c)
 {
-	struct s3c24x0_i2c *i2c = s3c24x0_get_base_i2c();
-
 	return !(readl(&i2c->iicstat) & I2CSTAT_NACK);
 }
 
-static void ReadWriteByte(void)
+static void ReadWriteByte(struct s3c24x0_i2c *i2c)
 {
-	struct s3c24x0_i2c *i2c = s3c24x0_get_base_i2c();
-
 	writel(readl(&i2c->iiccon) & ~I2CCON_IRPND, &i2c->iiccon);
 }
 
+static void i2c_ch_init(struct s3c24x0_i2c *i2c, int speed, int slaveadd)
+{
+	ulong freq, pres = 16, div;
+#ifdef CONFIG_EXYNOS5
+	freq = get_i2c_clk();
+#else
+	freq = get_PCLK();
+#endif
+	/* calculate prescaler and divisor values */
+	if ((freq / pres / (16 + 1)) > speed)
+		/* set prescaler to 512 */
+		pres = 512;
+
+	div = 0;
+	while ((freq / pres / (div + 1)) > speed)
+		div++;
+
+	/* set prescaler, divisor according to freq, also set ACKGEN, IRQ */
+	writel((div & 0x0F) | 0xA0 | ((pres == 512) ? 0x40 : 0), &i2c->iiccon);
+
+	/* init to SLAVE REVEIVE and set slaveaddr */
+	writel(0, &i2c->iicstat);
+	writel(slaveadd, &i2c->iicadd);
+	/* program Master Transmit (and implicit STOP) */
+	writel(I2C_MODE_MT | I2C_TXRX_ENA, &i2c->iicstat);
+}
+
+static void i2c_bus_init(struct s3c24x0_i2c *i2c, unsigned int bus)
+{
+	int periph_id = i2c_get_periph_id(bus);
+
+	exynos_pinmux_config(periph_id, 0);
+
+	i2c_ch_init(i2c, CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
+}
+
+#ifdef CONFIG_EXYNOS5
+void i2c_init(int speed, int slaveadd)
+{
+	struct s3c24x0_i2c *i2c;
+	struct exynos5_gpio_part1 *gpio;
+	int i;
+
+	/* By default i2c channel 0 is the current bus */
+	g_current_bus = I2C0;
+
+	i2c = get_base_i2c(g_current_bus);
+
+	i2c_bus_init(i2c, g_current_bus);
+
+	/* wait for some time to give previous transfer a chance to finish */
+	i = I2C_TIMEOUT * 1000;
+	while ((readl(&i2c->iicstat) & I2CSTAT_BSY) && (i > 0)) {
+		udelay(1000);
+		i--;
+	}
+
+	gpio = exynos_get_base_gpio1();
+	writel((readl(&gpio->b3.con) & ~0x00FF) | 0x0022, &gpio->b3.con);
+
+	i2c_ch_init(i2c, speed, slaveadd);
+}
+
+#else
 void i2c_init(int speed, int slaveadd)
 {
 	struct s3c24x0_i2c *i2c = s3c24x0_get_base_i2c();
 	struct s3c24x0_gpio *gpio = s3c24x0_get_base_gpio();
-	ulong freq, pres = 16, div;
 	int i;
 
 	/* wait for some time to give previous transfer a chance to finish */
@@ -171,27 +277,9 @@ void i2c_init(int speed, int slaveadd)
 #endif
 	}
 
-	/* calculate prescaler and divisor values */
-	freq = get_PCLK();
-	if ((freq / pres / (16 + 1)) > speed)
-		/* set prescaler to 512 */
-		pres = 512;
-
-	div = 0;
-	while ((freq / pres / (div + 1)) > speed)
-		div++;
-
-	/* set prescaler, divisor according to freq, also set
-	 * ACKGEN, IRQ */
-	writel((div & 0x0F) | 0xA0 | ((pres == 512) ? 0x40 : 0), &i2c->iiccon);
-
-	/* init to SLAVE REVEIVE and set slaveaddr */
-	writel(0, &i2c->iicstat);
-	writel(slaveadd, &i2c->iicadd);
-	/* program Master Transmit (and implicit STOP) */
-	writel(I2C_MODE_MT | I2C_TXRX_ENA, &i2c->iicstat);
-
+	i2c_ch_init(i2c, speed, slaveadd);
 }
+#endif
 
 /*
  * cmd_type is 0 for write, 1 for read.
@@ -200,19 +288,19 @@ void i2c_init(int speed, int slaveadd)
  * by the char, we could make it larger if needed. If it is
  * 0 we skip the address write cycle.
  */
-static
-int i2c_transfer(unsigned char cmd_type,
-		 unsigned char chip,
-		 unsigned char addr[],
-		 unsigned char addr_len,
-		 unsigned char data[], unsigned short data_len)
+static int i2c_transfer(struct s3c24x0_i2c *i2c,
+			unsigned char cmd_type,
+			unsigned char chip,
+			unsigned char addr[],
+			unsigned char addr_len,
+			unsigned char data[],
+			unsigned short data_len)
 {
-	struct s3c24x0_i2c *i2c = s3c24x0_get_base_i2c();
 	int i, result;
 
 	if (data == 0 || data_len == 0) {
 		/*Don't support data transfer of no length or to address 0 */
-		printf("i2c_transfer: bad call\n");
+		debug("i2c_transfer: bad call\n");
 		return I2C_NOK;
 	}
 
@@ -226,7 +314,7 @@ int i2c_transfer(unsigned char cmd_type,
 	if (readl(&i2c->iicstat) & I2CSTAT_BSY)
 		return I2C_NOK_TOUT;
 
-	writel(readl(&i2c->iiccon) | 0x80, &i2c->iiccon);
+	writel(readl(&i2c->iiccon) | I2CCON_ACKGEN, &i2c->iiccon);
 	result = I2C_OK;
 
 	switch (cmd_type) {
@@ -238,16 +326,16 @@ int i2c_transfer(unsigned char cmd_type,
 			       &i2c->iicstat);
 			i = 0;
 			while ((i < addr_len) && (result == I2C_OK)) {
-				result = WaitForXfer();
+				result = WaitForXfer(i2c);
 				writel(addr[i], &i2c->iicds);
-				ReadWriteByte();
+				ReadWriteByte(i2c);
 				i++;
 			}
 			i = 0;
 			while ((i < data_len) && (result == I2C_OK)) {
-				result = WaitForXfer();
+				result = WaitForXfer(i2c);
 				writel(data[i], &i2c->iicds);
-				ReadWriteByte();
+				ReadWriteByte(i2c);
 				i++;
 			}
 		} else {
@@ -257,19 +345,19 @@ int i2c_transfer(unsigned char cmd_type,
 			       &i2c->iicstat);
 			i = 0;
 			while ((i < data_len) && (result = I2C_OK)) {
-				result = WaitForXfer();
+				result = WaitForXfer(i2c);
 				writel(data[i], &i2c->iicds);
-				ReadWriteByte();
+				ReadWriteByte(i2c);
 				i++;
 			}
 		}
 
 		if (result == I2C_OK)
-			result = WaitForXfer();
+			result = WaitForXfer(i2c);
 
 		/* send STOP */
 		writel(I2C_MODE_MR | I2C_TXRX_ENA, &i2c->iicstat);
-		ReadWriteByte();
+		ReadWriteByte(i2c);
 		break;
 
 	case I2C_READ:
@@ -279,13 +367,13 @@ int i2c_transfer(unsigned char cmd_type,
 			/* send START */
 			writel(readl(&i2c->iicstat) | I2C_START_STOP,
 			       &i2c->iicstat);
-			result = WaitForXfer();
-			if (IsACK()) {
+			result = WaitForXfer(i2c);
+			if (IsACK(i2c)) {
 				i = 0;
 				while ((i < addr_len) && (result == I2C_OK)) {
 					writel(addr[i], &i2c->iicds);
-					ReadWriteByte();
-					result = WaitForXfer();
+					ReadWriteByte(i2c);
+					result = WaitForXfer(i2c);
 					i++;
 				}
 
@@ -293,16 +381,17 @@ int i2c_transfer(unsigned char cmd_type,
 				/* resend START */
 				writel(I2C_MODE_MR | I2C_TXRX_ENA |
 				       I2C_START_STOP, &i2c->iicstat);
-				ReadWriteByte();
-				result = WaitForXfer();
+			ReadWriteByte(i2c);
+			result = WaitForXfer(i2c);
 				i = 0;
 				while ((i < data_len) && (result == I2C_OK)) {
 					/* disable ACK for final READ */
 					if (i == data_len - 1)
 						writel(readl(&i2c->iiccon)
-						       & ~0x80, &i2c->iiccon);
-					ReadWriteByte();
-					result = WaitForXfer();
+							& ~I2CCON_ACKGEN,
+							&i2c->iiccon);
+				ReadWriteByte(i2c);
+				result = WaitForXfer(i2c);
 					data[i] = readl(&i2c->iicds);
 					i++;
 				}
@@ -316,17 +405,18 @@ int i2c_transfer(unsigned char cmd_type,
 			/* send START */
 			writel(readl(&i2c->iicstat) | I2C_START_STOP,
 			       &i2c->iicstat);
-			result = WaitForXfer();
+			result = WaitForXfer(i2c);
 
-			if (IsACK()) {
+			if (IsACK(i2c)) {
 				i = 0;
 				while ((i < data_len) && (result == I2C_OK)) {
 					/* disable ACK for final READ */
 					if (i == data_len - 1)
 						writel(readl(&i2c->iiccon) &
-						       ~0x80, &i2c->iiccon);
-					ReadWriteByte();
-					result = WaitForXfer();
+							~I2CCON_ACKGEN,
+							&i2c->iiccon);
+					ReadWriteByte(i2c);
+					result = WaitForXfer(i2c);
 					data[i] = readl(&i2c->iicds);
 					i++;
 				}
@@ -337,22 +427,28 @@ int i2c_transfer(unsigned char cmd_type,
 
 		/* send STOP */
 		writel(I2C_MODE_MR | I2C_TXRX_ENA, &i2c->iicstat);
-		ReadWriteByte();
+		ReadWriteByte(i2c);
 		break;
 
 	default:
-		printf("i2c_transfer: bad call\n");
+		debug("i2c_transfer: bad call\n");
 		result = I2C_NOK;
 		break;
 	}
 
-	return (result);
+	return result;
 }
 
 int i2c_probe(uchar chip)
 {
+	struct s3c24x0_i2c *i2c;
 	uchar buf[1];
 
+#ifdef CONFIG_EXYNOS5
+	i2c = get_base_i2c(g_current_bus);
+#else
+	i2c = s3c24x0_get_base_i2c();
+#endif
 	buf[0] = 0;
 
 	/*
@@ -360,16 +456,17 @@ int i2c_probe(uchar chip)
 	 * address was <ACK>ed (i.e. there was a chip at that address which
 	 * drove the data line low).
 	 */
-	return i2c_transfer(I2C_READ, chip << 1, 0, 0, buf, 1) != I2C_OK;
+	return i2c_transfer(i2c, I2C_READ, chip << 1, 0, 0, buf, 1) != I2C_OK;
 }
 
 int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len)
 {
+	struct s3c24x0_i2c *i2c;
 	uchar xaddr[4];
 	int ret;
 
 	if (alen > 4) {
-		printf("I2C read: addr len %d not supported\n", alen);
+		debug("I2C read: addr len %d not supported\n", alen);
 		return 1;
 	}
 
@@ -396,10 +493,15 @@ int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len)
 		chip |= ((addr >> (alen * 8)) &
 			 CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW);
 #endif
-	if ((ret =
-	     i2c_transfer(I2C_READ, chip << 1, &xaddr[4 - alen], alen,
-			  buffer, len)) != 0) {
-		printf("I2c read: failed %d\n", ret);
+#ifdef CONFIG_EXYNOS5
+	i2c = get_base_i2c(g_current_bus);
+#else
+	i2c = s3c24x0_get_base_i2c();
+#endif
+	ret = i2c_transfer(i2c, I2C_READ, chip << 1, &xaddr[4 - alen], alen,
+			buffer, len);
+	if (ret != 0) {
+		debug("I2c read: failed %d\n", ret);
 		return 1;
 	}
 	return 0;
@@ -407,10 +509,11 @@ int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len)
 
 int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len)
 {
+	struct s3c24x0_i2c *i2c;
 	uchar xaddr[4];
 
 	if (alen > 4) {
-		printf("I2C write: addr len %d not supported\n", alen);
+		debug("I2C write: addr len %d not supported\n", alen);
 		return 1;
 	}
 
@@ -436,8 +539,13 @@ int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len)
 		chip |= ((addr >> (alen * 8)) &
 			 CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW);
 #endif
+#ifdef CONFIG_EXYNOS5
+	i2c = get_base_i2c(g_current_bus);
+#else
+	i2c = s3c24x0_get_base_i2c();
+#endif
 	return (i2c_transfer
-		(I2C_WRITE, chip << 1, &xaddr[4 - alen], alen, buffer,
+		(i2c, I2C_WRITE, chip << 1, &xaddr[4 - alen], alen, buffer,
 		 len) != 0);
 }
 #endif /* CONFIG_HARD_I2C */
diff --git a/drivers/i2c/s3c24x0_i2c.h b/drivers/i2c/s3c24x0_i2c.h
index d357a0a..57aafb1 100644
--- a/drivers/i2c/s3c24x0_i2c.h
+++ b/drivers/i2c/s3c24x0_i2c.h
@@ -23,6 +23,9 @@
 #ifndef _S3C24X0_I2C_H
 #define _S3C24X0_I2C_H
 
+/* I2C channels exynos5 has 8 i2c channel */
+#define I2C0		0
+
 struct s3c24x0_i2c {
 	u32	iiccon;
 	u32	iicstat;
-- 
1.7.4.4

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [U-Boot] [PATCH 7/8 V2] I2C: Add support for Multi channel
  2012-06-07  6:09 [U-Boot] [PATCH 0/8 V2] EXYNOS5: Enable I2C support Rajeshwari Shinde
                   ` (5 preceding siblings ...)
  2012-06-07  6:09 ` [U-Boot] [PATCH 6/8 V2] I2C: Modify the I2C driver for EXYNOS5 Rajeshwari Shinde
@ 2012-06-07  6:09 ` Rajeshwari Shinde
  2012-06-15  7:15   ` Joonyoung Shim
  2012-06-07  6:09 ` [U-Boot] [PATCH 8/8 V2] CONFIG: SMDK5250: I2C: Enable I2C Rajeshwari Shinde
  7 siblings, 1 reply; 19+ messages in thread
From: Rajeshwari Shinde @ 2012-06-07  6:09 UTC (permalink / raw)
  To: u-boot

This adds multiple i2c channel support for I2C.

Signed-off-by: Alim Akhtar <alim.akhtar@samsung.com>
Signed-off-by: Rajeshwari Shinde <rajeshwari.s@samsung.com>
Acked-by: Simon Glass <sjg@chromium.org>
---
 drivers/i2c/s3c24x0_i2c.c |   27 +++++++++++++++++++++++++++
 1 files changed, 27 insertions(+), 0 deletions(-)

diff --git a/drivers/i2c/s3c24x0_i2c.c b/drivers/i2c/s3c24x0_i2c.c
index a71f147..7521cb8 100644
--- a/drivers/i2c/s3c24x0_i2c.c
+++ b/drivers/i2c/s3c24x0_i2c.c
@@ -191,6 +191,33 @@ static void i2c_bus_init(struct s3c24x0_i2c *i2c, unsigned int bus)
 	i2c_ch_init(i2c, CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
 }
 
+/*
+ * MULTI BUS I2C support
+ */
+
+#ifdef CONFIG_I2C_MULTI_BUS
+int i2c_set_bus_num(unsigned int bus)
+{
+	struct s3c24x0_i2c *i2c;
+
+	if ((bus < 0) || (bus >= CONFIG_MAX_I2C_NUM)) {
+		debug("Bad bus: %d\n", bus);
+		return -1;
+	}
+
+	g_current_bus = bus;
+	i2c = get_base_i2c(g_current_bus);
+	i2c_bus_init(i2c, g_current_bus);
+
+	return 0;
+}
+
+unsigned int i2c_get_bus_num(void)
+{
+	return g_current_bus;
+}
+#endif
+
 #ifdef CONFIG_EXYNOS5
 void i2c_init(int speed, int slaveadd)
 {
-- 
1.7.4.4

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [U-Boot] [PATCH 8/8 V2] CONFIG: SMDK5250: I2C: Enable I2C
  2012-06-07  6:09 [U-Boot] [PATCH 0/8 V2] EXYNOS5: Enable I2C support Rajeshwari Shinde
                   ` (6 preceding siblings ...)
  2012-06-07  6:09 ` [U-Boot] [PATCH 7/8 V2] I2C: Add support for Multi channel Rajeshwari Shinde
@ 2012-06-07  6:09 ` Rajeshwari Shinde
  7 siblings, 0 replies; 19+ messages in thread
From: Rajeshwari Shinde @ 2012-06-07  6:09 UTC (permalink / raw)
  To: u-boot

This enables I2C support on smdk5250.

Signed-off-by: Alim Akhtar <alim.akhtar@samsung.com>
Signed-off-by: Doug Anderson <dianders@chromium.org>
Signed-off-by: Rajeshwari Shinde <rajeshwari.s@samsung.com>
Acked-by: Simon Glass <sjg@chromium.org>
---
 include/configs/smdk5250.h |    8 ++++++++
 1 files changed, 8 insertions(+), 0 deletions(-)

diff --git a/include/configs/smdk5250.h b/include/configs/smdk5250.h
index 9659f9e..1fca652 100644
--- a/include/configs/smdk5250.h
+++ b/include/configs/smdk5250.h
@@ -190,6 +190,14 @@
 
 #define CONFIG_SYS_INIT_SP_ADDR	(CONFIG_SYS_LOAD_ADDR - 0x1000000)
 
+/* I2C */
+#define CONFIG_HARD_I2C
+#define CONFIG_CMD_I2C
+#define CONFIG_SYS_I2C_SPEED	100000		/* 100 Kbps */
+#define CONFIG_DRIVER_S3C24X0_I2C
+#define CONFIG_I2C_MULTI_BUS
+#define CONFIG_MAX_I2C_NUM	8
+
 /* Ethernet Controllor Driver */
 #ifdef CONFIG_CMD_NET
 #define CONFIG_SMC911X
-- 
1.7.4.4

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [U-Boot] [PATCH 1/8 V2] EXYNOS: CLK: Add i2c clock
  2012-06-07  6:09 ` [U-Boot] [PATCH 1/8 V2] EXYNOS: CLK: Add i2c clock Rajeshwari Shinde
@ 2012-06-12  5:46   ` Simon Glass
  0 siblings, 0 replies; 19+ messages in thread
From: Simon Glass @ 2012-06-12  5:46 UTC (permalink / raw)
  To: u-boot

On Wed, Jun 6, 2012 at 11:09 PM, Rajeshwari Shinde <rajeshwari.s@samsung.com
> wrote:

> This adds i2c clock information for EXYNOS5.
>
> Signed-off-by: Alim Akhtar <alim.akhtar@samsung.com>
> Signed-off-by: Doug Anderson <dianders@chromium.org>
> Signed-off-by: Rajeshwari Shinde <rajeshwari.s@samsung.com>
> Acked-by: Simon Glass <sjg@chromium.org>
> ---
> changes in V2:
>        - Incorporated comments from Simon Glass which are removed extra
>        braces around (readl(&clk->div_top1)) >> 24 and gave a tab space for
>        return statement.
>

Acked-by: Simon Glass <sjg@chromium.org>


>  arch/arm/cpu/armv7/exynos/clock.c      |   33
> ++++++++++++++++++++++++++++++++
>  arch/arm/include/asm/arch-exynos/clk.h |    1 +
>  2 files changed, 34 insertions(+), 0 deletions(-)
>
> diff --git a/arch/arm/cpu/armv7/exynos/clock.c
> b/arch/arm/cpu/armv7/exynos/clock.c
> index 330bd75..a80928b 100644
> --- a/arch/arm/cpu/armv7/exynos/clock.c
> +++ b/arch/arm/cpu/armv7/exynos/clock.c
> @@ -578,6 +578,29 @@ void exynos4_set_mipi_clk(void)
>        writel(cfg, &clk->div_lcd0);
>  }
>
> +/*
> + * I2C
> + *
> + * exynos5: obtaining the I2C clock
> + */
> +static unsigned long exynos5_get_i2c_clk(void)
> +{
> +       struct exynos5_clock *clk =
> +               (struct exynos5_clock *)samsung_get_base_clock();
> +       unsigned long aclk_66, aclk_66_pre, sclk;
> +       unsigned int ratio;
> +
> +       sclk = get_pll_clk(MPLL);
> +
> +       ratio = (readl(&clk->div_top1)) >> 24;
> +       ratio &= (0x7);
> +       aclk_66_pre = sclk/(ratio+1);
> +       ratio = readl(&clk->div_top0);
> +       ratio &= (0x7);
> +       aclk_66 = aclk_66_pre/(ratio+1);
> +       return aclk_66;
> +}
> +
>  unsigned long get_pll_clk(int pllreg)
>  {
>        if (cpu_is_exynos5())
> @@ -594,6 +617,16 @@ unsigned long get_arm_clk(void)
>                return exynos4_get_arm_clk();
>  }
>
> +unsigned long get_i2c_clk(void)
> +{
> +       if (cpu_is_exynos5()) {
> +               return exynos5_get_i2c_clk();
> +       } else {
> +               debug("I2C clock is not set for this CPU\n");
> +               return 0;
> +       }
> +}
> +
>  unsigned long get_pwm_clk(void)
>  {
>        if (cpu_is_exynos5())
> diff --git a/arch/arm/include/asm/arch-exynos/clk.h
> b/arch/arm/include/asm/arch-exynos/clk.h
> index 637fb4b..72dc655 100644
> --- a/arch/arm/include/asm/arch-exynos/clk.h
> +++ b/arch/arm/include/asm/arch-exynos/clk.h
> @@ -30,6 +30,7 @@
>
>  unsigned long get_pll_clk(int pllreg);
>  unsigned long get_arm_clk(void);
> +unsigned long get_i2c_clk(void);
>  unsigned long get_pwm_clk(void);
>  unsigned long get_uart_clk(int dev_index);
>  void set_mmc_clk(int dev_index, unsigned int div);
> --
> 1.7.4.4
>
>

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [U-Boot] [PATCH 3/8 V2] EXYNOS: PINMUX: Add pinmux support for I2C
  2012-06-07  6:09 ` [U-Boot] [PATCH 3/8 V2] EXYNOS: PINMUX: Add pinmux support for I2C Rajeshwari Shinde
@ 2012-06-12  5:47   ` Simon Glass
  0 siblings, 0 replies; 19+ messages in thread
From: Simon Glass @ 2012-06-12  5:47 UTC (permalink / raw)
  To: u-boot

On Wed, Jun 6, 2012 at 11:09 PM, Rajeshwari Shinde <rajeshwari.s@samsung.com
> wrote:

> This patch adds pinmux code for I2C.
>
> Signed-off-by: Rajeshwari Shinde <rajeshwari.s@samsung.com>
> Acked-by: Simon Glass <sjg@chromium.org>
> ---
> Changes in V2:
>        - Aligned the pinmux functionality as per the latest comments.
>

Acked-by: Simon Glass <sjg@chromium.org>


> This patch depends on the following patch:
> "[U-Boot] [PATCH 1/2 V6] EXYNOS5: PINMUX: Added default pinumx settings"
>  arch/arm/cpu/armv7/exynos/pinmux.c        |   52
> +++++++++++++++++++++++++++++
>  arch/arm/include/asm/arch-exynos/periph.h |    8 ++++
>  2 files changed, 60 insertions(+), 0 deletions(-)
>
> diff --git a/arch/arm/cpu/armv7/exynos/pinmux.c
> b/arch/arm/cpu/armv7/exynos/pinmux.c
> index 597e487..d3314a1 100644
> --- a/arch/arm/cpu/armv7/exynos/pinmux.c
> +++ b/arch/arm/cpu/armv7/exynos/pinmux.c
> @@ -182,6 +182,48 @@ static void exynos5_sromc_config(int flags)
>        }
>  }
>
> +static void exynos5_i2c_config(int peripheral, int flags)
> +{
> +
> +       struct exynos5_gpio_part1 *gpio1 =
> +               (struct exynos5_gpio_part1 *)
> samsung_get_base_gpio_part1();
> +
> +       switch (peripheral) {
> +       case PERIPH_ID_I2C0:
> +               s5p_gpio_cfg_pin(&gpio1->b3, 0, GPIO_FUNC(0x2));
> +               s5p_gpio_cfg_pin(&gpio1->b3, 1, GPIO_FUNC(0x2));
> +               break;
> +       case PERIPH_ID_I2C1:
> +               s5p_gpio_cfg_pin(&gpio1->b3, 2, GPIO_FUNC(0x2));
> +               s5p_gpio_cfg_pin(&gpio1->b3, 3, GPIO_FUNC(0x2));
> +               break;
> +       case PERIPH_ID_I2C2:
> +               s5p_gpio_cfg_pin(&gpio1->a0, 6, GPIO_FUNC(0x3));
> +               s5p_gpio_cfg_pin(&gpio1->a0, 7, GPIO_FUNC(0x3));
> +               break;
> +       case PERIPH_ID_I2C3:
> +               s5p_gpio_cfg_pin(&gpio1->a1, 2, GPIO_FUNC(0x3));
> +               s5p_gpio_cfg_pin(&gpio1->a1, 3, GPIO_FUNC(0x3));
> +               break;
> +       case PERIPH_ID_I2C4:
> +               s5p_gpio_cfg_pin(&gpio1->a2, 0, GPIO_FUNC(0x3));
> +               s5p_gpio_cfg_pin(&gpio1->a2, 1, GPIO_FUNC(0x3));
> +               break;
> +       case PERIPH_ID_I2C5:
> +               s5p_gpio_cfg_pin(&gpio1->a2, 2, GPIO_FUNC(0x3));
> +               s5p_gpio_cfg_pin(&gpio1->a2, 3, GPIO_FUNC(0x3));
> +               break;
> +       case PERIPH_ID_I2C6:
> +               s5p_gpio_cfg_pin(&gpio1->b1, 3, GPIO_FUNC(0x4));
> +               s5p_gpio_cfg_pin(&gpio1->b1, 4, GPIO_FUNC(0x4));
> +               break;
> +       case PERIPH_ID_I2C7:
> +               s5p_gpio_cfg_pin(&gpio1->b2, 2, GPIO_FUNC(0x3));
> +               s5p_gpio_cfg_pin(&gpio1->b2, 3, GPIO_FUNC(0x3));
> +               break;
> +       }
> +}
> +
>  static int exynos5_pinmux_config(int peripheral, int flags)
>  {
>        switch (peripheral) {
> @@ -200,6 +242,16 @@ static int exynos5_pinmux_config(int peripheral, int
> flags)
>        case PERIPH_ID_SROMC:
>                exynos5_sromc_config(flags);
>                break;
> +       case PERIPH_ID_I2C0:
> +       case PERIPH_ID_I2C1:
> +       case PERIPH_ID_I2C2:
> +       case PERIPH_ID_I2C3:
> +       case PERIPH_ID_I2C4:
> +       case PERIPH_ID_I2C5:
> +       case PERIPH_ID_I2C6:
> +       case PERIPH_ID_I2C7:
> +               exynos5_i2c_config(peripheral, flags);
> +               break;
>        default:
>                debug("%s: invalid peripheral %d", __func__, peripheral);
>                return -1;
> diff --git a/arch/arm/include/asm/arch-exynos/periph.h
> b/arch/arm/include/asm/arch-exynos/periph.h
> index 5db25aa..b861d7d 100644
> --- a/arch/arm/include/asm/arch-exynos/periph.h
> +++ b/arch/arm/include/asm/arch-exynos/periph.h
> @@ -30,6 +30,14 @@
>  *
>  */
>  enum periph_id {
> +       PERIPH_ID_I2C0,
> +       PERIPH_ID_I2C1,
> +       PERIPH_ID_I2C2,
> +       PERIPH_ID_I2C3,
> +       PERIPH_ID_I2C4,
> +       PERIPH_ID_I2C5,
> +       PERIPH_ID_I2C6,
> +       PERIPH_ID_I2C7,
>        PERIPH_ID_SDMMC0,
>        PERIPH_ID_SDMMC1,
>        PERIPH_ID_SDMMC2,
> --
> 1.7.4.4
>
>

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [U-Boot] [PATCH 6/8 V2] I2C: Modify the I2C driver for EXYNOS5
  2012-06-07  6:09 ` [U-Boot] [PATCH 6/8 V2] I2C: Modify the I2C driver for EXYNOS5 Rajeshwari Shinde
@ 2012-06-12  5:52   ` Simon Glass
  2012-06-15  7:10   ` Joonyoung Shim
  1 sibling, 0 replies; 19+ messages in thread
From: Simon Glass @ 2012-06-12  5:52 UTC (permalink / raw)
  To: u-boot

On Wed, Jun 6, 2012 at 11:09 PM, Rajeshwari Shinde <rajeshwari.s@samsung.com
> wrote:

> This patch modifies the S3C I2C driver to suppport EXYNOS5.
> The cahnges made to driver are as follows:
>        - I2C base address is passed as a parameter to many
>        functions to avoid multiple #ifdef
>        - I2C init for Exynos5 is made as different function.
>        - Channel initialisation is moved to a commom funation
>        as it is required by both the i2c_init.
>        - Separate functions written to get I2C base address,
>        peripheral id for pinmux support.
>        - Hardcoding for I2CCON_ACKGEN removed.
>        - Replaced printf with debug.
>        - Checkpatch issues resolved.
>
> Signed-off-by: Alim Akhtar <alim.akhtar@samsung.com>
> Signed-off-by: Doug Anderson <dianders@chromium.org>
> Signed-off-by: Rajeshwari Shinde <rajeshwari.s@samsung.com>
> Acked-by: Simon Glass <sjg@chromium.org>
> ---
> Changes in V2:
>        - Removed #define for I2C cahnnels from hearder file except for
> I2C0.
>        - Incorporated review comments from Simon Glass.
>

Acked-by: Simon Glass <sjg@chromium.org>

(Looking forward to getting the transfer loop simplified one day!)


>  drivers/i2c/s3c24x0_i2c.c |  254
> ++++++++++++++++++++++++++++++++-------------
>  drivers/i2c/s3c24x0_i2c.h |    3 +
>  2 files changed, 184 insertions(+), 73 deletions(-)
>
> diff --git a/drivers/i2c/s3c24x0_i2c.c b/drivers/i2c/s3c24x0_i2c.c
> index ba6f39b..a71f147 100644
> --- a/drivers/i2c/s3c24x0_i2c.c
> +++ b/drivers/i2c/s3c24x0_i2c.c
> @@ -27,10 +27,17 @@
>  */
>
>  #include <common.h>
> +#ifdef CONFIG_EXYNOS5
> +#include <asm/arch/clk.h>
> +#include <asm/arch/cpu.h>
> +#include <asm/arch/gpio.h>
> +#include <asm/arch/pinmux.h>
> +#else
>  #include <asm/arch/s3c24x0_cpu.h>
> -
> +#endif
>  #include <asm/io.h>
>  #include <i2c.h>
> +#include "s3c24x0_i2c.h"
>
>  #ifdef CONFIG_HARD_I2C
>
> @@ -45,6 +52,7 @@
>
>  #define I2CSTAT_BSY    0x20    /* Busy bit */
>  #define I2CSTAT_NACK   0x01    /* Nack bit */
> +#define I2CCON_ACKGEN  0x80    /* Acknowledge generation */
>  #define I2CCON_IRPND   0x10    /* Interrupt pending bit */
>  #define I2C_MODE_MT    0xC0    /* Master Transmit Mode */
>  #define I2C_MODE_MR    0x80    /* Master Receive Mode */
> @@ -53,6 +61,44 @@
>
>  #define I2C_TIMEOUT 1          /* 1 second */
>
> +#ifdef CONFIG_EXYNOS5
> +static unsigned int g_current_bus;     /* Stores Current I2C Bus */
> +
> +/* We should not rely on any particular ordering of these IDs */
> +static enum periph_id periph_for_dev[] = {
> +       PERIPH_ID_I2C0,
> +       PERIPH_ID_I2C1,
> +       PERIPH_ID_I2C2,
> +       PERIPH_ID_I2C3,
> +       PERIPH_ID_I2C4,
> +       PERIPH_ID_I2C5,
> +       PERIPH_ID_I2C6,
> +       PERIPH_ID_I2C7,
> +};
> +
> +static enum periph_id i2c_get_periph_id(unsigned dev_index)
> +{
> +       if (dev_index < ARRAY_SIZE(periph_for_dev))
> +               return periph_for_dev[dev_index];
> +
> +       debug("%s: invalid bus %d", __func__, dev_index);
> +
> +       return PERIPH_ID_NONE;
> +}
> +
> +static struct s3c24x0_i2c *get_base_i2c(int bus_idx)
> +{
> +       struct s3c24x0_i2c *i2c = (struct s3c24x0_i2c
> *)samsung_get_base_i2c();
> +
> +       return &i2c[bus_idx];
> +}
> +
> +static inline struct exynos5_gpio_part1 *exynos_get_base_gpio1(void)
> +{
> +       return (struct exynos5_gpio_part1 *)(EXYNOS5_GPIO_PART1_BASE);
> +}
> +
> +#else
>  static int GetI2CSDA(void)
>  {
>        struct s3c24x0_gpio *gpio = s3c24x0_get_base_gpio();
> @@ -77,16 +123,17 @@ static void SetI2CSCL(int x)
>        struct s3c24x0_gpio *gpio = s3c24x0_get_base_gpio();
>
>  #ifdef CONFIG_S3C2410
> -       writel((readl(&gpio->gpedat) & ~0x4000) | (x & 1) << 14,
> &gpio->gpedat);
> +       writel((readl(&gpio->gpedat) & ~0x4000) |
> +                                       (x & 1) << 14, &gpio->gpedat);
>  #endif
>  #ifdef CONFIG_S3C2400
>        writel((readl(&gpio->pgdat) & ~0x0040) | (x & 1) << 6,
> &gpio->pgdat);
>  #endif
>  }
> +#endif
>
> -static int WaitForXfer(void)
> +static int WaitForXfer(struct s3c24x0_i2c *i2c)
>  {
> -       struct s3c24x0_i2c *i2c = s3c24x0_get_base_i2c();
>        int i;
>
>        i = I2C_TIMEOUT * 10000;
> @@ -98,25 +145,84 @@ static int WaitForXfer(void)
>        return (readl(&i2c->iiccon) & I2CCON_IRPND) ? I2C_OK : I2C_NOK_TOUT;
>  }
>
> -static int IsACK(void)
> +static int IsACK(struct s3c24x0_i2c *i2c)
>  {
> -       struct s3c24x0_i2c *i2c = s3c24x0_get_base_i2c();
> -
>        return !(readl(&i2c->iicstat) & I2CSTAT_NACK);
>  }
>
> -static void ReadWriteByte(void)
> +static void ReadWriteByte(struct s3c24x0_i2c *i2c)
>  {
> -       struct s3c24x0_i2c *i2c = s3c24x0_get_base_i2c();
> -
>        writel(readl(&i2c->iiccon) & ~I2CCON_IRPND, &i2c->iiccon);
>  }
>
> +static void i2c_ch_init(struct s3c24x0_i2c *i2c, int speed, int slaveadd)
> +{
> +       ulong freq, pres = 16, div;
> +#ifdef CONFIG_EXYNOS5
> +       freq = get_i2c_clk();
> +#else
> +       freq = get_PCLK();
> +#endif
> +       /* calculate prescaler and divisor values */
> +       if ((freq / pres / (16 + 1)) > speed)
> +               /* set prescaler to 512 */
> +               pres = 512;
> +
> +       div = 0;
> +       while ((freq / pres / (div + 1)) > speed)
> +               div++;
> +
> +       /* set prescaler, divisor according to freq, also set ACKGEN, IRQ
> */
> +       writel((div & 0x0F) | 0xA0 | ((pres == 512) ? 0x40 : 0),
> &i2c->iiccon);
> +
> +       /* init to SLAVE REVEIVE and set slaveaddr */
> +       writel(0, &i2c->iicstat);
> +       writel(slaveadd, &i2c->iicadd);
> +       /* program Master Transmit (and implicit STOP) */
> +       writel(I2C_MODE_MT | I2C_TXRX_ENA, &i2c->iicstat);
> +}
> +
> +static void i2c_bus_init(struct s3c24x0_i2c *i2c, unsigned int bus)
> +{
> +       int periph_id = i2c_get_periph_id(bus);
> +
> +       exynos_pinmux_config(periph_id, 0);
> +
> +       i2c_ch_init(i2c, CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
> +}
> +
> +#ifdef CONFIG_EXYNOS5
> +void i2c_init(int speed, int slaveadd)
> +{
> +       struct s3c24x0_i2c *i2c;
> +       struct exynos5_gpio_part1 *gpio;
> +       int i;
> +
> +       /* By default i2c channel 0 is the current bus */
> +       g_current_bus = I2C0;
> +
> +       i2c = get_base_i2c(g_current_bus);
> +
> +       i2c_bus_init(i2c, g_current_bus);
> +
> +       /* wait for some time to give previous transfer a chance to finish
> */
> +       i = I2C_TIMEOUT * 1000;
> +       while ((readl(&i2c->iicstat) & I2CSTAT_BSY) && (i > 0)) {
> +               udelay(1000);
> +               i--;
> +       }
> +
> +       gpio = exynos_get_base_gpio1();
> +       writel((readl(&gpio->b3.con) & ~0x00FF) | 0x0022, &gpio->b3.con);
> +
> +       i2c_ch_init(i2c, speed, slaveadd);
> +}
> +
> +#else
>  void i2c_init(int speed, int slaveadd)
>  {
>        struct s3c24x0_i2c *i2c = s3c24x0_get_base_i2c();
>        struct s3c24x0_gpio *gpio = s3c24x0_get_base_gpio();
> -       ulong freq, pres = 16, div;
>        int i;
>
>        /* wait for some time to give previous transfer a chance to finish
> */
> @@ -171,27 +277,9 @@ void i2c_init(int speed, int slaveadd)
>  #endif
>        }
>
> -       /* calculate prescaler and divisor values */
> -       freq = get_PCLK();
> -       if ((freq / pres / (16 + 1)) > speed)
> -               /* set prescaler to 512 */
> -               pres = 512;
> -
> -       div = 0;
> -       while ((freq / pres / (div + 1)) > speed)
> -               div++;
> -
> -       /* set prescaler, divisor according to freq, also set
> -        * ACKGEN, IRQ */
> -       writel((div & 0x0F) | 0xA0 | ((pres == 512) ? 0x40 : 0),
> &i2c->iiccon);
> -
> -       /* init to SLAVE REVEIVE and set slaveaddr */
> -       writel(0, &i2c->iicstat);
> -       writel(slaveadd, &i2c->iicadd);
> -       /* program Master Transmit (and implicit STOP) */
> -       writel(I2C_MODE_MT | I2C_TXRX_ENA, &i2c->iicstat);
> -
> +       i2c_ch_init(i2c, speed, slaveadd);
>  }
> +#endif
>
>  /*
>  * cmd_type is 0 for write, 1 for read.
> @@ -200,19 +288,19 @@ void i2c_init(int speed, int slaveadd)
>  * by the char, we could make it larger if needed. If it is
>  * 0 we skip the address write cycle.
>  */
> -static
> -int i2c_transfer(unsigned char cmd_type,
> -                unsigned char chip,
> -                unsigned char addr[],
> -                unsigned char addr_len,
> -                unsigned char data[], unsigned short data_len)
> +static int i2c_transfer(struct s3c24x0_i2c *i2c,
> +                       unsigned char cmd_type,
> +                       unsigned char chip,
> +                       unsigned char addr[],
> +                       unsigned char addr_len,
> +                       unsigned char data[],
> +                       unsigned short data_len)
>  {
> -       struct s3c24x0_i2c *i2c = s3c24x0_get_base_i2c();
>        int i, result;
>
>        if (data == 0 || data_len == 0) {
>                /*Don't support data transfer of no length or to address 0
> */
> -               printf("i2c_transfer: bad call\n");
> +               debug("i2c_transfer: bad call\n");
>                return I2C_NOK;
>        }
>
> @@ -226,7 +314,7 @@ int i2c_transfer(unsigned char cmd_type,
>        if (readl(&i2c->iicstat) & I2CSTAT_BSY)
>                return I2C_NOK_TOUT;
>
> -       writel(readl(&i2c->iiccon) | 0x80, &i2c->iiccon);
> +       writel(readl(&i2c->iiccon) | I2CCON_ACKGEN, &i2c->iiccon);
>        result = I2C_OK;
>
>        switch (cmd_type) {
> @@ -238,16 +326,16 @@ int i2c_transfer(unsigned char cmd_type,
>                               &i2c->iicstat);
>                        i = 0;
>                        while ((i < addr_len) && (result == I2C_OK)) {
> -                               result = WaitForXfer();
> +                               result = WaitForXfer(i2c);
>                                writel(addr[i], &i2c->iicds);
> -                               ReadWriteByte();
> +                               ReadWriteByte(i2c);
>                                i++;
>                        }
>                        i = 0;
>                        while ((i < data_len) && (result == I2C_OK)) {
> -                               result = WaitForXfer();
> +                               result = WaitForXfer(i2c);
>                                writel(data[i], &i2c->iicds);
> -                               ReadWriteByte();
> +                               ReadWriteByte(i2c);
>                                i++;
>                        }
>                } else {
> @@ -257,19 +345,19 @@ int i2c_transfer(unsigned char cmd_type,
>                               &i2c->iicstat);
>                        i = 0;
>                        while ((i < data_len) && (result = I2C_OK)) {
> -                               result = WaitForXfer();
> +                               result = WaitForXfer(i2c);
>                                writel(data[i], &i2c->iicds);
> -                               ReadWriteByte();
> +                               ReadWriteByte(i2c);
>                                i++;
>                        }
>                }
>
>                if (result == I2C_OK)
> -                       result = WaitForXfer();
> +                       result = WaitForXfer(i2c);
>
>                /* send STOP */
>                writel(I2C_MODE_MR | I2C_TXRX_ENA, &i2c->iicstat);
> -               ReadWriteByte();
> +               ReadWriteByte(i2c);
>                break;
>
>        case I2C_READ:
> @@ -279,13 +367,13 @@ int i2c_transfer(unsigned char cmd_type,
>                        /* send START */
>                        writel(readl(&i2c->iicstat) | I2C_START_STOP,
>                               &i2c->iicstat);
> -                       result = WaitForXfer();
> -                       if (IsACK()) {
> +                       result = WaitForXfer(i2c);
> +                       if (IsACK(i2c)) {
>                                i = 0;
>                                while ((i < addr_len) && (result ==
> I2C_OK)) {
>                                        writel(addr[i], &i2c->iicds);
> -                                       ReadWriteByte();
> -                                       result = WaitForXfer();
> +                                       ReadWriteByte(i2c);
> +                                       result = WaitForXfer(i2c);
>                                        i++;
>                                }
>
> @@ -293,16 +381,17 @@ int i2c_transfer(unsigned char cmd_type,
>                                /* resend START */
>                                writel(I2C_MODE_MR | I2C_TXRX_ENA |
>                                       I2C_START_STOP, &i2c->iicstat);
> -                               ReadWriteByte();
> -                               result = WaitForXfer();
> +                       ReadWriteByte(i2c);
> +                       result = WaitForXfer(i2c);
>                                i = 0;
>                                while ((i < data_len) && (result ==
> I2C_OK)) {
>                                        /* disable ACK for final READ */
>                                        if (i == data_len - 1)
>                                                writel(readl(&i2c->iiccon)
> -                                                      & ~0x80,
> &i2c->iiccon);
> -                                       ReadWriteByte();
> -                                       result = WaitForXfer();
> +                                                       & ~I2CCON_ACKGEN,
> +                                                       &i2c->iiccon);
> +                               ReadWriteByte(i2c);
> +                               result = WaitForXfer(i2c);
>                                        data[i] = readl(&i2c->iicds);
>                                        i++;
>                                }
> @@ -316,17 +405,18 @@ int i2c_transfer(unsigned char cmd_type,
>                        /* send START */
>                        writel(readl(&i2c->iicstat) | I2C_START_STOP,
>                               &i2c->iicstat);
> -                       result = WaitForXfer();
> +                       result = WaitForXfer(i2c);
>
> -                       if (IsACK()) {
> +                       if (IsACK(i2c)) {
>                                i = 0;
>                                while ((i < data_len) && (result ==
> I2C_OK)) {
>                                        /* disable ACK for final READ */
>                                        if (i == data_len - 1)
>                                                writel(readl(&i2c->iiccon) &
> -                                                      ~0x80,
> &i2c->iiccon);
> -                                       ReadWriteByte();
> -                                       result = WaitForXfer();
> +                                                       ~I2CCON_ACKGEN,
> +                                                       &i2c->iiccon);
> +                                       ReadWriteByte(i2c);
> +                                       result = WaitForXfer(i2c);
>                                        data[i] = readl(&i2c->iicds);
>                                        i++;
>                                }
> @@ -337,22 +427,28 @@ int i2c_transfer(unsigned char cmd_type,
>
>                /* send STOP */
>                writel(I2C_MODE_MR | I2C_TXRX_ENA, &i2c->iicstat);
> -               ReadWriteByte();
> +               ReadWriteByte(i2c);
>                break;
>
>        default:
> -               printf("i2c_transfer: bad call\n");
> +               debug("i2c_transfer: bad call\n");
>                result = I2C_NOK;
>                break;
>        }
>
> -       return (result);
> +       return result;
>  }
>
>  int i2c_probe(uchar chip)
>  {
> +       struct s3c24x0_i2c *i2c;
>        uchar buf[1];
>
> +#ifdef CONFIG_EXYNOS5
> +       i2c = get_base_i2c(g_current_bus);
> +#else
> +       i2c = s3c24x0_get_base_i2c();
> +#endif
>        buf[0] = 0;
>
>        /*
> @@ -360,16 +456,17 @@ int i2c_probe(uchar chip)
>         * address was <ACK>ed (i.e. there was a chip at that address which
>         * drove the data line low).
>         */
> -       return i2c_transfer(I2C_READ, chip << 1, 0, 0, buf, 1) != I2C_OK;
> +       return i2c_transfer(i2c, I2C_READ, chip << 1, 0, 0, buf, 1) !=
> I2C_OK;
>  }
>
>  int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len)
>  {
> +       struct s3c24x0_i2c *i2c;
>        uchar xaddr[4];
>        int ret;
>
>        if (alen > 4) {
> -               printf("I2C read: addr len %d not supported\n", alen);
> +               debug("I2C read: addr len %d not supported\n", alen);
>                return 1;
>        }
>
> @@ -396,10 +493,15 @@ int i2c_read(uchar chip, uint addr, int alen, uchar
> *buffer, int len)
>                chip |= ((addr >> (alen * 8)) &
>                         CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW);
>  #endif
> -       if ((ret =
> -            i2c_transfer(I2C_READ, chip << 1, &xaddr[4 - alen], alen,
> -                         buffer, len)) != 0) {
> -               printf("I2c read: failed %d\n", ret);
> +#ifdef CONFIG_EXYNOS5
> +       i2c = get_base_i2c(g_current_bus);
> +#else
> +       i2c = s3c24x0_get_base_i2c();
> +#endif
> +       ret = i2c_transfer(i2c, I2C_READ, chip << 1, &xaddr[4 - alen],
> alen,
> +                       buffer, len);
> +       if (ret != 0) {
> +               debug("I2c read: failed %d\n", ret);
>                return 1;
>        }
>        return 0;
> @@ -407,10 +509,11 @@ int i2c_read(uchar chip, uint addr, int alen, uchar
> *buffer, int len)
>
>  int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len)
>  {
> +       struct s3c24x0_i2c *i2c;
>        uchar xaddr[4];
>
>        if (alen > 4) {
> -               printf("I2C write: addr len %d not supported\n", alen);
> +               debug("I2C write: addr len %d not supported\n", alen);
>                return 1;
>        }
>
> @@ -436,8 +539,13 @@ int i2c_write(uchar chip, uint addr, int alen, uchar
> *buffer, int len)
>                chip |= ((addr >> (alen * 8)) &
>                         CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW);
>  #endif
> +#ifdef CONFIG_EXYNOS5
> +       i2c = get_base_i2c(g_current_bus);
> +#else
> +       i2c = s3c24x0_get_base_i2c();
> +#endif
>        return (i2c_transfer
> -               (I2C_WRITE, chip << 1, &xaddr[4 - alen], alen, buffer,
> +               (i2c, I2C_WRITE, chip << 1, &xaddr[4 - alen], alen, buffer,
>                 len) != 0);
>  }
>  #endif /* CONFIG_HARD_I2C */
> diff --git a/drivers/i2c/s3c24x0_i2c.h b/drivers/i2c/s3c24x0_i2c.h
> index d357a0a..57aafb1 100644
> --- a/drivers/i2c/s3c24x0_i2c.h
> +++ b/drivers/i2c/s3c24x0_i2c.h
> @@ -23,6 +23,9 @@
>  #ifndef _S3C24X0_I2C_H
>  #define _S3C24X0_I2C_H
>
> +/* I2C channels exynos5 has 8 i2c channel */
> +#define I2C0           0
> +
>  struct s3c24x0_i2c {
>        u32     iiccon;
>        u32     iicstat;
> --
> 1.7.4.4
>
>

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [U-Boot] [PATCH 6/8 V2] I2C: Modify the I2C driver for EXYNOS5
  2012-06-07  6:09 ` [U-Boot] [PATCH 6/8 V2] I2C: Modify the I2C driver for EXYNOS5 Rajeshwari Shinde
  2012-06-12  5:52   ` Simon Glass
@ 2012-06-15  7:10   ` Joonyoung Shim
  2012-06-19  5:38     ` Rajeshwari Birje
  1 sibling, 1 reply; 19+ messages in thread
From: Joonyoung Shim @ 2012-06-15  7:10 UTC (permalink / raw)
  To: u-boot

Hi,

2012/6/7 Rajeshwari Shinde <rajeshwari.s@samsung.com>:
> This patch modifies the S3C I2C driver to suppport EXYNOS5.
> The cahnges made to driver are as follows:
> ? ? ? ?- I2C base address is passed as a parameter to many
> ? ? ? ?functions to avoid multiple #ifdef
> ? ? ? ?- I2C init for Exynos5 is made as different function.
> ? ? ? ?- Channel initialisation is moved to a commom funation
> ? ? ? ?as it is required by both the i2c_init.
> ? ? ? ?- Separate functions written to get I2C base address,
> ? ? ? ?peripheral id for pinmux support.
> ? ? ? ?- Hardcoding for I2CCON_ACKGEN removed.
> ? ? ? ?- Replaced printf with debug.
> ? ? ? ?- Checkpatch issues resolved.
>
> Signed-off-by: Alim Akhtar <alim.akhtar@samsung.com>
> Signed-off-by: Doug Anderson <dianders@chromium.org>
> Signed-off-by: Rajeshwari Shinde <rajeshwari.s@samsung.com>
> Acked-by: Simon Glass <sjg@chromium.org>
> ---
> Changes in V2:
> ? ? ? ?- Removed #define for I2C cahnnels from hearder file except for I2C0.
> ? ? ? ?- Incorporated review comments from Simon Glass.
> ?drivers/i2c/s3c24x0_i2c.c | ?254 ++++++++++++++++++++++++++++++++-------------
> ?drivers/i2c/s3c24x0_i2c.h | ? ?3 +
> ?2 files changed, 184 insertions(+), 73 deletions(-)
>
> diff --git a/drivers/i2c/s3c24x0_i2c.c b/drivers/i2c/s3c24x0_i2c.c
> index ba6f39b..a71f147 100644
> --- a/drivers/i2c/s3c24x0_i2c.c
> +++ b/drivers/i2c/s3c24x0_i2c.c
> @@ -27,10 +27,17 @@
> ?*/
>
> ?#include <common.h>
> +#ifdef CONFIG_EXYNOS5
> +#include <asm/arch/clk.h>
> +#include <asm/arch/cpu.h>
> +#include <asm/arch/gpio.h>
> +#include <asm/arch/pinmux.h>
> +#else
> ?#include <asm/arch/s3c24x0_cpu.h>
> -
> +#endif
> ?#include <asm/io.h>
> ?#include <i2c.h>
> +#include "s3c24x0_i2c.h"
>
> ?#ifdef CONFIG_HARD_I2C
>
> @@ -45,6 +52,7 @@
>
> ?#define I2CSTAT_BSY ? ?0x20 ? ?/* Busy bit */
> ?#define I2CSTAT_NACK ? 0x01 ? ?/* Nack bit */
> +#define I2CCON_ACKGEN ?0x80 ? ?/* Acknowledge generation */
> ?#define I2CCON_IRPND ? 0x10 ? ?/* Interrupt pending bit */
> ?#define I2C_MODE_MT ? ?0xC0 ? ?/* Master Transmit Mode */
> ?#define I2C_MODE_MR ? ?0x80 ? ?/* Master Receive Mode */
> @@ -53,6 +61,44 @@
>
> ?#define I2C_TIMEOUT 1 ? ? ? ? ?/* 1 second */
>
> +#ifdef CONFIG_EXYNOS5
> +static unsigned int g_current_bus; ? ? /* Stores Current I2C Bus */
> +
> +/* We should not rely on any particular ordering of these IDs */
> +static enum periph_id periph_for_dev[] = {
> + ? ? ? PERIPH_ID_I2C0,
> + ? ? ? PERIPH_ID_I2C1,
> + ? ? ? PERIPH_ID_I2C2,
> + ? ? ? PERIPH_ID_I2C3,
> + ? ? ? PERIPH_ID_I2C4,
> + ? ? ? PERIPH_ID_I2C5,
> + ? ? ? PERIPH_ID_I2C6,
> + ? ? ? PERIPH_ID_I2C7,
> +};
> +
> +static enum periph_id i2c_get_periph_id(unsigned dev_index)
> +{
> + ? ? ? if (dev_index < ARRAY_SIZE(periph_for_dev))
> + ? ? ? ? ? ? ? return periph_for_dev[dev_index];
> +
> + ? ? ? debug("%s: invalid bus %d", __func__, dev_index);
> +
> + ? ? ? return PERIPH_ID_NONE;
> +}
> +
> +static struct s3c24x0_i2c *get_base_i2c(int bus_idx)
> +{
> + ? ? ? struct s3c24x0_i2c *i2c = (struct s3c24x0_i2c *)samsung_get_base_i2c();
> +
> + ? ? ? return &i2c[bus_idx];
> +}

This function can use in the s3c24xx adding #ifdef in this fuction, then
you can reduce #ifdef.

> +
> +static inline struct exynos5_gpio_part1 *exynos_get_base_gpio1(void)
> +{
> + ? ? ? return (struct exynos5_gpio_part1 *)(EXYNOS5_GPIO_PART1_BASE);
> +}
> +
> +#else
> ?static int GetI2CSDA(void)
> ?{
> ? ? ? ?struct s3c24x0_gpio *gpio = s3c24x0_get_base_gpio();
> @@ -77,16 +123,17 @@ static void SetI2CSCL(int x)
> ? ? ? ?struct s3c24x0_gpio *gpio = s3c24x0_get_base_gpio();
>
> ?#ifdef CONFIG_S3C2410
> - ? ? ? writel((readl(&gpio->gpedat) & ~0x4000) | (x & 1) << 14, &gpio->gpedat);
> + ? ? ? writel((readl(&gpio->gpedat) & ~0x4000) |
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? (x & 1) << 14, &gpio->gpedat);
> ?#endif
> ?#ifdef CONFIG_S3C2400
> ? ? ? ?writel((readl(&gpio->pgdat) & ~0x0040) | (x & 1) << 6, &gpio->pgdat);
> ?#endif
> ?}
> +#endif
>
> -static int WaitForXfer(void)
> +static int WaitForXfer(struct s3c24x0_i2c *i2c)
> ?{
> - ? ? ? struct s3c24x0_i2c *i2c = s3c24x0_get_base_i2c();
> ? ? ? ?int i;
>
> ? ? ? ?i = I2C_TIMEOUT * 10000;
> @@ -98,25 +145,84 @@ static int WaitForXfer(void)
> ? ? ? ?return (readl(&i2c->iiccon) & I2CCON_IRPND) ? I2C_OK : I2C_NOK_TOUT;
> ?}
>
> -static int IsACK(void)
> +static int IsACK(struct s3c24x0_i2c *i2c)
> ?{
> - ? ? ? struct s3c24x0_i2c *i2c = s3c24x0_get_base_i2c();
> -
> ? ? ? ?return !(readl(&i2c->iicstat) & I2CSTAT_NACK);
> ?}
>
> -static void ReadWriteByte(void)
> +static void ReadWriteByte(struct s3c24x0_i2c *i2c)
> ?{
> - ? ? ? struct s3c24x0_i2c *i2c = s3c24x0_get_base_i2c();
> -
> ? ? ? ?writel(readl(&i2c->iiccon) & ~I2CCON_IRPND, &i2c->iiccon);
> ?}
>
> +static void i2c_ch_init(struct s3c24x0_i2c *i2c, int speed, int slaveadd)
> +{
> + ? ? ? ulong freq, pres = 16, div;
> +#ifdef CONFIG_EXYNOS5
> + ? ? ? freq = get_i2c_clk();
> +#else
> + ? ? ? freq = get_PCLK();
> +#endif
> + ? ? ? /* calculate prescaler and divisor values */
> + ? ? ? if ((freq / pres / (16 + 1)) > speed)
> + ? ? ? ? ? ? ? /* set prescaler to 512 */
> + ? ? ? ? ? ? ? pres = 512;
> +
> + ? ? ? div = 0;
> + ? ? ? while ((freq / pres / (div + 1)) > speed)
> + ? ? ? ? ? ? ? div++;
> +
> + ? ? ? /* set prescaler, divisor according to freq, also set ACKGEN, IRQ */
> + ? ? ? writel((div & 0x0F) | 0xA0 | ((pres == 512) ? 0x40 : 0), &i2c->iiccon);
> +
> + ? ? ? /* init to SLAVE REVEIVE and set slaveaddr */
> + ? ? ? writel(0, &i2c->iicstat);
> + ? ? ? writel(slaveadd, &i2c->iicadd);
> + ? ? ? /* program Master Transmit (and implicit STOP) */
> + ? ? ? writel(I2C_MODE_MT | I2C_TXRX_ENA, &i2c->iicstat);
> +}
> +
> +static void i2c_bus_init(struct s3c24x0_i2c *i2c, unsigned int bus)
> +{
> + ? ? ? int periph_id = i2c_get_periph_id(bus);
> +
> + ? ? ? exynos_pinmux_config(periph_id, 0);
> +
> + ? ? ? i2c_ch_init(i2c, CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
> +}

This function is used only in EXYNOS5.

> +
> +#ifdef CONFIG_EXYNOS5
> +void i2c_init(int speed, int slaveadd)
> +{
> + ? ? ? struct s3c24x0_i2c *i2c;
> + ? ? ? struct exynos5_gpio_part1 *gpio;
> + ? ? ? int i;
> +
> + ? ? ? /* By default i2c channel 0 is the current bus */
> + ? ? ? g_current_bus = I2C0;
> +
> + ? ? ? i2c = get_base_i2c(g_current_bus);
> +
> + ? ? ? i2c_bus_init(i2c, g_current_bus);
> +
> + ? ? ? /* wait for some time to give previous transfer a chance to finish */
> + ? ? ? i = I2C_TIMEOUT * 1000;
> + ? ? ? while ((readl(&i2c->iicstat) & I2CSTAT_BSY) && (i > 0)) {
> + ? ? ? ? ? ? ? udelay(1000);
> + ? ? ? ? ? ? ? i--;
> + ? ? ? }
> +
> + ? ? ? gpio = exynos_get_base_gpio1();
> + ? ? ? writel((readl(&gpio->b3.con) & ~0x00FF) | 0x0022, &gpio->b3.con);

This doesn't need to do because of i2c_bus_init().

> +
> + ? ? ? i2c_ch_init(i2c, speed, slaveadd);

The i2c_bus_init() calls i2c_ch_init() already.

> +}
> +
> +#else
> ?void i2c_init(int speed, int slaveadd)
> ?{
> ? ? ? ?struct s3c24x0_i2c *i2c = s3c24x0_get_base_i2c();
> ? ? ? ?struct s3c24x0_gpio *gpio = s3c24x0_get_base_gpio();
> - ? ? ? ulong freq, pres = 16, div;
> ? ? ? ?int i;
>
> ? ? ? ?/* wait for some time to give previous transfer a chance to finish */
> @@ -171,27 +277,9 @@ void i2c_init(int speed, int slaveadd)
> ?#endif
> ? ? ? ?}
>
> - ? ? ? /* calculate prescaler and divisor values */
> - ? ? ? freq = get_PCLK();
> - ? ? ? if ((freq / pres / (16 + 1)) > speed)
> - ? ? ? ? ? ? ? /* set prescaler to 512 */
> - ? ? ? ? ? ? ? pres = 512;
> -
> - ? ? ? div = 0;
> - ? ? ? while ((freq / pres / (div + 1)) > speed)
> - ? ? ? ? ? ? ? div++;
> -
> - ? ? ? /* set prescaler, divisor according to freq, also set
> - ? ? ? ?* ACKGEN, IRQ */
> - ? ? ? writel((div & 0x0F) | 0xA0 | ((pres == 512) ? 0x40 : 0), &i2c->iiccon);
> -
> - ? ? ? /* init to SLAVE REVEIVE and set slaveaddr */
> - ? ? ? writel(0, &i2c->iicstat);
> - ? ? ? writel(slaveadd, &i2c->iicadd);
> - ? ? ? /* program Master Transmit (and implicit STOP) */
> - ? ? ? writel(I2C_MODE_MT | I2C_TXRX_ENA, &i2c->iicstat);
> -
> + ? ? ? i2c_ch_init(i2c, speed, slaveadd);
> ?}
> +#endif
>
> ?/*
> ?* cmd_type is 0 for write, 1 for read.
> @@ -200,19 +288,19 @@ void i2c_init(int speed, int slaveadd)
> ?* by the char, we could make it larger if needed. If it is
> ?* 0 we skip the address write cycle.
> ?*/
> -static
> -int i2c_transfer(unsigned char cmd_type,
> - ? ? ? ? ? ? ? ?unsigned char chip,
> - ? ? ? ? ? ? ? ?unsigned char addr[],
> - ? ? ? ? ? ? ? ?unsigned char addr_len,
> - ? ? ? ? ? ? ? ?unsigned char data[], unsigned short data_len)
> +static int i2c_transfer(struct s3c24x0_i2c *i2c,
> + ? ? ? ? ? ? ? ? ? ? ? unsigned char cmd_type,
> + ? ? ? ? ? ? ? ? ? ? ? unsigned char chip,
> + ? ? ? ? ? ? ? ? ? ? ? unsigned char addr[],
> + ? ? ? ? ? ? ? ? ? ? ? unsigned char addr_len,
> + ? ? ? ? ? ? ? ? ? ? ? unsigned char data[],
> + ? ? ? ? ? ? ? ? ? ? ? unsigned short data_len)
> ?{
> - ? ? ? struct s3c24x0_i2c *i2c = s3c24x0_get_base_i2c();
> ? ? ? ?int i, result;
>
> ? ? ? ?if (data == 0 || data_len == 0) {
> ? ? ? ? ? ? ? ?/*Don't support data transfer of no length or to address 0 */
> - ? ? ? ? ? ? ? printf("i2c_transfer: bad call\n");
> + ? ? ? ? ? ? ? debug("i2c_transfer: bad call\n");
> ? ? ? ? ? ? ? ?return I2C_NOK;
> ? ? ? ?}
>
> @@ -226,7 +314,7 @@ int i2c_transfer(unsigned char cmd_type,
> ? ? ? ?if (readl(&i2c->iicstat) & I2CSTAT_BSY)
> ? ? ? ? ? ? ? ?return I2C_NOK_TOUT;
>
> - ? ? ? writel(readl(&i2c->iiccon) | 0x80, &i2c->iiccon);
> + ? ? ? writel(readl(&i2c->iiccon) | I2CCON_ACKGEN, &i2c->iiccon);
> ? ? ? ?result = I2C_OK;
>
> ? ? ? ?switch (cmd_type) {
> @@ -238,16 +326,16 @@ int i2c_transfer(unsigned char cmd_type,
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? &i2c->iicstat);
> ? ? ? ? ? ? ? ? ? ? ? ?i = 0;
> ? ? ? ? ? ? ? ? ? ? ? ?while ((i < addr_len) && (result == I2C_OK)) {
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? result = WaitForXfer();
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? result = WaitForXfer(i2c);
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?writel(addr[i], &i2c->iicds);
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ReadWriteByte();
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ReadWriteByte(i2c);
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?i++;
> ? ? ? ? ? ? ? ? ? ? ? ?}
> ? ? ? ? ? ? ? ? ? ? ? ?i = 0;
> ? ? ? ? ? ? ? ? ? ? ? ?while ((i < data_len) && (result == I2C_OK)) {
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? result = WaitForXfer();
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? result = WaitForXfer(i2c);
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?writel(data[i], &i2c->iicds);
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ReadWriteByte();
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ReadWriteByte(i2c);
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?i++;
> ? ? ? ? ? ? ? ? ? ? ? ?}
> ? ? ? ? ? ? ? ?} else {
> @@ -257,19 +345,19 @@ int i2c_transfer(unsigned char cmd_type,
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? &i2c->iicstat);
> ? ? ? ? ? ? ? ? ? ? ? ?i = 0;
> ? ? ? ? ? ? ? ? ? ? ? ?while ((i < data_len) && (result = I2C_OK)) {
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? result = WaitForXfer();
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? result = WaitForXfer(i2c);
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?writel(data[i], &i2c->iicds);
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ReadWriteByte();
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ReadWriteByte(i2c);
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?i++;
> ? ? ? ? ? ? ? ? ? ? ? ?}
> ? ? ? ? ? ? ? ?}
>
> ? ? ? ? ? ? ? ?if (result == I2C_OK)
> - ? ? ? ? ? ? ? ? ? ? ? result = WaitForXfer();
> + ? ? ? ? ? ? ? ? ? ? ? result = WaitForXfer(i2c);
>
> ? ? ? ? ? ? ? ?/* send STOP */
> ? ? ? ? ? ? ? ?writel(I2C_MODE_MR | I2C_TXRX_ENA, &i2c->iicstat);
> - ? ? ? ? ? ? ? ReadWriteByte();
> + ? ? ? ? ? ? ? ReadWriteByte(i2c);
> ? ? ? ? ? ? ? ?break;
>
> ? ? ? ?case I2C_READ:
> @@ -279,13 +367,13 @@ int i2c_transfer(unsigned char cmd_type,
> ? ? ? ? ? ? ? ? ? ? ? ?/* send START */
> ? ? ? ? ? ? ? ? ? ? ? ?writel(readl(&i2c->iicstat) | I2C_START_STOP,
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? &i2c->iicstat);
> - ? ? ? ? ? ? ? ? ? ? ? result = WaitForXfer();
> - ? ? ? ? ? ? ? ? ? ? ? if (IsACK()) {
> + ? ? ? ? ? ? ? ? ? ? ? result = WaitForXfer(i2c);
> + ? ? ? ? ? ? ? ? ? ? ? if (IsACK(i2c)) {
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?i = 0;
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?while ((i < addr_len) && (result == I2C_OK)) {
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?writel(addr[i], &i2c->iicds);
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ReadWriteByte();
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? result = WaitForXfer();
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ReadWriteByte(i2c);
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? result = WaitForXfer(i2c);
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?i++;
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?}
>
> @@ -293,16 +381,17 @@ int i2c_transfer(unsigned char cmd_type,
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?/* resend START */
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?writel(I2C_MODE_MR | I2C_TXRX_ENA |
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? I2C_START_STOP, &i2c->iicstat);
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ReadWriteByte();
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? result = WaitForXfer();
> + ? ? ? ? ? ? ? ? ? ? ? ReadWriteByte(i2c);
> + ? ? ? ? ? ? ? ? ? ? ? result = WaitForXfer(i2c);
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?i = 0;
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?while ((i < data_len) && (result == I2C_OK)) {
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?/* disable ACK for final READ */
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?if (i == data_len - 1)
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?writel(readl(&i2c->iiccon)
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?& ~0x80, &i2c->iiccon);
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ReadWriteByte();
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? result = WaitForXfer();
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? & ~I2CCON_ACKGEN,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? &i2c->iiccon);
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ReadWriteByte(i2c);
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? result = WaitForXfer(i2c);
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?data[i] = readl(&i2c->iicds);
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?i++;
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?}
> @@ -316,17 +405,18 @@ int i2c_transfer(unsigned char cmd_type,
> ? ? ? ? ? ? ? ? ? ? ? ?/* send START */
> ? ? ? ? ? ? ? ? ? ? ? ?writel(readl(&i2c->iicstat) | I2C_START_STOP,
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? &i2c->iicstat);
> - ? ? ? ? ? ? ? ? ? ? ? result = WaitForXfer();
> + ? ? ? ? ? ? ? ? ? ? ? result = WaitForXfer(i2c);
>
> - ? ? ? ? ? ? ? ? ? ? ? if (IsACK()) {
> + ? ? ? ? ? ? ? ? ? ? ? if (IsACK(i2c)) {
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?i = 0;
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?while ((i < data_len) && (result == I2C_OK)) {
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?/* disable ACK for final READ */
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?if (i == data_len - 1)
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?writel(readl(&i2c->iiccon) &
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?~0x80, &i2c->iiccon);
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ReadWriteByte();
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? result = WaitForXfer();
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ~I2CCON_ACKGEN,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? &i2c->iiccon);
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ReadWriteByte(i2c);
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? result = WaitForXfer(i2c);
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?data[i] = readl(&i2c->iicds);
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?i++;
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?}
> @@ -337,22 +427,28 @@ int i2c_transfer(unsigned char cmd_type,
>
> ? ? ? ? ? ? ? ?/* send STOP */
> ? ? ? ? ? ? ? ?writel(I2C_MODE_MR | I2C_TXRX_ENA, &i2c->iicstat);
> - ? ? ? ? ? ? ? ReadWriteByte();
> + ? ? ? ? ? ? ? ReadWriteByte(i2c);
> ? ? ? ? ? ? ? ?break;
>
> ? ? ? ?default:
> - ? ? ? ? ? ? ? printf("i2c_transfer: bad call\n");
> + ? ? ? ? ? ? ? debug("i2c_transfer: bad call\n");
> ? ? ? ? ? ? ? ?result = I2C_NOK;
> ? ? ? ? ? ? ? ?break;
> ? ? ? ?}
>
> - ? ? ? return (result);
> + ? ? ? return result;
> ?}
>
> ?int i2c_probe(uchar chip)
> ?{
> + ? ? ? struct s3c24x0_i2c *i2c;
> ? ? ? ?uchar buf[1];
>
> +#ifdef CONFIG_EXYNOS5
> + ? ? ? i2c = get_base_i2c(g_current_bus);
> +#else
> + ? ? ? i2c = s3c24x0_get_base_i2c();
> +#endif
> ? ? ? ?buf[0] = 0;
>
> ? ? ? ?/*
> @@ -360,16 +456,17 @@ int i2c_probe(uchar chip)
> ? ? ? ? * address was <ACK>ed (i.e. there was a chip at that address which
> ? ? ? ? * drove the data line low).
> ? ? ? ? */
> - ? ? ? return i2c_transfer(I2C_READ, chip << 1, 0, 0, buf, 1) != I2C_OK;
> + ? ? ? return i2c_transfer(i2c, I2C_READ, chip << 1, 0, 0, buf, 1) != I2C_OK;
> ?}
>
> ?int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len)
> ?{
> + ? ? ? struct s3c24x0_i2c *i2c;
> ? ? ? ?uchar xaddr[4];
> ? ? ? ?int ret;
>
> ? ? ? ?if (alen > 4) {
> - ? ? ? ? ? ? ? printf("I2C read: addr len %d not supported\n", alen);
> + ? ? ? ? ? ? ? debug("I2C read: addr len %d not supported\n", alen);
> ? ? ? ? ? ? ? ?return 1;
> ? ? ? ?}
>
> @@ -396,10 +493,15 @@ int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len)
> ? ? ? ? ? ? ? ?chip |= ((addr >> (alen * 8)) &
> ? ? ? ? ? ? ? ? ? ? ? ? CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW);
> ?#endif
> - ? ? ? if ((ret =
> - ? ? ? ? ? ?i2c_transfer(I2C_READ, chip << 1, &xaddr[4 - alen], alen,
> - ? ? ? ? ? ? ? ? ? ? ? ? buffer, len)) != 0) {
> - ? ? ? ? ? ? ? printf("I2c read: failed %d\n", ret);
> +#ifdef CONFIG_EXYNOS5
> + ? ? ? i2c = get_base_i2c(g_current_bus);
> +#else
> + ? ? ? i2c = s3c24x0_get_base_i2c();
> +#endif
> + ? ? ? ret = i2c_transfer(i2c, I2C_READ, chip << 1, &xaddr[4 - alen], alen,
> + ? ? ? ? ? ? ? ? ? ? ? buffer, len);
> + ? ? ? if (ret != 0) {
> + ? ? ? ? ? ? ? debug("I2c read: failed %d\n", ret);
> ? ? ? ? ? ? ? ?return 1;
> ? ? ? ?}
> ? ? ? ?return 0;
> @@ -407,10 +509,11 @@ int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len)
>
> ?int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len)
> ?{
> + ? ? ? struct s3c24x0_i2c *i2c;
> ? ? ? ?uchar xaddr[4];
>
> ? ? ? ?if (alen > 4) {
> - ? ? ? ? ? ? ? printf("I2C write: addr len %d not supported\n", alen);
> + ? ? ? ? ? ? ? debug("I2C write: addr len %d not supported\n", alen);
> ? ? ? ? ? ? ? ?return 1;
> ? ? ? ?}
>
> @@ -436,8 +539,13 @@ int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len)
> ? ? ? ? ? ? ? ?chip |= ((addr >> (alen * 8)) &
> ? ? ? ? ? ? ? ? ? ? ? ? CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW);
> ?#endif
> +#ifdef CONFIG_EXYNOS5
> + ? ? ? i2c = get_base_i2c(g_current_bus);
> +#else
> + ? ? ? i2c = s3c24x0_get_base_i2c();
> +#endif
> ? ? ? ?return (i2c_transfer
> - ? ? ? ? ? ? ? (I2C_WRITE, chip << 1, &xaddr[4 - alen], alen, buffer,
> + ? ? ? ? ? ? ? (i2c, I2C_WRITE, chip << 1, &xaddr[4 - alen], alen, buffer,
> ? ? ? ? ? ? ? ? len) != 0);
> ?}
> ?#endif /* CONFIG_HARD_I2C */
> diff --git a/drivers/i2c/s3c24x0_i2c.h b/drivers/i2c/s3c24x0_i2c.h
> index d357a0a..57aafb1 100644
> --- a/drivers/i2c/s3c24x0_i2c.h
> +++ b/drivers/i2c/s3c24x0_i2c.h
> @@ -23,6 +23,9 @@
> ?#ifndef _S3C24X0_I2C_H
> ?#define _S3C24X0_I2C_H
>
> +/* I2C channels exynos5 has 8 i2c channel */
> +#define I2C0 ? ? ? ? ? 0
> +
> ?struct s3c24x0_i2c {
> ? ? ? ?u32 ? ? iiccon;
> ? ? ? ?u32 ? ? iicstat;
> --
> 1.7.4.4
>
> _______________________________________________
> U-Boot mailing list
> U-Boot at lists.denx.de
> http://lists.denx.de/mailman/listinfo/u-boot

Thanks.

-- 
- Joonyoung Shim

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [U-Boot] [PATCH 7/8 V2] I2C: Add support for Multi channel
  2012-06-07  6:09 ` [U-Boot] [PATCH 7/8 V2] I2C: Add support for Multi channel Rajeshwari Shinde
@ 2012-06-15  7:15   ` Joonyoung Shim
  2012-06-19  5:44     ` Rajeshwari Birje
  0 siblings, 1 reply; 19+ messages in thread
From: Joonyoung Shim @ 2012-06-15  7:15 UTC (permalink / raw)
  To: u-boot

Hi,

2012/6/7 Rajeshwari Shinde <rajeshwari.s@samsung.com>:
> This adds multiple i2c channel support for I2C.
>
> Signed-off-by: Alim Akhtar <alim.akhtar@samsung.com>
> Signed-off-by: Rajeshwari Shinde <rajeshwari.s@samsung.com>
> Acked-by: Simon Glass <sjg@chromium.org>
> ---
> ?drivers/i2c/s3c24x0_i2c.c | ? 27 +++++++++++++++++++++++++++
> ?1 files changed, 27 insertions(+), 0 deletions(-)
>
> diff --git a/drivers/i2c/s3c24x0_i2c.c b/drivers/i2c/s3c24x0_i2c.c
> index a71f147..7521cb8 100644
> --- a/drivers/i2c/s3c24x0_i2c.c
> +++ b/drivers/i2c/s3c24x0_i2c.c
> @@ -191,6 +191,33 @@ static void i2c_bus_init(struct s3c24x0_i2c *i2c, unsigned int bus)
> ? ? ? ?i2c_ch_init(i2c, CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
> ?}
>
> +/*
> + * MULTI BUS I2C support
> + */
> +
> +#ifdef CONFIG_I2C_MULTI_BUS
> +int i2c_set_bus_num(unsigned int bus)
> +{
> + ? ? ? struct s3c24x0_i2c *i2c;
> +
> + ? ? ? if ((bus < 0) || (bus >= CONFIG_MAX_I2C_NUM)) {
> + ? ? ? ? ? ? ? debug("Bad bus: %d\n", bus);
> + ? ? ? ? ? ? ? return -1;
> + ? ? ? }
> +
> + ? ? ? g_current_bus = bus;
> + ? ? ? i2c = get_base_i2c(g_current_bus);
> + ? ? ? i2c_bus_init(i2c, g_current_bus);

This causes duplicated pin configuration whenever calls i2c_set_bus_num().

> +
> + ? ? ? return 0;
> +}
> +
> +unsigned int i2c_get_bus_num(void)
> +{
> + ? ? ? return g_current_bus;
> +}
> +#endif

Does only EXYNOS5 support CONFIG_I2C_MULTI_BUS?

> +
> ?#ifdef CONFIG_EXYNOS5
> ?void i2c_init(int speed, int slaveadd)
> ?{
> --
> 1.7.4.4
>
> _______________________________________________
> U-Boot mailing list
> U-Boot at lists.denx.de
> http://lists.denx.de/mailman/listinfo/u-boot

Thanks.

-- 
- Joonyoung Shim

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [U-Boot] [PATCH 6/8 V2] I2C: Modify the I2C driver for EXYNOS5
  2012-06-15  7:10   ` Joonyoung Shim
@ 2012-06-19  5:38     ` Rajeshwari Birje
  2012-06-19  7:15       ` Joonyoung Shim
  0 siblings, 1 reply; 19+ messages in thread
From: Rajeshwari Birje @ 2012-06-19  5:38 UTC (permalink / raw)
  To: u-boot

Hi Joonyoung Shim,

Thank you for comments.

On Fri, Jun 15, 2012 at 12:40 PM, Joonyoung Shim <dofmind@gmail.com> wrote:
> Hi,
>
> 2012/6/7 Rajeshwari Shinde <rajeshwari.s@samsung.com>:
>> This patch modifies the S3C I2C driver to suppport EXYNOS5.
>> The cahnges made to driver are as follows:
>> ? ? ? ?- I2C base address is passed as a parameter to many
>> ? ? ? ?functions to avoid multiple #ifdef
>> ? ? ? ?- I2C init for Exynos5 is made as different function.
>> ? ? ? ?- Channel initialisation is moved to a commom funation
>> ? ? ? ?as it is required by both the i2c_init.
>> ? ? ? ?- Separate functions written to get I2C base address,
>> ? ? ? ?peripheral id for pinmux support.
>> ? ? ? ?- Hardcoding for I2CCON_ACKGEN removed.
>> ? ? ? ?- Replaced printf with debug.
>> ? ? ? ?- Checkpatch issues resolved.
>>
>> Signed-off-by: Alim Akhtar <alim.akhtar@samsung.com>
>> Signed-off-by: Doug Anderson <dianders@chromium.org>
>> Signed-off-by: Rajeshwari Shinde <rajeshwari.s@samsung.com>
>> Acked-by: Simon Glass <sjg@chromium.org>
>> ---
>> Changes in V2:
>> ? ? ? ?- Removed #define for I2C cahnnels from hearder file except for I2C0.
>> ? ? ? ?- Incorporated review comments from Simon Glass.
>> ?drivers/i2c/s3c24x0_i2c.c | ?254 ++++++++++++++++++++++++++++++++-------------
>> ?drivers/i2c/s3c24x0_i2c.h | ? ?3 +
>> ?2 files changed, 184 insertions(+), 73 deletions(-)
>>
>> diff --git a/drivers/i2c/s3c24x0_i2c.c b/drivers/i2c/s3c24x0_i2c.c
>> index ba6f39b..a71f147 100644
>> --- a/drivers/i2c/s3c24x0_i2c.c
>> +++ b/drivers/i2c/s3c24x0_i2c.c
>> @@ -27,10 +27,17 @@
>> ?*/
>>
>> ?#include <common.h>
>> +#ifdef CONFIG_EXYNOS5
>> +#include <asm/arch/clk.h>
>> +#include <asm/arch/cpu.h>
>> +#include <asm/arch/gpio.h>
>> +#include <asm/arch/pinmux.h>
>> +#else
>> ?#include <asm/arch/s3c24x0_cpu.h>
>> -
>> +#endif
>> ?#include <asm/io.h>
>> ?#include <i2c.h>
>> +#include "s3c24x0_i2c.h"
>>
>> ?#ifdef CONFIG_HARD_I2C
>>
>> @@ -45,6 +52,7 @@
>>
>> ?#define I2CSTAT_BSY ? ?0x20 ? ?/* Busy bit */
>> ?#define I2CSTAT_NACK ? 0x01 ? ?/* Nack bit */
>> +#define I2CCON_ACKGEN ?0x80 ? ?/* Acknowledge generation */
>> ?#define I2CCON_IRPND ? 0x10 ? ?/* Interrupt pending bit */
>> ?#define I2C_MODE_MT ? ?0xC0 ? ?/* Master Transmit Mode */
>> ?#define I2C_MODE_MR ? ?0x80 ? ?/* Master Receive Mode */
>> @@ -53,6 +61,44 @@
>>
>> ?#define I2C_TIMEOUT 1 ? ? ? ? ?/* 1 second */
>>
>> +#ifdef CONFIG_EXYNOS5
>> +static unsigned int g_current_bus; ? ? /* Stores Current I2C Bus */
>> +
>> +/* We should not rely on any particular ordering of these IDs */
>> +static enum periph_id periph_for_dev[] = {
>> + ? ? ? PERIPH_ID_I2C0,
>> + ? ? ? PERIPH_ID_I2C1,
>> + ? ? ? PERIPH_ID_I2C2,
>> + ? ? ? PERIPH_ID_I2C3,
>> + ? ? ? PERIPH_ID_I2C4,
>> + ? ? ? PERIPH_ID_I2C5,
>> + ? ? ? PERIPH_ID_I2C6,
>> + ? ? ? PERIPH_ID_I2C7,
>> +};
>> +
>> +static enum periph_id i2c_get_periph_id(unsigned dev_index)
>> +{
>> + ? ? ? if (dev_index < ARRAY_SIZE(periph_for_dev))
>> + ? ? ? ? ? ? ? return periph_for_dev[dev_index];
>> +
>> + ? ? ? debug("%s: invalid bus %d", __func__, dev_index);
>> +
>> + ? ? ? return PERIPH_ID_NONE;
>> +}
>> +
>> +static struct s3c24x0_i2c *get_base_i2c(int bus_idx)
>> +{
>> + ? ? ? struct s3c24x0_i2c *i2c = (struct s3c24x0_i2c *)samsung_get_base_i2c();
>> +
>> + ? ? ? return &i2c[bus_idx];
>> +}
>
> This function can use in the s3c24xx adding #ifdef in this fuction, then
> you can reduce #ifdef.
-- Will do this.
>
>> +
>> +static inline struct exynos5_gpio_part1 *exynos_get_base_gpio1(void)
>> +{
>> + ? ? ? return (struct exynos5_gpio_part1 *)(EXYNOS5_GPIO_PART1_BASE);
>> +}
>> +
>> +#else
>> ?static int GetI2CSDA(void)
>> ?{
>> ? ? ? ?struct s3c24x0_gpio *gpio = s3c24x0_get_base_gpio();
>> @@ -77,16 +123,17 @@ static void SetI2CSCL(int x)
>> ? ? ? ?struct s3c24x0_gpio *gpio = s3c24x0_get_base_gpio();
>>
>> ?#ifdef CONFIG_S3C2410
>> - ? ? ? writel((readl(&gpio->gpedat) & ~0x4000) | (x & 1) << 14, &gpio->gpedat);
>> + ? ? ? writel((readl(&gpio->gpedat) & ~0x4000) |
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? (x & 1) << 14, &gpio->gpedat);
>> ?#endif
>> ?#ifdef CONFIG_S3C2400
>> ? ? ? ?writel((readl(&gpio->pgdat) & ~0x0040) | (x & 1) << 6, &gpio->pgdat);
>> ?#endif
>> ?}
>> +#endif
>>
>> -static int WaitForXfer(void)
>> +static int WaitForXfer(struct s3c24x0_i2c *i2c)
>> ?{
>> - ? ? ? struct s3c24x0_i2c *i2c = s3c24x0_get_base_i2c();
>> ? ? ? ?int i;
>>
>> ? ? ? ?i = I2C_TIMEOUT * 10000;
>> @@ -98,25 +145,84 @@ static int WaitForXfer(void)
>> ? ? ? ?return (readl(&i2c->iiccon) & I2CCON_IRPND) ? I2C_OK : I2C_NOK_TOUT;
>> ?}
>>
>> -static int IsACK(void)
>> +static int IsACK(struct s3c24x0_i2c *i2c)
>> ?{
>> - ? ? ? struct s3c24x0_i2c *i2c = s3c24x0_get_base_i2c();
>> -
>> ? ? ? ?return !(readl(&i2c->iicstat) & I2CSTAT_NACK);
>> ?}
>>
>> -static void ReadWriteByte(void)
>> +static void ReadWriteByte(struct s3c24x0_i2c *i2c)
>> ?{
>> - ? ? ? struct s3c24x0_i2c *i2c = s3c24x0_get_base_i2c();
>> -
>> ? ? ? ?writel(readl(&i2c->iiccon) & ~I2CCON_IRPND, &i2c->iiccon);
>> ?}
>>
>> +static void i2c_ch_init(struct s3c24x0_i2c *i2c, int speed, int slaveadd)
>> +{
>> + ? ? ? ulong freq, pres = 16, div;
>> +#ifdef CONFIG_EXYNOS5
>> + ? ? ? freq = get_i2c_clk();
>> +#else
>> + ? ? ? freq = get_PCLK();
>> +#endif
>> + ? ? ? /* calculate prescaler and divisor values */
>> + ? ? ? if ((freq / pres / (16 + 1)) > speed)
>> + ? ? ? ? ? ? ? /* set prescaler to 512 */
>> + ? ? ? ? ? ? ? pres = 512;
>> +
>> + ? ? ? div = 0;
>> + ? ? ? while ((freq / pres / (div + 1)) > speed)
>> + ? ? ? ? ? ? ? div++;
>> +
>> + ? ? ? /* set prescaler, divisor according to freq, also set ACKGEN, IRQ */
>> + ? ? ? writel((div & 0x0F) | 0xA0 | ((pres == 512) ? 0x40 : 0), &i2c->iiccon);
>> +
>> + ? ? ? /* init to SLAVE REVEIVE and set slaveaddr */
>> + ? ? ? writel(0, &i2c->iicstat);
>> + ? ? ? writel(slaveadd, &i2c->iicadd);
>> + ? ? ? /* program Master Transmit (and implicit STOP) */
>> + ? ? ? writel(I2C_MODE_MT | I2C_TXRX_ENA, &i2c->iicstat);
>> +}
>> +
>> +static void i2c_bus_init(struct s3c24x0_i2c *i2c, unsigned int bus)
>> +{
>> + ? ? ? int periph_id = i2c_get_periph_id(bus);
>> +
>> + ? ? ? exynos_pinmux_config(periph_id, 0);
>> +
>> + ? ? ? i2c_ch_init(i2c, CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
>> +}
>
> This function is used only in EXYNOS5.
-- This will be used in Multi bus also which other boards can use.
>
>> +
>> +#ifdef CONFIG_EXYNOS5
>> +void i2c_init(int speed, int slaveadd)
>> +{
>> + ? ? ? struct s3c24x0_i2c *i2c;
>> + ? ? ? struct exynos5_gpio_part1 *gpio;
>> + ? ? ? int i;
>> +
>> + ? ? ? /* By default i2c channel 0 is the current bus */
>> + ? ? ? g_current_bus = I2C0;
>> +
>> + ? ? ? i2c = get_base_i2c(g_current_bus);
>> +
>> + ? ? ? i2c_bus_init(i2c, g_current_bus);
>> +
>> + ? ? ? /* wait for some time to give previous transfer a chance to finish */
>> + ? ? ? i = I2C_TIMEOUT * 1000;
>> + ? ? ? while ((readl(&i2c->iicstat) & I2CSTAT_BSY) && (i > 0)) {
>> + ? ? ? ? ? ? ? udelay(1000);
>> + ? ? ? ? ? ? ? i--;
>> + ? ? ? }
>> +
>> + ? ? ? gpio = exynos_get_base_gpio1();
>> + ? ? ? writel((readl(&gpio->b3.con) & ~0x00FF) | 0x0022, &gpio->b3.con);
>
> This doesn't need to do because of i2c_bus_init().
-- Will correct this.
>
>> +
>> + ? ? ? i2c_ch_init(i2c, speed, slaveadd);
>
> The i2c_bus_init() calls i2c_ch_init() already.
>
-- You are right. Will correct this.

>> +}
>> +
>> +#else
>> ?void i2c_init(int speed, int slaveadd)
>> ?{
>> ? ? ? ?struct s3c24x0_i2c *i2c = s3c24x0_get_base_i2c();
>> ? ? ? ?struct s3c24x0_gpio *gpio = s3c24x0_get_base_gpio();
>> - ? ? ? ulong freq, pres = 16, div;
>> ? ? ? ?int i;
>>
>> ? ? ? ?/* wait for some time to give previous transfer a chance to finish */
>> @@ -171,27 +277,9 @@ void i2c_init(int speed, int slaveadd)
>> ?#endif
>> ? ? ? ?}
>>
>> - ? ? ? /* calculate prescaler and divisor values */
>> - ? ? ? freq = get_PCLK();
>> - ? ? ? if ((freq / pres / (16 + 1)) > speed)
>> - ? ? ? ? ? ? ? /* set prescaler to 512 */
>> - ? ? ? ? ? ? ? pres = 512;
>> -
>> - ? ? ? div = 0;
>> - ? ? ? while ((freq / pres / (div + 1)) > speed)
>> - ? ? ? ? ? ? ? div++;
>> -
>> - ? ? ? /* set prescaler, divisor according to freq, also set
>> - ? ? ? ?* ACKGEN, IRQ */
>> - ? ? ? writel((div & 0x0F) | 0xA0 | ((pres == 512) ? 0x40 : 0), &i2c->iiccon);
>> -
>> - ? ? ? /* init to SLAVE REVEIVE and set slaveaddr */
>> - ? ? ? writel(0, &i2c->iicstat);
>> - ? ? ? writel(slaveadd, &i2c->iicadd);
>> - ? ? ? /* program Master Transmit (and implicit STOP) */
>> - ? ? ? writel(I2C_MODE_MT | I2C_TXRX_ENA, &i2c->iicstat);
>> -
>> + ? ? ? i2c_ch_init(i2c, speed, slaveadd);
>> ?}
>> +#endif
>>
>> ?/*
>> ?* cmd_type is 0 for write, 1 for read.
>> @@ -200,19 +288,19 @@ void i2c_init(int speed, int slaveadd)
>> ?* by the char, we could make it larger if needed. If it is
>> ?* 0 we skip the address write cycle.
>> ?*/
>> -static
>> -int i2c_transfer(unsigned char cmd_type,
>> - ? ? ? ? ? ? ? ?unsigned char chip,
>> - ? ? ? ? ? ? ? ?unsigned char addr[],
>> - ? ? ? ? ? ? ? ?unsigned char addr_len,
>> - ? ? ? ? ? ? ? ?unsigned char data[], unsigned short data_len)
>> +static int i2c_transfer(struct s3c24x0_i2c *i2c,
>> + ? ? ? ? ? ? ? ? ? ? ? unsigned char cmd_type,
>> + ? ? ? ? ? ? ? ? ? ? ? unsigned char chip,
>> + ? ? ? ? ? ? ? ? ? ? ? unsigned char addr[],
>> + ? ? ? ? ? ? ? ? ? ? ? unsigned char addr_len,
>> + ? ? ? ? ? ? ? ? ? ? ? unsigned char data[],
>> + ? ? ? ? ? ? ? ? ? ? ? unsigned short data_len)
>> ?{
>> - ? ? ? struct s3c24x0_i2c *i2c = s3c24x0_get_base_i2c();
>> ? ? ? ?int i, result;
>>
>> ? ? ? ?if (data == 0 || data_len == 0) {
>> ? ? ? ? ? ? ? ?/*Don't support data transfer of no length or to address 0 */
>> - ? ? ? ? ? ? ? printf("i2c_transfer: bad call\n");
>> + ? ? ? ? ? ? ? debug("i2c_transfer: bad call\n");
>> ? ? ? ? ? ? ? ?return I2C_NOK;
>> ? ? ? ?}
>>
>> @@ -226,7 +314,7 @@ int i2c_transfer(unsigned char cmd_type,
>> ? ? ? ?if (readl(&i2c->iicstat) & I2CSTAT_BSY)
>> ? ? ? ? ? ? ? ?return I2C_NOK_TOUT;
>>
>> - ? ? ? writel(readl(&i2c->iiccon) | 0x80, &i2c->iiccon);
>> + ? ? ? writel(readl(&i2c->iiccon) | I2CCON_ACKGEN, &i2c->iiccon);
>> ? ? ? ?result = I2C_OK;
>>
>> ? ? ? ?switch (cmd_type) {
>> @@ -238,16 +326,16 @@ int i2c_transfer(unsigned char cmd_type,
>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? &i2c->iicstat);
>> ? ? ? ? ? ? ? ? ? ? ? ?i = 0;
>> ? ? ? ? ? ? ? ? ? ? ? ?while ((i < addr_len) && (result == I2C_OK)) {
>> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? result = WaitForXfer();
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? result = WaitForXfer(i2c);
>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?writel(addr[i], &i2c->iicds);
>> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ReadWriteByte();
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ReadWriteByte(i2c);
>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?i++;
>> ? ? ? ? ? ? ? ? ? ? ? ?}
>> ? ? ? ? ? ? ? ? ? ? ? ?i = 0;
>> ? ? ? ? ? ? ? ? ? ? ? ?while ((i < data_len) && (result == I2C_OK)) {
>> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? result = WaitForXfer();
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? result = WaitForXfer(i2c);
>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?writel(data[i], &i2c->iicds);
>> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ReadWriteByte();
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ReadWriteByte(i2c);
>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?i++;
>> ? ? ? ? ? ? ? ? ? ? ? ?}
>> ? ? ? ? ? ? ? ?} else {
>> @@ -257,19 +345,19 @@ int i2c_transfer(unsigned char cmd_type,
>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? &i2c->iicstat);
>> ? ? ? ? ? ? ? ? ? ? ? ?i = 0;
>> ? ? ? ? ? ? ? ? ? ? ? ?while ((i < data_len) && (result = I2C_OK)) {
>> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? result = WaitForXfer();
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? result = WaitForXfer(i2c);
>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?writel(data[i], &i2c->iicds);
>> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ReadWriteByte();
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ReadWriteByte(i2c);
>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?i++;
>> ? ? ? ? ? ? ? ? ? ? ? ?}
>> ? ? ? ? ? ? ? ?}
>>
>> ? ? ? ? ? ? ? ?if (result == I2C_OK)
>> - ? ? ? ? ? ? ? ? ? ? ? result = WaitForXfer();
>> + ? ? ? ? ? ? ? ? ? ? ? result = WaitForXfer(i2c);
>>
>> ? ? ? ? ? ? ? ?/* send STOP */
>> ? ? ? ? ? ? ? ?writel(I2C_MODE_MR | I2C_TXRX_ENA, &i2c->iicstat);
>> - ? ? ? ? ? ? ? ReadWriteByte();
>> + ? ? ? ? ? ? ? ReadWriteByte(i2c);
>> ? ? ? ? ? ? ? ?break;
>>
>> ? ? ? ?case I2C_READ:
>> @@ -279,13 +367,13 @@ int i2c_transfer(unsigned char cmd_type,
>> ? ? ? ? ? ? ? ? ? ? ? ?/* send START */
>> ? ? ? ? ? ? ? ? ? ? ? ?writel(readl(&i2c->iicstat) | I2C_START_STOP,
>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? &i2c->iicstat);
>> - ? ? ? ? ? ? ? ? ? ? ? result = WaitForXfer();
>> - ? ? ? ? ? ? ? ? ? ? ? if (IsACK()) {
>> + ? ? ? ? ? ? ? ? ? ? ? result = WaitForXfer(i2c);
>> + ? ? ? ? ? ? ? ? ? ? ? if (IsACK(i2c)) {
>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?i = 0;
>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?while ((i < addr_len) && (result == I2C_OK)) {
>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?writel(addr[i], &i2c->iicds);
>> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ReadWriteByte();
>> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? result = WaitForXfer();
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ReadWriteByte(i2c);
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? result = WaitForXfer(i2c);
>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?i++;
>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?}
>>
>> @@ -293,16 +381,17 @@ int i2c_transfer(unsigned char cmd_type,
>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?/* resend START */
>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?writel(I2C_MODE_MR | I2C_TXRX_ENA |
>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? I2C_START_STOP, &i2c->iicstat);
>> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ReadWriteByte();
>> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? result = WaitForXfer();
>> + ? ? ? ? ? ? ? ? ? ? ? ReadWriteByte(i2c);
>> + ? ? ? ? ? ? ? ? ? ? ? result = WaitForXfer(i2c);
>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?i = 0;
>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?while ((i < data_len) && (result == I2C_OK)) {
>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?/* disable ACK for final READ */
>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?if (i == data_len - 1)
>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?writel(readl(&i2c->iiccon)
>> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?& ~0x80, &i2c->iiccon);
>> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ReadWriteByte();
>> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? result = WaitForXfer();
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? & ~I2CCON_ACKGEN,
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? &i2c->iiccon);
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ReadWriteByte(i2c);
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? result = WaitForXfer(i2c);
>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?data[i] = readl(&i2c->iicds);
>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?i++;
>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?}
>> @@ -316,17 +405,18 @@ int i2c_transfer(unsigned char cmd_type,
>> ? ? ? ? ? ? ? ? ? ? ? ?/* send START */
>> ? ? ? ? ? ? ? ? ? ? ? ?writel(readl(&i2c->iicstat) | I2C_START_STOP,
>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? &i2c->iicstat);
>> - ? ? ? ? ? ? ? ? ? ? ? result = WaitForXfer();
>> + ? ? ? ? ? ? ? ? ? ? ? result = WaitForXfer(i2c);
>>
>> - ? ? ? ? ? ? ? ? ? ? ? if (IsACK()) {
>> + ? ? ? ? ? ? ? ? ? ? ? if (IsACK(i2c)) {
>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?i = 0;
>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?while ((i < data_len) && (result == I2C_OK)) {
>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?/* disable ACK for final READ */
>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?if (i == data_len - 1)
>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?writel(readl(&i2c->iiccon) &
>> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?~0x80, &i2c->iiccon);
>> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ReadWriteByte();
>> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? result = WaitForXfer();
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ~I2CCON_ACKGEN,
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? &i2c->iiccon);
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ReadWriteByte(i2c);
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? result = WaitForXfer(i2c);
>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?data[i] = readl(&i2c->iicds);
>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?i++;
>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?}
>> @@ -337,22 +427,28 @@ int i2c_transfer(unsigned char cmd_type,
>>
>> ? ? ? ? ? ? ? ?/* send STOP */
>> ? ? ? ? ? ? ? ?writel(I2C_MODE_MR | I2C_TXRX_ENA, &i2c->iicstat);
>> - ? ? ? ? ? ? ? ReadWriteByte();
>> + ? ? ? ? ? ? ? ReadWriteByte(i2c);
>> ? ? ? ? ? ? ? ?break;
>>
>> ? ? ? ?default:
>> - ? ? ? ? ? ? ? printf("i2c_transfer: bad call\n");
>> + ? ? ? ? ? ? ? debug("i2c_transfer: bad call\n");
>> ? ? ? ? ? ? ? ?result = I2C_NOK;
>> ? ? ? ? ? ? ? ?break;
>> ? ? ? ?}
>>
>> - ? ? ? return (result);
>> + ? ? ? return result;
>> ?}
>>
>> ?int i2c_probe(uchar chip)
>> ?{
>> + ? ? ? struct s3c24x0_i2c *i2c;
>> ? ? ? ?uchar buf[1];
>>
>> +#ifdef CONFIG_EXYNOS5
>> + ? ? ? i2c = get_base_i2c(g_current_bus);
>> +#else
>> + ? ? ? i2c = s3c24x0_get_base_i2c();
>> +#endif
>> ? ? ? ?buf[0] = 0;
>>
>> ? ? ? ?/*
>> @@ -360,16 +456,17 @@ int i2c_probe(uchar chip)
>> ? ? ? ? * address was <ACK>ed (i.e. there was a chip at that address which
>> ? ? ? ? * drove the data line low).
>> ? ? ? ? */
>> - ? ? ? return i2c_transfer(I2C_READ, chip << 1, 0, 0, buf, 1) != I2C_OK;
>> + ? ? ? return i2c_transfer(i2c, I2C_READ, chip << 1, 0, 0, buf, 1) != I2C_OK;
>> ?}
>>
>> ?int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len)
>> ?{
>> + ? ? ? struct s3c24x0_i2c *i2c;
>> ? ? ? ?uchar xaddr[4];
>> ? ? ? ?int ret;
>>
>> ? ? ? ?if (alen > 4) {
>> - ? ? ? ? ? ? ? printf("I2C read: addr len %d not supported\n", alen);
>> + ? ? ? ? ? ? ? debug("I2C read: addr len %d not supported\n", alen);
>> ? ? ? ? ? ? ? ?return 1;
>> ? ? ? ?}
>>
>> @@ -396,10 +493,15 @@ int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len)
>> ? ? ? ? ? ? ? ?chip |= ((addr >> (alen * 8)) &
>> ? ? ? ? ? ? ? ? ? ? ? ? CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW);
>> ?#endif
>> - ? ? ? if ((ret =
>> - ? ? ? ? ? ?i2c_transfer(I2C_READ, chip << 1, &xaddr[4 - alen], alen,
>> - ? ? ? ? ? ? ? ? ? ? ? ? buffer, len)) != 0) {
>> - ? ? ? ? ? ? ? printf("I2c read: failed %d\n", ret);
>> +#ifdef CONFIG_EXYNOS5
>> + ? ? ? i2c = get_base_i2c(g_current_bus);
>> +#else
>> + ? ? ? i2c = s3c24x0_get_base_i2c();
>> +#endif
>> + ? ? ? ret = i2c_transfer(i2c, I2C_READ, chip << 1, &xaddr[4 - alen], alen,
>> + ? ? ? ? ? ? ? ? ? ? ? buffer, len);
>> + ? ? ? if (ret != 0) {
>> + ? ? ? ? ? ? ? debug("I2c read: failed %d\n", ret);
>> ? ? ? ? ? ? ? ?return 1;
>> ? ? ? ?}
>> ? ? ? ?return 0;
>> @@ -407,10 +509,11 @@ int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len)
>>
>> ?int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len)
>> ?{
>> + ? ? ? struct s3c24x0_i2c *i2c;
>> ? ? ? ?uchar xaddr[4];
>>
>> ? ? ? ?if (alen > 4) {
>> - ? ? ? ? ? ? ? printf("I2C write: addr len %d not supported\n", alen);
>> + ? ? ? ? ? ? ? debug("I2C write: addr len %d not supported\n", alen);
>> ? ? ? ? ? ? ? ?return 1;
>> ? ? ? ?}
>>
>> @@ -436,8 +539,13 @@ int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len)
>> ? ? ? ? ? ? ? ?chip |= ((addr >> (alen * 8)) &
>> ? ? ? ? ? ? ? ? ? ? ? ? CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW);
>> ?#endif
>> +#ifdef CONFIG_EXYNOS5
>> + ? ? ? i2c = get_base_i2c(g_current_bus);
>> +#else
>> + ? ? ? i2c = s3c24x0_get_base_i2c();
>> +#endif
>> ? ? ? ?return (i2c_transfer
>> - ? ? ? ? ? ? ? (I2C_WRITE, chip << 1, &xaddr[4 - alen], alen, buffer,
>> + ? ? ? ? ? ? ? (i2c, I2C_WRITE, chip << 1, &xaddr[4 - alen], alen, buffer,
>> ? ? ? ? ? ? ? ? len) != 0);
>> ?}
>> ?#endif /* CONFIG_HARD_I2C */
>> diff --git a/drivers/i2c/s3c24x0_i2c.h b/drivers/i2c/s3c24x0_i2c.h
>> index d357a0a..57aafb1 100644
>> --- a/drivers/i2c/s3c24x0_i2c.h
>> +++ b/drivers/i2c/s3c24x0_i2c.h
>> @@ -23,6 +23,9 @@
>> ?#ifndef _S3C24X0_I2C_H
>> ?#define _S3C24X0_I2C_H
>>
>> +/* I2C channels exynos5 has 8 i2c channel */
>> +#define I2C0 ? ? ? ? ? 0
>> +
>> ?struct s3c24x0_i2c {
>> ? ? ? ?u32 ? ? iiccon;
>> ? ? ? ?u32 ? ? iicstat;
>> --
>> 1.7.4.4
>>
>> _______________________________________________
>> U-Boot mailing list
>> U-Boot at lists.denx.de
>> http://lists.denx.de/mailman/listinfo/u-boot
>
> Thanks.
>
> --
Regards
Rajeshwari Shinde
> - Joonyoung Shim
> _______________________________________________
> U-Boot mailing list
> U-Boot at lists.denx.de
> http://lists.denx.de/mailman/listinfo/u-boot

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [U-Boot] [PATCH 7/8 V2] I2C: Add support for Multi channel
  2012-06-15  7:15   ` Joonyoung Shim
@ 2012-06-19  5:44     ` Rajeshwari Birje
  2012-06-19  7:30       ` Joonyoung Shim
  0 siblings, 1 reply; 19+ messages in thread
From: Rajeshwari Birje @ 2012-06-19  5:44 UTC (permalink / raw)
  To: u-boot

Hi Joonyoung Shim,

Thank you for comments.

On Fri, Jun 15, 2012 at 12:45 PM, Joonyoung Shim <dofmind@gmail.com> wrote:
> Hi,
>
> 2012/6/7 Rajeshwari Shinde <rajeshwari.s@samsung.com>:
>> This adds multiple i2c channel support for I2C.
>>
>> Signed-off-by: Alim Akhtar <alim.akhtar@samsung.com>
>> Signed-off-by: Rajeshwari Shinde <rajeshwari.s@samsung.com>
>> Acked-by: Simon Glass <sjg@chromium.org>
>> ---
>> ?drivers/i2c/s3c24x0_i2c.c | ? 27 +++++++++++++++++++++++++++
>> ?1 files changed, 27 insertions(+), 0 deletions(-)
>>
>> diff --git a/drivers/i2c/s3c24x0_i2c.c b/drivers/i2c/s3c24x0_i2c.c
>> index a71f147..7521cb8 100644
>> --- a/drivers/i2c/s3c24x0_i2c.c
>> +++ b/drivers/i2c/s3c24x0_i2c.c
>> @@ -191,6 +191,33 @@ static void i2c_bus_init(struct s3c24x0_i2c *i2c, unsigned int bus)
>> ? ? ? ?i2c_ch_init(i2c, CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
>> ?}
>>
>> +/*
>> + * MULTI BUS I2C support
>> + */
>> +
>> +#ifdef CONFIG_I2C_MULTI_BUS
>> +int i2c_set_bus_num(unsigned int bus)
>> +{
>> + ? ? ? struct s3c24x0_i2c *i2c;
>> +
>> + ? ? ? if ((bus < 0) || (bus >= CONFIG_MAX_I2C_NUM)) {
>> + ? ? ? ? ? ? ? debug("Bad bus: %d\n", bus);
>> + ? ? ? ? ? ? ? return -1;
>> + ? ? ? }
>> +
>> + ? ? ? g_current_bus = bus;
>> + ? ? ? i2c = get_base_i2c(g_current_bus);
>> + ? ? ? i2c_bus_init(i2c, g_current_bus);
>
> This causes duplicated pin configuration whenever calls i2c_set_bus_num().
>
-- Initally we are initialising only for bus 0, When this function
gets called with bus id other than 0 we need to initialise that bus.
>> +
>> + ? ? ? return 0;
>> +}
>> +
>> +unsigned int i2c_get_bus_num(void)
>> +{
>> + ? ? ? return g_current_bus;
>> +}
>> +#endif
>
> Does only EXYNOS5 support CONFIG_I2C_MULTI_BUS?
-- EXYNOS4 also has Multi Bus I2C
>
>> +
>> ?#ifdef CONFIG_EXYNOS5
>> ?void i2c_init(int speed, int slaveadd)
>> ?{
>> --
>> 1.7.4.4
>>
>> _______________________________________________
>> U-Boot mailing list
>> U-Boot at lists.denx.de
>> http://lists.denx.de/mailman/listinfo/u-boot
>
> Thanks.
>
> --
> - Joonyoung Shim
> _______________________________________________
> U-Boot mailing list
> U-Boot at lists.denx.de
> http://lists.denx.de/mailman/listinfo/u-boot
Regards,
Rajeshwari Shinde.

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [U-Boot] [PATCH 6/8 V2] I2C: Modify the I2C driver for EXYNOS5
  2012-06-19  5:38     ` Rajeshwari Birje
@ 2012-06-19  7:15       ` Joonyoung Shim
  2012-06-19  7:28         ` Rajeshwari Birje
  0 siblings, 1 reply; 19+ messages in thread
From: Joonyoung Shim @ 2012-06-19  7:15 UTC (permalink / raw)
  To: u-boot

>>> +static void i2c_bus_init(struct s3c24x0_i2c *i2c, unsigned int bus)
>>> +{
>>> + ? ? ? int periph_id = i2c_get_periph_id(bus);
>>> +
>>> + ? ? ? exynos_pinmux_config(periph_id, 0);
>>> +
>>> + ? ? ? i2c_ch_init(i2c, CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
>>> +}
>>
>> This function is used only in EXYNOS5.
> -- This will be used in Multi bus also which other boards can use.

But, this will cause compile errors at the s3c24xx.


-- 
- Joonyoung Shim

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [U-Boot] [PATCH 6/8 V2] I2C: Modify the I2C driver for EXYNOS5
  2012-06-19  7:15       ` Joonyoung Shim
@ 2012-06-19  7:28         ` Rajeshwari Birje
  0 siblings, 0 replies; 19+ messages in thread
From: Rajeshwari Birje @ 2012-06-19  7:28 UTC (permalink / raw)
  To: u-boot

Hi Joonyoung Shim,

Thank you for comments.

On Tue, Jun 19, 2012 at 12:45 PM, Joonyoung Shim <dofmind@gmail.com> wrote:
>>>> +static void i2c_bus_init(struct s3c24x0_i2c *i2c, unsigned int bus)
>>>> +{
>>>> + ? ? ? int periph_id = i2c_get_periph_id(bus);
>>>> +
>>>> + ? ? ? exynos_pinmux_config(periph_id, 0);
>>>> +
>>>> + ? ? ? i2c_ch_init(i2c, CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
>>>> +}
>>>
>>> This function is used only in EXYNOS5.
>> -- This will be used in Multi bus also which other boards can use.
>
> But, this will cause compile errors at the s3c24xx.
-- Resoved the same and sent patch set.
>
>
> --
> - Joonyoung Shim

Regards,
Rajeshwari Shinde.

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [U-Boot] [PATCH 7/8 V2] I2C: Add support for Multi channel
  2012-06-19  5:44     ` Rajeshwari Birje
@ 2012-06-19  7:30       ` Joonyoung Shim
  0 siblings, 0 replies; 19+ messages in thread
From: Joonyoung Shim @ 2012-06-19  7:30 UTC (permalink / raw)
  To: u-boot

2012/6/19 Rajeshwari Birje <rajeshwari.birje@gmail.com>:
> Hi Joonyoung Shim,
>
> Thank you for comments.
>
> On Fri, Jun 15, 2012 at 12:45 PM, Joonyoung Shim <dofmind@gmail.com> wrote:
>> Hi,
>>
>> 2012/6/7 Rajeshwari Shinde <rajeshwari.s@samsung.com>:
>>> This adds multiple i2c channel support for I2C.
>>>
>>> Signed-off-by: Alim Akhtar <alim.akhtar@samsung.com>
>>> Signed-off-by: Rajeshwari Shinde <rajeshwari.s@samsung.com>
>>> Acked-by: Simon Glass <sjg@chromium.org>
>>> ---
>>> ?drivers/i2c/s3c24x0_i2c.c | ? 27 +++++++++++++++++++++++++++
>>> ?1 files changed, 27 insertions(+), 0 deletions(-)
>>>
>>> diff --git a/drivers/i2c/s3c24x0_i2c.c b/drivers/i2c/s3c24x0_i2c.c
>>> index a71f147..7521cb8 100644
>>> --- a/drivers/i2c/s3c24x0_i2c.c
>>> +++ b/drivers/i2c/s3c24x0_i2c.c
>>> @@ -191,6 +191,33 @@ static void i2c_bus_init(struct s3c24x0_i2c *i2c, unsigned int bus)
>>> ? ? ? ?i2c_ch_init(i2c, CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
>>> ?}
>>>
>>> +/*
>>> + * MULTI BUS I2C support
>>> + */
>>> +
>>> +#ifdef CONFIG_I2C_MULTI_BUS
>>> +int i2c_set_bus_num(unsigned int bus)
>>> +{
>>> + ? ? ? struct s3c24x0_i2c *i2c;
>>> +
>>> + ? ? ? if ((bus < 0) || (bus >= CONFIG_MAX_I2C_NUM)) {
>>> + ? ? ? ? ? ? ? debug("Bad bus: %d\n", bus);
>>> + ? ? ? ? ? ? ? return -1;
>>> + ? ? ? }
>>> +
>>> + ? ? ? g_current_bus = bus;
>>> + ? ? ? i2c = get_base_i2c(g_current_bus);
>>> + ? ? ? i2c_bus_init(i2c, g_current_bus);
>>
>> This causes duplicated pin configuration whenever calls i2c_set_bus_num().
>>
> -- Initally we are initialising only for bus 0, When this function
> gets called with bus id other than 0 we need to initialise that bus.

The problem is i2c_set_bus_num() can be called many times.
If did i2c_bus_init() already, just set g_current_bus.


-- 
- Joonyoung Shim

^ permalink raw reply	[flat|nested] 19+ messages in thread

end of thread, other threads:[~2012-06-19  7:30 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-06-07  6:09 [U-Boot] [PATCH 0/8 V2] EXYNOS5: Enable I2C support Rajeshwari Shinde
2012-06-07  6:09 ` [U-Boot] [PATCH 1/8 V2] EXYNOS: CLK: Add i2c clock Rajeshwari Shinde
2012-06-12  5:46   ` Simon Glass
2012-06-07  6:09 ` [U-Boot] [PATCH 2/8 V2] EXYNOS: Add I2C base address Rajeshwari Shinde
2012-06-07  6:09 ` [U-Boot] [PATCH 3/8 V2] EXYNOS: PINMUX: Add pinmux support for I2C Rajeshwari Shinde
2012-06-12  5:47   ` Simon Glass
2012-06-07  6:09 ` [U-Boot] [PATCH 4/8 V2] I2C: Move struct s3c24x0_i2c to a common place Rajeshwari Shinde
2012-06-07  6:09 ` [U-Boot] [PATCH 5/8 V2] I2C: S3C24X0: Add offset to calculate next i2c channel base address Rajeshwari Shinde
2012-06-07  6:09 ` [U-Boot] [PATCH 6/8 V2] I2C: Modify the I2C driver for EXYNOS5 Rajeshwari Shinde
2012-06-12  5:52   ` Simon Glass
2012-06-15  7:10   ` Joonyoung Shim
2012-06-19  5:38     ` Rajeshwari Birje
2012-06-19  7:15       ` Joonyoung Shim
2012-06-19  7:28         ` Rajeshwari Birje
2012-06-07  6:09 ` [U-Boot] [PATCH 7/8 V2] I2C: Add support for Multi channel Rajeshwari Shinde
2012-06-15  7:15   ` Joonyoung Shim
2012-06-19  5:44     ` Rajeshwari Birje
2012-06-19  7:30       ` Joonyoung Shim
2012-06-07  6:09 ` [U-Boot] [PATCH 8/8 V2] CONFIG: SMDK5250: I2C: Enable I2C Rajeshwari Shinde

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.