i2c-imx slave mode. detect stop condition

cancel
Showing results for 
Search instead for 
Did you mean: 

i2c-imx slave mode. detect stop condition

Jump to solution
1,443 Views
Contributor II

Hello,

We want to make an ipmb BMC, based on the imx6 processor.

To support ipmb protocol we need i2c-imx controller to support master and slave mode.

We work with Linux kernel 4.1 ( Freescale/linux-fslc · GitHub​​​  ).

There is a realisation of slave mode from 2.6 kernel ( linux-2.6-imx.git - Freescale i.MX Linux Tree ), and we are porting it to "i2c-imx.c" from 4.1 kernel, using new i2c slave subsystem ( linux-fslc/slave-interface at patches-4.1 · Freescale/linux-fslc · GitHub )

But "mxc_i2c_slave.c" is not able to detect stop condition from master. Thus, for instance, if master sends us two 15 bytes packages, the driver will not able to divide these packages, and just receive 30 bytes. We also can`t find a way to detect the stop condition in the datasheet on the i2c-imx controller.

How can we detect the stop condition in the slave mode?

Labels (1)
1 Solution
61 Views
Contributor II

I would like to update this thread.

We`ve dug into the datasheet one more time and it seems that i2c-imx controller has no such function.

It is very sad, if it is true. I hope that there is an adequate way to detect the stop condition.

For now, we`ve made up some workaround:

We check IBB bit after we`ve received each byte from a master. When master sends us the last byte he should release a bus and in this case IBB bit will be 0. But this method has a big drawback: it is not possible to predict how much time master will hold the bus after sending us the last byte. Thus we should wait some time before checking IBB bit. During our experiments we found that 50 microseconds seems to be enough time to be sure that it is the last byte (but all the same, very rarely it seems that we lose stop condition).

The part of our code that does this (I`m sorry for not providing full source code, but it is not finished for now, and frankly speaking it is very ugly):

static void i2c_imx_slave_isr_handler_tasklet(unsigned long i2c_imx_data)

{

    /*

    ...

    interrupt processing

    ...

    */

    udelay(50);

    status = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2SR);

    if((status & I2SR_IBB) == 0) {

        pr_alert("end of package");

        i2c_slave_event(i2c_imx->slave, I2C_SLAVE_STOP, &data);

    }

}

View solution in original post

9 Replies
62 Views
Contributor II

I would like to update this thread.

We`ve dug into the datasheet one more time and it seems that i2c-imx controller has no such function.

It is very sad, if it is true. I hope that there is an adequate way to detect the stop condition.

For now, we`ve made up some workaround:

We check IBB bit after we`ve received each byte from a master. When master sends us the last byte he should release a bus and in this case IBB bit will be 0. But this method has a big drawback: it is not possible to predict how much time master will hold the bus after sending us the last byte. Thus we should wait some time before checking IBB bit. During our experiments we found that 50 microseconds seems to be enough time to be sure that it is the last byte (but all the same, very rarely it seems that we lose stop condition).

The part of our code that does this (I`m sorry for not providing full source code, but it is not finished for now, and frankly speaking it is very ugly):

static void i2c_imx_slave_isr_handler_tasklet(unsigned long i2c_imx_data)

{

    /*

    ...

    interrupt processing

    ...

    */

    udelay(50);

    status = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2SR);

    if((status & I2SR_IBB) == 0) {

        pr_alert("end of package");

        i2c_slave_event(i2c_imx->slave, I2C_SLAVE_STOP, &data);

    }

}

View solution in original post

61 Views
NXP TechSupport
NXP TechSupport

Hello Ktulhu Uchiha,

Thank you por posting your workaround! I’m sure it will help other community users.

I’m sorry that the I2C module does not have an adequate way to handle that specific scenario. I believe it’s got a lot to do with the way the I2C protocol behaves, as it’s the master the one that sends data and releases the bus when done, so it’s hard to separate strings of data as packages from the same master.

Regards,

61 Views
Contributor II

Hello gusarambula,

Thank you for your answer.

According to the i2c specification, it should not be hard to separate packages, because master must send “stop” or “repeated start” signal after each transaction. You can look at transaction formats in Linux/Documentation/i2c/smbus-protocol - Linux Cross Reference - Free Electrons and Linux/Documentation/i2c/i2c-protocol - Linux Cross Reference - Free Electrons

Thus, if we can detect the stop condition, there is no problem to “separate strings of data as packages”.

Finally, we ended up with the following solution: we use kthread to process slave interrupts and poll ibb bit each 100 milliseconds:

<Update>

We`ve submitted our patch to the kernel mailing list: Gmane Loom  >

</Update>

0 Kudos
61 Views
Contributor III

Hi Ktulhu Uchiha:

   Would you please attach you patch here? We can't access the kernel mailing list: Gmane Loom.

Thanks a lot!

Best Regards,

Azmat

0 Kudos
61 Views
Contributor II
61 Views
Contributor III

That is a great help!

0 Kudos
61 Views
NXP Employee
NXP Employee

Could you please submit your patch to linux-i2c@vger.kernel.org, so that it can be reviewed and potentially applied to the kernel.

It would be nice to have imx i2c slave support in mainline.

Thanks,

Fabio Estevam

61 Views
Contributor II

Fabio Estevam,

Thank you for your suggestion.

We`ve submitted it (look at the previous message, we`ve updated it)

61 Views
NXP Employee
NXP Employee

Thanks for submitting it!