diff options
Diffstat (limited to 'drivers/input/touchscreen/cyttsp4_core.c')
-rw-r--r-- | drivers/input/touchscreen/cyttsp4_core.c | 6685 |
1 files changed, 0 insertions, 6685 deletions
diff --git a/drivers/input/touchscreen/cyttsp4_core.c b/drivers/input/touchscreen/cyttsp4_core.c deleted file mode 100644 index d1ab003..0000000 --- a/drivers/input/touchscreen/cyttsp4_core.c +++ /dev/null @@ -1,6685 +0,0 @@ -/* - * Core Source for: - * Cypress TrueTouch(TM) Standard Product (TTSP) touchscreen drivers. - * For use with Cypress Gen4 and Solo parts. - * Supported parts include: - * CY8CTMA884/616 - * CY8CTMA4XX - * - * Copyright (C) 2009-2012 Cypress Semiconductor, Inc. - * Copyright (C) 2011 Motorola Mobility, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2, and only version 2, as published by the - * Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * Contact Cypress Semiconductor at www.cypress.com <kev@cypress.com> - * - */ -#define TOUCH_BOOST 0 -#include "cyttsp4_core.h" - -#include <linux/delay.h> -#include <linux/gpio.h> -#include <linux/interrupt.h> -#include <linux/slab.h> -#include <linux/platform_data/cypress_cyttsp4.h> -#include <linux/firmware.h> /* This enables firmware class loader code */ - -#if TOUCH_BOOST -#include <linux/workqueue.h> -#include <linux/timer.h> -#include <mach/cpufreq_limits.h> -#ifdef CONFIG_DVFS_LIMIT -#include <linux/cpufreq.h> -#endif -bool boost; -#endif - -/* platform address lookup offsets */ -#define CY_TCH_ADDR_OFS 0 -#define CY_LDR_ADDR_OFS 1 - -/* helpers */ -#define GET_NUM_TOUCHES(x) ((x) & 0x1F) -#define IS_LARGE_AREA(x) ((x) & 0x20) -#define IS_BAD_PKT(x) ((x) & 0x20) -#define GET_HSTMODE(reg) ((reg & 0x70) >> 4) -#define IS_BOOTLOADERMODE(reg) (reg & 0x01) - -/* maximum number of concurrent tracks */ -#define CY_NUM_TCH_ID 10 -/* maximum number of track IDs */ -#define CY_NUM_TRK_ID 16 -/* maximum number of command data bytes */ -#define CY_NUM_DAT 6 -/* maximum number of config block read data */ -#define CY_NUM_CONFIG_BYTES 128 - -#define CY_REG_BASE 0x00 -#define CY_DELAY_DFLT 20 /* ms */ -#define CY_DELAY_MAX (500/CY_DELAY_DFLT) /* half second */ -#define CY_HALF_SEC_TMO_MS 500 /* half second in msecs */ -#define CY_TEN_SEC_TMO_MS 10000 /* ten seconds in msecs */ -#define CY_HANDSHAKE_BIT 0x80 -#define CY_WAKE_DFLT 99 /* causes wake strobe on INT line - * in sample board configuration - * platform data->hw_recov() function - */ -/* power mode select bits */ -#define CY_SOFT_RESET_MODE 0x01 -#define CY_DEEP_SLEEP_MODE 0x02 -#define CY_LOW_POWER_MODE 0x04 -/* device mode bits */ -#define CY_MODE_CHANGE 0x08 /* rd/wr hst_mode */ -#define CY_OPERATE_MODE 0x00 /* rd/wr hst_mode */ -#define CY_SYSINFO_MODE 0x10 /* rd/wr hst_mode */ -#define CY_CONFIG_MODE 0x20 /* rd/wr hst_mode */ -#define CY_BL_MODE 0x01 /* wr hst mode == soft reset - * was 0x10 to rep_stat for LTS - */ -#define CY_CMD_RDY_BIT 0x40 - -#define CY_REG_OP_START 0 -#define CY_REG_SI_START 0 -#define CY_REG_OP_END 0x20 -#define CY_REG_SI_END 0x20 - -#ifdef CY_USE_TMA400 -#define CY_TCH_CRC_LOC_TMA400 5884 /* location of CRC in touch EBID */ -#endif /* --CY_USE_TMA400 */ - -/* register field lengths */ -#define CY_NUM_REVCTRL 8 -#define CY_NUM_MFGID 8 -#define CY_NUM_TCHREC 10 -#define CY_NUM_DDATA 32 -#define CY_NUM_MDATA 64 -#define CY_TMA884_MAX_BYTES 255 /* - * max reg access for TMA884 - * in config mode - */ -#define CY_TMA400_MAX_BYTES 512 /* - * max reg access for TMA400 - * in config mode - */ - -/* touch event id codes */ -#define CY_GET_EVENTID(reg) ((reg & 0x60) >> 5) -#define CY_GET_TRACKID(reg) (reg & 0x1F) -#define CY_NOMOVE 0 -#define CY_TOUCHDOWN 1 -#define CY_MOVE 2 -#define CY_LIFTOFF 3 - -#define CY_CFG_BLK_SIZE 126 -#define CY_EBID_ROW_SIZE_DFLT 128 - -#define CY_BL_VERS_SIZE 12 -#define CY_NUM_TMA400_TT_CFG_BLK 51 /* Rev84 mapping */ - -#if defined(CY_USE_FORCE_LOAD) || defined(CONFIG_TOUCHSCREEN_DEBUG) -#define CY_BL_FW_NAME_SIZE NAME_MAX -#endif - - -#ifdef CY_USE_REG_ACCESS -#define CY_RW_REGID_MAX 0xFFFF -#define CY_RW_REG_DATA_MAX 0xFF -#endif - -/* abs settings */ -#define CY_IGNORE_VALUE 0xFFFF -/* abs signal capabilities offsets in the frameworks array */ -enum cyttsp4_sig_caps { - CY_SIGNAL_OST = 0, - CY_MIN_OST = 1, - CY_MAX_OST = 2, - CY_FUZZ_OST = 3, - CY_FLAT_OST = 4, - CY_NUM_ABS_SET /* number of signal capability fields */ -}; - -/* abs axis signal offsets in the framworks array */ -enum cyttsp4_sig_ost { - CY_ABS_X_OST = 0, - CY_ABS_Y_OST = 1, - CY_ABS_P_OST = 2, - CY_ABS_W_OST = 3, - CY_ABS_ID_OST = 4, - CY_ABS_MAJ_OST = 5, - CY_ABS_MIN_OST = 6, - CY_ABS_OR_OST = 7, - CY_NUM_ABS_OST /* number of abs signals */ -}; - -/* touch record system information offset masks and shifts */ -#define CY_SIZE_FIELD_MASK 0x1F -#define CY_BOFS_MASK 0xE0 -#define CY_BOFS_SHIFT 5 - -enum cyttsp4_driver_state { - CY_IDLE_STATE, /* IC cannot be reached */ - CY_READY_STATE, /* pre-operational; ready to go to ACTIVE */ - CY_ACTIVE_STATE, /* app is running, IC is scanning */ - CY_SLEEP_STATE, /* app is running, IC is idle */ - CY_BL_STATE, /* bootloader is running */ - CY_SYSINFO_STATE, /* switching to sysinfo mode */ - CY_CMD_STATE, /* command initiation mode */ - CY_EXIT_BL_STATE, /* sync bl heartbeat to app ready int */ - CY_TRANSFER_STATE, /* changing states */ - CY_INVALID_STATE /* always last in the list */ -}; - -static const char * const cyttsp4_driver_state_string[] = { - /* Order must match enum cyttsp4_driver_state above */ - "IDLE", - "READY", - "ACTIVE", - "SLEEP", - "BOOTLOADER", - "SYSINFO", - "CMD", - "EXIT_BL", - "TRANSFER", - "INVALID" -}; - -enum cyttsp4_controller_mode { - CY_MODE_BOOTLOADER, - CY_MODE_SYSINFO, - CY_MODE_OPERATIONAL, - CY_MODE_CONFIG, - CY_MODE_NUM -}; - -enum cyttsp4_ic_grpnum { - CY_IC_GRPNUM_RESERVED = 0, - CY_IC_GRPNUM_CMD_REGS, - CY_IC_GRPNUM_TCH_REP, - CY_IC_GRPNUM_DATA_REC, - CY_IC_GRPNUM_TEST_REC, - CY_IC_GRPNUM_PCFG_REC, - CY_IC_GRPNUM_TCH_PARM_VAL, - CY_IC_GRPNUM_TCH_PARM_SIZ, - CY_IC_GRPNUM_RESERVED1, - CY_IC_GRPNUM_RESERVED2, - CY_IC_GRPNUM_OPCFG_REC, - CY_IC_GRPNUM_DDATA_REC, - CY_IC_GRPNUM_MDATA_REC, - CY_IC_GRPNUM_TEST_REGS, - CY_IC_GRPNUM_BTN_KEYS, - CY_IC_GRPNUM_NUM -}; - -enum cyttsp4_ic_op_mode_commands { - CY_GET_PARAM_CMD = 0x02, - CY_SET_PARAM_CMD = 0x03, - CY_GET_CFG_BLK_CRC = 0x05, -}; - -enum cyttsp4_ic_config_mode_commands { - CY_GET_EBID_ROW_SIZE = 0x02, - CY_READ_EBID_DATA = 0x03, - CY_WRITE_EBID_DATA = 0x04, - CY_VERIFY_EBID_CRC = 0x11, -}; - -#ifdef CY_USE_TMA400 -enum cyttsp4_ic_ebid { - CY_TCH_PARM_EBID = 0x00, - CY_MDATA_EBID = 0x01, - CY_DDATA_EBID = 0x02, -}; -#endif /* --CY_USE_TMA400 */ - -#ifdef CY_USE_TMA884 -enum cyttsp4_ic_ebid { - CY_TCH_PARM_EBID = 0x00, - CY_DDATA_EBID = 0x05, - CY_MDATA_EBID = 0x06, -}; -#endif /* --CY_USE_TMA884 */ - -enum cyttsp4_flags { - CY_FLAG_NONE = 0x00, - CY_FLAG_HOVER = 0x04, -#ifdef CY_USE_DEBUG_TOOLS - CY_FLAG_FLIP = 0x08, - CY_FLAG_INV_X = 0x10, - CY_FLAG_INV_Y = 0x20, -#endif /* --CY_USE_DEBUG_TOOLS */ -}; - -enum cyttsp4_event_id { - CY_EV_NO_EVENT = 0, - CY_EV_TOUCHDOWN = 1, - CY_EV_MOVE = 2, /* significant displacement (> act dist) */ - CY_EV_LIFTOFF = 3, /* record reports last position */ -}; - -enum cyttsp4_object_id { - CY_OBJ_STANDARD_FINGER = 0, - CY_OBJ_LARGE_OBJECT = 1, - CY_OBJ_STYLUS = 2, - CY_OBJ_HOVER = 3, -}; - -enum cyttsp4_test_cmd { - CY_TEST_CMD_NULL = 0, -}; - -/* test mode NULL command driver codes; D */ -enum cyttsp4_null_test_cmd_code { - CY_NULL_CMD_NULL = 0, - CY_NULL_CMD_MODE, - CY_NULL_CMD_STATUS_SIZE, - CY_NULL_CMD_HANDSHAKE, -}; - -enum cyttsp_test_mode { - CY_TEST_MODE_NORMAL_OP = 0, /* Send touch data to OS; normal op */ - CY_TEST_MODE_CAT, /* Configuration and Test */ - CY_TEST_MODE_CLOSED_UNIT, /* Send scan data to sysfs */ -}; - -struct cyttsp4_test_mode { - int cur_mode; - int cur_cmd; - size_t cur_status_size; -}; - -/* GEN4/SOLO Operational interface definitions */ -enum cyttsp4_tch_abs { /* for ordering within the extracted touch data array */ - CY_TCH_X = 0, /* X */ - CY_TCH_Y, /* Y */ - CY_TCH_P, /* P (Z) */ - CY_TCH_T, /* TOUCH ID */ - CY_TCH_E, /* EVENT ID */ - CY_TCH_O, /* OBJECT ID */ - CY_TCH_W, /* SIZE (SOLO - Corresponds to TOUCH_MAJOR) */ -#ifdef CY_USE_TMA400_SP2 -#ifdef CY_USE_TMA400 - CY_TCH_MAJ, /* TOUCH_MAJOR */ - CY_TCH_MIN, /* TOUCH_MINOR */ - CY_TCH_OR, /* ORIENTATION */ -#endif /* --CY_USE_TMA400 */ -#endif /* --CY_USE_TMA400_SP2 */ - CY_TCH_NUM_ABS -}; -static const char * const cyttsp4_tch_abs_string[] = { - /* Order must match enum cyttsp4_tch_descriptor above */ - "X", - "Y", - "P", - "T", - "E", - "O", - "W", -#ifdef CY_USE_TMA400_SP2 -#ifdef CY_USE_TMA400 - "MAJ", - "MIN", - "OR", -#endif /* --CY_USE_TMA400 */ -#endif /* --CY_USE_TMA400_SP2 */ - "INVALID" -}; - -#ifdef CY_USE_TMA400 -#ifdef CY_USE_TMA400_SP2 -#define CY_NUM_NEW_TCH_FIELDS 3 -#else -#define CY_NUM_NEW_TCH_FIELDS 0 -#endif /* --CY_USE_TMA400_SP2 */ -#endif /* --CY_USE_TMA400 */ - -#ifdef CY_USE_TMA884 -#define CY_NUM_NEW_TCH_FIELDS 0 -#endif /* --CY_USE_TMA884 */ - -#define CY_NUM_OLD_TCH_FIELDS (CY_TCH_NUM_ABS - CY_NUM_NEW_TCH_FIELDS) - -struct cyttsp4_touch { - int abs[CY_TCH_NUM_ABS]; -}; - -/* TTSP System Information interface definitions */ -struct cyttsp4_cydata { - u8 ttpidh; - u8 ttpidl; - u8 fw_ver_major; - u8 fw_ver_minor; - u8 revctrl[CY_NUM_REVCTRL]; - u8 blver_major; - u8 blver_minor; - u8 jtag_si_id3; - u8 jtag_si_id2; - u8 jtag_si_id1; - u8 jtag_si_id0; - u8 mfgid_sz; - u8 mfg_id[CY_NUM_MFGID]; - u8 cyito_idh; - u8 cyito_idl; - u8 cyito_verh; - u8 cyito_verl; - u8 ttsp_ver_major; - u8 ttsp_ver_minor; - u8 device_info; -} __packed; - -struct cyttsp4_test { - u8 post_codeh; - u8 post_codel; -} __packed; - -struct cyttsp4_pcfg { - u8 electrodes_x; - u8 electrodes_y; - u8 len_xh; - u8 len_xl; - u8 len_yh; - u8 len_yl; - u8 axis_xh; - u8 axis_xl; - u8 axis_yh; - u8 axis_yl; - u8 max_zh; - u8 max_zl; -} __packed; - -struct cyttsp4_tch_rec_params { - u8 loc; - u8 size; -} __packed; - -struct cyttsp4_opcfg { - u8 cmd_ofs; - u8 rep_ofs; - u8 rep_szh; - u8 rep_szl; - u8 num_btns; - u8 tt_stat_ofs; - u8 obj_cfg0; - u8 max_tchs; - u8 tch_rec_siz; - struct cyttsp4_tch_rec_params tch_rec_old[CY_NUM_OLD_TCH_FIELDS]; - u8 btn_rec_siz; /* btn record size (in bytes) */ - u8 btn_diff_ofs;/* btn data loc ,diff counts, (Op-Mode byte ofs) */ - u8 btn_diff_siz;/* btn size of diff counts (in bits) */ -#ifdef CY_USE_TMA400 - struct cyttsp4_tch_rec_params tch_rec_new[CY_NUM_NEW_TCH_FIELDS]; -#endif /* --CY_USE_TMA400 */ -} __packed; - -struct cyttsp4_sysinfo_data { - u8 hst_mode; - u8 reserved; - u8 map_szh; - u8 map_szl; - u8 cydata_ofsh; - u8 cydata_ofsl; - u8 test_ofsh; - u8 test_ofsl; - u8 pcfg_ofsh; - u8 pcfg_ofsl; - u8 opcfg_ofsh; - u8 opcfg_ofsl; - u8 ddata_ofsh; - u8 ddata_ofsl; - u8 mdata_ofsh; - u8 mdata_ofsl; -} __packed; - -struct cyttsp4_sysinfo_ptr { - struct cyttsp4_cydata *cydata; - struct cyttsp4_test *test; - struct cyttsp4_pcfg *pcfg; - struct cyttsp4_opcfg *opcfg; - struct cyttsp4_ddata *ddata; - struct cyttsp4_mdata *mdata; -} __packed; - -struct cyttsp4_tch_abs_params { - size_t ofs; /* abs byte offset */ - size_t size; /* size in bits */ - size_t max; /* max value */ - size_t bofs; /* bit offset */ -}; - -struct cyttsp4_sysinfo_ofs { - size_t cmd_ofs; - size_t rep_ofs; - size_t rep_sz; - size_t num_btns; - size_t num_btn_regs; /* ceil(num_btns/4) */ - size_t tt_stat_ofs; - size_t tch_rec_siz; - size_t obj_cfg0; - size_t max_tchs; - size_t mode_size; - size_t data_size; - size_t map_sz; - size_t cydata_ofs; - size_t test_ofs; - size_t pcfg_ofs; - size_t opcfg_ofs; - size_t ddata_ofs; - size_t mdata_ofs; - size_t cydata_size; - size_t test_size; - size_t pcfg_size; - size_t opcfg_size; - size_t ddata_size; - size_t mdata_size; - size_t btn_keys_size; - struct cyttsp4_tch_abs_params tch_abs[CY_TCH_NUM_ABS]; - size_t btn_rec_siz; /* btn record size (in bytes) */ - size_t btn_diff_ofs;/* btn data loc ,diff counts, (Op-Mode byte ofs) */ - size_t btn_diff_siz;/* btn size of diff counts (in bits) */ -}; - -/* button to keycode support */ -#define CY_NUM_BTN_PER_REG 4 -#define CY_NUM_BTN_EVENT_ID 4 -#define CY_BITS_PER_BTN 2 - -enum cyttsp4_btn_state { - CY_BTN_RELEASED = 0, - CY_BTN_PRESSED = 1, - CY_BTN_NUM_STATE -}; - -struct cyttsp4_btn { - bool enabled; - int state; /* CY_BTN_PRESSED, CY_BTN_RELEASED */ - int key_code; -}; - -#define FW_VERSION 0x0100 - -#define FACTORY_TESTING - -#ifdef FACTORY_TESTING -extern struct class *sec_class; -#define TSP_VENDOR "CYPRESS" -#define TSP_IC "GEN4" - -#define TSP_CMD_STR_LEN 32 -#define TSP_CMD_RESULT_STR_LEN 512 -#define TSP_CMD_PARAM_NUM 8 - -struct factory_data { - struct list_head cmd_list_head; - u8 cmd_state; - char cmd[TSP_CMD_STR_LEN]; - int cmd_param[TSP_CMD_PARAM_NUM]; - char cmd_result[TSP_CMD_RESULT_STR_LEN]; - char cmd_buff[TSP_CMD_RESULT_STR_LEN]; - struct mutex cmd_lock; - bool cmd_is_running; -}; - -struct node_data { - s16 *cm_delta_data; - s16 *cm_abs_data; - s16 *intensity_data; - s16 *reference_data; -}; - -#define TSP_CMD(name, func) .cmd_name = name, .cmd_func = func -#define TOSTRING(x) #x - -enum { /* this is using by cmd_state valiable. */ - WAITING = 0, - RUNNING, - OK, - FAIL, - NOT_APPLICABLE, -}; - -struct tsp_cmd { - struct list_head list; - const char *cmd_name; - void (*cmd_func)(void *device_data); -}; - -#endif - - -/* driver context structure definitions */ - -struct cyttsp4 { - struct device *dev; - int irq; - struct input_dev *input; - struct mutex data_lock; /* prevent concurrent accesses */ - struct workqueue_struct *cyttsp4_wq; - struct work_struct cyttsp4_resume_startup_work; - char phys[32]; - const struct bus_type *bus_type; - const struct touch_platform_data *platform_data; - u8 *xy_mode; /* operational mode and status regs */ - u8 *xy_data; /* operational touch regs */ - u8 *xy_data_touch1; /* includes 1-byte for tt_stat */ - u8 *btn_rec_data; /* button diff count data */ - struct cyttsp4_bus_ops *bus_ops; - struct cyttsp4_sysinfo_data sysinfo_data; - struct cyttsp4_sysinfo_ptr sysinfo_ptr; - struct cyttsp4_sysinfo_ofs si_ofs; - struct cyttsp4_btn *btn; - struct cyttsp4_test_mode test; - struct completion int_running; - struct completion si_int_running; - struct completion ready_int_running; - enum cyttsp4_driver_state driver_state; - enum cyttsp4_controller_mode current_mode; - bool irq_enabled; - bool powered; /* protect against multiple open */ - bool was_suspended; - bool switch_flag; - bool soft_reset_asserted; - u16 flags; - size_t max_config_bytes; - size_t ebid_row_size; - int num_prv_tch; -#ifdef CY_USE_TMA400 - bool starting_up; -#endif /* --CY_USE_TMA400 */ -#ifdef CONFIG_HAS_EARLYSUSPEND - struct early_suspend early_suspend; -#endif -#ifdef CY_USE_WATCHDOG - struct work_struct work; - struct timer_list timer; -#endif -#if defined(CY_USE_FORCE_LOAD) || defined(CONFIG_TOUCHSCREEN_DEBUG) - bool waiting_for_fw; - char *fwname; -#endif -#ifdef CY_USE_REG_ACCESS - size_t rw_regid; -#endif -#ifdef FACTORY_TESTING - struct factory_data *factory_data; - struct node_data *node_data; -#endif -#if TOUCH_BOOST - struct timer_list dvfs_timer; -#endif -}; - -#if defined(CY_AUTO_LOAD_FW) || \ - defined(CY_USE_FORCE_LOAD) || \ - defined(CONFIG_TOUCHSCREEN_DEBUG) -static int _cyttsp4_load_app(struct cyttsp4 *ts, const u8 *fw, int fw_size); -#endif /* CY_AUTO_LOAD_FW || CY_USE_FORCE_LOAD || CONFIG_TOUCHSCREEN_DEBUG */ -static int _cyttsp4_ldr_exit(struct cyttsp4 *ts); -static int _cyttsp4_startup(struct cyttsp4 *ts); -static int _cyttsp4_get_ic_crc(struct cyttsp4 *ts, - enum cyttsp4_ic_ebid ebid, u8 *crc_h, u8 *crc_l); -static irqreturn_t cyttsp4_irq(int irq, void *handle); -static int _cyttsp4_set_mode(struct cyttsp4 *ts, u8 new_mode); -#ifdef CY_USE_TMA884 -static int _cyttsp4_calc_data_crc(struct cyttsp4 *ts, - size_t ndata, u8 *pdata, u8 *crc_h, u8 *crc_l, const char *name); -#endif /* --CY_USE_TMA884 */ - -static void _cyttsp4_pr_state(struct cyttsp4 *ts) -{ - dev_info(ts->dev, - "%s: %s\n", __func__, - ts->driver_state < CY_INVALID_STATE ? - cyttsp4_driver_state_string[ts->driver_state] : - "INVALID"); -} - -static void _cyttsp4_pr_buf(struct cyttsp4 *ts, u8 *dptr, int size, - const char *data_name) -{ - return; -} - -static int _cyttsp4_read_block_data(struct cyttsp4 *ts, u16 command, - size_t length, void *buf, int i2c_addr, bool use_subaddr) -{ - int retval = 0; - int tries = 0; - - if ((buf == NULL) || (length == 0)) { - dev_err(ts->dev, - "%s: pointer or length error" - " buf=%p length=%d\n", __func__, buf, length); - retval = -EINVAL; - } else { - for (tries = 0, retval = -1; - tries < CY_NUM_RETRY && (retval < 0); - tries++) { - retval = ts->bus_ops->read(ts->bus_ops, command, - length, buf, i2c_addr, use_subaddr); - if (retval < 0) { - msleep(CY_DELAY_DFLT); - /* - * TODO: remove the extra sleep delay when - * the loader exit sequence is streamlined - */ - msleep(150); - } - } - - if (retval < 0) { - dev_err(ts->dev, - "%s: bus read block data fail (ret=%d)\n", - __func__, retval); - } - } - - return retval; -} - -static int _cyttsp4_write_block_data(struct cyttsp4 *ts, u16 command, - size_t length, const void *buf, int i2c_addr, bool use_subaddr) -{ - int retval = 0; - int tries = 0; - - if ((buf == NULL) || (length == 0)) { - dev_err(ts->dev, - "%s: pointer or length error" - " buf=%p length=%d\n", __func__, buf, length); - retval = -EINVAL; - } else { - for (tries = 0, retval = -1; - tries < CY_NUM_RETRY && (retval < 0); - tries++) { - retval = ts->bus_ops->write(ts->bus_ops, command, - length, buf, i2c_addr, use_subaddr); - if (retval < 0) - msleep(CY_DELAY_DFLT); - } - - if (retval < 0) { - dev_err(ts->dev, - "%s: bus write block data fail (ret=%d)\n", - __func__, retval); - } - } - - return retval; -} - -#ifdef CY_USE_TMA400 -static int _cyttsp4_wait_ready_int_no_init(struct cyttsp4 *ts, - unsigned long timeout_ms) -{ - unsigned long uretval; - int retval = 0; - - mutex_unlock(&ts->data_lock); - uretval = wait_for_completion_interruptible_timeout( - &ts->ready_int_running, msecs_to_jiffies(timeout_ms)); - mutex_lock(&ts->data_lock); - if (uretval == 0) { - dev_err(ts->dev, - "%s: timeout waiting for interrupt\n", - __func__); - retval = -ETIMEDOUT; - } - - return retval; -} -#endif /* --CY_USE_TMA400 */ - -static int _cyttsp4_wait_int_no_init(struct cyttsp4 *ts, - unsigned long timeout_ms) -{ - unsigned long uretval; - int retval = 0; - - mutex_unlock(&ts->data_lock); - uretval = wait_for_completion_interruptible_timeout( - &ts->int_running, msecs_to_jiffies(timeout_ms)); - mutex_lock(&ts->data_lock); - if (uretval == 0) { - dev_err(ts->dev, - "%s: timeout waiting for interrupt\n", - __func__); - retval = -ETIMEDOUT; - } - - return retval; -} - -static int _cyttsp4_wait_int(struct cyttsp4 *ts, unsigned long timeout_ms) -{ - int retval = 0; - - INIT_COMPLETION(ts->int_running); - retval = _cyttsp4_wait_int_no_init(ts, timeout_ms); - if (retval < 0) { - dev_err(ts->dev, - "%s: timeout waiting for interrupt\n", - __func__); - } - - return retval; -} - -static int _cyttsp4_wait_si_int(struct cyttsp4 *ts, unsigned long timeout_ms) -{ - unsigned long uretval; - int retval = 0; - - mutex_unlock(&ts->data_lock); - uretval = wait_for_completion_interruptible_timeout( - &ts->si_int_running, msecs_to_jiffies(timeout_ms)); - mutex_lock(&ts->data_lock); - if (uretval == 0) { - dev_err(ts->dev, - "%s: timeout waiting for bootloader interrupt\n", - __func__); - retval = -ETIMEDOUT; - } - - return retval; -} - -static void _cyttsp4_queue_startup(struct cyttsp4 *ts, bool was_suspended) -{ - ts->was_suspended = was_suspended; - queue_work(ts->cyttsp4_wq, - &ts->cyttsp4_resume_startup_work); - dev_info(ts->dev, - "%s: startup queued\n", __func__); -} - -#if defined(CY_AUTO_LOAD_TOUCH_PARAMS) || \ - defined(CY_AUTO_LOAD_DDATA) || defined(CY_AUTO_LOAD_MDATA) || \ - defined(CY_USE_DEV_DEBUG_TOOLS) || defined(CY_USE_TMA884) || \ - defined(FACTORY_TESTING) -static u16 _cyttsp4_calc_partial_crc(struct cyttsp4 *ts, - u8 *pdata, size_t ndata, u16 crc) -{ - int i = 0; - int j = 0; - - for (i = 0; i < ndata; i++) { - crc ^= ((u16)pdata[i] << 8); - - for (j = 8; j > 0; --j) { - if (crc & 0x8000) - crc = (crc << 1) ^ 0x1021; - else - crc = crc << 1; - } - } - - return crc; -} - -static void _cyttsp4_calc_crc(struct cyttsp4 *ts, - u8 *pdata, size_t ndata, u8 *crc_h, u8 *crc_l) -{ - u16 crc = 0; - - if (pdata == NULL) - dev_err(ts->dev, - "%s: Null data ptr\n", __func__); - else if (ndata == 0) - dev_err(ts->dev, - "%s: Num data is 0\n", __func__); - else { - /* Calculate CRC */ - crc = 0xFFFF; - crc = _cyttsp4_calc_partial_crc(ts, pdata, ndata, crc); - *crc_h = crc / 256; - *crc_l = crc % 256; - } -} -#endif /* --CY_AUTO_LOAD_TOUCH_PARAMS --CY_AUTO_LOAD_DDATA - --CY_AUTO_LOAD_MDATA --CY_USE_DEV_DEBUG_TOOLS --CY_USE_TMA884 */ - -static bool _cyttsp4_chk_cmd_rdy(struct cyttsp4 *ts, u8 cmd) -{ - bool cond = !!(cmd & CY_CMD_RDY_BIT); - dev_vdbg(ts->dev, - "%s: cmd=%02X cond=%d\n", __func__, cmd, (int)cond); - - return cond; -} - -static bool _cyttsp4_chk_mode_change(struct cyttsp4 *ts, u8 cmd) -{ - bool cond = !(cmd & CY_MODE_CHANGE); - dev_vdbg(ts->dev, - "%s: cmd=%02X cond=%d\n", __func__, cmd, (int)cond); - - return cond; -} - -static void _cyttsp4_change_state(struct cyttsp4 *ts, - enum cyttsp4_driver_state new_state) -{ - ts->driver_state = new_state; - _cyttsp4_pr_state(ts); -} - -static int _cyttsp4_put_cmd_wait(struct cyttsp4 *ts, u16 ofs, - size_t cmd_len, const void *cmd_buf, unsigned long timeout_ms, - bool (*cond)(struct cyttsp4 *, u8), u8 *retcmd, - int i2c_addr, bool use_subaddr) -{ - enum cyttsp4_driver_state tmp_state; - unsigned long uretval = 0; - u8 cmd = 0; - int tries = 0; - int retval = 0; - - /* unlock here to allow any pending irq to complete */ - tmp_state = ts->driver_state; - _cyttsp4_change_state(ts, CY_TRANSFER_STATE); - mutex_unlock(&ts->data_lock); - mutex_lock(&ts->data_lock); - _cyttsp4_change_state(ts, CY_CMD_STATE); - INIT_COMPLETION(ts->int_running); - mutex_unlock(&ts->data_lock); - retval = _cyttsp4_write_block_data(ts, ofs, cmd_len, - cmd_buf, i2c_addr, use_subaddr); - if (retval < 0) { - dev_err(ts->dev, - "%s: Fail writing cmd buf r=%d\n", - __func__, retval); - mutex_lock(&ts->data_lock); - goto _cyttsp4_put_cmd_wait_exit; - } -_cyttsp4_put_cmd_wait_retry: - uretval = wait_for_completion_interruptible_timeout( - &ts->int_running, msecs_to_jiffies(timeout_ms)); - mutex_lock(&ts->data_lock); - - retval = _cyttsp4_read_block_data(ts, ofs, - sizeof(cmd), &cmd, i2c_addr, use_subaddr); - if (retval < 0) { - dev_err(ts->dev, - "%s: fail read cmd status r=%d\n", - __func__, retval); - } - if ((cond != NULL) && !cond(ts, cmd)) { - if (uretval == 0) { - dev_err(ts->dev, - "%s: timeout waiting for cmd ready\n", - __func__); - retval = -ETIMEDOUT; - } else { - if (tries++ < 2) { - INIT_COMPLETION(ts->int_running); - mutex_unlock(&ts->data_lock); - goto _cyttsp4_put_cmd_wait_retry; - } else { - dev_err(ts->dev, - "%s: cmd not ready error" - " cmd_stat=0x%02X\n", - __func__, cmd); - retval = -EIO; - } - } - } else { - /* got command ready */ - if (retcmd != NULL) - *retcmd = cmd; - retval = 0; - dev_vdbg(ts->dev, - "%s: got command ready; cmd=%02X retcmd=%p tries=%d\n", - __func__, cmd, retcmd, tries); - } - -_cyttsp4_put_cmd_wait_exit: - _cyttsp4_change_state(ts, tmp_state); - return retval; -} - -static int _cyttsp4_handshake(struct cyttsp4 *ts, u8 hst_mode) -{ - int retval = 0; - u8 cmd = 0; - - cmd = hst_mode & CY_HANDSHAKE_BIT ? - hst_mode & ~CY_HANDSHAKE_BIT : - hst_mode | CY_HANDSHAKE_BIT; - - retval = _cyttsp4_write_block_data(ts, CY_REG_BASE, - sizeof(cmd), (u8 *)&cmd, - ts->platform_data->addr[CY_TCH_ADDR_OFS], true); - - if (retval < 0) { - dev_err(ts->dev, - "%s: bus write fail on handshake (ret=%d)\n", - __func__, retval); - } - - return retval; -} - -static int _cyttsp4_cmd_handshake(struct cyttsp4 *ts) -{ - u8 host_mode = 0; - int retval = 0; - - retval = _cyttsp4_read_block_data(ts, CY_REG_BASE, - sizeof(host_mode), &host_mode, - ts->platform_data->addr[CY_TCH_ADDR_OFS], true); - if (retval < 0) { - dev_err(ts->dev, - "%s: Fail read host mode r=%d\n", - __func__, retval); - } else { - retval = _cyttsp4_handshake(ts, host_mode); - if (retval < 0) { - dev_err(ts->dev, - "%s: Fail handshake r=%d\n", - __func__, retval); - } - } - - return retval; -} - -#ifdef CY_USE_TMA400 -#if defined(CY_AUTO_LOAD_TOUCH_PARAMS) || defined(CY_USE_DEV_DEBUG_TOOLS) -static void _cyttsp_read_table_crc(struct cyttsp4 *ts, const u8 *ptable, - u8 *crc_h, u8 *crc_l) -{ - size_t crc_loc = (ptable[3] * 256) + ptable[2]; - - *crc_l = ptable[crc_loc]; - *crc_h = ptable[crc_loc + 1]; -} -#endif - -/* Get EBID Row Size is a Config mode command */ -static int _cyttsp4_get_ebid_row_size(struct cyttsp4 *ts) -{ - int retval = 0; - u8 cmd = 0; - u8 cmd_dat[CY_NUM_DAT + 1]; /* +1 for cmd byte */ - - memset(cmd_dat, 0, sizeof(cmd_dat)); - cmd_dat[0] = CY_GET_EBID_ROW_SIZE; /* get EBID row size command */ - - retval = _cyttsp4_put_cmd_wait(ts, ts->si_ofs.cmd_ofs, - sizeof(cmd_dat), cmd_dat, CY_HALF_SEC_TMO_MS, - _cyttsp4_chk_cmd_rdy, &cmd, - ts->platform_data->addr[CY_TCH_ADDR_OFS], true); - if (retval < 0) { - dev_err(ts->dev, - "%s: Fail Get EBID row size command r=%d\n", - __func__, retval); - } else { - retval = _cyttsp4_read_block_data(ts, ts->si_ofs.cmd_ofs, - sizeof(cmd_dat), cmd_dat, - ts->platform_data->addr[CY_TCH_ADDR_OFS], true); - if (retval < 0) { - dev_err(ts->dev, - "%s: Fail get EBID row size r=%d\n", - __func__, retval); - ts->ebid_row_size = CY_EBID_ROW_SIZE_DFLT; - dev_err(ts->dev, - "%s: Use default EBID row size=%d\n", - __func__, ts->ebid_row_size); - } else { - ts->ebid_row_size = (cmd_dat[1] * 256) + cmd_dat[2]; - retval = _cyttsp4_cmd_handshake(ts); - if (retval < 0) { - dev_err(ts->dev, - "%s: Command handshake error r=%d\n", - __func__, retval); - /* continue anyway; rely on handshake tmo */ - retval = 0; - } - } - } - - return retval; -} - -static const u8 cyttsp4_security_key[] = { - 0xA5, 0x01, 0x02, 0x03, 0xFF, 0xFE, 0xFD, 0x5A -}; - -#if defined(CY_AUTO_LOAD_TOUCH_PARAMS) || \ - defined(CY_AUTO_LOAD_DDATA) || defined(CY_AUTO_LOAD_MDATA) || \ - defined(CY_USE_DEV_DEBUG_TOOLS) || defined(FACTORY_TESTING) -/* Get EBID Row Data is a Config mode command */ -static int _cyttsp4_get_ebid_data_tma400(struct cyttsp4 *ts, - enum cyttsp4_ic_ebid ebid, size_t row_id, u8 *pdata) -{ - int rc = 0; - int retval = 0; - u8 crc_h = 0; - u8 crc_l = 0; - u8 cmd = 0; - u8 status = 0; - u8 cmd_dat[CY_NUM_DAT + 1]; /* +1 for cmd byte */ - - memset(cmd_dat, 0, sizeof(cmd_dat)); - cmd_dat[0] = CY_READ_EBID_DATA; /* get EBID data command */ - cmd_dat[1] = row_id / 256; - cmd_dat[2] = row_id % 256; - cmd_dat[3] = ts->ebid_row_size / 256; - cmd_dat[4] = ts->ebid_row_size % 256; - cmd_dat[5] = ebid; - - if (pdata == NULL) { - dev_err(ts->dev, - "%s: Get EBID=%d row=%d Data buffer err ptr=%p\n", - __func__, ebid, row_id, pdata); - goto _cyttsp4_get_ebid_data_tma400_exit; - } - - retval = _cyttsp4_put_cmd_wait(ts, ts->si_ofs.cmd_ofs, - sizeof(cmd_dat), cmd_dat, CY_HALF_SEC_TMO_MS, - _cyttsp4_chk_cmd_rdy, &cmd, - ts->platform_data->addr[CY_TCH_ADDR_OFS], true); - if (retval < 0) { - dev_err(ts->dev, - "%s: Fail Get EBID=%d row=%d Data cmd r=%d\n", - __func__, ebid, row_id, retval); - goto _cyttsp4_get_ebid_data_tma400_exit; - } - - retval = _cyttsp4_read_block_data(ts, ts->si_ofs.cmd_ofs + 1, - sizeof(status), &status, - ts->platform_data->addr[CY_TCH_ADDR_OFS], true); - if (retval < 0) { - dev_err(ts->dev, - "%s: Fail get EBID=%d row=%d status r=%d\n", - __func__, ebid, row_id, retval); - goto _cyttsp4_get_ebid_data_tma400_exit; - } - - if (status != 0x00) { - dev_err(ts->dev, - "%s: Get EBID=%d row=%d status=%d error\n", - __func__, ebid, row_id, status); - retval = -EIO; - goto _cyttsp4_get_ebid_data_tma400_exit; - } - - retval = _cyttsp4_read_block_data(ts, ts->si_ofs.cmd_ofs + 1 + 5, - ts->ebid_row_size + 2, pdata, - ts->platform_data->addr[CY_TCH_ADDR_OFS], true); - if (retval < 0) { - dev_err(ts->dev, - "%s: fail EBID=%d row=%d data r=%d\n", - __func__, ebid, row_id, retval); - retval = -EIO; - } else { - _cyttsp4_calc_crc(ts, pdata, ts->ebid_row_size, &crc_h, &crc_l); - if (pdata[ts->ebid_row_size] != crc_h || - pdata[ts->ebid_row_size + 1] != crc_l) { - dev_err(ts->dev, - "%s: EBID=%d row_id=%d row_data_crc=%02X%02X" - " not equal to calc_crc=%02X%02X\n", - __func__, ebid, row_id, - pdata[ts->ebid_row_size], - pdata[ts->ebid_row_size + 1], - crc_h, crc_l); - /* continue anyway; allow handshake */ - rc = -EIO; - } - retval = _cyttsp4_cmd_handshake(ts); - if (retval < 0) { - dev_err(ts->dev, - "%s: Command handshake error r=%d\n", - __func__, retval); - /* continue anyway; rely on handshake tmo */ - retval = 0; - } - retval = rc; - } - -_cyttsp4_get_ebid_data_tma400_exit: - return retval; -} - -/* Put EBID Row Data is a Config mode command */ -static int _cyttsp4_put_ebid_data_tma400(struct cyttsp4 *ts, - enum cyttsp4_ic_ebid ebid, size_t row_id, u8 *out_data) -{ - u8 calc_crc[2]; - u8 *pdata = NULL; - u8 ret_cmd = 0; - size_t psize = 0; - u8 status = 0; - int retval = 0; - - memset(calc_crc, 0, sizeof(calc_crc)); - psize = 1 + 5 + ts->ebid_row_size + sizeof(cyttsp4_security_key) + 2; - pdata = kzalloc(psize, GFP_KERNEL); - if (pdata == NULL || out_data == NULL) { - dev_err(ts->dev, - "%s: Buffer ptr err EBID=%d row=%d" - " alloc_ptr=%p out_data=%p\n", - __func__, ebid, row_id, pdata, out_data); - retval = -EINVAL; - } else { - pdata[0] = CY_WRITE_EBID_DATA; /* put ebid data command */ - pdata[1] = row_id / 256; - pdata[2] = row_id % 256; - pdata[3] = ts->ebid_row_size / 256; - pdata[4] = ts->ebid_row_size % 256; - pdata[5] = ebid; - memcpy(&pdata[1 + 5], out_data, ts->ebid_row_size); - memcpy(&pdata[1 + 5 + ts->ebid_row_size], - cyttsp4_security_key, sizeof(cyttsp4_security_key)); - _cyttsp4_calc_crc(ts, &pdata[1 + 5], ts->ebid_row_size, - &calc_crc[0], &calc_crc[1]); - memcpy(&pdata[1 + 5 + ts->ebid_row_size + - sizeof(cyttsp4_security_key)], - calc_crc, sizeof(calc_crc)); - - retval = _cyttsp4_put_cmd_wait(ts, ts->si_ofs.cmd_ofs, - psize, pdata, CY_HALF_SEC_TMO_MS, - _cyttsp4_chk_cmd_rdy, &ret_cmd, - ts->platform_data->addr[CY_TCH_ADDR_OFS], true); - if (retval < 0) { - dev_err(ts->dev, - "%s: Fail Put EBID=%d row=%d Data cmd r=%d\n", - __func__, ebid, row_id, retval); - goto _cyttsp4_put_ebid_data_tma400_exit; - } - - retval = _cyttsp4_read_block_data(ts, ts->si_ofs.cmd_ofs + 1, - sizeof(status), &status, - ts->platform_data->addr[CY_TCH_ADDR_OFS], true); - if (retval < 0) { - dev_err(ts->dev, - "%s: Fail put EBID=%d row=%d" - " read status r=%d\n", - __func__, ebid, row_id, retval); - goto _cyttsp4_put_ebid_data_tma400_exit; - } - - retval = _cyttsp4_cmd_handshake(ts); - if (retval < 0) { - dev_err(ts->dev, - "%s: Fail handshake on Put EBID=%d row=%d" - " r=%d\n", __func__, ebid, row_id, retval); - /* continue; rely on handshake tmo */ - retval = 0; - } - - if (status != 0x00) { - dev_err(ts->dev, - "%s: Put EBID=%d row=%d status=%d error\n", - __func__, ebid, row_id, status); - retval = -EIO; - } else - retval = 0; - } -_cyttsp4_put_ebid_data_tma400_exit: - if (pdata != NULL) - kfree(pdata); - return retval; -} -#endif /* --CY_AUTO_LOAD_TOUCH_PARAMS --CY_AUTO_LOAD_DDATA - --CY_AUTO_LOAD_MDATA --CY_USE_DEV_DEBUG_TOOLS */ - -#if defined(CY_AUTO_LOAD_TOUCH_PARAMS) || defined(CY_USE_DEV_DEBUG_TOOLS) -/* Put All Touch Params is a Config mode command */ -static int _cyttsp4_put_all_params_tma400(struct cyttsp4 *ts) -{ - enum cyttsp4_ic_ebid ebid = CY_TCH_PARM_EBID; - size_t row_id = 0; - size_t num_rows = 0; - size_t table_size = 0; - size_t residue = 0; - u8 *pdata = NULL; - u8 *ptable = NULL; - int retval = 0; - - pdata = kzalloc(ts->ebid_row_size, GFP_KERNEL); - if (pdata == NULL) { - dev_err(ts->dev, - "%s: Alloc error ebid=%d\n", - __func__, ebid); - retval = -ENOMEM; - } else if (ts->platform_data->sett[CY_IC_GRPNUM_TCH_PARM_VAL] == NULL) - dev_err(ts->dev, - "%s: NULL param values table\n", __func__); - else if (ts->platform_data->sett[CY_IC_GRPNUM_TCH_PARM_VAL] - ->data == NULL) - dev_err(ts->dev, - "%s: NULL param values table data\n", __func__); - else if (ts->platform_data->sett[CY_IC_GRPNUM_TCH_PARM_VAL]->size == 0) - dev_err(ts->dev, - "%s: param values table size is 0\n", __func__); - else { - ptable = (u8 *)ts->platform_data->sett - [CY_IC_GRPNUM_TCH_PARM_VAL]->data; - table_size = ts->platform_data->sett - [CY_IC_GRPNUM_TCH_PARM_VAL]->size; - num_rows = table_size / ts->ebid_row_size; - dev_vdbg(ts->dev, - "%s: num_rows=%d row_size=%d" - " table_size=%d\n", __func__, - num_rows, ts->ebid_row_size, table_size); - for (row_id = 0; row_id < num_rows;) { - memcpy(pdata, ptable, ts->ebid_row_size); - dev_vdbg(ts->dev, - "%s: row=%d pdata=%p\n", - __func__, row_id, pdata); - _cyttsp4_pr_buf(ts, pdata, ts->ebid_row_size, - "ebid_data"); - retval = _cyttsp4_put_ebid_data_tma400(ts, - ebid, row_id, pdata); - if (retval < 0) { - dev_err(ts->dev, - "%s: Fail put row=%d r=%d\n", - __func__, row_id, retval); - break; - } else { - ptable += ts->ebid_row_size; - row_id++; - } - } - if (!(retval < 0)) { - residue = table_size % ts->ebid_row_size; - if (residue) { - memset(pdata, 0, ts->ebid_row_size); - memcpy(pdata, ptable, residue); - dev_vdbg(ts->dev, - "%s: ebid=%d row=%d data:\n", - __func__, ebid, row_id); - _cyttsp4_pr_buf(ts, pdata, ts->ebid_row_size, - "ebid_data"); - retval = _cyttsp4_put_ebid_data_tma400(ts, - ebid, row_id, pdata); - if (retval < 0) { - dev_err(ts->dev, - "%s: Fail put row=%d r=%d\n", - __func__, row_id, retval); - } - } - } - } - - if (pdata != NULL) - kfree(pdata); - - return retval; -} -#endif /* --CY_AUTO_LOAD_TOUCH_PARAMS */ - -/* Check MDDATA is a Config mode command */ -static int _cyttsp4_check_mddata_tma400(struct cyttsp4 *ts, bool *updated) -{ - bool ddata_updated = false; - bool mdata_updated = false; -#if defined(CY_AUTO_LOAD_DDATA) || defined(CY_AUTO_LOAD_MDATA) - enum cyttsp4_ic_ebid ebid = CY_DDATA_EBID; - size_t num_data = 0; - size_t crc_ofs = 0; - u8 crc_h = 0; - u8 crc_l = 0; -#endif - u8 *pdata = NULL; - u8 *pmddata = NULL; - int retval = 0; - - if (ts->ebid_row_size == 0) { - dev_err(ts->dev, - "%s: fail allocate set MDDATA buffer\n", __func__); - retval = -EINVAL; - goto _cyttsp4_check_mddata_tma400_exit; - } - pdata = kzalloc(ts->ebid_row_size, GFP_KERNEL); - if (pdata == NULL) { - dev_err(ts->dev, - "%s: fail allocate set MDDATA buffer\n", __func__); - retval = -ENOMEM; - goto _cyttsp4_check_mddata_tma400_exit; - } - pmddata = kzalloc(ts->ebid_row_size, GFP_KERNEL); - if (pmddata == NULL) { - dev_err(ts->dev, - "%s: fail allocate set MDDATA buffer\n", __func__); - retval = -ENOMEM; - goto _cyttsp4_check_mddata_tma400_exit; - } - -#ifdef CY_AUTO_LOAD_DDATA - /* check for platform_data DDATA */ - ebid = CY_DDATA_EBID; - if (ts->platform_data->sett[CY_IC_GRPNUM_DDATA_REC] == NULL) { - dev_vdbg(ts->dev, - "%s: No platform DDATA table\n", __func__); - goto _cyttsp4_check_mdata_block; - } - if (ts->platform_data->sett[CY_IC_GRPNUM_DDATA_REC]->data == NULL) { - dev_vdbg(ts->dev, - "%s: No platform DDATA table data\n", __func__); - goto _cyttsp4_check_mdata_block; - } - if (ts->platform_data->sett[CY_IC_GRPNUM_DDATA_REC]->size == 0) { - dev_vdbg(ts->dev, - "%s: Platform DDATA table has size=0\n", __func__); - goto _cyttsp4_check_mdata_block; - } - - dev_vdbg(ts->dev, - "%s: call get ebid data for DDATA\n", __func__); - retval = _cyttsp4_get_ebid_data_tma400(ts, ebid, 0, pdata); - if (retval < 0) { - dev_err(ts->dev, - "%s: Fail get DDATA r=%d\n", __func__, retval); - goto _cyttsp4_check_mdata_block; - } - - dev_vdbg(ts->dev, - "%s: copy pdata -> pmddata\n", __func__); - memcpy(pmddata, pdata, 4); - num_data = ts->platform_data->sett - [CY_IC_GRPNUM_DDATA_REC]->size < CY_NUM_DDATA ? - ts->platform_data->sett - [CY_IC_GRPNUM_DDATA_REC]->size : CY_NUM_DDATA; - dev_vdbg(ts->dev, - "%s: copy %d bytes from platform data to ddata array\n", - __func__, num_data); - memcpy(&pmddata[4], ts->platform_data->sett - [CY_IC_GRPNUM_DDATA_REC]->data, num_data); - if (num_data < CY_NUM_DDATA) - memset(&pmddata[4 + num_data], 0, CY_NUM_DDATA - num_data); - crc_ofs = (pmddata[3] * 256) + pmddata[2]; - if (crc_ofs == 0) - crc_ofs = 126; - dev_vdbg(ts->dev, - "%s: ddata crc_ofs=%d num_data=%d\n", - __func__, crc_ofs, num_data); - - _cyttsp4_calc_crc(ts, pmddata, crc_ofs, &crc_h, &crc_l); - pmddata[crc_ofs] = crc_l; - pmddata[crc_ofs+1] = crc_h; - _cyttsp4_pr_buf(ts, pdata, ts->ebid_row_size, "pdata"); - _cyttsp4_pr_buf(ts, pmddata, ts->ebid_row_size, "pmddata"); - if (pmddata[crc_ofs] != pdata[crc_ofs] || - pmddata[crc_ofs+1] != pdata[crc_ofs+1]) { - retval = _cyttsp4_put_ebid_data_tma400(ts, ebid, 0, pmddata); - if (retval < 0) - dev_err(ts->dev, - "%s: Fail put DDATA r=%d\n", __func__, retval); - else - ddata_updated = true; - } - -_cyttsp4_check_mdata_block: -#else - ddata_updated = false; -#endif /* --CY_AUTO_LOAD_DDATA */ - -#ifdef CY_AUTO_LOAD_MDATA - /* check for platform_data MDATA */ - memset(pdata, 0, ts->ebid_row_size); - memset(pmddata, 0, ts->ebid_row_size); - ebid = CY_MDATA_EBID; - if (ts->platform_data->sett[CY_IC_GRPNUM_MDATA_REC] == NULL) { - dev_vdbg(ts->dev, - "%s: No platform MDATA table\n", __func__); - goto _cyttsp4_check_mddata_tma400_exit; - } - if (ts->platform_data->sett[CY_IC_GRPNUM_MDATA_REC]->data == NULL) { - dev_vdbg(ts->dev, - "%s: No platform MDATA table data\n", __func__); - goto _cyttsp4_check_mddata_tma400_exit; - } - if (ts->platform_data->sett[CY_IC_GRPNUM_MDATA_REC]->size == 0) { - dev_vdbg(ts->dev, - "%s: Platform MDATA table has size=0\n", __func__); - goto _cyttsp4_check_mddata_tma400_exit; - } - - retval = _cyttsp4_get_ebid_data_tma400(ts, ebid, 0, pdata); - if (retval < 0) { - dev_err(ts->dev, - "%s: Fail get MDATA r=%d\n", __func__, retval); - goto _cyttsp4_check_mddata_tma400_exit; - } - - memcpy(pmddata, pdata, 4); - num_data = ts->platform_data->sett - [CY_IC_GRPNUM_MDATA_REC]->size < CY_NUM_MDATA ? - ts->platform_data->sett - [CY_IC_GRPNUM_MDATA_REC]->size : CY_NUM_MDATA; - dev_vdbg(ts->dev, - "%s: copy %d bytes from platform data to mdata array\n", - __func__, num_data); - memcpy(&pmddata[4], ts->platform_data->sett - [CY_IC_GRPNUM_MDATA_REC]->data, num_data); - if (num_data < CY_NUM_MDATA) - memset(&pmddata[4 + num_data], 0, CY_NUM_MDATA - num_data); - crc_ofs = (pmddata[3] * 256) + pmddata[2]; - if (crc_ofs == 0) - crc_ofs = 124; - dev_vdbg(ts->dev, - "%s: mdata crc_ofs=%d num_data=%d\n", - __func__, crc_ofs, num_data); - _cyttsp4_calc_crc(ts, pmddata, crc_ofs, &crc_h, &crc_l); - pmddata[crc_ofs] = crc_l; - pmddata[crc_ofs+1] = crc_h; - _cyttsp4_pr_buf(ts, pdata, ts->ebid_row_size, "pdata"); - _cyttsp4_pr_buf(ts, pmddata, ts->ebid_row_size, "pmddata"); - if (pmddata[crc_ofs] != pdata[crc_ofs] || - pmddata[crc_ofs+1] != pdata[crc_ofs+1]) { - retval = _cyttsp4_put_ebid_data_tma400(ts, ebid, 0, pmddata); - if (retval < 0) - dev_err(ts->dev, - "%s: Fail put MDATA r=%d\n", __func__, retval); - else - mdata_updated = true; - } -#else - mdata_updated = false; -#endif /* --CY_AUTO_LOAD_MDATA */ - -_cyttsp4_check_mddata_tma400_exit: - if (pdata != NULL) - kfree(pdata); - if (pmddata != NULL) - kfree(pmddata); - if (updated != NULL) - *updated = ddata_updated || mdata_updated; - return retval; -} -#endif /* --CY_USE_TMA400 */ - -#ifdef CY_USE_TMA884 -static int _cyttsp4_handshake_enable(struct cyttsp4 *ts) -{ - int retval = 0; - u8 cmd_dat[CY_NUM_DAT + 1]; /* +1 for cmd byte */ - - memset(cmd_dat, 0, sizeof(cmd_dat)); - cmd_dat[0] = 0x26; /* handshake enable operational cmd */ - cmd_dat[1] = 0x03; /* synchronous level handshake */ - retval = _cyttsp4_put_cmd_wait(ts, ts->si_ofs.cmd_ofs, - sizeof(cmd_dat), cmd_dat, CY_HALF_SEC_TMO_MS, - _cyttsp4_chk_cmd_rdy, NULL, - ts->platform_data->addr[CY_TCH_ADDR_OFS], true); - if (retval < 0) { - dev_err(ts->dev, - "%s: Fail Enable Handshake command r=%d\n", - __func__, retval); - goto _cyttsp4_set_handshake_enable_exit; - } - - retval = _cyttsp4_read_block_data(ts, ts->si_ofs.cmd_ofs, - sizeof(cmd_dat), cmd_dat, - ts->platform_data->addr[CY_TCH_ADDR_OFS], true); - if (retval < 0) { - dev_err(ts->dev, - "%s: Fail read Enable Hanshake command status" - "r=%d\n", __func__, retval); - goto _cyttsp4_set_handshake_enable_exit; - } - - if (cmd_dat[6] != cmd_dat[1]) { - dev_err(ts->dev, - "%s: Fail enable handshake in device\n", - __func__); - /* return no error and let driver handshake anyway */ - } - - dev_vdbg(ts->dev, - "%s: check cmd ready r=%d" - " cmd[]=%02X %02X %02X %02X %02X %02X %02X\n", - __func__, retval, - cmd_dat[0], cmd_dat[1], cmd_dat[2], cmd_dat[3], - cmd_dat[4], cmd_dat[5], cmd_dat[6]); - -_cyttsp4_set_handshake_enable_exit: - return retval; -} -#endif /* --CY_USE_TMA884 */ - -/* - * change device mode - For example, change from - * system information mode to operating mode - */ -static int _cyttsp4_set_device_mode(struct cyttsp4 *ts, - u8 new_mode, u8 new_cur_mode, char *mode) -{ - u8 cmd = 0; - int retval = 0; - - cmd = new_mode + CY_MODE_CHANGE; - - retval = _cyttsp4_put_cmd_wait(ts, CY_REG_BASE, - sizeof(cmd), &cmd, CY_HALF_SEC_TMO_MS, - _cyttsp4_chk_mode_change, &cmd, - ts->platform_data->addr[CY_TCH_ADDR_OFS], true); - if (retval < 0) { - dev_err(ts->dev, - "%s: Fail Set mode command new_mode=%02X r=%d\n", - __func__, new_mode, retval); - goto _cyttsp4_set_device_mode_exit; - } - - if (cmd != new_mode) { - dev_err(ts->dev, - "%s: failed to switch to %s mode\n", __func__, mode); - retval = -EIO; - } else { - ts->current_mode = new_cur_mode; - retval = _cyttsp4_handshake(ts, cmd); - if (retval < 0) { - dev_err(ts->dev, - "%s: Fail handshake r=%d\n", __func__, retval); - /* continue; rely on handshake tmo */ - retval = 0; - } - } - - dev_dbg(ts->dev, - "%s: check op ready ret=%d host_mode=%02X\n", - __func__, retval, cmd); - -_cyttsp4_set_device_mode_exit: - return retval; -} - -static int _cyttsp4_set_mode(struct cyttsp4 *ts, u8 new_mode) -{ - enum cyttsp4_driver_state new_state = CY_TRANSFER_STATE; - u8 new_cur_mode = CY_MODE_OPERATIONAL; - char *mode = NULL; -#ifdef CY_USE_TMA400 - unsigned long uretval = 0; -#endif /* --CY_USE_TMA400 */ - int retval = 0; - - switch (new_mode) { - case CY_OPERATE_MODE: - new_cur_mode = CY_MODE_OPERATIONAL; - mode = "operational"; - INIT_COMPLETION(ts->ready_int_running); - _cyttsp4_change_state(ts, CY_READY_STATE); - new_state = CY_ACTIVE_STATE; - break; - case CY_SYSINFO_MODE: - new_cur_mode = CY_MODE_SYSINFO; - mode = "sysinfo"; - new_state = CY_SYSINFO_STATE; - break; - case CY_CONFIG_MODE: - new_cur_mode = CY_MODE_OPERATIONAL; - mode = "config"; - new_state = ts->driver_state; - - break; - default: - dev_err(ts->dev, - "%s: invalid mode change request m=0x%02X\n", - __func__, new_mode); - retval = -EINVAL; - goto _cyttsp_set_mode_exit; - } - - retval = _cyttsp4_set_device_mode(ts, - new_mode, new_cur_mode, mode); - if (retval < 0) { - dev_err(ts->dev, - "%s: Fail switch to %s mode\n", __func__, mode); - _cyttsp4_change_state(ts, CY_IDLE_STATE); - } else { -#ifdef CY_USE_TMA400 - if ((new_mode == CY_OPERATE_MODE) && ts->starting_up) { - uretval = _cyttsp4_wait_ready_int_no_init(ts, - CY_HALF_SEC_TMO_MS * 5); - } -#endif /* --CY_USE_TMA400 */ - _cyttsp4_change_state(ts, new_state); - } - -_cyttsp_set_mode_exit: - return retval; -} - -#ifdef CY_USE_TMA884 -static int _cyttsp4_write_config_block(struct cyttsp4 *ts, u8 blockid, - const u8 *pdata, size_t ndata, u8 crc_h, u8 crc_l, const char *name) -{ - uint8_t *buf = NULL; - size_t buf_size = 0; - u8 status = 0; - int retval = 0; - - /* pre-amble (10) + data (122) + crc (2) + key (8) */ - buf_size = sizeof(uint8_t) * 142; - buf = kzalloc(buf_size, GFP_KERNEL); - if (buf == NULL) { - dev_err(ts->dev, - "%s: Failed to allocate buffer for %s\n", - __func__, name); - retval = -ENOMEM; - goto _cyttsp4_write_config_block_exit; - } - - if (pdata == NULL) { - dev_err(ts->dev, - "%s: bad data pointer\n", __func__); - retval = -ENXIO; - goto _cyttsp4_write_config_block_exit; - } - - if (ndata > 122) { - dev_err(ts->dev, - "%s: %s is too large n=%d size=%d\n", - __func__, name, ndata, 122); - retval = -EOVERFLOW; - goto _cyttsp4_write_config_block_exit; - } - - /* Set command bytes */ - buf[0] = 0x04; /* cmd */ - buf[1] = 0x00; /* row offset high */ - buf[2] = 0x00; /* row offset low */ - buf[3] = 0x00; /* write block length high */ - buf[4] = 0x80; /* write block length low */ - buf[5] = blockid; /* write block id */ - buf[6] = 0x00; /* num of config bytes + 4 high */ - buf[7] = 0x7E; /* num of config bytes + 4 low */ - buf[8] = 0x00; /* max block size w/o crc high */ - buf[9] = 0x7E; /* max block size w/o crc low */ - - /* Copy platform data */ - memcpy(&(buf[10]), pdata, ndata); - - /* Copy block CRC */ - buf[132] = crc_h; - buf[133] = crc_l; - - /* Set key bytes */ - buf[134] = 0x45; - buf[135] = 0x63; - buf[136] = 0x36; - buf[137] = 0x6F; - buf[138] = 0x34; - buf[139] = 0x38; - buf[140] = 0x73; - buf[141] = 0x77; - - /* Write config block */ - _cyttsp4_pr_buf(ts, buf, buf_size, name); - - retval = _cyttsp4_write_block_data(ts, ts->si_ofs.cmd_ofs + 1, - 141, &(buf[1]), - ts->platform_data->addr[CY_TCH_ADDR_OFS], true); - if (retval < 0) { - dev_err(ts->dev, - "%s: Failed to write config %s r=%d\n", - __func__, name, retval); - goto _cyttsp4_write_config_block_exit; - } - - retval = _cyttsp4_put_cmd_wait(ts, ts->si_ofs.cmd_ofs, - 1, &(buf[0]), CY_TEN_SEC_TMO_MS, - _cyttsp4_chk_cmd_rdy, NULL, - ts->platform_data->addr[CY_TCH_ADDR_OFS], true); - if (retval < 0) { - dev_err(ts->dev, - "%s: Fail write config command r=%d\n", - __func__, retval); - goto _cyttsp4_write_config_block_exit; - } - - retval = _cyttsp4_read_block_data(ts, ts->si_ofs.cmd_ofs + 1, - sizeof(status), &status, - ts->platform_data->addr[CY_TCH_ADDR_OFS], true); - if (retval < 0) { - dev_err(ts->dev, - "%s: Fail read status r=%d\n", - __func__, retval); - goto _cyttsp4_write_config_block_exit; - } - - if (status != 0x00) { - dev_err(ts->dev, - "%s: Write config status=%d error\n", - __func__, status); - goto _cyttsp4_write_config_block_exit; - } - -_cyttsp4_write_config_block_exit: - kfree(buf); - return retval; -} -#endif /* --CY_USE_TMA884 */ - - -#ifdef CY_USE_TMA884 -#ifdef CY_AUTO_LOAD_TOUCH_PARAMS -static int _cyttsp4_set_op_params(struct cyttsp4 *ts, u8 crc_h, u8 crc_l) -{ - int retval = 0; - - if (ts->platform_data->sett[CY_IC_GRPNUM_TCH_PARM_VAL] == NULL) { - dev_err(ts->dev, - "%s: Missing Platform Touch Parameter" - " values table\n", __func__); - retval = -ENXIO; - goto _cyttsp4_set_op_params_exit; - } - - if ((ts->platform_data->sett - [CY_IC_GRPNUM_TCH_PARM_VAL]->data == NULL) || - (ts->platform_data->sett - [CY_IC_GRPNUM_TCH_PARM_VAL]->size == 0)) { - dev_err(ts->dev, - "%s: Missing Platform Touch Parameter" - " values table data\n", __func__); - retval = -ENXIO; - goto _cyttsp4_set_op_params_exit; - } - - /* Change to Config Mode */ - retval = _cyttsp4_set_mode(ts, CY_CONFIG_MODE); - if (retval < 0) { - dev_err(ts->dev, - "%s: Failed to switch to config mode" - " for touch params\n", __func__); - goto _cyttsp4_set_op_params_exit; - } - retval = _cyttsp4_write_config_block(ts, CY_TCH_PARM_EBID, - ts->platform_data->sett[CY_IC_GRPNUM_TCH_PARM_VAL]->data, - ts->platform_data->sett[CY_IC_GRPNUM_TCH_PARM_VAL]->size, - crc_h, crc_l, "platform_touch_param_data"); - -_cyttsp4_set_op_params_exit: - return retval; -} -#endif /* --CY_AUTO_LOAD_TOUCH_PARAMS */ - -static int _cyttsp4_set_data_block(struct cyttsp4 *ts, u8 blkid, u8 *pdata, - size_t ndata, const char *name, bool force, bool *data_updated) -{ - u8 data_crc[2]; - u8 ic_crc[2]; - int retval = 0; - - memset(data_crc, 0, sizeof(data_crc)); - memset(ic_crc, 0, sizeof(ic_crc)); - *data_updated = false; - - _cyttsp4_pr_buf(ts, pdata, ndata, name); - - dev_vdbg(ts->dev, - "%s: calc %s crc\n", __func__, name); - retval = _cyttsp4_calc_data_crc(ts, ndata, pdata, - &data_crc[0], &data_crc[1], - name); - if (retval < 0) { - dev_err(ts->dev, - "%s: fail calc crc for %s (0x%02X%02X) r=%d\n", - __func__, name, - data_crc[0], data_crc[1], - retval); - goto _cyttsp_set_data_block_exit; - } - - dev_vdbg(ts->dev, - "%s: get ic %s crc\n", __func__, name); - retval = _cyttsp4_set_mode(ts, CY_OPERATE_MODE); - if (retval < 0) { - dev_err(ts->dev, - "%s: Failed to switch to operational mode\n", __func__); - goto _cyttsp_set_data_block_exit; - } - retval = _cyttsp4_get_ic_crc(ts, blkid, - &ic_crc[0], &ic_crc[1]); - if (retval < 0) { - dev_err(ts->dev, - "%s: fail get ic crc for %s (0x%02X%02X) r=%d\n", - __func__, name, - ic_crc[0], ic_crc[1], - retval); - goto _cyttsp_set_data_block_exit; - } - - dev_vdbg(ts->dev, - "%s: %s calc_crc=0x%02X%02X ic_crc=0x%02X%02X\n", - __func__, name, - data_crc[0], data_crc[1], - ic_crc[0], ic_crc[1]); - if ((data_crc[0] != ic_crc[0]) || (data_crc[1] != ic_crc[1]) || force) { - /* Change to Config Mode */ - retval = _cyttsp4_set_mode(ts, CY_CONFIG_MODE); - if (retval < 0) { - dev_err(ts->dev, - "%s: Failed to switch to config mode" - " for sysinfo regs\n", __func__); - goto _cyttsp_set_data_block_exit; - } - retval = _cyttsp4_write_config_block(ts, blkid, pdata, - ndata, data_crc[0], data_crc[1], name); - if (retval < 0) { - dev_err(ts->dev, - "%s: fail write %s config block r=%d\n", - __func__, name, retval); - goto _cyttsp_set_data_block_exit; - } - - dev_vdbg(ts->dev, - "%s: write %s config block ok\n", __func__, name); - *data_updated = true; - } - -_cyttsp_set_data_block_exit: - return retval; -} - -static int _cyttsp4_set_sysinfo_regs(struct cyttsp4 *ts, bool *updated) -{ - bool ddata_updated = false; - bool mdata_updated = false; -#if defined(CY_AUTO_LOAD_DDATA) || defined(CY_AUTO_LOAD_MDATA) - size_t num_data = 0; -#endif /* --CY_AUTO_LOAD_DDATA || --CY_AUTO_LOAD_DDATA */ - u8 *pdata = NULL; - int retval = 0; - - pdata = kzalloc(CY_NUM_MDATA, GFP_KERNEL); - if (pdata == NULL) { - dev_err(ts->dev, - "%s: fail allocate set sysinfo regs buffer\n", - __func__); - retval = -ENOMEM; - goto _cyttsp4_set_sysinfo_regs_err; - } - -#ifdef CY_AUTO_LOAD_DDATA - /* check for missing DDATA */ - if (ts->platform_data->sett[CY_IC_GRPNUM_DDATA_REC] == NULL) { - dev_vdbg(ts->dev, - "%s: No platform_ddata table\n", __func__); - dev_vdbg(ts->dev, - "%s: Use a zero filled array to compare with device\n", - __func__); - goto _cyttsp4_set_sysinfo_regs_set_ddata_block; - } - if ((ts->platform_data->sett[CY_IC_GRPNUM_DDATA_REC]->data == NULL) || - (ts->platform_data->sett[CY_IC_GRPNUM_DDATA_REC]->size == 0)) { - dev_vdbg(ts->dev, - "%s: No platform_ddata table data\n", __func__); - dev_vdbg(ts->dev, - "%s: Use a zero filled array to compare with device\n", - __func__); - goto _cyttsp4_set_sysinfo_regs_set_ddata_block; - } - - /* copy platform data design data to the device eeprom */ - num_data = ts->platform_data->sett - [CY_IC_GRPNUM_DDATA_REC]->size < CY_NUM_DDATA ? - ts->platform_data->sett - [CY_IC_GRPNUM_DDATA_REC]->size : CY_NUM_DDATA; - dev_vdbg(ts->dev, - "%s: copy %d bytes from platform data to ddata array\n", - __func__, num_data); - memcpy(pdata, ts->platform_data->sett[CY_IC_GRPNUM_DDATA_REC]->data, - num_data); - -_cyttsp4_set_sysinfo_regs_set_ddata_block: - /* set data block will check CRC match/nomatch */ - retval = _cyttsp4_set_data_block(ts, CY_DDATA_EBID, pdata, - CY_NUM_DDATA, "platform_ddata", false, &ddata_updated); - if (retval < 0) { - dev_err(ts->dev, - "%s: Fail while writing platform_ddata" - " block to ic r=%d\n", __func__, retval); - } -#else - ddata_updated = false; -#endif /* --CY_AUTO_LOAD_DDATA */ - -#ifdef CY_AUTO_LOAD_MDATA - /* check for missing MDATA */ - if (ts->platform_data->sett[CY_IC_GRPNUM_MDATA_REC] == NULL) { - dev_vdbg(ts->dev, - "%s: No platform_mdata table\n", __func__); - dev_vdbg(ts->dev, - "%s: Use a zero filled array to compare with device\n", - __func__); - goto _cyttsp4_set_sysinfo_regs_set_mdata_block; - } - if ((ts->platform_data->sett[CY_IC_GRPNUM_MDATA_REC]->data == NULL) || - (ts->platform_data->sett[CY_IC_GRPNUM_MDATA_REC]->size == 0)) { - dev_vdbg(ts->dev, - "%s: No platform_mdata table data\n", __func__); - dev_vdbg(ts->dev, - "%s: Use a zero filled array to compare with device\n", - __func__); - goto _cyttsp4_set_sysinfo_regs_set_mdata_block; - } - - /* copy platform manufacturing data to the device eeprom */ - num_data = ts->platform_data->sett - [CY_IC_GRPNUM_MDATA_REC]->size < CY_NUM_MDATA ? - ts->platform_data->sett - [CY_IC_GRPNUM_MDATA_REC]->size : CY_NUM_MDATA; - dev_vdbg(ts->dev, - "%s: copy %d bytes from platform data to mdata array\n", - __func__, num_data); - memcpy(pdata, ts->platform_data->sett[CY_IC_GRPNUM_MDATA_REC]->data, - num_data); - -_cyttsp4_set_sysinfo_regs_set_mdata_block: - /* set data block will check CRC match/nomatch */ - retval = _cyttsp4_set_data_block(ts, CY_MDATA_EBID, pdata, - CY_NUM_MDATA, "platform_mdata", false, &mdata_updated); - if (retval < 0) { - dev_err(ts->dev, - "%s: Fail while writing platform_mdata" - " block to ic r=%d\n", __func__, retval); - } -#else - mdata_updated = false; -#endif /* --CY_AUTO_LOAD_MDATA */ - - kfree(pdata); -_cyttsp4_set_sysinfo_regs_err: - *updated = ddata_updated || mdata_updated; - return retval; -} -#endif /* --CY_USE_TMA884 */ - -static int _cyttsp4_bits_2_bytes(struct cyttsp4 *ts, int nbits, int *max) -{ - int nbytes; - - *max = 1 << nbits; - - for (nbytes = 0; nbits > 0;) { - dev_vdbg(ts->dev, - "%s: nbytes=%d nbits=%d\n", __func__, nbytes, nbits); - nbytes++; - if (nbits > 8) - nbits -= 8; - else - nbits = 0; - dev_vdbg(ts->dev, - "%s: nbytes=%d nbits=%d\n", __func__, nbytes, nbits); - } - - return nbytes; -} - -static int _cyttsp4_get_sysinfo_regs(struct cyttsp4 *ts) -{ - int btn = 0; - int num_defined_keys = 0; - u16 *key_table = NULL; - enum cyttsp4_tch_abs abs = 0; -#ifdef CY_USE_TMA400_SP2 -#ifdef CY_USE_TMA400 - int i = 0; -#endif /* --CY_USE_TMA400 */ -#endif /* --CY_USE_TMA400_SP2 */ - int retval = 0; - - /* pre-clear si_ofs structure */ - memset(&ts->si_ofs, 0, sizeof(struct cyttsp4_sysinfo_ofs)); - - /* get the sysinfo data offsets */ - retval = _cyttsp4_read_block_data(ts, CY_REG_BASE, - sizeof(ts->sysinfo_data), &(ts->sysinfo_data), - ts->platform_data->addr[CY_TCH_ADDR_OFS], true); - if (retval < 0) { - dev_err(ts->dev, - "%s: fail read sysinfo data offsets r=%d\n", - __func__, retval); - goto _cyttsp4_get_sysinfo_regs_exit_no_handshake; - } else { - /* Print sysinfo data offsets */ - _cyttsp4_pr_buf(ts, (u8 *)&ts->sysinfo_data, - sizeof(ts->sysinfo_data), "sysinfo_data_offsets"); - - /* convert sysinfo data offset bytes into integers */ - ts->si_ofs.map_sz = (ts->sysinfo_data.map_szh * 256) + - ts->sysinfo_data.map_szl; - ts->si_ofs.cydata_ofs = (ts->sysinfo_data.cydata_ofsh * 256) + - ts->sysinfo_data.cydata_ofsl; - ts->si_ofs.test_ofs = (ts->sysinfo_data.test_ofsh * 256) + - ts->sysinfo_data.test_ofsl; - ts->si_ofs.pcfg_ofs = (ts->sysinfo_data.pcfg_ofsh * 256) + - ts->sysinfo_data.pcfg_ofsl; - ts->si_ofs.opcfg_ofs = (ts->sysinfo_data.opcfg_ofsh * 256) + - ts->sysinfo_data.opcfg_ofsl; - ts->si_ofs.ddata_ofs = (ts->sysinfo_data.ddata_ofsh * 256) + - ts->sysinfo_data.ddata_ofsl; - ts->si_ofs.mdata_ofs = (ts->sysinfo_data.mdata_ofsh * 256) + - ts->sysinfo_data.mdata_ofsl; - dev_err(ts->dev, "%s: ofset.map_sz:%x,cydata_ofs:%x,test_ofs:%x,pcfg_ofs:%x,opcfg_ofs:%x,ddata_ofs:%x,mdata_ofs:%x\n", - __func__, ts->si_ofs.map_sz, ts->si_ofs.cydata_ofs, ts->si_ofs.test_ofs, ts->si_ofs.pcfg_ofs, ts->si_ofs.opcfg_ofs, ts->si_ofs.ddata_ofs, ts->si_ofs.mdata_ofs); - if (ts->si_ofs.map_sz != 0xc1 || ts->si_ofs.cydata_ofs != 0x10) { - dev_err(ts->dev, "%s: ofset data is invalid\n", __func__); - goto _cyttsp4_get_sysinfo_regs_exit_no_handshake; - } - } - - /* get the sysinfo cydata */ - ts->si_ofs.cydata_size = ts->si_ofs.test_ofs - ts->si_ofs.cydata_ofs; - if (ts->sysinfo_ptr.cydata == NULL) - ts->sysinfo_ptr.cydata = kzalloc(ts->si_ofs.cydata_size, GFP_KERNEL); - if (ts->sysinfo_ptr.cydata == NULL) { - retval = -ENOMEM; - dev_err(ts->dev, - "%s: fail alloc cydata memory r=%d\n", - __func__, retval); - goto _cyttsp4_get_sysinfo_regs_exit; - } else { - memset(ts->sysinfo_ptr.cydata, 0, ts->si_ofs.cydata_size); - retval = _cyttsp4_read_block_data(ts, ts->si_ofs.cydata_ofs, - ts->si_ofs.cydata_size, ts->sysinfo_ptr.cydata, - ts->platform_data->addr[CY_TCH_ADDR_OFS], true); - if (retval < 0) { - dev_err(ts->dev, - "%s: fail read cydata r=%d\n", - __func__, retval); - goto _cyttsp4_get_sysinfo_regs_exit; - } - /* Print sysinfo cydata */ - _cyttsp4_pr_buf(ts, (u8 *)ts->sysinfo_ptr.cydata, - ts->si_ofs.cydata_size, "sysinfo_cydata"); - } - /* get the sysinfo test data */ - ts->si_ofs.test_size = ts->si_ofs.pcfg_ofs - ts->si_ofs.test_ofs; - if (ts->sysinfo_ptr.test == NULL) - ts->sysinfo_ptr.test = kzalloc(ts->si_ofs.test_size, GFP_KERNEL); - if (ts->sysinfo_ptr.test == NULL) { - retval = -ENOMEM; - dev_err(ts->dev, - "%s: fail alloc test memory r=%d\n", - __func__, retval); - goto _cyttsp4_get_sysinfo_regs_exit; - } else { - memset(ts->sysinfo_ptr.test, 0, ts->si_ofs.test_size); - retval = _cyttsp4_read_block_data(ts, ts->si_ofs.test_ofs, - ts->si_ofs.test_size, ts->sysinfo_ptr.test, - ts->platform_data->addr[CY_TCH_ADDR_OFS], true); - if (retval < 0) { - dev_err(ts->dev, - "%s: fail read test data r=%d\n", - __func__, retval); - goto _cyttsp4_get_sysinfo_regs_exit; - } - /* Print sysinfo test data */ - _cyttsp4_pr_buf(ts, (u8 *)ts->sysinfo_ptr.test, - ts->si_ofs.test_size, "sysinfo_test_data"); -#ifdef CY_USE_TMA400 - if (ts->sysinfo_ptr.test->post_codel & 0x01) { - dev_info(ts->dev, - "%s: Reset was a WATCHDOG RESET codel=%02X\n", - __func__, ts->sysinfo_ptr.test->post_codel); - } - - if (!(ts->sysinfo_ptr.test->post_codel & 0x02)) { - dev_info(ts->dev, - "%s: Config Data CRC FAIL codel=%02X\n", - __func__, ts->sysinfo_ptr.test->post_codel); - } - - if (!(ts->sysinfo_ptr.test->post_codel & 0x04)) { - dev_info(ts->dev, - "%s: PANEL TEST FAIL codel=%02X\n", - __func__, ts->sysinfo_ptr.test->post_codel); - } - - dev_info(ts->dev, - "%s: SCANNING is %s codel=%02X\n", __func__, - ts->sysinfo_ptr.test->post_codel & 0x08 ? "ENABLED" : - "DISABLED", ts->sysinfo_ptr.test->post_codel); -#endif /* --CY_USE_TMA400 */ - } - /* get the sysinfo pcfg data */ - ts->si_ofs.pcfg_size = ts->si_ofs.opcfg_ofs - ts->si_ofs.pcfg_ofs; - if (ts->sysinfo_ptr.pcfg == NULL) - ts->sysinfo_ptr.pcfg = kzalloc(ts->si_ofs.pcfg_size, GFP_KERNEL); - if (ts->sysinfo_ptr.pcfg == NULL) { - retval = -ENOMEM; - dev_err(ts->dev, - "%s: fail alloc pcfg memory r=%d\n", - __func__, retval); - goto _cyttsp4_get_sysinfo_regs_exit; - } else { - memset(ts->sysinfo_ptr.pcfg, 0, ts->si_ofs.pcfg_size); - retval = _cyttsp4_read_block_data(ts, ts->si_ofs.pcfg_ofs, - ts->si_ofs.pcfg_size, ts->sysinfo_ptr.pcfg, - ts->platform_data->addr[CY_TCH_ADDR_OFS], true); - if (retval < 0) { - dev_err(ts->dev, - "%s: fail read pcfg data r=%d\n", - __func__, retval); - goto _cyttsp4_get_sysinfo_regs_exit; - } - /* Print sysinfo pcfg data */ - _cyttsp4_pr_buf(ts, (u8 *)ts->sysinfo_ptr.pcfg, - ts->si_ofs.pcfg_size, "sysinfo_pcfg_data"); - } - /* get the sysinfo opcfg data */ - ts->si_ofs.opcfg_size = ts->si_ofs.ddata_ofs - ts->si_ofs.opcfg_ofs; - if (ts->sysinfo_ptr.opcfg == NULL) - ts->sysinfo_ptr.opcfg = kzalloc(ts->si_ofs.opcfg_size, GFP_KERNEL); - if (ts->sysinfo_ptr.opcfg == NULL) { - retval = -ENOMEM; - dev_err(ts->dev, - "%s: fail alloc opcfg memory r=%d\n", - __func__, retval); - goto _cyttsp4_get_sysinfo_regs_exit; - } else { - memset(ts->sysinfo_ptr.opcfg, 0, ts->si_ofs.opcfg_size); - retval = _cyttsp4_read_block_data(ts, ts->si_ofs.opcfg_ofs, - ts->si_ofs.opcfg_size, ts->sysinfo_ptr.opcfg, - ts->platform_data->addr[CY_TCH_ADDR_OFS], true); - if (retval < 0) { - dev_err(ts->dev, - "%s: fail read opcfg data r=%d\n", - __func__, retval); - goto _cyttsp4_get_sysinfo_regs_exit; - } - ts->si_ofs.cmd_ofs = ts->sysinfo_ptr.opcfg->cmd_ofs; - ts->si_ofs.rep_ofs = ts->sysinfo_ptr.opcfg->rep_ofs; - ts->si_ofs.rep_sz = (ts->sysinfo_ptr.opcfg->rep_szh * 256) + - ts->sysinfo_ptr.opcfg->rep_szl; - ts->si_ofs.num_btns = ts->sysinfo_ptr.opcfg->num_btns; - if (ts->si_ofs.num_btns == 0) - ts->si_ofs.num_btn_regs = 0; - else { - ts->si_ofs.num_btn_regs = ts->si_ofs.num_btns / - CY_NUM_BTN_PER_REG; - if (ts->si_ofs.num_btns % CY_NUM_BTN_PER_REG) - ts->si_ofs.num_btn_regs++; - } - ts->si_ofs.tt_stat_ofs = ts->sysinfo_ptr.opcfg->tt_stat_ofs; - ts->si_ofs.obj_cfg0 = ts->sysinfo_ptr.opcfg->obj_cfg0; - ts->si_ofs.max_tchs = ts->sysinfo_ptr.opcfg->max_tchs & - CY_SIZE_FIELD_MASK; - ts->si_ofs.tch_rec_siz = ts->sysinfo_ptr.opcfg->tch_rec_siz & - CY_SIZE_FIELD_MASK; - - /* Get the old touch fields */ - for (abs = CY_TCH_X; abs < CY_NUM_OLD_TCH_FIELDS; abs++) { - ts->si_ofs.tch_abs[abs].ofs = - ts->sysinfo_ptr.opcfg->tch_rec_old[abs].loc; - ts->si_ofs.tch_abs[abs].size = - _cyttsp4_bits_2_bytes(ts, - ts->sysinfo_ptr.opcfg->tch_rec_old[abs].size & - CY_SIZE_FIELD_MASK, - &ts->si_ofs.tch_abs[abs].max); - ts->si_ofs.tch_abs[abs].bofs = - (ts->sysinfo_ptr.opcfg->tch_rec_old[abs].size & - CY_BOFS_MASK) >> CY_BOFS_SHIFT; - dev_vdbg(ts->dev, - "%s: tch_rec_%s\n", __func__, - cyttsp4_tch_abs_string[abs]); - dev_vdbg(ts->dev, - "%s: ofs =%2d\n", __func__, - ts->si_ofs.tch_abs[abs].ofs); - dev_vdbg(ts->dev, - "%s: siz =%2d\n", __func__, - ts->si_ofs.tch_abs[abs].size); - dev_vdbg(ts->dev, - "%s: max =%2d\n", __func__, - ts->si_ofs.tch_abs[abs].max); - dev_vdbg(ts->dev, - "%s: bofs=%2d\n", __func__, - ts->si_ofs.tch_abs[abs].bofs); - } - -#ifdef CY_USE_TMA400_SP2 -#ifdef CY_USE_TMA400 - /* skip over the button fields */ - - /* Get the new touch fields */ - for (i = 0; abs < CY_TCH_NUM_ABS; abs++, i++) { - ts->si_ofs.tch_abs[abs].ofs = - ts->sysinfo_ptr.opcfg->tch_rec_new[i].loc; - ts->si_ofs.tch_abs[abs].size = - _cyttsp4_bits_2_bytes(ts, - ts->sysinfo_ptr.opcfg->tch_rec_new[i].size & - CY_SIZE_FIELD_MASK, - &ts->si_ofs.tch_abs[abs].max); - ts->si_ofs.tch_abs[abs].bofs = - (ts->sysinfo_ptr.opcfg->tch_rec_new[i].size & - CY_BOFS_MASK) >> CY_BOFS_SHIFT; - dev_vdbg(ts->dev, - "%s: tch_rec_%s\n", __func__, - cyttsp4_tch_abs_string[abs]); - dev_vdbg(ts->dev, - "%s: ofs =%2d\n", __func__, - ts->si_ofs.tch_abs[abs].ofs); - dev_vdbg(ts->dev, - "%s: siz =%2d\n", __func__, - ts->si_ofs.tch_abs[abs].size); - dev_vdbg(ts->dev, - "%s: max =%2d\n", __func__, - ts->si_ofs.tch_abs[abs].max); - dev_vdbg(ts->dev, - "%s: bofs=%2d\n", __func__, - ts->si_ofs.tch_abs[abs].bofs); - } -#endif /* --CY_USE_TMA400 */ -#endif /* --CY_USE_TMA400_SP2 */ - - ts->si_ofs.btn_rec_siz = ts->sysinfo_ptr.opcfg->btn_rec_siz; - ts->si_ofs.btn_diff_ofs = ts->sysinfo_ptr.opcfg->btn_diff_ofs; - ts->si_ofs.btn_diff_siz = ts->sysinfo_ptr.opcfg->btn_diff_siz; - ts->si_ofs.mode_size = ts->si_ofs.tt_stat_ofs + 1; - ts->si_ofs.data_size = ts->si_ofs.max_tchs * - ts->sysinfo_ptr.opcfg->tch_rec_siz; - if (ts->si_ofs.num_btns) - ts->si_ofs.mode_size += ts->si_ofs.num_btn_regs; - - /* Print sysinfo opcfg data */ - _cyttsp4_pr_buf(ts, (u8 *)ts->sysinfo_ptr.opcfg, - ts->si_ofs.opcfg_size, "sysinfo_opcfg_data"); - } - - /* get the sysinfo ddata data */ - ts->si_ofs.ddata_size = ts->si_ofs.mdata_ofs - ts->si_ofs.ddata_ofs; - if (ts->sysinfo_ptr.ddata == NULL) - ts->sysinfo_ptr.ddata = kzalloc(ts->si_ofs.ddata_size, GFP_KERNEL); - if (ts->sysinfo_ptr.ddata == NULL) { - dev_err(ts->dev, - "%s: fail alloc ddata memory r=%d\n", - __func__, retval); - /* continue */ - } else { - memset(ts->sysinfo_ptr.ddata, 0, ts->si_ofs.ddata_size); - retval = _cyttsp4_read_block_data(ts, ts->si_ofs.ddata_ofs, - ts->si_ofs.ddata_size, ts->sysinfo_ptr.ddata, - ts->platform_data->addr[CY_TCH_ADDR_OFS], true); - if (retval < 0) { - dev_err(ts->dev, - "%s: fail read ddata data r=%d\n", - __func__, retval); - goto _cyttsp4_get_sysinfo_regs_exit; - } - /* Print sysinfo ddata */ - _cyttsp4_pr_buf(ts, (u8 *)ts->sysinfo_ptr.ddata, - ts->si_ofs.ddata_size, "sysinfo_ddata"); - } - /* get the sysinfo mdata data */ - ts->si_ofs.mdata_size = ts->si_ofs.map_sz - ts->si_ofs.mdata_ofs; - if (ts->sysinfo_ptr.mdata == NULL) - ts->sysinfo_ptr.mdata = kzalloc(ts->si_ofs.mdata_size, GFP_KERNEL); - if (ts->sysinfo_ptr.mdata == NULL) { - dev_err(ts->dev, - "%s: fail alloc mdata memory r=%d\n", - __func__, retval); - /* continue */ - } else { - memset(ts->sysinfo_ptr.mdata, 0, ts->si_ofs.mdata_size); - retval = _cyttsp4_read_block_data(ts, ts->si_ofs.mdata_ofs, - ts->si_ofs.mdata_size, ts->sysinfo_ptr.mdata, - ts->platform_data->addr[CY_TCH_ADDR_OFS], true); - if (retval < 0) { - dev_err(ts->dev, - "%s: fail read mdata data r=%d\n", - __func__, retval); - goto _cyttsp4_get_sysinfo_regs_exit; - } - /* Print sysinfo mdata */ - _cyttsp4_pr_buf(ts, (u8 *)ts->sysinfo_ptr.mdata, - ts->si_ofs.mdata_size, "sysinfo_mdata"); - } - - if (ts->si_ofs.num_btns) { - ts->si_ofs.btn_keys_size = ts->si_ofs.num_btns * - sizeof(struct cyttsp4_btn); - if (ts->btn == NULL) - ts->btn = kzalloc(ts->si_ofs.btn_keys_size, GFP_KERNEL); - if (ts->btn == NULL) { - dev_err(ts->dev, - "%s: fail alloc btn_keys memory r=%d\n", - __func__, retval); - } else { - if (ts->platform_data->sett - [CY_IC_GRPNUM_BTN_KEYS] == NULL) - num_defined_keys = 0; - else if (ts->platform_data->sett - [CY_IC_GRPNUM_BTN_KEYS]->data == NULL) - num_defined_keys = 0; - else - num_defined_keys = ts->platform_data->sett - [CY_IC_GRPNUM_BTN_KEYS]->size; - for (btn = 0; btn < ts->si_ofs.num_btns && - btn < num_defined_keys; btn++) { - key_table = (u16 *)ts->platform_data->sett - [CY_IC_GRPNUM_BTN_KEYS]->data; - ts->btn[btn].key_code = key_table[btn]; - ts->btn[btn].enabled = true; - } - for (; btn < ts->si_ofs.num_btns; btn++) { - ts->btn[btn].key_code = KEY_RESERVED; - ts->btn[btn].enabled = true; - } - } - } else { - ts->si_ofs.btn_keys_size = 0; - ts->btn = NULL; - } - - dev_vdbg(ts->dev, - "%s: cydata_ofs =%4d siz=%4d\n", __func__, - ts->si_ofs.cydata_ofs, ts->si_ofs.cydata_size); - dev_vdbg(ts->dev, - "%s: test_ofs =%4d siz=%4d\n", __func__, - ts->si_ofs.test_ofs, ts->si_ofs.test_size); - dev_vdbg(ts->dev, - "%s: pcfg_ofs =%4d siz=%4d\n", __func__, - ts->si_ofs.pcfg_ofs, ts->si_ofs.pcfg_size); - dev_vdbg(ts->dev, - "%s: opcfg_ofs =%4d siz=%4d\n", __func__, - ts->si_ofs.opcfg_ofs, ts->si_ofs.opcfg_size); - dev_vdbg(ts->dev, - "%s: ddata_ofs =%4d siz=%4d\n", __func__, - ts->si_ofs.ddata_ofs, ts->si_ofs.ddata_size); - dev_vdbg(ts->dev, - "%s: mdata_ofs =%4d siz=%4d\n", __func__, - ts->si_ofs.mdata_ofs, ts->si_ofs.mdata_size); - - dev_vdbg(ts->dev, - "%s: cmd_ofs =%4d\n", __func__, ts->si_ofs.cmd_ofs); - dev_vdbg(ts->dev, - "%s: rep_ofs =%4d\n", __func__, ts->si_ofs.rep_ofs); - dev_vdbg(ts->dev, - "%s: rep_sz =%4d\n", __func__, ts->si_ofs.rep_sz); - dev_vdbg(ts->dev, - "%s: num_btns =%4d\n", __func__, ts->si_ofs.num_btns); - dev_vdbg(ts->dev, - "%s: num_btn_regs =%4d\n", __func__, ts->si_ofs.num_btn_regs); - dev_vdbg(ts->dev, - "%s: tt_stat_ofs =%4d\n", __func__, ts->si_ofs.tt_stat_ofs); - dev_vdbg(ts->dev, - "%s: tch_rec_siz =%4d\n", __func__, ts->si_ofs.tch_rec_siz); - dev_vdbg(ts->dev, - "%s: max_tchs =%4d\n", __func__, ts->si_ofs.max_tchs); - dev_vdbg(ts->dev, - "%s: mode_siz =%4d\n", __func__, ts->si_ofs.mode_size); - dev_vdbg(ts->dev, - "%s: data_siz =%4d\n", __func__, ts->si_ofs.data_size); - dev_vdbg(ts->dev, - "%s: map_sz =%4d\n", __func__, ts->si_ofs.map_sz); - - dev_vdbg(ts->dev, - "%s: btn_rec_siz =%2d\n", __func__, ts->si_ofs.btn_rec_siz); - dev_vdbg(ts->dev, - "%s: btn_diff_ofs =%2d\n", __func__, ts->si_ofs.btn_diff_ofs); - dev_vdbg(ts->dev, - "%s: btn_diff_siz =%2d\n", __func__, ts->si_ofs.btn_diff_siz); - - dev_vdbg(ts->dev, - "%s: mode_size =%2d\n", __func__, ts->si_ofs.mode_size); - dev_vdbg(ts->dev, - "%s: data_size =%2d\n", __func__, ts->si_ofs.data_size); - - if (ts->xy_mode == NULL) - ts->xy_mode = kzalloc(ts->si_ofs.mode_size, GFP_KERNEL); - if (ts->xy_data == NULL) - ts->xy_data = kzalloc(ts->si_ofs.data_size, GFP_KERNEL); - if (ts->xy_data_touch1 == NULL) { - ts->xy_data_touch1 = kzalloc(ts->si_ofs.tch_rec_siz + 1, - GFP_KERNEL); - } - if (ts->btn_rec_data == NULL) { - ts->btn_rec_data = kzalloc(ts->si_ofs.btn_rec_siz * - ts->si_ofs.num_btns, GFP_KERNEL); - } - if ((ts->xy_mode == NULL) || (ts->xy_data == NULL) || - (ts->xy_data_touch1 == NULL) || (ts->btn_rec_data == NULL)) { - dev_err(ts->dev, - "%s: fail memory alloc xy_mode=%p xy_data=%p" - "xy_data_touch1=%p btn_rec_data=%p\n", __func__, - ts->xy_mode, ts->xy_data, - ts->xy_data_touch1, ts->btn_rec_data); - /* continue */ - } - - dev_vdbg(ts->dev, - "%s: xy_mode=%p xy_data=%p xy_data_touch1=%p\n", - __func__, ts->xy_mode, ts->xy_data, ts->xy_data_touch1); - -_cyttsp4_get_sysinfo_regs_exit: - /* provide flow control handshake */ - retval = _cyttsp4_handshake(ts, ts->sysinfo_data.hst_mode); - if (retval < 0) { - dev_err(ts->dev, - "%s: handshake fail on sysinfo reg\n", - __func__); - /* continue; rely on handshake tmo */ - } - -_cyttsp4_get_sysinfo_regs_exit_no_handshake: - return retval; -} - -static int _cyttsp4_load_status_regs(struct cyttsp4 *ts) -{ - int rep_stat_ofs = 0; - int retval = 0; - - rep_stat_ofs = ts->si_ofs.rep_ofs + 1; - if (ts->xy_mode == NULL) { - dev_err(ts->dev, - "%s: mode ptr not yet initialized xy_mode=%p\n", - __func__, ts->xy_mode); - /* continue */ - } else { - retval = _cyttsp4_read_block_data(ts, CY_REG_BASE, - ts->si_ofs.mode_size, ts->xy_mode, - ts->platform_data->addr[CY_TCH_ADDR_OFS], true); - if (retval < 0) { - dev_err(ts->dev, - "%s: fail read mode regs r=%d\n", - __func__, retval); - retval = -EIO; - } - _cyttsp4_pr_buf(ts, ts->xy_mode, ts->si_ofs.mode_size, - "xy_mode"); - } - return retval; -} - -static void _cyttsp4_btn_key_release(struct cyttsp4 *ts, - int cur_btn, u8 cur_btn_mask, int num_btns) -{ - int btn = 0; - - /* Check for button releases */ - for (btn = 0; btn < num_btns; btn++) { - if (ts->btn[cur_btn + btn].enabled) { - switch ((cur_btn_mask >> (btn * CY_BITS_PER_BTN)) & - (CY_NUM_BTN_EVENT_ID - 1)) { - case (CY_BTN_RELEASED): - if (ts->btn[cur_btn + btn].state == - CY_BTN_PRESSED) { - input_report_key(ts->input, - ts->btn[cur_btn + btn].key_code, - CY_BTN_RELEASED); - ts->btn[cur_btn + btn].state = - CY_BTN_RELEASED; - input_sync(ts->input); - dev_dbg(ts->dev, - "%s: btn=%d key_code=%d" - " RELEASED\n", __func__, - cur_btn + btn, ts->btn - [cur_btn + btn].key_code); - } - break; - case (CY_BTN_PRESSED): - break; - default: - break; - } - } - } - return; -} - -static void _cyttsp4_btn_key_press(struct cyttsp4 *ts, - int cur_btn, u8 cur_btn_mask, int num_btns) -{ - int btn = 0; - - /* Check for button presses */ - for (btn = 0; btn < num_btns; btn++) { - if (ts->btn[cur_btn + btn].enabled) { - switch ((cur_btn_mask >> (btn * CY_BITS_PER_BTN)) & - (CY_NUM_BTN_EVENT_ID - 1)) { - case (CY_BTN_RELEASED): - break; - case (CY_BTN_PRESSED): - if (ts->btn[cur_btn + btn].state == - CY_BTN_RELEASED) { - input_report_key(ts->input, - ts->btn[cur_btn + btn].key_code, - CY_BTN_PRESSED); - ts->btn[cur_btn + btn].state = - CY_BTN_PRESSED; - input_sync(ts->input); - dev_dbg(ts->dev, - "%s: btn=%d key_code=%d" - " PRESSED\n", __func__, - cur_btn + btn, ts->btn - [cur_btn + btn].key_code); - } - break; - default: - break; - } - } - } - return; -} - -static void _cyttsp4_get_touch_axis(struct cyttsp4 *ts, - enum cyttsp4_tch_abs abs, int *axis, int size, - int max, u8 *xy_data, int bofs) -{ - int nbyte = 0; - int next = 0; - - for (nbyte = 0, *axis = 0, next = 0; nbyte < size; nbyte++) { - dev_vdbg(ts->dev, - "%s: *axis=%02X(%d) size=%d max=%08X xy_data=%p" - " xy_data[%d]=%02X(%d)\n", - __func__, *axis, *axis, size, max, xy_data, next, - xy_data[next], xy_data[next]); - *axis = (*axis * 256) + (xy_data[next] >> bofs); - next++; - } - - *axis &= max - 1; - -#ifdef CY_USE_TMA400_SP2 -#ifdef CY_USE_TMA400 - /* sign extend signals that can have negative values */ - if (abs == CY_TCH_OR) { - if (*axis >= (max / 2)) - *axis = -((~(*axis) & (max - 1)) + 1); - } -#endif /* --CY_USE_TMA400 */ -#endif /* --CY_USE_TMA400_SP2 */ - - dev_vdbg(ts->dev, - "%s: *axis=%02X(%d) size=%d max=%08X xy_data=%p" - " xy_data[%d]=%02X(%d)\n", - __func__, *axis, *axis, size, max, xy_data, next, - xy_data[next], xy_data[next]); -} - -static void _cyttsp4_get_touch(struct cyttsp4 *ts, - struct cyttsp4_touch *touch, u8 *xy_data) -{ - enum cyttsp4_tch_abs abs = 0; -#ifdef CY_USE_DEBUG_TOOLS - int tmp = 0; - bool flipped = false; -#endif /* --CY_USE_DEBUG_TOOLS */ - - for (abs = CY_TCH_X; abs < CY_TCH_NUM_ABS; abs++) { - _cyttsp4_get_touch_axis(ts, abs, &touch->abs[abs], - ts->si_ofs.tch_abs[abs].size, - ts->si_ofs.tch_abs[abs].max, - xy_data + ts->si_ofs.tch_abs[abs].ofs, - ts->si_ofs.tch_abs[abs].bofs); - dev_vdbg(ts->dev, - "%s: get %s=%08X(%d) size=%d" - " ofs=%d max=%d xy_data+ofs=%p bofs=%d\n", - __func__, cyttsp4_tch_abs_string[abs], - touch->abs[abs], touch->abs[abs], - ts->si_ofs.tch_abs[abs].size, - ts->si_ofs.tch_abs[abs].ofs, - ts->si_ofs.tch_abs[abs].max, - xy_data + ts->si_ofs.tch_abs[abs].ofs, - ts->si_ofs.tch_abs[abs].bofs); - } - -#ifdef CY_USE_DEBUG_TOOLS - if (ts->flags & CY_FLAG_FLIP) { - tmp = touch->abs[CY_TCH_X]; - touch->abs[CY_TCH_X] = - touch->abs[CY_TCH_Y]; - touch->abs[CY_TCH_Y] = tmp; - flipped = true; - } - if (ts->flags & CY_FLAG_INV_X) { - if (!flipped) { - touch->abs[CY_TCH_X] = - ts->platform_data->frmwrk->abs - [(CY_ABS_X_OST * CY_NUM_ABS_SET) + CY_MAX_OST] - - touch->abs[CY_TCH_X]; - } else { - touch->abs[CY_TCH_X] = - ts->platform_data->frmwrk->abs - [(CY_ABS_Y_OST * CY_NUM_ABS_SET) + CY_MAX_OST] - - touch->abs[CY_TCH_X]; - } - } - if (ts->flags & CY_FLAG_INV_Y) { - if (!flipped) { - touch->abs[CY_TCH_Y] = - ts->platform_data->frmwrk->abs - [(CY_ABS_Y_OST * CY_NUM_ABS_SET) + CY_MAX_OST] - - touch->abs[CY_TCH_Y]; - } else { - touch->abs[CY_TCH_Y] = - ts->platform_data->frmwrk->abs - [(CY_ABS_X_OST * CY_NUM_ABS_SET) + CY_MAX_OST] - - touch->abs[CY_TCH_Y]; - } - } -#endif /* --CY_USE_DEBUG_TOOLS */ -} - -static void _cyttsp4_get_mt_touches(struct cyttsp4 *ts, int num_cur_tch) -{ - struct cyttsp4_touch touch; - int signal = CY_IGNORE_VALUE; - int i = 0; - int j = 0; - int t = 0; - - memset(&touch, 0, sizeof(struct cyttsp4_touch)); - for (i = 0; i < num_cur_tch; i++) { - _cyttsp4_get_touch(ts, &touch, - ts->xy_data + (i * ts->si_ofs.tch_rec_siz)); - if ((touch.abs[CY_TCH_T] < ts->platform_data->frmwrk->abs - [(CY_ABS_ID_OST * CY_NUM_ABS_SET) + CY_MIN_OST]) || - (touch.abs[CY_TCH_T] > ts->platform_data->frmwrk->abs - [(CY_ABS_ID_OST * CY_NUM_ABS_SET) + CY_MAX_OST])) { - dev_err(ts->dev, - "%s: touch=%d has bad track_id=%d max_id=%d\n", - __func__, i, touch.abs[CY_TCH_T], - ts->platform_data->frmwrk->abs - [(CY_ABS_ID_OST * CY_NUM_ABS_SET) + - CY_MAX_OST]); - input_mt_sync(ts->input); - } else { - /* use 0 based track id's */ - signal = ts->platform_data->frmwrk->abs - [(CY_ABS_ID_OST*CY_NUM_ABS_SET)+0]; - if (signal != CY_IGNORE_VALUE) { - t = touch.abs[CY_TCH_T] - - ts->platform_data->frmwrk->abs - [(CY_ABS_ID_OST * CY_NUM_ABS_SET) + - CY_MIN_OST]; - input_report_abs(ts->input, signal, t); - } - - /* all devices: position and pressure fields */ - for (j = 0; j < CY_ABS_W_OST ; j++) { - signal = ts->platform_data->frmwrk->abs - [((CY_ABS_X_OST + j) * - CY_NUM_ABS_SET) + 0]; - if (signal != CY_IGNORE_VALUE) { - input_report_abs(ts->input, signal, - touch.abs[CY_TCH_X + j]); - } - } - -#ifdef CY_USE_TMA884 - /* TMA884 size field */ - signal = ts->platform_data->frmwrk->abs - [(CY_ABS_W_OST * CY_NUM_ABS_SET) + 0]; - if (signal != CY_IGNORE_VALUE) - input_report_abs(ts->input, - signal, touch.abs[CY_TCH_W]); -#endif /* --CY_USE_TMA884 */ - -#ifdef CY_USE_TMA400_SP2 -#ifdef CY_USE_TMA400 - /* - * TMA400 size and orientation fields: - * if pressure is non-zero and major touch - * signal is zero, then set major and minor touch - * signal to minimum non-zero value - */ - if ((touch.abs[CY_TCH_P] > 0) && - (touch.abs[CY_TCH_MAJ] == 0)) { - touch.abs[CY_TCH_MAJ] = 1; - touch.abs[CY_TCH_MIN] = 1; - } - - for (j = 0; j < CY_NUM_NEW_TCH_FIELDS; j++) { - signal = ts->platform_data->frmwrk->abs - [((CY_ABS_MAJ_OST + j) * - CY_NUM_ABS_SET) + 0]; - if (signal != CY_IGNORE_VALUE) { - input_report_abs(ts->input, signal, - touch.abs[CY_TCH_MAJ + j]); - } - } -#endif /* --CY_USE_TMA400 */ -#endif /* --CY_USE_TMA400_SP2 */ - - input_mt_sync(ts->input); - } -#ifdef CY_USE_TMA400_SP2 - dev_dbg(ts->dev, - "%s: t=%d x=(%d) y=(%d) z=(%d) M=(%d) m=(%d) o=(%d)\n", - __func__, t, - touch.abs[CY_TCH_X], - touch.abs[CY_TCH_Y], - touch.abs[CY_TCH_P], - touch.abs[CY_TCH_MAJ], - touch.abs[CY_TCH_MIN], - touch.abs[CY_TCH_OR]); -#else - dev_dbg(ts->dev, - "%s: t=%d x=(%d) y=(%d) z=(%d)\n", __func__, - t, - touch.abs[CY_TCH_X], - touch.abs[CY_TCH_Y], - touch.abs[CY_TCH_P]); -#endif /* --CY_USE_TMA400_SP2 */ - } - input_sync(ts->input); - ts->num_prv_tch = num_cur_tch; - - return; -} - -/* read xy_data for all current touches */ -static int _cyttsp4_xy_worker(struct cyttsp4 *ts) -{ - struct cyttsp4_touch touch; - u8 num_cur_tch = 0; - u8 hst_mode = 0; - u8 rep_len = 0; - u8 rep_stat = 0; - u8 tt_stat = 0; - int i = 0; - int num_cur_btn = 0; - int cur_reg = 0; - u8 cur_btn_mask = 0; - int cur_btn = 0; - - enum cyttsp4_btn_state btn_state = CY_BTN_RELEASED; - int retval = 0; - - /* - * Get event data from CYTTSP device. - * The event data includes all data - * for all active touches. - */ - /* - * Use 2 reads: first to get mode bytes, - * second to get status (touch count) and touch 1 data. - * An optional 3rd read to get touch 2 - touch n data. - */ - memset(&touch, 0, sizeof(struct cyttsp4_touch)); - memset(ts->xy_mode, 0, ts->si_ofs.mode_size); - memset(ts->xy_data_touch1, 0, 1 + ts->si_ofs.tch_rec_siz); - - retval = _cyttsp4_load_status_regs(ts); - if (retval < 0) { - /* - * bus failure implies Watchdog -> bootloader running - * on TMA884 parts - */ - dev_err(ts->dev, - "%s: 1st read fail on mode regs r=%d\n", - __func__, retval); - retval = -EIO; - goto _cyttsp4_xy_worker_exit; - } - retval = _cyttsp4_read_block_data(ts, ts->si_ofs.tt_stat_ofs, - 1+ts->si_ofs.tch_rec_siz, ts->xy_data_touch1, - ts->platform_data->addr[CY_TCH_ADDR_OFS], true); - if (retval < 0) { - /* bus failure may imply bootloader running */ - dev_err(ts->dev, - "%s: read fail on mode regs r=%d\n", - __func__, retval); - retval = -EIO; - goto _cyttsp4_xy_worker_exit; - } - - hst_mode = ts->xy_mode[CY_REG_BASE]; - rep_len = ts->xy_mode[ts->si_ofs.rep_ofs]; - rep_stat = ts->xy_mode[ts->si_ofs.rep_ofs + 1]; - tt_stat = ts->xy_data_touch1[0]; - dev_dbg(ts->dev, - "%s: hst_mode=%02X rep_len=%d rep_stat=%02X tt_stat=%02X\n", - __func__, hst_mode, rep_len, rep_stat, tt_stat); - - if (rep_len == 0) { - dev_err(ts->dev, - "%s: report length error rep_len=%d\n", - __func__, rep_len); - goto _cyttsp4_xy_worker_exit; - } - - if (GET_NUM_TOUCHES(tt_stat) > 0) { - memcpy(ts->xy_data, ts->xy_data_touch1 + 1, - ts->si_ofs.tch_rec_siz); - } - if (GET_NUM_TOUCHES(tt_stat) > 1) { - retval = _cyttsp4_read_block_data(ts, ts->si_ofs.tt_stat_ofs + - 1 + ts->si_ofs.tch_rec_siz, - (GET_NUM_TOUCHES(tt_stat) - 1) * ts->si_ofs.tch_rec_siz, - ts->xy_data + ts->si_ofs.tch_rec_siz, - ts->platform_data->addr[CY_TCH_ADDR_OFS], true); - if (retval < 0) { - dev_err(ts->dev, - "%s: read fail on touch regs r=%d\n", - __func__, retval); - goto _cyttsp4_xy_worker_exit; - } - } - - - /* provide flow control handshake */ - retval = _cyttsp4_handshake(ts, hst_mode); - if (retval < 0) { - dev_err(ts->dev, - "%s: handshake fail on operational reg\n", - __func__); - /* continue; rely on handshake tmo */ - retval = 0; - } - - /* determine number of currently active touches */ - num_cur_tch = GET_NUM_TOUCHES(tt_stat); - - /* print xy data */ - _cyttsp4_pr_buf(ts, ts->xy_data, num_cur_tch * - ts->si_ofs.tch_rec_siz, "xy_data"); - - /* check for any error conditions */ - if (ts->driver_state == CY_IDLE_STATE) { - dev_err(ts->dev, - "%s: IDLE STATE detected\n", __func__); - retval = 0; - goto _cyttsp4_xy_worker_exit; - } else if (IS_BAD_PKT(rep_stat)) { - dev_err(ts->dev, - "%s: Invalid buffer detected\n", __func__); - retval = 0; - goto _cyttsp4_xy_worker_exit; - } else if (IS_BOOTLOADERMODE(rep_stat)) { - dev_info(ts->dev, - "%s: BL mode found in ACTIVE state\n", - __func__); - retval = -EIO; - goto _cyttsp4_xy_worker_exit; - } else if (GET_HSTMODE(hst_mode) == GET_HSTMODE(CY_SYSINFO_MODE)) { - /* if in sysinfo mode switch to op mode */ - dev_err(ts->dev, - "%s: Sysinfo mode=0x%02X detected in ACTIVE state\n", - __func__, hst_mode); - retval = _cyttsp4_set_mode(ts, CY_OPERATE_MODE); - if (retval < 0) { - _cyttsp4_change_state(ts, CY_IDLE_STATE); - dev_err(ts->dev, - "%s: Fail set operational mode (r=%d)\n", - __func__, retval); - } else { - _cyttsp4_change_state(ts, CY_ACTIVE_STATE); - dev_vdbg(ts->dev, - "%s: enable handshake\n", __func__); -#ifdef CY_USE_TMA884 - retval = _cyttsp4_handshake_enable(ts); - if (retval < 0) { - dev_err(ts->dev, - "%s: fail enable handshake r=%d", - __func__, retval); - } -#endif /* --CY_USE_TMA884 */ - } - goto _cyttsp4_xy_worker_exit; - } else if (IS_LARGE_AREA(tt_stat)) { - /* terminate all active tracks */ - num_cur_tch = 0; - dev_dbg(ts->dev, "%s: Large area detected\n", __func__); - } else if (num_cur_tch > ts->si_ofs.max_tchs) { - if (num_cur_tch == 0x1F) { - /* terminate all active tracks */ - dev_err(ts->dev, - "%s: Num touch err detected (n=%d)\n", - __func__, num_cur_tch); - num_cur_tch = 0; - } else { - dev_err(ts->dev, - "%s: too many tch; set to max tch (n=%d c=%d)\n", - __func__, num_cur_tch, CY_NUM_TCH_ID); - num_cur_tch = CY_NUM_TCH_ID; - } - } - - dev_dbg(ts->dev, - "%s: num_cur_tch=%d\n", __func__, num_cur_tch); - - /* extract xy_data for all currently reported touches */ - if (num_cur_tch) { - if (ts->num_prv_tch == 0) { - /* ICS touch down button press signal */ - input_report_key(ts->input, BTN_TOUCH, CY_BTN_PRESSED); - } - _cyttsp4_get_mt_touches(ts, num_cur_tch); - } else { - if (ts->num_prv_tch != 0) { - /* ICS Lift off button release signal and empty mt */ - input_report_key(ts->input, BTN_TOUCH, CY_BTN_RELEASED); - input_mt_sync(ts->input); - input_sync(ts->input); -#if TOUCH_BOOST - mod_timer(&ts->dvfs_timer, - jiffies + msecs_to_jiffies(500)); -#endif - } - ts->num_prv_tch = 0; - } - - if (ts->si_ofs.num_btns > 0) { - for (btn_state = CY_BTN_RELEASED; btn_state < CY_BTN_NUM_STATE; - btn_state++) { - for (cur_reg = 0, cur_btn = 0, - num_cur_btn = ts->si_ofs.num_btns; - cur_reg < ts->si_ofs.num_btn_regs; - cur_reg++, - cur_btn += CY_NUM_BTN_PER_REG, - num_cur_btn -= CY_NUM_BTN_PER_REG) { - if (num_cur_btn > 0) { - cur_btn_mask = ts->xy_mode - [ts->si_ofs.rep_ofs + - 2 + cur_reg]; - if (num_cur_btn / CY_NUM_BTN_PER_REG) - i = CY_NUM_BTN_PER_REG; - else - i = num_cur_btn; - switch (btn_state) { - case CY_BTN_RELEASED: - _cyttsp4_btn_key_release(ts, - cur_btn, - cur_btn_mask, i); - break; - case CY_BTN_PRESSED: - _cyttsp4_btn_key_press(ts, - cur_btn, - cur_btn_mask, i); - break; - default: - break; - } - } - } - } - } - - dev_dbg(ts->dev, - "%s:\n", __func__); - - retval = 0; -_cyttsp4_xy_worker_exit: -#ifdef CY_USE_LEVEL_IRQ - udelay(500); -#endif - return retval; -} - -#ifdef CY_USE_WATCHDOG -#define CY_TIMEOUT msecs_to_jiffies(1000) -static void _cyttsp4_start_wd_timer(struct cyttsp4 *ts) -{ - mod_timer(&ts->timer, jiffies + CY_TIMEOUT); - - return; -} - -static void _cyttsp4_stop_wd_timer(struct cyttsp4 *ts) -{ - del_timer(&ts->timer); - cancel_work_sync(&ts->work); - - return; -} - -static void cyttsp4_timer_watchdog(struct work_struct *work) -{ - struct cyttsp4 *ts = container_of(work, struct cyttsp4, work); - u8 rep_stat = 0; - int retval = 0; - - if (ts == NULL) { - dev_err(ts->dev, - "%s: NULL context pointer\n", __func__); - return; - } - - mutex_lock(&ts->data_lock); - if (ts->driver_state == CY_ACTIVE_STATE) { - retval = _cyttsp4_load_status_regs(ts); - if (retval < 0) { - dev_err(ts->dev, - "%s: failed to access device" - " in watchdog timer r=%d\n", __func__, retval); - _cyttsp4_queue_startup(ts, false); - goto cyttsp4_timer_watchdog_exit_error; - } - rep_stat = ts->xy_mode[ts->si_ofs.rep_ofs + 1]; - if (IS_BOOTLOADERMODE(rep_stat)) { - dev_err(ts->dev, - "%s: device found in bootloader mode" - " when operational mode rep_stat=0x%02X\n", - __func__, rep_stat); - _cyttsp4_queue_startup(ts, false); - goto cyttsp4_timer_watchdog_exit_error; - } - } - - _cyttsp4_start_wd_timer(ts); - cyttsp4_timer_watchdog_exit_error: - mutex_unlock(&ts->data_lock); - return; -} - -static void cyttsp4_timer(unsigned long handle) -{ - struct cyttsp4 *ts = (struct cyttsp4 *)handle; - - if (!work_pending(&ts->work)) - schedule_work(&ts->work); - - return; -} -#endif - -static int _cyttsp4_soft_reset(struct cyttsp4 *ts) -{ - u8 cmd = CY_SOFT_RESET_MODE; - - return _cyttsp4_write_block_data(ts, CY_REG_BASE, - sizeof(cmd), &cmd, - ts->platform_data->addr[CY_TCH_ADDR_OFS], true); -} - -static int _cyttsp4_reset(struct cyttsp4 *ts) -{ - enum cyttsp4_driver_state tmp_state = ts->driver_state; - int retval = 0; - - if (ts->platform_data->hw_reset) { - retval = ts->platform_data->hw_reset(); - if (retval == -ENOSYS) { - retval = _cyttsp4_soft_reset(ts); - ts->soft_reset_asserted = true; - } else - ts->soft_reset_asserted = false; - } else { - retval = _cyttsp4_soft_reset(ts); - ts->soft_reset_asserted = true; - } - - if (retval < 0) { - _cyttsp4_pr_state(ts); - return retval; - } else { - ts->current_mode = CY_MODE_BOOTLOADER; - ts->driver_state = CY_BL_STATE; - if (tmp_state != CY_BL_STATE) - _cyttsp4_pr_state(ts); - return retval; - } -} - -static void cyttsp4_ts_work_func(struct work_struct *work) -{ - struct cyttsp4 *ts = - container_of(work, struct cyttsp4, cyttsp4_resume_startup_work); - int retval = 0; - int i; - - dev_err(ts->dev, "%s: %d: wd timer stop\n", __func__, __LINE__); -#ifdef CY_USE_WATCHDOG - _cyttsp4_stop_wd_timer(ts); -#endif - mutex_lock(&ts->data_lock); - - ts->num_prv_tch = 0; - for (i = 0; i < ts->si_ofs.max_tchs; i++) { - input_mt_sync(ts->input); - } - input_report_key(ts->input, KEY_MENU, 0); - input_report_key(ts->input, KEY_BACK, 0); - input_report_key(ts->input, BTN_TOUCH, CY_BTN_RELEASED); - input_sync(ts->input); - retval = _cyttsp4_startup(ts); - if (retval < 0) { - dev_err(ts->dev, - "%s: Startup failed with error code %d\n", - __func__, retval); - _cyttsp4_change_state(ts, CY_IDLE_STATE); -#ifdef CY_USE_WATCHDOG - } else { - _cyttsp4_start_wd_timer(ts); -#endif - } - - mutex_unlock(&ts->data_lock); - - return; -} - -static int _cyttsp4_enter_sleep(struct cyttsp4 *ts) -{ - int retval = 0; -#if defined(CONFIG_PM_SLEEP) || \ - defined(CONFIG_PM) || \ - defined(CONFIG_HAS_EARLYSUSPEND) - uint8_t sleep = CY_DEEP_SLEEP_MODE; - - dev_vdbg(ts->dev, - "%s: Put the part back to sleep\n", __func__); - - retval = _cyttsp4_write_block_data(ts, CY_REG_BASE, - sizeof(sleep), &sleep, - ts->platform_data->addr[CY_TCH_ADDR_OFS], true); - if (retval < 0) { - dev_err(ts->dev, - "%s: Failed to write sleep bit r=%d\n", - __func__, retval); - } else - _cyttsp4_change_state(ts, CY_SLEEP_STATE); -#endif - return retval; -} - -static int _cyttsp4_wakeup(struct cyttsp4 *ts) -{ - int retval = 0; -#if defined(CONFIG_PM_SLEEP) || \ - defined(CONFIG_PM) || \ - defined(CONFIG_HAS_EARLYSUSPEND) - unsigned long timeout = 0; - unsigned long uretval = 0; - u8 hst_mode = 0; -#ifdef CY_USE_TMA400 - u8 rep_stat = 0; -#endif /* --CY_USE_TMA400 */ - int wake = CY_WAKE_DFLT; - - _cyttsp4_change_state(ts, CY_CMD_STATE); - INIT_COMPLETION(ts->int_running); - if (ts->platform_data->hw_recov == NULL) { - dev_vdbg(ts->dev, - "%s: no hw_recov function\n", __func__); - retval = -ENOSYS; - } else { - /* wake using strobe on host alert pin */ - retval = ts->platform_data->hw_recov(wake); - if (retval < 0) { - if (retval == -ENOSYS) { - dev_vdbg(ts->dev, - "%s: no hw_recov wake code=%d" - " function\n", __func__, wake); - } else { - dev_err(ts->dev, - "%s: fail hw_recov(wake=%d)" - " function r=%d\n", - __func__, wake, retval); - retval = -ENOSYS; - } - } - } - - if (retval == -ENOSYS) { - /* - * Wake the chip with bus traffic - * The first few reads should always fail because - * the part is not ready to respond, - * but the retries should succeed. - */ - /* - * Even though this is hardware-specific, it is done - * here because the board config file doesn't have - * access to the bus read routine - */ - retval = _cyttsp4_read_block_data(ts, CY_REG_BASE, - sizeof(hst_mode), &hst_mode, - ts->platform_data->addr[CY_TCH_ADDR_OFS], - true); - if (retval < 0) { - /* device may not be ready even with the - * bus read retries so just go ahead and - * wait for the cmd rdy interrupt or timeout - */ - retval = 0; - } else { - /* IC is awake but still need to check for - * proper mode - */ - } - } else - retval = 0; - - /* Wait for cmd rdy interrupt to signal device wake */ - timeout = msecs_to_jiffies(CY_HALF_SEC_TMO_MS); - mutex_unlock(&ts->data_lock); - uretval = wait_for_completion_interruptible_timeout( - &ts->int_running, timeout); - mutex_lock(&ts->data_lock); - - /* read registers even if wait ended with timeout */ - retval = _cyttsp4_read_block_data(ts, - CY_REG_BASE, sizeof(hst_mode), &hst_mode, - ts->platform_data->addr[CY_TCH_ADDR_OFS], true); - - /* TMA884 indicates bootloader mode by changing addr */ - if (retval < 0) { - dev_err(ts->dev, - "%s: failed to resume or in bootloader (r=%d)\n", - __func__, retval); - } else { -#ifdef CY_USE_TMA400 - /* read rep stat register for bootloader status */ - retval = _cyttsp4_load_status_regs(ts); - if (retval < 0) { - dev_err(ts->dev, - "%s: failed to access device on resume r=%d\n", - __func__, retval); - goto _cyttsp4_wakeup_exit; - } - rep_stat = ts->xy_mode[ts->si_ofs.rep_ofs + 1]; - if (IS_BOOTLOADERMODE(rep_stat)) { - dev_err(ts->dev, - "%s: device in bootloader mode on wakeup" - " rep_stat=0x%02X\n", - __func__, rep_stat); - retval = -EIO; - goto _cyttsp4_wakeup_exit; - } -#endif /* --CY_USE_TMA400 */ - retval = _cyttsp4_handshake(ts, hst_mode); - if (retval < 0) { - dev_err(ts->dev, - "%s: fail resume INT handshake (r=%d)\n", - __func__, retval); - /* continue; rely on handshake tmo */ - retval = 0; - } - _cyttsp4_change_state(ts, CY_ACTIVE_STATE); - } -#ifdef CY_USE_TMA400 -_cyttsp4_wakeup_exit: -#endif /* --CY_USE_TMA400 */ -#endif - return retval; -} - -#if defined(CONFIG_PM) || \ - defined(CONFIG_PM_SLEEP) || \ - defined(CONFIG_HAS_EARLYSUSPEND) - -#if defined(CONFIG_HAS_EARLYSUSPEND) -int cyttsp4_suspend(void *handle) -{ - struct cyttsp4 *ts = handle; -#elif defined(CONFIG_PM_SLEEP) -static int cyttsp4_suspend(struct device *dev) -{ - struct cyttsp4 *ts = dev_get_drvdata(dev); -#else -int cyttsp4_suspend(void *handle) -{ - struct cyttsp4 *ts = handle; -#endif - int retval = 0; - bool on = false; - - if (ts->test.cur_mode != CY_TEST_MODE_NORMAL_OP) { - retval = -EBUSY; - dev_err(ts->dev, - "%s: Suspend Blocked while in test mode=%d\n", - __func__, ts->test.cur_mode); - } else { - switch (ts->driver_state) { - case CY_ACTIVE_STATE: -#if defined(CY_USE_FORCE_LOAD) || defined(CONFIG_TOUCHSCREEN_DEBUG) - if (ts->waiting_for_fw) { - retval = -EBUSY; - dev_err(ts->dev, - "%s: Suspend Blocked while waiting for" - " fw load in %s state\n", __func__, - cyttsp4_driver_state_string - [ts->driver_state]); - break; - } -#endif - dev_vdbg(ts->dev, - "%s: Suspending...\n", __func__); -#ifdef CY_USE_WATCHDOG - _cyttsp4_stop_wd_timer(ts); -#endif - if (ts->irq_enabled) - disable_irq(ts->irq); - - ts->platform_data->hw_power(on); - _cyttsp4_change_state(ts, CY_SLEEP_STATE); - - break; - case CY_SLEEP_STATE: - dev_err(ts->dev, - "%s: already in Sleep state\n", __func__); - break; - /* - * These states could be changing the device state - * Some of these states don't directly change device state - * but the next state could happen at any time and that - * state DOES modify the device state - * they must complete before allowing suspend. - */ - case CY_BL_STATE: - case CY_CMD_STATE: - case CY_SYSINFO_STATE: - case CY_READY_STATE: - case CY_TRANSFER_STATE: - retval = -EBUSY; - dev_err(ts->dev, - "%s: Suspend Blocked while in %s state\n", - __func__, cyttsp4_driver_state_string - [ts->driver_state]); - break; - case CY_IDLE_STATE: - case CY_INVALID_STATE: - default: - dev_err(ts->dev, - "%s: Cannot enter suspend from %s state\n", - __func__, cyttsp4_driver_state_string - [ts->driver_state]); - break; - } - } -#if TOUCH_BOOST - if (true == boost) { - omap_cpufreq_min_limit_free(DVFS_LOCK_ID_TSP); - boost = false; - del_timer_sync(&ts->dvfs_timer); - } -#endif - - return retval; -} -EXPORT_SYMBOL_GPL(cyttsp4_suspend); - -#if defined(CONFIG_HAS_EARLYSUSPEND) -int cyttsp4_resume(void *handle) -{ - struct cyttsp4 *ts = handle; -#elif defined(CONFIG_PM_SLEEP) -static int cyttsp4_resume(struct device *dev) -{ - struct cyttsp4 *ts = dev_get_drvdata(dev); -#else -int cyttsp4_resume(void *handle) -{ - struct cyttsp4 *ts = handle; -#endif - int retval = 0; - - dev_vdbg(ts->dev, "%s: Resuming...\n", __func__); - - mutex_lock(&ts->data_lock); - if (ts->irq_enabled) - enable_irq(ts->irq); - retval = _cyttsp4_startup(ts); - - mutex_unlock(&ts->data_lock); - - dev_vdbg(ts->dev, - "%s: exit Resume r=%d\n", __func__, retval); - return retval; -} -EXPORT_SYMBOL_GPL(cyttsp4_resume); -#endif -#if !defined(CONFIG_HAS_EARLYSUSPEND) && defined(CONFIG_PM_SLEEP) -const struct dev_pm_ops cyttsp4_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(cyttsp4_suspend, cyttsp4_resume) -}; -EXPORT_SYMBOL_GPL(cyttsp4_pm_ops); -#endif - - -#if defined(CONFIG_HAS_EARLYSUSPEND) -void cyttsp4_early_suspend(struct early_suspend *h) -{ - struct cyttsp4 *ts = container_of(h, struct cyttsp4, early_suspend); - int retval = 0; - - dev_vdbg(ts->dev, "%s: EARLY SUSPEND ts=%p\n", - __func__, ts); - retval = cyttsp4_suspend(ts); - if (retval < 0) { - dev_err(ts->dev, - "%s: Early suspend failed with error code %d\n", - __func__, retval); - } -} -void cyttsp4_late_resume(struct early_suspend *h) -{ - struct cyttsp4 *ts = container_of(h, struct cyttsp4, early_suspend); - int retval = 0; - - dev_vdbg(ts->dev, "%s: LATE RESUME ts=%p\n", - __func__, ts); - retval = cyttsp4_resume(ts); - if (retval < 0) { - dev_err(ts->dev, - "%s: Late resume failed with error code %d\n", - __func__, retval); - } -} -#endif - -#ifdef CY_AUTO_LOAD_FW -static int _cyttsp4_boot_loader(struct cyttsp4 *ts, bool *upgraded) -{ - int retval = 0; - int i = 0; - u32 fw_vers_platform = 0; - u32 fw_vers_img = 0; - u32 fw_revctrl_platform_h = 0; - u32 fw_revctrl_platform_l = 0; - u32 fw_revctrl_img_h = 0; - u32 fw_revctrl_img_l = 0; - bool new_fw_vers = false; - bool new_fw_revctrl = false; - bool new_vers = false; - - *upgraded = false; - if (ts->driver_state == CY_SLEEP_STATE) { - dev_err(ts->dev, - "%s: cannot load firmware in sleep state\n", - __func__); - retval = 0; - } else if ((ts->platform_data->fw->ver == NULL) || - (ts->platform_data->fw->img == NULL)) { - dev_err(ts->dev, - "%s: empty version list or no image\n", - __func__); - retval = 0; - } else if (ts->platform_data->fw->vsize != CY_BL_VERS_SIZE) { - dev_err(ts->dev, - "%s: bad fw version list size=%d\n", - __func__, ts->platform_data->fw->vsize); - retval = 0; - } else { - /* automatically update firmware if new version detected */ - fw_vers_img = (ts->sysinfo_ptr.cydata->fw_ver_major * 256); - fw_vers_img += ts->sysinfo_ptr.cydata->fw_ver_minor; - fw_vers_platform = ts->platform_data->fw->ver[2] * 256; - fw_vers_platform += ts->platform_data->fw->ver[3]; -#ifdef CY_ANY_DIFF_NEW_VER - if (fw_vers_platform != fw_vers_img) - new_fw_vers = true; - else - new_fw_vers = false; -#else - if (fw_vers_platform > fw_vers_img) - new_fw_vers = true; - else - new_fw_vers = false; -#endif - dev_vdbg(ts->dev, - "%s: fw_vers_platform=%04X fw_vers_img=%04X\n", - __func__, fw_vers_platform, fw_vers_img); - - fw_revctrl_img_h = ts->sysinfo_ptr.cydata->revctrl[0]; - fw_revctrl_img_l = ts->sysinfo_ptr.cydata->revctrl[4]; - fw_revctrl_platform_h = ts->platform_data->fw->ver[4]; - fw_revctrl_platform_l = ts->platform_data->fw->ver[8]; - for (i = 1; i < 4; i++) { - fw_revctrl_img_h = (fw_revctrl_img_h * 256) + - ts->sysinfo_ptr.cydata->revctrl[0+i]; - fw_revctrl_img_l = (fw_revctrl_img_l * 256) + - ts->sysinfo_ptr.cydata->revctrl[4+i]; - fw_revctrl_platform_h = (fw_revctrl_platform_h * 256) + - ts->platform_data->fw->ver[4+i]; - fw_revctrl_platform_l = (fw_revctrl_platform_l * 256) + - ts->platform_data->fw->ver[8+i]; - } -#ifdef CY_ANY_DIFF_NEW_VER - if (fw_revctrl_platform_h != fw_revctrl_img_h) - new_fw_revctrl = true; - else if (fw_revctrl_platform_h == fw_revctrl_img_h) { - if (fw_revctrl_platform_l != fw_revctrl_img_l) - new_fw_revctrl = true; - else - new_fw_revctrl = false; - } else - new_fw_revctrl = false; -#else - if (fw_revctrl_platform_h > fw_revctrl_img_h) - new_fw_revctrl = true; - else if (fw_revctrl_platform_h == fw_revctrl_img_h) { - if (fw_revctrl_platform_l > fw_revctrl_img_l) - new_fw_revctrl = true; - else - new_fw_revctrl = false; - } else - new_fw_revctrl = false; -#endif - if (new_fw_vers || new_fw_revctrl) - new_vers = true; - - dev_vdbg(ts->dev, - "%s: fw_revctrl_platform_h=%08X" - " fw_revctrl_img_h=%08X\n", __func__, - fw_revctrl_platform_h, fw_revctrl_img_h); - dev_vdbg(ts->dev, - "%s: fw_revctrl_platform_l=%08X" - " fw_revctrl_img_l=%08X\n", __func__, - fw_revctrl_platform_l, fw_revctrl_img_l); - dev_vdbg(ts->dev, - "%s: new_fw_vers=%d new_fw_revctrl=%d new_vers=%d\n", - __func__, - (int)new_fw_vers, (int)new_fw_revctrl, (int)new_vers); - - if (new_vers) { - dev_info(ts->dev, - "%s: upgrading firmware...\n", __func__); - retval = _cyttsp4_load_app(ts, - ts->platform_data->fw->img, - ts->platform_data->fw->size); - if (retval < 0) { - dev_err(ts->dev, - "%s: communication fail" - " on load fw r=%d\n", - __func__, retval); - _cyttsp4_change_state(ts, CY_IDLE_STATE); - retval = -EIO; - } else - *upgraded = true; - } else { - dev_vdbg(ts->dev, - "%s: No auto firmware upgrade required\n", - __func__); - } - } - - return retval; -} -#endif /* --CY_AUTO_LOAD_FW */ - -static ssize_t cyttsp4_ic_ver_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct cyttsp4 *ts = dev_get_drvdata(dev); - - return sprintf(buf, "%s: 0x%02X 0x%02X\n%s: 0x%02X\n%s: 0x%02X\n%s: " - "0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X\n", - "TrueTouch Product ID", - ts->sysinfo_ptr.cydata->ttpidh, - ts->sysinfo_ptr.cydata->ttpidl, - "Firmware Major Version", ts->sysinfo_ptr.cydata->fw_ver_major, - "Firmware Minor Version", ts->sysinfo_ptr.cydata->fw_ver_minor, - "Revision Control Number", ts->sysinfo_ptr.cydata->revctrl[0], - ts->sysinfo_ptr.cydata->revctrl[1], - ts->sysinfo_ptr.cydata->revctrl[2], - ts->sysinfo_ptr.cydata->revctrl[3], - ts->sysinfo_ptr.cydata->revctrl[4], - ts->sysinfo_ptr.cydata->revctrl[5], - ts->sysinfo_ptr.cydata->revctrl[6], - ts->sysinfo_ptr.cydata->revctrl[7]); -} -static DEVICE_ATTR(ic_ver, S_IRUGO, cyttsp4_ic_ver_show, NULL); - -/* Driver version */ -static ssize_t cyttsp4_drv_ver_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct cyttsp4 *ts = dev_get_drvdata(dev); - - return snprintf(buf, CY_MAX_PRBUF_SIZE, - "Driver: %s\nVersion: %s\nDate: %s\n", - ts->input->name, CY_DRIVER_VERSION, CY_DRIVER_DATE); -} -static DEVICE_ATTR(drv_ver, S_IRUGO, cyttsp4_drv_ver_show, NULL); - - -/* Driver status */ -static ssize_t cyttsp4_drv_stat_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct cyttsp4 *ts = dev_get_drvdata(dev); - - return snprintf(buf, CY_MAX_PRBUF_SIZE, - "Driver state is %s\n", - cyttsp4_driver_state_string[ts->driver_state]); -} -static DEVICE_ATTR(drv_stat, S_IRUGO, cyttsp4_drv_stat_show, NULL); - - - - -#ifdef CY_USE_REG_ACCESS -static ssize_t cyttsp_drv_rw_regid_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct cyttsp4 *ts = dev_get_drvdata(dev); - - return snprintf(buf, CY_MAX_PRBUF_SIZE, - "Current Read/Write Regid=%02X(%d)\n", - ts->rw_regid, ts->rw_regid); -} -static ssize_t cyttsp_drv_rw_regid_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t size) -{ - struct cyttsp4 *ts = dev_get_drvdata(dev); - int retval = 0; - unsigned long value; - - mutex_lock(&ts->data_lock); - retval = strict_strtoul(buf, 10, &value); - if (retval < 0) { - retval = strict_strtoul(buf, 16, &value); - if (retval < 0) { - dev_err(ts->dev, - "%s: Failed to convert value\n", - __func__); - goto cyttsp_drv_rw_regid_store_exit; - } - } - - if (value > CY_RW_REGID_MAX) { - ts->rw_regid = CY_RW_REGID_MAX; - dev_err(ts->dev, - "%s: Invalid Read/Write Regid; set to max=%d\n", - __func__, ts->rw_regid); - } else - ts->rw_regid = value; - - retval = size; - -cyttsp_drv_rw_regid_store_exit: - mutex_unlock(&ts->data_lock); - return retval; -} -static DEVICE_ATTR(drv_rw_regid, S_IWUSR | S_IRUGO, - cyttsp_drv_rw_regid_show, cyttsp_drv_rw_regid_store); - - -static ssize_t cyttsp_drv_rw_reg_data_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct cyttsp4 *ts = dev_get_drvdata(dev); - int retval; - u8 reg_data; - - retval = _cyttsp4_read_block_data(ts, ts->rw_regid, - sizeof(reg_data), ®_data, - ts->platform_data->addr[CY_TCH_ADDR_OFS], true); - - if (retval < 0) - return snprintf(buf, CY_MAX_PRBUF_SIZE, - "Read/Write Regid(%02X(%d) Failed\n", - ts->rw_regid, ts->rw_regid); - else - return snprintf(buf, CY_MAX_PRBUF_SIZE, - "Read/Write Regid=%02X(%d) Data=%02X(%d)\n", - ts->rw_regid, ts->rw_regid, reg_data, reg_data); -} -static ssize_t cyttsp_drv_rw_reg_data_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t size) -{ - struct cyttsp4 *ts = dev_get_drvdata(dev); - int retval = 0; - unsigned long value; - u8 reg_data = 0; - - retval = strict_strtoul(buf, 10, &value); - if (retval < 0) { - retval = strict_strtoul(buf, 16, &value); - if (retval < 0) { - dev_err(ts->dev, - "%s: Failed to convert value\n", - __func__); - goto cyttsp_drv_rw_reg_data_store_exit; - } - } - - if (value > CY_RW_REG_DATA_MAX) { - dev_err(ts->dev, - "%s: Invalid Register Data Range; no write\n", - __func__); - } else { - reg_data = (u8)value; - retval = _cyttsp4_write_block_data(ts, ts->rw_regid, - sizeof(reg_data), ®_data, - ts->platform_data->addr[CY_TCH_ADDR_OFS], true); - if (retval < 0) { - dev_err(ts->dev, - "%s: Failed write to Regid=%02X(%d)\n", - __func__, ts->rw_regid, ts->rw_regid); - } - } - - retval = size; - -cyttsp_drv_rw_reg_data_store_exit: - return retval; -} -static DEVICE_ATTR(drv_rw_reg_data, S_IWUSR | S_IRUGO, - cyttsp_drv_rw_reg_data_show, cyttsp_drv_rw_reg_data_store); -#endif - -#ifdef FACTORY_TESTING - -static void set_node_data(struct cyttsp4 *ts_data, const u8 data_type, - int *max_value, int *min_value) -{ - /* TODO : fix later - * Add factory func. for cypress GEN4 - */ -} - -static void set_default_result(struct factory_data *data) -{ - char delim = ':'; - - memset(data->cmd_result, 0x00, ARRAY_SIZE(data->cmd_result)); - memset(data->cmd_buff, 0x00, ARRAY_SIZE(data->cmd_buff)); - memcpy(data->cmd_result, data->cmd, strlen(data->cmd)); - strncat(data->cmd_result, &delim, 1); -} - -static void set_cmd_result(struct factory_data *data, char *buff, int len) -{ - strncat(data->cmd_result, buff, len); -} - -static void not_support_cmd(void *device_data) -{ - struct cyttsp4 *ts_data = (struct cyttsp4 *)device_data; - struct factory_data *data = ts_data->factory_data; - - set_default_result(data); - sprintf(data->cmd_buff, "%s", "NA"); - set_cmd_result(data, data->cmd_buff, strlen(data->cmd_buff)); - data->cmd_state = NOT_APPLICABLE; - pr_info("tsp factory : %s: \"%s(%d)\"\n", __func__, - data->cmd_buff, strlen(data->cmd_buff)); - return; -} - -static void fw_update(void *device_data) -{ - /* TODO : fix later - * Add factory func. for cypress GEN4 - */ -} - -static void get_fw_ver_bin(void *device_data) -{ - struct cyttsp4 *ts_data = (struct cyttsp4 *)device_data; - struct factory_data *data = ts_data->factory_data; - - data->cmd_state = RUNNING; - - set_default_result(data); - sprintf(data->cmd_buff, "%.4x", FW_VERSION); - set_cmd_result(data, data->cmd_buff, strlen(data->cmd_buff)); - - data->cmd_state = OK; - return; -} - -static void get_fw_ver_ic(void *device_data) -{ - struct cyttsp4 *ts_data = (struct cyttsp4 *)device_data; - struct factory_data *data = ts_data->factory_data; - - u8 buf[2]; - - data->cmd_state = RUNNING; - buf[0] = *((u8 *)ts_data->sysinfo_ptr.ddata+21); - buf[1] = *((u8 *)ts_data->sysinfo_ptr.ddata+20); - - set_default_result(data); - sprintf(data->cmd_buff, "%.2x%.2x", buf[1], buf[0]); - set_cmd_result(data, data->cmd_buff, strlen(data->cmd_buff)); - - data->cmd_state = OK; - return; -} - -static void get_config_ver(void *device_data) -{ - struct cyttsp4 *ts_data = (struct cyttsp4 *)device_data; - struct factory_data *data = ts_data->factory_data; - - u8 buf = 0; - - data->cmd_state = RUNNING; - buf = *((u8 *)ts_data->sysinfo_ptr.ddata+22); - set_default_result(data); - sprintf(data->cmd_buff, "%.2x", buf); - set_cmd_result(data, data->cmd_buff, strlen(data->cmd_buff)); - - data->cmd_state = OK; - return; -} - -static void get_threshold(void *device_data) -{ - struct cyttsp4 *ts_data = (struct cyttsp4 *)device_data; - struct factory_data *data = ts_data->factory_data; - enum cyttsp4_ic_ebid ebid = CY_TCH_PARM_EBID; - u8 *pdata = NULL; - u8 buf = 0; - int retval = 0; - - data->cmd_state = RUNNING; - - pdata = kzalloc(ts_data->ebid_row_size, GFP_KERNEL); - memset(pdata, 0, ts_data->ebid_row_size); - mutex_lock(&ts_data->data_lock); - retval = _cyttsp4_set_mode(ts_data, CY_CONFIG_MODE); - if (retval < 0) { - dev_err(ts_data->dev, - "%s: Fail set config mode 1 r=%d\n", __func__, retval); - goto cyttsp_threshold_get_fail; - } - - retval = _cyttsp4_get_ebid_data_tma400(ts_data, ebid, 3, pdata); - if (retval < 0) { - dev_err(ts_data->dev, - "%s: Fail get threshold value r=%d\n", __func__, retval); - goto cyttsp_threshold_get_fail; - } - - retval = _cyttsp4_set_mode(ts_data, CY_OPERATE_MODE); - if (retval < 0) { - dev_err(ts_data->dev, - "%s: Fail set operational mode 1 (r=%d)\n", - __func__, retval); - goto cyttsp_threshold_get_fail; - } - - mutex_unlock(&ts_data->data_lock); - - buf = *(pdata+23); - -cyttsp_threshold_get_fail: - set_default_result(data); - - sprintf(data->cmd_buff, "%.2x", buf); - set_cmd_result(data, data->cmd_buff, strlen(data->cmd_buff)); - - data->cmd_state = OK; - if (pdata != NULL) - kfree(pdata); - - return; -} - -static void module_off_master(void *device_data) -{ - -} - -static void module_on_master(void *device_data) -{ - -} - -static void get_chip_vendor(void *device_data) -{ - struct cyttsp4 *ts_data = (struct cyttsp4 *)device_data; - struct factory_data *data = ts_data->factory_data; - - data->cmd_state = RUNNING; - - set_default_result(data); - sprintf(data->cmd_buff, "%s", TSP_VENDOR); - set_cmd_result(data, data->cmd_buff, strlen(data->cmd_buff)); - - data->cmd_state = OK; - return; -} - -static void get_chip_name(void *device_data) -{ - struct cyttsp4 *ts_data = (struct cyttsp4 *)device_data; - struct factory_data *data = ts_data->factory_data; - - data->cmd_state = RUNNING; - - set_default_result(data); - sprintf(data->cmd_buff, "%s", TSP_IC); - set_cmd_result(data, data->cmd_buff, strlen(data->cmd_buff)); - - data->cmd_state = OK; - return; -} - -static void get_x_num(void *device_data) -{ - struct cyttsp4 *ts_data = (struct cyttsp4 *)device_data; - struct factory_data *data = ts_data->factory_data; - - data->cmd_state = RUNNING; - - set_default_result(data); - - set_cmd_result(data, data->cmd_buff, strlen(data->cmd_buff)); - - data->cmd_state = OK; - return; -} - -static void get_y_num(void *device_data) -{ - struct cyttsp4 *ts_data = (struct cyttsp4 *)device_data; - struct factory_data *data = ts_data->factory_data; - - data->cmd_state = RUNNING; - - set_default_result(data); - - set_cmd_result(data, data->cmd_buff, strlen(data->cmd_buff)); - - data->cmd_state = OK; - return; -} - -static void get_reference(void *device_data) -{ - /* TODO : fix later - * Add factory func. for cypress GEN4 - */ -} - -static void get_cm_abs(void *device_data) -{ - /* TODO : fix later - * Add factory func. for cypress GEN4 - */ -} - -static void get_cm_delta(void *device_data) -{ - /* TODO : fix later - * Add factory func. for cypress GEN4 - */ -} - -static void get_intensity(void *device_data) -{ - /* TODO : fix later - * Add factory func. for cypress GEN4 - */ -} - -static void run_reference_read(void *device_data) -{ - /* TODO : fix later - * Add factory func. for cypress GEN4 - */ -} - -static void run_cm_abs_read(void *device_data) -{ - /* TODO : fix later - * Add factory func. for cypress GEN4 - */ -} - -static void run_cm_delta_read(void *device_data) -{ - /* TODO : fix later - * Add factory func. for cypress GEN4 - */ -} - -static void run_intensity_read(void *device_data) -{ - /* TODO : fix later - * Add factory func. for cypress GEN4 - */ -} - -struct tsp_cmd tsp_cmds[] = { - {TSP_CMD("fw_update", fw_update),}, - {TSP_CMD("get_fw_ver_bin", get_fw_ver_bin),}, - {TSP_CMD("get_fw_ver_ic", get_fw_ver_ic),}, - {TSP_CMD("get_config_ver", get_config_ver),}, - {TSP_CMD("get_threshold", get_threshold),}, - {TSP_CMD("module_off_master", module_off_master),}, - {TSP_CMD("module_on_master", module_on_master),}, - {TSP_CMD("module_off_slave", not_support_cmd),}, - {TSP_CMD("module_on_slave", not_support_cmd),}, - {TSP_CMD("get_chip_vendor", get_chip_vendor),}, - {TSP_CMD("get_chip_name", get_chip_name),}, - {TSP_CMD("get_x_num", get_x_num),}, - {TSP_CMD("get_y_num", get_y_num),}, - {TSP_CMD("get_reference", get_reference),}, - {TSP_CMD("get_cm_abs", get_cm_abs),}, - {TSP_CMD("get_cm_delta", get_cm_delta),}, - {TSP_CMD("get_intensity", get_intensity),}, - {TSP_CMD("run_reference_read", run_reference_read),}, - {TSP_CMD("run_cm_abs_read", run_cm_abs_read),}, - {TSP_CMD("run_cm_delta_read", run_cm_delta_read),}, - {TSP_CMD("run_intensity_read", run_intensity_read),}, - {TSP_CMD("not_support_cmd", not_support_cmd),}, -}; - -static ssize_t cmd_store(struct device *dev, struct device_attribute *devattr, - const char *buf, size_t count) -{ - struct cyttsp4 *ts_data = dev_get_drvdata(dev); - struct factory_data *data = ts_data->factory_data; - char *cur, *start, *end; - char buff[TSP_CMD_STR_LEN] = {0, }; - int len, i; - struct tsp_cmd *tsp_cmd_ptr = NULL; - char delim = ','; - bool cmd_found = false; - int param_cnt = 0; - - if (data == NULL) { - pr_err("factory_data is NULL.\n"); - goto err_out; - } - - if (data->cmd_is_running == true) { - pr_err("tsp cmd: other cmd is running.\n"); - goto err_out; - } - - /* check lock */ - mutex_lock(&data->cmd_lock); - data->cmd_is_running = true; - mutex_unlock(&data->cmd_lock); - - data->cmd_state = RUNNING; - - for (i = 0; i < ARRAY_SIZE(data->cmd_param); i++) - data->cmd_param[i] = 0; - - len = (int)count; - if (*(buf + len - 1) == '\n') - len--; - memset(data->cmd, 0x00, ARRAY_SIZE(data->cmd)); - memcpy(data->cmd, buf, len); - - cur = strchr(buf, (int)delim); - if (cur) - memcpy(buff, buf, cur - buf); - else - memcpy(buff, buf, len); - - /* find command */ - list_for_each_entry(tsp_cmd_ptr, &data->cmd_list_head, list) { - if (!strcmp(buff, tsp_cmd_ptr->cmd_name)) { - cmd_found = true; - break; - } - } - - /* set not_support_cmd */ - if (!cmd_found) { - list_for_each_entry(tsp_cmd_ptr, &data->cmd_list_head, list) { - if (!strcmp("not_support_cmd", tsp_cmd_ptr->cmd_name)) - break; - } - } - - /* parsing parameters */ - if (cur && cmd_found) { - cur++; - start = cur; - do { - memset(buff, 0x00, ARRAY_SIZE(buff)); - if (*cur == delim || cur - buf == len) { - end = cur; - memcpy(buff, start, end - start); - *(buff + strlen(buff)) = '\0'; - if (kstrtoint(buff, 10, - data->cmd_param + param_cnt) < 0) - break; - start = cur + 1; - param_cnt++; - } - cur++; - } while (cur - buf <= len); - } - - pr_info("cmd = %s\n", tsp_cmd_ptr->cmd_name); - for (i = 0; i < param_cnt; i++) - pr_info("cmd param %d= %d\n", i, data->cmd_param[i]); - - tsp_cmd_ptr->cmd_func(ts_data); - -err_out: - return count; -} - -static ssize_t cmd_status_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct cyttsp4 *ts_data = dev_get_drvdata(dev); - struct factory_data *data = ts_data->factory_data; - char buff[16]; - - pr_info("tsp cmd: status:%d\n", data->cmd_state); - - switch (data->cmd_state) { - case WAITING: - sprintf(buff, "%s", TOSTRING(WAITING)); - break; - case RUNNING: - sprintf(buff, "%s", TOSTRING(RUNNING)); - break; - case OK: - sprintf(buff, "%s", TOSTRING(OK)); - break; - case FAIL: - sprintf(buff, "%s", TOSTRING(FAIL)); - break; - case NOT_APPLICABLE: - sprintf(buff, "%s", TOSTRING(NOT_APPLICABLE)); - break; - default: - sprintf(buff, "%s", TOSTRING(NOT_APPLICABLE)); - break; - } - - return sprintf(buf, "%s\n", buff); -} - -static ssize_t cmd_result_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct cyttsp4 *ts_data = dev_get_drvdata(dev); - struct factory_data *data = ts_data->factory_data; - - pr_info("tsp factory : tsp cmd: result: \"%s(%d)\"\n", - data->cmd_result, strlen(data->cmd_result)); - - mutex_lock(&data->cmd_lock); - data->cmd_is_running = false; - mutex_unlock(&data->cmd_lock); - - data->cmd_state = WAITING; - - return sprintf(buf, "%s\n", data->cmd_result); -} - -static DEVICE_ATTR(cmd, S_IWUSR | S_IWGRP, NULL, cmd_store); -static DEVICE_ATTR(cmd_status, S_IRUGO, cmd_status_show, NULL); -static DEVICE_ATTR(cmd_result, S_IRUGO, cmd_result_show, NULL); - -static struct attribute *touchscreen_attributes[] = { - &dev_attr_cmd.attr, - &dev_attr_cmd_status.attr, - &dev_attr_cmd_result.attr, - NULL, -}; - -static struct attribute_group touchscreen_attr_group = { - .attrs = touchscreen_attributes, -}; -#endif - -#if TOUCH_BOOST -static void disable_dvfs(struct work_struct *unused) -{ - omap_cpufreq_min_limit_free(DVFS_LOCK_ID_TSP); - boost = false; - return; -} -static DECLARE_WORK(tsp_wq, disable_dvfs); - -static void timer_cb(unsigned long data) -{ - schedule_work(&tsp_wq); - return; -} -#endif - -#define CY_CMD_I2C_ADDR 0 -#define CY_STATUS_SIZE_BYTE 1 -#define CY_STATUS_TYP_DELAY 2 -#define CY_CMD_TAIL_LEN 3 -#define CY_CMD_BYTE 1 -#define CY_STATUS_BYTE 1 -#define CY_MAX_STATUS_SIZE 32 -#define CY_MIN_STATUS_SIZE 5 -#define CY_START_OF_PACKET 0x01 -#define CY_END_OF_PACKET 0x17 -#define CY_DATA_ROW_SIZE 288 -#define CY_DATA_ROW_SIZE_TMA400 128 -#define CY_PACKET_DATA_LEN 96 -#define CY_MAX_PACKET_LEN 512 -#define CY_COMM_BUSY 0xFF -#define CY_CMD_BUSY 0xFE -#define CY_SEPARATOR_OFFSET 0 -#define CY_ARRAY_ID_OFFSET 0 -#define CY_ROW_NUM_OFFSET 1 -#define CY_ROW_SIZE_OFFSET 3 -#define CY_ROW_DATA_OFFSET 5 -#define CY_FILE_SILICON_ID_OFFSET 0 -#define CY_FILE_REV_ID_OFFSET 4 -#define CY_CMD_LDR_HOST_SYNC 0xFF /* tma400 */ -#define CY_CMD_LDR_EXIT 0x3B -#define CY_CMD_LDR_EXIT_CMD_SIZE 7 -#define CY_CMD_LDR_EXIT_STAT_SIZE 7 - -enum ldr_status { - ERROR_SUCCESS = 0, - ERROR_COMMAND = 1, - ERROR_FLASH_ARRAY = 2, - ERROR_PACKET_DATA = 3, - ERROR_PACKET_LEN = 4, - ERROR_PACKET_CHECKSUM = 5, - ERROR_FLASH_PROTECTION = 6, - ERROR_FLASH_CHECKSUM = 7, - ERROR_VERIFY_IMAGE = 8, - ERROR_UKNOWN1 = 9, - ERROR_UKNOWN2 = 10, - ERROR_UKNOWN3 = 11, - ERROR_UKNOWN4 = 12, - ERROR_UKNOWN5 = 13, - ERROR_UKNOWN6 = 14, - ERROR_INVALID_COMMAND = 15, - ERROR_INVALID -}; - -static u16 _cyttsp4_compute_crc(struct cyttsp4 *ts, u8 *buf, int size) -{ - u16 crc = 0xffff; - u16 tmp; - int i; - - /* RUN CRC */ - - if (size == 0) - crc = ~crc; - else { - - do { - for (i = 0, tmp = 0x00ff & *buf++; i < 8; - i++, tmp >>= 1) { - if ((crc & 0x0001) ^ (tmp & 0x0001)) - crc = (crc >> 1) ^ 0x8408; - else - crc >>= 1; - } - } while (--size); - - crc = ~crc; - tmp = crc; - crc = (crc << 8) | (tmp >> 8 & 0xFF); - } - - return crc; -} - -static int _cyttsp4_get_status(struct cyttsp4 *ts, - u8 *buf, int size, unsigned long timeout_ms) -{ - unsigned long uretval = 0; - int tries = 0; - int retval = 0; - - if (timeout_ms != 0) { - /* wait until status ready interrupt or timeout occurs */ - uretval = wait_for_completion_interruptible_timeout( - &ts->int_running, msecs_to_jiffies(timeout_ms)); - - /* read the status packet */ - if (buf == NULL) { - dev_err(ts->dev, - "%s: Status buf ptr is NULL\n", __func__); - retval = -EINVAL; - goto _cyttsp4_get_status_exit; - } - for (tries = 0; tries < 2; tries++) { - retval = _cyttsp4_read_block_data(ts, CY_REG_BASE, size, - buf, ts->platform_data->addr[CY_LDR_ADDR_OFS], -#ifdef CY_USE_TMA400 - true); -#endif /* --CY_USE_TMA400 */ -#ifdef CY_USE_TMA884 - false); -#endif /* --CY_USE_TMA884 */ - /* - * retry if bus read error or - * status byte shows not ready - */ - if ((buf[1] == CY_COMM_BUSY) || (buf[1] == CY_CMD_BUSY)) - msleep(CY_DELAY_DFLT); - else - break; - } - dev_vdbg(ts->dev, - "%s: tries=%d ret=%d status=%02X\n", - __func__, tries, retval, buf[1]); - } - -_cyttsp4_get_status_exit: - mutex_lock(&ts->data_lock); - return retval; -} - -/* - * Send a bootloader command to the device; - * Wait for the ISR to execute indicating command - * was received and status is ready; - * Releases data_lock mutex to allow ISR to run, - * then locks it again. - */ -static int _cyttsp4_send_cmd(struct cyttsp4 *ts, const u8 *cmd_buf, - int cmd_size, u8 *stat_ret, size_t num_stat_byte, - size_t status_size, unsigned long timeout_ms) -{ - u8 *status_buf = NULL; - int retval = 0; - - if (timeout_ms > 0) { - status_buf = kzalloc(CY_MAX_STATUS_SIZE, GFP_KERNEL); - if (status_buf == NULL) { - dev_err(ts->dev, - "%s: Fail alloc status buffer=%p\n", - __func__, status_buf); - goto _cyttsp4_send_cmd_exit; - } - } - - if (cmd_buf == NULL) { - dev_err(ts->dev, - "%s: bad cmd_buf=%p\n", __func__, cmd_buf); - goto _cyttsp4_send_cmd_exit; - } - - if (cmd_size == 0) { - dev_err(ts->dev, - "%s: bad cmd_size=%d\n", __func__, cmd_size); - goto _cyttsp4_send_cmd_exit; - } - - _cyttsp4_pr_buf(ts, (u8 *)cmd_buf, cmd_size, "send_cmd"); - - mutex_unlock(&ts->data_lock); - if (timeout_ms > 0) - INIT_COMPLETION(ts->int_running); - retval = _cyttsp4_write_block_data(ts, CY_REG_BASE, cmd_size, cmd_buf, - ts->platform_data->addr[CY_LDR_ADDR_OFS], -#ifdef CY_USE_TMA400 - true); -#endif /* --CY_USE_TMA400 */ -#ifdef CY_USE_TMA884 - false); -#endif /* --CY_USE_TMA884 */ - if (retval < 0) { - dev_err(ts->dev, - "%s: Fail writing command=%02X\n", - __func__, cmd_buf[CY_CMD_BYTE]); - mutex_lock(&ts->data_lock); - goto _cyttsp4_send_cmd_exit; - } - - /* get the status and lock the mutex */ - if (timeout_ms > 0) { - retval = _cyttsp4_get_status(ts, status_buf, - status_size, timeout_ms); - if ((retval < 0) || (status_buf[0] != CY_START_OF_PACKET)) { - dev_err(ts->dev, - "%s: Error getting status r=%d" - " status_buf[0]=%02X\n", - __func__, retval, status_buf[0]); - if (!(retval < 0)) - retval = -EIO; - goto _cyttsp4_send_cmd_exit; - } else { - if (status_buf[CY_STATUS_BYTE] != ERROR_SUCCESS) { - dev_err(ts->dev, - "%s: Status=0x%02X error\n", - __func__, status_buf[CY_STATUS_BYTE]); - retval = -EIO; - } else if (stat_ret != NULL) { - if (num_stat_byte < status_size) - *stat_ret = status_buf[num_stat_byte]; - else - *stat_ret = 0; - } - } - } else { - if (stat_ret != NULL) - *stat_ret = ERROR_SUCCESS; - mutex_lock(&ts->data_lock); - } - -_cyttsp4_send_cmd_exit: - if (status_buf != NULL) - kfree(status_buf); - return retval; -} - -struct cyttsp4_dev_id { - u32 silicon_id; - u8 rev_id; - u32 bl_ver; -}; - -#if defined(CY_AUTO_LOAD_FW) || \ - defined(CY_USE_FORCE_LOAD) || \ - defined(CONFIG_TOUCHSCREEN_DEBUG) -#define CY_CMD_LDR_ENTER 0x38 -#define CY_CMD_LDR_ENTER_CMD_SIZE 7 -#define CY_CMD_LDR_ENTER_STAT_SIZE 15 -#define CY_CMD_LDR_INIT 0x48 -#define CY_CMD_LDR_INIT_CMD_SIZE 15 -#define CY_CMD_LDR_INIT_STAT_SIZE 7 -#define CY_CMD_LDR_ERASE_ROW 0x34 -#define CY_CMD_LDR_ERASE_ROW_CMD_SIZE 10 -#define CY_CMD_LDR_ERASE_ROW_STAT_SIZE 7 -#define CY_CMD_LDR_SEND_DATA 0x37 -#define CY_CMD_LDR_SEND_DATA_CMD_SIZE 4 /* hdr bytes only */ -#define CY_CMD_LDR_SEND_DATA_STAT_SIZE 8 -#define CY_CMD_LDR_PROG_ROW 0x39 -#define CY_CMD_LDR_PROG_ROW_CMD_SIZE 7 /* hdr bytes only */ -#define CY_CMD_LDR_PROG_ROW_STAT_SIZE 7 -#define CY_CMD_LDR_VERIFY_ROW 0x3A -#define CY_CMD_LDR_VERIFY_ROW_STAT_SIZE 8 -#define CY_CMD_LDR_VERIFY_ROW_CMD_SIZE 10 -#define CY_CMD_LDR_VERIFY_CHKSUM 0x31 -#define CY_CMD_LDR_VERIFY_CHKSUM_CMD_SIZE 7 -#define CY_CMD_LDR_VERIFY_CHKSUM_STAT_SIZE 8 - - -static u16 _cyttsp4_get_short(u8 *buf) -{ - return ((u16)(*buf) << 8) + *(buf+1); -} - -static u8 *_cyttsp4_get_row(struct cyttsp4 *ts, - u8 *row_buf, u8 *image_buf, int size) -{ - int i; - for (i = 0; i < size; i++) { - /* copy a row from the image */ - row_buf[i] = image_buf[i]; - } - - image_buf = image_buf + size; - return image_buf; -} - -static int _cyttsp4_ldr_enter(struct cyttsp4 *ts, struct cyttsp4_dev_id *dev_id) -{ - u16 crc; - int i = 0; - size_t cmd_size; - u8 status_buf[CY_MAX_STATUS_SIZE]; - u8 status = 0; - int retval = 0; - /* +1 for TMA400 host sync byte */ - u8 ldr_enter_cmd[CY_CMD_LDR_ENTER_CMD_SIZE+1]; - - memset(status_buf, 0, sizeof(status_buf)); - dev_id->bl_ver = 0; - dev_id->rev_id = 0; - dev_id->silicon_id = 0; - -#ifdef CY_USE_TMA400 - ldr_enter_cmd[i++] = CY_CMD_LDR_HOST_SYNC; -#endif /* --CY_USE_TMA400 */ - ldr_enter_cmd[i++] = CY_START_OF_PACKET; - ldr_enter_cmd[i++] = CY_CMD_LDR_ENTER; - ldr_enter_cmd[i++] = 0x00; /* data len lsb */ - ldr_enter_cmd[i++] = 0x00; /* data len msb */ -#ifdef CY_USE_TMA400 - crc = _cyttsp4_compute_crc(ts, &ldr_enter_cmd[1], i - 1); - cmd_size = sizeof(ldr_enter_cmd); -#endif /* --CY_USE_TMA400 */ -#ifdef CY_USE_TMA884 - crc = _cyttsp4_compute_crc(ts, ldr_enter_cmd, i); - cmd_size = sizeof(ldr_enter_cmd) - 1; -#endif /* --CY_USE_TMA884 */ - ldr_enter_cmd[i++] = (u8)crc; - ldr_enter_cmd[i++] = (u8)(crc >> 8); - ldr_enter_cmd[i++] = CY_END_OF_PACKET; - - mutex_unlock(&ts->data_lock); - INIT_COMPLETION(ts->int_running); - retval = _cyttsp4_write_block_data(ts, CY_REG_BASE, cmd_size, - ldr_enter_cmd, ts->platform_data->addr[CY_LDR_ADDR_OFS], -#ifdef CY_USE_TMA400 - true); -#endif /* --CY_USE_TMA400 */ -#ifdef CY_USE_TMA884 - false); -#endif /* --CY_USE_TMA884 */ - if (retval < 0) { - dev_err(ts->dev, - "%s: write block failed %d\n", __func__, retval); - goto _cyttsp4_ldr_enter_exit; - } - - /* Wait for ISR, get status and lock mutex */ - retval = _cyttsp4_get_status(ts, status_buf, - CY_CMD_LDR_ENTER_STAT_SIZE, CY_HALF_SEC_TMO_MS); - - if (retval < 0) { - dev_err(ts->dev, - "%s: Fail get status to Enter Loader command r=%d\n", - __func__, retval); - } else { - status = status_buf[CY_STATUS_BYTE]; - if (status == ERROR_SUCCESS) { - dev_id->bl_ver = - status_buf[11] << 16 | - status_buf[10] << 8 | - status_buf[9] << 0; - dev_id->rev_id = - status_buf[8] << 0; - dev_id->silicon_id = - status_buf[7] << 24 | - status_buf[6] << 16 | - status_buf[5] << 8 | - status_buf[4] << 0; - retval = 0; - } else - retval = -EIO; - dev_vdbg(ts->dev, - "%s: status=%d " - "bl_ver=%08X rev_id=%02X silicon_id=%08X\n", - __func__, status, - dev_id->bl_ver, dev_id->rev_id, dev_id->silicon_id); - } - -_cyttsp4_ldr_enter_exit: - return retval; -} - -#ifdef CY_USE_TMA400 -static int _cyttsp4_ldr_init(struct cyttsp4 *ts) -{ - u16 crc; - int i = 0; - int retval = 0; - /* +1 for TMA400 host sync byte */ - u8 ldr_init_cmd[CY_CMD_LDR_INIT_CMD_SIZE+1]; - - ldr_init_cmd[i++] = CY_CMD_LDR_HOST_SYNC; - ldr_init_cmd[i++] = CY_START_OF_PACKET; - ldr_init_cmd[i++] = CY_CMD_LDR_INIT; - ldr_init_cmd[i++] = 0x08; /* data len lsb */ - ldr_init_cmd[i++] = 0x00; /* data len msb */ - memcpy(&ldr_init_cmd[i], cyttsp4_security_key, - sizeof(cyttsp4_security_key)); - i += sizeof(cyttsp4_security_key); - crc = _cyttsp4_compute_crc(ts, &ldr_init_cmd[1], i - 1); - ldr_init_cmd[i++] = (u8)crc; - ldr_init_cmd[i++] = (u8)(crc >> 8); - ldr_init_cmd[i++] = CY_END_OF_PACKET; - - retval = _cyttsp4_send_cmd(ts, ldr_init_cmd, i, NULL, 0, - CY_CMD_LDR_INIT_STAT_SIZE, CY_TEN_SEC_TMO_MS); - if (retval < 0) { - dev_err(ts->dev, - "%s: Fail ldr init r=%d\n", - __func__, retval); - } - - return retval; -} -#endif /* --CY_USE_TMA400 */ - -struct cyttsp4_hex_image { - u8 array_id; - u16 row_num; - u16 row_size; - u8 row_data[CY_DATA_ROW_SIZE]; -} __packed; - -#ifdef CY_USE_TMA884 -static int _cyttsp4_ldr_erase_row(struct cyttsp4 *ts, - struct cyttsp4_hex_image *row_image) -{ - u16 crc; - int i = 0; - int retval = 0; - /* +1 for TMA400 host sync byte */ - u8 ldr_erase_row_cmd[CY_CMD_LDR_ERASE_ROW_CMD_SIZE+1]; - -#ifdef CY_USE_TMA400 - ldr_erase_row_cmd[i++] = CY_CMD_LDR_HOST_SYNC; -#endif /* --CY_USE_TMA400 */ - ldr_erase_row_cmd[i++] = CY_START_OF_PACKET; - ldr_erase_row_cmd[i++] = CY_CMD_LDR_ERASE_ROW; - ldr_erase_row_cmd[i++] = 0x03; /* data len lsb */ - ldr_erase_row_cmd[i++] = 0x00; /* data len msb */ - ldr_erase_row_cmd[i++] = row_image->array_id; - ldr_erase_row_cmd[i++] = (u8)row_image->row_num; - ldr_erase_row_cmd[i++] = (u8)(row_image->row_num >> 8); -#ifdef CY_USE_TMA400 - crc = _cyttsp4_compute_crc(ts, &ldr_erase_row_cmd[1], i - 1); -#endif /* --CY_USE_TMA400 */ -#ifdef CY_USE_TMA884 - crc = _cyttsp4_compute_crc(ts, ldr_erase_row_cmd, i); -#endif /* --CY_USE_TMA884 */ - ldr_erase_row_cmd[i++] = (u8)crc; - ldr_erase_row_cmd[i++] = (u8)(crc >> 8); - ldr_erase_row_cmd[i++] = CY_END_OF_PACKET; - - retval = _cyttsp4_send_cmd(ts, ldr_erase_row_cmd, i, NULL, 0, - CY_CMD_LDR_ERASE_ROW_STAT_SIZE, CY_HALF_SEC_TMO_MS); - - if (retval < 0) { - dev_err(ts->dev, - "%s: Fail erase row=%d r=%d\n", - __func__, row_image->row_num, retval); - } - return retval; -} -#endif - -static int _cyttsp4_ldr_parse_row(struct cyttsp4 *ts, u8 *row_buf, - struct cyttsp4_hex_image *row_image) -{ - u16 i, j; - int retval = 0; - - if (!row_buf) { - dev_err(ts->dev, - "%s parse row error - buf is null\n", __func__); - retval = -EINVAL; - goto cyttsp4_ldr_parse_row_exit; - } - - row_image->array_id = row_buf[CY_ARRAY_ID_OFFSET]; - row_image->row_num = _cyttsp4_get_short(&row_buf[CY_ROW_NUM_OFFSET]); - row_image->row_size = _cyttsp4_get_short(&row_buf[CY_ROW_SIZE_OFFSET]); - - if (row_image->row_size > ARRAY_SIZE(row_image->row_data)) { - dev_err(ts->dev, - "%s: row data buffer overflow\n", __func__); - retval = -EOVERFLOW; - goto cyttsp4_ldr_parse_row_exit; - } - - for (i = 0, j = CY_ROW_DATA_OFFSET; - i < row_image->row_size; i++) - row_image->row_data[i] = row_buf[j++]; - - retval = 0; - -cyttsp4_ldr_parse_row_exit: - return retval; -} - -static int _cyttsp4_ldr_prog_row(struct cyttsp4 *ts, - struct cyttsp4_hex_image *row_image) -{ - u16 crc; - int next; - int data; - int row_data; - u16 row_sum = 0; - size_t data_len; -#ifdef CY_USE_TMA884 - int segment; -#endif /* --CY_USE_TMA884 */ - int retval = 0; - - u8 *cmd = kzalloc(CY_MAX_PACKET_LEN, GFP_KERNEL); - - if (cmd != NULL) { - row_data = 0; - row_sum = 0; - -#ifdef CY_USE_TMA884 - for (segment = 0; segment < - (CY_DATA_ROW_SIZE/CY_PACKET_DATA_LEN)-1; - segment++) { - next = 0; - cmd[next++] = CY_START_OF_PACKET; - cmd[next++] = CY_CMD_LDR_SEND_DATA; - cmd[next++] = (u8)CY_PACKET_DATA_LEN; - cmd[next++] = (u8)(CY_PACKET_DATA_LEN >> 8); - - for (data = 0; - data < CY_PACKET_DATA_LEN; data++) { - cmd[next] = row_image->row_data - [row_data++]; - row_sum += cmd[next]; - next++; - } - - crc = _cyttsp4_compute_crc(ts, cmd, next); - cmd[next++] = (u8)crc; - cmd[next++] = (u8)(crc >> 8); - cmd[next++] = CY_END_OF_PACKET; - - retval = _cyttsp4_send_cmd(ts, cmd, next, NULL, - 0, CY_CMD_LDR_SEND_DATA_STAT_SIZE, - CY_HALF_SEC_TMO_MS); - - if (retval < 0) { - dev_err(ts->dev, - "%s: send row=%d segment=%d" - " fail r=%d\n", - __func__, row_image->row_num, - segment, retval); - goto cyttsp4_ldr_prog_row_exit; - } - } -#endif /* --CY_USE_TMA884 */ - - next = 0; -#ifdef CY_USE_TMA400 - cmd[next++] = CY_CMD_LDR_HOST_SYNC; -#endif /* --CY_USE_TMA400 */ - cmd[next++] = CY_START_OF_PACKET; - cmd[next++] = CY_CMD_LDR_PROG_ROW; - /* - * include array id size and row id size in CY_PACKET_DATA_LEN - */ -#ifdef CY_USE_TMA400 - data_len = CY_DATA_ROW_SIZE_TMA400; -#endif /* --CY_USE_TMA400 */ -#ifdef CY_USE_TMA884 - data_len = CY_PACKET_DATA_LEN; -#endif /* --CY_USE_TMA884 */ - cmd[next++] = (u8)(data_len+3); - cmd[next++] = (u8)((data_len+3) >> 8); - cmd[next++] = row_image->array_id; - cmd[next++] = (u8)row_image->row_num; - cmd[next++] = (u8)(row_image->row_num >> 8); - - for (data = 0; - data < data_len; data++) { - cmd[next] = row_image->row_data[row_data++]; - row_sum += cmd[next]; - next++; - } - -#ifdef CY_USE_TMA400 - crc = _cyttsp4_compute_crc(ts, &cmd[1], next - 1); -#endif /* --CY_USE_TMA400 */ -#ifdef CY_USE_TMA884 - crc = _cyttsp4_compute_crc(ts, cmd, next); -#endif /* --CY_USE_TMA884 */ - cmd[next++] = (u8)crc; - cmd[next++] = (u8)(crc >> 8); - cmd[next++] = CY_END_OF_PACKET; - - retval = _cyttsp4_send_cmd(ts, cmd, next, NULL, 0, - CY_CMD_LDR_PROG_ROW_STAT_SIZE, CY_HALF_SEC_TMO_MS); - - if (retval < 0) { - dev_err(ts->dev, - "%s: prog row=%d fail r=%d\n", - __func__, row_image->row_num, retval); - goto cyttsp4_ldr_prog_row_exit; - } - - } else { - dev_err(ts->dev, - "%s prog row error - cmd buf is NULL\n", __func__); - retval = -EIO; - } - -cyttsp4_ldr_prog_row_exit: - if (cmd != NULL) - kfree(cmd); - return retval; -} - -static int _cyttsp4_ldr_verify_row(struct cyttsp4 *ts, - struct cyttsp4_hex_image *row_image) -{ - u16 crc; - int i = 0; - u8 verify_checksum; - int retval = 0; - /* +1 for TMA400 host sync byte */ - u8 ldr_verify_row_cmd[CY_CMD_LDR_VERIFY_ROW_CMD_SIZE+1]; - -#ifdef CY_USE_TMA400 - ldr_verify_row_cmd[i++] = CY_CMD_LDR_HOST_SYNC; -#endif /* --CY_USE_TMA400 */ - ldr_verify_row_cmd[i++] = CY_START_OF_PACKET; - ldr_verify_row_cmd[i++] = CY_CMD_LDR_VERIFY_ROW; - ldr_verify_row_cmd[i++] = 0x03; /* data len lsb */ - ldr_verify_row_cmd[i++] = 0x00; /* data len msb */ - ldr_verify_row_cmd[i++] = row_image->array_id; - ldr_verify_row_cmd[i++] = (u8)row_image->row_num; - ldr_verify_row_cmd[i++] = (u8)(row_image->row_num >> 8); -#ifdef CY_USE_TMA400 - crc = _cyttsp4_compute_crc(ts, &ldr_verify_row_cmd[1], i - 1); -#endif /* --CY_USE_TMA400 */ -#ifdef CY_USE_TMA884 - crc = _cyttsp4_compute_crc(ts, ldr_verify_row_cmd, i); -#endif /* --CY_USE_TMA884 */ - ldr_verify_row_cmd[i++] = (u8)crc; - ldr_verify_row_cmd[i++] = (u8)(crc >> 8); - ldr_verify_row_cmd[i++] = CY_END_OF_PACKET; - - retval = _cyttsp4_send_cmd(ts, ldr_verify_row_cmd, i, - &verify_checksum, 4, - CY_CMD_LDR_VERIFY_ROW_STAT_SIZE, CY_HALF_SEC_TMO_MS); - - if (retval < 0) { - dev_err(ts->dev, - "%s: verify row=%d fail r=%d\n", - __func__, row_image->row_num, retval); - } - - return retval; -} - -static int _cyttsp4_ldr_verify_chksum(struct cyttsp4 *ts, u8 *app_chksum) -{ - u16 crc; - int i = 0; - int retval = 0; - /* +1 for TMA400 host sync byte */ - u8 ldr_verify_chksum_cmd[CY_CMD_LDR_VERIFY_CHKSUM_CMD_SIZE+1]; - -#ifdef CY_USE_TMA400 - ldr_verify_chksum_cmd[i++] = CY_CMD_LDR_HOST_SYNC; -#endif /* --CY_USE_TMA400 */ - ldr_verify_chksum_cmd[i++] = CY_START_OF_PACKET; - ldr_verify_chksum_cmd[i++] = CY_CMD_LDR_VERIFY_CHKSUM; - ldr_verify_chksum_cmd[i++] = 0x00; /* data len lsb */ - ldr_verify_chksum_cmd[i++] = 0x00; /* data len msb */ -#ifdef CY_USE_TMA400 - crc = _cyttsp4_compute_crc(ts, &ldr_verify_chksum_cmd[1], i - 1); -#endif /* --CY_USE_TMA400 */ -#ifdef CY_USE_TMA884 - crc = _cyttsp4_compute_crc(ts, ldr_verify_chksum_cmd, i); -#endif /* --CY_USE_TMA884 */ - ldr_verify_chksum_cmd[i++] = (u8)crc; - ldr_verify_chksum_cmd[i++] = (u8)(crc >> 8); - ldr_verify_chksum_cmd[i++] = CY_END_OF_PACKET; - - retval = _cyttsp4_send_cmd(ts, ldr_verify_chksum_cmd, i, - app_chksum, 4, - CY_CMD_LDR_VERIFY_CHKSUM_STAT_SIZE, CY_HALF_SEC_TMO_MS); - - if (retval < 0) { - dev_err(ts->dev, - "%s: verify checksum fail r=%d\n", - __func__, retval); - } - - return retval; -} - -static int _cyttsp4_load_app(struct cyttsp4 *ts, const u8 *fw, int fw_size) -{ - u8 *p; -#ifdef CY_USE_TMA884 - u8 tries; -#endif - int ret; - int retval; /* need separate return value at exit stage */ - struct cyttsp4_dev_id *file_id = NULL; - struct cyttsp4_dev_id *dev_id = NULL; - struct cyttsp4_hex_image *row_image = NULL; - u8 app_chksum; - - u8 *row_buf = NULL; - size_t image_rec_size; - size_t row_buf_size = 1024 > CY_MAX_PRBUF_SIZE ? - 1024 : CY_MAX_PRBUF_SIZE; - int row_count = 0; - -#ifdef CY_USE_TMA400 - image_rec_size = CY_DATA_ROW_SIZE_TMA400 + - (sizeof(struct cyttsp4_hex_image) - CY_DATA_ROW_SIZE); -#endif /* --CY_USE_TMA400 */ -#ifdef CY_USE_TMA884 - image_rec_size = sizeof(struct cyttsp4_hex_image); -#endif /* --CY_USE_TMA884 */ - - if (!fw_size || (fw_size % image_rec_size != 0)) { - dev_err(ts->dev, - "%s: Firmware image is misaligned\n", __func__); - retval = -EINVAL; - goto _cyttsp4_load_app_exit; - } - -#ifdef CY_USE_WATCHDOG - _cyttsp4_stop_wd_timer(ts); -#endif - - dev_info(ts->dev, - "%s: start load app\n", __func__); - - row_buf = kzalloc(row_buf_size, GFP_KERNEL); - row_image = kzalloc(sizeof(struct cyttsp4_hex_image), GFP_KERNEL); - file_id = kzalloc(sizeof(struct cyttsp4_dev_id), GFP_KERNEL); - dev_id = kzalloc(sizeof(struct cyttsp4_dev_id), GFP_KERNEL); - if ((row_buf == NULL) || (row_image == NULL) || - (file_id == NULL) || (dev_id == NULL)) { - dev_err(ts->dev, - "%s: Unable to alloc row buffers(%p %p %p %p)\n", - __func__, row_buf, row_image, file_id, dev_id); - retval = -ENOMEM; - goto _cyttsp4_load_app_error_exit; - } - - p = (u8 *)fw; - /* Enter Loader and return Silicon ID and Rev */ - - retval = _cyttsp4_reset(ts); - if (retval < 0) { - dev_err(ts->dev, - "%s: Fail reset device r=%d\n", __func__, retval); - goto _cyttsp4_load_app_exit; - } - retval = _cyttsp4_wait_int(ts, CY_TEN_SEC_TMO_MS); - if (retval < 0) { - dev_err(ts->dev, - "%s: Fail waiting for bootloader interrupt\n", - __func__); - goto _cyttsp4_load_app_exit; - } - - _cyttsp4_change_state(ts, CY_BL_STATE); - dev_info(ts->dev, - "%s: Send BL Loader Enter\n", __func__); - retval = _cyttsp4_ldr_enter(ts, dev_id); - if (retval < 0) { - dev_err(ts->dev, - "%s: Error cannot start Loader (ret=%d)\n", - __func__, retval); - goto _cyttsp4_load_app_error_exit; - } - - dev_vdbg(ts->dev, - "%s: dev: silicon id=%08X rev=%02X bl=%08X\n", - __func__, dev_id->silicon_id, - dev_id->rev_id, dev_id->bl_ver); - -#ifdef CY_USE_TMA400 - udelay(1000); - retval = _cyttsp4_ldr_init(ts); - if (retval < 0) { - dev_err(ts->dev, - "%s: Error cannot init Loader (ret=%d)\n", - __func__, retval); - goto _cyttsp4_load_app_error_exit; - } -#endif /* --CY_USE_TMA400 */ - - dev_info(ts->dev, - "%s: Send BL Loader Blocks\n", __func__); - while (p < (fw + fw_size)) { - /* Get row */ - dev_dbg(ts->dev, - "%s: read row=%d\n", __func__, ++row_count); - memset(row_buf, 0, row_buf_size); - p = _cyttsp4_get_row(ts, row_buf, p, image_rec_size); - - /* Parse row */ - dev_vdbg(ts->dev, - "%s: p=%p buf=%p buf[0]=%02X\n", __func__, - p, row_buf, row_buf[0]); - retval = _cyttsp4_ldr_parse_row(ts, row_buf, row_image); - dev_vdbg(ts->dev, - "%s: array_id=%02X row_num=%04X(%d)" - " row_size=%04X(%d)\n", __func__, - row_image->array_id, - row_image->row_num, row_image->row_num, - row_image->row_size, row_image->row_size); - if (retval < 0) { - dev_err(ts->dev, - "%s: Parse Row Error " - "(a=%d r=%d ret=%d\n", - __func__, row_image->array_id, - row_image->row_num, - retval); - goto bl_exit; - } else { - dev_vdbg(ts->dev, - "%s: Parse Row " - "(a=%d r=%d ret=%d\n", - __func__, row_image->array_id, - row_image->row_num, retval); - } - -#ifdef CY_USE_TMA884 - /* erase row */ - tries = 0; - do { - retval = _cyttsp4_ldr_erase_row(ts, row_image); - if (retval < 0) { - dev_err(ts->dev, - "%s: Erase Row Error " - "(array=%d row=%d ret=%d try=%d)\n", - __func__, row_image->array_id, - row_image->row_num, retval, tries); - } - } while (retval && tries++ < 5); - - if (retval < 0) - goto _cyttsp4_load_app_error_exit; -#endif - - /* program row */ - retval = _cyttsp4_ldr_prog_row(ts, row_image); - if (retval < 0) { - dev_err(ts->dev, - "%s: Program Row Error " - "(array=%d row=%d ret=%d)\n", - __func__, row_image->array_id, - row_image->row_num, retval); - goto _cyttsp4_load_app_error_exit; - } - - /* verify row */ - retval = _cyttsp4_ldr_verify_row(ts, row_image); - if (retval < 0) { - dev_err(ts->dev, - "%s: Verify Row Error " - "(array=%d row=%d ret=%d)\n", - __func__, row_image->array_id, - row_image->row_num, retval); - goto _cyttsp4_load_app_error_exit; - } - - dev_vdbg(ts->dev, - "%s: array=%d row_cnt=%d row_num=%04X\n", - __func__, row_image->array_id, row_count, - row_image->row_num); - } - - /* verify app checksum */ - retval = _cyttsp4_ldr_verify_chksum(ts, &app_chksum); - dev_dbg(ts->dev, - "%s: Application Checksum = %02X r=%d\n", - __func__, app_chksum, retval); - if (retval < 0) { - dev_err(ts->dev, - "%s: ldr_verify_chksum fail r=%d\n", __func__, retval); - retval = 0; - } - - /* exit loader */ -bl_exit: - dev_info(ts->dev, - "%s: Send BL Loader Terminate\n", __func__); - ret = _cyttsp4_ldr_exit(ts); - if (ret) { - dev_err(ts->dev, - "%s: Error on exit Loader (ret=%d)\n", - __func__, ret); - retval = ret; - goto _cyttsp4_load_app_error_exit; - } - - /* - * this is a temporary parking state; - * the driver will always run startup - * after the loader has completed - */ - _cyttsp4_change_state(ts, CY_TRANSFER_STATE); - goto _cyttsp4_load_app_exit; - -_cyttsp4_load_app_error_exit: - _cyttsp4_change_state(ts, CY_BL_STATE); -_cyttsp4_load_app_exit: - kfree(row_buf); - kfree(row_image); - kfree(file_id); - kfree(dev_id); - return retval; -} -#endif /* CY_AUTO_LOAD_FW || CY_USE_FORCE_LOAD || CONFIG_TOUCHSCREEN_DEBUG */ - -/* Constructs loader exit command and sends via _cyttsp4_send_cmd() */ -static int _cyttsp4_ldr_exit(struct cyttsp4 *ts) -{ - u16 crc; - int i = 0; - int retval = 0; - /* +1 for TMA400 host sync byte */ - u8 ldr_exit_cmd[CY_CMD_LDR_EXIT_CMD_SIZE+1]; - -#ifdef CY_USE_TMA400 - ldr_exit_cmd[i++] = CY_CMD_LDR_HOST_SYNC; -#endif /* --CY_USE_TMA400 */ - ldr_exit_cmd[i++] = CY_START_OF_PACKET; - ldr_exit_cmd[i++] = CY_CMD_LDR_EXIT; - ldr_exit_cmd[i++] = 0x00; /* data len lsb */ - ldr_exit_cmd[i++] = 0x00; /* data len msb */ -#ifdef CY_USE_TMA400 - crc = _cyttsp4_compute_crc(ts, &ldr_exit_cmd[1], i - 1); -#endif /* --CY_USE_TMA400 */ -#ifdef CY_USE_TMA884 - crc = _cyttsp4_compute_crc(ts, ldr_exit_cmd, i); -#endif /* --CY_USE_TMA884 */ - ldr_exit_cmd[i++] = (u8)crc; - ldr_exit_cmd[i++] = (u8)(crc >> 8); - ldr_exit_cmd[i++] = CY_END_OF_PACKET; - - retval = _cyttsp4_send_cmd(ts, ldr_exit_cmd, i, NULL, 0, - CY_CMD_LDR_EXIT_STAT_SIZE, 0); - - if (retval < 0) { - dev_err(ts->dev, - "%s: BL Loader exit fail r=%d\n", - __func__, retval); - } - - dev_vdbg(ts->dev, - "%s: Exit BL Loader r=%d\n", __func__, retval); - - return retval; -} - -#if defined(CY_USE_FORCE_LOAD) || defined(CONFIG_TOUCHSCREEN_DEBUG) -/* Force firmware upgrade */ -static void cyttsp4_firmware_cont(const struct firmware *fw, void *context) -{ - int retval = 0; - struct device *dev = context; - struct cyttsp4 *ts = dev_get_drvdata(dev); - u8 header_size = 0; - - mutex_lock(&ts->data_lock); - - if (fw == NULL) { - dev_err(ts->dev, - "%s: Firmware not found\n", __func__); - goto cyttsp4_firmware_cont_exit; - } - - if ((fw->data == NULL) || (fw->size == 0)) { - dev_err(ts->dev, - "%s: No firmware received\n", __func__); - goto cyttsp4_firmware_cont_release_exit; - } - - header_size = fw->data[0]; - if (header_size >= (fw->size + 1)) { - dev_err(ts->dev, - "%s: Firmware format is invalid\n", __func__); - goto cyttsp4_firmware_cont_release_exit; - } - retval = _cyttsp4_load_app(ts, &(fw->data[header_size + 1]), - fw->size - (header_size + 1)); - if (retval < 0) { - dev_err(ts->dev, - "%s: Firmware update failed with error code %d\n", - __func__, retval); - _cyttsp4_change_state(ts, CY_IDLE_STATE); - retval = -EIO; - goto cyttsp4_firmware_cont_release_exit; - } - - - retval = _cyttsp4_startup(ts); - if (retval < 0) { - dev_err(ts->dev, - "%s: Failed to restart IC with error code %d\n", - __func__, retval); - _cyttsp4_change_state(ts, CY_IDLE_STATE); - } - -cyttsp4_firmware_cont_release_exit: - release_firmware(fw); - -cyttsp4_firmware_cont_exit: - ts->waiting_for_fw = false; - mutex_unlock(&ts->data_lock); - return; -} -static ssize_t cyttsp4_ic_reflash_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - static const char *wait_fw_ld = "Driver is waiting for firmware load\n"; - static const char *no_fw_ld = "No firmware loading in progress\n"; - struct cyttsp4 *ts = dev_get_drvdata(dev); - - if (ts->waiting_for_fw) - return snprintf(buf, strlen(wait_fw_ld)+1, wait_fw_ld); - else - return snprintf(buf, strlen(no_fw_ld)+1, no_fw_ld); -} -static ssize_t cyttsp4_ic_reflash_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t size) -{ - int i; - int retval = 0; - struct cyttsp4 *ts = dev_get_drvdata(dev); - - if (ts->waiting_for_fw) { - dev_err(ts->dev, - "%s: Driver is already waiting for firmware\n", - __func__); - retval = -EALREADY; - goto cyttsp4_ic_reflash_store_exit; - } - - /* - * must configure FW_LOADER in .config file - * CONFIG_HOTPLUG=y - * CONFIG_FW_LOADER=y - * CONFIG_FIRMWARE_IN_KERNEL=y - * CONFIG_EXTRA_FIRMWARE="" - * CONFIG_EXTRA_FIRMWARE_DIR="" - */ - - if (size > CY_BL_FW_NAME_SIZE) { - dev_err(ts->dev, - "%s: Filename too long\n", __func__); - retval = -ENAMETOOLONG; - goto cyttsp4_ic_reflash_store_exit; - } else { - /* - * name string must be in alloc() memory - * or is lost on context switch - * strip off any line feed character(s) - * at the end of the buf string - */ - for (i = 0; buf[i]; i++) { - if (buf[i] < ' ') - ts->fwname[i] = 0; - else - ts->fwname[i] = buf[i]; - } - } - - dev_vdbg(ts->dev, - "%s: Enabling firmware class loader\n", __func__); - - retval = request_firmware_nowait(THIS_MODULE, - FW_ACTION_NOHOTPLUG, (const char *)ts->fwname, ts->dev, - GFP_KERNEL, ts->dev, cyttsp4_firmware_cont); - if (retval < 0) { - dev_err(ts->dev, - "%s: Fail request firmware class file load\n", - __func__); - ts->waiting_for_fw = false; - goto cyttsp4_ic_reflash_store_exit; - } else { - ts->waiting_for_fw = true; - retval = size; - } - -cyttsp4_ic_reflash_store_exit: - return retval; -} -static DEVICE_ATTR(ic_reflash, S_IRUSR | S_IWUSR, - cyttsp4_ic_reflash_show, cyttsp4_ic_reflash_store); -#endif /* CY_USE_FORCE_LOAD || CONFIG_TOUCHSCREEN_DEBUG */ - -#ifdef CY_USE_TMA884 -static int _cyttsp4_calc_data_crc(struct cyttsp4 *ts, size_t ndata, u8 *pdata, - u8 *crc_h, u8 *crc_l, const char *name) -{ - int retval = 0; - u8 *buf = NULL; - - *crc_h = 0; - *crc_l = 0; - - buf = kzalloc(sizeof(uint8_t) * 126, GFP_KERNEL); - if (buf == NULL) { - dev_err(ts->dev, - "%s: Failed to allocate buf\n", __func__); - retval = -ENOMEM; - goto _cyttsp4_calc_data_crc_exit; - } - - if (pdata == NULL) { - dev_err(ts->dev, - "%s: bad data pointer\n", __func__); - retval = -ENXIO; - goto _cyttsp4_calc_data_crc_exit; - } - - if (ndata > 122) { - dev_err(ts->dev, - "%s: %s is too large n=%d size=%d\n", - __func__, name, ndata, 126); - retval = -EOVERFLOW; - goto _cyttsp4_calc_data_crc_exit; - } - - buf[0] = 0x00; /* num of config bytes + 4 high */ - buf[1] = 0x7E; /* num of config bytes + 4 low */ - buf[2] = 0x00; /* max block size w/o crc high */ - buf[3] = 0x7E; /* max block size w/o crc low */ - - /* Copy platform data */ - memcpy(&(buf[4]), pdata, ndata); - - /* Calculate CRC */ - _cyttsp4_calc_crc(ts, buf, 126, crc_h, crc_l); - - dev_vdbg(ts->dev, - "%s: crc=%02X%02X\n", __func__, *crc_h, *crc_l); - -_cyttsp4_calc_data_crc_exit: - kfree(buf); - return retval; -} -#endif /* --CY_USE_TMA884 */ - - -#ifdef CY_USE_TMA884 -#ifdef CY_AUTO_LOAD_TOUCH_PARAMS -static int _cyttsp4_calc_settings_crc(struct cyttsp4 *ts, u8 *crc_h, u8 *crc_l) -{ - int retval = 0; - u8 *buf = NULL; - u8 size = 0; - - buf = kzalloc(sizeof(uint8_t) * 126, GFP_KERNEL); - if (buf == NULL) { - dev_err(ts->dev, - "%s: Failed to allocate buf\n", __func__); - retval = -ENOMEM; - goto _cyttsp4_calc_settings_crc_exit; - } - - if (ts->platform_data->sett[CY_IC_GRPNUM_TCH_PARM_VAL] == NULL) { - dev_err(ts->dev, - "%s: Missing Platform Touch Parameter" - " values table\n", __func__); - retval = -ENXIO; - goto _cyttsp4_calc_settings_crc_exit; - } - if ((ts->platform_data->sett - [CY_IC_GRPNUM_TCH_PARM_VAL]->data == NULL) || - (ts->platform_data->sett - [CY_IC_GRPNUM_TCH_PARM_VAL]->size == 0)) { - dev_err(ts->dev, - "%s: Missing Platform Touch Parameter" - " values table data\n", __func__); - retval = -ENXIO; - goto _cyttsp4_calc_settings_crc_exit; - } - - size = ts->platform_data->sett[CY_IC_GRPNUM_TCH_PARM_VAL]->size; - - if (size > 122) { - dev_err(ts->dev, - "%s: Platform data is too large\n", __func__); - retval = -EOVERFLOW; - goto _cyttsp4_calc_settings_crc_exit; - } - - buf[0] = 0x00; /* num of config bytes + 4 high */ - buf[1] = 0x7E; /* num of config bytes + 4 low */ - buf[2] = 0x00; /* max block size w/o crc high */ - buf[3] = 0x7E; /* max block size w/o crc low */ - - /* Copy platform data */ - memcpy(&(buf[4]), - ts->platform_data->sett[CY_IC_GRPNUM_TCH_PARM_VAL]->data, - size); - - /* Calculate CRC */ - _cyttsp4_calc_crc(ts, buf, 126, crc_h, crc_l); - -_cyttsp4_calc_settings_crc_exit: - kfree(buf); - return retval; -} -#endif /* --CY_AUTO_LOAD_TOUCH_PARAMS */ -#endif /* --CY_USE_TMA884 */ - -/* Get IC CRC is operational mode command */ -static int _cyttsp4_get_ic_crc(struct cyttsp4 *ts, - enum cyttsp4_ic_ebid ebid, u8 *crc_h, u8 *crc_l) -{ - int retval = 0; - u8 cmd_dat[CY_NUM_DAT + 1]; /* +1 for cmd byte */ - - memset(cmd_dat, 0, sizeof(cmd_dat)); - cmd_dat[0] = CY_GET_CFG_BLK_CRC;/* pack cmd */ - cmd_dat[1] = ebid; /* pack EBID id */ - - retval = _cyttsp4_put_cmd_wait(ts, ts->si_ofs.cmd_ofs, - sizeof(cmd_dat), cmd_dat, CY_HALF_SEC_TMO_MS, - _cyttsp4_chk_cmd_rdy, NULL, - ts->platform_data->addr[CY_TCH_ADDR_OFS], true); - if (retval < 0) { - dev_err(ts->dev, - "%s: Fail Get CRC command r=%d\n", - __func__, retval); - goto _cyttsp4_get_ic_crc_exit; - } - - memset(cmd_dat, 0, sizeof(cmd_dat)); - retval = _cyttsp4_read_block_data(ts, ts->si_ofs.cmd_ofs, - sizeof(cmd_dat), cmd_dat, - ts->platform_data->addr[CY_TCH_ADDR_OFS], true); - if (retval < 0) { - dev_err(ts->dev, - "%s: Fail Get CRC status r=%d\n", - __func__, retval); - goto _cyttsp4_get_ic_crc_exit; - } - - /* Check CRC status and assign values */ - if (cmd_dat[1] != 0) { - dev_err(ts->dev, - "%s: Get CRC status=%d error\n", - __func__, cmd_dat[1]); - retval = -EIO; - goto _cyttsp4_get_ic_crc_exit; - } - - *crc_h = cmd_dat[2]; - *crc_l = cmd_dat[3]; - -#ifdef CY_USE_TMA400 - retval = _cyttsp4_cmd_handshake(ts); - if (retval < 0) { - dev_err(ts->dev, - "%s: Command handshake error r=%d\n", - __func__, retval); - /* continue anyway; rely on handshake tmo */ - retval = 0; - } -#endif /* --CY_USE_TMA400 */ - -_cyttsp4_get_ic_crc_exit: - return retval; -} - -#ifdef CY_USE_TMA400 -static int _cyttsp4_startup(struct cyttsp4 *ts) -{ - int tries; - int retval = 0; - u8 ic_crc[2]; -#ifdef CY_AUTO_LOAD_TOUCH_PARAMS - u8 table_crc[2]; -#endif /* --CY_AUTO_LOAD_TOUCH_PARAMS */ - bool put_all_params_done = false; - bool upgraded = false; - bool mddata_updated = false; - bool sleep_state = false; - tries = 0; - ts->starting_up = true; - memset(&ts->test, 0, sizeof(struct cyttsp4_test_mode)); - if (ts->driver_state == CY_SLEEP_STATE) - sleep_state = true; -_cyttsp4_startup_tma400_restart: - - dev_err(ts->dev, - "%s: enter driver_state=%d\n", __func__, ts->driver_state); - ts->current_mode = CY_MODE_BOOTLOADER; - retval = _cyttsp4_reset(ts); - if (retval < 0) { - dev_err(ts->dev, - "%s: Fail reset device r=%d\n", __func__, retval); - /* continue anyway in case device was already in bootloader */ - } - /* - * Wait for heartbeat interrupt. If we didn't get the CPU quickly, this - * may not be the first interupt. - */ - dev_vdbg(ts->dev, - "%s: wait for first bootloader interrupt\n", __func__); - retval = _cyttsp4_wait_int(ts, CY_HALF_SEC_TMO_MS); - if (retval < 0) { - dev_err(ts->dev, - "%s: Fail waiting for bootloader interrupt\n", - __func__); - goto _cyttsp4_startup_tma400_exit; - } - - /* - * exit BL mode and eliminate race between heartbeat and - * command / response interrupts - */ - _cyttsp4_change_state(ts, CY_EXIT_BL_STATE); - ts->switch_flag = true; - retval = _cyttsp4_wait_si_int(ts, CY_TEN_SEC_TMO_MS); - if (retval < 0) { - dev_err(ts->dev, - "%s: Fail wait switch to Sysinfo r=%d\n", - __func__, retval); - /* continue anyway in case sync missed */ - } - - if (!sleep_state) { - - if (ts->driver_state != CY_SYSINFO_STATE) { - dev_err(ts->dev, - "%s: Fail set sysinfo mode; switch to sysinfo anyway\r", - __func__); - _cyttsp4_change_state(ts, CY_SYSINFO_STATE); - } else { - dev_vdbg(ts->dev, - "%s: Exit BL ok; now in sysinfo mode\n", __func__); - _cyttsp4_pr_state(ts); - } - - dev_vdbg(ts->dev, - "%s: Read Sysinfo regs and get rev numbers try=%d\n", - __func__, tries); - retval = _cyttsp4_get_sysinfo_regs(ts); - if (retval < 0) { - dev_err(ts->dev, - "%s: Read Block fail -get sys regs (r=%d)\n", - __func__, retval); - dev_err(ts->dev, - "%s: Fail to switch from Bootloader " - "to Application r=%d\n", - __func__, retval); - - _cyttsp4_change_state(ts, CY_BL_STATE); - - if (upgraded) { - dev_err(ts->dev, - "%s: app failed to launch after" - " platform firmware upgrade\n", __func__); - retval = -EIO; - goto _cyttsp4_startup_tma400_exit; - } - -#ifdef CY_AUTO_LOAD_FW - if (!ts->powered) { - dev_info(ts->dev, - "%s: attempting to reflash IC...\n", __func__); - if (ts->platform_data->fw->img == NULL || - ts->platform_data->fw->size == 0) { - dev_err(ts->dev, - "%s: no platform firmware available" - " for reflashing\n", __func__); - _cyttsp4_change_state(ts, CY_INVALID_STATE); - retval = -ENODATA; - goto _cyttsp4_startup_tma400_exit; - } - retval = _cyttsp4_load_app(ts, - ts->platform_data->fw->img, - ts->platform_data->fw->size); - if (retval) { - dev_err(ts->dev, - "%s: failed to reflash IC (r=%d)\n", - __func__, retval); - _cyttsp4_change_state(ts, CY_INVALID_STATE); - retval = -EIO; - goto _cyttsp4_startup_tma400_exit; - } - upgraded = true; - dev_info(ts->dev, - "%s: resetting IC after reflashing\n", __func__); - goto _cyttsp4_startup_tma400_restart; /* Reset the part */ - } -#endif /* --CY_AUTO_LOAD_FW */ - } - -#ifdef CY_AUTO_LOAD_FW - if (!ts->powered) { - retval = _cyttsp4_boot_loader(ts, &upgraded); - if (retval < 0) { - dev_err(ts->dev, - "%s: fail boot loader r=%d)\n", - __func__, retval); - _cyttsp4_change_state(ts, CY_IDLE_STATE); - goto _cyttsp4_startup_tma400_exit; - } - if (upgraded) - goto _cyttsp4_startup_tma400_restart; - } -#endif /* --CY_AUTO_LOAD_FW */ - - retval = _cyttsp4_set_mode(ts, CY_CONFIG_MODE); - if (retval < 0) { - dev_err(ts->dev, - "%s: Fail set config mode 1 r=%d\n", __func__, retval); - goto _cyttsp4_startup_tma400_bypass_crc_check; - } - - retval = _cyttsp4_get_ebid_row_size(ts); - if (retval < 0) { - dev_err(ts->dev, - "%s: Fail get EBID row size; using default r=%d\n", - __func__, retval); - } - dev_vdbg(ts->dev, - "%s: get EBID row size=%d\n", __func__, ts->ebid_row_size); - - memset(ic_crc, 0, sizeof(ic_crc)); - dev_vdbg(ts->dev, - "%s: Read IC CRC values\n", __func__); - /* Get settings CRC from touch IC */ - retval = _cyttsp4_set_mode(ts, CY_OPERATE_MODE); - if (retval < 0) { - dev_err(ts->dev, - "%s: Fail set operational mode 1 (r=%d)\n", - __func__, retval); - goto _cyttsp4_startup_tma400_exit; - } - retval = _cyttsp4_get_ic_crc(ts, CY_TCH_PARM_EBID, - &ic_crc[0], &ic_crc[1]); - if (retval < 0) { - dev_err(ts->dev, - "%s: Fail read ic crc r=%d\n", - __func__, retval); - } - - _cyttsp4_pr_buf(ts, ic_crc, sizeof(ic_crc), "read_ic_crc"); - - retval = _cyttsp4_set_mode(ts, CY_CONFIG_MODE); - if (retval < 0) { - dev_err(ts->dev, - "%s: Fail set config mode 2 r=%d\n", __func__, retval); - goto _cyttsp4_startup_tma400_exit; - } -#ifdef CY_AUTO_LOAD_TOUCH_PARAMS - if (!ts->powered) { - if (!put_all_params_done) { - if (ts->platform_data->sett - [CY_IC_GRPNUM_TCH_PARM_VAL] == NULL) { - dev_err(ts->dev, - "%s: missing param table\n", __func__); - goto _cyttsp4_startup_tma400_bypass_crc_check; - } else if (ts->platform_data->sett - [CY_IC_GRPNUM_TCH_PARM_VAL]->data == NULL) { - dev_err(ts->dev, - "%s: missing param table data\n", __func__); - goto _cyttsp4_startup_tma400_bypass_crc_check; - } else if (ts->platform_data->sett - [CY_IC_GRPNUM_TCH_PARM_VAL]->size == 0) { - dev_err(ts->dev, - "%s: param values table size is 0\n", __func__); - goto _cyttsp4_startup_tma400_bypass_crc_check; - } - _cyttsp_read_table_crc(ts, ts->platform_data->sett - [CY_IC_GRPNUM_TCH_PARM_VAL]->data, - &table_crc[0], &table_crc[1]); - _cyttsp4_pr_buf(ts, table_crc, sizeof(table_crc), - "read_table_crc"); - if ((ic_crc[0] != table_crc[0]) || - (ic_crc[1] != table_crc[1])) { - retval = _cyttsp4_put_all_params_tma400(ts); - if (retval < 0) { - dev_err(ts->dev, - "%s: Fail put all params r=%d\n", - __func__, retval); - goto _cyttsp4_startup_tma400_bypass_crc_check; - } - put_all_params_done = true; - goto _cyttsp4_startup_tma400_restart; - } - } - } -#else - put_all_params_done = true; -#endif /* --CY_AUTO_LOAD_TOUCH_PARAMS */ - -_cyttsp4_startup_tma400_bypass_crc_check: - if (!mddata_updated) { - retval = _cyttsp4_check_mddata_tma400(ts, &mddata_updated); - if (retval < 0) { - dev_err(ts->dev, - "%s: Fail update MDDATA r=%d\n", - __func__, retval); - } else if (mddata_updated) - goto _cyttsp4_startup_tma400_restart; - } - - } - - dev_vdbg(ts->dev, - "%s: enter operational mode\n", __func__); - /* mode=operational mode, state = active_state */ - retval = _cyttsp4_set_mode(ts, CY_OPERATE_MODE); - if (retval < 0) { - dev_err(ts->dev, - "%s: Fail set operational mode 2 (r=%d)\n", - __func__, retval); - goto _cyttsp4_startup_tma400_exit; - } - - if (ts->was_suspended) { - ts->was_suspended = false; - retval = _cyttsp4_enter_sleep(ts); - if (retval < 0) { - dev_err(ts->dev, - "%s: fail resume sleep r=%d\n", - __func__, retval); - } - } else { -#ifdef CY_USE_WATCHDOG - _cyttsp4_start_wd_timer(ts); -#endif - } -_cyttsp4_startup_tma400_exit: - ts->starting_up = false; - return retval; -} -#endif /* --CY_USE_TMA400 */ - -#ifdef CY_USE_TMA884 -#define CY_IRQ_DEASSERT 1 -#define CY_IRQ_ASSERT 0 -static int _cyttsp4_startup(struct cyttsp4 *ts) -{ - int retval = 0; - int i = 0; - u8 pdata_crc[2]; - u8 ic_crc[2]; - bool upgraded = false; - bool mddata_updated = false; - bool wrote_sysinfo_regs = false; - bool wrote_settings = false; - - memset(&ts->test, 0, sizeof(struct cyttsp4_test_mode)); -#ifdef CY_USE_WATCHDOG - _cyttsp4_stop_wd_timer(ts); -#endif -_cyttsp4_startup_start: - memset(pdata_crc, 0, sizeof(pdata_crc)); - memset(ic_crc, 0, sizeof(ic_crc)); - dev_vdbg(ts->dev, - "%s: enter driver_state=%d\n", __func__, ts->driver_state); - _cyttsp4_change_state(ts, CY_BL_STATE); - - retval = _cyttsp4_reset(ts); - if (retval < 0) { - dev_err(ts->dev, - "%s: Fail reset device r=%d\n", __func__, retval); - /* continue anyway in case device was already in bootloader */ - } - - /* wait for interrupt to set ready completion */ - retval = _cyttsp4_wait_int(ts, CY_HALF_SEC_TMO_MS); - if (retval < 0) { - dev_err(ts->dev, - "%s: Fail waiting for bootloader interrupt\n", - __func__); - goto _cyttsp4_startup_exit; - } - - INIT_COMPLETION(ts->si_int_running); - _cyttsp4_change_state(ts, CY_EXIT_BL_STATE); - ts->switch_flag = true; - retval = _cyttsp4_wait_si_int(ts, CY_TEN_SEC_TMO_MS); - if (retval < 0) { - dev_err(ts->dev, - "%s: Fail wait switch to Sysinfo r=%d\n", - __func__, retval); - /* continue anyway in case sync missed */ - } - if (ts->driver_state != CY_SYSINFO_STATE) - _cyttsp4_change_state(ts, CY_SYSINFO_STATE); - else - _cyttsp4_pr_state(ts); - - /* - * TODO: remove this wait for toggle high when - * startup from ES10 firmware is no longer required - */ - /* Wait for IRQ to toggle high */ - dev_vdbg(ts->dev, - "%s: wait for irq toggle high\n", __func__); - retval = -ETIMEDOUT; - for (i = 0; i < CY_DELAY_MAX * 10 * 5; i++) { - if (ts->platform_data->irq_stat() == CY_IRQ_DEASSERT) { - retval = 0; - break; - } - mdelay(CY_DELAY_DFLT); - } - if (retval < 0) { - dev_err(ts->dev, - "%s: timeout waiting for irq to de-assert\n", - __func__); - goto _cyttsp4_startup_exit; - } - - dev_vdbg(ts->dev, - "%s: read sysinfo 1\n", __func__); - memset(&ts->sysinfo_data, 0, - sizeof(struct cyttsp4_sysinfo_data)); - retval = _cyttsp4_read_block_data(ts, CY_REG_BASE, - sizeof(struct cyttsp4_sysinfo_data), &ts->sysinfo_data, - ts->platform_data->addr[CY_TCH_ADDR_OFS], true); - if (retval < 0) { - dev_err(ts->dev, - "%s: Fail to switch from Bootloader " - "to Application r=%d\n", - __func__, retval); - - _cyttsp4_change_state(ts, CY_BL_STATE); - - if (upgraded) { - dev_err(ts->dev, - "%s: app failed to launch after" - " platform firmware upgrade\n", __func__); - retval = -EIO; - goto _cyttsp4_startup_exit; - } - -#ifdef CY_AUTO_LOAD_FW - dev_info(ts->dev, - "%s: attempting to reflash IC...\n", __func__); - if (ts->platform_data->fw->img == NULL || - ts->platform_data->fw->size == 0) { - dev_err(ts->dev, - "%s: no platform firmware available" - " for reflashing\n", __func__); - _cyttsp4_change_state(ts, CY_INVALID_STATE); - retval = -ENODATA; - goto _cyttsp4_startup_exit; - } - retval = _cyttsp4_load_app(ts, - ts->platform_data->fw->img, - ts->platform_data->fw->size); - if (retval) { - dev_err(ts->dev, - "%s: failed to reflash IC (r=%d)\n", - __func__, retval); - _cyttsp4_change_state(ts, CY_INVALID_STATE); - retval = -EIO; - goto _cyttsp4_startup_exit; - } - upgraded = true; - dev_info(ts->dev, - "%s: resetting IC after reflashing\n", __func__); - goto _cyttsp4_startup_start; /* Reset the part */ -#endif /* --CY_AUTO_LOAD_FW */ - } - - /* - * read system information registers - * get version numbers and fill sysinfo regs - */ - dev_vdbg(ts->dev, - "%s: Read Sysinfo regs and get version numbers\n", __func__); - retval = _cyttsp4_get_sysinfo_regs(ts); - if (retval < 0) { - dev_err(ts->dev, - "%s: Read Block fail -get sys regs (r=%d)\n", - __func__, retval); - _cyttsp4_change_state(ts, CY_IDLE_STATE); - goto _cyttsp4_startup_exit; - } - -#ifdef CY_AUTO_LOAD_FW - retval = _cyttsp4_boot_loader(ts, &upgraded); - if (retval < 0) { - dev_err(ts->dev, - "%s: fail boot loader r=%d)\n", - __func__, retval); - _cyttsp4_change_state(ts, CY_IDLE_STATE); - goto _cyttsp4_startup_exit; - } - if (upgraded) - goto _cyttsp4_startup_start; -#endif /* --CY_AUTO_LOAD_FW */ - - if (!wrote_sysinfo_regs) { - dev_vdbg(ts->dev, - "%s: Set Sysinfo regs\n", __func__); - retval = _cyttsp4_set_mode(ts, CY_SYSINFO_MODE); - if (retval < 0) { - dev_err(ts->dev, - "%s: Set SysInfo Mode fail r=%d\n", - __func__, retval); - _cyttsp4_change_state(ts, CY_IDLE_STATE); - goto _cyttsp4_startup_exit; - } - retval = _cyttsp4_set_sysinfo_regs(ts, &mddata_updated); - if (retval < 0) { - dev_err(ts->dev, - "%s: Set SysInfo Regs fail r=%d\n", - __func__, retval); - _cyttsp4_change_state(ts, CY_IDLE_STATE); - goto _cyttsp4_startup_exit; - } else - wrote_sysinfo_regs = true; - } - - dev_vdbg(ts->dev, - "%s: enter operational mode\n", __func__); - retval = _cyttsp4_set_mode(ts, CY_OPERATE_MODE); - if (retval < 0) { - _cyttsp4_change_state(ts, CY_IDLE_STATE); - dev_err(ts->dev, - "%s: Fail set operational mode (r=%d)\n", - __func__, retval); - goto _cyttsp4_startup_exit; - } else { -#ifdef CY_AUTO_LOAD_TOUCH_PARAMS - /* Calculate settings CRC from platform settings */ - dev_vdbg(ts->dev, - "%s: Calculate settings CRC and get IC CRC\n", - __func__); - retval = _cyttsp4_calc_settings_crc(ts, - &pdata_crc[0], &pdata_crc[1]); - if (retval < 0) { - dev_err(ts->dev, - "%s: Unable to calculate settings CRC\n", - __func__); - goto _cyttsp4_startup_exit; - } - - /* Get settings CRC from touch IC */ - retval = _cyttsp4_get_ic_crc(ts, CY_TCH_PARM_EBID, - &ic_crc[0], &ic_crc[1]); - if (retval < 0) { - dev_err(ts->dev, - "%s: Unable to get settings CRC\n", __func__); - goto _cyttsp4_startup_exit; - } - - /* Compare CRC values */ - dev_vdbg(ts->dev, - "%s: PDATA CRC = 0x%02X%02X, IC CRC = 0x%02X%02X\n", - __func__, pdata_crc[0], pdata_crc[1], - ic_crc[0], ic_crc[1]); - - if ((pdata_crc[0] == ic_crc[0]) && - (pdata_crc[1] == ic_crc[1])) - goto _cyttsp4_startup_settings_valid; - - /* Update settings */ - dev_info(ts->dev, - "%s: Updating IC settings...\n", __func__); - - if (wrote_settings) { - dev_err(ts->dev, - "%s: Already updated IC settings\n", - __func__); - goto _cyttsp4_startup_settings_valid; - } - - retval = _cyttsp4_set_op_params(ts, pdata_crc[0], pdata_crc[1]); - if (retval < 0) { - dev_err(ts->dev, - "%s: Set Operational Params fail r=%d\n", - __func__, retval); - goto _cyttsp4_startup_exit; - } - - wrote_settings = true; -#else - wrote_settings = false; -#endif /* --CY_AUTO_LOAD_TOUCH_PARAMS */ - } - -#ifdef CY_AUTO_LOAD_TOUCH_PARAMS -_cyttsp4_startup_settings_valid: -#endif /* --CY_AUTO_LOAD_TOUCH_PARAMS */ - if (mddata_updated || wrote_settings) { - dev_info(ts->dev, - "%s: Resetting IC after writing settings\n", - __func__); - mddata_updated = false; - wrote_settings = false; - goto _cyttsp4_startup_start; /* Reset the part */ - } - dev_vdbg(ts->dev, - "%s: enable handshake\n", __func__); - retval = _cyttsp4_handshake_enable(ts); - if (retval < 0) - dev_err(ts->dev, - "%s: fail enable handshake r=%d", __func__, retval); - - _cyttsp4_change_state(ts, CY_ACTIVE_STATE); - - if (ts->was_suspended) { - ts->was_suspended = false; - retval = _cyttsp4_enter_sleep(ts); - if (retval < 0) { - dev_err(ts->dev, - "%s: fail resume sleep r=%d\n", - __func__, retval); - } - } else { -#ifdef CY_USE_WATCHDOG - _cyttsp4_start_wd_timer(ts); -#endif - } - -_cyttsp4_startup_exit: - return retval; -} -#endif /* --CY_USE_TMA884 */ - -static irqreturn_t cyttsp4_irq(int irq, void *handle) -{ - struct cyttsp4 *ts = handle; - u8 rep_stat = 0; - int retval = 0; - -#if TOUCH_BOOST - if (false == boost) { - omap_cpufreq_min_limit(DVFS_LOCK_ID_TSP, 800000); - boost = true; - } -#endif - - dev_vdbg(ts->dev, - "%s: GOT IRQ ps=%d\n", __func__, ts->driver_state); - mutex_lock(&ts->data_lock); - - dev_vdbg(ts->dev, - "%s: DO IRQ ps=%d\n", __func__, ts->driver_state); - - switch (ts->driver_state) { - case CY_BL_STATE: - case CY_CMD_STATE: - complete(&ts->int_running); -#ifdef CY_USE_LEVEL_IRQ - udelay(1000); -#endif - break; - case CY_SYSINFO_STATE: - complete(&ts->si_int_running); -#ifdef CY_USE_LEVEL_IRQ - udelay(500); -#endif - break; - case CY_EXIT_BL_STATE: -#ifdef CY_USE_LEVEL_IRQ - udelay(1000); -#endif - if (ts->switch_flag == true) { - ts->switch_flag = false; - retval = _cyttsp4_ldr_exit(ts); - if (retval < 0) { - dev_err(ts->dev, - "%s: Fail bl exit r=%d\n", - __func__, retval); - } else - ts->driver_state = CY_SYSINFO_STATE; - } - break; - case CY_SLEEP_STATE: - dev_vdbg(ts->dev, - "%s: Attempt to process touch after enter sleep or" - " unexpected wake event\n", __func__); - retval = _cyttsp4_wakeup(ts); /* in case its really asleep */ - if (retval < 0) { - dev_err(ts->dev, - "%s: wakeup fail r=%d\n", - __func__, retval); - _cyttsp4_pr_state(ts); - _cyttsp4_queue_startup(ts, true); - break; - } - /* Put the part back to sleep */ - retval = _cyttsp4_enter_sleep(ts); - if (retval < 0) { - dev_err(ts->dev, - "%s: fail resume sleep r=%d\n", - __func__, retval); - _cyttsp4_pr_state(ts); - _cyttsp4_queue_startup(ts, true); - } - break; - case CY_IDLE_STATE: - if (ts->xy_mode == NULL) { - /* initialization is not complete; invalid pointers */ - break; - } - - /* device now available; signal initialization */ - dev_info(ts->dev, - "%s: Received IRQ in IDLE state\n", - __func__); - /* Try to determine the IC's current state */ - retval = _cyttsp4_load_status_regs(ts); - if (retval < 0) { - dev_err(ts->dev, - "%s: Still unable to access IC after IRQ r=%d\n", - __func__, retval); - _cyttsp4_queue_startup(ts, false); - break; - } - rep_stat = ts->xy_mode[ts->si_ofs.rep_ofs + 1]; - if (IS_BOOTLOADERMODE(rep_stat)) { - dev_info(ts->dev, - "%s: BL mode found in IDLE state\n", - __func__); - _cyttsp4_queue_startup(ts, false); - break; - } - dev_err(ts->dev, - "%s: interrupt received in IDLE state -" - " try processing touch\n", - __func__); - _cyttsp4_change_state(ts, CY_ACTIVE_STATE); -#ifdef CY_USE_WATCHDOG - _cyttsp4_start_wd_timer(ts); -#endif - retval = _cyttsp4_xy_worker(ts); - if (retval < 0) { - dev_err(ts->dev, - "%s: xy_worker IDLE fail r=%d\n", - __func__, retval); - _cyttsp4_queue_startup(ts, false); - break; - } - -#ifdef CY_USE_LEVEL_IRQ - udelay(500); -#endif - break; - case CY_READY_STATE: - complete(&ts->ready_int_running); - /* do not break; do worker */ - case CY_ACTIVE_STATE: - if (ts->test.cur_mode == CY_TEST_MODE_CAT) { - complete(&ts->int_running); -#ifdef CY_USE_LEVEL_IRQ - udelay(500); -#endif - } else { - /* process the touches */ - retval = _cyttsp4_xy_worker(ts); - if (retval < 0) { - dev_err(ts->dev, - "%s: XY Worker fail r=%d\n", - __func__, retval); - _cyttsp4_queue_startup(ts, false); - } - } - break; - default: - break; - } - - mutex_unlock(&ts->data_lock); - dev_vdbg(ts->dev, - "%s: DONE IRQ ps=%d\n", __func__, ts->driver_state); - - return IRQ_HANDLED; -} - -static void _cyttsp4_file_init(struct cyttsp4 *ts) -{ - - if (device_create_file(ts->dev, &dev_attr_drv_stat)) - dev_err(ts->dev, - "%s: Error, could not create drv_stat\n", __func__); - - if (device_create_file(ts->dev, &dev_attr_drv_ver)) - dev_err(ts->dev, - "%s: Error, could not create drv_ver\n", __func__); - -#if defined(CY_USE_FORCE_LOAD) || defined(CONFIG_TOUCHSCREEN_DEBUG) - if (device_create_file(ts->dev, &dev_attr_ic_reflash)) - dev_err(ts->dev, - "%s: Error, could not create ic_reflash\n", __func__); -#endif - - - if (device_create_file(ts->dev, &dev_attr_ic_ver)) - dev_err(ts->dev, - "%s: Cannot create ic_ver\n", __func__); - -#ifdef CY_USE_REG_ACCESS - if (device_create_file(ts->dev, &dev_attr_drv_rw_regid)) - dev_err(ts->dev, - "%s: Cannot create drv_rw_regid\n", __func__); - - if (device_create_file(ts->dev, &dev_attr_drv_rw_reg_data)) - dev_err(ts->dev, - "%s: Cannot create drv_rw_reg_data\n", __func__); -#endif - - return; -} - -static void _cyttsp4_file_free(struct cyttsp4 *ts) -{ - device_remove_file(ts->dev, &dev_attr_drv_ver); - device_remove_file(ts->dev, &dev_attr_drv_stat); - device_remove_file(ts->dev, &dev_attr_ic_ver); -#if defined(CY_USE_FORCE_LOAD) || defined(CONFIG_TOUCHSCREEN_DEBUG) - device_remove_file(ts->dev, &dev_attr_ic_reflash); -#endif -#ifdef CY_USE_REG_ACCESS - device_remove_file(ts->dev, &dev_attr_drv_rw_regid); - device_remove_file(ts->dev, &dev_attr_drv_rw_reg_data); -#endif -} - -static int cyttsp4_open(struct input_dev *dev) -{ - int retval = 0; - - struct cyttsp4 *ts = input_get_drvdata(dev); - dev_dbg(ts->dev, "%s: Open call ts=%p\n", __func__, ts); - mutex_lock(&ts->data_lock); - if (!ts->powered) { - /* - * execute complete startup procedure. After this - * call the device is in active state and the worker - * is running - */ - retval = _cyttsp4_startup(ts); - - /* powered if no hard failure */ - if (retval < 0) { - ts->powered = false; - _cyttsp4_change_state(ts, CY_IDLE_STATE); - dev_err(ts->dev, - "%s: startup fail at power on r=%d\n", - __func__, retval); - } else - ts->powered = true; - - dev_info(ts->dev, - "%s: Powered ON(%d) r=%d\n", - __func__, (int)ts->powered, retval); - } - mutex_unlock(&ts->data_lock); - return 0; -} - -static void cyttsp4_close(struct input_dev *dev) -{ - /* - * close() normally powers down the device - * this call simply returns unless power - * to the device can be controlled by the driver - */ - return; -} - -void cyttsp4_core_release(void *handle) -{ - struct cyttsp4 *ts = handle; - - dev_dbg(ts->dev, "%s: Release call ts=%p\n", - __func__, ts); - if (ts == NULL) { - dev_err(ts->dev, - "%s: Null context pointer on driver release\n", - __func__); - goto cyttsp4_core_release_exit; - } - -#ifdef FACTORY_TESTING - kfree(ts->node_data->reference_data); - kfree(ts->node_data->intensity_data); - kfree(ts->node_data->cm_abs_data); - kfree(ts->node_data->cm_delta_data); - kfree(ts->node_data); - kfree(ts->factory_data); -#endif - -#ifdef CONFIG_HAS_EARLYSUSPEND - unregister_early_suspend(&ts->early_suspend); -#endif - _cyttsp4_file_free(ts); - if (mutex_is_locked(&ts->data_lock)) - mutex_unlock(&ts->data_lock); - mutex_destroy(&ts->data_lock); - free_irq(ts->irq, ts); - input_unregister_device(ts->input); - if (ts->cyttsp4_wq) { - destroy_workqueue(ts->cyttsp4_wq); - ts->cyttsp4_wq = NULL; - } - - if (ts->sysinfo_ptr.cydata != NULL) - kfree(ts->sysinfo_ptr.cydata); - if (ts->sysinfo_ptr.test != NULL) - kfree(ts->sysinfo_ptr.test); - if (ts->sysinfo_ptr.pcfg != NULL) - kfree(ts->sysinfo_ptr.pcfg); - if (ts->sysinfo_ptr.opcfg != NULL) - kfree(ts->sysinfo_ptr.opcfg); - if (ts->sysinfo_ptr.ddata != NULL) - kfree(ts->sysinfo_ptr.ddata); - if (ts->sysinfo_ptr.mdata != NULL) - kfree(ts->sysinfo_ptr.mdata); - if (ts->xy_mode != NULL) - kfree(ts->xy_mode); - if (ts->xy_data != NULL) - kfree(ts->xy_data); - if (ts->xy_data_touch1 != NULL) - kfree(ts->xy_data_touch1); - -#if TOUCH_BOOST - del_timer_sync(&ts->dvfs_timer); -#endif - - kfree(ts); -cyttsp4_core_release_exit: - return; -} -EXPORT_SYMBOL_GPL(cyttsp4_core_release); - -void *cyttsp4_core_init(struct cyttsp4_bus_ops *bus_ops, - struct device *dev, int irq, char *name) -{ - unsigned long irq_flags = 0; - int i = 0; - int min = 0; - int max = 0; - u16 signal = 0; - int retval = 0; - struct input_dev *input_device = NULL; - struct cyttsp4 *ts = NULL; -#ifdef FACTORY_TESTING - struct device *fac_dev_ts; - struct factory_data *factory_data; - struct node_data *node_data; - u32 rx, tx; -#endif - - if (dev == NULL) { - pr_err("%s: Error, dev pointer is Null\n", __func__); - goto error_alloc_data; - } - - if (bus_ops == NULL) { - dev_err(dev, - "%s: Error, bus_ops Pointer is Null\n", __func__); - goto error_alloc_data; - } - ts = kzalloc(sizeof(*ts), GFP_KERNEL); - if (ts == NULL) { - dev_err(dev, - "%s: Error, kzalloc context memory\n", __func__); - goto error_alloc_data; - } - -#if defined(CY_USE_FORCE_LOAD) || defined(CONFIG_TOUCHSCREEN_DEBUG) - ts->fwname = kzalloc(CY_BL_FW_NAME_SIZE, GFP_KERNEL); - if (ts->fwname == NULL) { - dev_err(dev, - "%s: Error, kzalloc fwname\n", __func__); - goto error_alloc_failed; - } -#endif - - ts->cyttsp4_wq = - create_singlethread_workqueue("cyttsp4_resume_startup_wq"); - if (ts->cyttsp4_wq == NULL) { - dev_err(dev, - "%s: No memory for cyttsp4_resume_startup_wq\n", - __func__); - goto error_alloc_failed; - } - - ts->driver_state = CY_INVALID_STATE; - ts->current_mode = CY_MODE_BOOTLOADER; - ts->powered = false; - ts->was_suspended = false; - ts->switch_flag = false; - ts->soft_reset_asserted = false; - ts->num_prv_tch = 0; - - ts->xy_data = NULL; - ts->xy_mode = NULL; - ts->xy_data_touch1 = NULL; - ts->btn_rec_data = NULL; - memset(&ts->test, 0, sizeof(struct cyttsp4_test_mode)); - - ts->dev = dev; - ts->bus_ops = bus_ops; - ts->platform_data = dev->platform_data; - if (ts->platform_data == NULL) { - dev_err(ts->dev, - "%s: Error, platform data is Null\n", __func__); - goto error_alloc_failed; - } - - if (ts->platform_data->frmwrk == NULL) { - dev_err(ts->dev, - "%s: Error, platform data framework is Null\n", - __func__); - goto error_alloc_failed; - } - - if (ts->platform_data->frmwrk->abs == NULL) { - dev_err(ts->dev, - "%s: Error, platform data framework array is Null\n", - __func__); - goto error_alloc_failed; - } - - mutex_init(&ts->data_lock); - init_completion(&ts->int_running); - init_completion(&ts->si_int_running); - init_completion(&ts->ready_int_running); - ts->flags = ts->platform_data->flags; -#if defined(CY_USE_FORCE_LOAD) || defined(CONFIG_TOUCHSCREEN_DEBUG) - ts->waiting_for_fw = false; -#endif - -#ifdef CY_USE_TMA400 - ts->max_config_bytes = CY_TMA400_MAX_BYTES; -#endif /* --CY_USE_TMA400 */ -#ifdef CY_USE_TMA884 - ts->max_config_bytes = CY_TMA884_MAX_BYTES; -#endif /* --CY_USE_TMA884 */ - - ts->irq = irq; - if (ts->irq <= 0) { - dev_vdbg(ts->dev, - "%s: Error, failed to allocate irq\n", __func__); - goto error_init; - } - - /* Create the input device and register it. */ - dev_vdbg(ts->dev, - "%s: Create the input device and register it\n", __func__); - input_device = input_allocate_device(); - if (input_device == NULL) { - dev_err(ts->dev, - "%s: Error, failed to allocate input device\n", - __func__); - goto error_init; - } - - ts->input = input_device; - input_device->name = name; - snprintf(ts->phys, sizeof(ts->phys)-1, "%s", dev_name(dev)); - input_device->phys = ts->phys; - input_device->dev.parent = ts->dev; - ts->bus_type = bus_ops->dev->bus; -#ifdef CY_USE_WATCHDOG - INIT_WORK(&ts->work, cyttsp4_timer_watchdog); - setup_timer(&ts->timer, cyttsp4_timer, (unsigned long)ts); -#endif - - dev_vdbg(ts->dev, - "%s: Initialize irq\n", __func__); -#ifdef CY_USE_LEVEL_IRQ - irq_flags = IRQF_TRIGGER_LOW | IRQF_ONESHOT; -#else - irq_flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT; -#endif - retval = request_threaded_irq(ts->irq, NULL, cyttsp4_irq, - irq_flags, ts->input->name, ts); - if (retval < 0) { - dev_err(ts->dev, - "%s: failed to init irq r=%d name=%s\n", - __func__, retval, ts->input->name); - ts->irq_enabled = false; - goto error_init; - } else { - ts->irq_enabled = true; - } - - - input_device->open = cyttsp4_open; - input_device->close = cyttsp4_close; - input_set_drvdata(input_device, ts); - dev_set_drvdata(dev, ts); - - dev_vdbg(ts->dev, - "%s: Initialize event signals\n", __func__); - __set_bit(EV_ABS, input_device->evbit); - __set_bit(EV_KEY, input_device->evbit); - bitmap_fill(input_device->absbit, ABS_MAX); - /* key led */ - __set_bit(EV_LED, input_device->evbit); - __set_bit(LED_MISC, input_device->ledbit); - - /* ICS touch down button press signal */ - __set_bit(BTN_TOUCH, input_device->keybit); - __set_bit(KEY_BACK, input_device->keybit); - __set_bit(KEY_MENU, input_device->keybit); - - __set_bit(INPUT_PROP_DIRECT, input_device->propbit); - - for (i = 0; i < (ts->platform_data->frmwrk->size / CY_NUM_ABS_SET); - i++) { - signal = ts->platform_data->frmwrk->abs[ - (i * CY_NUM_ABS_SET) + CY_SIGNAL_OST]; - if (signal != CY_IGNORE_VALUE) { - min = ts->platform_data->frmwrk->abs - [(i * CY_NUM_ABS_SET) + CY_MIN_OST]; - max = ts->platform_data->frmwrk->abs - [(i * CY_NUM_ABS_SET) + CY_MAX_OST]; - if (i == CY_ABS_ID_OST) { - /* shift track ids down to start at 0 */ - max = max - min; - min = min - min; - } - input_set_abs_params(input_device, - signal, - min, - max, - ts->platform_data->frmwrk->abs[ - (i * CY_NUM_ABS_SET) + CY_FUZZ_OST], - ts->platform_data->frmwrk->abs[ - (i * CY_NUM_ABS_SET) + CY_FLAT_OST]); - dev_vdbg(ts->dev, - "%s: s=%02X min=%d max=%d fuzz=%d flat=%d\n", - __func__, signal, min, max, - ts->platform_data->frmwrk->abs[ - (i * CY_NUM_ABS_SET) + CY_FUZZ_OST], - ts->platform_data->frmwrk->abs[ - (i * CY_NUM_ABS_SET) + CY_FLAT_OST]); - - } - } - -#ifdef CY_USE_DEBUG_TOOLS - if (ts->flags & CY_FLAG_FLIP) { - input_set_abs_params(input_device, - ABS_MT_POSITION_X, - ts->platform_data->frmwrk->abs - [(CY_ABS_Y_OST * CY_NUM_ABS_SET) + CY_MIN_OST], - ts->platform_data->frmwrk->abs - [(CY_ABS_Y_OST * CY_NUM_ABS_SET) + CY_MAX_OST], - ts->platform_data->frmwrk->abs - [(CY_ABS_Y_OST * CY_NUM_ABS_SET) + CY_FUZZ_OST], - ts->platform_data->frmwrk->abs - [(CY_ABS_Y_OST * CY_NUM_ABS_SET) + CY_FLAT_OST]); - - input_set_abs_params(input_device, - ABS_MT_POSITION_Y, - ts->platform_data->frmwrk->abs - [(CY_ABS_X_OST * CY_NUM_ABS_SET) + CY_MIN_OST], - ts->platform_data->frmwrk->abs - [(CY_ABS_X_OST * CY_NUM_ABS_SET) + CY_MAX_OST], - ts->platform_data->frmwrk->abs - [(CY_ABS_X_OST * CY_NUM_ABS_SET) + CY_FUZZ_OST], - ts->platform_data->frmwrk->abs - [(CY_ABS_X_OST * CY_NUM_ABS_SET) + CY_FLAT_OST]); - } -#endif /* --CY_USE_DEBUG_TOOLS */ - - input_set_events_per_packet(input_device, 6 * CY_NUM_TCH_ID); - - retval = input_register_device(input_device); - if (retval < 0) { - dev_err(ts->dev, - "%s: Error, failed to register input device r=%d\n", - __func__, retval); - goto error_init; - } - - /* add /sys files */ - _cyttsp4_file_init(ts); - -#if TOUCH_BOOST - setup_timer(&ts->dvfs_timer, timer_cb, 0); -#endif - -#ifdef FACTORY_TESTING - node_data = kzalloc(sizeof(struct node_data), GFP_KERNEL); - if (unlikely(node_data == NULL)) { - retval = -ENOMEM; - goto err_alloc_node_data_failed; - } - factory_data = kzalloc(sizeof(struct factory_data), GFP_KERNEL); - if (unlikely(factory_data == NULL)) { - retval = -ENOMEM; - goto err_alloc_factory_data_failed; - } - - INIT_LIST_HEAD(&factory_data->cmd_list_head); - for (i = 0; i < ARRAY_SIZE(tsp_cmds); i++) - list_add_tail(&tsp_cmds[i].list, &factory_data->cmd_list_head); - - mutex_init(&factory_data->cmd_lock); - factory_data->cmd_is_running = false; - - fac_dev_ts = device_create(sec_class, NULL, 0, ts, "tsp"); - if (!fac_dev_ts) - pr_err("[TSP_FACTORY] Failed to create fac tsp dev\n"); - - if (sysfs_create_group(&fac_dev_ts->kobj, &touchscreen_attr_group)) - pr_err("[TSP_FACTORY] Failed to create sysfs (touchscreen_attr_group).\n"); - - ts->factory_data = factory_data; - ts->node_data = node_data; - -#endif - -#ifdef CONFIG_HAS_EARLYSUSPEND - ts->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1; - ts->early_suspend.suspend = cyttsp4_early_suspend; - ts->early_suspend.resume = cyttsp4_late_resume; - register_early_suspend(&ts->early_suspend); -#endif - - INIT_WORK(&ts->cyttsp4_resume_startup_work, cyttsp4_ts_work_func); - - goto no_error; - -#ifdef FACTORY_TESTING - -err_alloc_factory_data_failed: - pr_err("tsp: ts_probe: err_alloc_factory_data failed.\n"); - -err_alloc_node_data_failed: - pr_err("tsp: ts_probe: err_alloc_node_data failed.\n"); - kfree(ts->node_data->reference_data); - kfree(ts->node_data->intensity_data); - kfree(ts->node_data->cm_abs_data); - kfree(ts->node_data->cm_delta_data); - kfree(ts->node_data); - -#endif - -error_init: - mutex_destroy(&ts->data_lock); - if (ts->cyttsp4_wq) { - destroy_workqueue(ts->cyttsp4_wq); - ts->cyttsp4_wq = NULL; - } -error_alloc_failed: - if (ts != NULL) { - kfree(ts); - ts = NULL; - } -error_alloc_data: - dev_err(ts->dev, - "%s: Failed Initialization\n", __func__); -no_error: - return ts; -} -EXPORT_SYMBOL_GPL(cyttsp4_core_init); - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Cypress TrueTouch(R) Standard touchscreen driver core"); -MODULE_AUTHOR("Cypress"); |