wangt13
wangt13

Reputation: 1265

Failed to read ST-1232 I2C register during device probing

I am working on an embedded Linux system (kernel-5.10.188) where there is touch screen, whose touch panel IC is ST1232.
I want to read the firmware version of ST1232 by reading its I2C register of 0x0, but I failed to do that in its probing as follows.

Then, I changed its driver by reading I2C registers from within its IRQ handler, that worked, as follows.

--- a/kernel/kernel-5.10/drivers/input/touchscreen/st1232.c
+++ b/kernel/kernel-5.10/drivers/input/touchscreen/st1232.c
@@ -45,9 +45,36 @@ struct st1232_ts_data {
        struct gpio_desc *reset_gpio;
        const struct st_chip_info *chip_info;
        int read_buf_len;
+       u32  fw_rev;
        u8 *read_buf;
 };

+static int st1232_ts_read_ver(struct st1232_ts_data *ts)
+{
+       struct i2c_client *client = ts->client;
+       u8 start_reg = 0x0;
+       struct i2c_msg msg[] = {
+               {
+                       .addr   = client->addr,
+                       .len    = sizeof(start_reg),
+                       .buf    = &start_reg,
+               },
+               {
+                       .addr   = client->addr,
+                       .flags  = I2C_M_RD | I2C_M_DMA_SAFE,
+                       .len    = 1,
+                       .buf    = (u8 *)&ts->fw_rev,
+               }
+       };
+       int ret;
+
+       ret = i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg));
+       if (ret != ARRAY_SIZE(msg))
+               return ret < 0 ? ret : -EIO;
+
+       return 0;
+}
+
 static int st1232_ts_read_data(struct st1232_ts_data *ts)
 {
        struct i2c_client *client = ts->client;
@@ -122,11 +149,19 @@ static irqreturn_t st1232_ts_irq_handler(int irq, void *dev_id)
        struct st1232_ts_data *ts = dev_id;
        int count;
        int error;
+static int xx = 0;

        error = st1232_ts_read_data(ts);
        if (error)
                goto out;

+if (xx < 5) {
+    error = st1232_ts_read_ver(ts);
+       memcpy(&ts->input_dev->id.version, &ts->fw_rev, 2);
+       printk("xxxxxxxxxxxxx fw_rev: 0x%x, error: %d\n", ts->fw_rev, error);
+}
+xx++;
+
        count = st1232_ts_parse_and_report(ts);
        if (!count) {
                if (ts->low_latency_req.dev) {
@@ -276,6 +311,9 @@ static int st1232_ts_probe(struct i2c_client *client,

        i2c_set_clientdata(client, ts);

+    error = st1232_ts_read_ver(ts);
+       memcpy(&ts->input_dev->id.version, &ts->fw_rev, 2);
+       printk("xxxxxxxxxxxxx fw_rev: 0x%x, error: %d\n", ts->fw_rev, error);
        return 0;
}

I got following kernel log.

# dmesg | grep xxxx
[    1.150101] xxxxxxxxxxxxx fw_rev: 0x0, error: -145
[    1.195555] xxxxxxxxxxxxx fw_rev: 0x6, error: 0

I don't know why it failed to read I2C register in the function of _probe, while it succeeded in the interrupt handler, what did I miss when reading the I2C register?

Upvotes: 2

Views: 58

Answers (0)

Related Questions