blob: 0a4f50744edc449c820086e37b5c652e8e2daefd [file] [log] [blame]
/*
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/input.h>
#include <linux/interrupt.h>
#include <linux/i2c.h>
#include <linux/timer.h>
#include <linux/gpio.h>
#include <linux/sysfs.h>
#include <linux/init.h>
#include <linux/mutex.h>
#include <linux/spinlock.h>
#include <linux/hrtimer.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/syscalls.h>
#include <linux/file.h>
#include <linux/fs.h>
#include <linux/fcntl.h>
#include <linux/string.h>
#include <linux/unistd.h>
#include <linux/cdev.h>
#include <linux/uaccess.h>
#include <linux/earlysuspend.h>
#include <linux/input.h>
*/
#include <linux/module.h>
#include <linux/input.h>
#include <linux/interrupt.h>
#include <linux/hrtimer.h>
#include <linux/platform_device.h>
#include <linux/i2c.h>
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/gpio.h>
#include <linux/earlysuspend.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/notifier.h>
#include <linux/wakelock.h>
#include <linux/of.h>
#include <linux/of_irq.h>
#include <linux/of_platform.h>
#include <linux/i2c-kona.h>
#include <linux/leds.h>
#include <linux/vmalloc.h>
#include <linux/uaccess.h>
#include <linux/fs.h>
#define VKEY_SYS
#define u8 unsigned char
#define u32 unsigned int
#define s32 signed int
#define REPORT_PACKET_LENGTH (8)
#define __FIRMWARE_UPDATE__
#define GPIO_TO_IRQ gpio_to_irq
static struct workqueue_struct *mstar_wq;
static int dbg_isr_num;
static int dbg_isr_disp;
static int msg21xx_irq;
static struct i2c_client *msg21xx_i2c_client;
static struct work_struct msg21xx_wq;
static struct delayed_work msg21xx_firmware_update;
static struct early_suspend early_suspend;
static struct input_dev *input;
typedef struct {
struct i2c_slave_platform_data i2c_pdata;
struct i2c_client *client;
int gpio_irq_pin;
int gpio_reset_pin;
int x_max_value;
int y_max_value;
} msg21xx_ts_data;
static int ts_gpio_irq_pin;
static int ts_gpio_reset_pin;
static int ts_x_max_value;
static int ts_y_max_value;
static const char *vkey_scope;
static bool have_vkey;
static struct workqueue_struct *synaptics_wq;
static struct wake_lock update_wake_lock;
static u8 g_dwiic_info_data[1024]; // Buffer for info data
u32 crc_tab[256];
#define N_BYTE_PER_TIME (8)
#define UPDATE_TIMES (1024/N_BYTE_PER_TIME)
#if 1
#define TP_DEBUG_ERR(format, ...) printk(KERN_ERR "MSG2133_MSG21XXA_updating ***" format "\n", ## __VA_ARGS__)
#else
#define TP_DEBUG_ERR(format, ...)
#endif
//#define __FIRMWARE_UPDATE_AT_BOOT__
#define MAX_TOUCH_FINGER 2
typedef struct {
u16 X;
u16 Y;
} TouchPoint_t;
typedef struct {
u8 nTouchKeyMode;
u8 nTouchKeyCode;
u8 nFingerNum;
TouchPoint_t Point[MAX_TOUCH_FINGER];
} TouchScreenInfo_t;
static BLOCKING_NOTIFIER_HEAD(touch_key_notifier);
static int register_touch_key_notifier(struct notifier_block *n)
{
return blocking_notifier_chain_register(&touch_key_notifier, n);
}
static int unregister_touch_key_notifier(struct notifier_block *n)
{
return blocking_notifier_chain_unregister(&touch_key_notifier, n);
}
static int g_debugTp;
static ssize_t tp_debug_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
return sprintf(buf, "%d\n", g_debugTp);
}
static ssize_t tp_debug_store(struct device *dev,
struct device_attribute *attr, const char *buf,
size_t size)
{
if (buf[0] == '0')
g_debugTp = 0;
else if (buf[0] == '1')
g_debugTp = 1;
else
g_debugTp = 2;
return size;
}
static DEVICE_ATTR(debug, 0777, tp_debug_show, tp_debug_store);
#ifdef __FIRMWARE_UPDATE__
#define FW_ADDR_MSG21XX (0xC4>>1)
#define FW_ADDR_MSG21XX_TP (0x4C>>1)
#define FW_UPDATE_ADDR_MSG21XX (0x92>>1)
#define TP_DEBUG printk
static char *fw_version;
static u8 temp[94][1024];
static unsigned short major, minor;
static unsigned short wanted_major;
static unsigned short wanted_minor;
static u8 curr_ic_type = 0;
#define CTP_ID_MSG21XX 1
#define CTP_ID_MSG21XXA 2
static unsigned short curr_ic_major=0;
static unsigned short curr_ic_minor=0;
static unsigned short update_bin_major=0;
static unsigned short update_bin_minor=0;
static u8 Fmr_Loader[1024];
static unsigned char MSG21XX_update_bin[]=
{
//#include <linux/i2c/File_123456.h>
//#include <linux/i2c/PB287_tp_V0x10002.h>
};
unsigned char MSG_FIRMWARE[94*1024] = {
//#include <linux/i2c/File_5_28_18_16.h>
//#include <linux/i2c/msg_21xx_firmware_v2.04.h>
};
static int FwDataCnt;
struct class *firmware_class;
struct device *firmware_cmd_dev;
static int HalTscrCReadI2CSeq(u8 addr, u8 *read_data, u8 size)
{
int ret;
/*according to your platform.*/
#if 0
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(KERN_ERR "HalTscrCReadI2CSeq error %d\n", rc);
return rc;
#else
msg21xx_i2c_client->addr = addr;
ret = i2c_master_recv(msg21xx_i2c_client, &read_data[0], size);
msg21xx_i2c_client->addr = FW_ADDR_MSG21XX_TP;
return ret;
#endif
}
static int HalTscrCDevWriteI2CSeq(u8 addr, u8 *data, u16 size)
{
int ret;
#if 0
/*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(KERN_ERR "HalTscrCDevWriteI2CSeq error %d, addr = %d\n", rc, addr);
return rc;
#else
msg21xx_i2c_client->addr = addr;
ret = i2c_master_send(msg21xx_i2c_client, &data[0], size);
msg21xx_i2c_client->addr = FW_ADDR_MSG21XX_TP;
return ret;
#endif
}
static void HalDisableIrq(void)
{
disable_irq_nosync(msg21xx_irq);
}
static void HalEnableIrq(void)
{
enable_irq(msg21xx_irq);
}
static void msg21xx_chip_init(void);
static void _HalTscrHWReset(void)
{
#if 0
gpio_request(ts_gpio_reset_pin, "reset");
gpio_direction_output(ts_gpio_reset_pin, 0);
gpio_set_value(ts_gpio_reset_pin, 0);
mdelay(10);/* Note that the RST must be in LOW 10ms at least */
gpio_direction_input(ts_gpio_reset_pin);
gpio_set_value(ts_gpio_reset_pin, 1);
/* Enable the interrupt service thread/routine for INT after 50ms */
gpio_free(ts_gpio_reset_pin);
mdelay(300);
#else
msg21xx_chip_init();
#endif
}
typedef enum {
EMEM_ALL = 0,
EMEM_MAIN,
EMEM_INFO,
} EMEM_TYPE_t;
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 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 unsigned short drvDB_ReadReg ( u8 bank, u8 addr )
{
int ret;
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);
ret = rx_data[1] << 8 | rx_data[0];
return ret;
}
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);
}
static void drvISP_EntryIspMode(void)
{
u8 bWriteData[5] = {
0x4D, 0x53, 0x54, 0x41, 0x52 };
HalTscrCDevWriteI2CSeq(FW_UPDATE_ADDR_MSG21XX, bWriteData, 5);
}
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);
mdelay(1);
if (n == 1) {
HalTscrCReadI2CSeq(FW_UPDATE_ADDR_MSG21XX, &dbbus_rx_data[0],
2);
*pDataToRead = 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);
HalTscrCDevWriteI2CSeq(FW_UPDATE_ADDR_MSG21XX, &bWriteData1, 1);
}
static void drvISP_ExitIspMode(void)
{
u8 bWriteData = 0x24;
HalTscrCDevWriteI2CSeq(FW_UPDATE_ADDR_MSG21XX, &bWriteData, 1);
}
static u8 drvISP_ReadStatus(void)
{
u8 bReadData = 0;
u8 bWriteData[2] = {
0x10, 0x05 };
u8 bWriteData1 = 0x12;
HalTscrCDevWriteI2CSeq(FW_UPDATE_ADDR_MSG21XX, bWriteData, 2);
mdelay(1);
drvISP_Read(1, &bReadData);
HalTscrCDevWriteI2CSeq(FW_UPDATE_ADDR_MSG21XX, &bWriteData1, 1);
return bReadData;
}
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);
mdelay(1);
timeOutCount = 0;
while ((drvISP_ReadStatus() & 0x01) == 0x01) {
timeOutCount++;
if (timeOutCount > 100)
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);
mdelay(1);
timeOutCount = 0;
while ((drvISP_ReadStatus() & 0x01) == 0x01) {
timeOutCount++;
if (timeOutCount > 500)
break; /* around 5 sec timeout */
}
}
static void drvISP_Program(u16 k, u8 *pDataToWrite)
{
u16 i = 0;
u16 j = 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];
mdelay(1);
timeOutCount = 0;
while ((drvISP_ReadStatus() & 0x01) == 0x01) {
timeOutCount++;
if (timeOutCount >= 100000)
break; /* around 1 sec timeout */
}
drvISP_WriteEnable();
/*write 133 bytes per cycle*/
HalTscrCDevWriteI2CSeq(FW_UPDATE_ADDR_MSG21XX, TX_data, 133);
HalTscrCDevWriteI2CSeq(FW_UPDATE_ADDR_MSG21XX, &bWriteData1, 1);
}
}
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);
mdelay(1);
timeOutCount = 0;
while ((drvISP_ReadStatus() & 0x01) == 0x01) {
timeOutCount++;
if (timeOutCount >= 100000)
break; /* around 1 sec timeout */
}
/*write read flash addr*/
HalTscrCDevWriteI2CSeq(FW_UPDATE_ADDR_MSG21XX, bWriteData, 5);
mdelay(1);
drvISP_Read(128, RX_data);
HalTscrCDevWriteI2CSeq(FW_UPDATE_ADDR_MSG21XX, &bWriteData1, 1);
for (i = 0; i < 128; i++) {/*log out if verify error*/
if ((RX_data[i] != 0) && index < 10)
index++;
if (RX_data[i] != pDataToVerify[128 * j + i])
TP_DEBUG("k=%d,j=%d,i=%d==Update Firmware Error=", k, j, i);
}
}
}
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 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_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 );
TP_DEBUG_ERR("2222222222");
do{
reg_data = drvDB_ReadReg ( 0x3C, 0xE4 );
}
while ( reg_data != 0x5B58 );
TP_DEBUG_ERR("33333333333333");
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 );
TP_DEBUG_ERR("4444444444444");
mdelay ( 50 );
// recive info data
//HalTscrCReadI2CSeq ( FW_ADDR_MSG21XX_TP, &g_dwiic_info_data[0], 1024 );
HalTscrCReadI2CSeq ( FW_ADDR_MSG21XX_TP, &g_dwiic_info_data[0], 8 );
TP_DEBUG_ERR("55555555555555");
return ( 1 );
}
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 );
}
}
/* 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_ERR ( "update_C2 OK\n" );
drvISP_ExitIspMode();
_HalTscrHWReset();
FwDataCnt = 0;
HalEnableIrq();
return size;
}
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 ) )
{
TP_DEBUG_ERR ( "update_C32 FAILED\n" );
_HalTscrHWReset();
FwDataCnt = 0;
HalEnableIrq();
return ( 0 );
}
TP_DEBUG_ERR ( "update_C32 OK\n" );
_HalTscrHWReset();
FwDataCnt = 0;
HalEnableIrq();
return size;
#endif
}
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;
TP_DEBUG_ERR("111111111111");
drvTP_read_info_dwiic_c33();
if (1)
{
// 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 );
TP_DEBUG_ERR("666666666666");
//polling 0x3CE4 is 0x2F43
do
{
reg_data = drvDB_ReadReg ( 0x3C, 0xE4 );
}
while ( reg_data != 0x2F43 );
TP_DEBUG_ERR("777777777777");
// transmit lk info data
HalTscrCDevWriteI2CSeq ( FW_ADDR_MSG21XX_TP , &g_dwiic_info_data[0], 1024 );
TP_DEBUG_ERR("88888888888");
//polling 0x3CE4 is 0xD0BC
do
{
reg_data = drvDB_ReadReg ( 0x3C, 0xE4 );
}
while ( reg_data != 0xD0BC );
TP_DEBUG_ERR("9999999999999");
}
//erase main
TP_DEBUG_ERR("aaaaaaaaaaa");
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;
}
TP_DEBUG_ERR("bbbbbbbbbbbbbb");
// polling 0x3CE4 is 0x2F43
do
{
reg_data = drvDB_ReadReg ( 0x3C, 0xE4 );
}
while ( reg_data != 0x2F43 );
TP_DEBUG_ERR("ccccccccccccc");
// 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 );
TP_DEBUG_ERR("dddddddddddddd");
#if 1
{
u32 n = 0;
for(n=0;n<UPDATE_TIMES;n++)
{
// TP_DEBUG_ERR("i=%d,n=%d",i,n);
HalTscrCDevWriteI2CSeq ( FW_ADDR_MSG21XX_TP, temp[i]+n*N_BYTE_PER_TIME, N_BYTE_PER_TIME );
}
}
#else
HalTscrCDevWriteI2CSeq ( FW_ADDR_MSG21XX_TP, temp[i], 1024 );
#endif
TP_DEBUG_ERR("eeeeeeeeeeee");
// polling 0x3CE4 is 0xD0BC
do
{
reg_data = drvDB_ReadReg ( 0x3C, 0xE4 );
}
while ( reg_data != 0xD0BC );
TP_DEBUG_ERR("ffffffffffffff");
drvDB_WriteReg ( 0x3C, 0xE4, 0x2F43 );
}
TP_DEBUG_ERR("ggggggggg");
if ( ( emem_type == EMEM_ALL ) || ( emem_type == EMEM_MAIN ) )
{
// write file done and check crc
drvDB_WriteReg ( 0x3C, 0xE4, 0x1380 );
TP_DEBUG_ERR("hhhhhhhhhhhhhh");
}
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
TP_DEBUG_ERR("iiiiiiiiii");
do
{
reg_data = drvDB_ReadReg ( 0x3C, 0xE4 );
}while ( reg_data != 0x9432 );
TP_DEBUG_ERR("jjjjjjjjjjjjj");
}
crc_main = crc_main ^ 0xffffffff;
crc_info = crc_info ^ 0xffffffff;
if ( ( emem_type == EMEM_ALL ) || ( emem_type == EMEM_MAIN ) )
{
TP_DEBUG_ERR("kkkkkkkkkkk");
// 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();
TP_DEBUG_ERR("lllllllllllll");
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 )
{
TP_DEBUG_ERR ( "update_C33 ok111\n" );
_HalTscrHWReset();
FwDataCnt = 0;
HalEnableIrq();
return size;
}
TP_DEBUG_ERR ( "update_C33 OK\n" );
_HalTscrHWReset();
FwDataCnt = 0;
HalEnableIrq();
return size;
}
static ssize_t firmware_update_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
return sprintf(buf, "%s\n", fw_version);
}
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};
HalDisableIrq();
_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 );
TP_DEBUG_ERR ( "111dbbus_rx version[0]=0x%x", dbbus_rx_data[0] );
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_ERR ( "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 );
}
}
static DEVICE_ATTR(update, 0777, firmware_update_show, firmware_update_store);
/*test=================*/
static ssize_t firmware_clear_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
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++) {
bWriteData[2] = (u8) ((addr + j * 128) >> 16);
bWriteData[3] = (u8) ((addr + j * 128) >> 8);
bWriteData[4] = (u8) (addr + j * 128);
mdelay(1);
timeOutCount = 0;
while ((drvISP_ReadStatus() & 0x01) == 0x01) {
timeOutCount++;
if (timeOutCount >= 100000)
break; /* around 1 sec timeout */
}
HalTscrCDevWriteI2CSeq(FW_UPDATE_ADDR_MSG21XX,
bWriteData, 5);
mdelay(1);
drvISP_Read(128, RX_data);
HalTscrCDevWriteI2CSeq(FW_UPDATE_ADDR_MSG21XX,
&bWriteData1, 1);
for (i = 0; i < 128; i++) { /*log out if verify error*/
if (RX_data[i] != 0xFF) {
TP_DEBUG
("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 };
_HalTscrHWReset();
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();
TP_DEBUG("chip erase+\n");
drvISP_ChipErase();
TP_DEBUG("chip erase-\n");
drvISP_ExitIspMode();
return size;
}
static DEVICE_ATTR(clear, 0777, firmware_clear_show, firmware_clear_store);
/*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] = {0};
unsigned char dbbus_rx_data[4] = {0};
unsigned short major = 0, minor = 0;
fw_version = kzalloc(sizeof(char), GFP_KERNEL);
/*SM-BUS GET FW 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 = 0;
minor = 0;
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("***fw_version = %s ***\n", fw_version);
return size;
}
static DEVICE_ATTR(version, 0777, 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_ERR("***FwDataCnt = %d ***\n", FwDataCnt);
// for (i = 0; i < 1024; i++)
{
memcpy(temp[FwDataCnt], buf, 1024);
}
FwDataCnt++;
return size;
}
static DEVICE_ATTR(data, 0777, firmware_data_show, firmware_data_store);
#endif
static void msg21xx_suspend(struct early_suspend *h)
{
disable_irq_nosync(msg21xx_irq);
gpio_request(ts_gpio_reset_pin, "reset");
gpio_direction_output(ts_gpio_reset_pin, 0);
gpio_set_value(ts_gpio_reset_pin, 0);
gpio_free(ts_gpio_reset_pin);
}
static void msg21xx_chip_init(void);
static void msg21xx_resume(struct early_suspend *h)
{
msg21xx_chip_init();
#ifdef PACKET_FROM_DBUS
dbbusDWIICEnterSerialDebugMode();
dbbusDWIICIICReshape();
#endif
enable_irq(msg21xx_irq);
}
static void msg21xx_chip_init(void)
{
/* After the LCD is on, power on the TP controller */
gpio_request(ts_gpio_reset_pin, "reset");
gpio_direction_output(ts_gpio_reset_pin, 0);
gpio_set_value(ts_gpio_reset_pin, 0);
mdelay(20);/*min value is 10ms */
gpio_set_value(ts_gpio_reset_pin, 1);
mdelay(80);/*min value is 50ms*/
gpio_free(ts_gpio_reset_pin);
}
static u8 Calculate_8BitsChecksum(u8 *msg, s32 s32Length)
{
s32 s32Checksum = 0;
s32 i;
for (i = 0; i < s32Length; i++)
s32Checksum += msg[i];
return (u8) ((-s32Checksum) & 0xFF);
}
static int i2c_read_bytes(struct i2c_client *client, uint8_t *buf, int len)
{
struct i2c_msg msgs[2];
int ret = -1;
msgs[0].flags = 0;
msgs[0].addr = client->addr;
msgs[0].len = 2;
msgs[0].buf = &buf[0];
msgs[1].flags = I2C_M_RD;
msgs[1].addr = client->addr;
msgs[1].len = len - 2;
msgs[1].buf = &buf[2];
ret = i2c_transfer(client->adapter, msgs, 2);
return ret;
}
static int msg21xx_i2c_rxdata(char *rxdata, int length)
{
int ret;
struct i2c_msg msgs[] = {
{
.addr = msg21xx_i2c_client->addr,
.flags = 0,
.len = 1,
.buf = rxdata,
},
{
.addr = msg21xx_i2c_client->addr,
.flags = I2C_M_RD,
.len = length,
.buf = rxdata,
},
};
ret = i2c_transfer(msg21xx_i2c_client->adapter, msgs, 2);
if (ret < 0)
printk(KERN_ERR "msg %s i2c read error: %d\n", __func__, ret);
return ret;
}
static void msg21xx_data_disposal(struct work_struct *work)
{
u8 temp[REPORT_PACKET_LENGTH+1] = {0};
u8 *val = &temp[1];
u8 Checksum = 0;
u8 i;
u32 delta_x = 0, delta_y = 0;
u32 u32X = 0;
u32 u32Y = 0;
int ret;
u8 touchkeycode = 0;
TouchScreenInfo_t touchData;
static u32 preKeyStatus;
int dbg_isr_numbak = dbg_isr_num;
#define SWAP_X_Y (1)
/*#define REVERSE_X (1)*/
/*#define REVERSE_Y (1)*/
#ifdef SWAP_X_Y
int tempx;
int tempy;
#endif
if (g_debugTp == 1)
printk(KERN_INFO "enter msg21xx_data_disposal.\n");
#ifdef PACKET_FROM_DBUS
val[0] = 0x10;
val[1] = 0x12;
val[2] = 0xE4;
ret = HalTscrCDevWriteI2CSeq(FW_ADDR_MSG21XX, val, 3 );
ret = HalTscrCReadI2CSeq(FW_ADDR_MSG21XX, temp, REPORT_PACKET_LENGTH+1);
drvDB_WriteReg(0x12, 0xEC, 0 );
#else
ret = i2c_master_recv(msg21xx_i2c_client, &val[0], REPORT_PACKET_LENGTH);
#endif
#if 1
if (ret != REPORT_PACKET_LENGTH) {
printk(KERN_ERR "data read error!\n");
enable_irq(msg21xx_irq);
return;
}
if (g_debugTp == 1) {
printk(KERN_INFO "going to print the data.\r\n");
for (i = 0; i < REPORT_PACKET_LENGTH; i++)
{
printk(KERN_INFO "msg21xx_data_disposal--val[%d]=0x%x\r\n",i,val[i]);
}
printk(KERN_INFO "end to print the data.\r\n");
i = 0;
}
#else
if (ret < 0) {
printk(KERN_ERR "[msg21xx_data_disposal] recv err!\n");
return;
}
#endif
/*enable_irq(msg21xx_irq);*/
dbg_isr_disp++;
if (g_debugTp == 2)
return;
Checksum = Calculate_8BitsChecksum(&val[0], 7); /*calculate checksum*/
if ((Checksum == val[7]) && (val[0] == 0x52)) {
/*check the checksum of packet*/
u32X = (((val[1] & 0xF0) << 4) | val[2]);
/*parse the packet to coordinates*/
u32Y = (((val[1] & 0x0F) << 8) | val[3]);
delta_x = (((val[4] & 0xF0) << 4) | val[5]);
delta_y = (((val[4] & 0x0F) << 8) | val[6]);
#ifdef SWAP_X_Y
tempy = u32X;
tempx = u32Y;
u32X = tempx;
u32Y = tempy;
tempy = delta_x;
tempx = delta_y;
delta_x = tempx;
delta_y = tempy;
#endif
#ifdef REVERSE_X
u32X = 2047 - u32X;
delta_x = 4095 - delta_x;
#endif
#ifdef REVERSE_Y
u32Y = 2047 - u32Y;
delta_y = 4095 - delta_y;
#endif
if ((val[1] == 0xFF) && (val[2] == 0xFF)
&& (val[3] == 0xFF) && (val[4] == 0xFF)
&& (val[6] == 0xFF)) {
touchData.Point[0].X = 0; /* final X coordinate*/
touchData.Point[0].Y = 0; /* final Y coordinate*/
if ((val[5] == 0x0) || (val[5] == 0xFF)) {
touchData.nFingerNum = 0;
touchData.nTouchKeyCode = 0;
touchData.nTouchKeyMode = 0;
}
else {
touchData.nTouchKeyMode = 1;
touchData.nTouchKeyCode = val[5];
touchData.nFingerNum = 1;
}
} else {
touchData.nTouchKeyMode = 0;
if (
#ifdef REVERSE_X
(delta_x == 4095)
#else
(delta_x == 0)
#endif
&&
#ifdef REVERSE_Y
(delta_y == 4095)
#else
(delta_y == 0)
#endif
)
{
touchData.nFingerNum = 1; /*one touch*/
touchData.Point[0].X = (u32X * ts_x_max_value) / 2048;
touchData.Point[0].Y = (u32Y * ts_y_max_value) / 2048;
} else {
u32 x2, y2;
touchData.nFingerNum = 2; /*two touch*/
/* Finger 1 */
touchData.Point[0].X = (u32X * ts_x_max_value) / 2048;
touchData.Point[0].Y = (u32Y * ts_y_max_value) / 2048;
/* Finger 2 */
if (delta_x > 2048) { /*transform the unsigh value to sign value*/
delta_x -= 4096;
}
if (delta_y > 2048)
delta_y -= 4096;
x2 = (u32) (u32X + delta_x);
y2 = (u32) (u32Y + delta_y);
touchData.Point[1].X = (x2 * ts_x_max_value) / 2048;
touchData.Point[1].Y = (y2 * ts_y_max_value) / 2048;
}
}
/*report...*/
if (touchData.nTouchKeyMode) {
#ifdef VKEY_SYS
if (touchData.nTouchKeyCode == 1) {
touchData.Point[0].X = 80;
touchData.Point[0].Y = 900;
}
if (touchData.nTouchKeyCode == 2) {
touchData.Point[0].X = 240;
touchData.Point[0].Y = 900;
}
if (touchData.nTouchKeyCode == 4) {
touchData.Point[0].X = 400;
touchData.Point[0].Y = 900;
}
input_report_abs(input,
ABS_MT_POSITION_X,
touchData.Point[0].
X);
input_report_abs(input,
ABS_MT_POSITION_Y,
touchData.Point[0].Y);
input_report_abs(input, ABS_MT_TOUCH_MAJOR, 8);
input_report_key(input, BTN_TOUCH, 1);
if (touchData.Point[0].Y > ts_y_max_value)
blocking_notifier_call_chain(
&touch_key_notifier, 0, NULL);
input_mt_sync(input);
input_sync(input);
#else
if (touchData.nTouchKeyCode == 1)
touchkeycode = KEY_BACK;
if (touchData.nTouchKeyCode == 2)
touchkeycode = KEY_HOME;
if (touchData.nTouchKeyCode == 4)
touchkeycode = KEY_MENU;
if (preKeyStatus != touchkeycode) {
preKeyStatus = touchkeycode;
input_report_key(input, touchkeycode, 1);
}
input_sync(input);
#endif
} else {
preKeyStatus = 0; /*clear key status..*/
if ((touchData.nFingerNum) == 0) { /*touch end*/
/*preFingerNum=0;*/
//input_report_key(input, KEY_BACK, 0);
//input_report_key(input, KEY_HOME, 0);
//input_report_key(input, KEY_MENU, 0);
input_report_key(input, BTN_TOUCH, 0);
input_mt_sync(input);
input_sync(input);
} else { /*touch on screen*/
/*
if(preFingerNum!=touchData.nFingerNum) {
printk("langwenlong number has changed\n");
preFingerNum = touchData.nFingerNum;
input_report_abs(input, ABS_MT_TOUCH_MAJOR, 0);
input_mt_sync(input);
input_sync(input);
} */
for (i = 0; i < (touchData.nFingerNum); i++) {
input_report_abs(input,
ABS_MT_POSITION_X,
touchData.Point[i].
X);
input_report_abs(input,
ABS_MT_POSITION_Y,
touchData.Point[i].Y);
input_report_abs(input, ABS_MT_TOUCH_MAJOR, 8);
input_report_key(input, BTN_TOUCH, 1);
if (g_debugTp == 1)
printk(KERN_INFO "x=%d,y=%d \r\n",
touchData.Point[i].X,
touchData.Point[i].Y);
input_mt_sync(input);
}
input_sync(input);
}
}
} else
printk(KERN_ERR "checksum error!\n");
if (g_debugTp == 1)
printk(KERN_INFO "msg21xx_data_disposal dbg_isr_disp=%d,dbg_isr_num=%d,diff=%d\n",
dbg_isr_disp, dbg_isr_num, dbg_isr_num - dbg_isr_disp);
enable_irq(msg21xx_irq);
}
static u8 getchipType(void)
{
u8 curr_ic_type = 0;
u8 dbbus_tx_data[4];
unsigned char dbbus_rx_data[2] = {0};
//_HalTscrHWReset();
HalDisableIrq();
//mdelay ( 300 );
dbbusDWIICEnterSerialDebugMode();
dbbusDWIICStopMCU();
dbbusDWIICIICUseBus();
dbbusDWIICIICReshape();
mdelay ( 200 );
// 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 );
mdelay(300);
HalTscrCReadI2CSeq ( FW_ADDR_MSG21XX, &dbbus_rx_data[0], 2 );
if ( dbbus_rx_data[0] == 2 )
{
curr_ic_type = CTP_ID_MSG21XXA;
}
else
{
curr_ic_type = CTP_ID_MSG21XX;
}
TP_DEBUG_ERR("CURR_IC_TYPE = %d \n",curr_ic_type);
//dbbusDWIICIICNotUseBus();
//dbbusDWIICNotStopMCU();
//dbbusDWIICExitSerialDebugMode();
HalEnableIrq();
_HalTscrHWReset();
return curr_ic_type;
}
static void getMSG21XXFWVersion(u8 curr_ic_type)
{
unsigned char dbbus_tx_data[3]={0};
unsigned char dbbus_rx_data[4]={0} ;
unsigned short major=0, minor=0;
int ret_write=0;
int ret_read=0;
_HalTscrHWReset();
HalDisableIrq();
mdelay(300);
dbbusDWIICEnterSerialDebugMode();
dbbusDWIICStopMCU();
dbbusDWIICIICUseBus();
dbbusDWIICIICReshape();
mdelay (400 );
dbbus_tx_data[0] = 0x53;
dbbus_tx_data[1] = 0x00;
if(curr_ic_type==CTP_ID_MSG21XXA)
{
dbbus_tx_data[2] = 0x2A;
}
else if(curr_ic_type==CTP_ID_MSG21XX)
{
dbbus_tx_data[2] = 0x74;
}
else
{
TP_DEBUG_ERR("***ic_type = %d ***\n", dbbus_tx_data[2]);
dbbus_tx_data[2] = 0x2A;
}
ret_write=HalTscrCDevWriteI2CSeq(FW_ADDR_MSG21XX_TP, &dbbus_tx_data[0], 3);
mdelay(500);
ret_read=HalTscrCReadI2CSeq(FW_ADDR_MSG21XX_TP, &dbbus_rx_data[0], 4);
curr_ic_major = (dbbus_rx_data[1]<<8)+dbbus_rx_data[0];
curr_ic_minor = (dbbus_rx_data[3]<<8)+dbbus_rx_data[2];
if ((ret_write!=3)||(ret_read!=4)){
curr_ic_major = 0xff;
curr_ic_minor = 0xff;
}
TP_DEBUG("***FW Version major = %d--ret_write=%d,ret_read=%d***\n", curr_ic_major, ret_write, ret_read);
TP_DEBUG("***FW Version minor = %d ***\n", curr_ic_minor);
_HalTscrHWReset();
HalEnableIrq();
mdelay ( 100 );
}
static void tp_firmware_update_work(struct work_struct *work)
{
#if 0
printk("lht--going to update the tp firmware.\r\n");
wake_lock(&update_wake_lock);
firmware_update_store(NULL, NULL, NULL, 0);
wake_unlock(&update_wake_lock);
printk("lht--after update the tp firmware.\r\n");
return;
firmware_version_store(NULL, NULL, NULL, 0);
wanted_major = (MSG_FIRMWARE[0x3076] << 8) + MSG_FIRMWARE[0x3077];
wanted_minor = (MSG_FIRMWARE[0x3074] << 8) + MSG_FIRMWARE[0x3075];
if (((0 < major) && (major < wanted_major))
|| ((major == wanted_major)
&& (minor < wanted_minor))) {
firmware_update_store(NULL, NULL, NULL, 0);
}
#else
printk(KERN_INFO "going to update the tp firmware.\r\n");
wake_lock(&update_wake_lock);
//curr_ic_type = getchipType();
curr_ic_type = 2;
getMSG21XXFWVersion(curr_ic_type);
TP_DEBUG_ERR("[TP] check auto updata\n");
if(curr_ic_type == CTP_ID_MSG21XXA) {
update_bin_major = MSG21XX_update_bin[0x7f4f]<<8|MSG21XX_update_bin[0x7f4e];
update_bin_minor = MSG21XX_update_bin[0x7f51]<<8|MSG21XX_update_bin[0x7f50];
TP_DEBUG_ERR("bin_major = %d\n", update_bin_major);
TP_DEBUG_ERR("bin_minor = %d\n", update_bin_minor);
if((update_bin_major==curr_ic_major \
&&update_bin_minor>curr_ic_minor) \
||((curr_ic_minor==0xff)&&(curr_ic_major==0xff))) {
int i = 0;
for (i = 0; i < 33; i++) {
firmware_data_store(NULL, NULL, &(MSG21XX_update_bin[i*1024]), 0);
}
//kthread_run(fwAutoUpdate, 0, "MSG21XXA_fw_auto_update");
firmware_update_store(NULL, NULL, NULL, 0);
}
}
else if(curr_ic_type == CTP_ID_MSG21XX) {
update_bin_major = MSG21XX_update_bin[0x3076]<<8|MSG21XX_update_bin[0x3077];
update_bin_minor = MSG21XX_update_bin[0x3074]<<8|MSG21XX_update_bin[0x3075];
TP_DEBUG_ERR("bin_major = %d \n",update_bin_major);
TP_DEBUG_ERR("bin_minor = %d \n",update_bin_minor);
if(update_bin_major==curr_ic_major
&&update_bin_minor>curr_ic_minor)
{
int i = 0;
for (i = 0; i < 94; i++)
{
firmware_data_store(NULL, NULL, &(MSG21XX_update_bin[i*1024]), 0);
}
// kthread_run(fwAutoUpdate, 0, "MSG21XX_fw_auto_update");
firmware_update_store(NULL, NULL, NULL, 0);
}
}
wake_unlock(&update_wake_lock);
printk("after update the tp firmware.\r\n");
#endif
}
static int msg21xx_ts_open(struct input_dev *dev)
{
return 0;
}
static void msg21xx_ts_close(struct input_dev *dev)
{
printk(KERN_INFO "msg21xx_ts_close\n");
}
static int msg21xx_init_input(void)
{
int err;
input = input_allocate_device();
input->name = msg21xx_i2c_client->name;
input->phys = "I2C";
if (have_vkey) {
input->id.bustype = BUS_I2C;
input->id.vendor = 0x8888;
input->id.product = 0x6666;
input->id.version = 1000;
}
input->dev.parent = &msg21xx_i2c_client->dev;
input->open = msg21xx_ts_open;
input->close = msg21xx_ts_close;
set_bit(EV_ABS, input->evbit);
set_bit(EV_SYN, input->evbit);
set_bit(EV_KEY, input->evbit);
set_bit(BTN_TOUCH, input->keybit);
if (have_vkey) {
set_bit(KEY_BACK, input->keybit);
set_bit(KEY_MENU, input->keybit);
set_bit(KEY_HOME, input->keybit);
}
set_bit(INPUT_PROP_DIRECT, input->propbit);
input_set_abs_params(input, ABS_MT_POSITION_X, 0,
ts_x_max_value, 0, 0);
input_set_abs_params(input, ABS_MT_POSITION_Y, 0, ts_y_max_value,
0, 0);
input_set_abs_params(input, ABS_MT_TOUCH_MAJOR, 0, 8, 0, 0);
err = input_register_device(input);
if (err)
goto fail_alloc_input;
fail_alloc_input:
return 0;
}
static irqreturn_t msg21xx_interrupt(int irq, void *dev_id)
{
int ret;
dbg_isr_num++;
disable_irq_nosync(msg21xx_irq);
//schedule_work(&msg21xx_wq);
#if 1
if (synaptics_wq) {
//ret = queue_work(mstar_wq, &msg21xx_wq);
ret = queue_work(synaptics_wq, &msg21xx_wq);
if (!ret) {
printk(KERN_INFO " last tp in queue=%d,%d,!!!\n",
dbg_isr_num, dbg_isr_disp);
}
}
#endif
return IRQ_HANDLED;
}
/*
*get firmware size
@firmware_name:firmware name
*note:the firmware default path is sdcard.
if you want to change the dir, please modify by yourself.
*/
static int msg21xx_get_firmware_size(char *firmware_name)
{
struct file *pfile = NULL;
struct inode *inode;
unsigned long magic;
off_t fsize = 0;
char filepath[256];
memset(filepath, 0, sizeof(filepath));
sprintf(filepath, "%s", firmware_name);
if (NULL == pfile)
pfile = filp_open(filepath, O_RDONLY, 0);
if (IS_ERR(pfile)) {
pr_err("error occured while opening file %s.\n", filepath);
return -EIO;
}
inode = pfile->f_dentry->d_inode;
magic = inode->i_sb->s_magic;
fsize = inode->i_size;
filp_close(pfile, NULL);
return fsize;
}
/*
*read firmware buf for .bin file.
@firmware_name: fireware name of full path
@firmware_buf: data buf of fireware
note:the firmware default path is sdcard.
if you want to change the dir, please modify by yourself.
*/
static int msg21xx_read_firmware(char *firmware_name,
unsigned char *firmware_buf)
{
struct file *pfile = NULL;
struct inode *inode;
unsigned long magic;
off_t fsize;
char filepath[256];
loff_t pos;
mm_segment_t old_fs;
if (!firmware_buf) {
pr_err("%s--firmware buffer NULL!\n", __func__);
return -EIO;
}
memset(filepath, 0, sizeof(filepath));
sprintf(filepath, "%s", firmware_name);
if (NULL == pfile)
pfile = filp_open(filepath, O_RDONLY, 0);
if (IS_ERR(pfile)) {
pr_err("error occured while opening file %s.\n", filepath);
return -EIO;
}
inode = pfile->f_dentry->d_inode;
magic = inode->i_sb->s_magic;
fsize = inode->i_size;
old_fs = get_fs();
set_fs(KERNEL_DS);
pos = 0;
vfs_read(pfile, firmware_buf, fsize, &pos);
filp_close(pfile, NULL);
set_fs(old_fs);
return 0;
}
/*
upgrade with *.bin file with full path firmware_name
*/
int msg_fw_upgrade_with_app_file(struct i2c_client *client,
char *firmware_name)
{
u8 *pbt_buf = NULL;
int i_ret;
int i;
int fwsize = msg21xx_get_firmware_size(firmware_name);
printk(KERN_INFO "adcdefghigklmn--fw name:%s\n", firmware_name);
if (fwsize <= 0) {
dev_err(&client->dev, "%s ERROR:Get firmware size failed\n",
__func__);
return -EIO;
}
if (fwsize < 8 || fwsize > 50 * 1024) {
dev_dbg(&client->dev, "%s:FW length error\n", __func__);
return -EIO;
}
/*=========FW upgrade========================*/
pbt_buf = vmalloc(fwsize + 1);
if (!pbt_buf) {
dev_err(&client->dev, "%s() - ERROR: memory allocate failed\n",
__func__);
return -EIO;
}
if (msg21xx_read_firmware(firmware_name, pbt_buf)) {
dev_err(&client->dev, "%s() - ERROR: request_firmware failed\n",
__func__);
vfree(pbt_buf);
return -EIO;
}
/*call the upgrade function */
for (i = 0; i < 33; i++)
firmware_data_store(NULL, NULL, pbt_buf+i*1024, 0);
firmware_update_store(NULL, NULL, NULL, 0);
printk(KERN_INFO "[FTS] upgrade successfully.\n");
vfree(pbt_buf);
return i_ret;
}
#if defined(VKEY_SYS)
static ssize_t msg21xx_virtual_keys_show(struct kobject *kobj,
struct kobj_attribute *attr, char *buf)
{
return sprintf(buf, vkey_scope);
}
static struct kobj_attribute msg21xx_virtual_keys_attr = {
.attr = {
.name = "virtualkeys.ms-msg21xx",
.mode = S_IRUGO,
},
.show = &msg21xx_virtual_keys_show,
};
static ssize_t msg21xx_firmware_version_show(struct kobject *kobj,
struct kobj_attribute *attr, char *buf)
{
firmware_version_store(NULL, attr, buf, 0);
return firmware_version_show(NULL, attr, buf);
}
ssize_t msg21xx_firmware_upgrade_store(struct kobject *kobj,
struct kobj_attribute *attr, const char *buf, size_t count)
{
int i;
char fwname[256];
wake_lock(&update_wake_lock);
memset(fwname, 0, sizeof(fwname));
sprintf(fwname, "%s", buf);
fwname[count - 1] = '\0';
msg_fw_upgrade_with_app_file(msg21xx_i2c_client, fwname);
wake_unlock(&update_wake_lock);
return count;
}
static struct kobj_attribute msg21xx_firmware_version_attr = {
.attr = {
.name = "upgradefw",
.mode = S_IRUGO,
},
.show = &msg21xx_firmware_version_show,
};
static struct kobj_attribute msg21xx_firmware_upgrade_attr = {
.attr = {
.name = "upgradeapp",
.mode = S_IRUGO|S_IWUGO,
},
.show = &msg21xx_firmware_version_show,
.store = &msg21xx_firmware_upgrade_store,
};
static struct attribute *msg21xx_properties_attrs[] = {
&msg21xx_virtual_keys_attr.attr,
&msg21xx_firmware_version_attr.attr,
&msg21xx_firmware_upgrade_attr.attr,
NULL
};
static struct attribute_group msg21xx_properties_attr_group = {
.attrs = msg21xx_properties_attrs,
};
#endif
static int __devinit msg21xx_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
int err = 0;
u32 val;
u8 chip_type = 0;
msg21xx_ts_data *pdata = NULL;
struct device_node *np = client->dev.of_node;
if (!client) {
err = -1;
goto err_i2c_client_check;
}
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
printk(KERN_ERR "%s: need I2C_FUNC_I2C\n", __func__);
err = -ENODEV;
goto err_i2c_client_check;
}
pdata = kzalloc(sizeof(msg21xx_ts_data), GFP_KERNEL);
if (!pdata) {
printk(KERN_ERR "Unable to allocate memory.\n");
return -ENOMEM;
}
msg21xx_i2c_client = client;
if (1 == g_debugTp)
printk(KERN_INFO "enter msg21xx_probe.\r\n");
if (client->dev.platform_data) {
ts_gpio_irq_pin = pdata->gpio_irq_pin;
ts_gpio_reset_pin = pdata->gpio_reset_pin;
ts_x_max_value = pdata->x_max_value;
ts_y_max_value = pdata->y_max_value;
} else if (client->dev.of_node) {
if (!of_property_read_u32(np, "gpio-irq-pin", &val))
ts_gpio_irq_pin = val;
if (!of_property_read_u32(np, "gpio-reset-pin", &val))
ts_gpio_reset_pin = val;
if (!of_property_read_u32(np, "x-max-value", &val))
ts_x_max_value = val;
if (!of_property_read_u32(np, "y-max-value", &val))
ts_y_max_value = val;
if (of_property_read_string(np, "vkey_scope", &vkey_scope)) {
have_vkey = false;
vkey_scope = "\n";
} else {
have_vkey = true;
}
if (!of_property_read_u32(np, "client_func_magic", &val))
pdata->i2c_pdata.client_func_magic = val;
if (!of_property_read_u32(np, "client_func_map", &val))
pdata->i2c_pdata.client_func_map = val;
}
i2c_set_clientdata(client, pdata);
client->dev.platform_data = &pdata->i2c_pdata;
mstar_wq = create_workqueue("mstar_wq");
if (!mstar_wq) {
printk(KERN_ERR "%s--Failed to create workqueue.\r\n",
__func__);
goto exit;
}
INIT_WORK(&msg21xx_wq, msg21xx_data_disposal);
gpio_request(ts_gpio_irq_pin, "interrupt");
gpio_direction_input(ts_gpio_irq_pin);
msg21xx_irq = GPIO_TO_IRQ(ts_gpio_irq_pin);
err = request_irq(msg21xx_irq, msg21xx_interrupt, IRQF_TRIGGER_FALLING,
"msg21xx", NULL);
if (err != 0) {
printk(KERN_ERR "%s: cannot register irq\n", __func__);
goto exit;
}
disable_irq(msg21xx_irq);
msg21xx_chip_init();
chip_type = getchipType();
printk(KERN_INFO "chip_type=%d \n",chip_type);
if (chip_type != 2)
goto chip_not_exist;
#if defined(VKEY_SYS)
struct kobject *properties_kobj;
err = -1;
properties_kobj = kobject_create_and_add("board_properties", NULL);
if (properties_kobj)
err = sysfs_create_group(properties_kobj,
&msg21xx_properties_attr_group);
if (!properties_kobj || err)
pr_err("failed to create board_properties\n");
#endif
wake_lock_init(&update_wake_lock, WAKE_LOCK_SUSPEND, "touch");
INIT_DELAYED_WORK(&msg21xx_firmware_update, tp_firmware_update_work);
msg21xx_init_input();
early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN;
early_suspend.suspend = msg21xx_suspend;
early_suspend.resume = msg21xx_resume;
register_early_suspend(&early_suspend);
/*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");
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);
/* debug*/
if (device_create_file(firmware_cmd_dev, &dev_attr_debug) < 0)
pr_err("Failed to create device file(%s)!\n",
dev_attr_debug.attr.name);
dev_set_drvdata(firmware_cmd_dev, NULL);
#endif /* */
#ifdef __FIRMWARE_UPDATE_AT_BOOT__
queue_delayed_work(mstar_wq, &msg21xx_firmware_update, 5*HZ);
#endif
#ifdef PACKET_FROM_DBUS
mdelay ( 500 );
dbbusDWIICEnterSerialDebugMode();
dbbusDWIICIICReshape();
#endif
#ifdef CONFIG_LEDS_TRIGGER_KPBL
led_kpbl_register(&register_touch_key_notifier);
led_kpbl_unregister(&unregister_touch_key_notifier);
#endif
if (1 == g_debugTp)
printk(KERN_INFO "exit msg21xx_probe.\r\n");
enable_irq(msg21xx_irq);
return 0;
chip_not_exist:
if (mstar_wq != NULL) {
destroy_workqueue(mstar_wq);
mstar_wq = NULL;
}
exit:
if(pdata) {
kfree(pdata);
pdata = NULL;
}
gpio_free(ts_gpio_irq_pin);
err_i2c_client_check:
return err;
}
static int __devexit msg21xx_remove(struct i2c_client *client)
{
return 0;
}
static const struct i2c_device_id msg21xx_id[] = { {"ms-msg21xx", 0x26}, {}
};
MODULE_DEVICE_TABLE(i2c, msg21xx_id);
static struct i2c_driver msg21xx_driver = {
.driver = {
.name = "ms-msg21xx",
.owner = THIS_MODULE, },
.probe = msg21xx_probe,
.remove = __devexit_p(msg21xx_remove),
.id_table = msg21xx_id,
};
static int __init msg21xx_init(void)
{
int err;
synaptics_wq = create_singlethread_workqueue("synaptics_wq");
if (!synaptics_wq) {
printk(KERN_ERR "Could not create work queue synaptics_wq: no memory");
return -ENOMEM;
}
err = i2c_add_driver(&msg21xx_driver);
if (err)
printk(KERN_WARNING "msg21xx driver failed,(errno = %d)\n", err);
else
printk(KERN_INFO "Successfully added driver %s\n", msg21xx_driver.driver.name);
return err;
}
static void __exit msg21xx_cleanup(void)
{
i2c_del_driver(&msg21xx_driver);
}
module_init(msg21xx_init);
module_exit(msg21xx_cleanup);
MODULE_AUTHOR("Mstar semiconductor");
MODULE_DESCRIPTION("Driver for msg21xx Touchscreen Controller");
MODULE_LICENSE("GPL");