Re: [PATCH] i2c:i2c-bfin-twi: TWI controller fails to restart next transfer in high system load.

2011-09-26 Thread Sonic Zhang
Ping.


Sonic Zhang

On Fri, Sep 23, 2011 at 2:25 PM, Sonic Zhang  wrote:
> From: Sonic Zhang 
>
> Current driver was developed based on BF537 0.2 HRM. In high system load, 
> BUFRDERR error
> interrupt may be raised if XMTSERV interrupt of last TX byte is not served in 
> time
> (set RSTART bit), which breaks restart tranfer as expected.
>
> "Buffer Read Error (BUFRDERR)" description in Blackfin HRM only applys to 
> BF537
> rev. < 0.3. In later rev. and later announced Blackfin chips, such as BF527 
> and
> BF548, a new TWI master feature "Clock Stretching" is added into the TWI 
> controller,
> BUFRDERR interrupt is not triggered after TX FIFO is empty.
>
> This patch sets RSTART bit at the beginning of the first transfer. The SCL 
> and SDA
> is hold till XMTSERV interrupt of last TX byte is served. Restart transfer is 
> not broken
> in high system load.
>
> Reported-by: Lukas Weiss 
> Signed-off-by: Sonic Zhang 
> ---
>  drivers/i2c/busses/i2c-bfin-twi.c |   42 +---
>  1 files changed, 24 insertions(+), 18 deletions(-)
>
> diff --git a/drivers/i2c/busses/i2c-bfin-twi.c 
> b/drivers/i2c/busses/i2c-bfin-twi.c
> index cbc98ae..5887ca4 100644
> --- a/drivers/i2c/busses/i2c-bfin-twi.c
> +++ b/drivers/i2c/busses/i2c-bfin-twi.c
> @@ -99,7 +99,7 @@ static void bfin_twi_handle_interrupt(struct bfin_twi_iface 
> *iface,
>                 */
>                else if (iface->cur_mode == TWI_I2C_MODE_COMBINED)
>                        write_MASTER_CTL(iface,
> -                               read_MASTER_CTL(iface) | MDIR | RSTART);
> +                               read_MASTER_CTL(iface) | MDIR);
>                else if (iface->manual_stop)
>                        write_MASTER_CTL(iface,
>                                read_MASTER_CTL(iface) | STOP);
> @@ -107,10 +107,10 @@ static void bfin_twi_handle_interrupt(struct 
> bfin_twi_iface *iface,
>                         iface->cur_msg + 1 < iface->msg_num) {
>                        if (iface->pmsg[iface->cur_msg + 1].flags & I2C_M_RD)
>                                write_MASTER_CTL(iface,
> -                                       read_MASTER_CTL(iface) | RSTART | 
> MDIR);
> +                                       read_MASTER_CTL(iface) | MDIR);
>                        else
>                                write_MASTER_CTL(iface,
> -                                       (read_MASTER_CTL(iface) | RSTART) & 
> ~MDIR);
> +                                       read_MASTER_CTL(iface) & ~MDIR);
>                }
>        }
>        if (twi_int_status & RCVSERV) {
> @@ -130,17 +130,20 @@ static void bfin_twi_handle_interrupt(struct 
> bfin_twi_iface *iface,
>                        }
>                        iface->transPtr++;
>                        iface->readNum--;
> -               } else if (iface->manual_stop) {
> -                       write_MASTER_CTL(iface,
> -                               read_MASTER_CTL(iface) | STOP);
> -               } else if (iface->cur_mode == TWI_I2C_MODE_REPEAT &&
> -                          iface->cur_msg + 1 < iface->msg_num) {
> -                       if (iface->pmsg[iface->cur_msg + 1].flags & I2C_M_RD)
> -                               write_MASTER_CTL(iface,
> -                                       read_MASTER_CTL(iface) | RSTART | 
> MDIR);
> -                       else
> +               }
> +               if (iface->readNum == 0) {
> +                       if (iface->manual_stop) {
>                                write_MASTER_CTL(iface,
> -                                       (read_MASTER_CTL(iface) | RSTART) & 
> ~MDIR);
> +                                       read_MASTER_CTL(iface) | STOP);
> +                       } else if (iface->cur_mode == TWI_I2C_MODE_REPEAT &&
> +                                  iface->cur_msg + 1 < iface->msg_num) {
> +                               if (iface->pmsg[iface->cur_msg + 1].flags & 
> I2C_M_RD)
> +                                       write_MASTER_CTL(iface,
> +                                               read_MASTER_CTL(iface) | 
> MDIR);
> +                               else
> +                                       write_MASTER_CTL(iface,
> +                                               read_MASTER_CTL(iface) & 
> ~MDIR);
> +                       }
>                }
>        }
>        if (twi_int_status & MERR) {
> @@ -252,9 +255,10 @@ static void bfin_twi_handle_interrupt(struct 
> bfin_twi_iface *iface,
>                                        (0xff << 6)));
>                                iface->manual_stop = 1;
>                        }
> -                       /* remove restart bit and enable master receive */
> -                       write_MASTER_CTL(iface,
> -                               read_MASTER_CTL(iface) & ~RSTART);
> +                       /* remove restart bit before last message */
> +                       if (iface->cur_msg+1 == iface->msg_num)
> +                               write_MASTER_CTL(ifa

Re: [PATCH 3/7] i2c-eg20t: delete 10bit access processing

2011-09-26 Thread Tomoya MORINAGA

(2011/09/23 2:49), Jeffrey (Sheng-Hui) Chu wrote:

The device is BCM20791.  Please contact Aaron Smith (aar...@broadcom.com) for 
evaluation.

Though googling the device, I can't find the device.
Broadcom website too.



By the way, the existing handling of 10-bit address in the patch you intended 
to delete does not work.  You'll need to fix that before you can test with the 
device successfully.

For the write operation, it's a easy fix:

@@ -410,25 +408,16 @@ static s32 pch_i2c_writebytes(struct i2c_adapter 
*i2c_adap,
}

if (msgs->flags&  I2C_M_TEN) {
-   addr_2_msb = ((addr&  I2C_MSB_2B_MSK)>>  7);
+   addr_2_msb = ((addr&  I2C_MSB_2B_MSK)>>  7)&  0x06;


For the read operation, static s32 pch_i2c_readbytes(), you'll need to do a 
write followed by a restart and a read...  please refer to the i2c spec...

Regards,


Thank you for your indication.
We will update this after supporting 10bit access.

Thanks,
tomoya
--
To unsubscribe from this list: send the line "unsubscribe linux-i2c" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [GIT PULL] I2C: OMAP: misc. cleanup for v3.2

2011-09-26 Thread Kevin Hilman

ping

On 09/06/2011 03:31 PM, Kevin Hilman wrote:

Hi Ben,

On 08/23/2011 05:10 PM, Kevin Hilman wrote:

Ben,

Here's one more I2C cleanup series for v3.2.

It applies on top of my for_3.2/i2c-fixes branch just submitted.

Please pull into your tree for linux-next.


I see you pulled the other two, can you pull this one as well?

Since master.kernel.org is still down, I pushed a (backup) copy of these
branches to my gitorious repo[1]. It should pull cleanly into what
you've already pulled since this branch is based on my for_3.2/i2c-fixes
which you've already pulled.

Thanks,

Kevin


[1] git://gitorious.org/khilman/linux-omap-pm.git
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majord...@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html


--
To unsubscribe from this list: send the line "unsubscribe linux-i2c" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 2/2 v3] i2c: i2c-riic: add dmaengine supporting

2011-09-26 Thread Yoshihiro Shimoda
We can use the dmaengine for the driver, if the dma_tx and/or
dma_rx in riic_platform_data is set. If we use it, we have to set
the irq number for EEI in the resource.

Signed-off-by: Yoshihiro Shimoda 
---
 about v3
  - adjust for the latest kernel (fix compile error)

 drivers/i2c/busses/i2c-riic.c |  290 +++--
 include/linux/i2c/riic.h  |4 +
 2 files changed, 251 insertions(+), 43 deletions(-)

diff --git a/drivers/i2c/busses/i2c-riic.c b/drivers/i2c/busses/i2c-riic.c
index 1e6639c..93e114c 100644
--- a/drivers/i2c/busses/i2c-riic.c
+++ b/drivers/i2c/busses/i2c-riic.c
@@ -31,6 +31,9 @@
 #include 
 #include 
 #include 
+#include 
+#include 
+#include 

 #define RIIC_ICCR1 0x00
 #define RIIC_ICCR2 0x01
@@ -166,6 +169,14 @@ struct riic_data {
void __iomem *reg;
struct i2c_adapter adap;
struct i2c_msg *msg;
+   int index;
+   unsigned char icsr2;
+
+   /* for DMAENGINE */
+   struct dma_chan *chan_tx;
+   struct dma_chan *chan_rx;
+   int dma_callbacked;
+   wait_queue_head_t wait;
 };

 #define DRIVER_VERSION "2011-09-21"
@@ -250,7 +261,8 @@ static int riic_init_setting(struct riic_data *pd, int 
clock)
return ret;

riic_set_bit(pd, ICCR1_ICE, RIIC_ICCR1);/* Enable RIIC */
-   riic_set_bit(pd, ICMR3_RDRFS | ICMR3_WAIT | ICMR3_ACKWP, RIIC_ICMR3);
+   riic_set_bit(pd, ICMR3_WAIT | ICMR3_ACKWP, RIIC_ICMR3);
+   riic_set_bit(pd, ICIER_TIE | ICIER_RIE, RIIC_ICIER);

return 0;
 }
@@ -312,10 +324,79 @@ static int riic_send_slave_address(struct riic_data *pd, 
int read)
return 0;
 }

+static void riic_dma_complete(void *arg)
+{
+   struct riic_data *pd = arg;
+
+   pd->dma_callbacked = 1;
+   wake_up(&pd->wait);
+}
+
+static int riic_master_transmit_pio(struct riic_data *pd)
+{
+   int index;
+   int ret = 0;
+
+   index = 0;
+   do {
+   ret = riic_wait_for_icsr2(pd, ICSR2_TDRE);
+   if (ret < 0)
+   return ret;
+
+   riic_write(pd, pd->msg->buf[index], RIIC_ICDRT);
+   index++;
+   } while (pd->msg->len > index);
+
+   return ret;
+}
+
+static int riic_master_transmit_dma(struct riic_data *pd)
+{
+   struct scatterlist sg;
+   unsigned char *buf = pd->msg->buf;
+   struct dma_async_tx_descriptor *desc;
+   int ret;
+
+   sg_init_table(&sg, 1);
+   sg_set_buf(&sg, buf, pd->msg->len);
+   sg_dma_len(&sg) = pd->msg->len;
+   dma_map_sg(pd->chan_tx->device->dev, &sg, 1, DMA_TO_DEVICE);
+
+   desc = pd->chan_tx->device->device_prep_slave_sg(pd->chan_tx,
+   &sg, 1, DMA_TO_DEVICE,
+   DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+   if (!desc)
+   return -EIO;
+
+   desc->callback = riic_dma_complete;
+   desc->callback_param = pd;
+   pd->dma_callbacked = 0;
+   ret = riic_wait_for_icsr2(pd, ICSR2_TDRE);
+   if (ret < 0)
+   return ret;
+   dmaengine_submit(desc);
+   dma_async_issue_pending(pd->chan_tx);
+
+   pd->icsr2 = riic_read(pd, RIIC_ICSR2);
+   riic_set_bit(pd, ICIER_NAKIE, RIIC_ICIER);
+   ret = wait_event_timeout(pd->wait, pd->dma_callbacked ||
+  pd->icsr2 & ICSR2_NACKF, HZ);
+   riic_clear_bit(pd, ICIER_NAKIE, RIIC_ICIER);
+   if (pd->icsr2 & ICSR2_NACKF) {
+   dmaengine_terminate_all(pd->chan_tx);
+   return -EIO;
+   }
+   if (!ret && !pd->dma_callbacked) {
+   dmaengine_terminate_all(pd->chan_tx);
+   return -ETIMEDOUT;
+   }
+
+   return 0;
+}
+
 static int riic_master_transmit(struct riic_data *pd, int stop)
 {
int ret = 0;
-   int index;

riic_set_bit(pd, ICCR2_ST, RIIC_ICCR2);
ret = riic_wait_for_icsr2(pd, ICSR2_START);
@@ -328,15 +409,12 @@ static int riic_master_transmit(struct riic_data *pd, int 
stop)
goto force_exit;

/* transmit data */
-   index = 0;
-   do {
-   ret = riic_wait_for_icsr2(pd, ICSR2_TDRE);
-   if (ret < 0)
-   goto force_exit;
-
-   riic_write(pd, pd->msg->buf[index], RIIC_ICDRT);
-   index++;
-   } while (pd->msg->len > index);
+   if (pd->chan_tx && pd->msg->len > 1)
+   ret = riic_master_transmit_dma(pd);
+   else
+   ret = riic_master_transmit_pio(pd);
+   if (ret < 0)
+   goto force_exit;

ret = riic_wait_for_icsr2(pd, ICSR2_TEND);
if (ret < 0)
@@ -361,12 +439,72 @@ static void riic_set_receive_ack(struct riic_data *pd, 
int ack)
riic_set_bit(pd, ICMR3_ACKBT, RIIC_ICMR3);
 }

+static int riic_master_receive_pio(struct riic_data *pd)
+{
+   int ret;
+
+   pd->index = 0;
+
+   while ((pd->msg->len - 1) > pd->index) {
+ 

[PATCH 1/2 v3] i2c: i2c-riic: add support for Renesas RIIC

2011-09-26 Thread Yoshihiro Shimoda
This driver supports the RIIC module. The SH7757 has it.
The driver doesn't use any IRQ handler. This is because the module
has errata in an interrupt. So, we cannot use the interrupt for
transfer.

Signed-off-by: Yoshihiro Shimoda 
---
 about v3
  - add clk framework
  - adjust for the latest kernel (fix compile error)

 drivers/i2c/busses/Kconfig|9 +
 drivers/i2c/busses/Makefile   |1 +
 drivers/i2c/busses/i2c-riic.c |  620 +
 include/linux/i2c/riic.h  |   29 ++
 4 files changed, 659 insertions(+), 0 deletions(-)
 create mode 100644 drivers/i2c/busses/i2c-riic.c
 create mode 100644 include/linux/i2c/riic.h

diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index 646068e..e057344 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -687,6 +687,15 @@ config I2C_EG20T
  ML7213/ML7223 is companion chip for Intel Atom E6xx series.
  ML7213/ML7223 is completely compatible for Intel EG20T PCH.

+config I2C_RIIC
+   tristate "Renesas RIIC controller"
+   depends on SUPERH
+   help
+ This driver supports the RIIC module of the Renesas SH7757.
+
+ This driver can also be built as a module.  If so, the module
+ will be called i2c-riic.
+
 comment "External I2C/SMBus adapter drivers"

 config I2C_DIOLAN_U2C
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index e6cf294..93ca34f 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -55,6 +55,7 @@ obj-$(CONFIG_I2C_PNX) += i2c-pnx.o
 obj-$(CONFIG_I2C_PUV3) += i2c-puv3.o
 obj-$(CONFIG_I2C_PXA)  += i2c-pxa.o
 obj-$(CONFIG_I2C_PXA_PCI)  += i2c-pxa-pci.o
+obj-$(CONFIG_I2C_RIIC)  += i2c-riic.o
 obj-$(CONFIG_I2C_S3C2410)  += i2c-s3c2410.o
 obj-$(CONFIG_I2C_S6000)+= i2c-s6000.o
 obj-$(CONFIG_I2C_SH7760)   += i2c-sh7760.o
diff --git a/drivers/i2c/busses/i2c-riic.c b/drivers/i2c/busses/i2c-riic.c
new file mode 100644
index 000..1e6639c
--- /dev/null
+++ b/drivers/i2c/busses/i2c-riic.c
@@ -0,0 +1,620 @@
+/*
+ * RIIC bus driver
+ *
+ * Copyright (C) 2011  Renesas Solutions Corp.
+ *
+ * Based on i2c-sh_mobile.c
+ * Portion Copyright (C) 2008 Magnus Damm
+ *
+ * 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; version 2 of the License.
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define RIIC_ICCR1 0x00
+#define RIIC_ICCR2 0x01
+#define RIIC_ICMR1 0x02
+#define RIIC_ICMR2 0x03
+#define RIIC_ICMR3 0x04
+#define RIIC_ICFER 0x05
+#define RIIC_ICSER 0x06
+#define RIIC_ICIER 0x07
+#define RIIC_ICSR1 0x08
+#define RIIC_ICSR2 0x09
+#define RIIC_SARL0 0x0a
+#define RIIC_SARU0 0x0b
+#define RIIC_SARL1 0x0c
+#define RIIC_SARU1 0x0d
+#define RIIC_SARL2 0x0e
+#define RIIC_SARU2 0x0f
+#define RIIC_ICBRL 0x10
+#define RIIC_ICBRH 0x11
+#define RIIC_ICDRT 0x12
+#define RIIC_ICDRR 0x13
+
+/* ICCR1 */
+#define ICCR1_ICE  0x80
+#define ICCR1_IICRST   0x40
+#define ICCR1_CLO  0x20
+#define ICCR1_SOWP 0x10
+#define ICCR1_SCLO 0x08
+#define ICCR1_SDAO 0x04
+#define ICCR1_SCLI 0x02
+#define ICCR1_SDAI 0x01
+
+/* ICCR2 */
+#define ICCR2_BBSY 0x80
+#define ICCR2_MST  0x40
+#define ICCR2_TRS  0x20
+#define ICCR2_SP   0x08
+#define ICCR2_RS   0x04
+#define ICCR2_ST   0x02
+
+/* ICMR1 */
+#define ICMR1_MTWP 0x80
+#define ICMR1_CKS_MASK 0x70
+#define ICMR1_BCWP 0x08
+#define ICMR1_BC_MASK  0x07
+
+#define ICMR1_CKS(_x)  ((_x << 4) & ICMR1_CKS_MASK)
+#define ICMR1_BC(_x)   ((_x) & ICMR1_BC_MASK)
+
+/* ICMR2 */
+#define ICMR2_DLCS 0x80
+#define ICMR2_SDDL_MASK0x70
+#define ICMR2_TMOH 0x04
+#define ICMR2_TMOL 0x02
+#define ICMR2_TMOS 0x01
+
+/* ICMR3 */
+#define ICMR3_SMBS 0x80
+#define ICMR3_WAIT 0x40
+#define ICMR3_RDRFS0x20
+#define ICMR3_ACKWP0x10
+#define ICMR3_ACKBT0x08
+#define ICMR3_ACKBR0x04
+#define ICMR3_NF_MASK  0x03
+
+/* ICFER */
+#define ICFER_FMPE 0x80
+#define ICFER_SCLE 0x40
+#define ICFER_NFE  0x20
+#define ICFER_NACKE0x10
+#define ICFER_SALE 0x08
+#define ICFER_NALE 0x04
+#define ICFER_MALE 0x02
+#define ICFER_TMOE 0x01
+
+/* ICSER */
+#define ICSER_HOAE 

[PATCH] i2c-eg20t: modified the setting of transfer rate.

2011-09-26 Thread Toshiharu Okada
This patch modified the setting value of
I2C Bus Transfer Rate Setting Counter regisrer.

Signed-off-by: Toshiharu Okada 
---
 drivers/i2c/busses/i2c-eg20t.c |2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/i2c/busses/i2c-eg20t.c b/drivers/i2c/busses/i2c-eg20t.c
index ce1a32b..6b46892 100644
--- a/drivers/i2c/busses/i2c-eg20t.c
+++ b/drivers/i2c/busses/i2c-eg20t.c
@@ -242,7 +242,7 @@ static void pch_i2c_init(struct i2c_algo_pch_data *adap)
if (pch_clk > PCH_MAX_CLK)
pch_clk = 62500;
 
-   pch_i2cbc = (pch_clk + (pch_i2c_speed * 4)) / pch_i2c_speed * 8;
+   pch_i2cbc = (pch_clk + (pch_i2c_speed * 4)) / (pch_i2c_speed * 8);
/* Set transfer speed in I2CBC */
iowrite32(pch_i2cbc, p + PCH_I2CBC);
 
-- 
1.7.4.4

--
To unsubscribe from this list: send the line "unsubscribe linux-i2c" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html