Reputation: 1265
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