read i2c failure on u-boot-imx_2015.04

キャンセル
次の結果を表示 
表示  限定  | 次の代わりに検索 
もしかして: 

read i2c failure on u-boot-imx_2015.04

749件の閲覧回数
bba
Contributor III

Hello, there seams to be an error in the i2c read procedure inside u-boot-imx_2015.04.

We are using an security module connected via i2c. Read and write works well with the community based linux-fslc_4.4. But from u-boot we always got 0xFF reading the i2c device. A code analysis together with oscilloscope shows the difference.

  • In write direction it should be correct:

   bus_i2c_write()

   => ii2c_init_transfer(i2c_regs, chip, addr, alen)

   ===> i2c_init_transfer_(i2c_regs, chip, addr, alen)

   => i2c_write_data()

   The address will be set inside i2c_init_transfer_() with: tx_byte(i2c_regs, chip << 1)

  • In read direction we have a similar procedure:

   bus_i2c_read()

   => ii2c_init_transfer(i2c_regs, chip, addr, alen)

   ===> i2c_init_transfer_(i2c_regs, chip, addr, alen)

   => set address with tx_byte(i2c_regs, (chip << 1) | 1)

   => i2c_read_data()

   That means, the address will be set twice, first inside i2c_init_transfer_() with: tx_byte(i2c_regs, chip << 1) followed by tx_byte(i2c_regs, (chip << 1) | 1)

So the i2c device can't understand these wrong address setting and answer with 0xFF.

Following workaround works with our i2c security module. We are using an additional flag to distinguish between read and write.

   bus_i2c_write()

   => ii2c_init_transfer(i2c_regs, chip, addr, alen, 1)

   ===> i2c_init_transfer_(i2c_regs, chip, addr, alen, 1)

   bus_i2c_read()

   => ii2c_init_transfer(i2c_regs, chip, addr, alen, 0)

   ===> i2c_init_transfer_(i2c_regs, chip, addr, alen, 0)

static int i2c_init_transfer_(struct mxc_i2c_regs *i2c_regs,
        uchar chip, uint addr, int alen, int flag)
{

...

    if (flag) {
        /* write slave address */
        ret = tx_byte(i2c_regs, chip << 1);
        if (ret < 0)
            return ret;

        while (alen--) {
            ret = tx_byte(i2c_regs, (addr >> (alen * 8)) & 0xff);
            if (ret < 0)
                return ret;
        }
    }
    return 0;

}

Now the address (with write request) will be only written inside i2c_init_transfer_() if the flag is set.

Regards,

Birger

ラベル(2)
タグ(2)
0 件の賞賛
0 返答(返信)