OpenWrt Forum Archive

Topic: MT7620A i2c-driver doesn't work

The content of this topic has been archived on 10 Apr 2018. There are no obvious gaps in this topic, but there may still be some posts missing at the end.

I want read temperature from BMP180 to NetRouter(a development board base on mt7620a)  by i2c bus.

1. I modify mt7620a.dtsi to enable i2c device and rebuild openwrt with i2c support
mt7620a.dtsi file:
    http://www.kingxf.cc/modify-mt7620a-dtsi.png
menuconfig:
    http://www.kingxf.cc/menuconfig-support-i2c.png

2. Update openwrt system, and I can found /dev/i2c-0
3. I try to run my program but I keep get "i2c-read line busy"

my program:

#include <stdio.h>
#include <stdint.h>
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <string.h>
#define BMP180_I2C_ADDR                 (0xee)
#define BMP180_I2C_ADDR_R                 (BMP180_I2C_ADDR)
#define BMP180_I2C_ADDR_W                (BMP180_I2C_ADDR | 1)
#define BMP180_REG_ADDR_TEMPERATURE        (0x2E)
#define I2C_DEV_NAME                    "/dev/i2c-0"



static int set_i2c_register(int file,
                            unsigned char addr,
                            unsigned char reg,
                            unsigned char value) {

    unsigned char outbuf[2];
    struct i2c_rdwr_ioctl_data packets;
    struct i2c_msg messages[1];

    messages[0].addr  = addr;
    messages[0].flags = 0;
    messages[0].len   = sizeof(outbuf);
    messages[0].buf   = outbuf;

    /* The first byte indicates which register we'll write */
    outbuf[0] = reg;

    /* 
     * The second byte indicates the value to write.  Note that for many
     * devices, we can write multiple, sequential registers at once by
     * simply making outbuf bigger.
     */
    outbuf[1] = value;

    /* Transfer the i2c packets to the kernel and verify it worked */
    packets.msgs  = messages;
    packets.nmsgs = 1;
    if(ioctl(file, I2C_RDWR, &packets) < 0) {
        perror("Unable to send data");
        return 1;
    }

    return 0;
}


static int get_i2c_register(int file,
                            unsigned char addr,
                            unsigned char reg,
                            unsigned char *val) {
    unsigned char inbuf, outbuf;
    struct i2c_rdwr_ioctl_data packets;
    struct i2c_msg messages[2];

    /*
     * In order to read a register, we first do a "dummy write" by writing
     * 0 bytes to the register we want to read from.  This is similar to
     * the packet in set_i2c_register, except it's 1 byte rather than 2.
     */
    outbuf = reg;
    messages[0].addr  = addr;
    messages[0].flags = 0;
    messages[0].len   = sizeof(outbuf);
    messages[0].buf   = &outbuf;

    /* The data will get returned in this structure */
    messages[1].addr  = addr;
    messages[1].flags = I2C_M_RD/* | I2C_M_NOSTART*/;
    messages[1].len   = sizeof(inbuf);
    messages[1].buf   = &inbuf;

    /* Send the request to the kernel and get the result back */
    packets.msgs      = messages;
    packets.nmsgs     = 2;
    if(ioctl(file, I2C_RDWR, &packets) < 0) {
        perror("Unable to send data");
        return 1;
    }
    *val = inbuf;

    return 0;
}

int main()
{
    int fd_i2c = 0;
    int ret = -1;
    unsigned char val;
    fd_i2c = open(I2C_DEV_NAME, O_RDWR);
    if (fd_i2c < 0)
    {
        perror(I2C_DEV_NAME);
        goto clean;
    }
    
    while(1)
    {
        set_i2c_register(fd_i2c, BMP180_I2C_ADDR, 0xF4, 0x2E);
        get_i2c_register(fd_i2c, BMP180_I2C_ADDR, 0xF6, &val);
        printf("val: %d\n", val);
    }
    

    ret = 0;
clean:
    if (fd_i2c >= 0)
    {
        close(fd_i2c);
    }
    return ret;
}

My openwrt version:  15.05

Please help, thanks

Hi

please do

status = "ok";

Thanks, I solve it.

I didn't configure the i2c pin to i2c pinmux modeā€¦

elektroman wrote:

Hi

please do

status = "ok";

The discussion might have continued from here.