/* * Cypress APA trackpad with I2C interface * * Author: Dudley Du <[email protected]> * Further cleanup and restructuring by: * Daniel Kurtz <[email protected]> * Benson Leung <[email protected]> * * Copyright (C) 2011-2015 Cypress Semiconductor, Inc. * Copyright (C) 2011-2012 Google, Inc. * * This file is subject to the terms and conditions of the GNU General Public * License. See the file COPYING in the main directory of this archive for * more details. */ #include <linux/delay.h> #include <linux/i2c.h> #include <linux/input.h> #include <linux/input/mt.h> #include <linux/module.h> #include <linux/slab.h> #include <linux/unaligned.h> #include "cyapa.h" #define GEN3_MAX_FINGERS … #define GEN3_FINGER_NUM(x) … #define BLK_HEAD_BYTES … /* Macro for register map group offset. */ #define PRODUCT_ID_SIZE … #define QUERY_DATA_SIZE … #define REG_PROTOCOL_GEN_QUERY_OFFSET … #define REG_OFFSET_DATA_BASE … #define REG_OFFSET_COMMAND_BASE … #define REG_OFFSET_QUERY_BASE … #define CYAPA_OFFSET_SOFT_RESET … #define OP_RECALIBRATION_MASK … #define OP_REPORT_BASELINE_MASK … #define REG_OFFSET_MAX_BASELINE … #define REG_OFFSET_MIN_BASELINE … #define REG_OFFSET_POWER_MODE … #define SET_POWER_MODE_DELAY … #define SET_POWER_MODE_TRIES … #define GEN3_BL_CMD_CHECKSUM_SEED … #define GEN3_BL_CMD_INITIATE_BL … #define GEN3_BL_CMD_WRITE_BLOCK … #define GEN3_BL_CMD_VERIFY_BLOCK … #define GEN3_BL_CMD_TERMINATE_BL … #define GEN3_BL_CMD_LAUNCH_APP … /* * CYAPA trackpad device states. * Used in register 0x00, bit1-0, DeviceStatus field. * Other values indicate device is in an abnormal state and must be reset. */ #define CYAPA_DEV_NORMAL … #define CYAPA_DEV_BUSY … #define CYAPA_FW_BLOCK_SIZE … #define CYAPA_FW_READ_SIZE … #define CYAPA_FW_HDR_START … #define CYAPA_FW_HDR_BLOCK_COUNT … #define CYAPA_FW_HDR_BLOCK_START … #define CYAPA_FW_HDR_SIZE … #define CYAPA_FW_DATA_START … #define CYAPA_FW_DATA_BLOCK_COUNT … #define CYAPA_FW_DATA_BLOCK_START … #define CYAPA_FW_DATA_SIZE … #define CYAPA_FW_SIZE … #define CYAPA_CMD_LEN … #define GEN3_BL_IDLE_FW_MAJ_VER_OFFSET … #define GEN3_BL_IDLE_FW_MIN_VER_OFFSET … struct cyapa_touch { … } __packed; struct cyapa_reg_data { … } __packed; struct gen3_write_block_cmd { … } __packed; static const u8 security_key[] = …; static const u8 bl_activate[] = …; static const u8 bl_deactivate[] = …; static const u8 bl_exit[] = …; /* for byte read/write command */ #define CMD_RESET … #define CMD_POWER_MODE … #define CMD_DEV_STATUS … #define CMD_REPORT_MAX_BASELINE … #define CMD_REPORT_MIN_BASELINE … #define SMBUS_BYTE_CMD(cmd) … #define CYAPA_SMBUS_RESET … #define CYAPA_SMBUS_POWER_MODE … #define CYAPA_SMBUS_DEV_STATUS … #define CYAPA_SMBUS_MAX_BASELINE … #define CYAPA_SMBUS_MIN_BASELINE … /* for group registers read/write command */ #define REG_GROUP_DATA … #define REG_GROUP_CMD … #define REG_GROUP_QUERY … #define SMBUS_GROUP_CMD(grp) … #define CYAPA_SMBUS_GROUP_DATA … #define CYAPA_SMBUS_GROUP_CMD … #define CYAPA_SMBUS_GROUP_QUERY … /* for register block read/write command */ #define CMD_BL_STATUS … #define CMD_BL_HEAD … #define CMD_BL_CMD … #define CMD_BL_DATA … #define CMD_BL_ALL … #define CMD_BLK_PRODUCT_ID … #define CMD_BLK_HEAD … #define SMBUS_BLOCK_CMD(cmd) … /* register block read/write command in bootloader mode */ #define CYAPA_SMBUS_BL_STATUS … #define CYAPA_SMBUS_BL_HEAD … #define CYAPA_SMBUS_BL_CMD … #define CYAPA_SMBUS_BL_DATA … #define CYAPA_SMBUS_BL_ALL … /* register block read/write command in operational mode */ #define CYAPA_SMBUS_BLK_PRODUCT_ID … #define CYAPA_SMBUS_BLK_HEAD … struct cyapa_cmd_len { … }; /* maps generic CYAPA_CMD_* code to the I2C equivalent */ static const struct cyapa_cmd_len cyapa_i2c_cmds[] = …; static const struct cyapa_cmd_len cyapa_smbus_cmds[] = …; static int cyapa_gen3_try_poll_handler(struct cyapa *cyapa); /* * cyapa_smbus_read_block - perform smbus block read command * @cyapa - private data structure of the driver * @cmd - the properly encoded smbus command * @len - expected length of smbus command result * @values - buffer to store smbus command result * * Returns negative errno, else the number of bytes written. * * Note: * In trackpad device, the memory block allocated for I2C register map * is 256 bytes, so the max read block for I2C bus is 256 bytes. */ ssize_t cyapa_smbus_read_block(struct cyapa *cyapa, u8 cmd, size_t len, u8 *values) { … } static s32 cyapa_read_byte(struct cyapa *cyapa, u8 cmd_idx) { … } static s32 cyapa_write_byte(struct cyapa *cyapa, u8 cmd_idx, u8 value) { … } ssize_t cyapa_i2c_reg_read_block(struct cyapa *cyapa, u8 reg, size_t len, u8 *values) { … } static ssize_t cyapa_i2c_reg_write_block(struct cyapa *cyapa, u8 reg, size_t len, const u8 *values) { … } ssize_t cyapa_read_block(struct cyapa *cyapa, u8 cmd_idx, u8 *values) { … } /* * Determine the Gen3 trackpad device's current operating state. * */ static int cyapa_gen3_state_parse(struct cyapa *cyapa, u8 *reg_data, int len) { … } /* * Enter bootloader by soft resetting the device. * * If device is already in the bootloader, the function just returns. * Otherwise, reset the device; after reset, device enters bootloader idle * state immediately. * * Returns: * 0 on success * -EAGAIN device was reset, but is not now in bootloader idle state * < 0 if the device never responds within the timeout */ static int cyapa_gen3_bl_enter(struct cyapa *cyapa) { … } static int cyapa_gen3_bl_activate(struct cyapa *cyapa) { … } static int cyapa_gen3_bl_deactivate(struct cyapa *cyapa) { … } /* * Exit bootloader * * Send bl_exit command, then wait 50 - 100 ms to let device transition to * operational mode. If this is the first time the device's firmware is * running, it can take up to 2 seconds to calibrate its sensors. So, poll * the device's new state for up to 2 seconds. * * Returns: * -EIO failure while reading from device * -EAGAIN device is stuck in bootloader, b/c it has invalid firmware * 0 device is supported and in operational mode */ static int cyapa_gen3_bl_exit(struct cyapa *cyapa) { … } static u16 cyapa_gen3_csum(const u8 *buf, size_t count) { … } /* * Verify the integrity of a CYAPA firmware image file. * * The firmware image file is 30848 bytes, composed of 482 64-byte blocks. * * The first 2 blocks are the firmware header. * The next 480 blocks are the firmware image. * * The first two bytes of the header hold the header checksum, computed by * summing the other 126 bytes of the header. * The last two bytes of the header hold the firmware image checksum, computed * by summing the 30720 bytes of the image modulo 0xffff. * * Both checksums are stored little-endian. */ static int cyapa_gen3_check_fw(struct cyapa *cyapa, const struct firmware *fw) { … } /* * Write a |len| byte long buffer |buf| to the device, by chopping it up into a * sequence of smaller |CYAPA_CMD_LEN|-length write commands. * * The data bytes for a write command are prepended with the 1-byte offset * of the data relative to the start of |buf|. */ static int cyapa_gen3_write_buffer(struct cyapa *cyapa, const u8 *buf, size_t len) { … } /* * A firmware block write command writes 64 bytes of data to a single flash * page in the device. The 78-byte block write command has the format: * <0xff> <CMD> <Key> <Start> <Data> <Data-Checksum> <CMD Checksum> * * <0xff> - every command starts with 0xff * <CMD> - the write command value is 0x39 * <Key> - write commands include an 8-byte key: { 00 01 02 03 04 05 06 07 } * <Block> - Memory Block number (address / 64) (16-bit, big-endian) * <Data> - 64 bytes of firmware image data * <Data Checksum> - sum of 64 <Data> bytes, modulo 0xff * <CMD Checksum> - sum of 77 bytes, from 0xff to <Data Checksum> * * Each write command is split into 5 i2c write transactions of up to 16 bytes. * Each transaction starts with an i2c register offset: (00, 10, 20, 30, 40). */ static int cyapa_gen3_write_fw_block(struct cyapa *cyapa, u16 block, const u8 *data) { … } static int cyapa_gen3_write_blocks(struct cyapa *cyapa, size_t start_block, size_t block_count, const u8 *image_data) { … } static int cyapa_gen3_do_fw_update(struct cyapa *cyapa, const struct firmware *fw) { … } static ssize_t cyapa_gen3_do_calibrate(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { … } static ssize_t cyapa_gen3_show_baseline(struct device *dev, struct device_attribute *attr, char *buf) { … } /* * cyapa_get_wait_time_for_pwr_cmd * * Compute the amount of time we need to wait after updating the touchpad * power mode. The touchpad needs to consume the incoming power mode set * command at the current clock rate. */ static u16 cyapa_get_wait_time_for_pwr_cmd(u8 pwr_mode) { … } /* * Set device power mode * * Write to the field to configure power state. Power states include : * Full : Max scans and report rate. * Idle : Report rate set by user specified time. * ButtonOnly : No scans for fingers. When the button is triggered, * a slave interrupt is asserted to notify host to wake up. * Off : Only awake for i2c commands from host. No function for button * or touch sensors. * * The power_mode command should conform to the following : * Full : 0x3f * Idle : Configurable from 20 to 1000ms. See note below for * cyapa_sleep_time_to_pwr_cmd and cyapa_pwr_cmd_to_sleep_time * ButtonOnly : 0x01 * Off : 0x00 * * Device power mode can only be set when device is in operational mode. */ static int cyapa_gen3_set_power_mode(struct cyapa *cyapa, u8 power_mode, u16 always_unused, enum cyapa_pm_stage pm_stage) { … } static int cyapa_gen3_set_proximity(struct cyapa *cyapa, bool enable) { … } static int cyapa_gen3_get_query_data(struct cyapa *cyapa) { … } static int cyapa_gen3_bl_query_data(struct cyapa *cyapa) { … } /* * Check if device is operational. * * An operational device is responding, has exited bootloader, and has * firmware supported by this driver. * * Returns: * -EBUSY no device or in bootloader * -EIO failure while reading from device * -EAGAIN device is still in bootloader * if ->state = CYAPA_STATE_BL_IDLE, device has invalid firmware * -EINVAL device is in operational mode, but not supported by this driver * 0 device is supported */ static int cyapa_gen3_do_operational_check(struct cyapa *cyapa) { … } /* * Return false, do not continue process * Return true, continue process. */ static bool cyapa_gen3_irq_cmd_handler(struct cyapa *cyapa) { … } static int cyapa_gen3_event_process(struct cyapa *cyapa, struct cyapa_reg_data *data) { … } static int cyapa_gen3_irq_handler(struct cyapa *cyapa) { … } /* * This function will be called in the cyapa_gen3_set_power_mode function, * and it's known that it may failed in some situation after the set power * mode command was sent. So this function is aimed to avoid the knwon * and unwanted output I2C and data parse error messages. */ static int cyapa_gen3_try_poll_handler(struct cyapa *cyapa) { … } static int cyapa_gen3_initialize(struct cyapa *cyapa) { … } static int cyapa_gen3_bl_initiate(struct cyapa *cyapa, const struct firmware *fw) { … } static int cyapa_gen3_empty_output_data(struct cyapa *cyapa, u8 *buf, int *len, cb_sort func) { … } const struct cyapa_dev_ops cyapa_gen3_ops = …;