diff options
Diffstat (limited to 'drivers/input/touchscreen/msg2138.c')
| -rw-r--r-- | drivers/input/touchscreen/msg2138.c | 4581 |
1 files changed, 4581 insertions, 0 deletions
diff --git a/drivers/input/touchscreen/msg2138.c b/drivers/input/touchscreen/msg2138.c new file mode 100644 index 00000000..efa1e76d --- /dev/null +++ b/drivers/input/touchscreen/msg2138.c @@ -0,0 +1,4581 @@ +/* + * Driver for Pixcir I2C touchscreen controllers. + * + * Copyright (C) 2010-2011 Pixcir, Inc. + * + * pixcir_i2c_ts.c V3.ss0 from v3.0 support TangoC solution and remove the previous soltutions + * + * pixcir_i2c_ts.c V3.1 Add bootloader function 7 + * Add RESET_TP 9 + * Add ENABLE_IRQ 10 + * Add DISABLE_IRQ 11 + * Add BOOTLOADER_STU 16 + * Add ATTB_VALUE 17 + * Add Write/Read Interface for APP software + * + * pixcir_i2c_ts.c V3.2.0A for INT_MODE 0x0A + * arrange to pixcir 10 slot + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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 library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <linux/i2c.h> +#include <linux/input.h> +#include <linux/gpio.h> +#include <linux/earlysuspend.h> +#include <linux/interrupt.h> +#include <linux/delay.h> +#include <linux/miscdevice.h> +#include <linux/firmware.h> +#include <linux/platform_device.h> + +#include <linux/slab.h> +#include <linux/miscdevice.h> +#include <linux/module.h> +#include <linux/mutex.h> +#include <linux/mm.h> +#include <linux/device.h> +#include <linux/interrupt.h> +#include <linux/delay.h> +#include <linux/sysctl.h> +#include <linux/input/mt.h> +#include <asm/uaccess.h> + +#include <linux/sched.h> +#include <linux/kthread.h> +#include <linux/completion.h> +#include <linux/err.h> + +#include <linux/regulator/consumer.h> +#include <linux/i2c/msg2138.h> +#include <soc/sprd/regulator.h> +#include <linux/fs.h> +#include <soc/sprd/board.h> +#ifdef CONFIG_HAS_EARLYSUSPEND +#include <linux/earlysuspend.h> +#endif +#if defined(CONFIG_I2C_SPRD) || defined(CONFIG_I2C_SPRD_V1) +#include <soc/sprd/i2c-sprd.h> +#endif + +#include <linux/of_device.h> +#include <linux/of_address.h> +#include <linux/of_gpio.h> + +/*********************************Bee-0928-TOP****************************************/ +//#define SYSFS_DEBUG //cg,20130929 +//#define PIXCIR_DEBUG +//#define PIXCIR_CQ_CALL 0 +#ifdef PIXCIR_DEBUG +#define PIXCIR_DBG(format, ...) \ + printk(KERN_INFO "PIXCIR_TS " format "\n", ## __VA_ARGS__) +#define TPD_DEBUG(format, ...) \ + printk(KERN_INFO "PIXCIR_TS " format "\n", ## __VA_ARGS__) +#else +#define PIXCIR_DBG(format, ...) +#define TPD_DEBUG(format, ...) +#endif + +#define USE_WAIT_QUEUE 1 +#define USE_THREADED_IRQ 0 +#define USE_WORK_QUEUE 0 + +#define TOUCH_VIRTUAL_KEYS +//#define TP_X_CHANGE +#define TP_XY_CHANGE 0 +#define SLAVE_ADDR 0x48 +#define BOOTLOADER_ADDR 0x5d + +#ifndef I2C_MAJOR +#define I2C_MAJOR 125 +#endif + +#define I2C_MINORS 256 +#define CALIBRATION_FLAG 1 +#define BOOTLOADER 7 +#define RESET_TP 9 +#define ENABLE_IRQ 10 +#define DISABLE_IRQ 11 +#define BOOTLOADER_STU 16 +#define ATTB_VALUE 17 +#define MAX_FINGER_NUM 5 +#define X_OFFSET 30 +#define Y_OFFSET 40 +#define TPD_OK 0 + +#define TPD_REG_BASE 0x00 +#define TPD_SOFT_RESET_MODE 0x01 +#define TPD_OP_MODE 0x00 +#define TPD_LOW_PWR_MODE 0x04 +#define TPD_SYSINFO_MODE 0x10 +#define GET_HSTMODE(reg) ((reg & 0x70) >> 4) // in op mode or not +#define GET_BOOTLOADERMODE(reg) ((reg & 0x10) >> 4) // in bl mode +//#define __FIRMWARE_UPDATE__ +#define REG_RT_PRIO(x) ((x) | 0x10000000) +#define RTPM_PRIO_TPD REG_RT_PRIO(4) + +#if USE_WAIT_QUEUE +static struct task_struct *thread = NULL; +static DECLARE_WAIT_QUEUE_HEAD(waiter); +static int tpd_flag = 0; +#endif + +struct pixcir_i2c_ts_data { + struct i2c_client *client; + struct input_dev *input; +#if USE_WORK_QUEUE + struct work_struct pen_event_work; + struct workqueue_struct *ts_workqueue; +#endif +#ifdef CONFIG_HAS_EARLYSUSPEND + struct work_struct resume_work; + struct workqueue_struct *ts_resume_workqueue; + struct early_suspend early_suspend; +#endif + struct msg2138_ts_platform_data *platform_data; + //const struct pixcir_ts_platform_data *chip; + bool exiting; +}; + +static unsigned char bl_cmd[] = { + 0x00, 0xFF, 0xA5, + 0x00, 0x01, 0x02, + 0x03, 0x04, 0x05, + 0x06, 0x07 +}; + //exit bl mode +struct tpd_operation_data_t { + unsigned char hst_mode; + unsigned char tt_mode; + unsigned char tt_stat; + + unsigned char x1_M,x1_L; + unsigned char y1_M,y1_L; + unsigned char z1; + unsigned char evnt_id; + + unsigned char x2_M,x2_L; + unsigned char y2_M,y2_L; + unsigned char r_0d; + unsigned char gest_cnt; + unsigned char gest_id; +}; +struct tpd_bootloader_data_t { + unsigned char bl_file; + unsigned char bl_status; + unsigned char bl_error; + unsigned char blver_hi,blver_lo; + unsigned char bld_blver_hi,bld_blver_lo; + + unsigned char ttspver_hi,ttspver_lo; + unsigned char appid_hi,appid_lo; + unsigned char appver_hi,appver_lo; + + unsigned char cid_0; + unsigned char cid_1; + unsigned char cid_2; +}; +struct tpd_sysinfo_data_t { + unsigned char hst_mode; + unsigned char mfg_cmd; + unsigned char mfg_stat; + unsigned char cid[3]; + unsigned char tt_undef1; + + unsigned char uid[8]; + unsigned char bl_verh; + unsigned char bl_verl; + + unsigned char tts_verh; + unsigned char tts_verl; + + unsigned char app_idh; + unsigned char app_idl; + unsigned char app_verh; + unsigned char app_verl; + + unsigned char tt_undef2[6]; + unsigned char act_intrvl; + unsigned char tch_tmout; + unsigned char lp_intrvl; +}; +struct touch_info { + int x1, y1; + int x2, y2; + int x3, y3; + int p1, p2,p3; + int count; +}; + +struct i2c_dev +{ + struct list_head list; + struct i2c_adapter *adap; + struct device *dev; +}; + +static struct i2c_client * msg21xx_i2c_client; +static struct pixcir_i2c_ts_data *msg21xx_i2c_ts_data; +//static unsigned char status_reg = 0; +static int global_irq; +static struct i2c_driver pixcir_i2c_ts_driver; +static struct class *i2c_dev_class; +static int MS_TS_MSG21XX_X_MAX = 0; +static int MS_TS_MSG21XX_Y_MAX = 0; + +static LIST_HEAD( i2c_dev_list); +static DEFINE_SPINLOCK( i2c_dev_list_lock); + +static int suspend_flag; +static struct early_suspend pixcir_early_suspend; + +static ssize_t pixcir_set_calibrate(struct device* cd, struct device_attribute *attr, + const char* buf, size_t len); +static ssize_t pixcir_show_suspend(struct device* cd,struct device_attribute *attr, char* buf); +static ssize_t pixcir_store_suspend(struct device* cd, struct device_attribute *attr,const char* buf, size_t len); +static void pixcir_ts_suspend(struct early_suspend *handler); +static void pixcir_ts_resume(struct early_suspend *handler); + +//static struct tpd_operation_data_t g_operation_data; +static struct tpd_bootloader_data_t g_bootloader_data; +static struct tpd_sysinfo_data_t g_sysinfo_data; +#ifdef SYSFS_DEBUG +static char *cg_fw_version = NULL; +#endif //cg,20130929 + +#define CTP_ID_MSG21XX 1 +#define CTP_ID_MSG21XXA 2 +#define FW_ADDR_MSG21XX (0xC4>>1) +static int HalTscrCReadI2CSeq(u8 addr, u8* read_data, u16 size) +{ + //according to your platform. + int rc; + + struct i2c_msg msgs[] = + { + { + .addr = addr, + .flags = I2C_M_RD, + .len = size, + .buf = read_data, + }, + }; + + rc = i2c_transfer(msg21xx_i2c_client->adapter, msgs, 1); + if( rc < 0 ) + { + printk("HalTscrCReadI2CSeq error %d\n", rc); + } + return rc; +} + +static int HalTscrCDevWriteI2CSeq(u8 addr, u8* data, u16 size) +{ + //according to your platform. + int rc; + struct i2c_msg msgs[] = + { + { + .addr = addr, + .flags = 0, + .len = size, + .buf = data, + }, + }; + rc = i2c_transfer(msg21xx_i2c_client->adapter, msgs, 1); + if( rc < 0 ) + { + printk("HalTscrCDevWriteI2CSeq error %d,addr = %d\n", rc,addr); + } + return rc; +} + +#ifdef __FIRMWARE_UPDATE__ +#define FW_ADDR_MSG21XX_TP (0x4C>>1) +#define FW_UPDATE_ADDR_MSG21XX (0x92>>1) +#define TP_DEBUG printk//(x) //x// +#define DBUG printk//(x) //x +static char *fw_version = NULL; + +static u8 temp[94][1024]; +u8 Fmr_Loader[1024]; +u32 crc_tab[256]; +static u8 g_dwiic_info_data[1024]; // Buffer for info data +static int FwDataCnt; +struct class *firmware_class; +struct device *firmware_cmd_dev; + +static void dbbusDWIICEnterSerialDebugMode(void) +{ + u8 data[5]; + + // Enter the Serial Debug Mode + data[0] = 0x53; + data[1] = 0x45; + data[2] = 0x52; + data[3] = 0x44; + data[4] = 0x42; + HalTscrCDevWriteI2CSeq(FW_ADDR_MSG21XX, data, 5); +} + +static void dbbusDWIICStopMCU(void) +{ + u8 data[1]; + + // Stop the MCU + data[0] = 0x37; + HalTscrCDevWriteI2CSeq(FW_ADDR_MSG21XX, data, 1); +} + +static void dbbusDWIICIICUseBus(void) +{ + u8 data[1]; + + // IIC Use Bus + data[0] = 0x35; + HalTscrCDevWriteI2CSeq(FW_ADDR_MSG21XX, data, 1); +} + +static void dbbusDWIICIICReshape(void) +{ + u8 data[1]; + + // IIC Re-shape + data[0] = 0x71; + HalTscrCDevWriteI2CSeq(FW_ADDR_MSG21XX, data, 1); +} + +static void dbbusDWIICIICNotUseBus(void) +{ + u8 data[1]; + + // IIC Not Use Bus + data[0] = 0x34; + HalTscrCDevWriteI2CSeq(FW_ADDR_MSG21XX, data, 1); +} + +static void dbbusDWIICNotStopMCU(void) +{ + u8 data[1]; + + // Not Stop the MCU + data[0] = 0x36; + HalTscrCDevWriteI2CSeq(FW_ADDR_MSG21XX, data, 1); +} + +static void dbbusDWIICExitSerialDebugMode(void) +{ + u8 data[1]; + + // Exit the Serial Debug Mode + data[0] = 0x45; + HalTscrCDevWriteI2CSeq(FW_ADDR_MSG21XX, data, 1); + + // Delay some interval to guard the next transaction + udelay ( 150);//200 ); // delay about 0.2ms +} + +static void drvISP_EntryIspMode(void) +{ + u8 bWriteData[5] = + { + 0x4D, 0x53, 0x54, 0x41, 0x52 + }; + printk("\n******%s come in*******\n",__FUNCTION__); + HalTscrCDevWriteI2CSeq(FW_UPDATE_ADDR_MSG21XX, bWriteData, 5); + udelay ( 150 );//200 ); // delay about 0.1ms +} + +static u8 drvISP_Read(u8 n, u8* pDataToRead) //First it needs send 0x11 to notify we want to get flash data back. +{ + u8 Read_cmd = 0x11; + unsigned char dbbus_rx_data[2] = {0}; + HalTscrCDevWriteI2CSeq(FW_UPDATE_ADDR_MSG21XX, &Read_cmd, 1); + //msctpc_LoopDelay ( 1 ); // delay about 100us***** + udelay( 800 );//200); + if (n == 1) + { + HalTscrCReadI2CSeq(FW_UPDATE_ADDR_MSG21XX, &dbbus_rx_data[0], 2); + *pDataToRead = dbbus_rx_data[0]; + TP_DEBUG("dbbus=%d,%d===drvISP_Read=====\n",dbbus_rx_data[0],dbbus_rx_data[1]); + } + else + { + HalTscrCReadI2CSeq(FW_UPDATE_ADDR_MSG21XX, pDataToRead, n); + } + + return 0; +} + +static void drvISP_WriteEnable(void) +{ + u8 bWriteData[2] = + { + 0x10, 0x06 + }; + u8 bWriteData1 = 0x12; + HalTscrCDevWriteI2CSeq(FW_UPDATE_ADDR_MSG21XX, bWriteData, 2); + udelay(150);//1.16 + HalTscrCDevWriteI2CSeq(FW_UPDATE_ADDR_MSG21XX, &bWriteData1, 1); +} + + +static void drvISP_ExitIspMode(void) +{ + u8 bWriteData = 0x24; + HalTscrCDevWriteI2CSeq(FW_UPDATE_ADDR_MSG21XX, &bWriteData, 1); + udelay( 150 );//200); +} + +static u8 drvISP_ReadStatus(void) +{ + u8 bReadData = 0; + u8 bWriteData[2] = + { + 0x10, 0x05 + }; + u8 bWriteData1 = 0x12; + + HalTscrCDevWriteI2CSeq(FW_UPDATE_ADDR_MSG21XX, bWriteData, 2); + //msctpc_LoopDelay ( 1 ); // delay about 100us***** + udelay(150);//200); + drvISP_Read(1, &bReadData); + HalTscrCDevWriteI2CSeq(FW_UPDATE_ADDR_MSG21XX, &bWriteData1, 1); + return bReadData; +} + + +static void drvISP_BlockErase(u32 addr) +{ + u8 bWriteData[5] = { 0x00, 0x00, 0x00, 0x00, 0x00 }; + u8 bWriteData1 = 0x12; + printk("\n******%s come in*******\n",__FUNCTION__); + u32 timeOutCount=0; + drvISP_WriteEnable(); + + //Enable write status register + bWriteData[0] = 0x10; + bWriteData[1] = 0x50; + HalTscrCDevWriteI2CSeq(FW_UPDATE_ADDR_MSG21XX, bWriteData, 2); + HalTscrCDevWriteI2CSeq(FW_UPDATE_ADDR_MSG21XX, &bWriteData1, 1); + + //Write Status + bWriteData[0] = 0x10; + bWriteData[1] = 0x01; + bWriteData[2] = 0x00; + HalTscrCDevWriteI2CSeq(FW_UPDATE_ADDR_MSG21XX, bWriteData, 3); + HalTscrCDevWriteI2CSeq(FW_UPDATE_ADDR_MSG21XX, &bWriteData1, 1); + + //Write disable + bWriteData[0] = 0x10; + bWriteData[1] = 0x04; + HalTscrCDevWriteI2CSeq(FW_UPDATE_ADDR_MSG21XX, bWriteData, 2); + HalTscrCDevWriteI2CSeq(FW_UPDATE_ADDR_MSG21XX, &bWriteData1, 1); + //msctpc_LoopDelay ( 1 ); // delay about 100us***** + udelay(150);//200); + timeOutCount=0; + while ( ( drvISP_ReadStatus() & 0x01 ) == 0x01 ) + { + timeOutCount++; + if ( timeOutCount >= 100000 ) break; /* around 1 sec timeout */ + } + drvISP_WriteEnable(); + + bWriteData[0] = 0x10; + bWriteData[1] = 0xC7;//0xD8; //Block Erase + //bWriteData[2] = ((addr >> 16) & 0xFF) ; + //bWriteData[3] = ((addr >> 8) & 0xFF) ; + //bWriteData[4] = (addr & 0xFF) ; + HalTscrCDevWriteI2CSeq(FW_UPDATE_ADDR_MSG21XX, bWriteData, 2); + //HalTscrCDevWriteI2CSeq(FW_UPDATE_ADDR_MSG21XX, &bWriteData, 5); + HalTscrCDevWriteI2CSeq(FW_UPDATE_ADDR_MSG21XX, &bWriteData1, 1); + //msctpc_LoopDelay ( 1 ); // delay about 100us***** + udelay(150);//200); + timeOutCount=0; + while ( ( drvISP_ReadStatus() & 0x01 ) == 0x01 ) + { + timeOutCount++; + if ( timeOutCount >= 500000 ) break; /* around 5 sec timeout */ + } +} + +static void drvISP_Program(u16 k, u8* pDataToWrite) +{ + u16 i = 0; + u16 j = 0; + //u16 n = 0; + u8 TX_data[133]; + u8 bWriteData1 = 0x12; + u32 addr = k * 1024; + u32 timeOutCount=0; + for (j = 0; j < 8; j++) //128*8 cycle + { + TX_data[0] = 0x10; + TX_data[1] = 0x02;// Page Program CMD + TX_data[2] = (addr + 128 * j) >> 16; + TX_data[3] = (addr + 128 * j) >> 8; + TX_data[4] = (addr + 128 * j); + for (i = 0; i < 128; i++) + { + TX_data[5 + i] = pDataToWrite[j * 128 + i]; + } + //msctpc_LoopDelay ( 1 ); // delay about 100us***** + udelay(150);//200); + + timeOutCount=0; + while ( ( drvISP_ReadStatus() & 0x01 ) == 0x01 ) + { + timeOutCount++; + if ( timeOutCount >= 100000 ) break; /* around 1 sec timeout */ + } + + drvISP_WriteEnable(); + HalTscrCDevWriteI2CSeq(FW_UPDATE_ADDR_MSG21XX, TX_data, 133); //write 133 byte per cycle + HalTscrCDevWriteI2CSeq(FW_UPDATE_ADDR_MSG21XX, &bWriteData1, 1); + } +} + +static ssize_t firmware_update_show ( struct device *dev, + struct device_attribute *attr, char *buf ) +{ + return sprintf ( buf, "%s\n", fw_version ); +} +/*reset the chip*/ +static void _HalTscrHWReset(void) +{ + struct msg2138_ts_platform_data *pdata = msg21xx_i2c_ts_data->platform_data; + gpio_direction_output(pdata->reset_gpio_number, 1); + gpio_set_value(pdata->reset_gpio_number, 1); + gpio_set_value(pdata->reset_gpio_number, 0); + mdelay(10); /* Note that the RST must be in LOW 10ms at least */ + gpio_set_value(pdata->reset_gpio_number, 1); + /* Enable the interrupt service thread/routine for INT after 50ms */ + mdelay(50); +} + +static void drvISP_Verify ( u16 k, u8* pDataToVerify ) +{ + u16 i = 0, j = 0; + u8 bWriteData[5] ={ 0x10, 0x03, 0, 0, 0 }; + u8 RX_data[256]; + u8 bWriteData1 = 0x12; + u32 addr = k * 1024; + u8 index = 0; + u32 timeOutCount; + for ( j = 0; j < 8; j++ ) //128*8 cycle + { + bWriteData[2] = ( u8 ) ( ( addr + j * 128 ) >> 16 ); + bWriteData[3] = ( u8 ) ( ( addr + j * 128 ) >> 8 ); + bWriteData[4] = ( u8 ) ( addr + j * 128 ); + udelay ( 100 ); // delay about 100us***** + + timeOutCount = 0; + while ( ( drvISP_ReadStatus() & 0x01 ) == 0x01 ) + { + timeOutCount++; + if ( timeOutCount >= 100000 ) break; /* around 1 sec timeout */ + } + + HalTscrCDevWriteI2CSeq ( FW_UPDATE_ADDR_MSG21XX, bWriteData, 5 ); //write read flash addr + udelay ( 100 ); // delay about 100us***** + drvISP_Read ( 128, RX_data ); + HalTscrCDevWriteI2CSeq ( FW_UPDATE_ADDR_MSG21XX, &bWriteData1, 1 ); //cmd end + for ( i = 0; i < 128; i++ ) //log out if verify error + { + if ( ( RX_data[i] != 0 ) && index < 10 ) + { + //TP_DEBUG("j=%d,RX_data[%d]=0x%x\n",j,i,RX_data[i]); + index++; + } + if ( RX_data[i] != pDataToVerify[128 * j + i] ) + { + TP_DEBUG ( "k=%d,j=%d,i=%d===============Update Firmware Error================", k, j, i ); + } + } + } +} + +static void drvISP_ChipErase() +{ + u8 bWriteData[5] = { 0x00, 0x00, 0x00, 0x00, 0x00 }; + u8 bWriteData1 = 0x12; + u32 timeOutCount = 0; + drvISP_WriteEnable(); + + //Enable write status register + bWriteData[0] = 0x10; + bWriteData[1] = 0x50; + HalTscrCDevWriteI2CSeq ( FW_UPDATE_ADDR_MSG21XX, bWriteData, 2 ); + HalTscrCDevWriteI2CSeq ( FW_UPDATE_ADDR_MSG21XX, &bWriteData1, 1 ); + + //Write Status + bWriteData[0] = 0x10; + bWriteData[1] = 0x01; + bWriteData[2] = 0x00; + HalTscrCDevWriteI2CSeq ( FW_UPDATE_ADDR_MSG21XX, bWriteData, 3 ); + HalTscrCDevWriteI2CSeq ( FW_UPDATE_ADDR_MSG21XX, &bWriteData1, 1 ); + + //Write disable + bWriteData[0] = 0x10; + bWriteData[1] = 0x04; + HalTscrCDevWriteI2CSeq ( FW_UPDATE_ADDR_MSG21XX, bWriteData, 2 ); + HalTscrCDevWriteI2CSeq ( FW_UPDATE_ADDR_MSG21XX, &bWriteData1, 1 ); + udelay ( 100 ); // delay about 100us***** + timeOutCount = 0; + while ( ( drvISP_ReadStatus() & 0x01 ) == 0x01 ) + { + timeOutCount++; + if ( timeOutCount >= 100000 ) break; /* around 1 sec timeout */ + } + drvISP_WriteEnable(); + + bWriteData[0] = 0x10; + bWriteData[1] = 0xC7; + + HalTscrCDevWriteI2CSeq ( FW_UPDATE_ADDR_MSG21XX, bWriteData, 2 ); + HalTscrCDevWriteI2CSeq ( FW_UPDATE_ADDR_MSG21XX, &bWriteData1, 1 ); + udelay ( 100 ); // delay about 100us***** + timeOutCount = 0; + while ( ( drvISP_ReadStatus() & 0x01 ) == 0x01 ) + { + timeOutCount++; + if ( timeOutCount >= 500000 ) break; /* around 5 sec timeout */ + } +} + +/* update the firmware part, used by apk*/ +/*show the fw version*/ + +static ssize_t firmware_update_c2 ( struct device *dev, + struct device_attribute *attr, const char *buf, size_t size ) +{ + u8 i; + u8 dbbus_tx_data[4]; + unsigned char dbbus_rx_data[2] = {0}; + + // set FRO to 50M + dbbus_tx_data[0] = 0x10; + dbbus_tx_data[1] = 0x11; + dbbus_tx_data[2] = 0xE2; + HalTscrCDevWriteI2CSeq ( FW_ADDR_MSG21XX, dbbus_tx_data, 3 ); + dbbus_rx_data[0] = 0; + dbbus_rx_data[1] = 0; + HalTscrCReadI2CSeq ( FW_ADDR_MSG21XX, &dbbus_rx_data[0], 2 ); + TP_DEBUG ( "dbbus_rx_data[0]=0x%x", dbbus_rx_data[0] ); + dbbus_tx_data[3] = dbbus_rx_data[0] & 0xF7; //Clear Bit 3 + HalTscrCDevWriteI2CSeq ( FW_ADDR_MSG21XX, dbbus_tx_data, 4 ); + + // set MCU clock,SPI clock =FRO + dbbus_tx_data[0] = 0x10; + dbbus_tx_data[1] = 0x1E; + dbbus_tx_data[2] = 0x22; + dbbus_tx_data[3] = 0x00; + HalTscrCDevWriteI2CSeq ( FW_ADDR_MSG21XX, dbbus_tx_data, 4 ); + + dbbus_tx_data[0] = 0x10; + dbbus_tx_data[1] = 0x1E; + dbbus_tx_data[2] = 0x23; + dbbus_tx_data[3] = 0x00; + HalTscrCDevWriteI2CSeq ( FW_ADDR_MSG21XX, dbbus_tx_data, 4 ); + + // Enable slave's ISP ECO mode + dbbus_tx_data[0] = 0x10; + dbbus_tx_data[1] = 0x08; + dbbus_tx_data[2] = 0x0c; + dbbus_tx_data[3] = 0x08; + HalTscrCDevWriteI2CSeq ( FW_ADDR_MSG21XX, dbbus_tx_data, 4 ); + + // Enable SPI Pad + dbbus_tx_data[0] = 0x10; + dbbus_tx_data[1] = 0x1E; + dbbus_tx_data[2] = 0x02; + HalTscrCDevWriteI2CSeq ( FW_ADDR_MSG21XX, dbbus_tx_data, 3 ); + HalTscrCReadI2CSeq ( FW_ADDR_MSG21XX, &dbbus_rx_data[0], 2 ); + TP_DEBUG ( "dbbus_rx_data[0]=0x%x", dbbus_rx_data[0] ); + dbbus_tx_data[3] = ( dbbus_rx_data[0] | 0x20 ); //Set Bit 5 + HalTscrCDevWriteI2CSeq ( FW_ADDR_MSG21XX, dbbus_tx_data, 4 ); + + // WP overwrite + dbbus_tx_data[0] = 0x10; + dbbus_tx_data[1] = 0x1E; + dbbus_tx_data[2] = 0x0E; + dbbus_tx_data[3] = 0x02; + HalTscrCDevWriteI2CSeq ( FW_ADDR_MSG21XX, dbbus_tx_data, 4 ); + + // set pin high + dbbus_tx_data[0] = 0x10; + dbbus_tx_data[1] = 0x1E; + dbbus_tx_data[2] = 0x10; + dbbus_tx_data[3] = 0x08; + HalTscrCDevWriteI2CSeq ( FW_ADDR_MSG21XX, dbbus_tx_data, 4 ); + + dbbusDWIICIICNotUseBus(); + dbbusDWIICNotStopMCU(); + dbbusDWIICExitSerialDebugMode(); + + drvISP_EntryIspMode(); + drvISP_ChipErase(); + _HalTscrHWReset(); + mdelay ( 300 ); + + // Program and Verify + dbbusDWIICEnterSerialDebugMode(); + dbbusDWIICStopMCU(); + dbbusDWIICIICUseBus(); + dbbusDWIICIICReshape(); + + // Disable the Watchdog + dbbus_tx_data[0] = 0x10; + dbbus_tx_data[1] = 0x3C; + dbbus_tx_data[2] = 0x60; + dbbus_tx_data[3] = 0x55; + HalTscrCDevWriteI2CSeq ( FW_ADDR_MSG21XX, dbbus_tx_data, 4 ); + dbbus_tx_data[0] = 0x10; + dbbus_tx_data[1] = 0x3C; + dbbus_tx_data[2] = 0x61; + dbbus_tx_data[3] = 0xAA; + HalTscrCDevWriteI2CSeq ( FW_ADDR_MSG21XX, dbbus_tx_data, 4 ); + + //Stop MCU + dbbus_tx_data[0] = 0x10; + dbbus_tx_data[1] = 0x0F; + dbbus_tx_data[2] = 0xE6; + dbbus_tx_data[3] = 0x01; + HalTscrCDevWriteI2CSeq ( FW_ADDR_MSG21XX, dbbus_tx_data, 4 ); + + // set FRO to 50M + dbbus_tx_data[0] = 0x10; + dbbus_tx_data[1] = 0x11; + dbbus_tx_data[2] = 0xE2; + HalTscrCDevWriteI2CSeq ( FW_ADDR_MSG21XX, dbbus_tx_data, 3 ); + dbbus_rx_data[0] = 0; + dbbus_rx_data[1] = 0; + HalTscrCReadI2CSeq ( FW_ADDR_MSG21XX, &dbbus_rx_data[0], 2 ); + TP_DEBUG ( "dbbus_rx_data[0]=0x%x", dbbus_rx_data[0] ); + dbbus_tx_data[3] = dbbus_rx_data[0] & 0xF7; //Clear Bit 3 + HalTscrCDevWriteI2CSeq ( FW_ADDR_MSG21XX, dbbus_tx_data, 4 ); + + // set MCU clock,SPI clock =FRO + dbbus_tx_data[0] = 0x10; + dbbus_tx_data[1] = 0x1E; + dbbus_tx_data[2] = 0x22; + dbbus_tx_data[3] = 0x00; + HalTscrCDevWriteI2CSeq ( FW_ADDR_MSG21XX, dbbus_tx_data, 4 ); + + dbbus_tx_data[0] = 0x10; + dbbus_tx_data[1] = 0x1E; + dbbus_tx_data[2] = 0x23; + dbbus_tx_data[3] = 0x00; + HalTscrCDevWriteI2CSeq ( FW_ADDR_MSG21XX, dbbus_tx_data, 4 ); + + // Enable slave's ISP ECO mode + dbbus_tx_data[0] = 0x10; + dbbus_tx_data[1] = 0x08; + dbbus_tx_data[2] = 0x0c; + dbbus_tx_data[3] = 0x08; + HalTscrCDevWriteI2CSeq ( FW_ADDR_MSG21XX, dbbus_tx_data, 4 ); + + // Enable SPI Pad + dbbus_tx_data[0] = 0x10; + dbbus_tx_data[1] = 0x1E; + dbbus_tx_data[2] = 0x02; + HalTscrCDevWriteI2CSeq ( FW_ADDR_MSG21XX, dbbus_tx_data, 3 ); + HalTscrCReadI2CSeq ( FW_ADDR_MSG21XX, &dbbus_rx_data[0], 2 ); + TP_DEBUG ( "dbbus_rx_data[0]=0x%x", dbbus_rx_data[0] ); + dbbus_tx_data[3] = ( dbbus_rx_data[0] | 0x20 ); //Set Bit 5 + HalTscrCDevWriteI2CSeq ( FW_ADDR_MSG21XX, dbbus_tx_data, 4 ); + + // WP overwrite + dbbus_tx_data[0] = 0x10; + dbbus_tx_data[1] = 0x1E; + dbbus_tx_data[2] = 0x0E; + dbbus_tx_data[3] = 0x02; + HalTscrCDevWriteI2CSeq ( FW_ADDR_MSG21XX, dbbus_tx_data, 4 ); + + // set pin high + dbbus_tx_data[0] = 0x10; + dbbus_tx_data[1] = 0x1E; + dbbus_tx_data[2] = 0x10; + dbbus_tx_data[3] = 0x08; + HalTscrCDevWriteI2CSeq ( FW_ADDR_MSG21XX, dbbus_tx_data, 4 ); + + dbbusDWIICIICNotUseBus(); + dbbusDWIICNotStopMCU(); + dbbusDWIICExitSerialDebugMode(); + + /////////////////////////////////////// + // Start to load firmware + /////////////////////////////////////// + drvISP_EntryIspMode(); + + for ( i = 0; i < 94; i++ ) // total 94 KB : 1 byte per R/W + { + drvISP_Program ( i, temp[i] ); // program to slave's flash + drvISP_Verify ( i, temp[i] ); //verify data + } + TP_DEBUG ( "update OK\n" ); + drvISP_ExitIspMode(); + FwDataCnt = 0; + return size; +} + +static u32 Reflect ( u32 ref, char ch ) //unsigned int Reflect(unsigned int ref, char ch) +{ + u32 value = 0; + u32 i = 0; + + for ( i = 1; i < ( ch + 1 ); i++ ) + { + if ( ref & 1 ) + { + value |= 1 << ( ch - i ); + } + ref >>= 1; + } + return value; +} + +u32 Get_CRC ( u32 text, u32 prevCRC, u32 *crc32_table ) +{ + u32 ulCRC = prevCRC; + ulCRC = ( ulCRC >> 8 ) ^ crc32_table[ ( ulCRC & 0xFF ) ^ text]; + return ulCRC ; +} +static void Init_CRC32_Table ( u32 *crc32_table ) +{ + u32 magicnumber = 0x04c11db7; + u32 i = 0, j; + + for ( i = 0; i <= 0xFF; i++ ) + { + crc32_table[i] = Reflect ( i, 8 ) << 24; + for ( j = 0; j < 8; j++ ) + { + crc32_table[i] = ( crc32_table[i] << 1 ) ^ ( crc32_table[i] & ( 0x80000000L ) ? magicnumber : 0 ); + } + crc32_table[i] = Reflect ( crc32_table[i], 32 ); + } +} + +typedef enum +{ + EMEM_ALL = 0, + EMEM_MAIN, + EMEM_INFO, +} EMEM_TYPE_t; + +static void drvDB_WriteReg8Bit ( u8 bank, u8 addr, u8 data ) +{ + u8 tx_data[4] = {0x10, bank, addr, data}; + HalTscrCDevWriteI2CSeq ( FW_ADDR_MSG21XX, tx_data, 4 ); +} + +static void drvDB_WriteReg ( u8 bank, u8 addr, u16 data ) +{ + u8 tx_data[5] = {0x10, bank, addr, data & 0xFF, data >> 8}; + HalTscrCDevWriteI2CSeq ( FW_ADDR_MSG21XX, tx_data, 5 ); +} + +static unsigned short drvDB_ReadReg ( u8 bank, u8 addr ) +{ + u8 tx_data[3] = {0x10, bank, addr}; + u8 rx_data[2] = {0}; + + HalTscrCDevWriteI2CSeq ( FW_ADDR_MSG21XX, tx_data, 3 ); + HalTscrCReadI2CSeq ( FW_ADDR_MSG21XX, &rx_data[0], 2 ); + return ( rx_data[1] << 8 | rx_data[0] ); +} + +static int drvTP_erase_emem_c32 ( void ) +{ + ///////////////////////// + //Erase all + ///////////////////////// + + //enter gpio mode + drvDB_WriteReg ( 0x16, 0x1E, 0xBEAF ); + + // before gpio mode, set the control pin as the orginal status + drvDB_WriteReg ( 0x16, 0x08, 0x0000 ); + drvDB_WriteReg8Bit ( 0x16, 0x0E, 0x10 ); + mdelay ( 10 ); //MCR_CLBK_DEBUG_DELAY ( 10, MCU_LOOP_DELAY_COUNT_MS ); + + // ptrim = 1, h'04[2] + drvDB_WriteReg8Bit ( 0x16, 0x08, 0x04 ); + drvDB_WriteReg8Bit ( 0x16, 0x0E, 0x10 ); + mdelay ( 10 ); //MCR_CLBK_DEBUG_DELAY ( 10, MCU_LOOP_DELAY_COUNT_MS ); + + // ptm = 6, h'04[12:14] = b'110 + drvDB_WriteReg8Bit ( 0x16, 0x09, 0x60 ); + drvDB_WriteReg8Bit ( 0x16, 0x0E, 0x10 ); + + // pmasi = 1, h'04[6] + drvDB_WriteReg8Bit ( 0x16, 0x08, 0x44 ); + // pce = 1, h'04[11] + drvDB_WriteReg8Bit ( 0x16, 0x09, 0x68 ); + // perase = 1, h'04[7] + drvDB_WriteReg8Bit ( 0x16, 0x08, 0xC4 ); + // pnvstr = 1, h'04[5] + drvDB_WriteReg8Bit ( 0x16, 0x08, 0xE4 ); + // pwe = 1, h'04[9] + drvDB_WriteReg8Bit ( 0x16, 0x09, 0x6A ); + // trigger gpio load + drvDB_WriteReg8Bit ( 0x16, 0x0E, 0x10 ); + + return ( 1 ); +} + +static ssize_t firmware_update_c32 ( struct device *dev, struct device_attribute *attr, + const char *buf, size_t size, EMEM_TYPE_t emem_type ) +{ + u8 dbbus_tx_data[4]; + u8 dbbus_rx_data[2] = {0}; + // Buffer for slave's firmware + + u32 i, j; + u32 crc_main, crc_main_tp; + u32 crc_info, crc_info_tp; + u16 reg_data = 0; + + crc_main = 0xffffffff; + crc_info = 0xffffffff; + +#if 1 + ///////////////////////// + // Erase all + ///////////////////////// + drvTP_erase_emem_c32(); + mdelay ( 1000 ); //MCR_CLBK_DEBUG_DELAY ( 1000, MCU_LOOP_DELAY_COUNT_MS ); + + //ResetSlave(); + _HalTscrHWReset(); + //drvDB_EnterDBBUS(); + dbbusDWIICEnterSerialDebugMode(); + dbbusDWIICStopMCU(); + dbbusDWIICIICUseBus(); + dbbusDWIICIICReshape(); + mdelay ( 300 ); + + // Reset Watchdog + drvDB_WriteReg8Bit ( 0x3C, 0x60, 0x55 ); + drvDB_WriteReg8Bit ( 0x3C, 0x61, 0xAA ); + + ///////////////////////// + // Program + ///////////////////////// + + //polling 0x3CE4 is 0x1C70 + do + { + reg_data = drvDB_ReadReg ( 0x3C, 0xE4 ); + } + while ( reg_data != 0x1C70 ); + + + drvDB_WriteReg ( 0x3C, 0xE4, 0xE38F ); // for all-blocks + + //polling 0x3CE4 is 0x2F43 + do + { + reg_data = drvDB_ReadReg ( 0x3C, 0xE4 ); + } + while ( reg_data != 0x2F43 ); + + + //calculate CRC 32 + Init_CRC32_Table ( &crc_tab[0] ); + + for ( i = 0; i < 33; i++ ) // total 33 KB : 2 byte per R/W + { + if ( i < 32 ) //emem_main + { + if ( i == 31 ) + { + temp[i][1014] = 0x5A; //Fmr_Loader[1014]=0x5A; + temp[i][1015] = 0xA5; //Fmr_Loader[1015]=0xA5; + + for ( j = 0; j < 1016; j++ ) + { + //crc_main=Get_CRC(Fmr_Loader[j],crc_main,&crc_tab[0]); + crc_main = Get_CRC ( temp[i][j], crc_main, &crc_tab[0] ); + } + } + else + { + for ( j = 0; j < 1024; j++ ) + { + //crc_main=Get_CRC(Fmr_Loader[j],crc_main,&crc_tab[0]); + crc_main = Get_CRC ( temp[i][j], crc_main, &crc_tab[0] ); + } + } + } + else // emem_info + { + for ( j = 0; j < 1024; j++ ) + { + //crc_info=Get_CRC(Fmr_Loader[j],crc_info,&crc_tab[0]); + crc_info = Get_CRC ( temp[i][j], crc_info, &crc_tab[0] ); + } + } + + //drvDWIIC_MasterTransmit( DWIIC_MODE_DWIIC_ID, 1024, Fmr_Loader ); + HalTscrCDevWriteI2CSeq ( FW_ADDR_MSG21XX_TP, temp[i], 1024 ); + + // polling 0x3CE4 is 0xD0BC + do + { + reg_data = drvDB_ReadReg ( 0x3C, 0xE4 ); + } + while ( reg_data != 0xD0BC ); + + drvDB_WriteReg ( 0x3C, 0xE4, 0x2F43 ); + } + + //write file done + drvDB_WriteReg ( 0x3C, 0xE4, 0x1380 ); + + mdelay ( 10 ); //MCR_CLBK_DEBUG_DELAY ( 10, MCU_LOOP_DELAY_COUNT_MS ); + // polling 0x3CE4 is 0x9432 + do + { + reg_data = drvDB_ReadReg ( 0x3C, 0xE4 ); + } + while ( reg_data != 0x9432 ); + + crc_main = crc_main ^ 0xffffffff; + crc_info = crc_info ^ 0xffffffff; + + // CRC Main from TP + crc_main_tp = drvDB_ReadReg ( 0x3C, 0x80 ); + crc_main_tp = ( crc_main_tp << 16 ) | drvDB_ReadReg ( 0x3C, 0x82 ); + + //CRC Info from TP + crc_info_tp = drvDB_ReadReg ( 0x3C, 0xA0 ); + crc_info_tp = ( crc_info_tp << 16 ) | drvDB_ReadReg ( 0x3C, 0xA2 ); + + TP_DEBUG ( "crc_main=0x%x, crc_info=0x%x, crc_main_tp=0x%x, crc_info_tp=0x%x\n", + crc_main, crc_info, crc_main_tp, crc_info_tp ); + + //drvDB_ExitDBBUS(); + if ( ( crc_main_tp != crc_main ) || ( crc_info_tp != crc_info ) ) + { + printk ( "update FAILED\n" ); + _HalTscrHWReset(); + FwDataCnt = 0; + enable_irq(global_irq); + return ( 0 ); + } + + printk ( "update OK\n" ); + _HalTscrHWReset(); + FwDataCnt = 0; + enable_irq(global_irq); + + return size; +#endif +} + +static int drvTP_erase_emem_c33 ( EMEM_TYPE_t emem_type ) +{ + // stop mcu + drvDB_WriteReg ( 0x0F, 0xE6, 0x0001 ); + + //disable watch dog + drvDB_WriteReg8Bit ( 0x3C, 0x60, 0x55 ); + drvDB_WriteReg8Bit ( 0x3C, 0x61, 0xAA ); + + // set PROGRAM password + drvDB_WriteReg8Bit ( 0x16, 0x1A, 0xBA ); + drvDB_WriteReg8Bit ( 0x16, 0x1B, 0xAB ); + + //proto.MstarWriteReg(F1.loopDevice, 0x1618, 0x80); + drvDB_WriteReg8Bit ( 0x16, 0x18, 0x80 ); + + if ( emem_type == EMEM_ALL ) + { + drvDB_WriteReg8Bit ( 0x16, 0x08, 0x10 ); //mark + } + + drvDB_WriteReg8Bit ( 0x16, 0x18, 0x40 ); + mdelay ( 10 ); + + drvDB_WriteReg8Bit ( 0x16, 0x18, 0x80 ); + + // erase trigger + if ( emem_type == EMEM_MAIN ) + { + drvDB_WriteReg8Bit ( 0x16, 0x0E, 0x04 ); //erase main + } + else + { + drvDB_WriteReg8Bit ( 0x16, 0x0E, 0x08 ); //erase all block + } + + return ( 1 ); +} + +static int drvTP_read_emem_dbbus_c33 ( EMEM_TYPE_t emem_type, u16 addr, size_t size, u8 *p, size_t set_pce_high ) +{ + u32 i; + + // Set the starting address ( must before enabling burst mode and enter riu mode ) + drvDB_WriteReg ( 0x16, 0x00, addr ); + + // Enable the burst mode ( must before enter riu mode ) + drvDB_WriteReg ( 0x16, 0x0C, drvDB_ReadReg ( 0x16, 0x0C ) | 0x0001 ); + + // Set the RIU password + drvDB_WriteReg ( 0x16, 0x1A, 0xABBA ); + + // Enable the information block if pifren is HIGH + if ( emem_type == EMEM_INFO ) + { + // Clear the PCE + drvDB_WriteReg ( 0x16, 0x18, drvDB_ReadReg ( 0x16, 0x18 ) | 0x0080 ); + mdelay ( 10 ); + + // Set the PIFREN to be HIGH + drvDB_WriteReg ( 0x16, 0x08, 0x0010 ); + } + + // Set the PCE to be HIGH + drvDB_WriteReg ( 0x16, 0x18, drvDB_ReadReg ( 0x16, 0x18 ) | 0x0040 ); + mdelay ( 10 ); + + // Wait pce becomes 1 ( read data ready ) + while ( ( drvDB_ReadReg ( 0x16, 0x10 ) & 0x0004 ) != 0x0004 ); + + for ( i = 0; i < size; i += 4 ) + { + // Fire the FASTREAD command + drvDB_WriteReg ( 0x16, 0x0E, drvDB_ReadReg ( 0x16, 0x0E ) | 0x0001 ); + + // Wait the operation is done + while ( ( drvDB_ReadReg ( 0x16, 0x10 ) & 0x0001 ) != 0x0001 ); + + p[i + 0] = drvDB_ReadReg ( 0x16, 0x04 ) & 0xFF; + p[i + 1] = ( drvDB_ReadReg ( 0x16, 0x04 ) >> 8 ) & 0xFF; + p[i + 2] = drvDB_ReadReg ( 0x16, 0x06 ) & 0xFF; + p[i + 3] = ( drvDB_ReadReg ( 0x16, 0x06 ) >> 8 ) & 0xFF; + } + + // Disable the burst mode + drvDB_WriteReg ( 0x16, 0x0C, drvDB_ReadReg ( 0x16, 0x0C ) & ( ~0x0001 ) ); + + // Clear the starting address + drvDB_WriteReg ( 0x16, 0x00, 0x0000 ); + + //Always return to main block + if ( emem_type == EMEM_INFO ) + { + // Clear the PCE before change block + drvDB_WriteReg ( 0x16, 0x18, drvDB_ReadReg ( 0x16, 0x18 ) | 0x0080 ); + mdelay ( 10 ); + // Set the PIFREN to be LOW + drvDB_WriteReg ( 0x16, 0x08, drvDB_ReadReg ( 0x16, 0x08 ) & ( ~0x0010 ) ); + + drvDB_WriteReg ( 0x16, 0x18, drvDB_ReadReg ( 0x16, 0x18 ) | 0x0040 ); + while ( ( drvDB_ReadReg ( 0x16, 0x10 ) & 0x0004 ) != 0x0004 ); + } + + // Clear the RIU password + drvDB_WriteReg ( 0x16, 0x1A, 0x0000 ); + + if ( set_pce_high ) + { + // Set the PCE to be HIGH before jumping back to e-flash codes + drvDB_WriteReg ( 0x16, 0x18, drvDB_ReadReg ( 0x16, 0x18 ) | 0x0040 ); + while ( ( drvDB_ReadReg ( 0x16, 0x10 ) & 0x0004 ) != 0x0004 ); + } + + return ( 1 ); +} + + +static int drvTP_read_info_dwiic_c33 ( void ) +{ + u8 dwiic_tx_data[5]; + u8 dwiic_rx_data[4]; + u16 reg_data=0; + mdelay ( 300 ); + + // Stop Watchdog + drvDB_WriteReg8Bit ( 0x3C, 0x60, 0x55 ); + drvDB_WriteReg8Bit ( 0x3C, 0x61, 0xAA ); + + drvDB_WriteReg ( 0x3C, 0xE4, 0xA4AB ); + + drvDB_WriteReg ( 0x1E, 0x04, 0x7d60 ); + + // TP SW reset + drvDB_WriteReg ( 0x1E, 0x04, 0x829F ); + mdelay ( 1 ); + dwiic_tx_data[0] = 0x10; + dwiic_tx_data[1] = 0x0F; + dwiic_tx_data[2] = 0xE6; + dwiic_tx_data[3] = 0x00; + HalTscrCDevWriteI2CSeq ( FW_ADDR_MSG21XX, dwiic_tx_data, 4 ); + mdelay ( 100 ); + + do{ + reg_data = drvDB_ReadReg ( 0x3C, 0xE4 ); + } + while ( reg_data != 0x5B58 ); + + dwiic_tx_data[0] = 0x72; + dwiic_tx_data[1] = 0x80; + dwiic_tx_data[2] = 0x00; + dwiic_tx_data[3] = 0x04; + dwiic_tx_data[4] = 0x00; + HalTscrCDevWriteI2CSeq ( FW_ADDR_MSG21XX_TP , dwiic_tx_data, 5 ); + + mdelay ( 50 ); + + // recive info data + HalTscrCReadI2CSeq ( FW_ADDR_MSG21XX_TP, &g_dwiic_info_data[0], 1024 ); + + return ( 1 ); +} + +static int drvTP_info_updata_C33 ( u16 start_index, u8 *data, u16 size ) +{ + // size != 0, start_index+size !> 1024 + u16 i; + for ( i = 0; i < size; i++ ) + { + g_dwiic_info_data[start_index] = * ( data + i ); + start_index++; + } + return ( 1 ); +} + +static ssize_t firmware_update_c33 ( struct device *dev, struct device_attribute *attr, + const char *buf, size_t size, EMEM_TYPE_t emem_type ) +{ + u8 dbbus_tx_data[4]; + u8 dbbus_rx_data[2] = {0}; + u8 life_counter[2]; + u32 i, j; + u32 crc_main, crc_main_tp; + u32 crc_info, crc_info_tp; + + int update_pass = 1; + u16 reg_data = 0; + + crc_main = 0xffffffff; + crc_info = 0xffffffff; + + drvTP_read_info_dwiic_c33(); + + if ( g_dwiic_info_data[0] == 'M' && g_dwiic_info_data[1] == 'S' && g_dwiic_info_data[2] == 'T' && g_dwiic_info_data[3] == 'A' && g_dwiic_info_data[4] == 'R' && g_dwiic_info_data[5] == 'T' && g_dwiic_info_data[6] == 'P' && g_dwiic_info_data[7] == 'C' ) + { + // updata FW Version + //drvTP_info_updata_C33 ( 8, &temp[32][8], 5 ); + + g_dwiic_info_data[8]=temp[32][8]; + g_dwiic_info_data[9]=temp[32][9]; + g_dwiic_info_data[10]=temp[32][10]; + g_dwiic_info_data[11]=temp[32][11]; + // updata life counter + life_counter[1] = (( ( (g_dwiic_info_data[13] << 8 ) | g_dwiic_info_data[12]) + 1 ) >> 8 ) & 0xFF; + life_counter[0] = ( ( (g_dwiic_info_data[13] << 8 ) | g_dwiic_info_data[12]) + 1 ) & 0xFF; + g_dwiic_info_data[12]=life_counter[0]; + g_dwiic_info_data[13]=life_counter[1]; + //drvTP_info_updata_C33 ( 10, &life_counter[0], 3 ); + drvDB_WriteReg ( 0x3C, 0xE4, 0x78C5 ); + drvDB_WriteReg ( 0x1E, 0x04, 0x7d60 ); + // TP SW reset + drvDB_WriteReg ( 0x1E, 0x04, 0x829F ); + + mdelay ( 50 ); + + //polling 0x3CE4 is 0x2F43 + do + { + reg_data = drvDB_ReadReg ( 0x3C, 0xE4 ); + + } + while ( reg_data != 0x2F43 ); + + // transmit lk info data + HalTscrCDevWriteI2CSeq ( FW_ADDR_MSG21XX_TP , &g_dwiic_info_data[0], 1024 ); + + //polling 0x3CE4 is 0xD0BC + do + { + reg_data = drvDB_ReadReg ( 0x3C, 0xE4 ); + } + while ( reg_data != 0xD0BC ); + + } + + //erase main + drvTP_erase_emem_c33 ( EMEM_MAIN ); + mdelay ( 1000 ); + + //ResetSlave(); + _HalTscrHWReset(); + + //drvDB_EnterDBBUS(); + dbbusDWIICEnterSerialDebugMode(); + dbbusDWIICStopMCU(); + dbbusDWIICIICUseBus(); + dbbusDWIICIICReshape(); + mdelay ( 300 ); + + ///////////////////////// + // Program + ///////////////////////// + + //polling 0x3CE4 is 0x1C70 + if ( ( emem_type == EMEM_ALL ) || ( emem_type == EMEM_MAIN ) ) + { + do + { + reg_data = drvDB_ReadReg ( 0x3C, 0xE4 ); + } + while ( reg_data != 0x1C70 ); + } + + switch ( emem_type ) + { + case EMEM_ALL: + drvDB_WriteReg ( 0x3C, 0xE4, 0xE38F ); // for all-blocks + break; + case EMEM_MAIN: + drvDB_WriteReg ( 0x3C, 0xE4, 0x7731 ); // for main block + break; + case EMEM_INFO: + drvDB_WriteReg ( 0x3C, 0xE4, 0x7731 ); // for info block + + drvDB_WriteReg8Bit ( 0x0F, 0xE6, 0x01 ); + + drvDB_WriteReg8Bit ( 0x3C, 0xE4, 0xC5 ); // + drvDB_WriteReg8Bit ( 0x3C, 0xE5, 0x78 ); // + + drvDB_WriteReg8Bit ( 0x1E, 0x04, 0x9F ); + drvDB_WriteReg8Bit ( 0x1E, 0x05, 0x82 ); + + drvDB_WriteReg8Bit ( 0x0F, 0xE6, 0x00 ); + mdelay ( 100 ); + break; + } + + // polling 0x3CE4 is 0x2F43 + do + { + reg_data = drvDB_ReadReg ( 0x3C, 0xE4 ); + } + while ( reg_data != 0x2F43 ); + + // calculate CRC 32 + Init_CRC32_Table ( &crc_tab[0] ); + + for ( i = 0; i < 33; i++ ) // total 33 KB : 2 byte per R/W + { + if ( emem_type == EMEM_INFO ) + i = 32; + + if ( i < 32 ) //emem_main + { + if ( i == 31 ) + { + temp[i][1014] = 0x5A; //Fmr_Loader[1014]=0x5A; + temp[i][1015] = 0xA5; //Fmr_Loader[1015]=0xA5; + + for ( j = 0; j < 1016; j++ ) + { + //crc_main=Get_CRC(Fmr_Loader[j],crc_main,&crc_tab[0]); + crc_main = Get_CRC ( temp[i][j], crc_main, &crc_tab[0] ); + } + } + else + { + for ( j = 0; j < 1024; j++ ) + { + //crc_main=Get_CRC(Fmr_Loader[j],crc_main,&crc_tab[0]); + crc_main = Get_CRC ( temp[i][j], crc_main, &crc_tab[0] ); + } + } + } + else //emem_info + { + for ( j = 0; j < 1024; j++ ) + { + //crc_info=Get_CRC(Fmr_Loader[j],crc_info,&crc_tab[0]); + crc_info = Get_CRC ( g_dwiic_info_data[j], crc_info, &crc_tab[0] ); + } + if ( emem_type == EMEM_MAIN ) break; + } + + //drvDWIIC_MasterTransmit( DWIIC_MODE_DWIIC_ID, 1024, Fmr_Loader ); + HalTscrCDevWriteI2CSeq ( FW_ADDR_MSG21XX_TP, temp[i], 1024 ); + + // polling 0x3CE4 is 0xD0BC + do + { + reg_data = drvDB_ReadReg ( 0x3C, 0xE4 ); + } + while ( reg_data != 0xD0BC ); + + drvDB_WriteReg ( 0x3C, 0xE4, 0x2F43 ); + } + + if ( ( emem_type == EMEM_ALL ) || ( emem_type == EMEM_MAIN ) ) + { + // write file done and check crc + drvDB_WriteReg ( 0x3C, 0xE4, 0x1380 ); + } + mdelay ( 10 ); //MCR_CLBK_DEBUG_DELAY ( 10, MCU_LOOP_DELAY_COUNT_MS ); + + if ( ( emem_type == EMEM_ALL ) || ( emem_type == EMEM_MAIN ) ) + { + // polling 0x3CE4 is 0x9432 + do + { + reg_data = drvDB_ReadReg ( 0x3C, 0xE4 ); + }while ( reg_data != 0x9432 ); + } + + crc_main = crc_main ^ 0xffffffff; + crc_info = crc_info ^ 0xffffffff; + + if ( ( emem_type == EMEM_ALL ) || ( emem_type == EMEM_MAIN ) ) + { + // CRC Main from TP + crc_main_tp = drvDB_ReadReg ( 0x3C, 0x80 ); + crc_main_tp = ( crc_main_tp << 16 ) | drvDB_ReadReg ( 0x3C, 0x82 ); + + // CRC Info from TP + crc_info_tp = drvDB_ReadReg ( 0x3C, 0xA0 ); + crc_info_tp = ( crc_info_tp << 16 ) | drvDB_ReadReg ( 0x3C, 0xA2 ); + } + TP_DEBUG ( "crc_main=0x%x, crc_info=0x%x, crc_main_tp=0x%x, crc_info_tp=0x%x\n", + crc_main, crc_info, crc_main_tp, crc_info_tp ); + + //drvDB_ExitDBBUS(); + + update_pass = 1; + if ( ( emem_type == EMEM_ALL ) || ( emem_type == EMEM_MAIN ) ) + { + if ( crc_main_tp != crc_main ) + update_pass = 0; + + if ( crc_info_tp != crc_info ) + update_pass = 0; + } + + if ( !update_pass ) + { + printk ( "update FAILED\n" ); + _HalTscrHWReset(); + FwDataCnt = 0; + enable_irq(global_irq); + return ( 0 ); + } + + printk ( "update OK\n" ); + _HalTscrHWReset(); + FwDataCnt = 0; + enable_irq(global_irq); + return size; +} + +#define _FW_UPDATE_C3_ +#ifdef _FW_UPDATE_C3_ +static ssize_t firmware_update_store ( struct device *dev, + struct device_attribute *attr, const char *buf, size_t size ) +{ + u8 i; + u8 dbbus_tx_data[4]; + unsigned char dbbus_rx_data[2] = {0}; + disable_irq(global_irq); + + _HalTscrHWReset(); + + // Erase TP Flash first + dbbusDWIICEnterSerialDebugMode(); + dbbusDWIICStopMCU(); + dbbusDWIICIICUseBus(); + dbbusDWIICIICReshape(); + mdelay ( 300 ); + + // Disable the Watchdog + dbbus_tx_data[0] = 0x10; + dbbus_tx_data[1] = 0x3C; + dbbus_tx_data[2] = 0x60; + dbbus_tx_data[3] = 0x55; + HalTscrCDevWriteI2CSeq ( FW_ADDR_MSG21XX, dbbus_tx_data, 4 ); + dbbus_tx_data[0] = 0x10; + dbbus_tx_data[1] = 0x3C; + dbbus_tx_data[2] = 0x61; + dbbus_tx_data[3] = 0xAA; + HalTscrCDevWriteI2CSeq ( FW_ADDR_MSG21XX, dbbus_tx_data, 4 ); + // Stop MCU + dbbus_tx_data[0] = 0x10; + dbbus_tx_data[1] = 0x0F; + dbbus_tx_data[2] = 0xE6; + dbbus_tx_data[3] = 0x01; + HalTscrCDevWriteI2CSeq ( FW_ADDR_MSG21XX, dbbus_tx_data, 4 ); + ///////////////////////// + // Difference between C2 and C3 + ///////////////////////// + // c2:2133 c32:2133a(2) c33:2138 + //check id + dbbus_tx_data[0] = 0x10; + dbbus_tx_data[1] = 0x1E; + dbbus_tx_data[2] = 0xCC; + HalTscrCDevWriteI2CSeq ( FW_ADDR_MSG21XX, dbbus_tx_data, 3 ); + HalTscrCReadI2CSeq ( FW_ADDR_MSG21XX, &dbbus_rx_data[0], 2 ); + if ( dbbus_rx_data[0] == 2 ) + { + // check version + dbbus_tx_data[0] = 0x10; + dbbus_tx_data[1] = 0x3C; + dbbus_tx_data[2] = 0xEA; + HalTscrCDevWriteI2CSeq ( FW_ADDR_MSG21XX, dbbus_tx_data, 3 ); + HalTscrCReadI2CSeq ( FW_ADDR_MSG21XX, &dbbus_rx_data[0], 2 ); + TP_DEBUG ( "dbbus_rx version[0]=0x%x", dbbus_rx_data[0] ); + + if ( dbbus_rx_data[0] == 3 ){ + return firmware_update_c33 ( dev, attr, buf, size, EMEM_MAIN ); + } + else{ + + return firmware_update_c32 ( dev, attr, buf, size, EMEM_ALL ); + } + } + else + { + return firmware_update_c2 ( dev, attr, buf, size ); + } +} +#else +static ssize_t firmware_update_store ( struct device *dev, + struct device_attribute *attr, const char *buf, size_t size ) +{ + u8 i; + u8 dbbus_tx_data[4]; + unsigned char dbbus_rx_data[2] = {0}; + + _HalTscrHWReset(); + + // 1. Erase TP Flash first + dbbusDWIICEnterSerialDebugMode(); + dbbusDWIICStopMCU(); + dbbusDWIICIICUseBus(); + dbbusDWIICIICReshape(); + mdelay ( 300 ); + + // Disable the Watchdog + dbbus_tx_data[0] = 0x10; + dbbus_tx_data[1] = 0x3C; + dbbus_tx_data[2] = 0x60; + dbbus_tx_data[3] = 0x55; + HalTscrCDevWriteI2CSeq ( FW_ADDR_MSG21XX, dbbus_tx_data, 4 ); + dbbus_tx_data[0] = 0x10; + dbbus_tx_data[1] = 0x3C; + dbbus_tx_data[2] = 0x61; + dbbus_tx_data[3] = 0xAA; + HalTscrCDevWriteI2CSeq ( FW_ADDR_MSG21XX, dbbus_tx_data, 4 ); + + // Stop MCU + dbbus_tx_data[0] = 0x10; + dbbus_tx_data[1] = 0x0F; + dbbus_tx_data[2] = 0xE6; + dbbus_tx_data[3] = 0x01; + HalTscrCDevWriteI2CSeq ( FW_ADDR_MSG21XX, dbbus_tx_data, 4 ); + + // set FRO to 50M + dbbus_tx_data[0] = 0x10; + dbbus_tx_data[1] = 0x11; + dbbus_tx_data[2] = 0xE2; + HalTscrCDevWriteI2CSeq ( FW_ADDR_MSG21XX, dbbus_tx_data, 3 ); + dbbus_rx_data[0] = 0; + dbbus_rx_data[1] = 0; + HalTscrCReadI2CSeq ( FW_ADDR_MSG21XX, &dbbus_rx_data[0], 2 ); + TP_DEBUG ( "dbbus_rx_data[0]=0x%x", dbbus_rx_data[0] ); + dbbus_tx_data[3] = dbbus_rx_data[0] & 0xF7; //Clear Bit 3 + HalTscrCDevWriteI2CSeq ( FW_ADDR_MSG21XX, dbbus_tx_data, 4 ); + + // set MCU clock,SPI clock =FRO + dbbus_tx_data[0] = 0x10; + dbbus_tx_data[1] = 0x1E; + dbbus_tx_data[2] = 0x22; + dbbus_tx_data[3] = 0x00; + HalTscrCDevWriteI2CSeq ( FW_ADDR_MSG21XX, dbbus_tx_data, 4 ); + + dbbus_tx_data[0] = 0x10; + dbbus_tx_data[1] = 0x1E; + dbbus_tx_data[2] = 0x23; + dbbus_tx_data[3] = 0x00; + HalTscrCDevWriteI2CSeq ( FW_ADDR_MSG21XX, dbbus_tx_data, 4 ); + + // Enable slave's ISP ECO mode + dbbus_tx_data[0] = 0x10; + dbbus_tx_data[1] = 0x08; + dbbus_tx_data[2] = 0x0c; + dbbus_tx_data[3] = 0x08; + HalTscrCDevWriteI2CSeq ( FW_ADDR_MSG21XX, dbbus_tx_data, 4 ); + + // Enable SPI Pad + dbbus_tx_data[0] = 0x10; + dbbus_tx_data[1] = 0x1E; + dbbus_tx_data[2] = 0x02; + HalTscrCDevWriteI2CSeq ( FW_ADDR_MSG21XX, dbbus_tx_data, 3 ); + HalTscrCReadI2CSeq ( FW_ADDR_MSG21XX, &dbbus_rx_data[0], 2 ); + TP_DEBUG ( "dbbus_rx_data[0]=0x%x", dbbus_rx_data[0] ); + dbbus_tx_data[3] = ( dbbus_rx_data[0] | 0x20 ); //Set Bit 5 + HalTscrCDevWriteI2CSeq ( FW_ADDR_MSG21XX, dbbus_tx_data, 4 ); + + // WP overwrite + dbbus_tx_data[0] = 0x10; + dbbus_tx_data[1] = 0x1E; + dbbus_tx_data[2] = 0x0E; + dbbus_tx_data[3] = 0x02; + HalTscrCDevWriteI2CSeq ( FW_ADDR_MSG21XX, dbbus_tx_data, 4 ); + + // set pin high + dbbus_tx_data[0] = 0x10; + dbbus_tx_data[1] = 0x1E; + dbbus_tx_data[2] = 0x10; + dbbus_tx_data[3] = 0x08; + HalTscrCDevWriteI2CSeq ( FW_ADDR_MSG21XX, dbbus_tx_data, 4 ); + + dbbusDWIICIICNotUseBus(); + dbbusDWIICNotStopMCU(); + dbbusDWIICExitSerialDebugMode(); + + drvISP_EntryIspMode(); + drvISP_ChipErase(); + _HalTscrHWReset(); + mdelay ( 300 ); + + // 2.Program and Verify + dbbusDWIICEnterSerialDebugMode(); + dbbusDWIICStopMCU(); + dbbusDWIICIICUseBus(); + dbbusDWIICIICReshape(); + + // Disable the Watchdog + dbbus_tx_data[0] = 0x10; + dbbus_tx_data[1] = 0x3C; + dbbus_tx_data[2] = 0x60; + dbbus_tx_data[3] = 0x55; + HalTscrCDevWriteI2CSeq ( FW_ADDR_MSG21XX, dbbus_tx_data, 4 ); + dbbus_tx_data[0] = 0x10; + dbbus_tx_data[1] = 0x3C; + dbbus_tx_data[2] = 0x61; + dbbus_tx_data[3] = 0xAA; + HalTscrCDevWriteI2CSeq ( FW_ADDR_MSG21XX, dbbus_tx_data, 4 ); + + // Stop MCU + dbbus_tx_data[0] = 0x10; + dbbus_tx_data[1] = 0x0F; + dbbus_tx_data[2] = 0xE6; + dbbus_tx_data[3] = 0x01; + HalTscrCDevWriteI2CSeq ( FW_ADDR_MSG21XX, dbbus_tx_data, 4 ); + + // set FRO to 50M + dbbus_tx_data[0] = 0x10; + dbbus_tx_data[1] = 0x11; + dbbus_tx_data[2] = 0xE2; + HalTscrCDevWriteI2CSeq ( FW_ADDR_MSG21XX, dbbus_tx_data, 3 ); + dbbus_rx_data[0] = 0; + dbbus_rx_data[1] = 0; + HalTscrCReadI2CSeq ( FW_ADDR_MSG21XX, &dbbus_rx_data[0], 2 ); + TP_DEBUG ( "dbbus_rx_data[0]=0x%x", dbbus_rx_data[0] ); + dbbus_tx_data[3] = dbbus_rx_data[0] & 0xF7; //Clear Bit 3 + HalTscrCDevWriteI2CSeq ( FW_ADDR_MSG21XX, dbbus_tx_data, 4 ); + + // set MCU clock,SPI clock =FRO + dbbus_tx_data[0] = 0x10; + dbbus_tx_data[1] = 0x1E; + dbbus_tx_data[2] = 0x22; + dbbus_tx_data[3] = 0x00; + HalTscrCDevWriteI2CSeq ( FW_ADDR_MSG21XX, dbbus_tx_data, 4 ); + + dbbus_tx_data[0] = 0x10; + dbbus_tx_data[1] = 0x1E; + dbbus_tx_data[2] = 0x23; + dbbus_tx_data[3] = 0x00; + HalTscrCDevWriteI2CSeq ( FW_ADDR_MSG21XX, dbbus_tx_data, 4 ); + + // Enable slave's ISP ECO mode + dbbus_tx_data[0] = 0x10; + dbbus_tx_data[1] = 0x08; + dbbus_tx_data[2] = 0x0c; + dbbus_tx_data[3] = 0x08; + HalTscrCDevWriteI2CSeq ( FW_ADDR_MSG21XX, dbbus_tx_data, 4 ); + + // Enable SPI Pad + dbbus_tx_data[0] = 0x10; + dbbus_tx_data[1] = 0x1E; + dbbus_tx_data[2] = 0x02; + HalTscrCDevWriteI2CSeq ( FW_ADDR_MSG21XX, dbbus_tx_data, 3 ); + HalTscrCReadI2CSeq ( FW_ADDR_MSG21XX, &dbbus_rx_data[0], 2 ); + TP_DEBUG ( "dbbus_rx_data[0]=0x%x", dbbus_rx_data[0] ); + dbbus_tx_data[3] = ( dbbus_rx_data[0] | 0x20 ); //Set Bit 5 + HalTscrCDevWriteI2CSeq ( FW_ADDR_MSG21XX, dbbus_tx_data, 4 ); + + // WP overwrite + dbbus_tx_data[0] = 0x10; + dbbus_tx_data[1] = 0x1E; + dbbus_tx_data[2] = 0x0E; + dbbus_tx_data[3] = 0x02; + HalTscrCDevWriteI2CSeq ( FW_ADDR_MSG21XX, dbbus_tx_data, 4 ); + + // set pin high + dbbus_tx_data[0] = 0x10; + dbbus_tx_data[1] = 0x1E; + dbbus_tx_data[2] = 0x10; + dbbus_tx_data[3] = 0x08; + HalTscrCDevWriteI2CSeq ( FW_ADDR_MSG21XX, dbbus_tx_data, 4 ); + + dbbusDWIICIICNotUseBus(); + dbbusDWIICNotStopMCU(); + dbbusDWIICExitSerialDebugMode(); + + /////////////////////////////////////// + // Start to load firmware + /////////////////////////////////////// + drvISP_EntryIspMode(); + + for ( i = 0; i < 94; i++ ) // total 94 KB : 1 byte per R/W + { + drvISP_Program ( i, temp[i] ); // program to slave's flash + drvISP_Verify ( i, temp[i] ); //verify data + } + TP_DEBUG ( "update OK\n" ); + drvISP_ExitIspMode(); + FwDataCnt = 0; + + return size; +} +#endif +static DEVICE_ATTR(update, 0664, firmware_update_show, firmware_update_store); +#if 0 +/*test=================*/ +static ssize_t firmware_clear_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + printk(" +++++++ [%s] Enter!++++++\n", __func__); + u16 k=0,i = 0, j = 0; + u8 bWriteData[5] = + { + 0x10, 0x03, 0, 0, 0 + }; + u8 RX_data[256]; + u8 bWriteData1 = 0x12; + u32 addr = 0; + u32 timeOutCount=0; + for (k = 0; k < 94; i++) // total 94 KB : 1 byte per R/W + { + addr = k * 1024; + for (j = 0; j < 8; j++) //128*8 cycle + { + bWriteData[2] = (u8)((addr + j * 128) >> 16); + bWriteData[3] = (u8)((addr + j * 128) >> 8); + bWriteData[4] = (u8)(addr + j * 128); + //msctpc_LoopDelay ( 1 ); // delay about 100us***** + udelay(150);//200); + + timeOutCount=0; + while ( ( drvISP_ReadStatus() & 0x01 ) == 0x01 ) + { + timeOutCount++; + if ( timeOutCount >= 100000 ) + break; /* around 1 sec timeout */ + } + + HalTscrCDevWriteI2CSeq(FW_UPDATE_ADDR_MSG21XX, bWriteData, 5); //write read flash addr + //msctpc_LoopDelay ( 1 ); // delay about 100us***** + udelay(150);//200); + drvISP_Read(128, RX_data); + HalTscrCDevWriteI2CSeq(FW_UPDATE_ADDR_MSG21XX, &bWriteData1, 1); //cmd end + for (i = 0; i < 128; i++) //log out if verify error + { + if (RX_data[i] != 0xFF) + { + //TP_DEBUG(printk("k=%d,j=%d,i=%d===============erase not clean================",k,j,i);) + printk("k=%d,j=%d,i=%d erase not clean !!",k,j,i); + } + } + } + } + TP_DEBUG("read finish\n"); + return sprintf(buf, "%s\n", fw_version); +} + +static ssize_t firmware_clear_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t size) +{ + + u8 dbbus_tx_data[4]; + unsigned char dbbus_rx_data[2] = {0}; + printk(" +++++++ [%s] Enter!++++++\n", __func__); + //msctpc_LoopDelay ( 100 ); // delay about 100ms***** + + // Enable slave's ISP ECO mode + + dbbus_tx_data[0] = 0x10; + dbbus_tx_data[1] = 0x08; + dbbus_tx_data[2] = 0x0c; + dbbus_tx_data[3] = 0x08; + + // Disable the Watchdog + HalTscrCDevWriteI2CSeq(FW_ADDR_MSG21XX, dbbus_tx_data, 4); + + dbbus_tx_data[0] = 0x10; + dbbus_tx_data[1] = 0x11; + dbbus_tx_data[2] = 0xE2; + dbbus_tx_data[3] = 0x00; + HalTscrCDevWriteI2CSeq(FW_ADDR_MSG21XX, dbbus_tx_data, 4); + + dbbus_tx_data[0] = 0x10; + dbbus_tx_data[1] = 0x3C; + dbbus_tx_data[2] = 0x60; + dbbus_tx_data[3] = 0x55; + HalTscrCDevWriteI2CSeq(FW_ADDR_MSG21XX, dbbus_tx_data, 4); + + dbbus_tx_data[0] = 0x10; + dbbus_tx_data[1] = 0x3C; + dbbus_tx_data[2] = 0x61; + dbbus_tx_data[3] = 0xAA; + HalTscrCDevWriteI2CSeq(FW_ADDR_MSG21XX, dbbus_tx_data, 4); + + //Stop MCU + dbbus_tx_data[0] = 0x10; + dbbus_tx_data[1] = 0x0F; + dbbus_tx_data[2] = 0xE6; + dbbus_tx_data[3] = 0x01; + HalTscrCDevWriteI2CSeq(FW_ADDR_MSG21XX, dbbus_tx_data, 4); + + //Enable SPI Pad + dbbus_tx_data[0] = 0x10; + dbbus_tx_data[1] = 0x1E; + dbbus_tx_data[2] = 0x02; + HalTscrCDevWriteI2CSeq(FW_ADDR_MSG21XX, dbbus_tx_data, 3); + HalTscrCReadI2CSeq(FW_ADDR_MSG21XX, &dbbus_rx_data[0], 2); + TP_DEBUG(printk("dbbus_rx_data[0]=0x%x", dbbus_rx_data[0]);) + dbbus_tx_data[3] = (dbbus_rx_data[0] | 0x20); //Set Bit 5 + HalTscrCDevWriteI2CSeq(FW_ADDR_MSG21XX, dbbus_tx_data, 4); + + dbbus_tx_data[0] = 0x10; + dbbus_tx_data[1] = 0x1E; + dbbus_tx_data[2] = 0x25; + HalTscrCDevWriteI2CSeq(FW_ADDR_MSG21XX, dbbus_tx_data, 3); + + dbbus_rx_data[0] = 0; + dbbus_rx_data[1] = 0; + HalTscrCReadI2CSeq(FW_ADDR_MSG21XX, &dbbus_rx_data[0], 2); + TP_DEBUG(printk("dbbus_rx_data[0]=0x%x", dbbus_rx_data[0]);) + dbbus_tx_data[3] = dbbus_rx_data[0] & 0xFC; //Clear Bit 1,0 + HalTscrCDevWriteI2CSeq(FW_ADDR_MSG21XX, dbbus_tx_data, 4); + + //WP overwrite + dbbus_tx_data[0] = 0x10; + dbbus_tx_data[1] = 0x1E; + dbbus_tx_data[2] = 0x0E; + dbbus_tx_data[3] = 0x02; + HalTscrCDevWriteI2CSeq(FW_ADDR_MSG21XX, dbbus_tx_data, 4); + + + //set pin high + dbbus_tx_data[0] = 0x10; + dbbus_tx_data[1] = 0x1E; + dbbus_tx_data[2] = 0x10; + dbbus_tx_data[3] = 0x08; + HalTscrCDevWriteI2CSeq(FW_ADDR_MSG21XX, dbbus_tx_data, 4); + //set FRO to 50M + dbbus_tx_data[0] = 0x10; + dbbus_tx_data[1] = 0x11; + dbbus_tx_data[2] = 0xE2; + HalTscrCDevWriteI2CSeq(FW_ADDR_MSG21XX, dbbus_tx_data, 3); + dbbus_rx_data[0] = 0; + dbbus_rx_data[1] = 0; + HalTscrCReadI2CSeq(FW_ADDR_MSG21XX, &dbbus_rx_data[0], 2); + TP_DEBUG(printk("dbbus_rx_data[0]=0x%x", dbbus_rx_data[0]);) + dbbus_tx_data[3] = dbbus_rx_data[0] & 0xF7; //Clear Bit 1,0 + HalTscrCDevWriteI2CSeq(FW_ADDR_MSG21XX, dbbus_tx_data, 4); + + dbbusDWIICIICNotUseBus(); + dbbusDWIICNotStopMCU(); + dbbusDWIICExitSerialDebugMode(); + + /////////////////////////////////////// + // Start to load firmware + /////////////////////////////////////// + drvISP_EntryIspMode(); + TP_DEBUG(printk("chip erase+\n");) + drvISP_BlockErase(0x00000); + TP_DEBUG(printk("chip erase-\n");) + drvISP_ExitIspMode(); + return size; +} +static DEVICE_ATTR(clear, 0664, firmware_clear_show, firmware_clear_store); +#endif //0 +/*test=================*/ +/*Add by Tracy.Lin for update touch panel firmware and get fw version*/ + +static ssize_t firmware_version_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + TP_DEBUG("*** firmware_version_show fw_version = %s***\n", fw_version); + return sprintf(buf, "%s\n", fw_version); +} + +static ssize_t firmware_version_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t size) +{ + unsigned char dbbus_tx_data[3]; + unsigned char dbbus_rx_data[4] ; + unsigned short major=0, minor=0; +/* + dbbusDWIICEnterSerialDebugMode(); + dbbusDWIICStopMCU(); + dbbusDWIICIICUseBus(); + dbbusDWIICIICReshape(); + +*/ + if(NULL==fw_version) + { + fw_version = kzalloc(sizeof(char), GFP_KERNEL); + } + + //Get_Chip_Version(); + dbbus_tx_data[0] = 0x53; + dbbus_tx_data[1] = 0x00; + dbbus_tx_data[2] = 0x2a; + HalTscrCDevWriteI2CSeq(FW_ADDR_MSG21XX_TP, &dbbus_tx_data[0], 3); + HalTscrCReadI2CSeq(FW_ADDR_MSG21XX_TP, &dbbus_rx_data[0], 4); + + major = (dbbus_rx_data[1]<<8)+dbbus_rx_data[0]; + minor = (dbbus_rx_data[3]<<8)+dbbus_rx_data[2]; + + TP_DEBUG("***major = %d ***\n", major); + TP_DEBUG("***minor = %d ***\n", minor); + sprintf(fw_version,"%03d%03d", major, minor); + //TP_DEBUG(printk("***fw_version = %s ***\n", fw_version);) + + return size; +} +static DEVICE_ATTR(version, 0664, firmware_version_show, firmware_version_store); + +static ssize_t firmware_data_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return FwDataCnt; +} + +static ssize_t firmware_data_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t size) +{ + int i; + TP_DEBUG("***FwDataCnt = %d ***\n", FwDataCnt); + for (i = 0; i < 1024; i++) + { + memcpy(temp[FwDataCnt], buf, 1024); + } + FwDataCnt++; + return size; +} +static DEVICE_ATTR(data, 0664, firmware_data_show, firmware_data_store); +#endif //__FIRMWARE_UPDATE__ + +static int pixcir_i2c_txdata(char *txdata, int length) +{ + int ret; + struct i2c_msg msg[] = { + { + .addr = msg21xx_i2c_client->addr, + .flags = 0, + .len = length, + .buf = txdata, + }, + }; + + ret = i2c_transfer(msg21xx_i2c_client->adapter, msg, 1); + if (ret < 0) + pr_err("%s i2c write error: %d\n", __func__, ret); + + return ret; +} + +static int pixcir_i2c_write_data(unsigned char addr, unsigned char data) +{ + unsigned char buf[2]; + buf[0]=addr; + buf[1]=data; + return pixcir_i2c_txdata(buf, 2); +} + +static bool msg2138_i2c_read(char *pbt_buf, int dw_lenth) +{ + int ret; + // pr_ch("The msg_i2c_client->addr=0x%x\n",i2c_client->addr); + ret = i2c_master_recv(msg21xx_i2c_client, pbt_buf, dw_lenth); + + if(ret <= 0) + { + //pr_tp("msg_i2c_read_interface error\n"); + return false; + } + + return true; +} + +static bool msg2138_i2c_write(char *pbt_buf, int dw_lenth) +{ + int ret; + // pr_ch("The msg_i2c_client->addr=0x%x\n",i2c_client->addr); + ret = i2c_master_send(msg21xx_i2c_client, pbt_buf, dw_lenth); + + if(ret <= 0) + { + //pr_tp("msg_i2c_read_interface error\n"); + return false; + } + + return true; +} + +static DEVICE_ATTR(calibrate, S_IRUGO | S_IWUSR, NULL, pixcir_set_calibrate); +static DEVICE_ATTR(suspend, S_IRUGO | S_IWUSR, pixcir_show_suspend, pixcir_store_suspend); + +static ssize_t pixcir_set_calibrate(struct device* cd, struct device_attribute *attr, + const char* buf, size_t len) +{ + unsigned long on_off = simple_strtoul(buf, NULL, 10); + + if(on_off==1) + { + printk("%s: PIXCIR calibrate\n",__func__); + pixcir_i2c_write_data(0x3a , 0x03); + msleep(5*1000); + } + + return len; +} + +static ssize_t pixcir_show_suspend(struct device* cd, + struct device_attribute *attr, char* buf) +{ + ssize_t ret = 0; + + if(suspend_flag==1) + sprintf(buf, "Pixcir Suspend\n"); + else + sprintf(buf, "Pixcir Resume\n"); + + ret = strlen(buf) + 1; + + return ret; +} + +static ssize_t pixcir_store_suspend(struct device* cd, struct device_attribute *attr, + const char* buf, size_t len) +{ + unsigned long on_off = simple_strtoul(buf, NULL, 10); + suspend_flag = on_off; + + if(on_off==1) + { + printk("Pixcir Entry Suspend\n"); + pixcir_ts_suspend(NULL); + } + else + { + printk("Pixcir Entry Resume\n"); + pixcir_ts_resume(NULL); + + } + + return len; +} + +static void pixcir_reset(void) +{ + struct msg2138_ts_platform_data *pdata = msg21xx_i2c_ts_data->platform_data; + + PIXCIR_DBG("%s\n",__func__); + gpio_set_value(pdata->reset_gpio_number, 1); + msleep(3); + gpio_set_value(pdata->reset_gpio_number, 0); + msleep(310); + gpio_set_value(pdata->reset_gpio_number, 1); + msleep(100); +} + +//cg,20130929,start +#ifdef SYSFS_DEBUG +static void cg_tpfwver_readfwver() +{ + unsigned char dbbus_tx_data[3]; + unsigned char dbbus_rx_data[4] ; + unsigned short major=0, minor=0; + u8 count = 0; + int ret = 0; + + for(count=0;count<5;count++) + { + pixcir_reset(); + msleep(100); + if(NULL == cg_fw_version) + { + cg_fw_version = kzalloc(sizeof(char), GFP_KERNEL); + } + + //Get_Chip_Version(); + dbbus_tx_data[0] = 0x53; + dbbus_tx_data[1] = 0x00; + dbbus_tx_data[2] = 0x2a; + ret = HalTscrCDevWriteI2CSeq(FW_ADDR_MSG21XX_TP, &dbbus_tx_data[0], 3); + if(ret<0) + { + printk("*** write fail ret = %d ***\n", ret); + continue; + } + msleep(100); + ret = HalTscrCReadI2CSeq(FW_ADDR_MSG21XX_TP, &dbbus_rx_data[0], 4); + if(ret<0) + { + printk("*** read fail ret = %d ***\n", ret); + continue; + } + major =(dbbus_rx_data[1]<<8)+dbbus_rx_data[0]; + if(0==major) + { + printk("*** major fail = %d ***\n", major); + continue; + } + minor =(dbbus_rx_data[3]<<8)+dbbus_rx_data[2]; + printk("***major = %d ***\n", major); + printk("***minor = %d ***\n", minor); + + sprintf(cg_fw_version,"%03d%03d", major, minor); + printk("***tp_fw_version = %s ***\n", cg_fw_version); + break; + } + printk("*** count = %d ***\n", count); +} + +static ssize_t cg_tpfwver_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + cg_tpfwver_readfwver(); + return sprintf(buf, "%s\n", cg_fw_version); + +} + +static ssize_t cg_tpfwver_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t size) +{ + return -EPERM; + +} +static DEVICE_ATTR(fwversion, S_IRUGO, cg_tpfwver_show,NULL); + +#endif +//cg,20130929,end + +static int pixcir_create_sysfs(struct i2c_client *client) +{ + int err; + struct device *dev = &(client->dev); + + PIXCIR_DBG("%s\n", __func__); + + err = device_create_file(dev, &dev_attr_calibrate); + err = device_create_file(dev, &dev_attr_suspend); + #ifdef SYSFS_DEBUG + err = device_create_file(dev, &dev_attr_fwversion); //cg,20130929 + #endif + return err; +} + +#ifdef CONFIG_HAS_EARLYSUSPEND +static void pixcir_ts_suspend(struct early_suspend *handler) +{ + struct msg2138_ts_platform_data *pdata = msg21xx_i2c_ts_data->platform_data; + printk("==%s==\n", __func__); + disable_irq_nosync(global_irq); + msleep(3); + gpio_set_value(pdata->reset_gpio_number, 0); + msleep(10); +} +static void pixcir_ts_resume(struct early_suspend *handler) +{ + //unsigned char rdbuf[27]; + //int num = 10; + //disable_irq_nosync(global_irq); + +#if 0 + struct pixcir_i2c_ts_data *pixcir_ts = (struct pixcir_i2c_ts_data *)i2c_get_clientdata(msg21xx_i2c_client); + queue_work(pixcir_ts->ts_resume_workqueue, &pixcir_ts->resume_work); +#endif + printk("==%s==start==\n", __func__); + pixcir_reset(); + enable_irq(global_irq); + printk("==%s==end==\n", __func__); + +} +#endif + +#ifdef TOUCH_VIRTUAL_KEYS +/*static ssize_t virtual_keys_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) +{ + return sprintf(buf, + __stringify(EV_KEY) ":" __stringify(KEY_HOMEPAGE) ":192:1000:64:60" + ":" __stringify(EV_KEY) ":" __stringify(KEY_MENU) ":256:1000:64:60" + ":" __stringify(EV_KEY) ":" __stringify(KEY_BACK) ":128:1000:64:60" + ":" __stringify(EV_KEY) ":" __stringify(KEY_SEARCH) ":64:1000:64:60" + "\n"); +}*/ +static ssize_t virtual_keys_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) +{ + struct pixcir_i2c_ts_data *data = i2c_get_clientdata(msg21xx_i2c_client); + struct msg2138_ts_platform_data *pdata = data->platform_data; + return sprintf(buf,"%s:%s:%d:%d:%d:%d:%s:%s:%d:%d:%d:%d:%s:%s:%d:%d:%d:%d\n" + ,__stringify(EV_KEY), __stringify(KEY_MENU),pdata ->virtualkeys[0],pdata ->virtualkeys[1],pdata ->virtualkeys[2],pdata ->virtualkeys[3] + ,__stringify(EV_KEY), __stringify(KEY_HOMEPAGE),pdata ->virtualkeys[4],pdata ->virtualkeys[5],pdata ->virtualkeys[6],pdata ->virtualkeys[7] + ,__stringify(EV_KEY), __stringify(KEY_BACK),pdata ->virtualkeys[8],pdata ->virtualkeys[9],pdata ->virtualkeys[10],pdata ->virtualkeys[11]); +} + +static struct kobj_attribute virtual_keys_attr = { + .attr = { + .name = "virtualkeys.msg2138_ts", + .mode = S_IRUGO, + }, + .show = &virtual_keys_show, +}; + +static struct attribute *properties_attrs[] = { + &virtual_keys_attr.attr, + NULL +}; + +static struct attribute_group properties_attr_group = { + .attrs = properties_attrs, +}; + +static void pixcir_ts_virtual_keys_init(void) +{ + int ret; + struct kobject *properties_kobj; + + PIXCIR_DBG("%s\n",__func__); + + properties_kobj = kobject_create_and_add("board_properties", NULL); + if (properties_kobj) + ret = sysfs_create_group(properties_kobj, + &properties_attr_group); + if (!properties_kobj || ret) + pr_err("failed to create board_properties\n"); +} +#endif + +static int getchipType(void) +{ + int curr_ic_type = 0; + u8 dbbus_tx_data[4]; + unsigned char dbbus_rx_data[2] = {0}; + int error = 0; + + //check id + dbbus_tx_data[0] = 0x10; + dbbus_tx_data[1] = 0x1E; + dbbus_tx_data[2] = 0xCC; + error = HalTscrCDevWriteI2CSeq ( FW_ADDR_MSG21XX, dbbus_tx_data, 3 ); + if (error < 0) { + pr_err("[MSG2138A] getchipType() write i2c error %d\n",error); + return error; + } + error = HalTscrCReadI2CSeq ( FW_ADDR_MSG21XX, &dbbus_rx_data[0], 2 ); + if (error < 0) { + pr_err("[MSG2138A] getchipType() read i2c error %d\n",error); + return error; + } + if ( dbbus_rx_data[0] == 2 ) { + curr_ic_type = CTP_ID_MSG21XXA; + } else { + curr_ic_type = CTP_ID_MSG21XX; + } + + return curr_ic_type; + +} + +static void pixcir_ts_hw_init(struct pixcir_i2c_ts_data *tsdata) +{ + struct regulator *g_cg_reg_vdd; + struct msg2138_ts_platform_data *pdata = tsdata->platform_data; + struct i2c_client *client = tsdata->client; + int err= 0; + gpio_request(pdata->reset_gpio_number, "gpio_tp_rst"); + gpio_request(pdata->irq_gpio_number, "gpio_tp_irq"); + gpio_direction_output(pdata->reset_gpio_number,1); + gpio_direction_input(pdata->irq_gpio_number); + g_cg_reg_vdd = regulator_get(&client->dev, pdata->vdd_name); + if (!WARN(IS_ERR(g_cg_reg_vdd), "[MSG2138] pixcir_ts_hw_init regulator: failed to get %s.\n", pdata->vdd_name)) { + regulator_set_voltage(g_cg_reg_vdd, 2800000, 2800000); + err = regulator_enable(g_cg_reg_vdd); + } + msleep(100); + pixcir_reset(); +} + +/*static int attb_read_val(void) +{ + struct msg2138_ts_platform_data *pdata = msg21xx_i2c_ts_data->platform_data; + return gpio_get_value(pdata->irq_gpio_number); +}*/ + +unsigned char tpd_check_sum(unsigned char *pval) +{ + int i, sum = 0; + + for(i = 0; i < 7; i++) + { + sum += pval[i]; + } + + return (unsigned char)((-sum) & 0xFF); +} + +static void return_i2c_dev(struct i2c_dev *i2c_dev) +{ + spin_lock(&i2c_dev_list_lock); + list_del(&i2c_dev->list); + spin_unlock(&i2c_dev_list_lock); + kfree(i2c_dev); +} + +static struct i2c_dev *i2c_dev_get_by_minor(unsigned index) +{ + struct i2c_dev *i2c_dev; + i2c_dev = NULL; + + spin_lock(&i2c_dev_list_lock); + list_for_each_entry(i2c_dev, &i2c_dev_list, list) + { + if (i2c_dev->adap->nr == index) + goto found; + } + i2c_dev = NULL; + found: spin_unlock(&i2c_dev_list_lock); + return i2c_dev; +} + +static struct i2c_dev *get_free_i2c_dev(struct i2c_adapter *adap) +{ + struct i2c_dev *i2c_dev; + + if (adap->nr >= I2C_MINORS) { + printk(KERN_ERR "i2c-dev: Out of device minors (%d)\n", + adap->nr); + return ERR_PTR(-ENODEV); + } + + i2c_dev = kzalloc(sizeof(*i2c_dev), GFP_KERNEL); + if (!i2c_dev) + return ERR_PTR(-ENOMEM); + + i2c_dev->adap = adap; + + spin_lock(&i2c_dev_list_lock); + list_add_tail(&i2c_dev->list, &i2c_dev_list); + spin_unlock(&i2c_dev_list_lock); + return i2c_dev; +} +/*********************************Bee-0928-bottom**************************************/ + +struct point_node_t{ + unsigned char active ; + unsigned char finger_id; + int posx; + int posy; +}; + +static struct point_node_t point_slot[MAX_FINGER_NUM*2]; +static int keycode; +static int sy_rxdata(struct touch_info *cinfo, struct touch_info *pinfo) + { + //u32 retval; + //static unsigned char tt_mode; + //pinfo->count = cinfo->count; + unsigned char reg_val[8] = {0}; + int dst_x=0,dst_y=0; + unsigned int temp_checksum; + struct TouchScreenInfo_t touchData; + //unsigned char touchkeycode = 0; + //static int preKeyStatus; + + //TPD_DEBUG("pinfo->count =%d\n",pinfo->count); + cinfo->count = 0; //touch end + msg2138_i2c_read(reg_val, 8); + + //retval = i2c_smbus_read_i2c_block_data(msg21xx_i2c_client, TPD_REG_BASE, 8, (unsigned char *)&g_operation_data); + //retval += i2c_smbus_read_i2c_block_data(msg21xx_i2c_client, TPD_REG_BASE + 8, 8, (((unsigned char *)(&g_operation_data)) + 8)); + + cinfo->x1 = ((reg_val[1] & 0xF0) << 4) | reg_val[2]; + cinfo->y1 = ((reg_val[1] & 0x0F) << 8) | reg_val[3]; + dst_x = ((reg_val[4] & 0xF0) << 4) | reg_val[5]; + dst_y = ((reg_val[4] & 0x0F) << 8) | reg_val[6]; + + + temp_checksum = tpd_check_sum(reg_val); + + if((temp_checksum==reg_val[7])&&(reg_val[0] == 0x52)) + { + + if ((reg_val[1] == 0xFF) && (reg_val[2] == 0xFF) && (reg_val[3] == 0xFF) && (reg_val[4] == 0xFF) && (reg_val[6] == 0xFF)) + { + cinfo->x1 = 0; // final X coordinate + cinfo->y1 = 0; // final Y coordinate + + if((reg_val[5]==0x0)||(reg_val[5]==0xFF)) + { + cinfo->count = 0; //touch end + touchData.nTouchKeyCode = 0; //TouchKeyMode + touchData.nTouchKeyMode = 0; //TouchKeyMode + keycode=0; + } + else + { + touchData.nTouchKeyMode = 1; //TouchKeyMode + touchData.nTouchKeyCode = reg_val[5]; //TouchKeyCode + keycode= reg_val[5]; + + if(keycode==1) + { + cinfo->x1 = 256; // final X coordinate + cinfo->y1 = 1000; // final Y coordinate + + } + else if(keycode==2) + { + cinfo->x1 = 192; // final X coordinate + cinfo->y1 = 1000; // final Y coordinate + + } + else if (keycode==4) + { + cinfo->x1 = 128; // final X coordinate + cinfo->y1 = 1000; // final Y coordinate + + } + + cinfo->count = 1; + } + } + else + { + touchData.nTouchKeyMode = 0; //Touch on screen... + + if ((dst_x == 0) && (dst_y == 0)) + { + cinfo->count = 1; //one touch + #if TP_XY_CHANGE + xysawp_temp=cinfo->x1; + //cinfo->x1=2047-cinfo->y1; + cinfo->x1=cinfo->y1; + cinfo->y1=xysawp_temp; + #endif + + #ifdef TP_X_CHANGE + cinfo->x1 = 2047 - cinfo->x1; + #endif + + cinfo->x1 = (cinfo->x1 * MS_TS_MSG21XX_X_MAX) / 2048; + cinfo->y1 = (cinfo->y1 * MS_TS_MSG21XX_Y_MAX) / 2048; + } + else + { + + cinfo->count = 2; //two touch + + + if (dst_x > 2048) //transform the unsigh value to sign value + { + dst_x -= 4096; + } + if (dst_y > 2048) + { + dst_y -= 4096; + } + + cinfo->x2 = (cinfo->x1 + dst_x); + cinfo->y2 = (cinfo->y1 + dst_y); + + #if TP_XY_CHANGE + xysawp_temp=cinfo->x1; + //cinfo->x1=2047-cinfo->y1; + cinfo->x1=cinfo->y1; + cinfo->y1=xysawp_temp; + + xysawp_temp=cinfo->x2; + cinfo->x2=2047-cinfo->y2; + cinfo->y2=xysawp_temp; + #endif + + #ifdef TP_X_CHANGE + cinfo->x1 = 2047 - cinfo->x1; + cinfo->x2 = 2047 - cinfo->x2; + #endif + + cinfo->x1 = (cinfo->x1 * MS_TS_MSG21XX_X_MAX) / 2048; + cinfo->y1 = (cinfo->y1 * MS_TS_MSG21XX_Y_MAX) / 2048; + + cinfo->x2 = (cinfo->x2 * MS_TS_MSG21XX_X_MAX) / 2048; + cinfo->y2 = (cinfo->y2 * MS_TS_MSG21XX_Y_MAX) / 2048; + + } + } + + return 1; + } + return 1; + } +static void pixcir_ts_poscheck(struct pixcir_i2c_ts_data *data) +{ + struct pixcir_i2c_ts_data *tsdata = data; + struct touch_info cinfo, pinfo; + int *p; + unsigned char touch; + unsigned char rdbuf[27]; + int i; + //static int lastkey=0; + // printk("===%s===\n",__func__); + rdbuf[0]=0; + //pixcir_i2c_rxdata(rdbuf, 27); + + //touch = rdbuf[0]&0x07; + sy_rxdata(&cinfo, &pinfo); + touch = cinfo.count; + //button = rdbuf[1]; + //p=&rdbuf[2]; + p=(int*)&cinfo; + // printk("===touch:%d===",touch); + for (i=0; i<touch; i++) { + //pix_id = (*(p+4)); + //slot_id = ((pix_id & 7)<<1) | ((pix_id & 8)>>3); + point_slot[i].active = 1; + point_slot[i].finger_id = i; + point_slot[i].posx = *(p+i*2); + point_slot[i].posy = *(p+i*2+1); + + } + + if(touch) { + //input_report_key(tsdata->input, BTN_TOUCH, 1); + //input_report_abs(tsdata->input, ABS_MT_TOUCH_MAJOR, 15); + for (i=0; i<touch; i++) { + if (point_slot[i].active == 1) { + if(point_slot[i].posy<0) { + } else { + if(point_slot[i].posx<0) { + point_slot[i].posx = 0; + } else if (point_slot[i].posx>(MS_TS_MSG21XX_X_MAX -2)) { + point_slot[i].posx = (MS_TS_MSG21XX_X_MAX -2); + } + input_report_abs(tsdata->input, ABS_MT_POSITION_X, point_slot[i].posx); + input_report_abs(tsdata->input, ABS_MT_POSITION_Y, point_slot[i].posy); + //input_report_abs(tsdata->input, ABS_MT_TOUCH_MAJOR, 15); + //input_report_abs(tsdata->input, ABS_MT_WIDTH_MAJOR, 1); + input_report_key(tsdata->input, BTN_TOUCH, 1); + input_mt_sync(tsdata->input); + PIXCIR_DBG("%s: slot=%d,x%d=%d,y%d=%d\n",__func__, i, i/2,point_slot[i].posx, i/2, point_slot[i].posy); + } + } + } + } else { + PIXCIR_DBG("%s: release\n",__func__); + #if 0 + //input_report_key(tsdata->input, BTN_TOUCH, 0); + input_report_abs(tsdata->input, ABS_MT_TOUCH_MAJOR, 0); + input_report_abs(tsdata->input, ABS_MT_WIDTH_MAJOR, 0); + input_mt_sync(tsdata->input); + #endif + input_report_key(tsdata->input, BTN_TOUCH, 0); + input_mt_sync(tsdata->input); + } + PIXCIR_DBG("%s: keycode =%x\n",__func__,keycode); + /* + if(lastkey!=keycode) + { + for(i=0;i<3;i++) + { + input_report_key(tsdata->input, keymap[i], (keycode)&(1<<i)); + } + lastkey=keycode; + }*/ + input_sync(tsdata->input); + for (i=0; i<MAX_FINGER_NUM*2; i++) { + if (point_slot[i].active == 0) { + point_slot[i].posx = 0; + point_slot[i].posy = 0; + } + point_slot[i].active = 0; + } +} + +#if USE_WAIT_QUEUE +static int touch_event_handler(void *unused) +{ + struct sched_param param = { .sched_priority = 5 }; + + struct pixcir_i2c_ts_data *tsdata = i2c_get_clientdata(msg21xx_i2c_client); + sched_setscheduler(current, SCHED_RR, ¶m); + + do { + set_current_state(TASK_INTERRUPTIBLE); + wait_event_interruptible(waiter, (0 != tpd_flag)); + tpd_flag = 0; + set_current_state(TASK_RUNNING); + + pixcir_ts_poscheck(tsdata); + + } while (!kthread_should_stop()); + + return 0; +} +#endif + +static irqreturn_t pixcir_ts_isr(int irq, void *dev_id) +{ +#if USE_WAIT_QUEUE + tpd_flag = 1; + wake_up_interruptible(&waiter); + return IRQ_HANDLED; +#endif + +#if 0 + struct pixcir_i2c_ts_data *tsdata = dev_id; + + disable_irq_nosync(irq); + + // while (!tsdata->exiting) { + pixcir_ts_poscheck(tsdata); +#endif //cg,20140402 +#if 0 + if (attb_read_val()) { + PIXCIR_DBG("%s: release\n",__func__); + //input_report_key(tsdata->input, BTN_TOUCH, 0); + input_report_abs(tsdata->input, ABS_MT_TOUCH_MAJOR, 0); + input_sync(tsdata->input); + break; + } +#endif +// msleep(10); + +// } + + enable_irq(irq); + + return IRQ_HANDLED; +} + +#ifdef CONFIG_PM_SLEEP +static int pixcir_i2c_ts_suspend(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + unsigned char wrbuf[2] = { 0 }; + int ret; + + wrbuf[0] = 0x33; + wrbuf[1] = 0x03; //enter into freeze mode; + /************************************************************** + wrbuf[1]: 0x00: Active mode + 0x01: Sleep mode + 0xA4: Sleep mode automatically switch + 0x03: Freeze mode + More details see application note 710 power manangement section + ****************************************************************/ + ret = i2c_master_send(client, wrbuf, 2); + if(ret!=2) { + dev_err(&client->dev, + "%s: i2c_master_send failed(), ret=%d\n", + __func__, ret); + } + + if (device_may_wakeup(&client->dev)) + enable_irq_wake(client->irq); + + return 0; +} + +static int pixcir_i2c_ts_resume(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); +///if suspend enter into freeze mode please reset TP +#if 1 + pixcir_reset(); +#else + unsigned char wrbuf[2] = { 0 }; + int ret; + + wrbuf[0] = 0x33; + wrbuf[1] = 0; + ret = i2c_master_send(client, wrbuf, 2); + if(ret!=2) { + dev_err(&client->dev, + "%s: i2c_master_send failed(), ret=%d\n", + __func__, ret); + } +#endif + if (device_may_wakeup(&client->dev)) + disable_irq_wake(client->irq); + + return 0; +} +#endif + +static SIMPLE_DEV_PM_OPS(pixcir_dev_pm_ops, + pixcir_i2c_ts_suspend, pixcir_i2c_ts_resume); + +static int tpd_get_bl_info (int show) + { + int retval = TPD_OK; + + retval = i2c_smbus_read_i2c_block_data(msg21xx_i2c_client, TPD_REG_BASE, 8, (unsigned char *)&g_bootloader_data); + retval += i2c_smbus_read_i2c_block_data(msg21xx_i2c_client, TPD_REG_BASE + 8, 8, (((unsigned char *)&g_bootloader_data) + 8)); + TPD_DEBUG("ret=%d,first=0x%02x\n",retval,(unsigned char )(*((unsigned char *)&g_bootloader_data))); + if (show) + { + + TPD_DEBUG("BL: bl_file = %02X, bl_status = %02X, bl_error = %02X, blver = %02X%02X, bld_blver = %02X%02X\n", \ + g_bootloader_data.bl_file, \ + g_bootloader_data.bl_status, \ + g_bootloader_data.bl_error, \ + g_bootloader_data.blver_hi, g_bootloader_data.blver_lo, \ + g_bootloader_data.bld_blver_hi, g_bootloader_data.bld_blver_lo); + + TPD_DEBUG("BL: ttspver = 0x%02X%02X, appid=0x%02X%02X, appver=0x%02X%02X\n", \ + g_bootloader_data.ttspver_hi, g_bootloader_data.ttspver_lo, \ + g_bootloader_data.appid_hi, g_bootloader_data.appid_lo, \ + g_bootloader_data.appver_hi, g_bootloader_data.appver_lo); + + TPD_DEBUG("BL: cid = 0x%02X%02X%02X\n", \ + g_bootloader_data.cid_0, \ + g_bootloader_data.cid_1, \ + g_bootloader_data.cid_2); + + } + /*ergate-001*/ + //mdelay(100); + + return retval; + } + +static int sy_init(void) +{ + int retval = TPD_OK; + int tries = 0; + unsigned char host_reg; + host_reg = TPD_SOFT_RESET_MODE; + // printk("==sy_init==0=="); + retval = i2c_smbus_write_i2c_block_data(msg21xx_i2c_client,TPD_REG_BASE,sizeof(host_reg),&host_reg); + // printk("==sy_init==1==retval:%d==",retval); + if(retval < TPD_OK) + return retval; + + do{ + mdelay(100); + retval = tpd_get_bl_info(1); + }while(!(retval < TPD_OK) && !GET_BOOTLOADERMODE(g_bootloader_data.bl_status)&& + !(g_bootloader_data.bl_file == TPD_OP_MODE + TPD_LOW_PWR_MODE) && tries++ < 10); + if(g_bootloader_data.bl_status != (unsigned char )0x11) + { + if(!(retval < 0)) + { + host_reg = TPD_OP_MODE; + retval = i2c_smbus_write_i2c_block_data(msg21xx_i2c_client,TPD_REG_BASE,sizeof(host_reg),&host_reg); + mdelay(100); + } + if(!(retval < 0)) + { + TPD_DEBUG("Switch to sysinfo mode \n"); + host_reg = TPD_SYSINFO_MODE; + retval = i2c_smbus_write_i2c_block_data(msg21xx_i2c_client,TPD_REG_BASE,sizeof(host_reg),&host_reg); + mdelay(100); + + if(!(retval < TPD_OK)) + { + retval = i2c_smbus_read_i2c_block_data(msg21xx_i2c_client,TPD_REG_BASE, 8, (unsigned char *)&g_sysinfo_data); + retval += i2c_smbus_read_i2c_block_data(msg21xx_i2c_client,TPD_REG_BASE + 8, 8, (((unsigned char *)(&g_sysinfo_data)) + 8)); + retval += i2c_smbus_read_i2c_block_data(msg21xx_i2c_client,TPD_REG_BASE + 16, 8, (((unsigned char *)(&g_sysinfo_data)) + 16)); + retval += i2c_smbus_read_i2c_block_data (msg21xx_i2c_client,TPD_REG_BASE + 24, 8, (((unsigned char *)(&g_sysinfo_data)) + 24)); + + TPD_DEBUG("SI: hst_mode = 0x%02X, mfg_cmd = 0x%02X, mfg_stat = 0x%02X\n", \ + g_sysinfo_data.hst_mode, \ + g_sysinfo_data.mfg_cmd, \ + g_sysinfo_data.mfg_stat); + TPD_DEBUG("SI: bl_ver = 0x%02X%02X\n", \ + g_sysinfo_data.bl_verh, \ + g_sysinfo_data.bl_verl); + TPD_DEBUG("SI: act_int = 0x%02X, tch_tmout = 0x%02X, lp_int = 0x%02X\n", \ + g_sysinfo_data.act_intrvl, \ + g_sysinfo_data.tch_tmout, \ + g_sysinfo_data.lp_intrvl); + TPD_DEBUG("SI: tver = %02X%02X, a_id = %02X%02X, aver = %02X%02X\n", \ + g_sysinfo_data.tts_verh, \ + g_sysinfo_data.tts_verl, \ + g_sysinfo_data.app_idh, \ + g_sysinfo_data.app_idl, \ + g_sysinfo_data.app_verh, \ + g_sysinfo_data.app_verl); + TPD_DEBUG("SI: c_id = %02X%02X%02X\n", \ + g_sysinfo_data.cid[0], \ + g_sysinfo_data.cid[1], \ + g_sysinfo_data.cid[2]); + } + + TPD_DEBUG("Switch back to operational mode \n"); + if (!(retval < TPD_OK)) + { + host_reg = TPD_OP_MODE; + retval = i2c_smbus_write_i2c_block_data(msg21xx_i2c_client, TPD_REG_BASE, sizeof(host_reg), &host_reg); + mdelay(100); + } + } + } + else + { + //update_support = 1; + TPD_DEBUG("Switch back to operational mode \n"); + + if (!(retval < TPD_OK)) + { + unsigned char op_cmds[] = {0x00, 0x00, 0xFF, 0xA5, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07}; + //retval = i2c_master_send_ext(i2c_client, op_cmds, sizeof(op_cmds)); + retval = i2c_master_send(msg21xx_i2c_client,op_cmds, sizeof(op_cmds)); + mdelay(100); + } + } + if(retval > TPD_OK) + retval = TPD_OK; + + return retval; + +} + +//#define ITO_TEST +#ifdef ITO_TEST +static void ito_test_create_entry(void); +#endif + +#ifdef CONFIG_OF +static struct msg2138_ts_platform_data *pixcir_ts_parse_dt(struct device *dev) +{ + struct msg2138_ts_platform_data *pdata = NULL; + struct device_node *np = dev->of_node; + int ret; + + pdata = kzalloc(sizeof(*pdata), GFP_KERNEL); + if (!pdata) { + dev_err(dev, "Could not allocate struct msg2138_ts_platform_data"); + return NULL; + } + pdata->reset_gpio_number = of_get_gpio(np, 0); + if(pdata->reset_gpio_number < 0){ + dev_err(dev, "fail to get reset_gpio_number\n"); + goto fail; + } + pdata->irq_gpio_number = of_get_gpio(np, 1); + if(pdata->irq_gpio_number < 0){ + dev_err(dev, "fail to get irq_gpio_number\n"); + goto fail; + } + ret = of_property_read_string(np, "vdd_name", &pdata->vdd_name); + if(ret){ + dev_err(dev, "fail to get vdd_name\n"); + goto fail; + } + ret = of_property_read_u32_array(np, "virtualkeys", &pdata->virtualkeys,12); + if(ret){ + dev_err(dev, "fail to get virtualkeys\n"); + goto fail; + } + ret = of_property_read_u32(np, "TP_MAX_X", &pdata->TP_MAX_X); + if(ret){ + dev_err(dev, "fail to get TP_MAX_X\n"); + goto fail; + } + ret = of_property_read_u32(np, "TP_MAX_Y", &pdata->TP_MAX_Y); + if(ret){ + dev_err(dev, "fail to get TP_MAX_Y\n"); + goto fail; + } + + return pdata; +fail: + kfree(pdata); + return NULL; +} +#endif + +static int pixcir_i2c_ts_probe(struct i2c_client *client,const struct i2c_device_id *id) +{ + struct msg2138_ts_platform_data *pdata = client->dev.platform_data; + struct pixcir_i2c_ts_data *tsdata = NULL; + struct input_dev *input = NULL; + struct device *dev = NULL; + struct i2c_dev *i2c_dev = NULL; + int i, error; + + printk("msg2138 probe in! \n"); + +#ifdef CONFIG_OF + struct device_node *np = client->dev.of_node; + if (np && !pdata){ + pdata = pixcir_ts_parse_dt(&client->dev); + if(pdata){ + client->dev.platform_data = pdata; + } + else{ + error = -ENOMEM; + goto exit_alloc_platform_data_failed; + } + } +#endif + + tsdata = kzalloc(sizeof(*tsdata), GFP_KERNEL); + if (!tsdata) { + error = -ENOMEM; + dev_err(&client->dev, "Failed to allocate tsdata!\n"); + goto exit_alloc_tsdata_failed; + } + + msg21xx_i2c_client = client; + tsdata->client = client; + msg21xx_i2c_ts_data = tsdata; + tsdata->platform_data = pdata; + MS_TS_MSG21XX_X_MAX = pdata->TP_MAX_X; + MS_TS_MSG21XX_Y_MAX = pdata->TP_MAX_Y; + //client->addr = 0x26; + pixcir_ts_hw_init(tsdata); + client->irq = gpio_to_irq(pdata->irq_gpio_number); + i2c_set_clientdata(client, tsdata); + +#if defined(CONFIG_I2C_SPRD) || defined(CONFIG_I2C_SPRD_V1) + sprd_i2c_ctl_chg_clk(client->adapter->nr, 400000); +#endif + + error = getchipType(); + if (error < 0) { + pr_err("[MSG2138A] read chip id failed\n"); + error = -ENODEV; + goto exit_chip_check_failed; + } else { + printk("[MSG2138A] the chip id is %d\n",error); + } + + for(i=0; i<MAX_FINGER_NUM*2; i++) { + point_slot[i].active = 0; + } + sy_init(); + msleep(200); + + input = input_allocate_device(); + if (!input) { + dev_err(&client->dev, "Failed to allocate input device!\n"); + error = -ENOMEM; + goto exit_input_alloc_failed; + } + +#ifdef TOUCH_VIRTUAL_KEYS + pixcir_ts_virtual_keys_init(); +#endif + + tsdata->input = input; + global_irq = client->irq; + input->name = MSG2138_TS_NAME; + input->id.bustype = BUS_I2C; + input->dev.parent = &client->dev; + + __set_bit(EV_KEY, input->evbit); + __set_bit(EV_ABS, input->evbit); + __set_bit(EV_SYN, input->evbit); + //__set_bit(BTN_TOUCH, input->keybit); + __set_bit(ABS_MT_TOUCH_MAJOR, input->absbit); + __set_bit(ABS_MT_POSITION_X, input->absbit); + __set_bit(ABS_MT_POSITION_Y, input->absbit); + __set_bit(ABS_MT_WIDTH_MAJOR, input->absbit); + + __set_bit(KEY_MENU, input->keybit); + __set_bit(KEY_BACK, input->keybit); + __set_bit(KEY_HOME, input->keybit); + __set_bit(KEY_SEARCH, input->keybit); + + input_set_abs_params(input, ABS_MT_POSITION_X, 0, pdata->TP_MAX_X, 0, 0); + input_set_abs_params(input, ABS_MT_POSITION_Y, 0, pdata->TP_MAX_Y, 0, 0); + input_set_abs_params(input, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0); + input_set_abs_params(input, ABS_MT_WIDTH_MAJOR, 0, 255, 0, 0); + input_set_drvdata(input, tsdata); + + error = request_irq(client->irq, pixcir_ts_isr, + IRQF_TRIGGER_FALLING, client->name, tsdata); + if (error) { + dev_err(&client->dev, "Unable to request touchscreen IRQ.\n"); + goto exit_requst_irq_failed; + } + disable_irq_nosync(client->irq); + + error = input_register_device(input); + if (error) + goto exit_input_register_failed; + device_init_wakeup(&client->dev, 1); + + /*********************************Bee-0928-TOP****************************************/ + i2c_dev = get_free_i2c_dev(client->adapter); + if (IS_ERR(i2c_dev)) { + error = PTR_ERR(i2c_dev); + goto exit_get_i2c_dev_failed; + } + + dev = device_create(i2c_dev_class, &client->adapter->dev, MKDEV(I2C_MAJOR, + client->adapter->nr), NULL, "pixcir_i2c_ts%d", 0); + if (IS_ERR(dev)) { + error = PTR_ERR(dev); + goto exit_device_create_failed; + } + /*********************************Bee-0928-BOTTOM****************************************/ +#ifdef CONFIG_HAS_EARLYSUSPEND + pixcir_early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1; + pixcir_early_suspend.suspend = pixcir_ts_suspend; + pixcir_early_suspend.resume = pixcir_ts_resume; + register_early_suspend(&pixcir_early_suspend); +#endif + + /********* frameware upgrade *********/ +#ifdef __FIRMWARE_UPDATE__ + firmware_class = class_create(THIS_MODULE, "ms-touchscreen-msg20xx"); + if (IS_ERR(firmware_class)) + pr_err("Failed to create class(firmware)!\n"); + firmware_cmd_dev = device_create(firmware_class, + NULL, 0, NULL, "device"); + if (IS_ERR(firmware_cmd_dev)) + pr_err("Failed to create device(firmware_cmd_dev)!\n"); + + // version + if (device_create_file(firmware_cmd_dev, &dev_attr_version) < 0) + pr_err("Failed to create device file(%s)!\n", dev_attr_version.attr.name); + // update + if (device_create_file(firmware_cmd_dev, &dev_attr_update) < 0) + pr_err("Failed to create device file(%s)!\n", dev_attr_update.attr.name); + // data + if (device_create_file(firmware_cmd_dev, &dev_attr_data) < 0) + pr_err("Failed to create device file(%s)!\n", dev_attr_data.attr.name); + // clear + // if (device_create_file(firmware_cmd_dev, &dev_attr_clear) < 0) + // pr_err("Failed to create device file(%s)!\n", dev_attr_clear.attr.name); + + dev_set_drvdata(firmware_cmd_dev, NULL); +#endif //__FIRMWARE_UPDATE__ +#ifdef ITO_TEST + ito_test_create_entry(); +#endif +#if 0 + error = pixcir_create_sysfs(client); + if (error) { + dev_err(&client->dev, "insmod successfully!\n"); + goto exit_create_sysfs_failed; + }; +#endif +#ifdef SYSFS_DEBUG + cg_tpfwver_readfwver(); +#endif //cg,20130929 + +#if USE_WAIT_QUEUE + thread = kthread_run(touch_event_handler, 0, "pixcir-wait-queue"); + if (IS_ERR(thread)) + { + error = PTR_ERR(thread); + dev_err(&client->dev, "failed to create kernel thread\n"); + goto exit_kthread_run_failed; + } +#endif + + enable_irq(client->irq); + //tp_cg_flag=2; + printk("[MSG2138A]pixcir_i2c probe success\n"); + return 0; + +exit_kthread_run_failed: +exit_create_sysfs_failed: +exit_device_create_failed: +exit_get_i2c_dev_failed: + input_unregister_device(input); +exit_input_register_failed: + free_irq(client->irq, tsdata); +exit_requst_irq_failed: + input_free_device(input); +exit_input_alloc_failed: +exit_chip_check_failed: + gpio_free(pdata->irq_gpio_number); + gpio_free(pdata->reset_gpio_number); + kfree(tsdata); +exit_alloc_tsdata_failed: + pdata = NULL; + client = NULL; +exit_alloc_platform_data_failed: + return error; +} + +static int pixcir_i2c_ts_remove(struct i2c_client *client) +{ + int error; + struct i2c_dev *i2c_dev; + struct pixcir_i2c_ts_data *tsdata = i2c_get_clientdata(client); + + device_init_wakeup(&client->dev, 0); + + tsdata->exiting = true; + mb(); + free_irq(client->irq, tsdata); + + /*********************************Bee-0928-TOP****************************************/ + i2c_dev = get_free_i2c_dev(client->adapter); + if (IS_ERR(i2c_dev)) { + error = PTR_ERR(i2c_dev); + return error; + } + + return_i2c_dev(i2c_dev); + device_destroy(i2c_dev_class, MKDEV(I2C_MAJOR, client->adapter->nr)); + /*********************************Bee-0928-BOTTOM****************************************/ + unregister_early_suspend(&pixcir_early_suspend); + input_unregister_device(tsdata->input); + kfree(tsdata); + + return 0; +} + +/*************************************Bee-0928****************************************/ +/* pixcir_open */ +/*************************************Bee-0928****************************************/ +static int pixcir_open(struct inode *inode, struct file *file) +{ + int subminor; + struct i2c_client *client; + struct i2c_adapter *adapter; + struct i2c_dev *i2c_dev; + int ret = 0; + PIXCIR_DBG("enter pixcir_open function\n"); + + subminor = iminor(inode); + +// lock_kernel(); + i2c_dev = i2c_dev_get_by_minor(subminor); + if (!i2c_dev) { + //printk("error i2c_dev\n"); + return -ENODEV; + } + + adapter = i2c_get_adapter(i2c_dev->adap->nr); + if (!adapter) { + return -ENODEV; + } + + client = kzalloc(sizeof(*client), GFP_KERNEL); + if (!client) { + i2c_put_adapter(adapter); + ret = -ENOMEM; + } + + snprintf(client->name, I2C_NAME_SIZE, "pixcir_i2c_ts%d", adapter->nr); + client->driver = &pixcir_i2c_ts_driver; + client->adapter = adapter; + + file->private_data = client; + + return 0; +} + +/*************************************Bee-0928****************************************/ +/* pixcir_ioctl */ +/*************************************Bee-0928****************************************/ +static long pixcir_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + //struct i2c_client *client = (struct i2c_client *) file->private_data; + + PIXCIR_DBG("pixcir_ioctl(),cmd = %d,arg = %ld\n", cmd, arg); + +#if 0 + switch (cmd) + { + case CALIBRATION_FLAG: //CALIBRATION_FLAG = 1 + client->addr = SLAVE_ADDR; + status_reg = CALIBRATION_FLAG; + break; + + case BOOTLOADER: //BOOTLOADER = 7 + client->addr = BOOTLOADER_ADDR; + status_reg = BOOTLOADER; + + pixcir_reset(); + mdelay(5); + break; + + case RESET_TP: //RESET_TP = 9 + pixcir_reset(); + break; + + case ENABLE_IRQ: //ENABLE_IRQ = 10 + status_reg = 0; + enable_irq(global_irq); + break; + + case DISABLE_IRQ: //DISABLE_IRQ = 11 + disable_irq_nosync(global_irq); + break; + + case BOOTLOADER_STU: //BOOTLOADER_STU = 12 + client->addr = BOOTLOADER_ADDR; + status_reg = BOOTLOADER_STU; + + pixcir_reset(); + mdelay(5); + + case ATTB_VALUE: //ATTB_VALUE = 13 + client->addr = SLAVE_ADDR; + status_reg = ATTB_VALUE; + break; + + default: + client->addr = SLAVE_ADDR; + status_reg = 0; + break; + } +#endif + return 0; +} + +/***********************************Bee-0928****************************************/ +/* pixcir_read */ +/***********************************Bee-0928****************************************/ +static ssize_t pixcir_read (struct file *file, char __user *buf, size_t count,loff_t *offset) +{ + //struct i2c_client *client = (struct i2c_client *)file->private_data; + //unsigned char *tmp, bootloader_stu[4], attb_value[1]; + int ret = 0; +#if 0 + switch(status_reg) + { + case BOOTLOADER_STU: + i2c_master_recv(client, bootloader_stu, sizeof(bootloader_stu)); + if (ret!=sizeof(bootloader_stu)) { + dev_err(&client->dev, + "%s: BOOTLOADER_STU: i2c_master_recv() failed, ret=%d\n", + __func__, ret); + return -EFAULT; + } + + ret = copy_to_user(buf, bootloader_stu, sizeof(bootloader_stu)); + if(ret) { + dev_err(&client->dev, + "%s: BOOTLOADER_STU: copy_to_user() failed.\n", __func__); + return -EFAULT; + }else { + ret = 4; + } + break; + + case ATTB_VALUE: + attb_value[0] = attb_read_val(); + if(copy_to_user(buf, attb_value, sizeof(attb_value))) { + dev_err(&client->dev, + "%s: ATTB_VALUE: copy_to_user() failed.\n", __func__); + return -EFAULT; + }else { + ret = 1; + } + break; + + default: + tmp = kmalloc(count,GFP_KERNEL); + if (tmp==NULL) + return -ENOMEM; + + ret = i2c_master_recv(client, tmp, count); + if (ret != count) { + dev_err(&client->dev, + "%s: default: i2c_master_recv() failed, ret=%d\n", + __func__, ret); + return -EFAULT; + } + + if(copy_to_user(buf, tmp, count)) { + dev_err(&client->dev, + "%s: default: copy_to_user() failed.\n", __func__); + kfree(tmp); + return -EFAULT; + } + kfree(tmp); + break; + } + #endif + return ret; +} + +/***********************************Bee-0928****************************************/ +/* pixcir_write */ +/***********************************Bee-0928****************************************/ +static ssize_t pixcir_write(struct file *file,const char __user *buf,size_t count, loff_t *ppos) +{ + //struct i2c_client *client; + //unsigned char *tmp, bootload_data[143]; + int ret=0; +#if 0 + client = file->private_data; + + switch(status_reg) + { + case CALIBRATION_FLAG: //CALIBRATION_FLAG=1 + tmp = kmalloc(count,GFP_KERNEL); + if (tmp==NULL) + return -ENOMEM; + + if (copy_from_user(tmp,buf,count)) { + dev_err(&client->dev, + "%s: CALIBRATION_FLAG: copy_from_user() failed.\n", __func__); + kfree(tmp); + return -EFAULT; + } + + ret = i2c_master_send(client,tmp,count); + if (ret!=count ) { + dev_err(&client->dev, + "%s: CALIBRATION: i2c_master_send() failed, ret=%d\n", + __func__, ret); + kfree(tmp); + return -EFAULT; + } + + while(!attb_read_val()) { + msleep(100); + i++; + if(i>99) + break; //10s no high aatb break + } //waiting to finish the calibration.(pixcir application_note_710_v3 p43) + + kfree(tmp); + break; + + case BOOTLOADER: + memset(bootload_data, 0, sizeof(bootload_data)); + + if (copy_from_user(bootload_data, buf, count)) { + dev_err(&client->dev, + "%s: BOOTLOADER: copy_from_user() failed.\n", __func__); + return -EFAULT; + } + + ret = i2c_master_send(client, bootload_data, count); + if(ret!=count) { + dev_err(&client->dev, + "%s: BOOTLOADER: i2c_master_send() failed, ret = %d\n", + __func__, ret); + return -EFAULT; + } + break; + + default: + tmp = kmalloc(count,GFP_KERNEL); + if (tmp==NULL) + return -ENOMEM; + + if (copy_from_user(tmp,buf,count)) { + dev_err(&client->dev, + "%s: default: copy_from_user() failed.\n", __func__); + kfree(tmp); + return -EFAULT; + } + + ret = i2c_master_send(client,tmp,count); + if (ret!=count ) { + dev_err(&client->dev, + "%s: default: i2c_master_send() failed, ret=%d\n", + __func__, ret); + kfree(tmp); + return -EFAULT; + } + kfree(tmp); + break; + } + #endif + return ret; +} + +/***********************************Bee-0928****************************************/ +/* pixcir_release */ +/***********************************Bee-0928****************************************/ +static int pixcir_release(struct inode *inode, struct file *file) +{ + struct i2c_client *client = file->private_data; + + PIXCIR_DBG("enter pixcir_release funtion\n"); + + i2c_put_adapter(client->adapter); + kfree(client); + file->private_data = NULL; + + return 0; +} + +/*********************************Bee-0928-TOP****************************************/ +static const struct file_operations pixcir_i2c_ts_fops = +{ .owner = THIS_MODULE, + .read = pixcir_read, + .write = pixcir_write, + .open = pixcir_open, + .unlocked_ioctl = pixcir_ioctl, + .release = pixcir_release, +}; +/*********************************Bee-0928-BOTTOM****************************************/ + +static const struct i2c_device_id pixcir_i2c_ts_id[] = { + { MSG2138_TS_NAME, MSG2138_TS_ADDR },//0 + { } +}; +MODULE_DEVICE_TABLE(i2c, pixcir_i2c_ts_id); + +#if 0 +static unsigned short force[] = {0,0x4c,I2C_CLIENT_END,I2C_CLIENT_END}; +static const unsigned short * const forces[] = { force, NULL }; +static struct i2c_client_address_data addr_data = { .forces = forces, }; +#endif +static const struct of_device_id msg2138_of_match[] = { + { .compatible = "Mstar,msg2138_ts", }, + { } +}; +MODULE_DEVICE_TABLE(of, msg2138_of_match); + +static struct i2c_driver pixcir_i2c_ts_driver = { + .driver = { + .owner = THIS_MODULE, + .name = MSG2138_TS_NAME, + .of_match_table = msg2138_of_match, + }, + .probe = pixcir_i2c_ts_probe, + .remove = pixcir_i2c_ts_remove, + .id_table = pixcir_i2c_ts_id, +}; + +static int __init pixcir_i2c_ts_init(void) +{ + int ret; + + /*if (0 != tp_cg_flag) + { + return -ENODEV; + }*/ + /*********************************Bee-0928-TOP****************************************/ + TPD_DEBUG("msg2138 init111!\n"); + ret = register_chrdev(I2C_MAJOR,"pixcir_i2c_ts",&pixcir_i2c_ts_fops); + if (ret) { + //printk(KERN_ERR "%s:register chrdev failed\n",__FILE__); + return ret; + } + TPD_DEBUG("msg2138 init222!\n"); + i2c_dev_class = class_create(THIS_MODULE, "pixcir_i2c_dev"); + if (IS_ERR(i2c_dev_class)) { + ret = PTR_ERR(i2c_dev_class); + class_destroy(i2c_dev_class); + } + /********************************Bee-0928-BOTTOM******************************************/ + + return i2c_add_driver(&pixcir_i2c_ts_driver); +} + +static void pixcir_i2c_ts_exit(void) +{ + i2c_del_driver(&pixcir_i2c_ts_driver); + /********************************Bee-0928-TOP******************************************/ + class_destroy(i2c_dev_class); + unregister_chrdev(I2C_MAJOR,"pixcir_i2c_ts"); + /********************************Bee-0928-BOTTOM******************************************/ +} + +module_init(pixcir_i2c_ts_init); +module_exit(pixcir_i2c_ts_exit); + +#ifdef ITO_TEST + +#include "./ito_test/open_test_ANA1_8861A_lianchuang.h" +#include "./ito_test/open_test_ANA2_8861A_lianchuang.h" +#include "./ito_test/open_test_ANA1_B_8861A_lianchuang.h" +#include "./ito_test/open_test_ANA2_B_8861A_lianchuang.h" +#include "./ito_test/open_test_ANA3_8861A_lianchuang.h" +/////////////////////////////////////////////////////////////////////////// +u8 bItoTestDebug = 0; +#define ITO_TEST_DEBUG(format, ...) \ +{ \ + if(bItoTestDebug) \ + { \ + printk(KERN_ERR "ito_test ***" format "\n", ## __VA_ARGS__); \ + mdelay(5); \ + } \ +} +#define ITO_TEST_DEBUG_MUST(format, ...) printk(KERN_ERR "ito_test ***" format "\n", ## __VA_ARGS__);mdelay(5) + + + +s16 s16_raw_data_1[48] = {0}; +s16 s16_raw_data_2[48] = {0}; +s16 s16_raw_data_3[48] = {0}; +u8 ito_test_keynum = 0; +u8 ito_test_dummynum = 0; +u8 ito_test_trianglenum = 0; +u8 ito_test_2r = 0; +u8 g_LTP = 1; +uint16_t *open_1 = NULL; +uint16_t *open_1B = NULL; +uint16_t *open_2 = NULL; +uint16_t *open_2B = NULL; +uint16_t *open_3 = NULL; +u8 *MAP1 = NULL; +u8 *MAP2=NULL; +u8 *MAP3=NULL; +u8 *MAP40_1 = NULL; +u8 *MAP40_2 = NULL; +u8 *MAP40_3 = NULL; +u8 *MAP40_4 = NULL; +u8 *MAP41_1 = NULL; +u8 *MAP41_2 = NULL; +u8 *MAP41_3 = NULL; +u8 *MAP41_4 = NULL; + + +#define ITO_TEST_ADDR_TP (0x4C>>1) +#define ITO_TEST_ADDR_REG (0xC4>>1) +#define REG_INTR_FIQ_MASK 0x04 +#define FIQ_E_FRAME_READY_MASK ( 1 << 8 ) +#define MAX_CHNL_NUM (48) +#define BIT0 (1<<0) +#define BIT1 (1<<1) +#define BIT5 (1<<5) +#define BIT11 (1<<11) +#define BIT15 (1<<15) + + +static int ito_test_i2c_read(u8 addr, u8* read_data, u16 size) +{ + int rc; + u8 addr_before = msg21xx_i2c_client->addr; + msg21xx_i2c_client->addr = addr; + + #ifdef DMA_IIC + if(size>8&&NULL!=I2CDMABuf_va) + { + int i = 0; + msg21xx_i2c_client->ext_flag = msg21xx_i2c_client->ext_flag | I2C_DMA_FLAG ; + rc = i2c_master_recv(msg21xx_i2c_client, (unsigned char *)I2CDMABuf_pa, size); + for(i = 0; i < size; i++) + { + read_data[i] = I2CDMABuf_va[i]; + } + } + else + { + rc = i2c_master_recv(msg21xx_i2c_client, read_data, size); + } + msg21xx_i2c_client->ext_flag = msg21xx_i2c_client->ext_flag & (~I2C_DMA_FLAG); + #else + rc = i2c_master_recv(msg21xx_i2c_client, read_data, size); + #endif + + msg21xx_i2c_client->addr = addr_before; + if( rc < 0 ) + { + ITO_TEST_DEBUG_MUST("ito_test_i2c_read error %d,addr=%d\n", rc,addr); + } + return rc; +} + +static int ito_test_i2c_write(u8 addr, u8* data, u16 size) +{ + int rc; + u8 addr_before = msg21xx_i2c_client->addr; + msg21xx_i2c_client->addr = addr; + +#ifdef DMA_IIC + if(size>8&&NULL!=I2CDMABuf_va) + { + int i = 0; + for(i=0;i<size;i++) + { + I2CDMABuf_va[i]=data[i]; + } + msg21xx_i2c_client->ext_flag = msg21xx_i2c_client->ext_flag | I2C_DMA_FLAG ; + rc = i2c_master_send(msg21xx_i2c_client, (unsigned char *)I2CDMABuf_pa, size); + } + else + { + rc = i2c_master_send(msg21xx_i2c_client, data, size); + } + msg21xx_i2c_client->ext_flag = msg21xx_i2c_client->ext_flag & (~I2C_DMA_FLAG); +#else + rc = i2c_master_send(msg21xx_i2c_client, data, size); +#endif + + msg21xx_i2c_client->addr = addr_before; + if( rc < 0 ) + { + ITO_TEST_DEBUG_MUST("ito_test_i2c_write error %d,addr = %d,data[0]=%d\n", rc, addr,data[0]); + } + return rc; +} + +static void ito_test_reset(void) +{ + struct msg2138_ts_platform_data *pdata = msg21xx_i2c_ts_data->platform_data; + gpio_direction_output(pdata->reset_gpio_number, 1); + gpio_set_value(pdata->reset_gpio_number, 1); + gpio_set_value(pdata->reset_gpio_number, 0); + mdelay(100); + ITO_TEST_DEBUG("reset tp\n"); + gpio_set_value(pdata->reset_gpio_number, 1); + mdelay(200); +} +static void ito_test_disable_irq(void) +{ + disable_irq_nosync(global_irq); +} +static void ito_test_enable_irq(void) +{ + enable_irq(global_irq); +} + +static void ito_test_set_iic_rate(u32 iicRate) +{ + #ifdef CONFIG_I2C_SPRD + sprd_i2c_ctl_chg_clk(msg21xx_i2c_client->adapter->nr, iicRate); + mdelay(100); + #endif + #if MTK + msg21xx_i2c_client->timing = iicRate/1000; + #endif +} + +static void ito_test_WriteReg( u8 bank, u8 addr, u16 data ) +{ + u8 tx_data[5] = {0x10, bank, addr, data & 0xFF, data >> 8}; + ito_test_i2c_write( ITO_TEST_ADDR_REG, &tx_data[0], 5 ); +} +static void ito_test_WriteReg8Bit( u8 bank, u8 addr, u8 data ) +{ + u8 tx_data[4] = {0x10, bank, addr, data}; + ito_test_i2c_write ( ITO_TEST_ADDR_REG, &tx_data[0], 4 ); +} +static unsigned short ito_test_ReadReg( u8 bank, u8 addr ) +{ + u8 tx_data[3] = {0x10, bank, addr}; + u8 rx_data[2] = {0}; + + ito_test_i2c_write( ITO_TEST_ADDR_REG, &tx_data[0], 3 ); + ito_test_i2c_read ( ITO_TEST_ADDR_REG, &rx_data[0], 2 ); + return ( rx_data[1] << 8 | rx_data[0] ); +} +static u32 ito_test_get_TpType(void) +{ + u8 tx_data[3] = {0}; + u8 rx_data[4] = {0}; + u32 Major = 0, Minor = 0; + + ITO_TEST_DEBUG("GetTpType\n"); + + tx_data[0] = 0x53; + tx_data[1] = 0x00; + tx_data[2] = 0x2A; + ito_test_i2c_write(ITO_TEST_ADDR_TP, &tx_data[0], 3); + mdelay(50); + ito_test_i2c_read(ITO_TEST_ADDR_TP, &rx_data[0], 4); + Major = (rx_data[1]<<8) + rx_data[0]; + Minor = (rx_data[3]<<8) + rx_data[2]; + + ITO_TEST_DEBUG("***TpTypeMajor = %d ***\n", Major); + ITO_TEST_DEBUG("***TpTypeMinor = %d ***\n", Minor); + + return Major; + +} + +#define TP_OF_LIANCHUANG (2) +static u32 ito_test_choose_TpType(void) +{ + u32 tpType = 0; + u8 i = 0; + open_1 = NULL; + open_1B = NULL; + open_2 = NULL; + open_2B = NULL; + open_3 = NULL; + MAP1 = NULL; + MAP2 = NULL; + MAP3 = NULL; + MAP40_1 = NULL; + MAP40_2 = NULL; + MAP40_3 = NULL; + MAP40_4 = NULL; + MAP41_1 = NULL; + MAP41_2 = NULL; + MAP41_3 = NULL; + MAP41_4 = NULL; + ito_test_keynum = 0; + ito_test_dummynum = 0; + ito_test_trianglenum = 0; + ito_test_2r = 0; + + for(i=0;i<10;i++) + { + tpType = ito_test_get_TpType(); + ITO_TEST_DEBUG("tpType=%d;i=%d;\n",tpType,i); + if(TP_OF_LIANCHUANG==tpType) + { + break; + } + else if(i<5) + { + mdelay(100); + } + else + { + ito_test_reset(); + } + } + + if(TP_OF_LIANCHUANG==tpType) + { + open_1 = open_1_lianchuang; + open_1B = open_1B_lianchuang; + open_2 = open_2_lianchuang; + open_2B = open_2B_lianchuang; + open_3 = open_3_lianchuang; + MAP1 = MAP1_lianchuang; + MAP2 = MAP2_lianchuang; + MAP3 = MAP3_lianchuang; + MAP40_1 = MAP40_1_lianchuang; + MAP40_2 = MAP40_2_lianchuang; + MAP40_3 = MAP40_3_lianchuang; + MAP40_4 = MAP40_4_lianchuang; + MAP41_1 = MAP41_1_lianchuang; + MAP41_2 = MAP41_2_lianchuang; + MAP41_3 = MAP41_3_lianchuang; + MAP41_4 = MAP41_4_lianchuang; + ito_test_keynum = NUM_KEY_LIANCHUANG; + ito_test_dummynum = NUM_DUMMY_LIANCHUANG; + ito_test_trianglenum = NUM_SENSOR_LIANCHUANG; + ito_test_2r = ENABLE_2R_LIANCHUANG; + } + else + { + tpType = 0; + } + return tpType; +} +static void ito_test_EnterSerialDebugMode(void) +{ + u8 data[5]; + + data[0] = 0x53; + data[1] = 0x45; + data[2] = 0x52; + data[3] = 0x44; + data[4] = 0x42; + ito_test_i2c_write(ITO_TEST_ADDR_REG, &data[0], 5); + + data[0] = 0x37; + ito_test_i2c_write(ITO_TEST_ADDR_REG, &data[0], 1); + + data[0] = 0x35; + ito_test_i2c_write(ITO_TEST_ADDR_REG, &data[0], 1); + + data[0] = 0x71; + ito_test_i2c_write(ITO_TEST_ADDR_REG, &data[0], 1); +} +static uint16_t ito_test_get_num( void ) +{ + uint16_t num_of_sensor,i; + uint16_t RegValue1,RegValue2; + + num_of_sensor = 0; + + RegValue1 = ito_test_ReadReg( 0x11, 0x4A); + ITO_TEST_DEBUG("ito_test_get_num,RegValue1=%d\n",RegValue1); + if ( ( RegValue1 & BIT1) == BIT1 ) + { + RegValue1 = ito_test_ReadReg( 0x12, 0x0A); + RegValue1 = RegValue1 & 0x0F; + + RegValue2 = ito_test_ReadReg( 0x12, 0x16); + RegValue2 = (( RegValue2 >> 1 ) & 0x0F) + 1; + + num_of_sensor = RegValue1 * RegValue2; + } + else + { + for(i=0;i<4;i++) + { + num_of_sensor+=(ito_test_ReadReg( 0x12, 0x0A)>>(4*i))&0x0F; + } + } + ITO_TEST_DEBUG("ito_test_get_num,num_of_sensor=%d\n",num_of_sensor); + return num_of_sensor; +} +static void ito_test_polling( void ) +{ + uint16_t reg_int = 0x0000; + uint8_t dbbus_tx_data[5]; + uint8_t dbbus_rx_data[4]; + uint16_t reg_value; + + + reg_int = 0; + + ito_test_WriteReg( 0x13, 0x0C, BIT15 ); + ito_test_WriteReg( 0x12, 0x14, (ito_test_ReadReg(0x12,0x14) | BIT0) ); + + ITO_TEST_DEBUG("polling start\n"); + while( ( reg_int & BIT0 ) == 0x0000 ) + { + dbbus_tx_data[0] = 0x10; + dbbus_tx_data[1] = 0x3D; + dbbus_tx_data[2] = 0x18; + ito_test_i2c_write(ITO_TEST_ADDR_REG, dbbus_tx_data, 3); + ito_test_i2c_read(ITO_TEST_ADDR_REG, dbbus_rx_data, 2); + reg_int = dbbus_rx_data[1]; + } + ITO_TEST_DEBUG("polling end\n"); + reg_value = ito_test_ReadReg( 0x3D, 0x18 ); + ito_test_WriteReg( 0x3D, 0x18, reg_value & (~BIT0) ); +} +static uint16_t ito_test_get_data_out( int16_t* s16_raw_data ) +{ + uint8_t i,dbbus_tx_data[8]; + uint16_t raw_data[48]={0}; + uint16_t num_of_sensor; + uint16_t reg_int; + uint8_t dbbus_rx_data[96]={0}; + + num_of_sensor = ito_test_get_num(); + if(num_of_sensor*2>96) + { + ITO_TEST_DEBUG("danger,num_of_sensor=%d\n",num_of_sensor); + return num_of_sensor; + } + + reg_int = ito_test_ReadReg( 0x3d, REG_INTR_FIQ_MASK<<1 ); + ito_test_WriteReg( 0x3d, REG_INTR_FIQ_MASK<<1, (reg_int & (uint16_t)(~FIQ_E_FRAME_READY_MASK) ) ); + ito_test_polling(); + dbbus_tx_data[0] = 0x10; + dbbus_tx_data[1] = 0x13; + dbbus_tx_data[2] = 0x40; + ito_test_i2c_write(ITO_TEST_ADDR_REG, dbbus_tx_data, 3); + mdelay(20); + ito_test_i2c_read(ITO_TEST_ADDR_REG, &dbbus_rx_data[0], (num_of_sensor * 2)); + mdelay(100); + for(i=0;i<num_of_sensor * 2;i++) + { + ITO_TEST_DEBUG("dbbus_rx_data[%d]=%d\n",i,dbbus_rx_data[i]); + } + + reg_int = ito_test_ReadReg( 0x3d, REG_INTR_FIQ_MASK<<1 ); + ito_test_WriteReg( 0x3d, REG_INTR_FIQ_MASK<<1, (reg_int | (uint16_t)FIQ_E_FRAME_READY_MASK ) ); + + + for( i = 0; i < num_of_sensor; i++ ) + { + raw_data[i] = ( dbbus_rx_data[ 2 * i + 1] << 8 ) | ( dbbus_rx_data[2 * i] ); + s16_raw_data[i] = ( int16_t )raw_data[i]; + } + + return(num_of_sensor); +} + + +static void ito_test_send_data_in( uint8_t step ) +{ + uint16_t i; + uint8_t dbbus_tx_data[512]; + uint16_t *Type1=NULL; + + ITO_TEST_DEBUG("ito_test_send_data_in step=%d\n",step); + if( step == 4 ) + { + Type1 = &open_1[0]; + } + else if( step == 5 ) + { + Type1 = &open_2[0]; + } + else if( step == 6 ) + { + Type1 = &open_3[0]; + } + else if( step == 9 ) + { + Type1 = &open_1B[0]; + } + else if( step == 10 ) + { + Type1 = &open_2B[0]; + } + + dbbus_tx_data[0] = 0x10; + dbbus_tx_data[1] = 0x11; + dbbus_tx_data[2] = 0x00; + for( i = 0; i <= 0x3E ; i++ ) + { + dbbus_tx_data[3+2*i] = Type1[i] & 0xFF; + dbbus_tx_data[4+2*i] = ( Type1[i] >> 8 ) & 0xFF; + } + ito_test_i2c_write(ITO_TEST_ADDR_REG, dbbus_tx_data, 3+0x3F*2); + + dbbus_tx_data[2] = 0x7A * 2; + for( i = 0x7A; i <= 0x7D ; i++ ) + { + dbbus_tx_data[3+2*(i-0x7A)] = 0; + dbbus_tx_data[4+2*(i-0x7A)] = 0; + } + ito_test_i2c_write(ITO_TEST_ADDR_REG, dbbus_tx_data, 3+8); + + dbbus_tx_data[0] = 0x10; + dbbus_tx_data[1] = 0x12; + + dbbus_tx_data[2] = 5 * 2; + dbbus_tx_data[3] = Type1[128+5] & 0xFF; + dbbus_tx_data[4] = ( Type1[128+5] >> 8 ) & 0xFF; + ito_test_i2c_write(ITO_TEST_ADDR_REG, dbbus_tx_data, 5); + + dbbus_tx_data[2] = 0x0B * 2; + dbbus_tx_data[3] = Type1[128+0x0B] & 0xFF; + dbbus_tx_data[4] = ( Type1[128+0x0B] >> 8 ) & 0xFF; + ito_test_i2c_write(ITO_TEST_ADDR_REG, dbbus_tx_data, 5); + + dbbus_tx_data[2] = 0x12 * 2; + dbbus_tx_data[3] = Type1[128+0x12] & 0xFF; + dbbus_tx_data[4] = ( Type1[128+0x12] >> 8 ) & 0xFF; + ito_test_i2c_write(ITO_TEST_ADDR_REG, dbbus_tx_data, 5); + + dbbus_tx_data[2] = 0x15 * 2; + dbbus_tx_data[3] = Type1[128+0x15] & 0xFF; + dbbus_tx_data[4] = ( Type1[128+0x15] >> 8 ) & 0xFF; + ito_test_i2c_write(ITO_TEST_ADDR_REG, dbbus_tx_data, 5); +} + +static void ito_test_set_v( uint8_t Enable, uint8_t Prs) +{ + uint16_t u16RegValue; + + + u16RegValue = ito_test_ReadReg( 0x12, 0x08); + u16RegValue = u16RegValue & 0xF1; + if ( Prs == 0 ) + { + ito_test_WriteReg( 0x12, 0x08, u16RegValue| 0x0C); + } + else if ( Prs == 1 ) + { + ito_test_WriteReg( 0x12, 0x08, u16RegValue| 0x0E); + } + else + { + ito_test_WriteReg( 0x12, 0x08, u16RegValue| 0x02); + } + + if ( Enable ) + { + u16RegValue = ito_test_ReadReg( 0x11, 0x06); + ito_test_WriteReg( 0x11, 0x06, u16RegValue| 0x03); + } + else + { + u16RegValue = ito_test_ReadReg( 0x11, 0x06); + u16RegValue = u16RegValue & 0xFC; + ito_test_WriteReg( 0x11, 0x06, u16RegValue); + } + +} + +static void ito_test_set_c( uint8_t Csub_Step ) +{ + uint8_t i; + uint8_t dbbus_tx_data[MAX_CHNL_NUM+3]; + uint8_t HighLevel_Csub = false; + uint8_t Csub_new; + + dbbus_tx_data[0] = 0x10; + dbbus_tx_data[1] = 0x11; + dbbus_tx_data[2] = 0x84; + for( i = 0; i < MAX_CHNL_NUM; i++ ) + { + Csub_new = Csub_Step; + HighLevel_Csub = false; + if( Csub_new > 0x1F ) + { + Csub_new = Csub_new - 0x14; + HighLevel_Csub = true; + } + + dbbus_tx_data[3+i] = Csub_new & 0x1F; + if( HighLevel_Csub == true ) + { + dbbus_tx_data[3+i] |= BIT5; + } + } + ito_test_i2c_write(ITO_TEST_ADDR_REG, dbbus_tx_data, MAX_CHNL_NUM+3); + + dbbus_tx_data[2] = 0xB4; + ito_test_i2c_write(ITO_TEST_ADDR_REG, dbbus_tx_data, MAX_CHNL_NUM+3); +} + +static void ito_test_sw( void ) +{ + ito_test_WriteReg( 0x11, 0x00, 0xFFFF ); + ito_test_WriteReg( 0x11, 0x00, 0x0000 ); + mdelay( 50 ); +} + + + +static void ito_test_first( uint8_t item_id , int16_t* s16_raw_data) +{ + uint8_t result = 0,loop; + uint8_t dbbus_tx_data[9]; + uint8_t i,j; + int16_t s16_raw_data_tmp[48]={0}; + uint8_t num_of_sensor, num_of_sensor2,total_sensor; + uint16_t u16RegValue; + uint8_t *pMapping=NULL; + + + num_of_sensor = 0; + num_of_sensor2 = 0; + + ITO_TEST_DEBUG("ito_test_first item_id=%d\n",item_id); + ito_test_WriteReg( 0x0F, 0xE6, 0x01 ); + + ito_test_WriteReg( 0x1E, 0x24, 0x0500 ); + ito_test_WriteReg( 0x1E, 0x2A, 0x0000 ); + ito_test_WriteReg( 0x1E, 0xE6, 0x6E00 ); + ito_test_WriteReg( 0x1E, 0xE8, 0x0071 ); + + if ( item_id == 40 ) + { + pMapping = &MAP1[0]; + if ( ito_test_2r ) + { + total_sensor = ito_test_trianglenum/2; + } + else + { + total_sensor = ito_test_trianglenum/2 + ito_test_keynum + ito_test_dummynum; + } + } + else if( item_id == 41 ) + { + pMapping = &MAP2[0]; + if ( ito_test_2r ) + { + total_sensor = ito_test_trianglenum/2; + } + else + { + total_sensor = ito_test_trianglenum/2 + ito_test_keynum + ito_test_dummynum; + } + } + else if( item_id == 42 ) + { + pMapping = &MAP3[0]; + total_sensor = ito_test_trianglenum + ito_test_keynum+ ito_test_dummynum; + } + + + loop = 1; + if ( item_id != 42 ) + { + if(total_sensor>11) + { + loop = 2; + } + } + ITO_TEST_DEBUG("loop=%d\n",loop); + for ( i = 0; i < loop; i++ ) + { + if ( i == 0 ) + { + ito_test_send_data_in( item_id - 36 ); + } + else + { + if ( item_id == 40 ) + ito_test_send_data_in( 9 ); + else + ito_test_send_data_in( 10 ); + } + + ito_test_set_v(1,0); + u16RegValue = ito_test_ReadReg( 0x11, 0x0E); + ito_test_WriteReg( 0x11, 0x0E, u16RegValue | BIT11 ); + + if ( g_LTP == 1 ) + ito_test_set_c( 32 ); + else + ito_test_set_c( 0 ); + + ito_test_sw(); + + if ( i == 0 ) + { + num_of_sensor=ito_test_get_data_out( s16_raw_data_tmp ); + ITO_TEST_DEBUG("num_of_sensor=%d;\n",num_of_sensor); + } + else + { + num_of_sensor2=ito_test_get_data_out( &s16_raw_data_tmp[num_of_sensor] ); + ITO_TEST_DEBUG("num_of_sensor=%d;num_of_sensor2=%d\n",num_of_sensor,num_of_sensor2); + } + } + for ( j = 0; j < total_sensor ; j ++ ) + { + if ( g_LTP == 1 ) + s16_raw_data[pMapping[j]] = s16_raw_data_tmp[j] + 4096; + else + s16_raw_data[pMapping[j]] = s16_raw_data_tmp[j]; + } + + return; +} + +typedef enum +{ + ITO_TEST_OK = 0, + ITO_TEST_FAIL, + ITO_TEST_GET_TP_TYPE_ERROR, +} ITO_TEST_RET; + +ITO_TEST_RET ito_test_second (u8 item_id) +{ + u8 i = 0; + + s32 s16_raw_data_jg_tmp1 = 0; + s32 s16_raw_data_jg_tmp2 = 0; + s32 jg_tmp1_avg_Th_max =0; + s32 jg_tmp1_avg_Th_min =0; + s32 jg_tmp2_avg_Th_max =0; + s32 jg_tmp2_avg_Th_min =0; + + u8 Th_Tri = 25; + u8 Th_bor = 25; + + if ( item_id == 40 ) + { + for (i=0; i<(ito_test_trianglenum/2)-2; i++) + { + s16_raw_data_jg_tmp1 += s16_raw_data_1[MAP40_1[i]]; + } + for (i=0; i<2; i++) + { + s16_raw_data_jg_tmp2 += s16_raw_data_1[MAP40_2[i]]; + } + } + else if( item_id == 41 ) + { + for (i=0; i<(ito_test_trianglenum/2)-2; i++) + { + s16_raw_data_jg_tmp1 += s16_raw_data_2[MAP41_1[i]]; + } + for (i=0; i<2; i++) + { + s16_raw_data_jg_tmp2 += s16_raw_data_2[MAP41_2[i]]; + } + } + + jg_tmp1_avg_Th_max = (s16_raw_data_jg_tmp1 / ((ito_test_trianglenum/2)-2)) * ( 100 + Th_Tri) / 100 ; + jg_tmp1_avg_Th_min = (s16_raw_data_jg_tmp1 / ((ito_test_trianglenum/2)-2)) * ( 100 - Th_Tri) / 100 ; + jg_tmp2_avg_Th_max = (s16_raw_data_jg_tmp2 / 2) * ( 100 + Th_bor) / 100 ; + jg_tmp2_avg_Th_min = (s16_raw_data_jg_tmp2 / 2 ) * ( 100 - Th_bor) / 100 ; + + ITO_TEST_DEBUG("item_id=%d;sum1=%d;max1=%d;min1=%d;sum2=%d;max2=%d;min2=%d\n",item_id,s16_raw_data_jg_tmp1,jg_tmp1_avg_Th_max,jg_tmp1_avg_Th_min,s16_raw_data_jg_tmp2,jg_tmp2_avg_Th_max,jg_tmp2_avg_Th_min); + + if ( item_id == 40 ) + { + for (i=0; i<(ito_test_trianglenum/2)-2; i++) + { + if (s16_raw_data_1[MAP40_1[i]] > jg_tmp1_avg_Th_max || s16_raw_data_1[MAP40_1[i]] < jg_tmp1_avg_Th_min) + return ITO_TEST_FAIL; + } + for (i=0; i<(ito_test_trianglenum/2)-3; i++) + { + if (s16_raw_data_1[MAP40_1[i]] > s16_raw_data_1[MAP40_1[i+1]] ) + return ITO_TEST_FAIL; + } + for (i=0; i<2; i++) + { + if (s16_raw_data_1[MAP40_2[i]] > jg_tmp2_avg_Th_max || s16_raw_data_1[MAP40_2[i]] < jg_tmp2_avg_Th_min) + return ITO_TEST_FAIL; + } + } + + if ( item_id == 41 ) + { + for (i=0; i<(ito_test_trianglenum/2)-2; i++) + { + if (s16_raw_data_2[MAP41_1[i]] > jg_tmp1_avg_Th_max || s16_raw_data_2[MAP41_1[i]] < jg_tmp1_avg_Th_min) + return ITO_TEST_FAIL; + } + for (i=0; i<(ito_test_trianglenum/2)-3; i++) + { + if (s16_raw_data_2[MAP41_1[i]] < s16_raw_data_2[MAP41_1[i+1]] ) + return ITO_TEST_FAIL; + } + + for (i=0; i<2; i++) + { + if (s16_raw_data_2[MAP41_2[i]] > jg_tmp2_avg_Th_max || s16_raw_data_2[MAP41_2[i]] < jg_tmp2_avg_Th_min) + return ITO_TEST_FAIL; + } + } + + return ITO_TEST_OK; + +} +ITO_TEST_RET ito_test_second_2r (u8 item_id) +{ + u8 i = 0; + + s32 s16_raw_data_jg_tmp1 = 0; + s32 s16_raw_data_jg_tmp2 = 0; + s32 s16_raw_data_jg_tmp3 = 0; + s32 s16_raw_data_jg_tmp4 = 0; + + s32 jg_tmp1_avg_Th_max =0; + s32 jg_tmp1_avg_Th_min =0; + s32 jg_tmp2_avg_Th_max =0; + s32 jg_tmp2_avg_Th_min =0; + s32 jg_tmp3_avg_Th_max =0; + s32 jg_tmp3_avg_Th_min =0; + s32 jg_tmp4_avg_Th_max =0; + s32 jg_tmp4_avg_Th_min =0; + + u8 Th_Tri = 25; // non-border threshold + u8 Th_bor = 25; // border threshold + + if ( item_id == 40 ) + { + for (i=0; i<(ito_test_trianglenum/4)-2; i++) + { + s16_raw_data_jg_tmp1 += s16_raw_data_1[MAP40_1[i]]; //first region: non-border + } + for (i=0; i<2; i++) + { + s16_raw_data_jg_tmp2 += s16_raw_data_1[MAP40_2[i]]; //first region: border + } + + for (i=0; i<(ito_test_trianglenum/4)-2; i++) + { + s16_raw_data_jg_tmp3 += s16_raw_data_1[MAP40_3[i]]; //second region: non-border + } + for (i=0; i<2; i++) + { + s16_raw_data_jg_tmp4 += s16_raw_data_1[MAP40_4[i]]; //second region: border + } + } + + + + + else if( item_id == 41 ) + { + for (i=0; i<(ito_test_trianglenum/4)-2; i++) + { + s16_raw_data_jg_tmp1 += s16_raw_data_2[MAP41_1[i]]; //first region: non-border + } + for (i=0; i<2; i++) + { + s16_raw_data_jg_tmp2 += s16_raw_data_2[MAP41_2[i]]; //first region: border + } + for (i=0; i<(ito_test_trianglenum/4)-2; i++) + { + s16_raw_data_jg_tmp3 += s16_raw_data_2[MAP41_3[i]]; //second region: non-border + } + for (i=0; i<2; i++) + { + s16_raw_data_jg_tmp4 += s16_raw_data_2[MAP41_4[i]]; //second region: border + } + } + + jg_tmp1_avg_Th_max = (s16_raw_data_jg_tmp1 / ((ito_test_trianglenum/4)-2)) * ( 100 + Th_Tri) / 100 ; + jg_tmp1_avg_Th_min = (s16_raw_data_jg_tmp1 / ((ito_test_trianglenum/4)-2)) * ( 100 - Th_Tri) / 100 ; + jg_tmp2_avg_Th_max = (s16_raw_data_jg_tmp2 / 2) * ( 100 + Th_bor) / 100 ; + jg_tmp2_avg_Th_min = (s16_raw_data_jg_tmp2 / 2) * ( 100 - Th_bor) / 100 ; + jg_tmp3_avg_Th_max = (s16_raw_data_jg_tmp3 / ((ito_test_trianglenum/4)-2)) * ( 100 + Th_Tri) / 100 ; + jg_tmp3_avg_Th_min = (s16_raw_data_jg_tmp3 / ((ito_test_trianglenum/4)-2)) * ( 100 - Th_Tri) / 100 ; + jg_tmp4_avg_Th_max = (s16_raw_data_jg_tmp4 / 2) * ( 100 + Th_bor) / 100 ; + jg_tmp4_avg_Th_min = (s16_raw_data_jg_tmp4 / 2) * ( 100 - Th_bor) / 100 ; + + + ITO_TEST_DEBUG("item_id=%d;sum1=%d;max1=%d;min1=%d;sum2=%d;max2=%d;min2=%d;sum3=%d;max3=%d;min3=%d;sum4=%d;max4=%d;min4=%d;\n",item_id,s16_raw_data_jg_tmp1,jg_tmp1_avg_Th_max,jg_tmp1_avg_Th_min,s16_raw_data_jg_tmp2,jg_tmp2_avg_Th_max,jg_tmp2_avg_Th_min,s16_raw_data_jg_tmp3,jg_tmp3_avg_Th_max,jg_tmp3_avg_Th_min,s16_raw_data_jg_tmp4,jg_tmp4_avg_Th_max,jg_tmp4_avg_Th_min); + + + + + if ( item_id == 40 ) + { + for (i=0; i<(ito_test_trianglenum/4)-2; i++) + { + if (s16_raw_data_1[MAP40_1[i]] > jg_tmp1_avg_Th_max || s16_raw_data_1[MAP40_1[i]] < jg_tmp1_avg_Th_min) + return ITO_TEST_FAIL; + } + + for (i=0; i<2; i++) + { + if (s16_raw_data_1[MAP40_2[i]] > jg_tmp2_avg_Th_max || s16_raw_data_1[MAP40_2[i]] < jg_tmp2_avg_Th_min) + return ITO_TEST_FAIL; + } + + for (i=0; i<(ito_test_trianglenum/4)-2; i++) + { + if (s16_raw_data_1[MAP40_3[i]] > jg_tmp3_avg_Th_max || s16_raw_data_1[MAP40_3[i]] < jg_tmp3_avg_Th_min) + return ITO_TEST_FAIL; + } + + for (i=0; i<2; i++) + { + if (s16_raw_data_1[MAP40_4[i]] > jg_tmp4_avg_Th_max || s16_raw_data_1[MAP40_4[i]] < jg_tmp4_avg_Th_min) + return ITO_TEST_FAIL; + } + } + + if ( item_id == 41 ) + { + for (i=0; i<(ito_test_trianglenum/4)-2; i++) + { + if (s16_raw_data_2[MAP41_1[i]] > jg_tmp1_avg_Th_max || s16_raw_data_2[MAP41_1[i]] < jg_tmp1_avg_Th_min) + return ITO_TEST_FAIL; + } + + for (i=0; i<2; i++) + { + if (s16_raw_data_2[MAP41_2[i]] > jg_tmp2_avg_Th_max || s16_raw_data_2[MAP41_2[i]] < jg_tmp2_avg_Th_min) + return ITO_TEST_FAIL; + } + + for (i=0; i<(ito_test_trianglenum/4)-2; i++) + { + if (s16_raw_data_2[MAP41_3[i]] > jg_tmp3_avg_Th_max || s16_raw_data_2[MAP41_3[i]] < jg_tmp3_avg_Th_min) + return ITO_TEST_FAIL; + } + + for (i=0; i<2; i++) + { + if (s16_raw_data_2[MAP41_4[i]] > jg_tmp4_avg_Th_max || s16_raw_data_2[MAP41_4[i]] < jg_tmp4_avg_Th_min) + return ITO_TEST_FAIL; + } + + } + + return ITO_TEST_OK; + +} + +static ITO_TEST_RET ito_test_interface(void) +{ + ITO_TEST_RET ret = ITO_TEST_OK; + uint16_t i = 0; +#ifdef DMA_IIC + _msg_dma_alloc(); +#endif + ito_test_set_iic_rate(50000); + ITO_TEST_DEBUG("start\n"); + ito_test_disable_irq(); + ito_test_reset(); + if(!ito_test_choose_TpType()) + { + ITO_TEST_DEBUG("choose tpType fail\n"); + ret = ITO_TEST_GET_TP_TYPE_ERROR; + goto ITO_TEST_END; + } + ito_test_EnterSerialDebugMode(); + mdelay(100); + ITO_TEST_DEBUG("EnterSerialDebugMode\n"); + ito_test_WriteReg8Bit ( 0x0F, 0xE6, 0x01 ); + ito_test_WriteReg ( 0x3C, 0x60, 0xAA55 ); + ITO_TEST_DEBUG("stop mcu and disable watchdog V.005\n"); + mdelay(50); + + for(i = 0;i < 48;i++) + { + s16_raw_data_1[i] = 0; + s16_raw_data_2[i] = 0; + s16_raw_data_3[i] = 0; + } + + ito_test_first(40, s16_raw_data_1); + ITO_TEST_DEBUG("40 get s16_raw_data_1\n"); + if(ito_test_2r) + { + ret=ito_test_second_2r(40); + } + else + { + ret=ito_test_second(40); + } + if(ITO_TEST_FAIL==ret) + { + goto ITO_TEST_END; + } + + ito_test_first(41, s16_raw_data_2); + ITO_TEST_DEBUG("41 get s16_raw_data_2\n"); + if(ito_test_2r) + { + ret=ito_test_second_2r(41); + } + else + { + ret=ito_test_second(41); + } + if(ITO_TEST_FAIL==ret) + { + goto ITO_TEST_END; + } + + ito_test_first(42, s16_raw_data_3); + ITO_TEST_DEBUG("42 get s16_raw_data_3\n"); + + ITO_TEST_END: +#ifdef DMA_IIC + _msg_dma_free(); +#endif + ito_test_set_iic_rate(100000); + ito_test_reset(); + ito_test_enable_irq(); + ITO_TEST_DEBUG("end\n"); + return ret; +} + +#include <linux/proc_fs.h> +#define ITO_TEST_AUTHORITY 0777 +static struct proc_dir_entry *msg_ito_test = NULL; +static struct proc_dir_entry *debug = NULL; +static struct proc_dir_entry *debug_on_off = NULL; +#define PROC_MSG_ITO_TESE "msg-ito-test" +#define PROC_ITO_TEST_DEBUG "debug" +#define PROC_ITO_TEST_DEBUG_ON_OFF "debug-on-off" +ITO_TEST_RET g_ito_test_ret = ITO_TEST_OK; +static int ito_test_proc_read_debug(char *page, char **start, off_t off, int count, int *eof, void *data) +{ + int cnt= 0; + + g_ito_test_ret = ito_test_interface(); + if(ITO_TEST_OK==g_ito_test_ret) + { + ITO_TEST_DEBUG_MUST("ITO_TEST_OK"); + } + else if(ITO_TEST_FAIL==g_ito_test_ret) + { + ITO_TEST_DEBUG_MUST("ITO_TEST_FAIL"); + } + else if(ITO_TEST_GET_TP_TYPE_ERROR==g_ito_test_ret) + { + ITO_TEST_DEBUG_MUST("ITO_TEST_GET_TP_TYPE_ERROR"); + } + + *eof = 1; + return cnt; +} + +static int ito_test_proc_write_debug(struct file *file, const char *buffer, unsigned long count, void *data) +{ + u16 i = 0; + mdelay(5); + ITO_TEST_DEBUG_MUST("ito_test_ret = %d",g_ito_test_ret); + mdelay(5); + for(i=0;i<48;i++) + { + ITO_TEST_DEBUG_MUST("data_1[%d]=%d;\n",i,s16_raw_data_1[i]); + } + mdelay(5); + for(i=0;i<48;i++) + { + ITO_TEST_DEBUG_MUST("data_2[%d]=%d;\n",i,s16_raw_data_2[i]); + } + mdelay(5); + for(i=0;i<48;i++) + { + ITO_TEST_DEBUG_MUST("data_3[%d]=%d;\n",i,s16_raw_data_3[i]); + } + mdelay(5); + return count; +} +static int ito_test_proc_read_debug_on_off(char *page, char **start, off_t off, int count, int *eof, void *data) +{ + int cnt= 0; + + bItoTestDebug = 1; + ITO_TEST_DEBUG_MUST("on debug bItoTestDebug = %d",bItoTestDebug); + + *eof = 1; + return cnt; +} + +static int ito_test_proc_write_debug_on_off(struct file *file, const char *buffer, unsigned long count, void *data) +{ + bItoTestDebug = 0; + ITO_TEST_DEBUG_MUST("off debug bItoTestDebug = %d",bItoTestDebug); + return count; +} + +static void ito_test_create_entry(void) +{ + + static const struct file_operations debug_ops = { + .owner = THIS_MODULE, + .read = ito_test_proc_read_debug, + .write = ito_test_proc_write_debug, + }; + + static const struct file_operations debug_on_off_ops = { + .owner = THIS_MODULE, + .read = ito_test_proc_read_debug_on_off, + .write = ito_test_proc_write_debug_on_off, + }; + + msg_ito_test = proc_mkdir(PROC_MSG_ITO_TESE, NULL); + debug = proc_create(PROC_ITO_TEST_DEBUG,ITO_TEST_AUTHORITY,msg_ito_test,&debug_ops); + debug_on_off = proc_create(PROC_ITO_TEST_DEBUG_ON_OFF,ITO_TEST_AUTHORITY,msg_ito_test,&debug_on_off_ops); + if (NULL==debug) + { + ITO_TEST_DEBUG_MUST("create_proc_entry ITO TEST DEBUG failed\n"); + } + else + { + ITO_TEST_DEBUG_MUST("create_proc_entry ITO TEST DEBUG OK\n"); + } + if (NULL==debug_on_off) + { + ITO_TEST_DEBUG_MUST("create_proc_entry ITO TEST ON OFF failed\n"); + } + else + { + ITO_TEST_DEBUG_MUST("create_proc_entry ITO TEST ON OFF OK\n"); + } +} +#endif +MODULE_AUTHOR("Jianchun Bian <jcbian@pixcir.com.cn>"); +MODULE_DESCRIPTION("Pixcir I2C Touchscreen Driver"); +MODULE_LICENSE("GPL"); |
