Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    2)  * Cypress APA trackpad with I2C interface
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    3)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    4)  * Author: Dudley Du <dudl@cypress.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    5)  * Further cleanup and restructuring by:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    6)  *   Daniel Kurtz <djkurtz@chromium.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    7)  *   Benson Leung <bleung@chromium.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    8)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    9)  * Copyright (C) 2011-2015 Cypress Semiconductor, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   10)  * Copyright (C) 2011-2012 Google, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   11)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   12)  * This file is subject to the terms and conditions of the GNU General Public
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   13)  * License.  See the file COPYING in the main directory of this archive for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   14)  * more details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   15)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   16) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   17) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   18) #include <linux/i2c.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   19) #include <linux/input.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   20) #include <linux/input/mt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   21) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   22) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   23) #include <asm/unaligned.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   24) #include "cyapa.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   25) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   26) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   27) #define GEN3_MAX_FINGERS 5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   28) #define GEN3_FINGER_NUM(x) (((x) >> 4) & 0x07)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   29) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   30) #define BLK_HEAD_BYTES 32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   31) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   32) /* Macro for register map group offset. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   33) #define PRODUCT_ID_SIZE  16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   34) #define QUERY_DATA_SIZE  27
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   35) #define REG_PROTOCOL_GEN_QUERY_OFFSET  20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   36) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   37) #define REG_OFFSET_DATA_BASE     0x0000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   38) #define REG_OFFSET_COMMAND_BASE  0x0028
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   39) #define REG_OFFSET_QUERY_BASE    0x002a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   40) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   41) #define CYAPA_OFFSET_SOFT_RESET  REG_OFFSET_COMMAND_BASE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   42) #define OP_RECALIBRATION_MASK    0x80
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   43) #define OP_REPORT_BASELINE_MASK  0x40
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   44) #define REG_OFFSET_MAX_BASELINE  0x0026
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   45) #define REG_OFFSET_MIN_BASELINE  0x0027
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   46) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   47) #define REG_OFFSET_POWER_MODE (REG_OFFSET_COMMAND_BASE + 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   48) #define SET_POWER_MODE_DELAY   10000  /* Unit: us */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   49) #define SET_POWER_MODE_TRIES   5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   50) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   51) #define GEN3_BL_CMD_CHECKSUM_SEED 0xff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   52) #define GEN3_BL_CMD_INITIATE_BL   0x38
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   53) #define GEN3_BL_CMD_WRITE_BLOCK   0x39
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   54) #define GEN3_BL_CMD_VERIFY_BLOCK  0x3a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   55) #define GEN3_BL_CMD_TERMINATE_BL  0x3b
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   56) #define GEN3_BL_CMD_LAUNCH_APP    0xa5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   57) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   58) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   59)  * CYAPA trackpad device states.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   60)  * Used in register 0x00, bit1-0, DeviceStatus field.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   61)  * Other values indicate device is in an abnormal state and must be reset.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   62)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   63) #define CYAPA_DEV_NORMAL  0x03
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   64) #define CYAPA_DEV_BUSY    0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   65) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   66) #define CYAPA_FW_BLOCK_SIZE	64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   67) #define CYAPA_FW_READ_SIZE	16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   68) #define CYAPA_FW_HDR_START	0x0780
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   69) #define CYAPA_FW_HDR_BLOCK_COUNT  2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   70) #define CYAPA_FW_HDR_BLOCK_START  (CYAPA_FW_HDR_START / CYAPA_FW_BLOCK_SIZE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   71) #define CYAPA_FW_HDR_SIZE	  (CYAPA_FW_HDR_BLOCK_COUNT * \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   72) 					CYAPA_FW_BLOCK_SIZE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   73) #define CYAPA_FW_DATA_START	0x0800
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   74) #define CYAPA_FW_DATA_BLOCK_COUNT  480
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   75) #define CYAPA_FW_DATA_BLOCK_START  (CYAPA_FW_DATA_START / CYAPA_FW_BLOCK_SIZE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   76) #define CYAPA_FW_DATA_SIZE	(CYAPA_FW_DATA_BLOCK_COUNT * \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   77) 				 CYAPA_FW_BLOCK_SIZE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   78) #define CYAPA_FW_SIZE		(CYAPA_FW_HDR_SIZE + CYAPA_FW_DATA_SIZE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   79) #define CYAPA_CMD_LEN		16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   80) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   81) #define GEN3_BL_IDLE_FW_MAJ_VER_OFFSET 0x0b
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   82) #define GEN3_BL_IDLE_FW_MIN_VER_OFFSET (GEN3_BL_IDLE_FW_MAJ_VER_OFFSET + 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   83) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   84) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   85) struct cyapa_touch {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   86) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   87) 	 * high bits or x/y position value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   88) 	 * bit 7 - 4: high 4 bits of x position value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   89) 	 * bit 3 - 0: high 4 bits of y position value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   90) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   91) 	u8 xy_hi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   92) 	u8 x_lo;  /* low 8 bits of x position value. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   93) 	u8 y_lo;  /* low 8 bits of y position value. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   94) 	u8 pressure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   95) 	/* id range is 1 - 15.  It is incremented with every new touch. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   96) 	u8 id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   97) } __packed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   98) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   99) struct cyapa_reg_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  100) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  101) 	 * bit 0 - 1: device status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  102) 	 * bit 3 - 2: power mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  103) 	 * bit 6 - 4: reserved
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  104) 	 * bit 7: interrupt valid bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  105) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  106) 	u8 device_status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  107) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  108) 	 * bit 7 - 4: number of fingers currently touching pad
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  109) 	 * bit 3: valid data check bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  110) 	 * bit 2: middle mechanism button state if exists
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  111) 	 * bit 1: right mechanism button state if exists
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  112) 	 * bit 0: left mechanism button state if exists
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  113) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  114) 	u8 finger_btn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  115) 	/* CYAPA reports up to 5 touches per packet. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  116) 	struct cyapa_touch touches[5];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  117) } __packed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  118) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  119) struct gen3_write_block_cmd {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  120) 	u8 checksum_seed;  /* Always be 0xff */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  121) 	u8 cmd_code;       /* command code: 0x39 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  122) 	u8 key[8];         /* 8-byte security key */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  123) 	__be16 block_num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  124) 	u8 block_data[CYAPA_FW_BLOCK_SIZE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  125) 	u8 block_checksum;  /* Calculated using bytes 12 - 75 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  126) 	u8 cmd_checksum;    /* Calculated using bytes 0-76 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  127) } __packed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  128) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  129) static const u8 security_key[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  130) 		0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  131) static const u8 bl_activate[] = { 0x00, 0xff, 0x38, 0x00, 0x01, 0x02, 0x03,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  132) 		0x04, 0x05, 0x06, 0x07 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  133) static const u8 bl_deactivate[] = { 0x00, 0xff, 0x3b, 0x00, 0x01, 0x02, 0x03,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  134) 		0x04, 0x05, 0x06, 0x07 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  135) static const u8 bl_exit[] = { 0x00, 0xff, 0xa5, 0x00, 0x01, 0x02, 0x03, 0x04,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  136) 		0x05, 0x06, 0x07 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  137) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  138) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  139)  /* for byte read/write command */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  140) #define CMD_RESET 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  141) #define CMD_POWER_MODE 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  142) #define CMD_DEV_STATUS 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  143) #define CMD_REPORT_MAX_BASELINE 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  144) #define CMD_REPORT_MIN_BASELINE 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  145) #define SMBUS_BYTE_CMD(cmd) (((cmd) & 0x3f) << 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  146) #define CYAPA_SMBUS_RESET         SMBUS_BYTE_CMD(CMD_RESET)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  147) #define CYAPA_SMBUS_POWER_MODE    SMBUS_BYTE_CMD(CMD_POWER_MODE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  148) #define CYAPA_SMBUS_DEV_STATUS    SMBUS_BYTE_CMD(CMD_DEV_STATUS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  149) #define CYAPA_SMBUS_MAX_BASELINE  SMBUS_BYTE_CMD(CMD_REPORT_MAX_BASELINE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  150) #define CYAPA_SMBUS_MIN_BASELINE  SMBUS_BYTE_CMD(CMD_REPORT_MIN_BASELINE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  151) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  152)  /* for group registers read/write command */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  153) #define REG_GROUP_DATA  0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  154) #define REG_GROUP_CMD   2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  155) #define REG_GROUP_QUERY 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  156) #define SMBUS_GROUP_CMD(grp) (0x80 | (((grp) & 0x07) << 3))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  157) #define CYAPA_SMBUS_GROUP_DATA  SMBUS_GROUP_CMD(REG_GROUP_DATA)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  158) #define CYAPA_SMBUS_GROUP_CMD   SMBUS_GROUP_CMD(REG_GROUP_CMD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  159) #define CYAPA_SMBUS_GROUP_QUERY SMBUS_GROUP_CMD(REG_GROUP_QUERY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  160) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  161)  /* for register block read/write command */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  162) #define CMD_BL_STATUS		0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  163) #define CMD_BL_HEAD		1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  164) #define CMD_BL_CMD		2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  165) #define CMD_BL_DATA		3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  166) #define CMD_BL_ALL		4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  167) #define CMD_BLK_PRODUCT_ID	5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  168) #define CMD_BLK_HEAD		6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  169) #define SMBUS_BLOCK_CMD(cmd) (0xc0 | (((cmd) & 0x1f) << 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  170) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  171) /* register block read/write command in bootloader mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  172) #define CYAPA_SMBUS_BL_STATUS SMBUS_BLOCK_CMD(CMD_BL_STATUS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  173) #define CYAPA_SMBUS_BL_HEAD   SMBUS_BLOCK_CMD(CMD_BL_HEAD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  174) #define CYAPA_SMBUS_BL_CMD    SMBUS_BLOCK_CMD(CMD_BL_CMD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  175) #define CYAPA_SMBUS_BL_DATA   SMBUS_BLOCK_CMD(CMD_BL_DATA)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  176) #define CYAPA_SMBUS_BL_ALL    SMBUS_BLOCK_CMD(CMD_BL_ALL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  177) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  178) /* register block read/write command in operational mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  179) #define CYAPA_SMBUS_BLK_PRODUCT_ID SMBUS_BLOCK_CMD(CMD_BLK_PRODUCT_ID)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  180) #define CYAPA_SMBUS_BLK_HEAD       SMBUS_BLOCK_CMD(CMD_BLK_HEAD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  181) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  182) struct cyapa_cmd_len {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  183) 	u8 cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  184) 	u8 len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  185) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  186) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  187) /* maps generic CYAPA_CMD_* code to the I2C equivalent */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  188) static const struct cyapa_cmd_len cyapa_i2c_cmds[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  189) 	{ CYAPA_OFFSET_SOFT_RESET, 1 },		/* CYAPA_CMD_SOFT_RESET */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  190) 	{ REG_OFFSET_COMMAND_BASE + 1, 1 },	/* CYAPA_CMD_POWER_MODE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  191) 	{ REG_OFFSET_DATA_BASE, 1 },		/* CYAPA_CMD_DEV_STATUS */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  192) 	{ REG_OFFSET_DATA_BASE, sizeof(struct cyapa_reg_data) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  193) 						/* CYAPA_CMD_GROUP_DATA */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  194) 	{ REG_OFFSET_COMMAND_BASE, 0 },		/* CYAPA_CMD_GROUP_CMD */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  195) 	{ REG_OFFSET_QUERY_BASE, QUERY_DATA_SIZE }, /* CYAPA_CMD_GROUP_QUERY */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  196) 	{ BL_HEAD_OFFSET, 3 },			/* CYAPA_CMD_BL_STATUS */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  197) 	{ BL_HEAD_OFFSET, 16 },			/* CYAPA_CMD_BL_HEAD */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  198) 	{ BL_HEAD_OFFSET, 16 },			/* CYAPA_CMD_BL_CMD */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  199) 	{ BL_DATA_OFFSET, 16 },			/* CYAPA_CMD_BL_DATA */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  200) 	{ BL_HEAD_OFFSET, 32 },			/* CYAPA_CMD_BL_ALL */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  201) 	{ REG_OFFSET_QUERY_BASE, PRODUCT_ID_SIZE },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  202) 						/* CYAPA_CMD_BLK_PRODUCT_ID */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  203) 	{ REG_OFFSET_DATA_BASE, 32 },		/* CYAPA_CMD_BLK_HEAD */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  204) 	{ REG_OFFSET_MAX_BASELINE, 1 },		/* CYAPA_CMD_MAX_BASELINE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  205) 	{ REG_OFFSET_MIN_BASELINE, 1 },		/* CYAPA_CMD_MIN_BASELINE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  206) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  207) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  208) static const struct cyapa_cmd_len cyapa_smbus_cmds[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  209) 	{ CYAPA_SMBUS_RESET, 1 },		/* CYAPA_CMD_SOFT_RESET */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  210) 	{ CYAPA_SMBUS_POWER_MODE, 1 },		/* CYAPA_CMD_POWER_MODE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  211) 	{ CYAPA_SMBUS_DEV_STATUS, 1 },		/* CYAPA_CMD_DEV_STATUS */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  212) 	{ CYAPA_SMBUS_GROUP_DATA, sizeof(struct cyapa_reg_data) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  213) 						/* CYAPA_CMD_GROUP_DATA */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  214) 	{ CYAPA_SMBUS_GROUP_CMD, 2 },		/* CYAPA_CMD_GROUP_CMD */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  215) 	{ CYAPA_SMBUS_GROUP_QUERY, QUERY_DATA_SIZE },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  216) 						/* CYAPA_CMD_GROUP_QUERY */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  217) 	{ CYAPA_SMBUS_BL_STATUS, 3 },		/* CYAPA_CMD_BL_STATUS */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  218) 	{ CYAPA_SMBUS_BL_HEAD, 16 },		/* CYAPA_CMD_BL_HEAD */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  219) 	{ CYAPA_SMBUS_BL_CMD, 16 },		/* CYAPA_CMD_BL_CMD */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  220) 	{ CYAPA_SMBUS_BL_DATA, 16 },		/* CYAPA_CMD_BL_DATA */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  221) 	{ CYAPA_SMBUS_BL_ALL, 32 },		/* CYAPA_CMD_BL_ALL */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  222) 	{ CYAPA_SMBUS_BLK_PRODUCT_ID, PRODUCT_ID_SIZE },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  223) 						/* CYAPA_CMD_BLK_PRODUCT_ID */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  224) 	{ CYAPA_SMBUS_BLK_HEAD, 16 },		/* CYAPA_CMD_BLK_HEAD */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  225) 	{ CYAPA_SMBUS_MAX_BASELINE, 1 },	/* CYAPA_CMD_MAX_BASELINE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  226) 	{ CYAPA_SMBUS_MIN_BASELINE, 1 },	/* CYAPA_CMD_MIN_BASELINE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  227) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  228) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  229) static int cyapa_gen3_try_poll_handler(struct cyapa *cyapa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  230) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  231) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  232)  * cyapa_smbus_read_block - perform smbus block read command
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  233)  * @cyapa  - private data structure of the driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  234)  * @cmd    - the properly encoded smbus command
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  235)  * @len    - expected length of smbus command result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  236)  * @values - buffer to store smbus command result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  237)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  238)  * Returns negative errno, else the number of bytes written.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  239)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  240)  * Note:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  241)  * In trackpad device, the memory block allocated for I2C register map
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  242)  * is 256 bytes, so the max read block for I2C bus is 256 bytes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  243)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  244) ssize_t cyapa_smbus_read_block(struct cyapa *cyapa, u8 cmd, size_t len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  245) 				      u8 *values)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  246) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  247) 	ssize_t ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  248) 	u8 index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  249) 	u8 smbus_cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  250) 	u8 *buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  251) 	struct i2c_client *client = cyapa->client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  252) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  253) 	if (!(SMBUS_BYTE_BLOCK_CMD_MASK & cmd))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  254) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  255) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  256) 	if (SMBUS_GROUP_BLOCK_CMD_MASK & cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  257) 		/* read specific block registers command. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  258) 		smbus_cmd = SMBUS_ENCODE_RW(cmd, SMBUS_READ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  259) 		ret = i2c_smbus_read_block_data(client, smbus_cmd, values);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  260) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  261) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  262) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  263) 	ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  264) 	for (index = 0; index * I2C_SMBUS_BLOCK_MAX < len; index++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  265) 		smbus_cmd = SMBUS_ENCODE_IDX(cmd, index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  266) 		smbus_cmd = SMBUS_ENCODE_RW(smbus_cmd, SMBUS_READ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  267) 		buf = values + I2C_SMBUS_BLOCK_MAX * index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  268) 		ret = i2c_smbus_read_block_data(client, smbus_cmd, buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  269) 		if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  270) 			goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  271) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  272) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  273) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  274) 	return ret > 0 ? len : ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  275) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  276) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  277) static s32 cyapa_read_byte(struct cyapa *cyapa, u8 cmd_idx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  278) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  279) 	u8 cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  280) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  281) 	if (cyapa->smbus) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  282) 		cmd = cyapa_smbus_cmds[cmd_idx].cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  283) 		cmd = SMBUS_ENCODE_RW(cmd, SMBUS_READ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  284) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  285) 		cmd = cyapa_i2c_cmds[cmd_idx].cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  286) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  287) 	return i2c_smbus_read_byte_data(cyapa->client, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  288) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  289) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  290) static s32 cyapa_write_byte(struct cyapa *cyapa, u8 cmd_idx, u8 value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  291) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  292) 	u8 cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  293) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  294) 	if (cyapa->smbus) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  295) 		cmd = cyapa_smbus_cmds[cmd_idx].cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  296) 		cmd = SMBUS_ENCODE_RW(cmd, SMBUS_WRITE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  297) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  298) 		cmd = cyapa_i2c_cmds[cmd_idx].cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  299) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  300) 	return i2c_smbus_write_byte_data(cyapa->client, cmd, value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  301) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  302) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  303) ssize_t cyapa_i2c_reg_read_block(struct cyapa *cyapa, u8 reg, size_t len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  304) 					u8 *values)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  305) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  306) 	return i2c_smbus_read_i2c_block_data(cyapa->client, reg, len, values);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  307) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  308) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  309) static ssize_t cyapa_i2c_reg_write_block(struct cyapa *cyapa, u8 reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  310) 					 size_t len, const u8 *values)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  311) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  312) 	return i2c_smbus_write_i2c_block_data(cyapa->client, reg, len, values);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  313) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  314) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  315) ssize_t cyapa_read_block(struct cyapa *cyapa, u8 cmd_idx, u8 *values)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  316) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  317) 	u8 cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  318) 	size_t len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  319) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  320) 	if (cyapa->smbus) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  321) 		cmd = cyapa_smbus_cmds[cmd_idx].cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  322) 		len = cyapa_smbus_cmds[cmd_idx].len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  323) 		return cyapa_smbus_read_block(cyapa, cmd, len, values);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  324) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  325) 	cmd = cyapa_i2c_cmds[cmd_idx].cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  326) 	len = cyapa_i2c_cmds[cmd_idx].len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  327) 	return cyapa_i2c_reg_read_block(cyapa, cmd, len, values);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  328) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  329) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  330) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  331)  * Determine the Gen3 trackpad device's current operating state.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  332)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  333)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  334) static int cyapa_gen3_state_parse(struct cyapa *cyapa, u8 *reg_data, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  335) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  336) 	cyapa->state = CYAPA_STATE_NO_DEVICE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  337) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  338) 	/* Parse based on Gen3 characteristic registers and bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  339) 	if (reg_data[REG_BL_FILE] == BL_FILE &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  340) 		reg_data[REG_BL_ERROR] == BL_ERROR_NO_ERR_IDLE &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  341) 		(reg_data[REG_BL_STATUS] ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  342) 			(BL_STATUS_RUNNING | BL_STATUS_CSUM_VALID) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  343) 			reg_data[REG_BL_STATUS] == BL_STATUS_RUNNING)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  344) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  345) 		 * Normal state after power on or reset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  346) 		 * REG_BL_STATUS == 0x11, firmware image checksum is valid.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  347) 		 * REG_BL_STATUS == 0x10, firmware image checksum is invalid.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  348) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  349) 		cyapa->gen = CYAPA_GEN3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  350) 		cyapa->state = CYAPA_STATE_BL_IDLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  351) 	} else if (reg_data[REG_BL_FILE] == BL_FILE &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  352) 		(reg_data[REG_BL_STATUS] & BL_STATUS_RUNNING) ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  353) 			BL_STATUS_RUNNING) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  354) 		cyapa->gen = CYAPA_GEN3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  355) 		if (reg_data[REG_BL_STATUS] & BL_STATUS_BUSY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  356) 			cyapa->state = CYAPA_STATE_BL_BUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  357) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  358) 			if ((reg_data[REG_BL_ERROR] & BL_ERROR_BOOTLOADING) ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  359) 					BL_ERROR_BOOTLOADING)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  360) 				cyapa->state = CYAPA_STATE_BL_ACTIVE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  361) 			else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  362) 				cyapa->state = CYAPA_STATE_BL_IDLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  363) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  364) 	} else if ((reg_data[REG_OP_STATUS] & OP_STATUS_SRC) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  365) 			(reg_data[REG_OP_DATA1] & OP_DATA_VALID)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  366) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  367) 		 * Normal state when running in operational mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  368) 		 * may also not in full power state or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  369) 		 * busying in command process.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  370) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  371) 		if (GEN3_FINGER_NUM(reg_data[REG_OP_DATA1]) <=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  372) 				GEN3_MAX_FINGERS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  373) 			/* Finger number data is valid. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  374) 			cyapa->gen = CYAPA_GEN3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  375) 			cyapa->state = CYAPA_STATE_OP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  376) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  377) 	} else if (reg_data[REG_OP_STATUS] == 0x0C &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  378) 			reg_data[REG_OP_DATA1] == 0x08) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  379) 		/* Op state when first two registers overwritten with 0x00 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  380) 		cyapa->gen = CYAPA_GEN3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  381) 		cyapa->state = CYAPA_STATE_OP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  382) 	} else if (reg_data[REG_BL_STATUS] &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  383) 			(BL_STATUS_RUNNING | BL_STATUS_BUSY)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  384) 		cyapa->gen = CYAPA_GEN3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  385) 		cyapa->state = CYAPA_STATE_BL_BUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  386) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  387) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  388) 	if (cyapa->gen == CYAPA_GEN3 && (cyapa->state == CYAPA_STATE_OP ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  389) 		cyapa->state == CYAPA_STATE_BL_IDLE ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  390) 		cyapa->state == CYAPA_STATE_BL_ACTIVE ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  391) 		cyapa->state == CYAPA_STATE_BL_BUSY))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  392) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  393) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  394) 	return -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  395) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  396) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  397) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  398)  * Enter bootloader by soft resetting the device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  399)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  400)  * If device is already in the bootloader, the function just returns.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  401)  * Otherwise, reset the device; after reset, device enters bootloader idle
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  402)  * state immediately.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  403)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  404)  * Returns:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  405)  *   0        on success
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  406)  *   -EAGAIN  device was reset, but is not now in bootloader idle state
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  407)  *   < 0      if the device never responds within the timeout
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  408)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  409) static int cyapa_gen3_bl_enter(struct cyapa *cyapa)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  410) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  411) 	int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  412) 	int waiting_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  413) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  414) 	error = cyapa_poll_state(cyapa, 500);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  415) 	if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  416) 		return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  417) 	if (cyapa->state == CYAPA_STATE_BL_IDLE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  418) 		/* Already in BL_IDLE. Skipping reset. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  419) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  420) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  421) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  422) 	if (cyapa->state != CYAPA_STATE_OP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  423) 		return -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  424) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  425) 	cyapa->operational = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  426) 	cyapa->state = CYAPA_STATE_NO_DEVICE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  427) 	error = cyapa_write_byte(cyapa, CYAPA_CMD_SOFT_RESET, 0x01);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  428) 	if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  429) 		return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  430) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  431) 	usleep_range(25000, 50000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  432) 	waiting_time = 2000;  /* For some shipset, max waiting time is 1~2s. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  433) 	do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  434) 		error = cyapa_poll_state(cyapa, 500);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  435) 		if (error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  436) 			if (error == -ETIMEDOUT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  437) 				waiting_time -= 500;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  438) 				continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  439) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  440) 			return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  441) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  442) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  443) 		if ((cyapa->state == CYAPA_STATE_BL_IDLE) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  444) 			!(cyapa->status[REG_BL_STATUS] & BL_STATUS_WATCHDOG))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  445) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  446) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  447) 		msleep(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  448) 		waiting_time -= 100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  449) 	} while (waiting_time > 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  450) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  451) 	if ((cyapa->state != CYAPA_STATE_BL_IDLE) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  452) 		(cyapa->status[REG_BL_STATUS] & BL_STATUS_WATCHDOG))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  453) 		return -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  454) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  455) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  456) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  457) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  458) static int cyapa_gen3_bl_activate(struct cyapa *cyapa)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  459) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  460) 	int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  461) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  462) 	error = cyapa_i2c_reg_write_block(cyapa, 0, sizeof(bl_activate),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  463) 					bl_activate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  464) 	if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  465) 		return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  466) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  467) 	/* Wait for bootloader to activate; takes between 2 and 12 seconds */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  468) 	msleep(2000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  469) 	error = cyapa_poll_state(cyapa, 11000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  470) 	if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  471) 		return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  472) 	if (cyapa->state != CYAPA_STATE_BL_ACTIVE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  473) 		return -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  474) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  475) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  476) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  477) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  478) static int cyapa_gen3_bl_deactivate(struct cyapa *cyapa)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  479) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  480) 	int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  481) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  482) 	error = cyapa_i2c_reg_write_block(cyapa, 0, sizeof(bl_deactivate),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  483) 					bl_deactivate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  484) 	if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  485) 		return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  486) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  487) 	/* Wait for bootloader to switch to idle state; should take < 100ms */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  488) 	msleep(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  489) 	error = cyapa_poll_state(cyapa, 500);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  490) 	if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  491) 		return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  492) 	if (cyapa->state != CYAPA_STATE_BL_IDLE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  493) 		return -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  494) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  495) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  496) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  497) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  498)  * Exit bootloader
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  499)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  500)  * Send bl_exit command, then wait 50 - 100 ms to let device transition to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  501)  * operational mode.  If this is the first time the device's firmware is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  502)  * running, it can take up to 2 seconds to calibrate its sensors.  So, poll
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  503)  * the device's new state for up to 2 seconds.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  504)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  505)  * Returns:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  506)  *   -EIO    failure while reading from device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  507)  *   -EAGAIN device is stuck in bootloader, b/c it has invalid firmware
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  508)  *   0       device is supported and in operational mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  509)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  510) static int cyapa_gen3_bl_exit(struct cyapa *cyapa)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  511) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  512) 	int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  513) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  514) 	error = cyapa_i2c_reg_write_block(cyapa, 0, sizeof(bl_exit), bl_exit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  515) 	if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  516) 		return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  517) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  518) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  519) 	 * Wait for bootloader to exit, and operation mode to start.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  520) 	 * Normally, this takes at least 50 ms.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  521) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  522) 	msleep(50);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  523) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  524) 	 * In addition, when a device boots for the first time after being
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  525) 	 * updated to new firmware, it must first calibrate its sensors, which
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  526) 	 * can take up to an additional 2 seconds. If the device power is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  527) 	 * running low, this may take even longer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  528) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  529) 	error = cyapa_poll_state(cyapa, 4000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  530) 	if (error < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  531) 		return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  532) 	if (cyapa->state != CYAPA_STATE_OP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  533) 		return -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  534) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  535) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  536) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  537) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  538) static u16 cyapa_gen3_csum(const u8 *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  539) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  540) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  541) 	u16 csum = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  542) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  543) 	for (i = 0; i < count; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  544) 		csum += buf[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  545) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  546) 	return csum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  547) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  548) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  549) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  550)  * Verify the integrity of a CYAPA firmware image file.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  551)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  552)  * The firmware image file is 30848 bytes, composed of 482 64-byte blocks.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  553)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  554)  * The first 2 blocks are the firmware header.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  555)  * The next 480 blocks are the firmware image.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  556)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  557)  * The first two bytes of the header hold the header checksum, computed by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  558)  * summing the other 126 bytes of the header.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  559)  * The last two bytes of the header hold the firmware image checksum, computed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  560)  * by summing the 30720 bytes of the image modulo 0xffff.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  561)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  562)  * Both checksums are stored little-endian.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  563)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  564) static int cyapa_gen3_check_fw(struct cyapa *cyapa, const struct firmware *fw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  565) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  566) 	struct device *dev = &cyapa->client->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  567) 	u16 csum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  568) 	u16 csum_expected;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  569) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  570) 	/* Firmware must match exact 30848 bytes = 482 64-byte blocks. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  571) 	if (fw->size != CYAPA_FW_SIZE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  572) 		dev_err(dev, "invalid firmware size = %zu, expected %u.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  573) 			fw->size, CYAPA_FW_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  574) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  575) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  576) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  577) 	/* Verify header block */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  578) 	csum_expected = (fw->data[0] << 8) | fw->data[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  579) 	csum = cyapa_gen3_csum(&fw->data[2], CYAPA_FW_HDR_SIZE - 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  580) 	if (csum != csum_expected) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  581) 		dev_err(dev, "%s %04x, expected: %04x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  582) 			"invalid firmware header checksum = ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  583) 			csum, csum_expected);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  584) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  585) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  586) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  587) 	/* Verify firmware image */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  588) 	csum_expected = (fw->data[CYAPA_FW_HDR_SIZE - 2] << 8) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  589) 			 fw->data[CYAPA_FW_HDR_SIZE - 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  590) 	csum = cyapa_gen3_csum(&fw->data[CYAPA_FW_HDR_SIZE],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  591) 			CYAPA_FW_DATA_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  592) 	if (csum != csum_expected) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  593) 		dev_err(dev, "%s %04x, expected: %04x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  594) 			"invalid firmware header checksum = ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  595) 			csum, csum_expected);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  596) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  597) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  598) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  599) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  600) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  601) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  602)  * Write a |len| byte long buffer |buf| to the device, by chopping it up into a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  603)  * sequence of smaller |CYAPA_CMD_LEN|-length write commands.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  604)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  605)  * The data bytes for a write command are prepended with the 1-byte offset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  606)  * of the data relative to the start of |buf|.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  607)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  608) static int cyapa_gen3_write_buffer(struct cyapa *cyapa,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  609) 		const u8 *buf, size_t len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  610) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  611) 	int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  612) 	size_t i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  613) 	unsigned char cmd[CYAPA_CMD_LEN + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  614) 	size_t cmd_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  615) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  616) 	for (i = 0; i < len; i += CYAPA_CMD_LEN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  617) 		const u8 *payload = &buf[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  618) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  619) 		cmd_len = (len - i >= CYAPA_CMD_LEN) ? CYAPA_CMD_LEN : len - i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  620) 		cmd[0] = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  621) 		memcpy(&cmd[1], payload, cmd_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  622) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  623) 		error = cyapa_i2c_reg_write_block(cyapa, 0, cmd_len + 1, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  624) 		if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  625) 			return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  626) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  627) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  628) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  629) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  630) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  631)  * A firmware block write command writes 64 bytes of data to a single flash
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  632)  * page in the device.  The 78-byte block write command has the format:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  633)  *   <0xff> <CMD> <Key> <Start> <Data> <Data-Checksum> <CMD Checksum>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  634)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  635)  *  <0xff>  - every command starts with 0xff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  636)  *  <CMD>   - the write command value is 0x39
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  637)  *  <Key>   - write commands include an 8-byte key: { 00 01 02 03 04 05 06 07 }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  638)  *  <Block> - Memory Block number (address / 64) (16-bit, big-endian)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  639)  *  <Data>  - 64 bytes of firmware image data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  640)  *  <Data Checksum> - sum of 64 <Data> bytes, modulo 0xff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  641)  *  <CMD Checksum> - sum of 77 bytes, from 0xff to <Data Checksum>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  642)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  643)  * Each write command is split into 5 i2c write transactions of up to 16 bytes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  644)  * Each transaction starts with an i2c register offset: (00, 10, 20, 30, 40).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  645)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  646) static int cyapa_gen3_write_fw_block(struct cyapa *cyapa,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  647) 		u16 block, const u8 *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  648) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  649) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  650) 	struct gen3_write_block_cmd write_block_cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  651) 	u8 status[BL_STATUS_SIZE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  652) 	int tries;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  653) 	u8 bl_status, bl_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  654) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  655) 	/* Set write command and security key bytes. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  656) 	write_block_cmd.checksum_seed = GEN3_BL_CMD_CHECKSUM_SEED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  657) 	write_block_cmd.cmd_code = GEN3_BL_CMD_WRITE_BLOCK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  658) 	memcpy(write_block_cmd.key, security_key, sizeof(security_key));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  659) 	put_unaligned_be16(block, &write_block_cmd.block_num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  660) 	memcpy(write_block_cmd.block_data, data, CYAPA_FW_BLOCK_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  661) 	write_block_cmd.block_checksum = cyapa_gen3_csum(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  662) 			write_block_cmd.block_data, CYAPA_FW_BLOCK_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  663) 	write_block_cmd.cmd_checksum = cyapa_gen3_csum((u8 *)&write_block_cmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  664) 			sizeof(write_block_cmd) - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  665) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  666) 	ret = cyapa_gen3_write_buffer(cyapa, (u8 *)&write_block_cmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  667) 			sizeof(write_block_cmd));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  668) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  669) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  670) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  671) 	/* Wait for write to finish */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  672) 	tries = 11;  /* Programming for one block can take about 100ms. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  673) 	do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  674) 		usleep_range(10000, 20000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  675) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  676) 		/* Check block write command result status. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  677) 		ret = cyapa_i2c_reg_read_block(cyapa, BL_HEAD_OFFSET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  678) 					       BL_STATUS_SIZE, status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  679) 		if (ret != BL_STATUS_SIZE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  680) 			return (ret < 0) ? ret : -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  681) 	} while ((status[REG_BL_STATUS] & BL_STATUS_BUSY) && --tries);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  682) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  683) 	/* Ignore WATCHDOG bit and reserved bits. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  684) 	bl_status = status[REG_BL_STATUS] & ~BL_STATUS_REV_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  685) 	bl_error = status[REG_BL_ERROR] & ~BL_ERROR_RESERVED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  686) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  687) 	if (bl_status & BL_STATUS_BUSY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  688) 		ret = -ETIMEDOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  689) 	else if (bl_status != BL_STATUS_RUNNING ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  690) 		bl_error != BL_ERROR_BOOTLOADING)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  691) 		ret = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  692) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  693) 		ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  694) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  695) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  696) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  697) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  698) static int cyapa_gen3_write_blocks(struct cyapa *cyapa,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  699) 		size_t start_block, size_t block_count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  700) 		const u8 *image_data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  701) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  702) 	int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  703) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  704) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  705) 	for (i = 0; i < block_count; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  706) 		size_t block = start_block + i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  707) 		size_t addr = i * CYAPA_FW_BLOCK_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  708) 		const u8 *data = &image_data[addr];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  709) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  710) 		error = cyapa_gen3_write_fw_block(cyapa, block, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  711) 		if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  712) 			return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  713) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  714) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  715) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  716) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  717) static int cyapa_gen3_do_fw_update(struct cyapa *cyapa,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  718) 		const struct firmware *fw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  719) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  720) 	struct device *dev = &cyapa->client->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  721) 	int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  722) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  723) 	/* First write data, starting at byte 128 of fw->data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  724) 	error = cyapa_gen3_write_blocks(cyapa,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  725) 		CYAPA_FW_DATA_BLOCK_START, CYAPA_FW_DATA_BLOCK_COUNT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  726) 		&fw->data[CYAPA_FW_HDR_BLOCK_COUNT * CYAPA_FW_BLOCK_SIZE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  727) 	if (error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  728) 		dev_err(dev, "FW update aborted, write image: %d\n", error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  729) 		return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  730) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  731) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  732) 	/* Then write checksum */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  733) 	error = cyapa_gen3_write_blocks(cyapa,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  734) 		CYAPA_FW_HDR_BLOCK_START, CYAPA_FW_HDR_BLOCK_COUNT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  735) 		&fw->data[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  736) 	if (error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  737) 		dev_err(dev, "FW update aborted, write checksum: %d\n", error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  738) 		return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  739) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  740) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  741) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  742) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  743) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  744) static ssize_t cyapa_gen3_do_calibrate(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  745) 				     struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  746) 				     const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  747) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  748) 	struct cyapa *cyapa = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  749) 	unsigned long timeout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  750) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  751) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  752) 	ret = cyapa_read_byte(cyapa, CYAPA_CMD_DEV_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  753) 	if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  754) 		dev_err(dev, "Error reading dev status: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  755) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  756) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  757) 	if ((ret & CYAPA_DEV_NORMAL) != CYAPA_DEV_NORMAL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  758) 		dev_warn(dev, "Trackpad device is busy, device state: 0x%02x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  759) 			 ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  760) 		ret = -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  761) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  762) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  763) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  764) 	ret = cyapa_write_byte(cyapa, CYAPA_CMD_SOFT_RESET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  765) 			       OP_RECALIBRATION_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  766) 	if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  767) 		dev_err(dev, "Failed to send calibrate command: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  768) 			ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  769) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  770) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  771) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  772) 	/* max recalibration timeout 2s. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  773) 	timeout = jiffies + 2 * HZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  774) 	do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  775) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  776) 		 * For this recalibration, the max time will not exceed 2s.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  777) 		 * The average time is approximately 500 - 700 ms, and we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  778) 		 * will check the status every 100 - 200ms.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  779) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  780) 		msleep(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  781) 		ret = cyapa_read_byte(cyapa, CYAPA_CMD_DEV_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  782) 		if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  783) 			dev_err(dev, "Error reading dev status: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  784) 			goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  785) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  786) 		if ((ret & CYAPA_DEV_NORMAL) == CYAPA_DEV_NORMAL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  787) 			dev_dbg(dev, "Calibration successful.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  788) 			goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  789) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  790) 	} while (time_is_after_jiffies(timeout));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  791) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  792) 	dev_err(dev, "Failed to calibrate. Timeout.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  793) 	ret = -ETIMEDOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  794) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  795) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  796) 	return ret < 0 ? ret : count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  797) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  798) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  799) static ssize_t cyapa_gen3_show_baseline(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  800) 				   struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  801) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  802) 	struct cyapa *cyapa = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  803) 	int max_baseline, min_baseline;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  804) 	int tries;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  805) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  806) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  807) 	ret = cyapa_read_byte(cyapa, CYAPA_CMD_DEV_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  808) 	if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  809) 		dev_err(dev, "Error reading dev status. err = %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  810) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  811) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  812) 	if ((ret & CYAPA_DEV_NORMAL) != CYAPA_DEV_NORMAL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  813) 		dev_warn(dev, "Trackpad device is busy. device state = 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  814) 			 ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  815) 		ret = -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  816) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  817) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  818) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  819) 	ret = cyapa_write_byte(cyapa, CYAPA_CMD_SOFT_RESET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  820) 			       OP_REPORT_BASELINE_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  821) 	if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  822) 		dev_err(dev, "Failed to send report baseline command. %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  823) 			ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  824) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  825) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  826) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  827) 	tries = 3;  /* Try for 30 to 60 ms */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  828) 	do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  829) 		usleep_range(10000, 20000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  830) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  831) 		ret = cyapa_read_byte(cyapa, CYAPA_CMD_DEV_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  832) 		if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  833) 			dev_err(dev, "Error reading dev status. err = %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  834) 				ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  835) 			goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  836) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  837) 		if ((ret & CYAPA_DEV_NORMAL) == CYAPA_DEV_NORMAL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  838) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  839) 	} while (--tries);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  840) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  841) 	if (tries == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  842) 		dev_err(dev, "Device timed out going to Normal state.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  843) 		ret = -ETIMEDOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  844) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  845) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  846) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  847) 	ret = cyapa_read_byte(cyapa, CYAPA_CMD_MAX_BASELINE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  848) 	if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  849) 		dev_err(dev, "Failed to read max baseline. err = %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  850) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  851) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  852) 	max_baseline = ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  853) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  854) 	ret = cyapa_read_byte(cyapa, CYAPA_CMD_MIN_BASELINE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  855) 	if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  856) 		dev_err(dev, "Failed to read min baseline. err = %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  857) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  858) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  859) 	min_baseline = ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  860) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  861) 	dev_dbg(dev, "Baseline report successful. Max: %d Min: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  862) 		max_baseline, min_baseline);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  863) 	ret = scnprintf(buf, PAGE_SIZE, "%d %d\n", max_baseline, min_baseline);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  864) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  865) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  866) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  867) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  868) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  869) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  870)  * cyapa_get_wait_time_for_pwr_cmd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  871)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  872)  * Compute the amount of time we need to wait after updating the touchpad
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  873)  * power mode. The touchpad needs to consume the incoming power mode set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  874)  * command at the current clock rate.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  875)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  876) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  877) static u16 cyapa_get_wait_time_for_pwr_cmd(u8 pwr_mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  878) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  879) 	switch (pwr_mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  880) 	case PWR_MODE_FULL_ACTIVE: return 20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  881) 	case PWR_MODE_BTN_ONLY: return 20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  882) 	case PWR_MODE_OFF: return 20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  883) 	default: return cyapa_pwr_cmd_to_sleep_time(pwr_mode) + 50;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  884) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  885) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  886) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  887) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  888)  * Set device power mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  889)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  890)  * Write to the field to configure power state. Power states include :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  891)  *   Full : Max scans and report rate.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  892)  *   Idle : Report rate set by user specified time.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  893)  *   ButtonOnly : No scans for fingers. When the button is triggered,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  894)  *     a slave interrupt is asserted to notify host to wake up.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  895)  *   Off : Only awake for i2c commands from host. No function for button
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  896)  *     or touch sensors.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  897)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  898)  * The power_mode command should conform to the following :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  899)  *   Full : 0x3f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  900)  *   Idle : Configurable from 20 to 1000ms. See note below for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  901)  *     cyapa_sleep_time_to_pwr_cmd and cyapa_pwr_cmd_to_sleep_time
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  902)  *   ButtonOnly : 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  903)  *   Off : 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  904)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  905)  * Device power mode can only be set when device is in operational mode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  906)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  907) static int cyapa_gen3_set_power_mode(struct cyapa *cyapa, u8 power_mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  908) 		u16 always_unused, enum cyapa_pm_stage pm_stage)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  909) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  910) 	struct input_dev *input = cyapa->input;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  911) 	u8 power;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  912) 	int tries;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  913) 	int sleep_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  914) 	int interval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  915) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  916) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  917) 	if (cyapa->state != CYAPA_STATE_OP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  918) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  919) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  920) 	tries = SET_POWER_MODE_TRIES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  921) 	while (tries--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  922) 		ret = cyapa_read_byte(cyapa, CYAPA_CMD_POWER_MODE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  923) 		if (ret >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  924) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  925) 		usleep_range(SET_POWER_MODE_DELAY, 2 * SET_POWER_MODE_DELAY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  926) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  927) 	if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  928) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  929) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  930) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  931) 	 * Return early if the power mode to set is the same as the current
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  932) 	 * one.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  933) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  934) 	if ((ret & PWR_MODE_MASK) == power_mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  935) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  936) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  937) 	sleep_time = (int)cyapa_get_wait_time_for_pwr_cmd(ret & PWR_MODE_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  938) 	power = ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  939) 	power &= ~PWR_MODE_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  940) 	power |= power_mode & PWR_MODE_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  941) 	tries = SET_POWER_MODE_TRIES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  942) 	while (tries--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  943) 		ret = cyapa_write_byte(cyapa, CYAPA_CMD_POWER_MODE, power);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  944) 		if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  945) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  946) 		usleep_range(SET_POWER_MODE_DELAY, 2 * SET_POWER_MODE_DELAY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  947) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  948) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  949) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  950) 	 * Wait for the newly set power command to go in at the previous
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  951) 	 * clock speed (scanrate) used by the touchpad firmware. Not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  952) 	 * doing so before issuing the next command may result in errors
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  953) 	 * depending on the command's content.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  954) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  955) 	if (cyapa->operational && input && input->users &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  956) 	    (pm_stage == CYAPA_PM_RUNTIME_SUSPEND ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  957) 	     pm_stage == CYAPA_PM_RUNTIME_RESUME)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  958) 		/* Try to polling in 120Hz, read may fail, just ignore it. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  959) 		interval = 1000 / 120;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  960) 		while (sleep_time > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  961) 			if (sleep_time > interval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  962) 				msleep(interval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  963) 			else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  964) 				msleep(sleep_time);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  965) 			sleep_time -= interval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  966) 			cyapa_gen3_try_poll_handler(cyapa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  967) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  968) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  969) 		msleep(sleep_time);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  970) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  971) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  972) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  973) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  974) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  975) static int cyapa_gen3_set_proximity(struct cyapa *cyapa, bool enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  976) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  977) 	return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  978) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  979) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  980) static int cyapa_gen3_get_query_data(struct cyapa *cyapa)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  981) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  982) 	u8 query_data[QUERY_DATA_SIZE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  983) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  984) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  985) 	if (cyapa->state != CYAPA_STATE_OP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  986) 		return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  987) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  988) 	ret = cyapa_read_block(cyapa, CYAPA_CMD_GROUP_QUERY, query_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  989) 	if (ret != QUERY_DATA_SIZE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  990) 		return (ret < 0) ? ret : -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  991) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  992) 	memcpy(&cyapa->product_id[0], &query_data[0], 5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  993) 	cyapa->product_id[5] = '-';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  994) 	memcpy(&cyapa->product_id[6], &query_data[5], 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  995) 	cyapa->product_id[12] = '-';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  996) 	memcpy(&cyapa->product_id[13], &query_data[11], 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  997) 	cyapa->product_id[15] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  998) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  999) 	cyapa->fw_maj_ver = query_data[15];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) 	cyapa->fw_min_ver = query_data[16];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) 	cyapa->btn_capability = query_data[19] & CAPABILITY_BTN_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) 	cyapa->gen = query_data[20] & 0x0f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) 	cyapa->max_abs_x = ((query_data[21] & 0xf0) << 4) | query_data[22];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) 	cyapa->max_abs_y = ((query_data[21] & 0x0f) << 8) | query_data[23];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) 	cyapa->physical_size_x =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) 		((query_data[24] & 0xf0) << 4) | query_data[25];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) 	cyapa->physical_size_y =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) 		((query_data[24] & 0x0f) << 8) | query_data[26];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) 	cyapa->max_z = 255;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) static int cyapa_gen3_bl_query_data(struct cyapa *cyapa)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) 	u8 bl_data[CYAPA_CMD_LEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) 	ret = cyapa_i2c_reg_read_block(cyapa, 0, CYAPA_CMD_LEN, bl_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) 	if (ret != CYAPA_CMD_LEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) 		return (ret < 0) ? ret : -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) 	 * This value will be updated again when entered application mode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) 	 * If TP failed to enter application mode, this fw version values
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) 	 * can be used as a reference.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) 	 * This firmware version valid when fw image checksum is valid.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) 	if (bl_data[REG_BL_STATUS] ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) 			(BL_STATUS_RUNNING | BL_STATUS_CSUM_VALID)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) 		cyapa->fw_maj_ver = bl_data[GEN3_BL_IDLE_FW_MAJ_VER_OFFSET];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) 		cyapa->fw_min_ver = bl_data[GEN3_BL_IDLE_FW_MIN_VER_OFFSET];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044)  * Check if device is operational.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046)  * An operational device is responding, has exited bootloader, and has
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047)  * firmware supported by this driver.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049)  * Returns:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050)  *   -EBUSY  no device or in bootloader
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051)  *   -EIO    failure while reading from device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052)  *   -EAGAIN device is still in bootloader
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053)  *           if ->state = CYAPA_STATE_BL_IDLE, device has invalid firmware
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054)  *   -EINVAL device is in operational mode, but not supported by this driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055)  *   0       device is supported
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) static int cyapa_gen3_do_operational_check(struct cyapa *cyapa)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) 	struct device *dev = &cyapa->client->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) 	int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) 	switch (cyapa->state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) 	case CYAPA_STATE_BL_ACTIVE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) 		error = cyapa_gen3_bl_deactivate(cyapa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) 		if (error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) 			dev_err(dev, "failed to bl_deactivate: %d\n", error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) 			return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) 		fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) 	case CYAPA_STATE_BL_IDLE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) 		/* Try to get firmware version in bootloader mode. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) 		cyapa_gen3_bl_query_data(cyapa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) 		error = cyapa_gen3_bl_exit(cyapa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) 		if (error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) 			dev_err(dev, "failed to bl_exit: %d\n", error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) 			return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) 		fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) 	case CYAPA_STATE_OP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) 		 * Reading query data before going back to the full mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) 		 * may cause problems, so we set the power mode first here.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) 		error = cyapa_gen3_set_power_mode(cyapa,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) 				PWR_MODE_FULL_ACTIVE, 0, CYAPA_PM_ACTIVE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) 		if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) 			dev_err(dev, "%s: set full power mode failed: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) 				__func__, error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) 		error = cyapa_gen3_get_query_data(cyapa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) 		if (error < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) 			return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) 		/* Only support firmware protocol gen3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) 		if (cyapa->gen != CYAPA_GEN3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) 			dev_err(dev, "unsupported protocol version (%d)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) 				cyapa->gen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) 			return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) 		/* Only support product ID starting with CYTRA */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) 		if (memcmp(cyapa->product_id, product_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) 				strlen(product_id)) != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) 			dev_err(dev, "unsupported product ID (%s)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) 				cyapa->product_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) 			return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) 		return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120)  * Return false, do not continue process
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121)  * Return true, continue process.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) static bool cyapa_gen3_irq_cmd_handler(struct cyapa *cyapa)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) 	/* Not gen3 irq command response, skip for continue. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) 	if (cyapa->gen != CYAPA_GEN3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) 		return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) 	if (cyapa->operational)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) 		return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) 	 * Driver in detecting or other interface function processing,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) 	 * so, stop cyapa_gen3_irq_handler to continue process to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) 	 * avoid unwanted to error detecting and processing.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) 	 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) 	 * And also, avoid the periodically asserted interrupts to be processed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) 	 * as touch inputs when gen3 failed to launch into application mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) 	 * which will cause gen3 stays in bootloader mode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) 	return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) static int cyapa_gen3_event_process(struct cyapa *cyapa,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) 				    struct cyapa_reg_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) 	struct input_dev *input = cyapa->input;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) 	int num_fingers;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) 	num_fingers = (data->finger_btn >> 4) & 0x0f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) 	for (i = 0; i < num_fingers; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) 		const struct cyapa_touch *touch = &data->touches[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) 		/* Note: touch->id range is 1 to 15; slots are 0 to 14. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) 		int slot = touch->id - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) 		input_mt_slot(input, slot);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) 		input_mt_report_slot_state(input, MT_TOOL_FINGER, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) 		input_report_abs(input, ABS_MT_POSITION_X,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) 				 ((touch->xy_hi & 0xf0) << 4) | touch->x_lo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) 		input_report_abs(input, ABS_MT_POSITION_Y,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) 				 ((touch->xy_hi & 0x0f) << 8) | touch->y_lo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) 		input_report_abs(input, ABS_MT_PRESSURE, touch->pressure);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) 	input_mt_sync_frame(input);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) 	if (cyapa->btn_capability & CAPABILITY_LEFT_BTN_MASK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) 		input_report_key(input, BTN_LEFT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) 				 !!(data->finger_btn & OP_DATA_LEFT_BTN));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) 	if (cyapa->btn_capability & CAPABILITY_MIDDLE_BTN_MASK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) 		input_report_key(input, BTN_MIDDLE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) 				 !!(data->finger_btn & OP_DATA_MIDDLE_BTN));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) 	if (cyapa->btn_capability & CAPABILITY_RIGHT_BTN_MASK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) 		input_report_key(input, BTN_RIGHT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) 				 !!(data->finger_btn & OP_DATA_RIGHT_BTN));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) 	input_sync(input);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) static int cyapa_gen3_irq_handler(struct cyapa *cyapa)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) 	struct device *dev = &cyapa->client->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) 	struct cyapa_reg_data data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) 	ret = cyapa_read_block(cyapa, CYAPA_CMD_GROUP_DATA, (u8 *)&data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) 	if (ret != sizeof(data)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) 		dev_err(dev, "failed to read report data, (%d)\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) 	if ((data.device_status & OP_STATUS_SRC) != OP_STATUS_SRC ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) 	    (data.device_status & OP_STATUS_DEV) != CYAPA_DEV_NORMAL ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) 	    (data.finger_btn & OP_DATA_VALID) != OP_DATA_VALID) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) 		dev_err(dev, "invalid device state bytes: %02x %02x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) 			data.device_status, data.finger_btn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) 	return cyapa_gen3_event_process(cyapa, &data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206)  * This function will be called in the cyapa_gen3_set_power_mode function,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207)  * and it's known that it may failed in some situation after the set power
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208)  * mode command was sent. So this function is aimed to avoid the knwon
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209)  * and unwanted output I2C and data parse error messages.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) static int cyapa_gen3_try_poll_handler(struct cyapa *cyapa)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) 	struct cyapa_reg_data data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) 	ret = cyapa_read_block(cyapa, CYAPA_CMD_GROUP_DATA, (u8 *)&data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) 	if (ret != sizeof(data))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) 	if ((data.device_status & OP_STATUS_SRC) != OP_STATUS_SRC ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) 	    (data.device_status & OP_STATUS_DEV) != CYAPA_DEV_NORMAL ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) 	    (data.finger_btn & OP_DATA_VALID) != OP_DATA_VALID)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) 	return cyapa_gen3_event_process(cyapa, &data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) static int cyapa_gen3_initialize(struct cyapa *cyapa) { return 0; }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) static int cyapa_gen3_bl_initiate(struct cyapa *cyapa,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) 		const struct firmware *fw) { return 0; }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) static int cyapa_gen3_empty_output_data(struct cyapa *cyapa,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) 		u8 *buf, int *len, cb_sort func) { return 0; }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) const struct cyapa_dev_ops cyapa_gen3_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) 	.check_fw = cyapa_gen3_check_fw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) 	.bl_enter = cyapa_gen3_bl_enter,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) 	.bl_activate = cyapa_gen3_bl_activate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) 	.update_fw = cyapa_gen3_do_fw_update,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) 	.bl_deactivate = cyapa_gen3_bl_deactivate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) 	.bl_initiate = cyapa_gen3_bl_initiate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) 	.show_baseline = cyapa_gen3_show_baseline,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) 	.calibrate_store = cyapa_gen3_do_calibrate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) 	.initialize = cyapa_gen3_initialize,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) 	.state_parse = cyapa_gen3_state_parse,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) 	.operational_check = cyapa_gen3_do_operational_check,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) 	.irq_handler = cyapa_gen3_irq_handler,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) 	.irq_cmd_handler = cyapa_gen3_irq_cmd_handler,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) 	.sort_empty_output_data = cyapa_gen3_empty_output_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) 	.set_power_mode = cyapa_gen3_set_power_mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) 	.set_proximity = cyapa_gen3_set_proximity,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) };