0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017 #include <linux/delay.h>
0018 #include <linux/i2c.h>
0019 #include <linux/input.h>
0020 #include <linux/input/mt.h>
0021 #include <linux/module.h>
0022 #include <linux/slab.h>
0023 #include <asm/unaligned.h>
0024 #include "cyapa.h"
0025
0026
0027 #define GEN3_MAX_FINGERS 5
0028 #define GEN3_FINGER_NUM(x) (((x) >> 4) & 0x07)
0029
0030 #define BLK_HEAD_BYTES 32
0031
0032
0033 #define PRODUCT_ID_SIZE 16
0034 #define QUERY_DATA_SIZE 27
0035 #define REG_PROTOCOL_GEN_QUERY_OFFSET 20
0036
0037 #define REG_OFFSET_DATA_BASE 0x0000
0038 #define REG_OFFSET_COMMAND_BASE 0x0028
0039 #define REG_OFFSET_QUERY_BASE 0x002a
0040
0041 #define CYAPA_OFFSET_SOFT_RESET REG_OFFSET_COMMAND_BASE
0042 #define OP_RECALIBRATION_MASK 0x80
0043 #define OP_REPORT_BASELINE_MASK 0x40
0044 #define REG_OFFSET_MAX_BASELINE 0x0026
0045 #define REG_OFFSET_MIN_BASELINE 0x0027
0046
0047 #define REG_OFFSET_POWER_MODE (REG_OFFSET_COMMAND_BASE + 1)
0048 #define SET_POWER_MODE_DELAY 10000
0049 #define SET_POWER_MODE_TRIES 5
0050
0051 #define GEN3_BL_CMD_CHECKSUM_SEED 0xff
0052 #define GEN3_BL_CMD_INITIATE_BL 0x38
0053 #define GEN3_BL_CMD_WRITE_BLOCK 0x39
0054 #define GEN3_BL_CMD_VERIFY_BLOCK 0x3a
0055 #define GEN3_BL_CMD_TERMINATE_BL 0x3b
0056 #define GEN3_BL_CMD_LAUNCH_APP 0xa5
0057
0058
0059
0060
0061
0062
0063 #define CYAPA_DEV_NORMAL 0x03
0064 #define CYAPA_DEV_BUSY 0x01
0065
0066 #define CYAPA_FW_BLOCK_SIZE 64
0067 #define CYAPA_FW_READ_SIZE 16
0068 #define CYAPA_FW_HDR_START 0x0780
0069 #define CYAPA_FW_HDR_BLOCK_COUNT 2
0070 #define CYAPA_FW_HDR_BLOCK_START (CYAPA_FW_HDR_START / CYAPA_FW_BLOCK_SIZE)
0071 #define CYAPA_FW_HDR_SIZE (CYAPA_FW_HDR_BLOCK_COUNT * \
0072 CYAPA_FW_BLOCK_SIZE)
0073 #define CYAPA_FW_DATA_START 0x0800
0074 #define CYAPA_FW_DATA_BLOCK_COUNT 480
0075 #define CYAPA_FW_DATA_BLOCK_START (CYAPA_FW_DATA_START / CYAPA_FW_BLOCK_SIZE)
0076 #define CYAPA_FW_DATA_SIZE (CYAPA_FW_DATA_BLOCK_COUNT * \
0077 CYAPA_FW_BLOCK_SIZE)
0078 #define CYAPA_FW_SIZE (CYAPA_FW_HDR_SIZE + CYAPA_FW_DATA_SIZE)
0079 #define CYAPA_CMD_LEN 16
0080
0081 #define GEN3_BL_IDLE_FW_MAJ_VER_OFFSET 0x0b
0082 #define GEN3_BL_IDLE_FW_MIN_VER_OFFSET (GEN3_BL_IDLE_FW_MAJ_VER_OFFSET + 1)
0083
0084
0085 struct cyapa_touch {
0086
0087
0088
0089
0090
0091 u8 xy_hi;
0092 u8 x_lo;
0093 u8 y_lo;
0094 u8 pressure;
0095
0096 u8 id;
0097 } __packed;
0098
0099 struct cyapa_reg_data {
0100
0101
0102
0103
0104
0105
0106 u8 device_status;
0107
0108
0109
0110
0111
0112
0113
0114 u8 finger_btn;
0115
0116 struct cyapa_touch touches[5];
0117 } __packed;
0118
0119 struct gen3_write_block_cmd {
0120 u8 checksum_seed;
0121 u8 cmd_code;
0122 u8 key[8];
0123 __be16 block_num;
0124 u8 block_data[CYAPA_FW_BLOCK_SIZE];
0125 u8 block_checksum;
0126 u8 cmd_checksum;
0127 } __packed;
0128
0129 static const u8 security_key[] = {
0130 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 };
0131 static const u8 bl_activate[] = { 0x00, 0xff, 0x38, 0x00, 0x01, 0x02, 0x03,
0132 0x04, 0x05, 0x06, 0x07 };
0133 static const u8 bl_deactivate[] = { 0x00, 0xff, 0x3b, 0x00, 0x01, 0x02, 0x03,
0134 0x04, 0x05, 0x06, 0x07 };
0135 static const u8 bl_exit[] = { 0x00, 0xff, 0xa5, 0x00, 0x01, 0x02, 0x03, 0x04,
0136 0x05, 0x06, 0x07 };
0137
0138
0139
0140 #define CMD_RESET 0
0141 #define CMD_POWER_MODE 1
0142 #define CMD_DEV_STATUS 2
0143 #define CMD_REPORT_MAX_BASELINE 3
0144 #define CMD_REPORT_MIN_BASELINE 4
0145 #define SMBUS_BYTE_CMD(cmd) (((cmd) & 0x3f) << 1)
0146 #define CYAPA_SMBUS_RESET SMBUS_BYTE_CMD(CMD_RESET)
0147 #define CYAPA_SMBUS_POWER_MODE SMBUS_BYTE_CMD(CMD_POWER_MODE)
0148 #define CYAPA_SMBUS_DEV_STATUS SMBUS_BYTE_CMD(CMD_DEV_STATUS)
0149 #define CYAPA_SMBUS_MAX_BASELINE SMBUS_BYTE_CMD(CMD_REPORT_MAX_BASELINE)
0150 #define CYAPA_SMBUS_MIN_BASELINE SMBUS_BYTE_CMD(CMD_REPORT_MIN_BASELINE)
0151
0152
0153 #define REG_GROUP_DATA 0
0154 #define REG_GROUP_CMD 2
0155 #define REG_GROUP_QUERY 3
0156 #define SMBUS_GROUP_CMD(grp) (0x80 | (((grp) & 0x07) << 3))
0157 #define CYAPA_SMBUS_GROUP_DATA SMBUS_GROUP_CMD(REG_GROUP_DATA)
0158 #define CYAPA_SMBUS_GROUP_CMD SMBUS_GROUP_CMD(REG_GROUP_CMD)
0159 #define CYAPA_SMBUS_GROUP_QUERY SMBUS_GROUP_CMD(REG_GROUP_QUERY)
0160
0161
0162 #define CMD_BL_STATUS 0
0163 #define CMD_BL_HEAD 1
0164 #define CMD_BL_CMD 2
0165 #define CMD_BL_DATA 3
0166 #define CMD_BL_ALL 4
0167 #define CMD_BLK_PRODUCT_ID 5
0168 #define CMD_BLK_HEAD 6
0169 #define SMBUS_BLOCK_CMD(cmd) (0xc0 | (((cmd) & 0x1f) << 1))
0170
0171
0172 #define CYAPA_SMBUS_BL_STATUS SMBUS_BLOCK_CMD(CMD_BL_STATUS)
0173 #define CYAPA_SMBUS_BL_HEAD SMBUS_BLOCK_CMD(CMD_BL_HEAD)
0174 #define CYAPA_SMBUS_BL_CMD SMBUS_BLOCK_CMD(CMD_BL_CMD)
0175 #define CYAPA_SMBUS_BL_DATA SMBUS_BLOCK_CMD(CMD_BL_DATA)
0176 #define CYAPA_SMBUS_BL_ALL SMBUS_BLOCK_CMD(CMD_BL_ALL)
0177
0178
0179 #define CYAPA_SMBUS_BLK_PRODUCT_ID SMBUS_BLOCK_CMD(CMD_BLK_PRODUCT_ID)
0180 #define CYAPA_SMBUS_BLK_HEAD SMBUS_BLOCK_CMD(CMD_BLK_HEAD)
0181
0182 struct cyapa_cmd_len {
0183 u8 cmd;
0184 u8 len;
0185 };
0186
0187
0188 static const struct cyapa_cmd_len cyapa_i2c_cmds[] = {
0189 { CYAPA_OFFSET_SOFT_RESET, 1 },
0190 { REG_OFFSET_COMMAND_BASE + 1, 1 },
0191 { REG_OFFSET_DATA_BASE, 1 },
0192 { REG_OFFSET_DATA_BASE, sizeof(struct cyapa_reg_data) },
0193
0194 { REG_OFFSET_COMMAND_BASE, 0 },
0195 { REG_OFFSET_QUERY_BASE, QUERY_DATA_SIZE },
0196 { BL_HEAD_OFFSET, 3 },
0197 { BL_HEAD_OFFSET, 16 },
0198 { BL_HEAD_OFFSET, 16 },
0199 { BL_DATA_OFFSET, 16 },
0200 { BL_HEAD_OFFSET, 32 },
0201 { REG_OFFSET_QUERY_BASE, PRODUCT_ID_SIZE },
0202
0203 { REG_OFFSET_DATA_BASE, 32 },
0204 { REG_OFFSET_MAX_BASELINE, 1 },
0205 { REG_OFFSET_MIN_BASELINE, 1 },
0206 };
0207
0208 static const struct cyapa_cmd_len cyapa_smbus_cmds[] = {
0209 { CYAPA_SMBUS_RESET, 1 },
0210 { CYAPA_SMBUS_POWER_MODE, 1 },
0211 { CYAPA_SMBUS_DEV_STATUS, 1 },
0212 { CYAPA_SMBUS_GROUP_DATA, sizeof(struct cyapa_reg_data) },
0213
0214 { CYAPA_SMBUS_GROUP_CMD, 2 },
0215 { CYAPA_SMBUS_GROUP_QUERY, QUERY_DATA_SIZE },
0216
0217 { CYAPA_SMBUS_BL_STATUS, 3 },
0218 { CYAPA_SMBUS_BL_HEAD, 16 },
0219 { CYAPA_SMBUS_BL_CMD, 16 },
0220 { CYAPA_SMBUS_BL_DATA, 16 },
0221 { CYAPA_SMBUS_BL_ALL, 32 },
0222 { CYAPA_SMBUS_BLK_PRODUCT_ID, PRODUCT_ID_SIZE },
0223
0224 { CYAPA_SMBUS_BLK_HEAD, 16 },
0225 { CYAPA_SMBUS_MAX_BASELINE, 1 },
0226 { CYAPA_SMBUS_MIN_BASELINE, 1 },
0227 };
0228
0229 static int cyapa_gen3_try_poll_handler(struct cyapa *cyapa);
0230
0231
0232
0233
0234
0235
0236
0237
0238
0239
0240
0241
0242
0243
0244 ssize_t cyapa_smbus_read_block(struct cyapa *cyapa, u8 cmd, size_t len,
0245 u8 *values)
0246 {
0247 ssize_t ret;
0248 u8 index;
0249 u8 smbus_cmd;
0250 u8 *buf;
0251 struct i2c_client *client = cyapa->client;
0252
0253 if (!(SMBUS_BYTE_BLOCK_CMD_MASK & cmd))
0254 return -EINVAL;
0255
0256 if (SMBUS_GROUP_BLOCK_CMD_MASK & cmd) {
0257
0258 smbus_cmd = SMBUS_ENCODE_RW(cmd, SMBUS_READ);
0259 ret = i2c_smbus_read_block_data(client, smbus_cmd, values);
0260 goto out;
0261 }
0262
0263 ret = 0;
0264 for (index = 0; index * I2C_SMBUS_BLOCK_MAX < len; index++) {
0265 smbus_cmd = SMBUS_ENCODE_IDX(cmd, index);
0266 smbus_cmd = SMBUS_ENCODE_RW(smbus_cmd, SMBUS_READ);
0267 buf = values + I2C_SMBUS_BLOCK_MAX * index;
0268 ret = i2c_smbus_read_block_data(client, smbus_cmd, buf);
0269 if (ret < 0)
0270 goto out;
0271 }
0272
0273 out:
0274 return ret > 0 ? len : ret;
0275 }
0276
0277 static s32 cyapa_read_byte(struct cyapa *cyapa, u8 cmd_idx)
0278 {
0279 u8 cmd;
0280
0281 if (cyapa->smbus) {
0282 cmd = cyapa_smbus_cmds[cmd_idx].cmd;
0283 cmd = SMBUS_ENCODE_RW(cmd, SMBUS_READ);
0284 } else {
0285 cmd = cyapa_i2c_cmds[cmd_idx].cmd;
0286 }
0287 return i2c_smbus_read_byte_data(cyapa->client, cmd);
0288 }
0289
0290 static s32 cyapa_write_byte(struct cyapa *cyapa, u8 cmd_idx, u8 value)
0291 {
0292 u8 cmd;
0293
0294 if (cyapa->smbus) {
0295 cmd = cyapa_smbus_cmds[cmd_idx].cmd;
0296 cmd = SMBUS_ENCODE_RW(cmd, SMBUS_WRITE);
0297 } else {
0298 cmd = cyapa_i2c_cmds[cmd_idx].cmd;
0299 }
0300 return i2c_smbus_write_byte_data(cyapa->client, cmd, value);
0301 }
0302
0303 ssize_t cyapa_i2c_reg_read_block(struct cyapa *cyapa, u8 reg, size_t len,
0304 u8 *values)
0305 {
0306 return i2c_smbus_read_i2c_block_data(cyapa->client, reg, len, values);
0307 }
0308
0309 static ssize_t cyapa_i2c_reg_write_block(struct cyapa *cyapa, u8 reg,
0310 size_t len, const u8 *values)
0311 {
0312 return i2c_smbus_write_i2c_block_data(cyapa->client, reg, len, values);
0313 }
0314
0315 ssize_t cyapa_read_block(struct cyapa *cyapa, u8 cmd_idx, u8 *values)
0316 {
0317 u8 cmd;
0318 size_t len;
0319
0320 if (cyapa->smbus) {
0321 cmd = cyapa_smbus_cmds[cmd_idx].cmd;
0322 len = cyapa_smbus_cmds[cmd_idx].len;
0323 return cyapa_smbus_read_block(cyapa, cmd, len, values);
0324 }
0325 cmd = cyapa_i2c_cmds[cmd_idx].cmd;
0326 len = cyapa_i2c_cmds[cmd_idx].len;
0327 return cyapa_i2c_reg_read_block(cyapa, cmd, len, values);
0328 }
0329
0330
0331
0332
0333
0334 static int cyapa_gen3_state_parse(struct cyapa *cyapa, u8 *reg_data, int len)
0335 {
0336 cyapa->state = CYAPA_STATE_NO_DEVICE;
0337
0338
0339 if (reg_data[REG_BL_FILE] == BL_FILE &&
0340 reg_data[REG_BL_ERROR] == BL_ERROR_NO_ERR_IDLE &&
0341 (reg_data[REG_BL_STATUS] ==
0342 (BL_STATUS_RUNNING | BL_STATUS_CSUM_VALID) ||
0343 reg_data[REG_BL_STATUS] == BL_STATUS_RUNNING)) {
0344
0345
0346
0347
0348
0349 cyapa->gen = CYAPA_GEN3;
0350 cyapa->state = CYAPA_STATE_BL_IDLE;
0351 } else if (reg_data[REG_BL_FILE] == BL_FILE &&
0352 (reg_data[REG_BL_STATUS] & BL_STATUS_RUNNING) ==
0353 BL_STATUS_RUNNING) {
0354 cyapa->gen = CYAPA_GEN3;
0355 if (reg_data[REG_BL_STATUS] & BL_STATUS_BUSY) {
0356 cyapa->state = CYAPA_STATE_BL_BUSY;
0357 } else {
0358 if ((reg_data[REG_BL_ERROR] & BL_ERROR_BOOTLOADING) ==
0359 BL_ERROR_BOOTLOADING)
0360 cyapa->state = CYAPA_STATE_BL_ACTIVE;
0361 else
0362 cyapa->state = CYAPA_STATE_BL_IDLE;
0363 }
0364 } else if ((reg_data[REG_OP_STATUS] & OP_STATUS_SRC) &&
0365 (reg_data[REG_OP_DATA1] & OP_DATA_VALID)) {
0366
0367
0368
0369
0370
0371 if (GEN3_FINGER_NUM(reg_data[REG_OP_DATA1]) <=
0372 GEN3_MAX_FINGERS) {
0373
0374 cyapa->gen = CYAPA_GEN3;
0375 cyapa->state = CYAPA_STATE_OP;
0376 }
0377 } else if (reg_data[REG_OP_STATUS] == 0x0C &&
0378 reg_data[REG_OP_DATA1] == 0x08) {
0379
0380 cyapa->gen = CYAPA_GEN3;
0381 cyapa->state = CYAPA_STATE_OP;
0382 } else if (reg_data[REG_BL_STATUS] &
0383 (BL_STATUS_RUNNING | BL_STATUS_BUSY)) {
0384 cyapa->gen = CYAPA_GEN3;
0385 cyapa->state = CYAPA_STATE_BL_BUSY;
0386 }
0387
0388 if (cyapa->gen == CYAPA_GEN3 && (cyapa->state == CYAPA_STATE_OP ||
0389 cyapa->state == CYAPA_STATE_BL_IDLE ||
0390 cyapa->state == CYAPA_STATE_BL_ACTIVE ||
0391 cyapa->state == CYAPA_STATE_BL_BUSY))
0392 return 0;
0393
0394 return -EAGAIN;
0395 }
0396
0397
0398
0399
0400
0401
0402
0403
0404
0405
0406
0407
0408
0409 static int cyapa_gen3_bl_enter(struct cyapa *cyapa)
0410 {
0411 int error;
0412 int waiting_time;
0413
0414 error = cyapa_poll_state(cyapa, 500);
0415 if (error)
0416 return error;
0417 if (cyapa->state == CYAPA_STATE_BL_IDLE) {
0418
0419 return 0;
0420 }
0421
0422 if (cyapa->state != CYAPA_STATE_OP)
0423 return -EAGAIN;
0424
0425 cyapa->operational = false;
0426 cyapa->state = CYAPA_STATE_NO_DEVICE;
0427 error = cyapa_write_byte(cyapa, CYAPA_CMD_SOFT_RESET, 0x01);
0428 if (error)
0429 return -EIO;
0430
0431 usleep_range(25000, 50000);
0432 waiting_time = 2000;
0433 do {
0434 error = cyapa_poll_state(cyapa, 500);
0435 if (error) {
0436 if (error == -ETIMEDOUT) {
0437 waiting_time -= 500;
0438 continue;
0439 }
0440 return error;
0441 }
0442
0443 if ((cyapa->state == CYAPA_STATE_BL_IDLE) &&
0444 !(cyapa->status[REG_BL_STATUS] & BL_STATUS_WATCHDOG))
0445 break;
0446
0447 msleep(100);
0448 waiting_time -= 100;
0449 } while (waiting_time > 0);
0450
0451 if ((cyapa->state != CYAPA_STATE_BL_IDLE) ||
0452 (cyapa->status[REG_BL_STATUS] & BL_STATUS_WATCHDOG))
0453 return -EAGAIN;
0454
0455 return 0;
0456 }
0457
0458 static int cyapa_gen3_bl_activate(struct cyapa *cyapa)
0459 {
0460 int error;
0461
0462 error = cyapa_i2c_reg_write_block(cyapa, 0, sizeof(bl_activate),
0463 bl_activate);
0464 if (error)
0465 return error;
0466
0467
0468 msleep(2000);
0469 error = cyapa_poll_state(cyapa, 11000);
0470 if (error)
0471 return error;
0472 if (cyapa->state != CYAPA_STATE_BL_ACTIVE)
0473 return -EAGAIN;
0474
0475 return 0;
0476 }
0477
0478 static int cyapa_gen3_bl_deactivate(struct cyapa *cyapa)
0479 {
0480 int error;
0481
0482 error = cyapa_i2c_reg_write_block(cyapa, 0, sizeof(bl_deactivate),
0483 bl_deactivate);
0484 if (error)
0485 return error;
0486
0487
0488 msleep(100);
0489 error = cyapa_poll_state(cyapa, 500);
0490 if (error)
0491 return error;
0492 if (cyapa->state != CYAPA_STATE_BL_IDLE)
0493 return -EAGAIN;
0494 return 0;
0495 }
0496
0497
0498
0499
0500
0501
0502
0503
0504
0505
0506
0507
0508
0509
0510 static int cyapa_gen3_bl_exit(struct cyapa *cyapa)
0511 {
0512 int error;
0513
0514 error = cyapa_i2c_reg_write_block(cyapa, 0, sizeof(bl_exit), bl_exit);
0515 if (error)
0516 return error;
0517
0518
0519
0520
0521
0522 msleep(50);
0523
0524
0525
0526
0527
0528
0529 error = cyapa_poll_state(cyapa, 4000);
0530 if (error < 0)
0531 return error;
0532 if (cyapa->state != CYAPA_STATE_OP)
0533 return -EAGAIN;
0534
0535 return 0;
0536 }
0537
0538 static u16 cyapa_gen3_csum(const u8 *buf, size_t count)
0539 {
0540 int i;
0541 u16 csum = 0;
0542
0543 for (i = 0; i < count; i++)
0544 csum += buf[i];
0545
0546 return csum;
0547 }
0548
0549
0550
0551
0552
0553
0554
0555
0556
0557
0558
0559
0560
0561
0562
0563
0564 static int cyapa_gen3_check_fw(struct cyapa *cyapa, const struct firmware *fw)
0565 {
0566 struct device *dev = &cyapa->client->dev;
0567 u16 csum;
0568 u16 csum_expected;
0569
0570
0571 if (fw->size != CYAPA_FW_SIZE) {
0572 dev_err(dev, "invalid firmware size = %zu, expected %u.\n",
0573 fw->size, CYAPA_FW_SIZE);
0574 return -EINVAL;
0575 }
0576
0577
0578 csum_expected = (fw->data[0] << 8) | fw->data[1];
0579 csum = cyapa_gen3_csum(&fw->data[2], CYAPA_FW_HDR_SIZE - 2);
0580 if (csum != csum_expected) {
0581 dev_err(dev, "%s %04x, expected: %04x\n",
0582 "invalid firmware header checksum = ",
0583 csum, csum_expected);
0584 return -EINVAL;
0585 }
0586
0587
0588 csum_expected = (fw->data[CYAPA_FW_HDR_SIZE - 2] << 8) |
0589 fw->data[CYAPA_FW_HDR_SIZE - 1];
0590 csum = cyapa_gen3_csum(&fw->data[CYAPA_FW_HDR_SIZE],
0591 CYAPA_FW_DATA_SIZE);
0592 if (csum != csum_expected) {
0593 dev_err(dev, "%s %04x, expected: %04x\n",
0594 "invalid firmware header checksum = ",
0595 csum, csum_expected);
0596 return -EINVAL;
0597 }
0598 return 0;
0599 }
0600
0601
0602
0603
0604
0605
0606
0607
0608 static int cyapa_gen3_write_buffer(struct cyapa *cyapa,
0609 const u8 *buf, size_t len)
0610 {
0611 int error;
0612 size_t i;
0613 unsigned char cmd[CYAPA_CMD_LEN + 1];
0614 size_t cmd_len;
0615
0616 for (i = 0; i < len; i += CYAPA_CMD_LEN) {
0617 const u8 *payload = &buf[i];
0618
0619 cmd_len = (len - i >= CYAPA_CMD_LEN) ? CYAPA_CMD_LEN : len - i;
0620 cmd[0] = i;
0621 memcpy(&cmd[1], payload, cmd_len);
0622
0623 error = cyapa_i2c_reg_write_block(cyapa, 0, cmd_len + 1, cmd);
0624 if (error)
0625 return error;
0626 }
0627 return 0;
0628 }
0629
0630
0631
0632
0633
0634
0635
0636
0637
0638
0639
0640
0641
0642
0643
0644
0645
0646 static int cyapa_gen3_write_fw_block(struct cyapa *cyapa,
0647 u16 block, const u8 *data)
0648 {
0649 int ret;
0650 struct gen3_write_block_cmd write_block_cmd;
0651 u8 status[BL_STATUS_SIZE];
0652 int tries;
0653 u8 bl_status, bl_error;
0654
0655
0656 write_block_cmd.checksum_seed = GEN3_BL_CMD_CHECKSUM_SEED;
0657 write_block_cmd.cmd_code = GEN3_BL_CMD_WRITE_BLOCK;
0658 memcpy(write_block_cmd.key, security_key, sizeof(security_key));
0659 put_unaligned_be16(block, &write_block_cmd.block_num);
0660 memcpy(write_block_cmd.block_data, data, CYAPA_FW_BLOCK_SIZE);
0661 write_block_cmd.block_checksum = cyapa_gen3_csum(
0662 write_block_cmd.block_data, CYAPA_FW_BLOCK_SIZE);
0663 write_block_cmd.cmd_checksum = cyapa_gen3_csum((u8 *)&write_block_cmd,
0664 sizeof(write_block_cmd) - 1);
0665
0666 ret = cyapa_gen3_write_buffer(cyapa, (u8 *)&write_block_cmd,
0667 sizeof(write_block_cmd));
0668 if (ret)
0669 return ret;
0670
0671
0672 tries = 11;
0673 do {
0674 usleep_range(10000, 20000);
0675
0676
0677 ret = cyapa_i2c_reg_read_block(cyapa, BL_HEAD_OFFSET,
0678 BL_STATUS_SIZE, status);
0679 if (ret != BL_STATUS_SIZE)
0680 return (ret < 0) ? ret : -EIO;
0681 } while ((status[REG_BL_STATUS] & BL_STATUS_BUSY) && --tries);
0682
0683
0684 bl_status = status[REG_BL_STATUS] & ~BL_STATUS_REV_MASK;
0685 bl_error = status[REG_BL_ERROR] & ~BL_ERROR_RESERVED;
0686
0687 if (bl_status & BL_STATUS_BUSY)
0688 ret = -ETIMEDOUT;
0689 else if (bl_status != BL_STATUS_RUNNING ||
0690 bl_error != BL_ERROR_BOOTLOADING)
0691 ret = -EIO;
0692 else
0693 ret = 0;
0694
0695 return ret;
0696 }
0697
0698 static int cyapa_gen3_write_blocks(struct cyapa *cyapa,
0699 size_t start_block, size_t block_count,
0700 const u8 *image_data)
0701 {
0702 int error;
0703 int i;
0704
0705 for (i = 0; i < block_count; i++) {
0706 size_t block = start_block + i;
0707 size_t addr = i * CYAPA_FW_BLOCK_SIZE;
0708 const u8 *data = &image_data[addr];
0709
0710 error = cyapa_gen3_write_fw_block(cyapa, block, data);
0711 if (error)
0712 return error;
0713 }
0714 return 0;
0715 }
0716
0717 static int cyapa_gen3_do_fw_update(struct cyapa *cyapa,
0718 const struct firmware *fw)
0719 {
0720 struct device *dev = &cyapa->client->dev;
0721 int error;
0722
0723
0724 error = cyapa_gen3_write_blocks(cyapa,
0725 CYAPA_FW_DATA_BLOCK_START, CYAPA_FW_DATA_BLOCK_COUNT,
0726 &fw->data[CYAPA_FW_HDR_BLOCK_COUNT * CYAPA_FW_BLOCK_SIZE]);
0727 if (error) {
0728 dev_err(dev, "FW update aborted, write image: %d\n", error);
0729 return error;
0730 }
0731
0732
0733 error = cyapa_gen3_write_blocks(cyapa,
0734 CYAPA_FW_HDR_BLOCK_START, CYAPA_FW_HDR_BLOCK_COUNT,
0735 &fw->data[0]);
0736 if (error) {
0737 dev_err(dev, "FW update aborted, write checksum: %d\n", error);
0738 return error;
0739 }
0740
0741 return 0;
0742 }
0743
0744 static ssize_t cyapa_gen3_do_calibrate(struct device *dev,
0745 struct device_attribute *attr,
0746 const char *buf, size_t count)
0747 {
0748 struct cyapa *cyapa = dev_get_drvdata(dev);
0749 unsigned long timeout;
0750 int ret;
0751
0752 ret = cyapa_read_byte(cyapa, CYAPA_CMD_DEV_STATUS);
0753 if (ret < 0) {
0754 dev_err(dev, "Error reading dev status: %d\n", ret);
0755 goto out;
0756 }
0757 if ((ret & CYAPA_DEV_NORMAL) != CYAPA_DEV_NORMAL) {
0758 dev_warn(dev, "Trackpad device is busy, device state: 0x%02x\n",
0759 ret);
0760 ret = -EAGAIN;
0761 goto out;
0762 }
0763
0764 ret = cyapa_write_byte(cyapa, CYAPA_CMD_SOFT_RESET,
0765 OP_RECALIBRATION_MASK);
0766 if (ret < 0) {
0767 dev_err(dev, "Failed to send calibrate command: %d\n",
0768 ret);
0769 goto out;
0770 }
0771
0772
0773 timeout = jiffies + 2 * HZ;
0774 do {
0775
0776
0777
0778
0779
0780 msleep(100);
0781 ret = cyapa_read_byte(cyapa, CYAPA_CMD_DEV_STATUS);
0782 if (ret < 0) {
0783 dev_err(dev, "Error reading dev status: %d\n", ret);
0784 goto out;
0785 }
0786 if ((ret & CYAPA_DEV_NORMAL) == CYAPA_DEV_NORMAL) {
0787 dev_dbg(dev, "Calibration successful.\n");
0788 goto out;
0789 }
0790 } while (time_is_after_jiffies(timeout));
0791
0792 dev_err(dev, "Failed to calibrate. Timeout.\n");
0793 ret = -ETIMEDOUT;
0794
0795 out:
0796 return ret < 0 ? ret : count;
0797 }
0798
0799 static ssize_t cyapa_gen3_show_baseline(struct device *dev,
0800 struct device_attribute *attr, char *buf)
0801 {
0802 struct cyapa *cyapa = dev_get_drvdata(dev);
0803 int max_baseline, min_baseline;
0804 int tries;
0805 int ret;
0806
0807 ret = cyapa_read_byte(cyapa, CYAPA_CMD_DEV_STATUS);
0808 if (ret < 0) {
0809 dev_err(dev, "Error reading dev status. err = %d\n", ret);
0810 goto out;
0811 }
0812 if ((ret & CYAPA_DEV_NORMAL) != CYAPA_DEV_NORMAL) {
0813 dev_warn(dev, "Trackpad device is busy. device state = 0x%x\n",
0814 ret);
0815 ret = -EAGAIN;
0816 goto out;
0817 }
0818
0819 ret = cyapa_write_byte(cyapa, CYAPA_CMD_SOFT_RESET,
0820 OP_REPORT_BASELINE_MASK);
0821 if (ret < 0) {
0822 dev_err(dev, "Failed to send report baseline command. %d\n",
0823 ret);
0824 goto out;
0825 }
0826
0827 tries = 3;
0828 do {
0829 usleep_range(10000, 20000);
0830
0831 ret = cyapa_read_byte(cyapa, CYAPA_CMD_DEV_STATUS);
0832 if (ret < 0) {
0833 dev_err(dev, "Error reading dev status. err = %d\n",
0834 ret);
0835 goto out;
0836 }
0837 if ((ret & CYAPA_DEV_NORMAL) == CYAPA_DEV_NORMAL)
0838 break;
0839 } while (--tries);
0840
0841 if (tries == 0) {
0842 dev_err(dev, "Device timed out going to Normal state.\n");
0843 ret = -ETIMEDOUT;
0844 goto out;
0845 }
0846
0847 ret = cyapa_read_byte(cyapa, CYAPA_CMD_MAX_BASELINE);
0848 if (ret < 0) {
0849 dev_err(dev, "Failed to read max baseline. err = %d\n", ret);
0850 goto out;
0851 }
0852 max_baseline = ret;
0853
0854 ret = cyapa_read_byte(cyapa, CYAPA_CMD_MIN_BASELINE);
0855 if (ret < 0) {
0856 dev_err(dev, "Failed to read min baseline. err = %d\n", ret);
0857 goto out;
0858 }
0859 min_baseline = ret;
0860
0861 dev_dbg(dev, "Baseline report successful. Max: %d Min: %d\n",
0862 max_baseline, min_baseline);
0863 ret = scnprintf(buf, PAGE_SIZE, "%d %d\n", max_baseline, min_baseline);
0864
0865 out:
0866 return ret;
0867 }
0868
0869
0870
0871
0872
0873
0874
0875
0876
0877 static u16 cyapa_get_wait_time_for_pwr_cmd(u8 pwr_mode)
0878 {
0879 switch (pwr_mode) {
0880 case PWR_MODE_FULL_ACTIVE: return 20;
0881 case PWR_MODE_BTN_ONLY: return 20;
0882 case PWR_MODE_OFF: return 20;
0883 default: return cyapa_pwr_cmd_to_sleep_time(pwr_mode) + 50;
0884 }
0885 }
0886
0887
0888
0889
0890
0891
0892
0893
0894
0895
0896
0897
0898
0899
0900
0901
0902
0903
0904
0905
0906
0907 static int cyapa_gen3_set_power_mode(struct cyapa *cyapa, u8 power_mode,
0908 u16 always_unused, enum cyapa_pm_stage pm_stage)
0909 {
0910 struct input_dev *input = cyapa->input;
0911 u8 power;
0912 int tries;
0913 int sleep_time;
0914 int interval;
0915 int ret;
0916
0917 if (cyapa->state != CYAPA_STATE_OP)
0918 return 0;
0919
0920 tries = SET_POWER_MODE_TRIES;
0921 while (tries--) {
0922 ret = cyapa_read_byte(cyapa, CYAPA_CMD_POWER_MODE);
0923 if (ret >= 0)
0924 break;
0925 usleep_range(SET_POWER_MODE_DELAY, 2 * SET_POWER_MODE_DELAY);
0926 }
0927 if (ret < 0)
0928 return ret;
0929
0930
0931
0932
0933
0934 if ((ret & PWR_MODE_MASK) == power_mode)
0935 return 0;
0936
0937 sleep_time = (int)cyapa_get_wait_time_for_pwr_cmd(ret & PWR_MODE_MASK);
0938 power = ret;
0939 power &= ~PWR_MODE_MASK;
0940 power |= power_mode & PWR_MODE_MASK;
0941 tries = SET_POWER_MODE_TRIES;
0942 while (tries--) {
0943 ret = cyapa_write_byte(cyapa, CYAPA_CMD_POWER_MODE, power);
0944 if (!ret)
0945 break;
0946 usleep_range(SET_POWER_MODE_DELAY, 2 * SET_POWER_MODE_DELAY);
0947 }
0948
0949
0950
0951
0952
0953
0954
0955 if (cyapa->operational &&
0956 input && input_device_enabled(input) &&
0957 (pm_stage == CYAPA_PM_RUNTIME_SUSPEND ||
0958 pm_stage == CYAPA_PM_RUNTIME_RESUME)) {
0959
0960 interval = 1000 / 120;
0961 while (sleep_time > 0) {
0962 if (sleep_time > interval)
0963 msleep(interval);
0964 else
0965 msleep(sleep_time);
0966 sleep_time -= interval;
0967 cyapa_gen3_try_poll_handler(cyapa);
0968 }
0969 } else {
0970 msleep(sleep_time);
0971 }
0972
0973 return ret;
0974 }
0975
0976 static int cyapa_gen3_set_proximity(struct cyapa *cyapa, bool enable)
0977 {
0978 return -EOPNOTSUPP;
0979 }
0980
0981 static int cyapa_gen3_get_query_data(struct cyapa *cyapa)
0982 {
0983 u8 query_data[QUERY_DATA_SIZE];
0984 int ret;
0985
0986 if (cyapa->state != CYAPA_STATE_OP)
0987 return -EBUSY;
0988
0989 ret = cyapa_read_block(cyapa, CYAPA_CMD_GROUP_QUERY, query_data);
0990 if (ret != QUERY_DATA_SIZE)
0991 return (ret < 0) ? ret : -EIO;
0992
0993 memcpy(&cyapa->product_id[0], &query_data[0], 5);
0994 cyapa->product_id[5] = '-';
0995 memcpy(&cyapa->product_id[6], &query_data[5], 6);
0996 cyapa->product_id[12] = '-';
0997 memcpy(&cyapa->product_id[13], &query_data[11], 2);
0998 cyapa->product_id[15] = '\0';
0999
1000 cyapa->fw_maj_ver = query_data[15];
1001 cyapa->fw_min_ver = query_data[16];
1002
1003 cyapa->btn_capability = query_data[19] & CAPABILITY_BTN_MASK;
1004
1005 cyapa->gen = query_data[20] & 0x0f;
1006
1007 cyapa->max_abs_x = ((query_data[21] & 0xf0) << 4) | query_data[22];
1008 cyapa->max_abs_y = ((query_data[21] & 0x0f) << 8) | query_data[23];
1009
1010 cyapa->physical_size_x =
1011 ((query_data[24] & 0xf0) << 4) | query_data[25];
1012 cyapa->physical_size_y =
1013 ((query_data[24] & 0x0f) << 8) | query_data[26];
1014
1015 cyapa->max_z = 255;
1016
1017 return 0;
1018 }
1019
1020 static int cyapa_gen3_bl_query_data(struct cyapa *cyapa)
1021 {
1022 u8 bl_data[CYAPA_CMD_LEN];
1023 int ret;
1024
1025 ret = cyapa_i2c_reg_read_block(cyapa, 0, CYAPA_CMD_LEN, bl_data);
1026 if (ret != CYAPA_CMD_LEN)
1027 return (ret < 0) ? ret : -EIO;
1028
1029
1030
1031
1032
1033
1034
1035 if (bl_data[REG_BL_STATUS] ==
1036 (BL_STATUS_RUNNING | BL_STATUS_CSUM_VALID)) {
1037 cyapa->fw_maj_ver = bl_data[GEN3_BL_IDLE_FW_MAJ_VER_OFFSET];
1038 cyapa->fw_min_ver = bl_data[GEN3_BL_IDLE_FW_MIN_VER_OFFSET];
1039 }
1040
1041 return 0;
1042 }
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058 static int cyapa_gen3_do_operational_check(struct cyapa *cyapa)
1059 {
1060 struct device *dev = &cyapa->client->dev;
1061 int error;
1062
1063 switch (cyapa->state) {
1064 case CYAPA_STATE_BL_ACTIVE:
1065 error = cyapa_gen3_bl_deactivate(cyapa);
1066 if (error) {
1067 dev_err(dev, "failed to bl_deactivate: %d\n", error);
1068 return error;
1069 }
1070
1071 fallthrough;
1072 case CYAPA_STATE_BL_IDLE:
1073
1074 cyapa_gen3_bl_query_data(cyapa);
1075
1076 error = cyapa_gen3_bl_exit(cyapa);
1077 if (error) {
1078 dev_err(dev, "failed to bl_exit: %d\n", error);
1079 return error;
1080 }
1081
1082 fallthrough;
1083 case CYAPA_STATE_OP:
1084
1085
1086
1087
1088 error = cyapa_gen3_set_power_mode(cyapa,
1089 PWR_MODE_FULL_ACTIVE, 0, CYAPA_PM_ACTIVE);
1090 if (error)
1091 dev_err(dev, "%s: set full power mode failed: %d\n",
1092 __func__, error);
1093 error = cyapa_gen3_get_query_data(cyapa);
1094 if (error < 0)
1095 return error;
1096
1097
1098 if (cyapa->gen != CYAPA_GEN3) {
1099 dev_err(dev, "unsupported protocol version (%d)",
1100 cyapa->gen);
1101 return -EINVAL;
1102 }
1103
1104
1105 if (memcmp(cyapa->product_id, product_id,
1106 strlen(product_id)) != 0) {
1107 dev_err(dev, "unsupported product ID (%s)\n",
1108 cyapa->product_id);
1109 return -EINVAL;
1110 }
1111
1112 return 0;
1113
1114 default:
1115 return -EIO;
1116 }
1117 return 0;
1118 }
1119
1120
1121
1122
1123
1124 static bool cyapa_gen3_irq_cmd_handler(struct cyapa *cyapa)
1125 {
1126
1127 if (cyapa->gen != CYAPA_GEN3)
1128 return true;
1129
1130 if (cyapa->operational)
1131 return true;
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142 return false;
1143 }
1144
1145 static int cyapa_gen3_event_process(struct cyapa *cyapa,
1146 struct cyapa_reg_data *data)
1147 {
1148 struct input_dev *input = cyapa->input;
1149 int num_fingers;
1150 int i;
1151
1152 num_fingers = (data->finger_btn >> 4) & 0x0f;
1153 for (i = 0; i < num_fingers; i++) {
1154 const struct cyapa_touch *touch = &data->touches[i];
1155
1156 int slot = touch->id - 1;
1157
1158 input_mt_slot(input, slot);
1159 input_mt_report_slot_state(input, MT_TOOL_FINGER, true);
1160 input_report_abs(input, ABS_MT_POSITION_X,
1161 ((touch->xy_hi & 0xf0) << 4) | touch->x_lo);
1162 input_report_abs(input, ABS_MT_POSITION_Y,
1163 ((touch->xy_hi & 0x0f) << 8) | touch->y_lo);
1164 input_report_abs(input, ABS_MT_PRESSURE, touch->pressure);
1165 }
1166
1167 input_mt_sync_frame(input);
1168
1169 if (cyapa->btn_capability & CAPABILITY_LEFT_BTN_MASK)
1170 input_report_key(input, BTN_LEFT,
1171 !!(data->finger_btn & OP_DATA_LEFT_BTN));
1172 if (cyapa->btn_capability & CAPABILITY_MIDDLE_BTN_MASK)
1173 input_report_key(input, BTN_MIDDLE,
1174 !!(data->finger_btn & OP_DATA_MIDDLE_BTN));
1175 if (cyapa->btn_capability & CAPABILITY_RIGHT_BTN_MASK)
1176 input_report_key(input, BTN_RIGHT,
1177 !!(data->finger_btn & OP_DATA_RIGHT_BTN));
1178 input_sync(input);
1179
1180 return 0;
1181 }
1182
1183 static int cyapa_gen3_irq_handler(struct cyapa *cyapa)
1184 {
1185 struct device *dev = &cyapa->client->dev;
1186 struct cyapa_reg_data data;
1187 int ret;
1188
1189 ret = cyapa_read_block(cyapa, CYAPA_CMD_GROUP_DATA, (u8 *)&data);
1190 if (ret != sizeof(data)) {
1191 dev_err(dev, "failed to read report data, (%d)\n", ret);
1192 return -EINVAL;
1193 }
1194
1195 if ((data.device_status & OP_STATUS_SRC) != OP_STATUS_SRC ||
1196 (data.device_status & OP_STATUS_DEV) != CYAPA_DEV_NORMAL ||
1197 (data.finger_btn & OP_DATA_VALID) != OP_DATA_VALID) {
1198 dev_err(dev, "invalid device state bytes: %02x %02x\n",
1199 data.device_status, data.finger_btn);
1200 return -EINVAL;
1201 }
1202
1203 return cyapa_gen3_event_process(cyapa, &data);
1204 }
1205
1206
1207
1208
1209
1210
1211
1212 static int cyapa_gen3_try_poll_handler(struct cyapa *cyapa)
1213 {
1214 struct cyapa_reg_data data;
1215 int ret;
1216
1217 ret = cyapa_read_block(cyapa, CYAPA_CMD_GROUP_DATA, (u8 *)&data);
1218 if (ret != sizeof(data))
1219 return -EINVAL;
1220
1221 if ((data.device_status & OP_STATUS_SRC) != OP_STATUS_SRC ||
1222 (data.device_status & OP_STATUS_DEV) != CYAPA_DEV_NORMAL ||
1223 (data.finger_btn & OP_DATA_VALID) != OP_DATA_VALID)
1224 return -EINVAL;
1225
1226 return cyapa_gen3_event_process(cyapa, &data);
1227
1228 }
1229
1230 static int cyapa_gen3_initialize(struct cyapa *cyapa) { return 0; }
1231 static int cyapa_gen3_bl_initiate(struct cyapa *cyapa,
1232 const struct firmware *fw) { return 0; }
1233 static int cyapa_gen3_empty_output_data(struct cyapa *cyapa,
1234 u8 *buf, int *len, cb_sort func) { return 0; }
1235
1236 const struct cyapa_dev_ops cyapa_gen3_ops = {
1237 .check_fw = cyapa_gen3_check_fw,
1238 .bl_enter = cyapa_gen3_bl_enter,
1239 .bl_activate = cyapa_gen3_bl_activate,
1240 .update_fw = cyapa_gen3_do_fw_update,
1241 .bl_deactivate = cyapa_gen3_bl_deactivate,
1242 .bl_initiate = cyapa_gen3_bl_initiate,
1243
1244 .show_baseline = cyapa_gen3_show_baseline,
1245 .calibrate_store = cyapa_gen3_do_calibrate,
1246
1247 .initialize = cyapa_gen3_initialize,
1248
1249 .state_parse = cyapa_gen3_state_parse,
1250 .operational_check = cyapa_gen3_do_operational_check,
1251
1252 .irq_handler = cyapa_gen3_irq_handler,
1253 .irq_cmd_handler = cyapa_gen3_irq_cmd_handler,
1254 .sort_empty_output_data = cyapa_gen3_empty_output_data,
1255 .set_power_mode = cyapa_gen3_set_power_mode,
1256
1257 .set_proximity = cyapa_gen3_set_proximity,
1258 };