109c434b8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 2c6ac8f0bSMarek Vasut #include <linux/crc-ccitt.h> 371f8e38aSDmitry Torokhov #include <linux/delay.h> 471f8e38aSDmitry Torokhov #include <linux/gpio/consumer.h> 55c6a7a62SOlivier Sobrie #include <linux/i2c.h> 6c6ac8f0bSMarek Vasut #include <linux/ihex.h> 75c6a7a62SOlivier Sobrie #include <linux/input.h> 85c6a7a62SOlivier Sobrie #include <linux/input/mt.h> 9f67cc3e9SMarek Vasut #include <linux/input/touchscreen.h> 1071f8e38aSDmitry Torokhov #include <linux/interrupt.h> 11*dbce1a7dSRob Herring #include <linux/mod_devicetable.h> 1271f8e38aSDmitry Torokhov #include <linux/module.h> 13b32fbeaeSSven Van Asbroeck #include <linux/sizes.h> 1471f8e38aSDmitry Torokhov #include <linux/slab.h> 15e3559442SMarek Vasut #include <asm/unaligned.h> 165c6a7a62SOlivier Sobrie 1727931d38SMarek Vasut #define ILI2XXX_POLL_PERIOD 15 185c6a7a62SOlivier Sobrie 19ef536abdSDmitry Torokhov #define ILI210X_DATA_SIZE 64 20ef536abdSDmitry Torokhov #define ILI211X_DATA_SIZE 43 21ef536abdSDmitry Torokhov #define ILI251X_DATA_SIZE1 31 22ef536abdSDmitry Torokhov #define ILI251X_DATA_SIZE2 20 23ef536abdSDmitry Torokhov 245c6a7a62SOlivier Sobrie /* Touchscreen commands */ 255c6a7a62SOlivier Sobrie #define REG_TOUCHDATA 0x10 265c6a7a62SOlivier Sobrie #define REG_PANEL_INFO 0x20 2770a7681dSMarek Vasut #define REG_FIRMWARE_VERSION 0x40 2870a7681dSMarek Vasut #define REG_PROTOCOL_VERSION 0x42 2970a7681dSMarek Vasut #define REG_KERNEL_VERSION 0x61 30c6ac8f0bSMarek Vasut #define REG_IC_BUSY 0x80 31c6ac8f0bSMarek Vasut #define REG_IC_BUSY_NOT_BUSY 0x50 3270a7681dSMarek Vasut #define REG_GET_MODE 0xc0 3370a7681dSMarek Vasut #define REG_GET_MODE_AP 0x5a 3470a7681dSMarek Vasut #define REG_GET_MODE_BL 0x55 35c6ac8f0bSMarek Vasut #define REG_SET_MODE_AP 0xc1 36c6ac8f0bSMarek Vasut #define REG_SET_MODE_BL 0xc2 37c6ac8f0bSMarek Vasut #define REG_WRITE_DATA 0xc3 38c6ac8f0bSMarek Vasut #define REG_WRITE_ENABLE 0xc4 39c6ac8f0bSMarek Vasut #define REG_READ_DATA_CRC 0xc7 405c6a7a62SOlivier Sobrie #define REG_CALIBRATE 0xcc 415c6a7a62SOlivier Sobrie 42c6ac8f0bSMarek Vasut #define ILI251X_FW_FILENAME "ilitek/ili251x.bin" 43c6ac8f0bSMarek Vasut 44ef536abdSDmitry Torokhov struct ili2xxx_chip { 45ef536abdSDmitry Torokhov int (*read_reg)(struct i2c_client *client, u8 reg, 46ef536abdSDmitry Torokhov void *buf, size_t len); 47ef536abdSDmitry Torokhov int (*get_touch_data)(struct i2c_client *client, u8 *data); 48ef536abdSDmitry Torokhov bool (*parse_touch_data)(const u8 *data, unsigned int finger, 4960159e9eSMarek Vasut unsigned int *x, unsigned int *y, 5060159e9eSMarek Vasut unsigned int *z); 51ef536abdSDmitry Torokhov bool (*continue_polling)(const u8 *data, bool touch); 52ef536abdSDmitry Torokhov unsigned int max_touches; 53b32fbeaeSSven Van Asbroeck unsigned int resolution; 54cc12ba18SSven Van Asbroeck bool has_calibrate_reg; 55235300edSMarek Vasut bool has_firmware_proto; 5660159e9eSMarek Vasut bool has_pressure_reg; 5749588917SMarek Vasut }; 5849588917SMarek Vasut 595c6a7a62SOlivier Sobrie struct ili210x { 605c6a7a62SOlivier Sobrie struct i2c_client *client; 615c6a7a62SOlivier Sobrie struct input_dev *input; 62201f3c80SMarek Vasut struct gpio_desc *reset_gpio; 63f67cc3e9SMarek Vasut struct touchscreen_properties prop; 64ef536abdSDmitry Torokhov const struct ili2xxx_chip *chip; 6570a7681dSMarek Vasut u8 version_firmware[8]; 6670a7681dSMarek Vasut u8 version_kernel[5]; 6770a7681dSMarek Vasut u8 version_proto[2]; 6870a7681dSMarek Vasut u8 ic_mode[2]; 6971f8e38aSDmitry Torokhov bool stop; 705c6a7a62SOlivier Sobrie }; 715c6a7a62SOlivier Sobrie 72ef536abdSDmitry Torokhov static int ili210x_read_reg(struct i2c_client *client, 73ef536abdSDmitry Torokhov u8 reg, void *buf, size_t len) 745c6a7a62SOlivier Sobrie { 75ef536abdSDmitry Torokhov struct i2c_msg msg[] = { 765c6a7a62SOlivier Sobrie { 775c6a7a62SOlivier Sobrie .addr = client->addr, 785c6a7a62SOlivier Sobrie .flags = 0, 795c6a7a62SOlivier Sobrie .len = 1, 805c6a7a62SOlivier Sobrie .buf = ®, 815c6a7a62SOlivier Sobrie }, 825c6a7a62SOlivier Sobrie { 835c6a7a62SOlivier Sobrie .addr = client->addr, 845c6a7a62SOlivier Sobrie .flags = I2C_M_RD, 855c6a7a62SOlivier Sobrie .len = len, 865c6a7a62SOlivier Sobrie .buf = buf, 875c6a7a62SOlivier Sobrie } 885c6a7a62SOlivier Sobrie }; 89ef536abdSDmitry Torokhov int error, ret; 905c6a7a62SOlivier Sobrie 91ef536abdSDmitry Torokhov ret = i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg)); 92ef536abdSDmitry Torokhov if (ret != ARRAY_SIZE(msg)) { 93ef536abdSDmitry Torokhov error = ret < 0 ? ret : -EIO; 94ef536abdSDmitry Torokhov dev_err(&client->dev, "%s failed: %d\n", __func__, error); 95ef536abdSDmitry Torokhov return error; 9649588917SMarek Vasut } 9749588917SMarek Vasut 9849588917SMarek Vasut return 0; 9949588917SMarek Vasut } 10049588917SMarek Vasut 101ef536abdSDmitry Torokhov static int ili210x_read_touch_data(struct i2c_client *client, u8 *data) 10249588917SMarek Vasut { 103ef536abdSDmitry Torokhov return ili210x_read_reg(client, REG_TOUCHDATA, 104ef536abdSDmitry Torokhov data, ILI210X_DATA_SIZE); 10549588917SMarek Vasut } 1065c6a7a62SOlivier Sobrie 107ef536abdSDmitry Torokhov static bool ili210x_touchdata_to_coords(const u8 *touchdata, 108e3559442SMarek Vasut unsigned int finger, 10960159e9eSMarek Vasut unsigned int *x, unsigned int *y, 11060159e9eSMarek Vasut unsigned int *z) 1115c6a7a62SOlivier Sobrie { 112ac05a8a9SHansem Ro if (!(touchdata[0] & BIT(finger))) 113e3559442SMarek Vasut return false; 114e3559442SMarek Vasut 115e3559442SMarek Vasut *x = get_unaligned_be16(touchdata + 1 + (finger * 4) + 0); 116e3559442SMarek Vasut *y = get_unaligned_be16(touchdata + 1 + (finger * 4) + 2); 117e3559442SMarek Vasut 118e3559442SMarek Vasut return true; 119e3559442SMarek Vasut } 120e3559442SMarek Vasut 121ef536abdSDmitry Torokhov static bool ili210x_check_continue_polling(const u8 *data, bool touch) 122ef536abdSDmitry Torokhov { 123ef536abdSDmitry Torokhov return data[0] & 0xf3; 124ef536abdSDmitry Torokhov } 125ef536abdSDmitry Torokhov 126ef536abdSDmitry Torokhov static const struct ili2xxx_chip ili210x_chip = { 127ef536abdSDmitry Torokhov .read_reg = ili210x_read_reg, 128ef536abdSDmitry Torokhov .get_touch_data = ili210x_read_touch_data, 129ef536abdSDmitry Torokhov .parse_touch_data = ili210x_touchdata_to_coords, 130ef536abdSDmitry Torokhov .continue_polling = ili210x_check_continue_polling, 131ef536abdSDmitry Torokhov .max_touches = 2, 132cc12ba18SSven Van Asbroeck .has_calibrate_reg = true, 133ef536abdSDmitry Torokhov }; 134ef536abdSDmitry Torokhov 135ef536abdSDmitry Torokhov static int ili211x_read_touch_data(struct i2c_client *client, u8 *data) 136ef536abdSDmitry Torokhov { 137ef536abdSDmitry Torokhov s16 sum = 0; 138ef536abdSDmitry Torokhov int error; 139ef536abdSDmitry Torokhov int ret; 140ef536abdSDmitry Torokhov int i; 141ef536abdSDmitry Torokhov 142ef536abdSDmitry Torokhov ret = i2c_master_recv(client, data, ILI211X_DATA_SIZE); 143ef536abdSDmitry Torokhov if (ret != ILI211X_DATA_SIZE) { 144ef536abdSDmitry Torokhov error = ret < 0 ? ret : -EIO; 145ef536abdSDmitry Torokhov dev_err(&client->dev, "%s failed: %d\n", __func__, error); 146ef536abdSDmitry Torokhov return error; 147ef536abdSDmitry Torokhov } 148ef536abdSDmitry Torokhov 149ef536abdSDmitry Torokhov /* This chip uses custom checksum at the end of data */ 150ef536abdSDmitry Torokhov for (i = 0; i < ILI211X_DATA_SIZE - 1; i++) 151ef536abdSDmitry Torokhov sum = (sum + data[i]) & 0xff; 152ef536abdSDmitry Torokhov 153ef536abdSDmitry Torokhov if ((-sum & 0xff) != data[ILI211X_DATA_SIZE - 1]) { 154ef536abdSDmitry Torokhov dev_err(&client->dev, 155ef536abdSDmitry Torokhov "CRC error (crc=0x%02x expected=0x%02x)\n", 156ef536abdSDmitry Torokhov sum, data[ILI211X_DATA_SIZE - 1]); 157ef536abdSDmitry Torokhov return -EIO; 158ef536abdSDmitry Torokhov } 159ef536abdSDmitry Torokhov 160ef536abdSDmitry Torokhov return 0; 161ef536abdSDmitry Torokhov } 162ef536abdSDmitry Torokhov 163ef536abdSDmitry Torokhov static bool ili211x_touchdata_to_coords(const u8 *touchdata, 164eb91ecc9SMarek Vasut unsigned int finger, 16560159e9eSMarek Vasut unsigned int *x, unsigned int *y, 16660159e9eSMarek Vasut unsigned int *z) 167eb91ecc9SMarek Vasut { 168eb91ecc9SMarek Vasut u32 data; 169eb91ecc9SMarek Vasut 170eb91ecc9SMarek Vasut data = get_unaligned_be32(touchdata + 1 + (finger * 4) + 0); 171eb91ecc9SMarek Vasut if (data == 0xffffffff) /* Finger up */ 172eb91ecc9SMarek Vasut return false; 173eb91ecc9SMarek Vasut 174eb91ecc9SMarek Vasut *x = ((touchdata[1 + (finger * 4) + 0] & 0xf0) << 4) | 175eb91ecc9SMarek Vasut touchdata[1 + (finger * 4) + 1]; 176eb91ecc9SMarek Vasut *y = ((touchdata[1 + (finger * 4) + 0] & 0x0f) << 8) | 177eb91ecc9SMarek Vasut touchdata[1 + (finger * 4) + 2]; 178eb91ecc9SMarek Vasut 179eb91ecc9SMarek Vasut return true; 180eb91ecc9SMarek Vasut } 181eb91ecc9SMarek Vasut 182ef536abdSDmitry Torokhov static bool ili211x_decline_polling(const u8 *data, bool touch) 183ef536abdSDmitry Torokhov { 184ef536abdSDmitry Torokhov return false; 185ef536abdSDmitry Torokhov } 186ef536abdSDmitry Torokhov 187ef536abdSDmitry Torokhov static const struct ili2xxx_chip ili211x_chip = { 188ef536abdSDmitry Torokhov .read_reg = ili210x_read_reg, 189ef536abdSDmitry Torokhov .get_touch_data = ili211x_read_touch_data, 190ef536abdSDmitry Torokhov .parse_touch_data = ili211x_touchdata_to_coords, 191ef536abdSDmitry Torokhov .continue_polling = ili211x_decline_polling, 192ef536abdSDmitry Torokhov .max_touches = 10, 193b32fbeaeSSven Van Asbroeck .resolution = 2048, 194ef536abdSDmitry Torokhov }; 195ef536abdSDmitry Torokhov 196d0c5e7d4SLuca Weiss static bool ili212x_touchdata_to_coords(const u8 *touchdata, 197d0c5e7d4SLuca Weiss unsigned int finger, 19860159e9eSMarek Vasut unsigned int *x, unsigned int *y, 19960159e9eSMarek Vasut unsigned int *z) 200d0c5e7d4SLuca Weiss { 201d0c5e7d4SLuca Weiss u16 val; 202d0c5e7d4SLuca Weiss 203d0c5e7d4SLuca Weiss val = get_unaligned_be16(touchdata + 3 + (finger * 5) + 0); 204d0c5e7d4SLuca Weiss if (!(val & BIT(15))) /* Touch indication */ 205d0c5e7d4SLuca Weiss return false; 206d0c5e7d4SLuca Weiss 207d0c5e7d4SLuca Weiss *x = val & 0x3fff; 208d0c5e7d4SLuca Weiss *y = get_unaligned_be16(touchdata + 3 + (finger * 5) + 2); 209d0c5e7d4SLuca Weiss 210d0c5e7d4SLuca Weiss return true; 211d0c5e7d4SLuca Weiss } 212d0c5e7d4SLuca Weiss 213d0c5e7d4SLuca Weiss static bool ili212x_check_continue_polling(const u8 *data, bool touch) 214d0c5e7d4SLuca Weiss { 215d0c5e7d4SLuca Weiss return touch; 216d0c5e7d4SLuca Weiss } 217d0c5e7d4SLuca Weiss 218d0c5e7d4SLuca Weiss static const struct ili2xxx_chip ili212x_chip = { 219d0c5e7d4SLuca Weiss .read_reg = ili210x_read_reg, 220d0c5e7d4SLuca Weiss .get_touch_data = ili210x_read_touch_data, 221d0c5e7d4SLuca Weiss .parse_touch_data = ili212x_touchdata_to_coords, 222d0c5e7d4SLuca Weiss .continue_polling = ili212x_check_continue_polling, 223d0c5e7d4SLuca Weiss .max_touches = 10, 224d0c5e7d4SLuca Weiss .has_calibrate_reg = true, 225d0c5e7d4SLuca Weiss }; 226d0c5e7d4SLuca Weiss 227de889108SMarek Vasut static int ili251x_read_reg_common(struct i2c_client *client, 228de889108SMarek Vasut u8 reg, void *buf, size_t len, 229de889108SMarek Vasut unsigned int delay) 230ef536abdSDmitry Torokhov { 231ef536abdSDmitry Torokhov int error; 232ef536abdSDmitry Torokhov int ret; 233ef536abdSDmitry Torokhov 234ef536abdSDmitry Torokhov ret = i2c_master_send(client, ®, 1); 235ef536abdSDmitry Torokhov if (ret == 1) { 236de889108SMarek Vasut if (delay) 237de889108SMarek Vasut usleep_range(delay, delay + 500); 238ef536abdSDmitry Torokhov 239ef536abdSDmitry Torokhov ret = i2c_master_recv(client, buf, len); 240ef536abdSDmitry Torokhov if (ret == len) 241ef536abdSDmitry Torokhov return 0; 242ef536abdSDmitry Torokhov } 243ef536abdSDmitry Torokhov 244ef536abdSDmitry Torokhov error = ret < 0 ? ret : -EIO; 245ef536abdSDmitry Torokhov dev_err(&client->dev, "%s failed: %d\n", __func__, error); 246ef536abdSDmitry Torokhov return ret; 247ef536abdSDmitry Torokhov } 248ef536abdSDmitry Torokhov 249de889108SMarek Vasut static int ili251x_read_reg(struct i2c_client *client, 250de889108SMarek Vasut u8 reg, void *buf, size_t len) 251de889108SMarek Vasut { 252de889108SMarek Vasut return ili251x_read_reg_common(client, reg, buf, len, 5000); 253de889108SMarek Vasut } 254de889108SMarek Vasut 255ef536abdSDmitry Torokhov static int ili251x_read_touch_data(struct i2c_client *client, u8 *data) 256ef536abdSDmitry Torokhov { 257ef536abdSDmitry Torokhov int error; 258ef536abdSDmitry Torokhov 259de889108SMarek Vasut error = ili251x_read_reg_common(client, REG_TOUCHDATA, 260de889108SMarek Vasut data, ILI251X_DATA_SIZE1, 0); 261ef536abdSDmitry Torokhov if (!error && data[0] == 2) { 262ef536abdSDmitry Torokhov error = i2c_master_recv(client, data + ILI251X_DATA_SIZE1, 263ef536abdSDmitry Torokhov ILI251X_DATA_SIZE2); 264ef536abdSDmitry Torokhov if (error >= 0 && error != ILI251X_DATA_SIZE2) 265ef536abdSDmitry Torokhov error = -EIO; 266ef536abdSDmitry Torokhov } 267ef536abdSDmitry Torokhov 268ef536abdSDmitry Torokhov return error; 269ef536abdSDmitry Torokhov } 270ef536abdSDmitry Torokhov 271ef536abdSDmitry Torokhov static bool ili251x_touchdata_to_coords(const u8 *touchdata, 27249588917SMarek Vasut unsigned int finger, 27360159e9eSMarek Vasut unsigned int *x, unsigned int *y, 27460159e9eSMarek Vasut unsigned int *z) 27549588917SMarek Vasut { 276ef536abdSDmitry Torokhov u16 val; 277ef536abdSDmitry Torokhov 278ef536abdSDmitry Torokhov val = get_unaligned_be16(touchdata + 1 + (finger * 5) + 0); 279ef536abdSDmitry Torokhov if (!(val & BIT(15))) /* Touch indication */ 28049588917SMarek Vasut return false; 28149588917SMarek Vasut 282ef536abdSDmitry Torokhov *x = val & 0x3fff; 28349588917SMarek Vasut *y = get_unaligned_be16(touchdata + 1 + (finger * 5) + 2); 28460159e9eSMarek Vasut *z = touchdata[1 + (finger * 5) + 4]; 28549588917SMarek Vasut 28649588917SMarek Vasut return true; 28749588917SMarek Vasut } 28849588917SMarek Vasut 289ef536abdSDmitry Torokhov static bool ili251x_check_continue_polling(const u8 *data, bool touch) 290ef536abdSDmitry Torokhov { 291ef536abdSDmitry Torokhov return touch; 292ef536abdSDmitry Torokhov } 293ef536abdSDmitry Torokhov 294ef536abdSDmitry Torokhov static const struct ili2xxx_chip ili251x_chip = { 295ef536abdSDmitry Torokhov .read_reg = ili251x_read_reg, 296ef536abdSDmitry Torokhov .get_touch_data = ili251x_read_touch_data, 297ef536abdSDmitry Torokhov .parse_touch_data = ili251x_touchdata_to_coords, 298ef536abdSDmitry Torokhov .continue_polling = ili251x_check_continue_polling, 299ef536abdSDmitry Torokhov .max_touches = 10, 300cc12ba18SSven Van Asbroeck .has_calibrate_reg = true, 301235300edSMarek Vasut .has_firmware_proto = true, 30260159e9eSMarek Vasut .has_pressure_reg = true, 303ef536abdSDmitry Torokhov }; 304ef536abdSDmitry Torokhov 305e3559442SMarek Vasut static bool ili210x_report_events(struct ili210x *priv, u8 *touchdata) 306e3559442SMarek Vasut { 307e3559442SMarek Vasut struct input_dev *input = priv->input; 3085c6a7a62SOlivier Sobrie int i; 309ef536abdSDmitry Torokhov bool contact = false, touch; 31060159e9eSMarek Vasut unsigned int x = 0, y = 0, z = 0; 3115c6a7a62SOlivier Sobrie 312ef536abdSDmitry Torokhov for (i = 0; i < priv->chip->max_touches; i++) { 31360159e9eSMarek Vasut touch = priv->chip->parse_touch_data(touchdata, i, &x, &y, &z); 31449588917SMarek Vasut 315f67cc3e9SMarek Vasut input_mt_slot(input, i); 316ef536abdSDmitry Torokhov if (input_mt_report_slot_state(input, MT_TOOL_FINGER, touch)) { 317ef536abdSDmitry Torokhov touchscreen_report_pos(input, &priv->prop, x, y, true); 31860159e9eSMarek Vasut if (priv->chip->has_pressure_reg) 31960159e9eSMarek Vasut input_report_abs(input, ABS_MT_PRESSURE, z); 320ef536abdSDmitry Torokhov contact = true; 321ef536abdSDmitry Torokhov } 3225c6a7a62SOlivier Sobrie } 3235c6a7a62SOlivier Sobrie 3245c6a7a62SOlivier Sobrie input_mt_report_pointer_emulation(input, false); 3255c6a7a62SOlivier Sobrie input_sync(input); 326e3559442SMarek Vasut 32749588917SMarek Vasut return contact; 3285c6a7a62SOlivier Sobrie } 3295c6a7a62SOlivier Sobrie 33071f8e38aSDmitry Torokhov static irqreturn_t ili210x_irq(int irq, void *irq_data) 3315c6a7a62SOlivier Sobrie { 33271f8e38aSDmitry Torokhov struct ili210x *priv = irq_data; 3335c6a7a62SOlivier Sobrie struct i2c_client *client = priv->client; 334ef536abdSDmitry Torokhov const struct ili2xxx_chip *chip = priv->chip; 335ef536abdSDmitry Torokhov u8 touchdata[ILI210X_DATA_SIZE] = { 0 }; 336ef536abdSDmitry Torokhov bool keep_polling; 3378639e042SMarek Vasut ktime_t time_next; 3388639e042SMarek Vasut s64 time_delta; 339e3559442SMarek Vasut bool touch; 34071f8e38aSDmitry Torokhov int error; 3415c6a7a62SOlivier Sobrie 34271f8e38aSDmitry Torokhov do { 3438639e042SMarek Vasut time_next = ktime_add_ms(ktime_get(), ILI2XXX_POLL_PERIOD); 344ef536abdSDmitry Torokhov error = chip->get_touch_data(client, touchdata); 3455c6a7a62SOlivier Sobrie if (error) { 3465c6a7a62SOlivier Sobrie dev_err(&client->dev, 347ef536abdSDmitry Torokhov "Unable to get touch data: %d\n", error); 34871f8e38aSDmitry Torokhov break; 3495c6a7a62SOlivier Sobrie } 3505c6a7a62SOlivier Sobrie 351e3559442SMarek Vasut touch = ili210x_report_events(priv, touchdata); 352ef536abdSDmitry Torokhov keep_polling = chip->continue_polling(touchdata, touch); 3538639e042SMarek Vasut if (keep_polling) { 3548639e042SMarek Vasut time_delta = ktime_us_delta(time_next, ktime_get()); 3558639e042SMarek Vasut if (time_delta > 0) 3568639e042SMarek Vasut usleep_range(time_delta, time_delta + 1000); 3578639e042SMarek Vasut } 358ef536abdSDmitry Torokhov } while (!priv->stop && keep_polling); 3595c6a7a62SOlivier Sobrie 3605c6a7a62SOlivier Sobrie return IRQ_HANDLED; 3615c6a7a62SOlivier Sobrie } 3625c6a7a62SOlivier Sobrie 363235300edSMarek Vasut static int ili251x_firmware_update_resolution(struct device *dev) 364235300edSMarek Vasut { 365235300edSMarek Vasut struct i2c_client *client = to_i2c_client(dev); 366235300edSMarek Vasut struct ili210x *priv = i2c_get_clientdata(client); 367235300edSMarek Vasut u16 resx, resy; 368235300edSMarek Vasut u8 rs[10]; 369235300edSMarek Vasut int error; 370235300edSMarek Vasut 371235300edSMarek Vasut /* The firmware update blob might have changed the resolution. */ 372235300edSMarek Vasut error = priv->chip->read_reg(client, REG_PANEL_INFO, &rs, sizeof(rs)); 373e1141b0cSMarek Vasut if (!error) { 374235300edSMarek Vasut resx = le16_to_cpup((__le16 *)rs); 375235300edSMarek Vasut resy = le16_to_cpup((__le16 *)(rs + 2)); 376235300edSMarek Vasut 377235300edSMarek Vasut /* The value reported by the firmware is invalid. */ 378235300edSMarek Vasut if (!resx || resx == 0xffff || !resy || resy == 0xffff) 379e1141b0cSMarek Vasut error = -EINVAL; 380e1141b0cSMarek Vasut } 381e1141b0cSMarek Vasut 382e1141b0cSMarek Vasut /* 383e1141b0cSMarek Vasut * In case of error, the firmware might be stuck in bootloader mode, 384e1141b0cSMarek Vasut * e.g. after a failed firmware update. Set maximum resolution, but 385e1141b0cSMarek Vasut * do not fail to probe, so the user can re-trigger the firmware 386e1141b0cSMarek Vasut * update and recover the touch controller. 387e1141b0cSMarek Vasut */ 388e1141b0cSMarek Vasut if (error) { 389e1141b0cSMarek Vasut dev_warn(dev, "Invalid resolution reported by controller.\n"); 390e1141b0cSMarek Vasut resx = 16384; 391e1141b0cSMarek Vasut resy = 16384; 392e1141b0cSMarek Vasut } 393235300edSMarek Vasut 394235300edSMarek Vasut input_abs_set_max(priv->input, ABS_X, resx - 1); 395235300edSMarek Vasut input_abs_set_max(priv->input, ABS_Y, resy - 1); 396235300edSMarek Vasut input_abs_set_max(priv->input, ABS_MT_POSITION_X, resx - 1); 397235300edSMarek Vasut input_abs_set_max(priv->input, ABS_MT_POSITION_Y, resy - 1); 398235300edSMarek Vasut 399e1141b0cSMarek Vasut return error; 400235300edSMarek Vasut } 401235300edSMarek Vasut 40270a7681dSMarek Vasut static ssize_t ili251x_firmware_update_firmware_version(struct device *dev) 40370a7681dSMarek Vasut { 40470a7681dSMarek Vasut struct i2c_client *client = to_i2c_client(dev); 40570a7681dSMarek Vasut struct ili210x *priv = i2c_get_clientdata(client); 40670a7681dSMarek Vasut int error; 40770a7681dSMarek Vasut u8 fw[8]; 40870a7681dSMarek Vasut 40970a7681dSMarek Vasut /* Get firmware version */ 41070a7681dSMarek Vasut error = priv->chip->read_reg(client, REG_FIRMWARE_VERSION, 41170a7681dSMarek Vasut &fw, sizeof(fw)); 41270a7681dSMarek Vasut if (!error) 41370a7681dSMarek Vasut memcpy(priv->version_firmware, fw, sizeof(fw)); 41470a7681dSMarek Vasut 41570a7681dSMarek Vasut return error; 41670a7681dSMarek Vasut } 41770a7681dSMarek Vasut 41870a7681dSMarek Vasut static ssize_t ili251x_firmware_update_kernel_version(struct device *dev) 41970a7681dSMarek Vasut { 42070a7681dSMarek Vasut struct i2c_client *client = to_i2c_client(dev); 42170a7681dSMarek Vasut struct ili210x *priv = i2c_get_clientdata(client); 42270a7681dSMarek Vasut int error; 42370a7681dSMarek Vasut u8 kv[5]; 42470a7681dSMarek Vasut 42570a7681dSMarek Vasut /* Get kernel version */ 42670a7681dSMarek Vasut error = priv->chip->read_reg(client, REG_KERNEL_VERSION, 42770a7681dSMarek Vasut &kv, sizeof(kv)); 42870a7681dSMarek Vasut if (!error) 42970a7681dSMarek Vasut memcpy(priv->version_kernel, kv, sizeof(kv)); 43070a7681dSMarek Vasut 43170a7681dSMarek Vasut return error; 43270a7681dSMarek Vasut } 43370a7681dSMarek Vasut 43470a7681dSMarek Vasut static ssize_t ili251x_firmware_update_protocol_version(struct device *dev) 43570a7681dSMarek Vasut { 43670a7681dSMarek Vasut struct i2c_client *client = to_i2c_client(dev); 43770a7681dSMarek Vasut struct ili210x *priv = i2c_get_clientdata(client); 43870a7681dSMarek Vasut int error; 43970a7681dSMarek Vasut u8 pv[2]; 44070a7681dSMarek Vasut 44170a7681dSMarek Vasut /* Get protocol version */ 44270a7681dSMarek Vasut error = priv->chip->read_reg(client, REG_PROTOCOL_VERSION, 44370a7681dSMarek Vasut &pv, sizeof(pv)); 44470a7681dSMarek Vasut if (!error) 44570a7681dSMarek Vasut memcpy(priv->version_proto, pv, sizeof(pv)); 44670a7681dSMarek Vasut 44770a7681dSMarek Vasut return error; 44870a7681dSMarek Vasut } 44970a7681dSMarek Vasut 45070a7681dSMarek Vasut static ssize_t ili251x_firmware_update_ic_mode(struct device *dev) 45170a7681dSMarek Vasut { 45270a7681dSMarek Vasut struct i2c_client *client = to_i2c_client(dev); 45370a7681dSMarek Vasut struct ili210x *priv = i2c_get_clientdata(client); 45470a7681dSMarek Vasut int error; 45570a7681dSMarek Vasut u8 md[2]; 45670a7681dSMarek Vasut 45770a7681dSMarek Vasut /* Get chip boot mode */ 45870a7681dSMarek Vasut error = priv->chip->read_reg(client, REG_GET_MODE, &md, sizeof(md)); 45970a7681dSMarek Vasut if (!error) 46070a7681dSMarek Vasut memcpy(priv->ic_mode, md, sizeof(md)); 46170a7681dSMarek Vasut 46270a7681dSMarek Vasut return error; 46370a7681dSMarek Vasut } 46470a7681dSMarek Vasut 465235300edSMarek Vasut static int ili251x_firmware_update_cached_state(struct device *dev) 466235300edSMarek Vasut { 467235300edSMarek Vasut struct i2c_client *client = to_i2c_client(dev); 468235300edSMarek Vasut struct ili210x *priv = i2c_get_clientdata(client); 469235300edSMarek Vasut int error; 470235300edSMarek Vasut 471235300edSMarek Vasut if (!priv->chip->has_firmware_proto) 472235300edSMarek Vasut return 0; 473235300edSMarek Vasut 474235300edSMarek Vasut /* Wait for firmware to boot and stabilize itself. */ 475235300edSMarek Vasut msleep(200); 476235300edSMarek Vasut 477235300edSMarek Vasut /* Firmware does report valid information. */ 478235300edSMarek Vasut error = ili251x_firmware_update_resolution(dev); 479235300edSMarek Vasut if (error) 480235300edSMarek Vasut return error; 481235300edSMarek Vasut 48270a7681dSMarek Vasut error = ili251x_firmware_update_firmware_version(dev); 48370a7681dSMarek Vasut if (error) 48470a7681dSMarek Vasut return error; 48570a7681dSMarek Vasut 48670a7681dSMarek Vasut error = ili251x_firmware_update_kernel_version(dev); 48770a7681dSMarek Vasut if (error) 48870a7681dSMarek Vasut return error; 48970a7681dSMarek Vasut 49070a7681dSMarek Vasut error = ili251x_firmware_update_protocol_version(dev); 49170a7681dSMarek Vasut if (error) 49270a7681dSMarek Vasut return error; 49370a7681dSMarek Vasut 49470a7681dSMarek Vasut error = ili251x_firmware_update_ic_mode(dev); 49570a7681dSMarek Vasut if (error) 49670a7681dSMarek Vasut return error; 49770a7681dSMarek Vasut 498235300edSMarek Vasut return 0; 499235300edSMarek Vasut } 500235300edSMarek Vasut 50170a7681dSMarek Vasut static ssize_t ili251x_firmware_version_show(struct device *dev, 50270a7681dSMarek Vasut struct device_attribute *attr, 50370a7681dSMarek Vasut char *buf) 50470a7681dSMarek Vasut { 50570a7681dSMarek Vasut struct i2c_client *client = to_i2c_client(dev); 50670a7681dSMarek Vasut struct ili210x *priv = i2c_get_clientdata(client); 50770a7681dSMarek Vasut u8 *fw = priv->version_firmware; 50870a7681dSMarek Vasut 50970a7681dSMarek Vasut return sysfs_emit(buf, "%02x%02x.%02x%02x.%02x%02x.%02x%02x\n", 51070a7681dSMarek Vasut fw[0], fw[1], fw[2], fw[3], 51170a7681dSMarek Vasut fw[4], fw[5], fw[6], fw[7]); 51270a7681dSMarek Vasut } 51370a7681dSMarek Vasut static DEVICE_ATTR(firmware_version, 0444, ili251x_firmware_version_show, NULL); 51470a7681dSMarek Vasut 51570a7681dSMarek Vasut static ssize_t ili251x_kernel_version_show(struct device *dev, 51670a7681dSMarek Vasut struct device_attribute *attr, 51770a7681dSMarek Vasut char *buf) 51870a7681dSMarek Vasut { 51970a7681dSMarek Vasut struct i2c_client *client = to_i2c_client(dev); 52070a7681dSMarek Vasut struct ili210x *priv = i2c_get_clientdata(client); 52170a7681dSMarek Vasut u8 *kv = priv->version_kernel; 52270a7681dSMarek Vasut 52370a7681dSMarek Vasut return sysfs_emit(buf, "%02x.%02x.%02x.%02x.%02x\n", 52470a7681dSMarek Vasut kv[0], kv[1], kv[2], kv[3], kv[4]); 52570a7681dSMarek Vasut } 52670a7681dSMarek Vasut static DEVICE_ATTR(kernel_version, 0444, ili251x_kernel_version_show, NULL); 52770a7681dSMarek Vasut 52870a7681dSMarek Vasut static ssize_t ili251x_protocol_version_show(struct device *dev, 52970a7681dSMarek Vasut struct device_attribute *attr, 53070a7681dSMarek Vasut char *buf) 53170a7681dSMarek Vasut { 53270a7681dSMarek Vasut struct i2c_client *client = to_i2c_client(dev); 53370a7681dSMarek Vasut struct ili210x *priv = i2c_get_clientdata(client); 53470a7681dSMarek Vasut u8 *pv = priv->version_proto; 53570a7681dSMarek Vasut 53670a7681dSMarek Vasut return sysfs_emit(buf, "%02x.%02x\n", pv[0], pv[1]); 53770a7681dSMarek Vasut } 53870a7681dSMarek Vasut static DEVICE_ATTR(protocol_version, 0444, ili251x_protocol_version_show, NULL); 53970a7681dSMarek Vasut 54070a7681dSMarek Vasut static ssize_t ili251x_mode_show(struct device *dev, 54170a7681dSMarek Vasut struct device_attribute *attr, char *buf) 54270a7681dSMarek Vasut { 54370a7681dSMarek Vasut struct i2c_client *client = to_i2c_client(dev); 54470a7681dSMarek Vasut struct ili210x *priv = i2c_get_clientdata(client); 54570a7681dSMarek Vasut u8 *md = priv->ic_mode; 54670a7681dSMarek Vasut char *mode = "AP"; 54770a7681dSMarek Vasut 54870a7681dSMarek Vasut if (md[0] == REG_GET_MODE_AP) /* Application Mode */ 54970a7681dSMarek Vasut mode = "AP"; 55070a7681dSMarek Vasut else if (md[0] == REG_GET_MODE_BL) /* BootLoader Mode */ 55170a7681dSMarek Vasut mode = "BL"; 55270a7681dSMarek Vasut else /* Unknown Mode */ 55370a7681dSMarek Vasut mode = "??"; 55470a7681dSMarek Vasut 55570a7681dSMarek Vasut return sysfs_emit(buf, "%02x.%02x:%s\n", md[0], md[1], mode); 55670a7681dSMarek Vasut } 55770a7681dSMarek Vasut static DEVICE_ATTR(mode, 0444, ili251x_mode_show, NULL); 55870a7681dSMarek Vasut 5595c6a7a62SOlivier Sobrie static ssize_t ili210x_calibrate(struct device *dev, 5605c6a7a62SOlivier Sobrie struct device_attribute *attr, 5615c6a7a62SOlivier Sobrie const char *buf, size_t count) 5625c6a7a62SOlivier Sobrie { 5635c6a7a62SOlivier Sobrie struct i2c_client *client = to_i2c_client(dev); 5645c6a7a62SOlivier Sobrie struct ili210x *priv = i2c_get_clientdata(client); 5655c6a7a62SOlivier Sobrie unsigned long calibrate; 5665c6a7a62SOlivier Sobrie int rc; 5675c6a7a62SOlivier Sobrie u8 cmd = REG_CALIBRATE; 5685c6a7a62SOlivier Sobrie 5695c6a7a62SOlivier Sobrie if (kstrtoul(buf, 10, &calibrate)) 5705c6a7a62SOlivier Sobrie return -EINVAL; 5715c6a7a62SOlivier Sobrie 5725c6a7a62SOlivier Sobrie if (calibrate > 1) 5735c6a7a62SOlivier Sobrie return -EINVAL; 5745c6a7a62SOlivier Sobrie 5755c6a7a62SOlivier Sobrie if (calibrate) { 5765c6a7a62SOlivier Sobrie rc = i2c_master_send(priv->client, &cmd, sizeof(cmd)); 5775c6a7a62SOlivier Sobrie if (rc != sizeof(cmd)) 5785c6a7a62SOlivier Sobrie return -EIO; 5795c6a7a62SOlivier Sobrie } 5805c6a7a62SOlivier Sobrie 5815c6a7a62SOlivier Sobrie return count; 5825c6a7a62SOlivier Sobrie } 583b27c0d0cSDmitry Torokhov static DEVICE_ATTR(calibrate, S_IWUSR, NULL, ili210x_calibrate); 5845c6a7a62SOlivier Sobrie 585c6ac8f0bSMarek Vasut static int ili251x_firmware_to_buffer(const struct firmware *fw, 586c6ac8f0bSMarek Vasut u8 **buf, u16 *ac_end, u16 *df_end) 587c6ac8f0bSMarek Vasut { 588c6ac8f0bSMarek Vasut const struct ihex_binrec *rec; 589c6ac8f0bSMarek Vasut u32 fw_addr, fw_last_addr = 0; 590c6ac8f0bSMarek Vasut u16 fw_len; 591c6ac8f0bSMarek Vasut u8 *fw_buf; 592c6ac8f0bSMarek Vasut int error; 593c6ac8f0bSMarek Vasut 594c6ac8f0bSMarek Vasut /* 595c6ac8f0bSMarek Vasut * The firmware ihex blob can never be bigger than 64 kiB, so make this 596c6ac8f0bSMarek Vasut * simple -- allocate a 64 kiB buffer, iterate over the ihex blob records 597c6ac8f0bSMarek Vasut * once, copy them all into this buffer at the right locations, and then 598c6ac8f0bSMarek Vasut * do all operations on this linear buffer. 599c6ac8f0bSMarek Vasut */ 600c6ac8f0bSMarek Vasut fw_buf = kzalloc(SZ_64K, GFP_KERNEL); 601c6ac8f0bSMarek Vasut if (!fw_buf) 602c6ac8f0bSMarek Vasut return -ENOMEM; 603c6ac8f0bSMarek Vasut 604c6ac8f0bSMarek Vasut rec = (const struct ihex_binrec *)fw->data; 605c6ac8f0bSMarek Vasut while (rec) { 606c6ac8f0bSMarek Vasut fw_addr = be32_to_cpu(rec->addr); 607c6ac8f0bSMarek Vasut fw_len = be16_to_cpu(rec->len); 608c6ac8f0bSMarek Vasut 609c6ac8f0bSMarek Vasut /* The last 32 Byte firmware block can be 0xffe0 */ 610c6ac8f0bSMarek Vasut if (fw_addr + fw_len > SZ_64K || fw_addr > SZ_64K - 32) { 611c6ac8f0bSMarek Vasut error = -EFBIG; 612c6ac8f0bSMarek Vasut goto err_big; 613c6ac8f0bSMarek Vasut } 614c6ac8f0bSMarek Vasut 615c6ac8f0bSMarek Vasut /* Find the last address before DF start address, that is AC end */ 616c6ac8f0bSMarek Vasut if (fw_addr == 0xf000) 617c6ac8f0bSMarek Vasut *ac_end = fw_last_addr; 618c6ac8f0bSMarek Vasut fw_last_addr = fw_addr + fw_len; 619c6ac8f0bSMarek Vasut 620c6ac8f0bSMarek Vasut memcpy(fw_buf + fw_addr, rec->data, fw_len); 621c6ac8f0bSMarek Vasut rec = ihex_next_binrec(rec); 622c6ac8f0bSMarek Vasut } 623c6ac8f0bSMarek Vasut 624c6ac8f0bSMarek Vasut /* DF end address is the last address in the firmware blob */ 625c6ac8f0bSMarek Vasut *df_end = fw_addr + fw_len; 626c6ac8f0bSMarek Vasut *buf = fw_buf; 627c6ac8f0bSMarek Vasut return 0; 628c6ac8f0bSMarek Vasut 629c6ac8f0bSMarek Vasut err_big: 630c6ac8f0bSMarek Vasut kfree(fw_buf); 631c6ac8f0bSMarek Vasut return error; 632c6ac8f0bSMarek Vasut } 633c6ac8f0bSMarek Vasut 634c6ac8f0bSMarek Vasut /* Switch mode between Application and BootLoader */ 635c6ac8f0bSMarek Vasut static int ili251x_switch_ic_mode(struct i2c_client *client, u8 cmd_mode) 636c6ac8f0bSMarek Vasut { 637c6ac8f0bSMarek Vasut struct ili210x *priv = i2c_get_clientdata(client); 638c6ac8f0bSMarek Vasut u8 cmd_wren[3] = { REG_WRITE_ENABLE, 0x5a, 0xa5 }; 639c6ac8f0bSMarek Vasut u8 md[2]; 640c6ac8f0bSMarek Vasut int error; 641c6ac8f0bSMarek Vasut 642c6ac8f0bSMarek Vasut error = priv->chip->read_reg(client, REG_GET_MODE, md, sizeof(md)); 643c6ac8f0bSMarek Vasut if (error) 644c6ac8f0bSMarek Vasut return error; 645c6ac8f0bSMarek Vasut /* Mode already set */ 646c6ac8f0bSMarek Vasut if ((cmd_mode == REG_SET_MODE_AP && md[0] == REG_GET_MODE_AP) || 647c6ac8f0bSMarek Vasut (cmd_mode == REG_SET_MODE_BL && md[0] == REG_GET_MODE_BL)) 648c6ac8f0bSMarek Vasut return 0; 649c6ac8f0bSMarek Vasut 650c6ac8f0bSMarek Vasut /* Unlock writes */ 651c6ac8f0bSMarek Vasut error = i2c_master_send(client, cmd_wren, sizeof(cmd_wren)); 652c6ac8f0bSMarek Vasut if (error != sizeof(cmd_wren)) 653c6ac8f0bSMarek Vasut return -EINVAL; 654c6ac8f0bSMarek Vasut 655c6ac8f0bSMarek Vasut mdelay(20); 656c6ac8f0bSMarek Vasut 657c6ac8f0bSMarek Vasut /* Select mode (BootLoader or Application) */ 658c6ac8f0bSMarek Vasut error = i2c_master_send(client, &cmd_mode, 1); 659c6ac8f0bSMarek Vasut if (error != 1) 660c6ac8f0bSMarek Vasut return -EINVAL; 661c6ac8f0bSMarek Vasut 662c6ac8f0bSMarek Vasut mdelay(200); /* Reboot into bootloader takes a lot of time ... */ 663c6ac8f0bSMarek Vasut 664c6ac8f0bSMarek Vasut /* Read back mode */ 665c6ac8f0bSMarek Vasut error = priv->chip->read_reg(client, REG_GET_MODE, md, sizeof(md)); 666c6ac8f0bSMarek Vasut if (error) 667c6ac8f0bSMarek Vasut return error; 668c6ac8f0bSMarek Vasut /* Check if mode is correct now. */ 669c6ac8f0bSMarek Vasut if ((cmd_mode == REG_SET_MODE_AP && md[0] == REG_GET_MODE_AP) || 670c6ac8f0bSMarek Vasut (cmd_mode == REG_SET_MODE_BL && md[0] == REG_GET_MODE_BL)) 671c6ac8f0bSMarek Vasut return 0; 672c6ac8f0bSMarek Vasut 673c6ac8f0bSMarek Vasut return -EINVAL; 674c6ac8f0bSMarek Vasut } 675c6ac8f0bSMarek Vasut 676c6ac8f0bSMarek Vasut static int ili251x_firmware_busy(struct i2c_client *client) 677c6ac8f0bSMarek Vasut { 678c6ac8f0bSMarek Vasut struct ili210x *priv = i2c_get_clientdata(client); 679c6ac8f0bSMarek Vasut int error, i = 0; 680c6ac8f0bSMarek Vasut u8 data; 681c6ac8f0bSMarek Vasut 682c6ac8f0bSMarek Vasut do { 683c6ac8f0bSMarek Vasut /* The read_reg already contains suitable delay */ 684c6ac8f0bSMarek Vasut error = priv->chip->read_reg(client, REG_IC_BUSY, &data, 1); 685c6ac8f0bSMarek Vasut if (error) 686c6ac8f0bSMarek Vasut return error; 687c6ac8f0bSMarek Vasut if (i++ == 100000) 688c6ac8f0bSMarek Vasut return -ETIMEDOUT; 689c6ac8f0bSMarek Vasut } while (data != REG_IC_BUSY_NOT_BUSY); 690c6ac8f0bSMarek Vasut 691c6ac8f0bSMarek Vasut return 0; 692c6ac8f0bSMarek Vasut } 693c6ac8f0bSMarek Vasut 694c6ac8f0bSMarek Vasut static int ili251x_firmware_write_to_ic(struct device *dev, u8 *fwbuf, 695c6ac8f0bSMarek Vasut u16 start, u16 end, u8 dataflash) 696c6ac8f0bSMarek Vasut { 697c6ac8f0bSMarek Vasut struct i2c_client *client = to_i2c_client(dev); 698c6ac8f0bSMarek Vasut struct ili210x *priv = i2c_get_clientdata(client); 699c6ac8f0bSMarek Vasut u8 cmd_crc = REG_READ_DATA_CRC; 700c6ac8f0bSMarek Vasut u8 crcrb[4] = { 0 }; 701c6ac8f0bSMarek Vasut u8 fw_data[33]; 702c6ac8f0bSMarek Vasut u16 fw_addr; 703c6ac8f0bSMarek Vasut int error; 704c6ac8f0bSMarek Vasut 705c6ac8f0bSMarek Vasut /* 706c6ac8f0bSMarek Vasut * The DF (dataflash) needs 2 bytes offset for unknown reasons, 707c6ac8f0bSMarek Vasut * the AC (application) has 2 bytes CRC16-CCITT at the end. 708c6ac8f0bSMarek Vasut */ 709c6ac8f0bSMarek Vasut u16 crc = crc_ccitt(0, fwbuf + start + (dataflash ? 2 : 0), 710c6ac8f0bSMarek Vasut end - start - 2); 711c6ac8f0bSMarek Vasut 712c6ac8f0bSMarek Vasut /* Unlock write to either AC (application) or DF (dataflash) area */ 713c6ac8f0bSMarek Vasut u8 cmd_wr[10] = { 714c6ac8f0bSMarek Vasut REG_WRITE_ENABLE, 0x5a, 0xa5, dataflash, 715c6ac8f0bSMarek Vasut (end >> 16) & 0xff, (end >> 8) & 0xff, end & 0xff, 716c6ac8f0bSMarek Vasut (crc >> 16) & 0xff, (crc >> 8) & 0xff, crc & 0xff 717c6ac8f0bSMarek Vasut }; 718c6ac8f0bSMarek Vasut 719c6ac8f0bSMarek Vasut error = i2c_master_send(client, cmd_wr, sizeof(cmd_wr)); 720c6ac8f0bSMarek Vasut if (error != sizeof(cmd_wr)) 721c6ac8f0bSMarek Vasut return -EINVAL; 722c6ac8f0bSMarek Vasut 723c6ac8f0bSMarek Vasut error = ili251x_firmware_busy(client); 724c6ac8f0bSMarek Vasut if (error) 725c6ac8f0bSMarek Vasut return error; 726c6ac8f0bSMarek Vasut 727c6ac8f0bSMarek Vasut for (fw_addr = start; fw_addr < end; fw_addr += 32) { 728c6ac8f0bSMarek Vasut fw_data[0] = REG_WRITE_DATA; 729c6ac8f0bSMarek Vasut memcpy(&(fw_data[1]), fwbuf + fw_addr, 32); 730c6ac8f0bSMarek Vasut error = i2c_master_send(client, fw_data, 33); 731c6ac8f0bSMarek Vasut if (error != sizeof(fw_data)) 732c6ac8f0bSMarek Vasut return error; 733c6ac8f0bSMarek Vasut error = ili251x_firmware_busy(client); 734c6ac8f0bSMarek Vasut if (error) 735c6ac8f0bSMarek Vasut return error; 736c6ac8f0bSMarek Vasut } 737c6ac8f0bSMarek Vasut 738c6ac8f0bSMarek Vasut error = i2c_master_send(client, &cmd_crc, 1); 739c6ac8f0bSMarek Vasut if (error != 1) 740c6ac8f0bSMarek Vasut return -EINVAL; 741c6ac8f0bSMarek Vasut 742c6ac8f0bSMarek Vasut error = ili251x_firmware_busy(client); 743c6ac8f0bSMarek Vasut if (error) 744c6ac8f0bSMarek Vasut return error; 745c6ac8f0bSMarek Vasut 746c6ac8f0bSMarek Vasut error = priv->chip->read_reg(client, REG_READ_DATA_CRC, 747c6ac8f0bSMarek Vasut &crcrb, sizeof(crcrb)); 748c6ac8f0bSMarek Vasut if (error) 749c6ac8f0bSMarek Vasut return error; 750c6ac8f0bSMarek Vasut 751c6ac8f0bSMarek Vasut /* Check CRC readback */ 752c6ac8f0bSMarek Vasut if ((crcrb[0] != (crc & 0xff)) || crcrb[1] != ((crc >> 8) & 0xff)) 753c6ac8f0bSMarek Vasut return -EINVAL; 754c6ac8f0bSMarek Vasut 755c6ac8f0bSMarek Vasut return 0; 756c6ac8f0bSMarek Vasut } 757c6ac8f0bSMarek Vasut 758c6ac8f0bSMarek Vasut static int ili251x_firmware_reset(struct i2c_client *client) 759c6ac8f0bSMarek Vasut { 760c6ac8f0bSMarek Vasut u8 cmd_reset[2] = { 0xf2, 0x01 }; 761c6ac8f0bSMarek Vasut int error; 762c6ac8f0bSMarek Vasut 763c6ac8f0bSMarek Vasut error = i2c_master_send(client, cmd_reset, sizeof(cmd_reset)); 764c6ac8f0bSMarek Vasut if (error != sizeof(cmd_reset)) 765c6ac8f0bSMarek Vasut return -EINVAL; 766c6ac8f0bSMarek Vasut 767c6ac8f0bSMarek Vasut return ili251x_firmware_busy(client); 768c6ac8f0bSMarek Vasut } 769c6ac8f0bSMarek Vasut 770b26ff913SMarek Vasut static void ili210x_hardware_reset(struct gpio_desc *reset_gpio) 771c6ac8f0bSMarek Vasut { 772c6ac8f0bSMarek Vasut /* Reset the controller */ 773b26ff913SMarek Vasut gpiod_set_value_cansleep(reset_gpio, 1); 774b26ff913SMarek Vasut usleep_range(12000, 15000); 775b26ff913SMarek Vasut gpiod_set_value_cansleep(reset_gpio, 0); 776c6ac8f0bSMarek Vasut msleep(300); 777c6ac8f0bSMarek Vasut } 778c6ac8f0bSMarek Vasut 779c6ac8f0bSMarek Vasut static ssize_t ili210x_firmware_update_store(struct device *dev, 780c6ac8f0bSMarek Vasut struct device_attribute *attr, 781c6ac8f0bSMarek Vasut const char *buf, size_t count) 782c6ac8f0bSMarek Vasut { 783c6ac8f0bSMarek Vasut struct i2c_client *client = to_i2c_client(dev); 784b26ff913SMarek Vasut struct ili210x *priv = i2c_get_clientdata(client); 785c6ac8f0bSMarek Vasut const char *fwname = ILI251X_FW_FILENAME; 786c6ac8f0bSMarek Vasut const struct firmware *fw; 787c6ac8f0bSMarek Vasut u16 ac_end, df_end; 788c6ac8f0bSMarek Vasut u8 *fwbuf; 789c6ac8f0bSMarek Vasut int error; 790c6ac8f0bSMarek Vasut int i; 791c6ac8f0bSMarek Vasut 792c6ac8f0bSMarek Vasut error = request_ihex_firmware(&fw, fwname, dev); 793c6ac8f0bSMarek Vasut if (error) { 794c6ac8f0bSMarek Vasut dev_err(dev, "Failed to request firmware %s, error=%d\n", 795c6ac8f0bSMarek Vasut fwname, error); 796c6ac8f0bSMarek Vasut return error; 797c6ac8f0bSMarek Vasut } 798c6ac8f0bSMarek Vasut 799c6ac8f0bSMarek Vasut error = ili251x_firmware_to_buffer(fw, &fwbuf, &ac_end, &df_end); 800c6ac8f0bSMarek Vasut release_firmware(fw); 801c6ac8f0bSMarek Vasut if (error) 802c6ac8f0bSMarek Vasut return error; 803c6ac8f0bSMarek Vasut 804c6ac8f0bSMarek Vasut /* 805c6ac8f0bSMarek Vasut * Disable touchscreen IRQ, so that we would not get spurious touch 806c6ac8f0bSMarek Vasut * interrupt during firmware update, and so that the IRQ handler won't 807c6ac8f0bSMarek Vasut * trigger and interfere with the firmware update. There is no bit in 808c6ac8f0bSMarek Vasut * the touch controller to disable the IRQs during update, so we have 809c6ac8f0bSMarek Vasut * to do it this way here. 810c6ac8f0bSMarek Vasut */ 811c6ac8f0bSMarek Vasut disable_irq(client->irq); 812c6ac8f0bSMarek Vasut 813c6ac8f0bSMarek Vasut dev_dbg(dev, "Firmware update started, firmware=%s\n", fwname); 814c6ac8f0bSMarek Vasut 815b26ff913SMarek Vasut ili210x_hardware_reset(priv->reset_gpio); 816c6ac8f0bSMarek Vasut 817c6ac8f0bSMarek Vasut error = ili251x_firmware_reset(client); 818c6ac8f0bSMarek Vasut if (error) 819c6ac8f0bSMarek Vasut goto exit; 820c6ac8f0bSMarek Vasut 821c6ac8f0bSMarek Vasut /* This may not succeed on first try, so re-try a few times. */ 822c6ac8f0bSMarek Vasut for (i = 0; i < 5; i++) { 823c6ac8f0bSMarek Vasut error = ili251x_switch_ic_mode(client, REG_SET_MODE_BL); 824c6ac8f0bSMarek Vasut if (!error) 825c6ac8f0bSMarek Vasut break; 826c6ac8f0bSMarek Vasut } 827c6ac8f0bSMarek Vasut 828c6ac8f0bSMarek Vasut if (error) 829c6ac8f0bSMarek Vasut goto exit; 830c6ac8f0bSMarek Vasut 831c6ac8f0bSMarek Vasut dev_dbg(dev, "IC is now in BootLoader mode\n"); 832c6ac8f0bSMarek Vasut 833c6ac8f0bSMarek Vasut msleep(200); /* The bootloader seems to need some time too. */ 834c6ac8f0bSMarek Vasut 835c6ac8f0bSMarek Vasut error = ili251x_firmware_write_to_ic(dev, fwbuf, 0xf000, df_end, 1); 836c6ac8f0bSMarek Vasut if (error) { 837c6ac8f0bSMarek Vasut dev_err(dev, "DF firmware update failed, error=%d\n", error); 838c6ac8f0bSMarek Vasut goto exit; 839c6ac8f0bSMarek Vasut } 840c6ac8f0bSMarek Vasut 841c6ac8f0bSMarek Vasut dev_dbg(dev, "DataFlash firmware written\n"); 842c6ac8f0bSMarek Vasut 843c6ac8f0bSMarek Vasut error = ili251x_firmware_write_to_ic(dev, fwbuf, 0x2000, ac_end, 0); 844c6ac8f0bSMarek Vasut if (error) { 845c6ac8f0bSMarek Vasut dev_err(dev, "AC firmware update failed, error=%d\n", error); 846c6ac8f0bSMarek Vasut goto exit; 847c6ac8f0bSMarek Vasut } 848c6ac8f0bSMarek Vasut 849c6ac8f0bSMarek Vasut dev_dbg(dev, "Application firmware written\n"); 850c6ac8f0bSMarek Vasut 851c6ac8f0bSMarek Vasut /* This may not succeed on first try, so re-try a few times. */ 852c6ac8f0bSMarek Vasut for (i = 0; i < 5; i++) { 853c6ac8f0bSMarek Vasut error = ili251x_switch_ic_mode(client, REG_SET_MODE_AP); 854c6ac8f0bSMarek Vasut if (!error) 855c6ac8f0bSMarek Vasut break; 856c6ac8f0bSMarek Vasut } 857c6ac8f0bSMarek Vasut 858c6ac8f0bSMarek Vasut if (error) 859c6ac8f0bSMarek Vasut goto exit; 860c6ac8f0bSMarek Vasut 861c6ac8f0bSMarek Vasut dev_dbg(dev, "IC is now in Application mode\n"); 862c6ac8f0bSMarek Vasut 863c6ac8f0bSMarek Vasut error = ili251x_firmware_update_cached_state(dev); 864c6ac8f0bSMarek Vasut if (error) 865c6ac8f0bSMarek Vasut goto exit; 866c6ac8f0bSMarek Vasut 867c6ac8f0bSMarek Vasut error = count; 868c6ac8f0bSMarek Vasut 869c6ac8f0bSMarek Vasut exit: 870b26ff913SMarek Vasut ili210x_hardware_reset(priv->reset_gpio); 871c6ac8f0bSMarek Vasut dev_dbg(dev, "Firmware update ended, error=%i\n", error); 872c6ac8f0bSMarek Vasut enable_irq(client->irq); 873c6ac8f0bSMarek Vasut kfree(fwbuf); 874c6ac8f0bSMarek Vasut return error; 875c6ac8f0bSMarek Vasut } 876c6ac8f0bSMarek Vasut 877c6ac8f0bSMarek Vasut static DEVICE_ATTR(firmware_update, 0200, NULL, ili210x_firmware_update_store); 878c6ac8f0bSMarek Vasut 8795c6a7a62SOlivier Sobrie static struct attribute *ili210x_attributes[] = { 8805c6a7a62SOlivier Sobrie &dev_attr_calibrate.attr, 881c6ac8f0bSMarek Vasut &dev_attr_firmware_update.attr, 88270a7681dSMarek Vasut &dev_attr_firmware_version.attr, 88370a7681dSMarek Vasut &dev_attr_kernel_version.attr, 88470a7681dSMarek Vasut &dev_attr_protocol_version.attr, 88570a7681dSMarek Vasut &dev_attr_mode.attr, 8865c6a7a62SOlivier Sobrie NULL, 8875c6a7a62SOlivier Sobrie }; 8885c6a7a62SOlivier Sobrie 88970a7681dSMarek Vasut static umode_t ili210x_attributes_visible(struct kobject *kobj, 890cc12ba18SSven Van Asbroeck struct attribute *attr, int index) 891cc12ba18SSven Van Asbroeck { 892cc12ba18SSven Van Asbroeck struct device *dev = kobj_to_dev(kobj); 893cc12ba18SSven Van Asbroeck struct i2c_client *client = to_i2c_client(dev); 894cc12ba18SSven Van Asbroeck struct ili210x *priv = i2c_get_clientdata(client); 895cc12ba18SSven Van Asbroeck 89670a7681dSMarek Vasut /* Calibrate is present on all ILI2xxx which have calibrate register */ 89770a7681dSMarek Vasut if (attr == &dev_attr_calibrate.attr) 898fbd1ec00SLuca Weiss return priv->chip->has_calibrate_reg ? attr->mode : 0; 89970a7681dSMarek Vasut 90070a7681dSMarek Vasut /* Firmware/Kernel/Protocol/BootMode is implememted only for ILI251x */ 90170a7681dSMarek Vasut if (!priv->chip->has_firmware_proto) 90270a7681dSMarek Vasut return 0; 90370a7681dSMarek Vasut 90470a7681dSMarek Vasut return attr->mode; 905cc12ba18SSven Van Asbroeck } 906cc12ba18SSven Van Asbroeck 9075c6a7a62SOlivier Sobrie static const struct attribute_group ili210x_attr_group = { 9085c6a7a62SOlivier Sobrie .attrs = ili210x_attributes, 90970a7681dSMarek Vasut .is_visible = ili210x_attributes_visible, 9105c6a7a62SOlivier Sobrie }; 9115c6a7a62SOlivier Sobrie 912201f3c80SMarek Vasut static void ili210x_power_down(void *data) 913201f3c80SMarek Vasut { 914201f3c80SMarek Vasut struct gpio_desc *reset_gpio = data; 915201f3c80SMarek Vasut 916201f3c80SMarek Vasut gpiod_set_value_cansleep(reset_gpio, 1); 917201f3c80SMarek Vasut } 918201f3c80SMarek Vasut 91971f8e38aSDmitry Torokhov static void ili210x_stop(void *data) 9201bdec5d9SMarek Vasut { 9211bdec5d9SMarek Vasut struct ili210x *priv = data; 9221bdec5d9SMarek Vasut 92371f8e38aSDmitry Torokhov /* Tell ISR to quit even if there is a contact. */ 92471f8e38aSDmitry Torokhov priv->stop = true; 9251bdec5d9SMarek Vasut } 9261bdec5d9SMarek Vasut 927497a2c8eSUwe Kleine-König static int ili210x_i2c_probe(struct i2c_client *client) 9285c6a7a62SOlivier Sobrie { 929497a2c8eSUwe Kleine-König const struct i2c_device_id *id = i2c_client_get_device_id(client); 9305c6a7a62SOlivier Sobrie struct device *dev = &client->dev; 931ef536abdSDmitry Torokhov const struct ili2xxx_chip *chip; 9325c6a7a62SOlivier Sobrie struct ili210x *priv; 933201f3c80SMarek Vasut struct gpio_desc *reset_gpio; 9345c6a7a62SOlivier Sobrie struct input_dev *input; 9355c6a7a62SOlivier Sobrie int error; 936b32fbeaeSSven Van Asbroeck unsigned int max_xy; 9375c6a7a62SOlivier Sobrie 9385c6a7a62SOlivier Sobrie dev_dbg(dev, "Probing for ILI210X I2C Touschreen driver"); 9395c6a7a62SOlivier Sobrie 940ef536abdSDmitry Torokhov chip = device_get_match_data(dev); 941ef536abdSDmitry Torokhov if (!chip && id) 942ef536abdSDmitry Torokhov chip = (const struct ili2xxx_chip *)id->driver_data; 943ef536abdSDmitry Torokhov if (!chip) { 944ef536abdSDmitry Torokhov dev_err(&client->dev, "unknown device model\n"); 945ef536abdSDmitry Torokhov return -ENODEV; 946ef536abdSDmitry Torokhov } 947ef536abdSDmitry Torokhov 9485c6a7a62SOlivier Sobrie if (client->irq <= 0) { 9495c6a7a62SOlivier Sobrie dev_err(dev, "No IRQ!\n"); 9505c6a7a62SOlivier Sobrie return -EINVAL; 9515c6a7a62SOlivier Sobrie } 9525c6a7a62SOlivier Sobrie 953201f3c80SMarek Vasut reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH); 954201f3c80SMarek Vasut if (IS_ERR(reset_gpio)) 955201f3c80SMarek Vasut return PTR_ERR(reset_gpio); 956201f3c80SMarek Vasut 957201f3c80SMarek Vasut if (reset_gpio) { 958201f3c80SMarek Vasut error = devm_add_action_or_reset(dev, ili210x_power_down, 959201f3c80SMarek Vasut reset_gpio); 960201f3c80SMarek Vasut if (error) 961201f3c80SMarek Vasut return error; 962201f3c80SMarek Vasut 963b26ff913SMarek Vasut ili210x_hardware_reset(reset_gpio); 964201f3c80SMarek Vasut } 965201f3c80SMarek Vasut 96612294577SMarek Vasut priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 96712294577SMarek Vasut if (!priv) 96812294577SMarek Vasut return -ENOMEM; 96912294577SMarek Vasut 97012294577SMarek Vasut input = devm_input_allocate_device(dev); 97112294577SMarek Vasut if (!input) 97212294577SMarek Vasut return -ENOMEM; 97312294577SMarek Vasut 97412294577SMarek Vasut priv->client = client; 97512294577SMarek Vasut priv->input = input; 97612294577SMarek Vasut priv->reset_gpio = reset_gpio; 977ef536abdSDmitry Torokhov priv->chip = chip; 97812294577SMarek Vasut i2c_set_clientdata(client, priv); 97912294577SMarek Vasut 9805c6a7a62SOlivier Sobrie /* Setup input device */ 9815c6a7a62SOlivier Sobrie input->name = "ILI210x Touchscreen"; 9825c6a7a62SOlivier Sobrie input->id.bustype = BUS_I2C; 9835c6a7a62SOlivier Sobrie 9845c6a7a62SOlivier Sobrie /* Multi touch */ 985b32fbeaeSSven Van Asbroeck max_xy = (chip->resolution ?: SZ_64K) - 1; 986b32fbeaeSSven Van Asbroeck input_set_abs_params(input, ABS_MT_POSITION_X, 0, max_xy, 0, 0); 987b32fbeaeSSven Van Asbroeck input_set_abs_params(input, ABS_MT_POSITION_Y, 0, max_xy, 0, 0); 98860159e9eSMarek Vasut if (priv->chip->has_pressure_reg) 98960159e9eSMarek Vasut input_set_abs_params(input, ABS_MT_PRESSURE, 0, 0xa, 0, 0); 990235300edSMarek Vasut error = ili251x_firmware_update_cached_state(dev); 991e1141b0cSMarek Vasut if (error) 992e1141b0cSMarek Vasut dev_warn(dev, "Unable to cache firmware information, err: %d\n", 993235300edSMarek Vasut error); 994e1141b0cSMarek Vasut 995f67cc3e9SMarek Vasut touchscreen_parse_properties(input, true, &priv->prop); 99643f06a4cSDmitry Torokhov 997ef536abdSDmitry Torokhov error = input_mt_init_slots(input, priv->chip->max_touches, 998ef536abdSDmitry Torokhov INPUT_MT_DIRECT); 99943f06a4cSDmitry Torokhov if (error) { 100043f06a4cSDmitry Torokhov dev_err(dev, "Unable to set up slots, err: %d\n", error); 100143f06a4cSDmitry Torokhov return error; 100243f06a4cSDmitry Torokhov } 10035c6a7a62SOlivier Sobrie 100471f8e38aSDmitry Torokhov error = devm_request_threaded_irq(dev, client->irq, NULL, ili210x_irq, 100571f8e38aSDmitry Torokhov IRQF_ONESHOT, client->name, priv); 10065c6a7a62SOlivier Sobrie if (error) { 10075c6a7a62SOlivier Sobrie dev_err(dev, "Unable to request touchscreen IRQ, err: %d\n", 10085c6a7a62SOlivier Sobrie error); 10091bdec5d9SMarek Vasut return error; 10105c6a7a62SOlivier Sobrie } 10115c6a7a62SOlivier Sobrie 101271f8e38aSDmitry Torokhov error = devm_add_action_or_reset(dev, ili210x_stop, priv); 101371f8e38aSDmitry Torokhov if (error) 101471f8e38aSDmitry Torokhov return error; 101571f8e38aSDmitry Torokhov 1016576057bfSDmitry Torokhov error = devm_device_add_group(dev, &ili210x_attr_group); 10175c6a7a62SOlivier Sobrie if (error) { 10185c6a7a62SOlivier Sobrie dev_err(dev, "Unable to create sysfs attributes, err: %d\n", 10195c6a7a62SOlivier Sobrie error); 10201bdec5d9SMarek Vasut return error; 10215c6a7a62SOlivier Sobrie } 10225c6a7a62SOlivier Sobrie 10235c6a7a62SOlivier Sobrie error = input_register_device(priv->input); 10245c6a7a62SOlivier Sobrie if (error) { 1025971bd8faSMasanari Iida dev_err(dev, "Cannot register input device, err: %d\n", error); 1026576057bfSDmitry Torokhov return error; 10275c6a7a62SOlivier Sobrie } 10285c6a7a62SOlivier Sobrie 10295c6a7a62SOlivier Sobrie return 0; 10305c6a7a62SOlivier Sobrie } 10315c6a7a62SOlivier Sobrie 10325c6a7a62SOlivier Sobrie static const struct i2c_device_id ili210x_i2c_id[] = { 1033ef536abdSDmitry Torokhov { "ili210x", (long)&ili210x_chip }, 1034ef536abdSDmitry Torokhov { "ili2117", (long)&ili211x_chip }, 1035d0c5e7d4SLuca Weiss { "ili2120", (long)&ili212x_chip }, 1036ef536abdSDmitry Torokhov { "ili251x", (long)&ili251x_chip }, 10375c6a7a62SOlivier Sobrie { } 10385c6a7a62SOlivier Sobrie }; 10395c6a7a62SOlivier Sobrie MODULE_DEVICE_TABLE(i2c, ili210x_i2c_id); 10405c6a7a62SOlivier Sobrie 1041c5d0e4b5SMarek Vasut static const struct of_device_id ili210x_dt_ids[] = { 1042ef536abdSDmitry Torokhov { .compatible = "ilitek,ili210x", .data = &ili210x_chip }, 1043ef536abdSDmitry Torokhov { .compatible = "ilitek,ili2117", .data = &ili211x_chip }, 1044d0c5e7d4SLuca Weiss { .compatible = "ilitek,ili2120", .data = &ili212x_chip }, 1045ef536abdSDmitry Torokhov { .compatible = "ilitek,ili251x", .data = &ili251x_chip }, 1046ef536abdSDmitry Torokhov { } 1047c5d0e4b5SMarek Vasut }; 1048c5d0e4b5SMarek Vasut MODULE_DEVICE_TABLE(of, ili210x_dt_ids); 1049c5d0e4b5SMarek Vasut 10505c6a7a62SOlivier Sobrie static struct i2c_driver ili210x_ts_driver = { 10515c6a7a62SOlivier Sobrie .driver = { 10525c6a7a62SOlivier Sobrie .name = "ili210x_i2c", 1053c5d0e4b5SMarek Vasut .of_match_table = ili210x_dt_ids, 10545c6a7a62SOlivier Sobrie }, 10555c6a7a62SOlivier Sobrie .id_table = ili210x_i2c_id, 1056d8bde56dSUwe Kleine-König .probe = ili210x_i2c_probe, 10575c6a7a62SOlivier Sobrie }; 10585c6a7a62SOlivier Sobrie 10595c6a7a62SOlivier Sobrie module_i2c_driver(ili210x_ts_driver); 10605c6a7a62SOlivier Sobrie 10615c6a7a62SOlivier Sobrie MODULE_AUTHOR("Olivier Sobrie <olivier@sobrie.be>"); 10625c6a7a62SOlivier Sobrie MODULE_DESCRIPTION("ILI210X I2C Touchscreen Driver"); 10635c6a7a62SOlivier Sobrie MODULE_LICENSE("GPL"); 1064