All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH] sh: i2c: Add support I2C controller of SH7734
@ 2012-02-22  1:13 Nobuhiro Iwamatsu
  2012-02-22  4:25 ` Mike Frysinger
  0 siblings, 1 reply; 11+ messages in thread
From: Nobuhiro Iwamatsu @ 2012-02-22  1:13 UTC (permalink / raw)
  To: u-boot

Renesas SH7734 has two I2C interfaceis.
This supports these I2C.

V3: - Fix error for whitespace.
V2: - Changed bit control to use the clr|set|clrsetbits_* functions.
    - Fix wrong comment style.
    - Add new line before for loop in i2c_read.

Signed-off-by: Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com>
Acked-by: Heiko Schocher <hs@denx.de>

---
 drivers/i2c/Makefile        |    1 +
 drivers/i2c/sh_sh7734_i2c.c |  445 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 446 insertions(+), 0 deletions(-)
 create mode 100644 drivers/i2c/sh_sh7734_i2c.c

diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile
index 504db03..506269d 100644
--- a/drivers/i2c/Makefile
+++ b/drivers/i2c/Makefile
@@ -44,6 +44,7 @@ COBJS-$(CONFIG_SPEAR_I2C) += spr_i2c.o
 COBJS-$(CONFIG_TSI108_I2C) += tsi108_i2c.o
 COBJS-$(CONFIG_U8500_I2C) += u8500_i2c.o
 COBJS-$(CONFIG_SH_I2C) += sh_i2c.o
+COBJS-$(CONFIG_SH_SH7734_I2C) += sh_sh7734_i2c.o
 
 COBJS	:= $(COBJS-y)
 SRCS	:= $(COBJS:.o=.c)
diff --git a/drivers/i2c/sh_sh7734_i2c.c b/drivers/i2c/sh_sh7734_i2c.c
new file mode 100644
index 0000000..32b129c
--- /dev/null
+++ b/drivers/i2c/sh_sh7734_i2c.c
@@ -0,0 +1,445 @@
+/*
+ * Copyright (C) 2012 Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com>
+ * Copyright (C) 2012 Renesas Solutions Corp.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/io.h>
+
+struct sh_i2c {
+	u8 iccr1;
+	u8 iccr2;
+	u8 icmr;
+	u8 icier;
+	u8 icsr;
+	u8 sar;
+	u8 icdrt;
+	u8 icdrr;
+	u8 nf2cyc;
+	u8 __pad0;
+	u8 __pad1;
+};
+
+static struct sh_i2c *base;
+static u8 iccr1_cks, nf2cyc;
+
+/* ICCR1 */
+#define SH_I2C_ICCR1_ICE	(1 << 7)
+#define SH_I2C_ICCR1_RCVD	(1 << 6)
+#define SH_I2C_ICCR1_MST	(1 << 5)
+#define SH_I2C_ICCR1_TRS	(1 << 4)
+#define SH_I2C_ICCR1_MTRS	\
+	(SH_I2C_ICCR1_MST | SH_I2C_ICCR1_TRS)
+
+/* ICCR1 */
+#define SH_I2C_ICCR2_BBSY	(1 << 7)
+#define SH_I2C_ICCR2_SCP	(1 << 6)
+#define SH_I2C_ICCR2_SDAO	(1 << 5)
+#define SH_I2C_ICCR2_SDAOP	(1 << 4)
+#define SH_I2C_ICCR2_SCLO	(1 << 3)
+#define SH_I2C_ICCR2_IICRST	(1 << 1)
+
+#define SH_I2C_ICIER_TIE	(1 << 7)
+#define SH_I2C_ICIER_TEIE	(1 << 6)
+#define SH_I2C_ICIER_RIE	(1 << 5)
+#define SH_I2C_ICIER_NAKIE	(1 << 4)
+#define SH_I2C_ICIER_STIE	(1 << 3)
+#define SH_I2C_ICIER_ACKE	(1 << 2)
+#define SH_I2C_ICIER_ACKBR	(1 << 1)
+#define SH_I2C_ICIER_ACKBT	(1 << 0)
+
+#define SH_I2C_ICSR_TDRE	(1 << 7)
+#define SH_I2C_ICSR_TEND	(1 << 6)
+#define SH_I2C_ICSR_RDRF	(1 << 5)
+#define SH_I2C_ICSR_NACKF	(1 << 4)
+#define SH_I2C_ICSR_STOP	(1 << 3)
+#define SH_I2C_ICSR_ALOVE	(1 << 2)
+#define SH_I2C_ICSR_AAS		(1 << 1)
+#define SH_I2C_ICSR_ADZ		(1 << 0)
+
+#define IRQ_WAIT 1000
+
+
+static void sh_i2c_send_stop(struct sh_i2c *base)
+{
+	clrbits_le8(&base->iccr2, (SH_I2C_ICCR2_BBSY | SH_I2C_ICCR2_SCP));
+}
+
+static int check_stop(struct sh_i2c *base)
+{
+	int i, ret = 1;
+
+	for (i = 0 ; i < IRQ_WAIT ; i++) {
+		if (SH_I2C_ICSR_STOP & readb(&base->icsr)) {
+			ret = 0;
+			break;
+		}
+		udelay(10);
+	}
+
+	clrbits_le8(&base->icsr, SH_I2C_ICSR_STOP);
+
+	return ret;
+}
+
+static int check_tend(struct sh_i2c *base, int stop)
+{
+	int i, ret = 1;
+
+	for (i = 0 ; i < IRQ_WAIT ; i++) {
+		if (SH_I2C_ICSR_TEND & readb(&base->icsr)) {
+			ret = 0;
+			break;
+		}
+		udelay(10);
+	}
+
+	if (stop) {
+		u8 data;
+
+		clrbits_le8(&base->icsr, SH_I2C_ICSR_STOP);
+
+		sh_i2c_send_stop(base);
+	}
+
+	clrbits_le8(&base->icsr, SH_I2C_ICSR_TEND);
+
+	return ret;
+}
+
+static int check_tdre(struct sh_i2c *base)
+{
+	int i;
+
+	for (i = 0 ; i < IRQ_WAIT ; i++) {
+		if (SH_I2C_ICSR_TDRE & readb(&base->icsr))
+			return 0;
+		udelay(10);
+	}
+
+	return 1;
+}
+
+static int check_rdrf(struct sh_i2c *base)
+{
+	int i;
+
+	for (i = 0 ; i < IRQ_WAIT ; i++) {
+		if (SH_I2C_ICSR_RDRF & readb(&base->icsr))
+			return 0;
+		udelay(10);
+	}
+
+	return 1;
+}
+
+static int check_bbsy(struct sh_i2c *base)
+{
+	int i;
+
+	for (i = 0 ; i < IRQ_WAIT ; i++) {
+		if (!(SH_I2C_ICCR2_BBSY & readb(&base->iccr2)))
+			return 0;
+		udelay(10);
+	}
+	return 1;
+}
+
+static int check_ackbr(struct sh_i2c *base)
+{
+	int i;
+
+	for (i = 0 ; i < IRQ_WAIT ; i++) {
+		if (!(SH_I2C_ICIER_ACKBR & readb(&base->icier)))
+			return 0;
+		udelay(10);
+	}
+
+	return 1;
+}
+
+#if DEBUG
+static void sh_i2c_dump_reg(struct sh_i2c *base)
+{
+	printf("iccr1 : %02X\n", readb(&base->iccr1));
+	printf("iccr2 : %02X\n", readb(&base->iccr2));
+	printf("icmr  : %02X\n", readb(&base->icmr));
+	printf("icier : %02X\n", readb(&base->icier));
+	printf("icsr  : %02X\n", readb(&base->icsr));
+	printf("sar   : %02X\n", readb(&base->sar));
+	printf("icdrt : %02X\n", readb(&base->icdrt));
+	printf("icdrr : %02X\n", readb(&base->icdrr));
+	printf("nf2cyc: %02X\n", readb(&base->nf2cyc));
+}
+#endif
+
+static void sh_i2c_reset(struct sh_i2c *base)
+{
+	setbits_8(&base->iccr2, SH_I2C_ICCR2_IICRST);
+
+	udelay(100);
+
+	clrbits_8(&base->iccr2, SH_I2C_ICCR2_IICRST);
+}
+
+static int i2c_set_addr(struct sh_i2c *base, u8 id, u8 reg)
+{
+	u8 data;
+
+	if (check_bbsy(base)) {
+		printf("i2c bus busy\n");
+		goto fail;
+	}
+
+	setbits_8(&base->iccr1, SH_I2C_ICCR1_MTRS)
+
+	clrsetbits_8(&base->iccr1, SH_I2C_ICCR2_SCP, SH_I2C_ICCR2_BBSY);
+
+	writeb(id << 1, &base->icdrt);
+
+	if (check_tend(base, 0)) {
+		printf("TEND check fail...\n");
+		goto fail;
+	}
+
+	if (check_ackbr(base)) {
+		check_tend(base, 0);
+		sh_i2c_send_stop(base);
+		goto fail;
+	}
+
+	writeb(reg, &base->icdrt);
+
+	if (check_tdre(base)) {
+		printf("TDRE check fail...\n");
+		goto fail;
+	}
+
+	if (check_tend(base, 0)) {
+		printf("TEND check fail...\n");
+		goto fail;
+	}
+
+	return 0;
+
+fail:
+
+	return 1;
+}
+
+static int
+i2c_raw_write(struct sh_i2c *base, u8 id, u8 reg, u8 *val, int size)
+{
+	int i;
+	u8 data;
+
+	if (i2c_set_addr(base, id, reg)) {
+		printf("Fail set slave address\n");
+		return 1;
+	}
+
+	for (i = 0 ; i < size ; i++) {
+		writeb(val[i], &base->icdrt);
+		check_tdre(base);
+	}
+
+	check_tend(base, 1);
+	check_stop(base);
+
+	udelay(100);
+
+	clrbits_8(&base->iccr1, SH_I2C_ICCR1_MTRS);
+	clrbits_8(&base->icsr, SH_I2C_ICSR_TDRE);
+
+	sh_i2c_reset(base);
+
+	return 0;
+}
+
+static u8 i2c_raw_read(struct sh_i2c *base, u8 id, u8 reg)
+{
+	u8 ret = 0;
+
+	if (i2c_set_addr(base, id, reg)) {
+		printf("Fail set slave address\n");
+		goto fail;
+	}
+
+	clrsetbits_8(&base->iccr2, SH_I2C_ICCR2_SCP, SH_I2C_ICCR2_BBSY);
+
+	writeb(id << 1 | 1, &base->icdrt);
+
+	if (check_tend(base, 0))
+		printf("TDRE check fail...\n");
+
+	clrsetbits_8(&base->iccr2, SH_I2C_ICCR1_TRS, SH_I2C_ICCR1_MST);
+
+	clrbits_8(&base->icsr, SH_I2C_ICSR_TDRE);
+
+	setbits_8(&base->icier, SH_I2C_ICIER_ACKBT);
+	setbits_8(&base->iccr1, SH_I2C_ICCR1_RCVD);
+
+	/* read data (dummy) */
+	ret = readb(&base->icdrr);
+
+	if (check_rdrf(base)) {
+		printf("check RDRF error\n");
+		goto fail;
+	}
+
+	clrbits_8(&base->icsr, SH_I2C_ICSR_STOP);
+
+	udelay(1000);
+
+	sh_i2c_send_stop(base);
+
+	if (check_stop(base)) {
+		printf("check STOP error\n");
+		goto fail;
+	}
+
+	clrbits_8(&base->iccr1, SH_I2C_ICCR1_MTRS);
+	clrbits_8(&base->icsr, SH_I2C_ICSR_TDRE);
+
+	/* data read */
+	ret = readb(&base->icdrr);
+
+fail:
+	clrbits_8(&base->iccr1, SH_I2C_ICCR1_RCVD);
+
+	return ret;
+}
+
+#ifdef CONFIG_I2C_MULTI_BUS
+static unsigned int current_bus;
+
+/*
+ * i2c_set_bus_num - change active I2C bus
+ *	@bus: bus index, zero based
+ *	@returns: 0 on success, non-0 on failure
+ */
+int i2c_set_bus_num(unsigned int bus)
+{
+	if ((bus < 0) || (bus >= CONFIG_SYS_MAX_I2C_BUS)) {
+		printf("Bad bus: %d\n", bus);
+		return -1;
+	}
+
+	switch (bus) {
+	case 0:
+		base = (void *)CONFIG_SH_I2C_BASE0;
+		break;
+	case 1:
+		base = (void *)CONFIG_SH_I2C_BASE1;
+		break;
+	default:
+		return -1;
+	}
+	current_bus = bus;
+
+	return 0;
+}
+
+/*
+ * i2c_get_bus_num - returns index of active I2C bus
+ */
+unsigned int i2c_get_bus_num(void)
+{
+	return current_bus;
+}
+#endif
+
+void i2c_init(int speed, int slaveaddr)
+{
+	int num, denom, tmp;
+
+#ifdef CONFIG_I2C_MULTI_BUS
+	current_bus = 0;
+#endif
+	base = (struct sh_i2c *)CONFIG_SH_I2C_BASE0;
+
+	if (speed == 400000)
+		iccr1_cks = 0x07;
+	else
+		iccr1_cks = 0x0F;
+
+	nf2cyc = 1;
+
+	/* Reset */
+	sh_i2c_reset(base);
+
+	/* ICE enable and set clock */
+	writeb(SH_I2C_ICCR1_ICE | iccr1_cks, &base->iccr1);
+	writeb(nf2cyc, &base->nf2cyc);
+}
+
+/*
+ * i2c_read: - Read multiple bytes from an i2c device
+ *
+ * The higher level routines take into account that this function is only
+ * called with len < page length of the device (see configuration file)
+ *
+ * @chip:   address of the chip which is to be read
+ * @addr:   i2c data address within the chip
+ * @alen:   length of the i2c data address (1..2 bytes)
+ * @buffer: where to write the data
+ * @len:    how much byte do we want to read
+ * @return: 0 in case of success
+ */
+int i2c_read(u8 chip, u32 addr, int alen, u8 *buffer, int len)
+{
+	int i = 0;
+
+	for (i = 0 ; i < len ; i++)
+		buffer[i] = i2c_raw_read(base, chip, addr + i);
+
+	return 0;
+}
+
+/*
+ * i2c_write: -  Write multiple bytes to an i2c device
+ *
+ * The higher level routines take into account that this function is only
+ * called with len < page length of the device (see configuration file)
+ *
+ * @chip:   address of the chip which is to be written
+ * @addr:   i2c data address within the chip
+ * @alen:   length of the i2c data address (1..2 bytes)
+ * @buffer: where to find the data to be written
+ * @len:    how much byte do we want to read
+ * @return: 0 in case of success
+ */
+int i2c_write(u8 chip, u32 addr, int alen, u8 *buffer, int len)
+{
+	int ret;
+
+	ret = i2c_raw_write(base, chip, addr, buffer, len);
+
+	return 0;
+}
+
+/*
+ * i2c_probe: - Test if a chip answers for a given i2c address
+ *
+ * @chip:   address of the chip which is searched for
+ * @return: 0 if a chip was found, -1 otherwhise
+ */
+int i2c_probe(u8 chip)
+{
+	return 0;
+}
-- 
1.7.7.3

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

* [U-Boot] [PATCH] sh: i2c: Add support I2C controller of SH7734
  2012-02-22  1:13 [U-Boot] [PATCH] sh: i2c: Add support I2C controller of SH7734 Nobuhiro Iwamatsu
@ 2012-02-22  4:25 ` Mike Frysinger
  2012-02-22 13:53   ` Marek Vasut
  2012-03-01  2:44   ` Nobuhiro Iwamatsu
  0 siblings, 2 replies; 11+ messages in thread
From: Mike Frysinger @ 2012-02-22  4:25 UTC (permalink / raw)
  To: u-boot

On Tuesday 21 February 2012 20:13:47 Nobuhiro Iwamatsu wrote:
> --- /dev/null
> +++ b/drivers/i2c/sh_sh7734_i2c.c
>
> +#if DEBUG
> +static void sh_i2c_dump_reg(struct sh_i2c *base)
> +{
> +	printf("iccr1 : %02X\n", readb(&base->iccr1));
> +	printf("iccr2 : %02X\n", readb(&base->iccr2));
> +	printf("icmr  : %02X\n", readb(&base->icmr));
> +	printf("icier : %02X\n", readb(&base->icier));
> +	printf("icsr  : %02X\n", readb(&base->icsr));
> +	printf("sar   : %02X\n", readb(&base->sar));
> +	printf("icdrt : %02X\n", readb(&base->icdrt));
> +	printf("icdrr : %02X\n", readb(&base->icdrr));
> +	printf("nf2cyc: %02X\n", readb(&base->nf2cyc));
> +}
> +#endif

if you used debug(), you wouldn't need the DEBUG check

> +static int
> +i2c_raw_write(struct sh_i2c *base, u8 id, u8 reg, u8 *val, int size)
> +{
> +	int i;
> +	u8 data;
> +
> +	if (i2c_set_addr(base, id, reg)) {
> +		printf("Fail set slave address\n");

should use puts() when there's no fmt

> +	for (i = 0 ; i < size ; i++) {

no space before the semi-colon

> +int i2c_set_bus_num(unsigned int bus)
> +{
> +	if ((bus < 0) || (bus >= CONFIG_SYS_MAX_I2C_BUS)) {
> +		printf("Bad bus: %d\n", bus);
> +		return -1;
> +	}
> +
> +	switch (bus) {
> +	case 0:
> +		base = (void *)CONFIG_SH_I2C_BASE0;
> +		break;
> +	case 1:
> +		base = (void *)CONFIG_SH_I2C_BASE1;
> +		break;
> +	default:
> +		return -1;
> +	}

do you need the if() check if you have default here ?
-mike
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: This is a digitally signed message part.
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20120221/eafc816a/attachment.pgp>

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

* [U-Boot] [PATCH] sh: i2c: Add support I2C controller of SH7734
  2012-02-22  4:25 ` Mike Frysinger
@ 2012-02-22 13:53   ` Marek Vasut
  2012-02-22 16:38     ` Mike Frysinger
  2012-03-01  2:44   ` Nobuhiro Iwamatsu
  1 sibling, 1 reply; 11+ messages in thread
From: Marek Vasut @ 2012-02-22 13:53 UTC (permalink / raw)
  To: u-boot

> On Tuesday 21 February 2012 20:13:47 Nobuhiro Iwamatsu wrote:
> > --- /dev/null
> > +++ b/drivers/i2c/sh_sh7734_i2c.c
> > 
> > +#if DEBUG
> > +static void sh_i2c_dump_reg(struct sh_i2c *base)
> > +{
> > +	printf("iccr1 : %02X\n", readb(&base->iccr1));
> > +	printf("iccr2 : %02X\n", readb(&base->iccr2));
> > +	printf("icmr  : %02X\n", readb(&base->icmr));
> > +	printf("icier : %02X\n", readb(&base->icier));
> > +	printf("icsr  : %02X\n", readb(&base->icsr));
> > +	printf("sar   : %02X\n", readb(&base->sar));
> > +	printf("icdrt : %02X\n", readb(&base->icdrt));
> > +	printf("icdrr : %02X\n", readb(&base->icdrr));
> > +	printf("nf2cyc: %02X\n", readb(&base->nf2cyc));
> > +}
> > +#endif
> 
> if you used debug(), you wouldn't need the DEBUG check

But this puts lower amount of strain on the CPP. It doesn't have to check if 
DEBUG is defined 10 times, but only once ;-) Putting this into one big debug() 
call is also possible btw., though I don't like it.

> 
> > +static int
> > +i2c_raw_write(struct sh_i2c *base, u8 id, u8 reg, u8 *val, int size)
> > +{
> > +	int i;
> > +	u8 data;
> > +
> > +	if (i2c_set_addr(base, id, reg)) {
> > +		printf("Fail set slave address\n");
> 
> should use puts() when there's no fmt
> 
> > +	for (i = 0 ; i < size ; i++) {
> 
> no space before the semi-colon
> 
> > +int i2c_set_bus_num(unsigned int bus)
> > +{
> > +	if ((bus < 0) || (bus >= CONFIG_SYS_MAX_I2C_BUS)) {
> > +		printf("Bad bus: %d\n", bus);
> > +		return -1;
> > +	}
> > +
> > +	switch (bus) {
> > +	case 0:
> > +		base = (void *)CONFIG_SH_I2C_BASE0;
> > +		break;
> > +	case 1:
> > +		base = (void *)CONFIG_SH_I2C_BASE1;
> > +		break;
> > +	default:
> > +		return -1;
> > +	}
> 
> do you need the if() check if you have default here ?

CONFIG_SYS_MAX_I2C_BUS may be different in some obscure case?

M

> -mike

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

* [U-Boot] [PATCH] sh: i2c: Add support I2C controller of SH7734
  2012-02-22 13:53   ` Marek Vasut
@ 2012-02-22 16:38     ` Mike Frysinger
  0 siblings, 0 replies; 11+ messages in thread
From: Mike Frysinger @ 2012-02-22 16:38 UTC (permalink / raw)
  To: u-boot

On Wednesday 22 February 2012 08:53:50 Marek Vasut wrote:
> > On Tuesday 21 February 2012 20:13:47 Nobuhiro Iwamatsu wrote:
> > > --- /dev/null
> > > +++ b/drivers/i2c/sh_sh7734_i2c.c
> > > 
> > > +#if DEBUG
> > > +static void sh_i2c_dump_reg(struct sh_i2c *base)
> > > +{
> > > +	printf("iccr1 : %02X\n", readb(&base->iccr1));
> > > +	printf("iccr2 : %02X\n", readb(&base->iccr2));
> > > +	printf("icmr  : %02X\n", readb(&base->icmr));
> > > +	printf("icier : %02X\n", readb(&base->icier));
> > > +	printf("icsr  : %02X\n", readb(&base->icsr));
> > > +	printf("sar   : %02X\n", readb(&base->sar));
> > > +	printf("icdrt : %02X\n", readb(&base->icdrt));
> > > +	printf("icdrr : %02X\n", readb(&base->icdrr));
> > > +	printf("nf2cyc: %02X\n", readb(&base->nf2cyc));
> > > +}
> > > +#endif
> > 
> > if you used debug(), you wouldn't need the DEBUG check
> 
> But this puts lower amount of strain on the CPP. It doesn't have to check
> if DEBUG is defined 10 times, but only once ;-) Putting this into one big
> debug() call is also possible btw., though I don't like it.

assuming you're not joking, i'm fairly certain that's now how the CPP engine 
works.  we want to minimize ifdef's and let the compiler to code checking as 
much as possible and do DCE on unused stuff.

> > > +int i2c_set_bus_num(unsigned int bus)
> > > +{
> > > +	if ((bus < 0) || (bus >= CONFIG_SYS_MAX_I2C_BUS)) {
> > > +		printf("Bad bus: %d\n", bus);
> > > +		return -1;
> > > +	}
> > > +
> > > +	switch (bus) {
> > > +	case 0:
> > > +		base = (void *)CONFIG_SH_I2C_BASE0;
> > > +		break;
> > > +	case 1:
> > > +		base = (void *)CONFIG_SH_I2C_BASE1;
> > > +		break;
> > > +	default:
> > > +		return -1;
> > > +	}
> > 
> > do you need the if() check if you have default here ?
> 
> CONFIG_SYS_MAX_I2C_BUS may be different in some obscure case?

unlikely, but you're right.  the code could still be unified though:
	if (bus >= CONFIG_SYS_MAX_I2C_BUS)
		goto case_bad_bus;
	switch (bus) {
	case 0:
		...
	case 1:
		...
	case_bad_bus:
	default:
		printf("...warning...");
		return -1;
	}
-mike
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: This is a digitally signed message part.
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20120222/c09d76af/attachment.pgp>

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

* [U-Boot] [PATCH] sh: i2c: Add support I2C controller of SH7734
  2012-02-22  4:25 ` Mike Frysinger
  2012-02-22 13:53   ` Marek Vasut
@ 2012-03-01  2:44   ` Nobuhiro Iwamatsu
  1 sibling, 0 replies; 11+ messages in thread
From: Nobuhiro Iwamatsu @ 2012-03-01  2:44 UTC (permalink / raw)
  To: u-boot

Hi, Mike.

Thank you for your review.

2012/2/22 Mike Frysinger <vapier@gentoo.org>:
> On Tuesday 21 February 2012 20:13:47 Nobuhiro Iwamatsu wrote:
>> --- /dev/null
>> +++ b/drivers/i2c/sh_sh7734_i2c.c
>>
>> +#if DEBUG
>> +static void sh_i2c_dump_reg(struct sh_i2c *base)
>> +{
>> + ? ? printf("iccr1 : %02X\n", readb(&base->iccr1));
>> + ? ? printf("iccr2 : %02X\n", readb(&base->iccr2));
>> + ? ? printf("icmr ?: %02X\n", readb(&base->icmr));
>> + ? ? printf("icier : %02X\n", readb(&base->icier));
>> + ? ? printf("icsr ?: %02X\n", readb(&base->icsr));
>> + ? ? printf("sar ? : %02X\n", readb(&base->sar));
>> + ? ? printf("icdrt : %02X\n", readb(&base->icdrt));
>> + ? ? printf("icdrr : %02X\n", readb(&base->icdrr));
>> + ? ? printf("nf2cyc: %02X\n", readb(&base->nf2cyc));
>> +}
>> +#endif
>
> if you used debug(), you wouldn't need the DEBUG check

OK, but sh_i2c_dump_reg function is not referred from anywhere, I remove.

>
>> +static int
>> +i2c_raw_write(struct sh_i2c *base, u8 id, u8 reg, u8 *val, int size)
>> +{
>> + ? ? int i;
>> + ? ? u8 data;
>> +
>> + ? ? if (i2c_set_addr(base, id, reg)) {
>> + ? ? ? ? ? ? printf("Fail set slave address\n");
>
> should use puts() when there's no fmt

OK.

>
>> + ? ? for (i = 0 ; i < size ; i++) {
>
> no space before the semi-colon
>
>> +int i2c_set_bus_num(unsigned int bus)
>> +{
>> + ? ? if ((bus < 0) || (bus >= CONFIG_SYS_MAX_I2C_BUS)) {
>> + ? ? ? ? ? ? printf("Bad bus: %d\n", bus);
>> + ? ? ? ? ? ? return -1;
>> + ? ? }
>> +
>> + ? ? switch (bus) {
>> + ? ? case 0:
>> + ? ? ? ? ? ? base = (void *)CONFIG_SH_I2C_BASE0;
>> + ? ? ? ? ? ? break;
>> + ? ? case 1:
>> + ? ? ? ? ? ? base = (void *)CONFIG_SH_I2C_BASE1;
>> + ? ? ? ? ? ? break;
>> + ? ? default:
>> + ? ? ? ? ? ? return -1;
>> + ? ? }
>
> do you need the if() check if you have default here ?

int i2c_set_bus_num(unsigned int bus)
{
    switch (bus) {
    case 0:
        base = (void *)CONFIG_SH_I2C_BASE0;
        break;
    case 1:
        base = (void *)CONFIG_SH_I2C_BASE1;
        break;
    default:
        printf("Bad bus: %d\n", bus);
        return -1;


Bestr regards,
  Nobuhiro
-- 
Nobuhiro Iwamatsu

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

* [U-Boot] [PATCH] sh: i2c: Add support I2C controller of SH7734
  2012-03-02  3:56 Nobuhiro Iwamatsu
  2012-03-02  4:37 ` Mike Frysinger
@ 2012-04-24  9:11 ` Heiko Schocher
  1 sibling, 0 replies; 11+ messages in thread
From: Heiko Schocher @ 2012-04-24  9:11 UTC (permalink / raw)
  To: u-boot

Hello Nobuhiro,

Nobuhiro Iwamatsu wrote:
> Renesas SH7734 has two I2C interfaceis.
> This supports these I2C.
> 
> V5: - include i2c.h.
>     - Add check of icsr bit polling logic.
> 	- Implement i2c_probe.
> V4: - Remove sh_i2c_dump_reg function.
>     - Use puts() when there's no format.
>     - Chnage check for I2C bus number.
>     - Remove space before the semi-colon.
> V3: - Fix error for whitespace.
> V2: - Changed bit control to use the clr|set|clrsetbits_* functions.
>     - Fix wrong comment style.
>     - Add new line before for loop in i2c_read.
> 
> Signed-off-by: Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com>
> Acked-by: Heiko Schocher <hs@denx.de>
> Signed-off-by: Nobuhiro Iwamatsu <iwamatsu@nigauri.org>
> ---
>  drivers/i2c/Makefile        |    1 +
>  drivers/i2c/sh_sh7734_i2c.c |  387 +++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 388 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/i2c/sh_sh7734_i2c.c

Applied to u-boot-i2c.git

Thanks!

bye
Heiko
-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany

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

* [U-Boot] [PATCH] sh: i2c: Add support I2C controller of SH7734
  2012-03-02  3:56 Nobuhiro Iwamatsu
@ 2012-03-02  4:37 ` Mike Frysinger
  2012-04-24  9:11 ` Heiko Schocher
  1 sibling, 0 replies; 11+ messages in thread
From: Mike Frysinger @ 2012-03-02  4:37 UTC (permalink / raw)
  To: u-boot

Acked-by: Mike Frysinger <vapier@gentoo.org>
-mike
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: This is a digitally signed message part.
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20120301/7f45ebc4/attachment.pgp>

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

* [U-Boot] [PATCH] sh: i2c: Add support I2C controller of SH7734
@ 2012-03-02  3:56 Nobuhiro Iwamatsu
  2012-03-02  4:37 ` Mike Frysinger
  2012-04-24  9:11 ` Heiko Schocher
  0 siblings, 2 replies; 11+ messages in thread
From: Nobuhiro Iwamatsu @ 2012-03-02  3:56 UTC (permalink / raw)
  To: u-boot

Renesas SH7734 has two I2C interfaceis.
This supports these I2C.

V5: - include i2c.h.
    - Add check of icsr bit polling logic.
	- Implement i2c_probe.
V4: - Remove sh_i2c_dump_reg function.
    - Use puts() when there's no format.
    - Chnage check for I2C bus number.
    - Remove space before the semi-colon.
V3: - Fix error for whitespace.
V2: - Changed bit control to use the clr|set|clrsetbits_* functions.
    - Fix wrong comment style.
    - Add new line before for loop in i2c_read.

Signed-off-by: Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com>
Acked-by: Heiko Schocher <hs@denx.de>
Signed-off-by: Nobuhiro Iwamatsu <iwamatsu@nigauri.org>
---
 drivers/i2c/Makefile        |    1 +
 drivers/i2c/sh_sh7734_i2c.c |  387 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 388 insertions(+), 0 deletions(-)
 create mode 100644 drivers/i2c/sh_sh7734_i2c.c

diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile
index 504db03..506269d 100644
--- a/drivers/i2c/Makefile
+++ b/drivers/i2c/Makefile
@@ -44,6 +44,7 @@ COBJS-$(CONFIG_SPEAR_I2C) += spr_i2c.o
 COBJS-$(CONFIG_TSI108_I2C) += tsi108_i2c.o
 COBJS-$(CONFIG_U8500_I2C) += u8500_i2c.o
 COBJS-$(CONFIG_SH_I2C) += sh_i2c.o
+COBJS-$(CONFIG_SH_SH7734_I2C) += sh_sh7734_i2c.o
 
 COBJS	:= $(COBJS-y)
 SRCS	:= $(COBJS:.o=.c)
diff --git a/drivers/i2c/sh_sh7734_i2c.c b/drivers/i2c/sh_sh7734_i2c.c
new file mode 100644
index 0000000..9da173d
--- /dev/null
+++ b/drivers/i2c/sh_sh7734_i2c.c
@@ -0,0 +1,387 @@
+/*
+ * Copyright (C) 2012 Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com>
+ * Copyright (C) 2012 Renesas Solutions Corp.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <i2c.h>
+#include <asm/io.h>
+
+struct sh_i2c {
+	u8 iccr1;
+	u8 iccr2;
+	u8 icmr;
+	u8 icier;
+	u8 icsr;
+	u8 sar;
+	u8 icdrt;
+	u8 icdrr;
+	u8 nf2cyc;
+	u8 __pad0;
+	u8 __pad1;
+};
+
+static struct sh_i2c *base;
+static u8 iccr1_cks, nf2cyc;
+
+/* ICCR1 */
+#define SH_I2C_ICCR1_ICE	(1 << 7)
+#define SH_I2C_ICCR1_RCVD	(1 << 6)
+#define SH_I2C_ICCR1_MST	(1 << 5)
+#define SH_I2C_ICCR1_TRS	(1 << 4)
+#define SH_I2C_ICCR1_MTRS	\
+	(SH_I2C_ICCR1_MST | SH_I2C_ICCR1_TRS)
+
+/* ICCR1 */
+#define SH_I2C_ICCR2_BBSY	(1 << 7)
+#define SH_I2C_ICCR2_SCP	(1 << 6)
+#define SH_I2C_ICCR2_SDAO	(1 << 5)
+#define SH_I2C_ICCR2_SDAOP	(1 << 4)
+#define SH_I2C_ICCR2_SCLO	(1 << 3)
+#define SH_I2C_ICCR2_IICRST	(1 << 1)
+
+#define SH_I2C_ICIER_TIE	(1 << 7)
+#define SH_I2C_ICIER_TEIE	(1 << 6)
+#define SH_I2C_ICIER_RIE	(1 << 5)
+#define SH_I2C_ICIER_NAKIE	(1 << 4)
+#define SH_I2C_ICIER_STIE	(1 << 3)
+#define SH_I2C_ICIER_ACKE	(1 << 2)
+#define SH_I2C_ICIER_ACKBR	(1 << 1)
+#define SH_I2C_ICIER_ACKBT	(1 << 0)
+
+#define SH_I2C_ICSR_TDRE	(1 << 7)
+#define SH_I2C_ICSR_TEND	(1 << 6)
+#define SH_I2C_ICSR_RDRF	(1 << 5)
+#define SH_I2C_ICSR_NACKF	(1 << 4)
+#define SH_I2C_ICSR_STOP	(1 << 3)
+#define SH_I2C_ICSR_ALOVE	(1 << 2)
+#define SH_I2C_ICSR_AAS		(1 << 1)
+#define SH_I2C_ICSR_ADZ		(1 << 0)
+
+#define IRQ_WAIT 1000
+
+static void sh_i2c_send_stop(struct sh_i2c *base)
+{
+	clrbits_8(&base->iccr2, SH_I2C_ICCR2_BBSY | SH_I2C_ICCR2_SCP);
+}
+
+static int check_icsr_bits(struct sh_i2c *base, u8 bits)
+{
+	int i;
+
+	for (i = 0; i < IRQ_WAIT; i++) {
+		if (bits & readb(&base->icsr))
+			return 0;
+		udelay(10);
+	}
+
+	return 1;
+}
+
+static int check_stop(struct sh_i2c *base)
+{
+	int ret = check_icsr_bits(base, SH_I2C_ICSR_STOP);
+	clrbits_8(&base->icsr, SH_I2C_ICSR_STOP);
+
+	return ret;
+}
+
+static int check_tend(struct sh_i2c *base, int stop)
+{
+	int ret = check_icsr_bits(base, SH_I2C_ICSR_TEND);
+
+	if (stop) {
+		clrbits_8(&base->icsr, SH_I2C_ICSR_STOP);
+		sh_i2c_send_stop(base);
+	}
+
+	clrbits_8(&base->icsr, SH_I2C_ICSR_TEND);
+	return ret;
+}
+
+static int check_tdre(struct sh_i2c *base)
+{
+	return check_icsr_bits(base, SH_I2C_ICSR_TDRE);
+}
+
+static int check_rdrf(struct sh_i2c *base)
+{
+	return check_icsr_bits(base, SH_I2C_ICSR_RDRF);
+}
+
+static int check_bbsy(struct sh_i2c *base)
+{
+	int i;
+
+	for (i = 0 ; i < IRQ_WAIT ; i++) {
+		if (!(SH_I2C_ICCR2_BBSY & readb(&base->iccr2)))
+			return 0;
+		udelay(10);
+	}
+	return 1;
+}
+
+static int check_ackbr(struct sh_i2c *base)
+{
+	int i;
+
+	for (i = 0 ; i < IRQ_WAIT ; i++) {
+		if (!(SH_I2C_ICIER_ACKBR & readb(&base->icier)))
+			return 0;
+		udelay(10);
+	}
+
+	return 1;
+}
+
+static void sh_i2c_reset(struct sh_i2c *base)
+{
+	setbits_8(&base->iccr2, SH_I2C_ICCR2_IICRST);
+
+	udelay(100);
+
+	clrbits_8(&base->iccr2, SH_I2C_ICCR2_IICRST);
+}
+
+static int i2c_set_addr(struct sh_i2c *base, u8 id, u8 reg)
+{
+	if (check_bbsy(base)) {
+		puts("i2c bus busy\n");
+		goto fail;
+	}
+
+	setbits_8(&base->iccr1, SH_I2C_ICCR1_MTRS);
+	clrsetbits_8(&base->iccr2, SH_I2C_ICCR2_SCP, SH_I2C_ICCR2_BBSY);
+
+	writeb((id << 1), &base->icdrt);
+
+	if (check_tend(base, 0)) {
+		puts("TEND check fail...\n");
+		goto fail;
+	}
+
+	if (check_ackbr(base)) {
+		check_tend(base, 0);
+		sh_i2c_send_stop(base);
+		goto fail;
+	}
+
+	writeb(reg, &base->icdrt);
+
+	if (check_tdre(base)) {
+		puts("TDRE check fail...\n");
+		goto fail;
+	}
+
+	if (check_tend(base, 0)) {
+		puts("TEND check fail...\n");
+		goto fail;
+	}
+
+	return 0;
+fail:
+
+	return 1;
+}
+
+static int
+i2c_raw_write(struct sh_i2c *base, u8 id, u8 reg, u8 *val, int size)
+{
+	int i;
+
+	if (i2c_set_addr(base, id, reg)) {
+		puts("Fail set slave address\n");
+		return 1;
+	}
+
+	for (i = 0; i < size; i++) {
+		writeb(val[i], &base->icdrt);
+		check_tdre(base);
+	}
+
+	check_tend(base, 1);
+	check_stop(base);
+
+	udelay(100);
+
+	clrbits_8(&base->iccr1, SH_I2C_ICCR1_MTRS);
+	clrbits_8(&base->icsr, SH_I2C_ICSR_TDRE);
+	sh_i2c_reset(base);
+
+	return 0;
+}
+
+static u8 i2c_raw_read(struct sh_i2c *base, u8 id, u8 reg)
+{
+	u8 ret = 0;
+
+	if (i2c_set_addr(base, id, reg)) {
+		puts("Fail set slave address\n");
+		goto fail;
+	}
+
+	clrsetbits_8(&base->iccr2, SH_I2C_ICCR2_SCP, SH_I2C_ICCR2_BBSY);
+	writeb((id << 1) | 1, &base->icdrt);
+
+	if (check_tend(base, 0))
+		puts("TDRE check fail...\n");
+
+	clrsetbits_8(&base->iccr1, SH_I2C_ICCR1_TRS, SH_I2C_ICCR1_MST);
+	clrbits_8(&base->icsr, SH_I2C_ICSR_TDRE);
+	setbits_8(&base->icier, SH_I2C_ICIER_ACKBT);
+	setbits_8(&base->iccr1, SH_I2C_ICCR1_RCVD);
+
+	/* read data (dummy) */
+	ret = readb(&base->icdrr);
+
+	if (check_rdrf(base)) {
+		puts("check RDRF error\n");
+		goto fail;
+	}
+
+	clrbits_8(&base->icsr, SH_I2C_ICSR_STOP);
+	udelay(1000);
+
+	sh_i2c_send_stop(base);
+
+	if (check_stop(base)) {
+		puts("check STOP error\n");
+		goto fail;
+	}
+
+	clrbits_8(&base->iccr1, SH_I2C_ICCR1_MTRS);
+	clrbits_8(&base->icsr, SH_I2C_ICSR_TDRE);
+
+	/* data read */
+	ret = readb(&base->icdrr);
+
+fail:
+	clrbits_8(&base->iccr1, SH_I2C_ICCR1_RCVD);
+
+	return ret;
+}
+
+#ifdef CONFIG_I2C_MULTI_BUS
+static unsigned int current_bus;
+
+/**
+ * i2c_set_bus_num - change active I2C bus
+ *	@bus: bus index, zero based
+ *	@returns: 0 on success, non-0 on failure
+ */
+int i2c_set_bus_num(unsigned int bus)
+{
+	switch (bus) {
+	case 0:
+		base = (void *)CONFIG_SH_I2C_BASE0;
+		break;
+	case 1:
+		base = (void *)CONFIG_SH_I2C_BASE1;
+		break;
+	default:
+		printf("Bad bus: %d\n", bus);
+		return -1;
+	}
+
+	current_bus = bus;
+
+	return 0;
+}
+
+/**
+ * i2c_get_bus_num - returns index of active I2C bus
+ */
+unsigned int i2c_get_bus_num(void)
+{
+	return current_bus;
+}
+#endif
+
+void i2c_init(int speed, int slaveaddr)
+{
+#ifdef CONFIG_I2C_MULTI_BUS
+	current_bus = 0;
+#endif
+	base = (struct sh_i2c *)CONFIG_SH_I2C_BASE0;
+
+	if (speed == 400000)
+		iccr1_cks = 0x07;
+	else
+		iccr1_cks = 0x0F;
+
+	nf2cyc = 1;
+
+	/* Reset */
+	sh_i2c_reset(base);
+
+	/* ICE enable and set clock */
+	writeb(SH_I2C_ICCR1_ICE | iccr1_cks, &base->iccr1);
+	writeb(nf2cyc, &base->nf2cyc);
+}
+
+/*
+ * i2c_read: - Read multiple bytes from an i2c device
+ *
+ * The higher level routines take into account that this function is only
+ * called with len < page length of the device (see configuration file)
+ *
+ * @chip:   address of the chip which is to be read
+ * @addr:   i2c data address within the chip
+ * @alen:   length of the i2c data address (1..2 bytes)
+ * @buffer: where to write the data
+ * @len:    how much byte do we want to read
+ * @return: 0 in case of success
+ */
+int i2c_read(u8 chip, u32 addr, int alen, u8 *buffer, int len)
+{
+	int i = 0;
+	for (i = 0; i < len; i++)
+		buffer[i] = i2c_raw_read(base, chip, addr + i);
+
+	return 0;
+}
+
+/*
+ * i2c_write: -  Write multiple bytes to an i2c device
+ *
+ * The higher level routines take into account that this function is only
+ * called with len < page length of the device (see configuration file)
+ *
+ * @chip:   address of the chip which is to be written
+ * @addr:   i2c data address within the chip
+ * @alen:   length of the i2c data address (1..2 bytes)
+ * @buffer: where to find the data to be written
+ * @len:    how much byte do we want to read
+ * @return: 0 in case of success
+ */
+int i2c_write(u8 chip, u32 addr, int alen, u8 *buffer, int len)
+{
+	return i2c_raw_write(base, chip, addr, buffer, len);
+}
+
+/*
+ * i2c_probe: - Test if a chip answers for a given i2c address
+ *
+ * @chip:   address of the chip which is searched for
+ * @return: 0 if a chip was found, -1 otherwhise
+ */
+int i2c_probe(u8 chip)
+{
+	u8 byte;
+	return i2c_read(chip, 0, 0, &byte, 1);
+}
-- 
1.7.9.1

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

* [U-Boot] [PATCH] sh: i2c: Add support I2C controller of SH7734
  2012-02-06  6:52 ` Heiko Schocher
@ 2012-02-15  7:33   ` Nobuhiro Iwamatsu
  0 siblings, 0 replies; 11+ messages in thread
From: Nobuhiro Iwamatsu @ 2012-02-15  7:33 UTC (permalink / raw)
  To: u-boot

Hi,

Thanks for your comment.

2012/2/6 Heiko Schocher <hs@denx.de>:
> Hello Nobuhiro,
>
> Nobuhiro Iwamatsu wrote:
>> Renesas SH7734 has two I2C interfaceis.
>> This supports these I2C.
>>
>> Signed-off-by: Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com>
>> ---
>> ?drivers/i2c/Makefile ? ? ? ?| ? ?1 +
>> ?drivers/i2c/sh_sh7734_i2c.c | ?468 +++++++++++++++++++++++++++++++++++++++++++
>> ?2 files changed, 469 insertions(+), 0 deletions(-)
>> ?create mode 100644 drivers/i2c/sh_sh7734_i2c.c
>
> [...]
>> diff --git a/drivers/i2c/sh_sh7734_i2c.c b/drivers/i2c/sh_sh7734_i2c.c
>> new file mode 100644
>> index 0000000..6c514b4
>> --- /dev/null
>> +++ b/drivers/i2c/sh_sh7734_i2c.c
>> @@ -0,0 +1,468 @@
>
> [...]
>> +static void sh_i2c_send_stop(struct sh_i2c *base)
>> +{
>> + ? ? writeb(readb(&base->iccr2) & ~(SH_I2C_ICCR2_BBSY | SH_I2C_ICCR2_SCP),
>> + ? ? ? ? ? ? &base->iccr2);
>
> Please use clrbits_*

OK, but clrbits_* functions is not implement to SuperH and other.
I will implement these functions to SuperH.

>
> [...]
>> +static int check_tend(struct sh_i2c *base, int stop)
>> +{
>> + ? ? int i, ret = 1;
>> +
>> + ? ? for (i = 0 ; i < IRQ_WAIT ; i++) {
>> + ? ? ? ? ? ? if (SH_I2C_ICSR_TEND & readb(&base->icsr)) {
>> + ? ? ? ? ? ? ? ? ? ? ret = 0;
>> + ? ? ? ? ? ? ? ? ? ? break;
>> + ? ? ? ? ? ? }
>> + ? ? ? ? ? ? udelay(10);
>> + ? ? }
>> +
>> + ? ? if (stop) {
>> + ? ? ? ? ? ? u8 data;
>> +
>> + ? ? ? ? ? ? writeb(readb(&base->icsr) & ~SH_I2C_ICSR_STOP, &base->icsr);
>> +
>> + ? ? ? ? ? ? sh_i2c_send_stop(base);
>> + ? ? }
>> +
>> + ? ? writeb(readb(&base->icsr) & ~SH_I2C_ICSR_TEND, &base->icsr);
>
> here too... please check globally.

OK. I will changed from writeb to clr|set|clrsetbits_*.

>
> [...]
>> +#ifdef CONFIG_I2C_MULTI_BUS
>> +static unsigned int current_bus;
>> +
>> +/**
>
> wrong comment style.
>

OK.
> [...]
>> +/**
>
> here too.

OK.
>
>> + * i2c_get_bus_num - returns index of active I2C bus
>> + */
>> +unsigned int i2c_get_bus_num(void)
> [...]
>> +int i2c_read(u8 chip, u32 addr, int alen, u8 *buffer, int len)
>> +{
>> + ? ? int i = 0;
>
> new line please.
>

OK.

>> + ? ? for (i = 0 ; i < len ; i++)
>> + ? ? ? ? ? ? buffer[i] = i2c_raw_read(base, chip, addr + i);
> [...]
>
> Beside of this minor comments patch looks good, thanks!
>

Thanks!

Nobuhiro
-- 
Nobuhiro Iwamatsu

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

* [U-Boot] [PATCH] sh: i2c: Add support I2C controller of SH7734
  2012-02-03  7:33 Nobuhiro Iwamatsu
@ 2012-02-06  6:52 ` Heiko Schocher
  2012-02-15  7:33   ` Nobuhiro Iwamatsu
  0 siblings, 1 reply; 11+ messages in thread
From: Heiko Schocher @ 2012-02-06  6:52 UTC (permalink / raw)
  To: u-boot

Hello Nobuhiro,

Nobuhiro Iwamatsu wrote:
> Renesas SH7734 has two I2C interfaceis.
> This supports these I2C.
> 
> Signed-off-by: Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com>
> ---
>  drivers/i2c/Makefile        |    1 +
>  drivers/i2c/sh_sh7734_i2c.c |  468 +++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 469 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/i2c/sh_sh7734_i2c.c

[...]
> diff --git a/drivers/i2c/sh_sh7734_i2c.c b/drivers/i2c/sh_sh7734_i2c.c
> new file mode 100644
> index 0000000..6c514b4
> --- /dev/null
> +++ b/drivers/i2c/sh_sh7734_i2c.c
> @@ -0,0 +1,468 @@

[...]
> +static void sh_i2c_send_stop(struct sh_i2c *base)
> +{
> +	writeb(readb(&base->iccr2) & ~(SH_I2C_ICCR2_BBSY | SH_I2C_ICCR2_SCP),
> +		&base->iccr2);

Please use clrbits_*

[...]
> +static int check_tend(struct sh_i2c *base, int stop)
> +{
> +	int i, ret = 1;
> +
> +	for (i = 0 ; i < IRQ_WAIT ; i++) {
> +		if (SH_I2C_ICSR_TEND & readb(&base->icsr)) {
> +			ret = 0;
> +			break;
> +		}
> +		udelay(10);
> +	}
> +
> +	if (stop) {
> +		u8 data;
> +
> +		writeb(readb(&base->icsr) & ~SH_I2C_ICSR_STOP, &base->icsr);
> +
> +		sh_i2c_send_stop(base);
> +	}
> +
> +	writeb(readb(&base->icsr) & ~SH_I2C_ICSR_TEND, &base->icsr);

here too... please check globally.

[...]
> +#ifdef CONFIG_I2C_MULTI_BUS
> +static unsigned int current_bus;
> +
> +/**

wrong comment style.

[...]
> +/**

here too.

> + * i2c_get_bus_num - returns index of active I2C bus
> + */
> +unsigned int i2c_get_bus_num(void)
[...]
> +int i2c_read(u8 chip, u32 addr, int alen, u8 *buffer, int len)
> +{
> +	int i = 0;

new line please.

> +	for (i = 0 ; i < len ; i++)
> +		buffer[i] = i2c_raw_read(base, chip, addr + i);
[...]

Beside of this minor comments patch looks good, thanks!

bye,
Heiko
-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany

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

* [U-Boot] [PATCH] sh: i2c: Add support I2C controller of SH7734
@ 2012-02-03  7:33 Nobuhiro Iwamatsu
  2012-02-06  6:52 ` Heiko Schocher
  0 siblings, 1 reply; 11+ messages in thread
From: Nobuhiro Iwamatsu @ 2012-02-03  7:33 UTC (permalink / raw)
  To: u-boot

Renesas SH7734 has two I2C interfaceis.
This supports these I2C.

Signed-off-by: Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com>
---
 drivers/i2c/Makefile        |    1 +
 drivers/i2c/sh_sh7734_i2c.c |  468 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 469 insertions(+), 0 deletions(-)
 create mode 100644 drivers/i2c/sh_sh7734_i2c.c

diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile
index 504db03..506269d 100644
--- a/drivers/i2c/Makefile
+++ b/drivers/i2c/Makefile
@@ -44,6 +44,7 @@ COBJS-$(CONFIG_SPEAR_I2C) += spr_i2c.o
 COBJS-$(CONFIG_TSI108_I2C) += tsi108_i2c.o
 COBJS-$(CONFIG_U8500_I2C) += u8500_i2c.o
 COBJS-$(CONFIG_SH_I2C) += sh_i2c.o
+COBJS-$(CONFIG_SH_SH7734_I2C) += sh_sh7734_i2c.o
 
 COBJS	:= $(COBJS-y)
 SRCS	:= $(COBJS:.o=.c)
diff --git a/drivers/i2c/sh_sh7734_i2c.c b/drivers/i2c/sh_sh7734_i2c.c
new file mode 100644
index 0000000..6c514b4
--- /dev/null
+++ b/drivers/i2c/sh_sh7734_i2c.c
@@ -0,0 +1,468 @@
+/*
+ * Copyright (C) 2012 Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com>
+ * Copyright (C) 2012 Renesas Solutions Corp.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/io.h>
+
+struct sh_i2c {
+	u8 iccr1;
+	u8 iccr2;
+	u8 icmr;
+	u8 icier;
+	u8 icsr;
+	u8 sar;
+	u8 icdrt;
+	u8 icdrr;
+	u8 nf2cyc;
+	u8 __pad0;
+	u8 __pad1;
+};
+
+static struct sh_i2c *base;
+static u8 iccr1_cks, nf2cyc;
+
+/* ICCR1 */
+#define SH_I2C_ICCR1_ICE	(1 << 7)
+#define SH_I2C_ICCR1_RCVD	(1 << 6)
+#define SH_I2C_ICCR1_MST	(1 << 5)
+#define SH_I2C_ICCR1_TRS	(1 << 4)
+#define SH_I2C_ICCR1_MTRS	\
+	(SH_I2C_ICCR1_MST | SH_I2C_ICCR1_TRS)
+
+/* ICCR1 */
+#define SH_I2C_ICCR2_BBSY	(1 << 7)
+#define SH_I2C_ICCR2_SCP	(1 << 6)
+#define SH_I2C_ICCR2_SDAO	(1 << 5)
+#define SH_I2C_ICCR2_SDAOP	(1 << 4)
+#define SH_I2C_ICCR2_SCLO	(1 << 3)
+#define SH_I2C_ICCR2_IICRST	(1 << 1)
+
+#define SH_I2C_ICIER_TIE	(1 << 7)
+#define SH_I2C_ICIER_TEIE	(1 << 6)
+#define SH_I2C_ICIER_RIE	(1 << 5)
+#define SH_I2C_ICIER_NAKIE	(1 << 4)
+#define SH_I2C_ICIER_STIE	(1 << 3)
+#define SH_I2C_ICIER_ACKE	(1 << 2)
+#define SH_I2C_ICIER_ACKBR	(1 << 1)
+#define SH_I2C_ICIER_ACKBT	(1 << 0)
+
+#define SH_I2C_ICSR_TDRE	(1 << 7)
+#define SH_I2C_ICSR_TEND	(1 << 6)
+#define SH_I2C_ICSR_RDRF	(1 << 5)
+#define SH_I2C_ICSR_NACKF	(1 << 4)
+#define SH_I2C_ICSR_STOP	(1 << 3)
+#define SH_I2C_ICSR_ALOVE	(1 << 2)
+#define SH_I2C_ICSR_AAS		(1 << 1)
+#define SH_I2C_ICSR_ADZ		(1 << 0)
+
+#define IRQ_WAIT 1000
+
+
+static void sh_i2c_send_stop(struct sh_i2c *base)
+{
+	writeb(readb(&base->iccr2) & ~(SH_I2C_ICCR2_BBSY | SH_I2C_ICCR2_SCP),
+		&base->iccr2);
+}
+
+static int check_stop(struct sh_i2c *base)
+{
+	int i, ret = 1;
+
+	for (i = 0 ; i < IRQ_WAIT ; i++) {
+		if (SH_I2C_ICSR_STOP & readb(&base->icsr)) {
+			ret = 0;
+			break;
+		}
+		udelay(10);
+	}
+
+	writeb(readb(&base->icsr) & ~SH_I2C_ICSR_STOP, &base->icsr);
+
+	return ret;
+}
+
+static int check_tend(struct sh_i2c *base, int stop)
+{
+	int i, ret = 1;
+
+	for (i = 0 ; i < IRQ_WAIT ; i++) {
+		if (SH_I2C_ICSR_TEND & readb(&base->icsr)) {
+			ret = 0;
+			break;
+		}
+		udelay(10);
+	}
+
+	if (stop) {
+		u8 data;
+
+		writeb(readb(&base->icsr) & ~SH_I2C_ICSR_STOP, &base->icsr);
+
+		sh_i2c_send_stop(base);
+	}
+
+	writeb(readb(&base->icsr) & ~SH_I2C_ICSR_TEND, &base->icsr);
+
+	return ret;
+}
+
+static int check_tdre(struct sh_i2c *base)
+{
+	int i;
+
+	for (i = 0 ; i < IRQ_WAIT ; i++) {
+		if (SH_I2C_ICSR_TDRE & readb(&base->icsr))
+			return 0;
+		udelay(10);
+	}
+
+	return 1;
+}
+
+static int check_rdrf(struct sh_i2c *base)
+{
+	int i;
+
+	for (i = 0 ; i < IRQ_WAIT ; i++) {
+		if (SH_I2C_ICSR_RDRF & readb(&base->icsr))
+			return 0;
+		udelay(10);
+	}
+
+	return 1;
+}
+
+static int check_bbsy(struct sh_i2c *base)
+{
+	int i;
+
+	for (i = 0 ; i < IRQ_WAIT ; i++) {
+		if (!(SH_I2C_ICCR2_BBSY & readb(&base->iccr2)))
+			return 0;
+		udelay(10);
+	}
+	return 1;
+}
+
+static int check_ackbr(struct sh_i2c *base)
+{
+	int i;
+
+	for (i = 0 ; i < IRQ_WAIT ; i++) {
+		if (!(SH_I2C_ICIER_ACKBR & readb(&base->icier)))
+			return 0;
+		udelay(10);
+	}
+
+	return 1;
+}
+
+#if DEBUG
+static void sh_i2c_dump_reg(struct sh_i2c *base)
+{
+	printf("iccr1 : %02X\n", readb(&base->iccr1));
+	printf("iccr2 : %02X\n", readb(&base->iccr2));
+	printf("icmr  : %02X\n", readb(&base->icmr));
+	printf("icier : %02X\n", readb(&base->icier));
+	printf("icsr  : %02X\n", readb(&base->icsr));
+	printf("sar   : %02X\n", readb(&base->sar));
+	printf("icdrt : %02X\n", readb(&base->icdrt));
+	printf("icdrr : %02X\n", readb(&base->icdrr));
+	printf("nf2cyc: %02X\n", readb(&base->nf2cyc));
+}
+#endif
+
+static void sh_i2c_reset(struct sh_i2c *base)
+{
+	writeb(readb(&base->iccr2) | SH_I2C_ICCR2_IICRST,
+			&base->iccr2);
+
+	udelay(100);
+
+	writeb(readb(&base->iccr2) & ~SH_I2C_ICCR2_IICRST,
+			&base->iccr2);
+}
+
+static int i2c_set_addr(struct sh_i2c *base, u8 id, u8 reg)
+{
+	u8 data;
+
+	if (check_bbsy(base)) {
+		printf("i2c bus busy\n");
+		goto fail;
+	}
+
+	writeb(readb(&base->iccr1) | SH_I2C_ICCR1_MTRS,
+		&base->iccr1);
+
+	writeb((readb(&base->iccr2) | SH_I2C_ICCR2_BBSY) & ~SH_I2C_ICCR2_SCP,
+		&base->iccr2);
+
+	writeb(id << 1, &base->icdrt);
+
+	if (check_tend(base, 0)) {
+		printf("TEND check fail...\n");
+		goto fail;
+	}
+
+	if (check_ackbr(base)) {
+		check_tend(base, 0);
+		sh_i2c_send_stop(base);
+		goto fail;
+	}
+
+	writeb(reg, &base->icdrt);
+
+	if (check_tdre(base)) {
+		printf("TDRE check fail...\n");
+		goto fail;
+	}
+
+	if (check_tend(base, 0)) {
+		printf("TEND check fail...\n");
+		goto fail;
+	}
+
+	return 0;
+
+fail:
+
+	return 1;
+}
+
+static int
+i2c_raw_write(struct sh_i2c *base, u8 id, u8 reg, u8 *val, int size)
+{
+	int i;
+	u8 data;
+
+	if (i2c_set_addr(base, id, reg)) {
+		printf("Fail set slave address\n");
+		return 1;
+	}
+
+	for (i = 0 ; i < size ; i++) {
+		writeb(val[i], &base->icdrt);
+		check_tdre(base);
+	}
+
+	check_tend(base, 1);
+	check_stop(base);
+
+	udelay(100);
+
+	writeb(readb(&base->iccr1) & ~SH_I2C_ICCR1_MTRS,
+		&base->iccr1);
+
+	writeb(readb(&base->icsr) & ~SH_I2C_ICSR_TDRE,
+		&base->icsr);
+
+	sh_i2c_reset(base);
+
+	return 0;
+}
+
+static u8 i2c_raw_read(struct sh_i2c *base, u8 id, u8 reg)
+{
+	u8 ret = 0;
+
+	if (i2c_set_addr(base, id, reg)) {
+		printf("Fail set slave address\n");
+		goto fail;
+	}
+
+	writeb((readb(&base->iccr2) & ~SH_I2C_ICCR2_SCP) | SH_I2C_ICCR2_BBSY,
+		&base->iccr2);
+
+	writeb(id << 1 | 1, &base->icdrt);
+
+	if (check_tend(base, 0))
+		printf("TDRE check fail...\n");
+
+	writeb((readb(&base->iccr1) & ~SH_I2C_ICCR1_TRS) | SH_I2C_ICCR1_MST,
+		&base->iccr1);
+
+	writeb(readb(&base->icsr) & ~SH_I2C_ICSR_TDRE,
+		&base->icsr);
+
+	writeb(readb(&base->icier) | SH_I2C_ICIER_ACKBT,
+		&base->icier);
+
+	writeb(readb(&base->iccr1) | SH_I2C_ICCR1_RCVD,
+		&base->iccr1);
+
+	/* read data (dummy) */
+	ret = readb(&base->icdrr);
+
+	if (check_rdrf(base)) {
+		printf("check RDRF error\n");
+		goto fail;
+	}
+
+	writeb(readb(&base->icsr) & ~SH_I2C_ICSR_STOP,
+		&base->icsr);
+
+	udelay(1000);
+
+	sh_i2c_send_stop(base);
+
+	if (check_stop(base)) {
+		printf("check STOP error\n");
+		goto fail;
+	}
+
+	writeb(readb(&base->iccr1) & ~SH_I2C_ICCR1_MTRS,
+		&base->iccr1);
+
+	writeb(readb(&base->icsr) & ~SH_I2C_ICSR_TDRE,
+		&base->icsr);
+
+	/* data read */
+	ret = readb(&base->icdrr);
+
+fail:
+	writeb(readb(&base->iccr1) & ~SH_I2C_ICCR1_RCVD,
+		&base->iccr1);
+
+	return ret;
+}
+
+#ifdef CONFIG_I2C_MULTI_BUS
+static unsigned int current_bus;
+
+/**
+ * i2c_set_bus_num - change active I2C bus
+ *	@bus: bus index, zero based
+ *	@returns: 0 on success, non-0 on failure
+ */
+int i2c_set_bus_num(unsigned int bus)
+{
+	if ((bus < 0) || (bus >= CONFIG_SYS_MAX_I2C_BUS)) {
+		printf("Bad bus: %d\n", bus);
+		return -1;
+	}
+
+	switch (bus) {
+	case 0:
+		base = (void *)CONFIG_SH_I2C_BASE0;
+		break;
+	case 1:
+		base = (void *)CONFIG_SH_I2C_BASE1;
+		break;
+	default:
+		return -1;
+	}
+	current_bus = bus;
+
+	return 0;
+}
+
+/**
+ * i2c_get_bus_num - returns index of active I2C bus
+ */
+unsigned int i2c_get_bus_num(void)
+{
+	return current_bus;
+}
+#endif
+
+#define SH_I2C_ICCL_CALC(clk, date, t_low, t_high) \
+		((clk / rate) * (t_low / t_low + t_high))
+#define SH_I2C_ICCH_CALC(clk, date, t_low, t_high) \
+		((clk / rate) * (t_high / t_low + t_high))
+
+void i2c_init(int speed, int slaveaddr)
+{
+	int num, denom, tmp;
+
+#ifdef CONFIG_I2C_MULTI_BUS
+	current_bus = 0;
+#endif
+	base = (struct sh_i2c *)CONFIG_SH_I2C_BASE0;
+
+	if (speed == 400000)
+		iccr1_cks = 0x07;
+	else
+		iccr1_cks = 0x0F;
+
+	nf2cyc = 1;
+
+	/* Reset */
+	sh_i2c_reset(base);
+
+	/* ICE enable and set clock */
+	writeb(SH_I2C_ICCR1_ICE | iccr1_cks, &base->iccr1);
+	writeb(nf2cyc, &base->nf2cyc);
+}
+
+/*
+ * i2c_read: - Read multiple bytes from an i2c device
+ *
+ * The higher level routines take into account that this function is only
+ * called with len < page length of the device (see configuration file)
+ *
+ * @chip:   address of the chip which is to be read
+ * @addr:   i2c data address within the chip
+ * @alen:   length of the i2c data address (1..2 bytes)
+ * @buffer: where to write the data
+ * @len:    how much byte do we want to read
+ * @return: 0 in case of success
+ */
+int i2c_read(u8 chip, u32 addr, int alen, u8 *buffer, int len)
+{
+	int i = 0;
+	for (i = 0 ; i < len ; i++)
+		buffer[i] = i2c_raw_read(base, chip, addr + i);
+
+	return 0;
+}
+
+/*
+ * i2c_write: -  Write multiple bytes to an i2c device
+ *
+ * The higher level routines take into account that this function is only
+ * called with len < page length of the device (see configuration file)
+ *
+ * @chip:   address of the chip which is to be written
+ * @addr:   i2c data address within the chip
+ * @alen:   length of the i2c data address (1..2 bytes)
+ * @buffer: where to find the data to be written
+ * @len:    how much byte do we want to read
+ * @return: 0 in case of success
+ */
+int i2c_write(u8 chip, u32 addr, int alen, u8 *buffer, int len)
+{
+	int ret;
+
+	ret = i2c_raw_write(base, chip, addr, buffer, len);
+
+	return 0;
+}
+
+/*
+ * i2c_probe: - Test if a chip answers for a given i2c address
+ *
+ * @chip:   address of the chip which is searched for
+ * @return: 0 if a chip was found, -1 otherwhise
+ */
+int i2c_probe(u8 chip)
+{
+	return 0;
+}
-- 
1.7.7.3

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

end of thread, other threads:[~2012-04-24  9:11 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-02-22  1:13 [U-Boot] [PATCH] sh: i2c: Add support I2C controller of SH7734 Nobuhiro Iwamatsu
2012-02-22  4:25 ` Mike Frysinger
2012-02-22 13:53   ` Marek Vasut
2012-02-22 16:38     ` Mike Frysinger
2012-03-01  2:44   ` Nobuhiro Iwamatsu
  -- strict thread matches above, loose matches on Subject: below --
2012-03-02  3:56 Nobuhiro Iwamatsu
2012-03-02  4:37 ` Mike Frysinger
2012-04-24  9:11 ` Heiko Schocher
2012-02-03  7:33 Nobuhiro Iwamatsu
2012-02-06  6:52 ` Heiko Schocher
2012-02-15  7:33   ` Nobuhiro Iwamatsu

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.