Conflict on 2 I2C buses

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Conflict on 2 I2C buses

Jump to solution
4,821 Views
samuelsalas
Contributor III

Hi,

It seems I have a communication conflict with between my touchscreen driver on the i2c-1 and my external board on i2c-0 which both are communicating with my imx28 board.

No hardware problem, but the kernel seems not to make the difference and stop randomly when both are connected.

When one is connected, no problem.

Any idea?

Labels (2)
0 Kudos
1 Solution
3,102 Views
samuelsalas
Contributor III

The correct solution is to switch to new kernel with the new driver or to apply the same modification (avoiding global values for DMA) in the 2.6.35 kernel.

We did the second solution, if anyone is interested, we could give the patch.

The BUG_ON fixing is not the correct solution.

View solution in original post

0 Kudos
16 Replies
3,102 Views
binoyjayan
Contributor III

Hi samuel,

Could you please post the patch here.? I am also facing the same issue when communicating with two i2c slaves..

Thank you

Binoy

0 Kudos
3,102 Views
binoyjayan
Contributor III

Hi,

It finally worked for me by patching i2c-mxs.c and i2c-mxs.h.

Regards,

Binoy

0 Kudos
3,102 Views
srinivasanshanm
Contributor III

Hi Binoy,

Even am using L2.6.35_10.12.01_ER_source & don't want to use latest kernels, & I am also facing the same issue when communicating with two i2c slaves. when using i2c-0 & i2c-1 buses for communicating with slaves, could you please post me the patch that is to be applied as early as possible

Many Many Thanks in advance,

0 Kudos
3,102 Views
samuelsalas
Contributor III

Hi everyone,

As I saw it's not the first time someone is asking the patch, I prefer to publish it for the future. Here the patch we used on 2.6.35 kernel :

--------------------------

diff -Naur a/arch/arm/plat-mxs/include/mach/device.h b/arch/arm/plat-mxs/include/mach/device.h

--- a/arch/arm/plat-mxs/include/mach/device.h 2013-05-02 18:20:09.000000000 +0200

+++ b/arch/arm/plat-mxs/include/mach/device.h 2013-05-02 18:32:23.000000000 +0200

@@ -62,6 +62,7 @@

struct mxs_i2c_plat_data {

  unsigned int pioqueue_mode:1;

+ unsigned int speed;

};

struct mxs_lradc_plat_data {

@@ -128,7 +129,7 @@

struct mxs_spi_platform_data {

  int (*hw_pin_init)(void);

  int (*hw_pin_release)(void);

-

+ struct platform_device * cli;

  char *clk;

};

diff -Naur a/drivers/i2c/busses/i2c-mxs.c b/drivers/i2c/busses/i2c-mxs.c

--- a/drivers/i2c/busses/i2c-mxs.c 2013-05-02 18:20:11.000000000 +0200

+++ b/drivers/i2c/busses/i2c-mxs.c 2013-05-02 18:32:23.000000000 +0200

@@ -35,15 +35,9 @@

#include <mach/regs-i2c.h>

#include <mach/system.h>

#include <mach/hardware.h>

-

+#include <linux/spinlock.h>

#include "i2c-mxs.h"

-/* 2 for read, 1 for write */

-#define NR_DESC 3

-static struct mxs_dma_desc *desc[NR_DESC];

-static dma_addr_t i2c_buf_phys;

-static u8 *i2c_buf_virt;

-

#define CMD_I2C_SELECT (BM_I2C_CTRL0_RETAIN_CLOCK | \

  BM_I2C_CTRL0_PRE_SEND_START | \

  BM_I2C_CTRL0_MASTER_MODE | \

@@ -67,6 +61,31 @@

#define HW_I2C_QUEUECTRL_CLR HW_I2C_VERSION

#endif

+

+/*

+ * Timing values for the default 24MHz clock supplied into the i2c block.

+ *

+ * The bus can operate at 95kHz or at 400kHz with the following timing

+ * register configurations. The 100kHz mode isn't present because it's

+ * values are not stated in the i.MX233/i.MX28 datasheet. The 95kHz mode

+ * shall be close enough replacement. Therefore when the bus is configured

+ * for 100kHz operation, 95kHz timing settings are actually loaded.

+ *

+ * For details, see i.MX233 [25.4.2 - 25.4.4] and i.MX28 [27.5.2 - 27.5.4].

+ */

+

+static const struct mxs_i2c_speed_config mxs_i2c_95kHz_config = {

+ .timing0 = 0x00780030,

+ .timing1 = 0x00800030,

+ .timing2 = 0x00300030,

+};

+

+static const struct mxs_i2c_speed_config mxs_i2c_400kHz_config = {

+ .timing0 = 0x000f0007,

+ .timing1 = 0x001f000f,

+ .timing2 = 0x00300030,

+};

+

static void hw_i2c_dmachan_reset(struct mxs_i2c_dev *dev)

{

  mxs_dma_disable(dev->dma_chan);

@@ -80,6 +99,10 @@

  mxs_dma_enable_irq(mxs_i2c->dma_chan, 1);

  mxs_reset_block((void __iomem *)mxs_i2c->regbase, 0);

  __raw_writel(0x0000FF00, mxs_i2c->regbase + HW_I2C_CTRL1_SET);

+ writel(mxs_i2c->speed.timing0, mxs_i2c->regbase + HW_I2C_TIMING0);

+ writel(mxs_i2c->speed.timing1, mxs_i2c->regbase + HW_I2C_TIMING1);

+ writel(mxs_i2c->speed.timing2, mxs_i2c->regbase + HW_I2C_TIMING2);

+

}

static int hw_i2c_dma_init(struct platform_device *pdev)

@@ -92,14 +115,14 @@

  return ret;

  for (i = 0; i < NR_DESC; i++) {

- desc[i] = mxs_dma_alloc_desc();

- if (desc[i] == NULL)

+ mxs_i2c->desc[i] = mxs_dma_alloc_desc();

+ if (mxs_i2c->desc[i] == NULL)

  goto err;

  }

- i2c_buf_virt = dma_alloc_coherent(&pdev->dev,

-  PAGE_SIZE, &i2c_buf_phys, GFP_KERNEL);

- if (i2c_buf_virt == NULL)

+ mxs_i2c->i2c_buf_virt = dma_alloc_coherent(&pdev->dev,

+  PAGE_SIZE, &mxs_i2c->i2c_buf_phys, GFP_KERNEL);

+ if (mxs_i2c->i2c_buf_virt == NULL)

  goto err;

  hw_i2c_dmachan_reset(mxs_i2c);

@@ -109,7 +132,7 @@

err:

  while (--i >= 0)

- mxs_dma_free_desc(desc[i]);

+ mxs_dma_free_desc(mxs_i2c->desc[i]);

  return -ENOMEM;

}

@@ -125,11 +148,11 @@

  mxs_dma_disable(mxs_i2c->dma_chan);

  for (i = 0; i < NR_DESC; i++)

- mxs_dma_free_desc(desc[i]);

+ mxs_dma_free_desc(mxs_i2c->desc[i]);

  hw_i2c_dmachan_reset(mxs_i2c);

- dma_free_coherent(&pdev->dev, PAGE_SIZE, i2c_buf_virt, i2c_buf_phys);

+ dma_free_coherent(&pdev->dev, PAGE_SIZE, mxs_i2c->i2c_buf_virt, mxs_i2c->i2c_buf_phys);

  mxs_dma_release(mxs_i2c->dma_chan, &pdev->dev);

}

@@ -157,34 +180,34 @@

}

-static void hw_i2c_dma_setup_read(u8 addr, void *buff, int len, int flags)

+static void hw_i2c_dma_setup_read(u8 addr, void *buff, int len, int flags,struct mxs_i2c_dev *dev)

{

  if (len > (PAGE_SIZE - 4))

  BUG();

- memset(&desc[0]->cmd, 0, sizeof(desc[0]->cmd));

- memset(&desc[1]->cmd, 0, sizeof(desc[1]->cmd));

+ memset(&dev->desc[0]->cmd, 0, sizeof(dev->desc[0]->cmd));

+ memset(&dev->desc[1]->cmd, 0, sizeof(dev->desc[1]->cmd));

- desc[0]->cmd.cmd.bits.bytes = 1;

- desc[0]->cmd.cmd.bits.pio_words = 1;

- desc[0]->cmd.cmd.bits.wait4end = 1;

- desc[0]->cmd.cmd.bits.dec_sem = 1;

- desc[0]->cmd.cmd.bits.irq = 0;

- desc[0]->cmd.cmd.bits.chain = 1;

- desc[0]->cmd.cmd.bits.command = DMA_READ;

- desc[0]->cmd.address = i2c_buf_phys;

- desc[0]->cmd.pio_words[0] = CMD_I2C_SELECT;

- i2c_buf_virt[0] = (addr << 1) | I2C_READ;

-

- desc[1]->cmd.cmd.bits.bytes = len;

- desc[1]->cmd.cmd.bits.pio_words = 1;

- desc[1]->cmd.cmd.bits.wait4end = 1;

- desc[1]->cmd.cmd.bits.dec_sem = 1;

- desc[1]->cmd.cmd.bits.irq = 1;

- desc[1]->cmd.cmd.bits.command = DMA_WRITE;

- desc[1]->cmd.address = (u32) i2c_buf_phys + 1;

- desc[1]->cmd.pio_words[0] = CMD_I2C_READ;

- desc[1]->cmd.pio_words[0] |= BF_I2C_CTRL0_XFER_COUNT(len) | flags;

+ dev->desc[0]->cmd.cmd.bits.bytes = 1;

+ dev->desc[0]->cmd.cmd.bits.pio_words = 1;

+ dev->desc[0]->cmd.cmd.bits.wait4end = 1;

+ dev->desc[0]->cmd.cmd.bits.dec_sem = 1;

+ dev->desc[0]->cmd.cmd.bits.irq = 0;

+ dev->desc[0]->cmd.cmd.bits.chain = 1;

+ dev->desc[0]->cmd.cmd.bits.command = DMA_READ;

+ dev->desc[0]->cmd.address = dev->i2c_buf_phys;

+ dev->desc[0]->cmd.pio_words[0] = CMD_I2C_SELECT;

+ dev->i2c_buf_virt[0] = (addr << 1) | I2C_READ;

+

+ dev->desc[1]->cmd.cmd.bits.bytes = len;

+ dev->desc[1]->cmd.cmd.bits.pio_words = 1;

+ dev->desc[1]->cmd.cmd.bits.wait4end = 1;

+ dev->desc[1]->cmd.cmd.bits.dec_sem = 1;

+ dev->desc[1]->cmd.cmd.bits.irq = 1;

+ dev->desc[1]->cmd.cmd.bits.command = DMA_WRITE;

+ dev->desc[1]->cmd.address = (u32) dev->i2c_buf_phys + 1;

+ dev->desc[1]->cmd.pio_words[0] = CMD_I2C_READ;

+ dev->desc[1]->cmd.pio_words[0] |= BF_I2C_CTRL0_XFER_COUNT(len) | flags;

}

static void hw_i2c_pioq_setup_write(struct mxs_i2c_dev *dev,

@@ -219,23 +242,23 @@

  __raw_writel(*buf2++, dev->regbase + HW_I2C_DATA);

}

-static void hw_i2c_dma_setup_write(u8 addr, void *buff, int len, int flags)

+static void hw_i2c_dma_setup_write(u8 addr, void *buff, int len, int flags,struct mxs_i2c_dev *dev)

{

- memset(&desc[2]->cmd, 0, sizeof(desc[2]->cmd));

+ memset(&dev->desc[2]->cmd, 0, sizeof(dev->desc[2]->cmd));

- desc[2]->cmd.cmd.bits.bytes = len + 1;

- desc[2]->cmd.cmd.bits.pio_words = 1;

- desc[2]->cmd.cmd.bits.wait4end = 1;

- desc[2]->cmd.cmd.bits.dec_sem = 1;

- desc[2]->cmd.cmd.bits.irq = 1;

- desc[2]->cmd.cmd.bits.command = DMA_READ;

- desc[2]->cmd.address = i2c_buf_phys;

- desc[2]->cmd.pio_words[0] = CMD_I2C_WRITE;

- desc[2]->cmd.pio_words[0] |= BM_I2C_CTRL0_POST_SEND_STOP;

- desc[2]->cmd.pio_words[0] |= BF_I2C_CTRL0_XFER_COUNT(len + 1) | flags;

+ dev->desc[2]->cmd.cmd.bits.bytes = len + 1;

+ dev->desc[2]->cmd.cmd.bits.pio_words = 1;

+ dev->desc[2]->cmd.cmd.bits.wait4end = 1;

+ dev->desc[2]->cmd.cmd.bits.dec_sem = 1;

+ dev->desc[2]->cmd.cmd.bits.irq = 1;

+ dev->desc[2]->cmd.cmd.bits.command = DMA_READ;

+ dev->desc[2]->cmd.address = dev->i2c_buf_phys;

+ dev->desc[2]->cmd.pio_words[0] = CMD_I2C_WRITE;

+ dev->desc[2]->cmd.pio_words[0] |= BM_I2C_CTRL0_POST_SEND_STOP;

+ dev->desc[2]->cmd.pio_words[0] |= BF_I2C_CTRL0_XFER_COUNT(len + 1) | flags;

- i2c_buf_virt[0] = (addr << 1) | I2C_WRITE;

- memcpy(&i2c_buf_virt[1], buff, len);

+ dev->i2c_buf_virt[0] = (addr << 1) | I2C_WRITE;

+ memcpy(&dev->i2c_buf_virt[1], buff, len);

}

static void hw_i2c_pioq_run(struct mxs_i2c_dev *dev)

@@ -246,10 +269,10 @@

static void hw_i2c_dma_run(struct mxs_i2c_dev *dev, int dir)

{

  if (dir == I2C_READ) {

- mxs_dma_desc_append(dev->dma_chan, desc[0]);

- mxs_dma_desc_append(dev->dma_chan, desc[1]);

+ mxs_dma_desc_append(dev->dma_chan, dev->desc[0]);

+ mxs_dma_desc_append(dev->dma_chan, dev->desc[1]);

  } else

- mxs_dma_desc_append(dev->dma_chan, desc[2]);

+ mxs_dma_desc_append(dev->dma_chan, dev->desc[2]);

  mxs_dma_enable(dev->dma_chan);

}

@@ -276,7 +299,7 @@

  memcpy(buff, buf1, len);

  } else

- memcpy(buff, &i2c_buf_virt[1], len);

+ memcpy(buff, &dev->i2c_buf_virt[1], len);

}

/*

@@ -288,7 +311,7 @@

  struct mxs_i2c_dev *dev = i2c_get_adapdata(adap);

  int err;

  int flags;

-

+

  init_completion(&dev->cmd_complete);

  dev->cmd_err = 0;

@@ -299,7 +322,6 @@

  return -EINVAL;

  flags = stop ? BM_I2C_CTRL0_POST_SEND_STOP : 0;

-

  if (msg->flags & I2C_M_RD) {

  if (dev->flags & MXS_I2C_PIOQUEUE_MODE) {

  hw_i2c_pioq_setup_read(dev,

@@ -307,8 +329,9 @@

        msg->buf, msg->len, flags);

  hw_i2c_pioq_run(dev);

  } else {

+

  hw_i2c_dma_setup_read(msg->addr,

-      msg->buf, msg->len, flags);

+      msg->buf, msg->len, flags,dev);

  hw_i2c_dma_run(dev, I2C_READ);

  }

@@ -320,53 +343,71 @@

  hw_i2c_pioq_run(dev);

  } else {

  hw_i2c_dma_setup_write(msg->addr,

-       msg->buf, msg->len, flags);

+       msg->buf, msg->len, flags,dev);

  hw_i2c_dma_run(dev, I2C_WRITE);

+

  }

  }

-

  err = wait_for_completion_interruptible_timeout(&dev->cmd_complete,

  msecs_to_jiffies(1000)

     );

- if (err <= 0) {

- mxs_i2c_reset(dev);

+ if (err == 0) {

  dev_dbg(dev->dev, "controller is timed out\n");

- return -ETIMEDOUT;

+ dev->cmd_err = -ETIMEDOUT;

+ hw_i2c_dmachan_reset(dev);

+ mxs_i2c_reset(dev);

+    goto done;

  }

  if ((!dev->cmd_err) && (msg->flags & I2C_M_RD))

  hw_i2c_finish_read(dev, msg->buf, msg->len);

+

+ /* No Slave ack */

+ if (dev->cmd_err == -ENXIO) {

+ mxs_i2c_reset(dev);

+ hw_i2c_dmachan_reset(dev);

+ goto done;

+ } else if (dev->cmd_err == -EIO) {

+ printk(KERN_WARNING "%s: I2C Fault!\n", __func__);

+ hw_i2c_dmachan_reset(dev);

+ mxs_i2c_reset(dev);

+ goto done;

+ }

- dev_dbg(dev->dev, "Done with err=%d\n", dev->cmd_err);

+ if ((!dev->cmd_err) && (msg->flags & I2C_M_RD))

+ {

+ hw_i2c_finish_read(dev, msg->buf, msg->len);

+ }

+done:

+ dev_dbg(dev->dev, "Done with err=%d\n", dev->cmd_err);

  return dev->cmd_err;

}

-static int

-mxs_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)

+static int mxs_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)

{

  int i;

  int err;

-

  if (!msgs->len)

+ {

  return -EINVAL;

-

+ }

  for (i = 0; i < num; i++) {

  err = mxs_i2c_xfer_msg(adap, &msgs[i], (i == (num - 1)));

  if (err)

  break;

  }

-

  if (err == 0)

  err = num;

- return err;

+ return err;

}

static u32 mxs_i2c_func(struct i2c_adapter *adap)

{

  return I2C_FUNC_I2C | (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK);

}

+#define I2C_IRQ_MASK 0x000000FF

static irqreturn_t mxs_i2c_dma_isr(int this_irq, void *dev_id)

{

@@ -389,20 +430,21 @@

  complete(&mxs_i2c->cmd_complete);

}

-#define I2C_IRQ_MASK 0x000000FF

+

static irqreturn_t mxs_i2c_isr(int this_irq, void *dev_id)

{

  struct mxs_i2c_dev *mxs_i2c = dev_id;

  u32 stat;

  u32 done_mask =

     BM_I2C_CTRL1_DATA_ENGINE_CMPLT_IRQ | BM_I2C_CTRL1_BUS_FREE_IRQ;

-

  stat = __raw_readl(mxs_i2c->regbase + HW_I2C_CTRL1) & I2C_IRQ_MASK;

+

  if (!stat)

  return IRQ_NONE;

  if (stat & BM_I2C_CTRL1_NO_SLAVE_ACK_IRQ) {

- mxs_i2c->cmd_err = -EREMOTEIO;

+ mxs_i2c->cmd_err = -ENXIO;

+

  /* it takes long time to reset i2c */

  schedule_work(&mxs_i2c->work);

  goto done;

@@ -499,6 +541,13 @@

  goto no_dma_irq;

  }

+

+ if (pdata->speed == 400000)

+ mxs_i2c->speed = mxs_i2c_400kHz_config;

+ else

+ mxs_i2c->speed = mxs_i2c_95kHz_config;

+

+

  /* reset I2C module */

  mxs_reset_block((void __iomem *)mxs_i2c->regbase, 1);

  platform_set_drvdata(pdev, mxs_i2c);

@@ -537,7 +586,6 @@

  }

  INIT_WORK(&mxs_i2c->work, mxs_i2c_task);

-

  return 0;

no_i2c_adapter:

diff -Naur a/drivers/i2c/busses/i2c-mxs.h b/drivers/i2c/busses/i2c-mxs.h

--- a/drivers/i2c/busses/i2c-mxs.h 2013-05-02 18:20:08.000000000 +0200

+++ b/drivers/i2c/busses/i2c-mxs.h 2013-05-02 18:32:23.000000000 +0200

@@ -19,8 +19,16 @@

#ifndef _I2C_H

#define _I2C_H

+/* 2 for read, 1 for write */

#define I2C_READ   1

#define I2C_WRITE  0

+#define NR_DESC 3

+

+struct mxs_i2c_speed_config {

+ u32 timing0;

+ u32 timing1;

+ u32 timing2;

+};

struct mxs_i2c_dev {

  struct device *dev;

@@ -38,5 +46,9 @@

  spinlock_t lock;

  wait_queue_head_t queue;

  struct work_struct work;

+ struct mxs_i2c_speed_config speed;

+ u8 *i2c_buf_virt;

+ dma_addr_t i2c_buf_phys;

+ struct mxs_dma_desc *desc[NR_DESC];

};

#endif

diff -Naur a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig

--- a/drivers/i2c/busses/Kconfig 2013-05-02 18:20:05.000000000 +0200

+++ b/drivers/i2c/busses/Kconfig 2013-05-02 18:32:23.000000000 +0200

@@ -470,6 +470,12 @@

   say yes if you are sure transfer length is eqaul to or less than 24 bytes.

   Otherwise say no to use DMA mode by default.

+config I2C_MXS_SELECT0_400_MODE

+ bool "MXS I2C0 speed at 400kHz"

+ depends on (I2C_MXS_SELECT0 && !ARCH_MX23)

+ help

+  say yes if you want to have 400kHz speed I2C.

+

config I2C_MXS_SELECT1

  bool "Enable I2C1 module"

  depends on (I2C_MXS && !ARCH_MX23)

@@ -483,6 +489,12 @@

   say yes if you are sure transfer length is eqaul to or less than 24 bytes.

   Otherwise say no to use DMA mode by default.

+config I2C_MXS_SELECT1_400_MODE

+ bool "MXS I2C1 speed at 400kHz"

+ depends on (I2C_MXS_SELECT1 && !ARCH_MX23)

+ help

+  say yes if you want to have 400kHz speed I2C.

+

config I2C_STMP378X

  tristate "STMP378x I2C adapter"

  depends on MACH_STMP378X

--------------------------

0 Kudos
3,102 Views
srinivasanshanm
Contributor III

Thanks a lot Samuel, it really helped a lot where I was struggling from many days,

But now the issue is after applying the path which you mentioned above am getting more than 400Khz, ie., I am getting the I2C_SCL as 436.3902 Khz as shown in the above attachment , could you please let me know how this can be accurated to 400Khz, as am using "L2.6.35_10.12.01_ER_source" I.MX28 BSP and the above patch is applied on this source code, & am using i.Mx28 EVK PCB REV D board

Awaiting for your replies as early. & would really appreciate for your help

Many Thanks a lot in advance

0 Kudos
3,102 Views
srinivasanshanm
Contributor III

Hi,

Once again many thanks for the above patch

In the above patch, I suspect that the below highlighted code is required or not,  if am not wrong, could you please confirm & I suspect that the above patch configures.. I2C0 & I2C1 buses.. to 400 Khz, if possible could you please provide if any options of how to readback the the configured register values ie.,

.timing0 = 0x000f0007, .timing1 = 0x001f000f, .timing2 = 0x00300030, because I suspect that am not getting 400khz even after configuring, hope this readback of these register values.. should help in order to verify whether my configuration is correct or not through I2C

static struct mxs_i2c_plat_data i2c1_platdata = {

#ifdef CONFIG_I2C_MXS_SELECT1_PIOQUEUE_MODE

  .pioqueue_mode = 1,

#endif

#ifdef  CONFIG_I2C_MXS_SELECT1_400_MODE

        .speed =  400000,

#endif  

};

static struct mxs_i2c_plat_data i2c0_platdata = {

#ifdef CONFIG_I2C_MXS_SELECT0_PIOQUEUE_MODE

  .pioqueue_mode = 1,

#endif

#ifdef  CONFIG_I2C_MXS_SELECT0_400_MODE

        .speed =  400000,

#endif  

};

Kindly do the needful if as early as possible, as only this is pending for my verification of the configures register values

0 Kudos
3,102 Views
samuelsalas
Contributor III

hi,

you find the maximum info in the chapter 27 of the document MCIMX28RM page 1729/2327:

http://free-electrons.com/~maxime/pub/datasheet/MCIMX28RM.pdf

And in chapter 27.5.2 or 27.5.3 you will find examples. I never try another frequencies, so if you try to understand the "bit" combination of the register, you will be able to change the frequency.

And I remeber if the bus make a reset, you will not have the modified values. Try to put these lines in i2c-mxs.c / function "mxs_i2c_reset" after "mxs_reset_block((void __iomem *)mxs_i2c->regbase, 0);"

---

writel(mxs_i2c_95kHz_config.timing0, mxs_i2c->regbase + HW_I2C_TIMING0);

writel(mxs_i2c_95kHz_config.timing1, mxs_i2c->regbase + HW_I2C_TIMING1);

writel(mxs_i2c_95kHz_config.timing2, mxs_i2c->regbase + HW_I2C_TIMING2);

---

Another possibility is to ask freescale via you FAE or provider.

Good luck and if you achieve you problem, please tell us what you did!

Sam.

0 Kudos
3,102 Views
srinivasanshanm
Contributor III

Hi Sam,

Thanks for your replies,

Even I suspect the bus is getting reset, could you please let me know should the below line is to be put as

---

writel(mxs_i2c_95kHz_config.timing0, mxs_i2c->regbase + HW_I2C_TIMING0);

writel(mxs_i2c_95kHz_config.timing1, mxs_i2c->regbase + HW_I2C_TIMING1);

writel(mxs_i2c_95kHz_config.timing2, mxs_i2c->regbase + HW_I2C_TIMING2);

---

OR

writel(mxs_i2c_400kHz_config.timing0, mxs_i2c->regbase + HW_I2C_TIMING0);

writel(mxs_i2c_400kHz_config.timing1, mxs_i2c->regbase + HW_I2C_TIMING1);

writel(mxs_i2c_400kHz_config.timing2, mxs_i2c->regbase + HW_I2C_TIMING2);

Thanks in advance,

0 Kudos
3,102 Views
samuelsalas
Contributor III

Hi,

The second choice is right if you choose 400kHz.

BR,

Sam

0 Kudos
3,102 Views
fabio_estevam
NXP Employee
NXP Employee

I would recommend you trying a mainline kernel from kernel.org.

Regards,

Fabio Estevam

0 Kudos
3,103 Views
samuelsalas
Contributor III

The correct solution is to switch to new kernel with the new driver or to apply the same modification (avoiding global values for DMA) in the 2.6.35 kernel.

We did the second solution, if anyone is interested, we could give the patch.

The BUG_ON fixing is not the correct solution.

0 Kudos
3,102 Views
samuelsalas
Contributor III

Hi,

My issue was solved by removing the "BUG_ON" function in dmaengine.c as said the kernel trace (kernel BUG at arch/arm/plat-mxs/dmaengine.c:223!).

I read that BUG() shouldn't be used as a debugging function, and only when there is no other choice than killing the system. And when it's removed, it's working fine, so I wonder if this line really need to be there...

0 Kudos
3,102 Views
samuelsalas
Contributor III

Hi,

I applied all the patches, but no chance.

Situation :

One touchscreen driver using i2c-core function "i2c_master_recv" on i2c-1. this driver works on an IRQ every 10 ms.

One User application crosscompiled using ioctl (so using i2c-dev.c) on i2c-0. this application is used randomly.

If "i2c_master_recv" is disabled in my touchscreen driver, no problem.

My error message is :

--

noaliadebian login: kernel BUG at arch/arm/plat-mxs/dmaengine.c:223!

Unable to handle kernel NULL pointer dereference at virtual address 00000000

pgd = c73c0000

[00000000] *pgd=473a8031, *pte=00000000, *ppte=00000000

Internal error: Oops: 817 [#1] PREEMPT

last sysfs file: /sys/devices/virtual/net/lo/operstate

Modules linked in:

CPU: 0    Not tainted  (2.6.35.3-571-gcca29a0 #661)

PC is at __bug+0x20/0x2c

LR is at release_console_sem+0x1b4/0x230


(..to the kernel panic ...)

Kernel panic - not syncing: Fatal exception in interrupt

Backtrace:

[<c00524a8>] (dump_backtrace+0x0/0x114) from [<c03d5860>] (dump_stack+0x18/0x1c)

r7:c005213c r6:00000001 r5:c7393ac4 r4:c0535358

[<c03d5848>] (dump_stack+0x0/0x1c) from [<c03d58dc>] (panic+0x78/0xf4)

[<c03d5864>] (panic+0x0/0xf4) from [<c005288c>] (die+0x2d0/0x324)

(...)


Any other idea ?

0 Kudos
3,102 Views
MarekVasut
Senior Contributor I

Can you by any chance try with upstream 3.7 kernel? The i2c driver there is different. Be aware that the upstream kernel is in a good shape on mx28evk, but there are still some less interesting components missing (like DCP ... if you need it). From what I remember, the DMA actually works on the I2C even for very long transfers (>32k bytes) and there is a different DMA engine driver.

Otherwise, it seems you ought to check dmaengine.c at line 223 and that might give you a hint ;-)

3,102 Views
samuelsalas
Contributor III

Hi we already have modifyed some features in the kernel and I prefer not to change the kernel.

But I will have a look at the i2c-mxs.c from this kernel and I will let you know.

0 Kudos
3,102 Views
jimmychan
NXP TechSupport
NXP TechSupport

There are some patches for i.MX28. Do you apply it all?

You can download the patches from here:

< http://www.freescale.com/webapp/sps/site/prod_summary.jsp?code=MCIMX28EVKJ >