I2C problems.

I am having some problems with using the I2C. Each time I write a value to the I2C_CNT register and attempt yo read it, I read a different value from what I had just written to it. I tried to write with the I2C module enabled and with the I2C disabled, but it did not make any difference. Reads from the I2C_DATA returns 0xFF and the I2C_STAT register is 0x0000.

What could be the problem? I have tried all combination of reading and writing that I thought logical. Have I missed something?

The code is running bare metal.

Thank you.

Is there a reason that you are not using the I2C access routines
defined in linux/i2c.h? You should not be reading and writing omap
i2c registers directly unless you're touching the drivers.

look at i2c_smbus_read_byte and i2c_smbus_write_byte, and the
associated functions.

Basically, you'll need to add the i2c device with something like
i2c_register_device (or is it i2c_add_device)... I don't have the
kernel in front of me. But look at Documentation/i2c/*.


Adding details to the above post:

I discovered that If I attempt yo write I2C_CNT register with a number <3, I2C_CNT remains 2. If I attempt to write I2C_CNT with a value>=3, it takes that value. I did not find this in any documentation. TI’s xloader source from gitorious (the i2c functions) writes a value of 0 to the I2C_CNT although the datasheet clearly states that this is an illegal value. Any comments? Did I get anything wrong here?

Can you provide source code so that we can reproduce the behavior?

----- Message from lord.loh@gmail.com ---------

http://b1.lohray.com/pub/u-boot-vml.tar.gz is the compressed file. It is one big hack (sorry!).

The file where the code is is called main.c the functions to see are init_i2c, i2c_readbyte.

I compile it using a script called compile.sh. My cross compiler is “arm-none-eabi-”. I finally add this u-boot.bin to the sd card or a qemu nand image to test it.

I had troubles following through several files of x-loader and u-boot and attempted to write everything in a single file and put it up on my blog for others to follow before rewriting the code in a proper style.

Thank you for the help.

I am writing a bare metal program. Actually porting an OS. So there is no linux. I have to create my own drivers and libraries etc.

I did a bit more work on this and did not succeed :frowning:

So I finally copied the i2c functions from the xloader source and things worked as it should have. Now I am trying to swap parts of the xloader code with my own and see where I had gone wrong. xloader has a piece of code in the i2c_read_byte() function

if (status & 1<<I2C_STAT_XRDY) {
/* Important: have to use byte access */
val8(I2C_DATA) = regoffset;
udelay (20000);
if (val (I2C_STAT) & 1<<I2C_STAT_NACK) {
i2c_error = 1;
} else {
i2c_error = 1;

val8() is a macro I had written in place of in and out.

My question here is - Is there a way around udelay(20000)? Can I poll a bit instead of waiting for 20ms? I really want to avoid all kinds of random delays.

Thank you. :slight_smile:

I tried replacing the udelay(20000); with a sequence that polled the BB flag. The programs still seems to read data off the i2c bus fine. (I am running this on qemu and not the actual hardware). Can anyone tell me off their experience if this code works by fluke? or is it safe to poll the BB bit instead of a udelay 20 ms?

Thank you

Hello Lord Loh,
A while ago, I found out a way which I was able to write values into
the registers from I2C. It was a little weird and I can not explain
the reason.
If you want bit 0 as high level, bit 16 has also to be set as high
Setting bit 1 as high level, you have to set bit 17 as well.
Same for bit 2 and 18, 3 and 19 and so on.
That worked for me concerning the settings of a register. But as I
told you, I do not know the reason.