summaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/bpf/helpers.c2
-rw-r--r--kernel/cgroup.c20
-rw-r--r--kernel/drivers/input/touchscreen/msg21xx/msg21xx_ts.c1757
-rw-r--r--kernel/drivers/input/touchscreen/synaptics_fw_update.c521
-rw-r--r--kernel/drivers/input/touchscreen/synaptics_i2c_rmi4.c282
-rw-r--r--kernel/drivers/input/touchscreen/synaptics_i2c_rmi4.h6
-rw-r--r--kernel/events/core.c20
-rw-r--r--kernel/power/hibernate.c1
-rw-r--r--kernel/sched/core.c1
-rw-r--r--kernel/sched/cputime.c14
-rw-r--r--kernel/sched/sched.h13
-rw-r--r--kernel/sysctl_binary.c2
-rw-r--r--kernel/trace/trace.c5
-rw-r--r--kernel/trace/trace_irqsoff.c8
-rw-r--r--kernel/trace/trace_printk.c3
-rw-r--r--kernel/watchdog.c9
16 files changed, 563 insertions, 2101 deletions
diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c
index 4504ca66118d..50da680c479f 100644
--- a/kernel/bpf/helpers.c
+++ b/kernel/bpf/helpers.c
@@ -166,7 +166,7 @@ static u64 bpf_get_current_comm(u64 r1, u64 size, u64 r3, u64 r4, u64 r5)
if (!task)
return -EINVAL;
- memcpy(buf, task->comm, min_t(size_t, size, sizeof(task->comm)));
+ strlcpy(buf, task->comm, min_t(size_t, size, sizeof(task->comm)));
return 0;
}
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index d5512e1e7138..e8d71110ed2a 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -2498,6 +2498,14 @@ static void cgroup_migrate_add_src(struct css_set *src_cset,
lockdep_assert_held(&cgroup_mutex);
lockdep_assert_held(&css_set_lock);
+ /*
+ * If ->dead, @src_set is associated with one or more dead cgroups
+ * and doesn't contain any migratable tasks. Ignore it early so
+ * that the rest of migration path doesn't get confused by it.
+ */
+ if (src_cset->dead)
+ return;
+
src_cgrp = cset_cgroup_from_root(src_cset, dst_cgrp->root);
if (!list_empty(&src_cset->mg_preload_node))
@@ -5186,6 +5194,7 @@ static int cgroup_destroy_locked(struct cgroup *cgrp)
__releases(&cgroup_mutex) __acquires(&cgroup_mutex)
{
struct cgroup_subsys_state *css;
+ struct cgrp_cset_link *link;
int ssid;
lockdep_assert_held(&cgroup_mutex);
@@ -5206,11 +5215,18 @@ static int cgroup_destroy_locked(struct cgroup *cgrp)
return -EBUSY;
/*
- * Mark @cgrp dead. This prevents further task migration and child
- * creation by disabling cgroup_lock_live_group().
+ * Mark @cgrp and the associated csets dead. The former prevents
+ * further task migration and child creation by disabling
+ * cgroup_lock_live_group(). The latter makes the csets ignored by
+ * the migration path.
*/
cgrp->self.flags &= ~CSS_ONLINE;
+ spin_lock_bh(&css_set_lock);
+ list_for_each_entry(link, &cgrp->cset_links, cset_link)
+ link->cset->dead = true;
+ spin_unlock_bh(&css_set_lock);
+
/* initiate massacre of all css's */
for_each_css(css, ssid, cgrp)
kill_css(css);
diff --git a/kernel/drivers/input/touchscreen/msg21xx/msg21xx_ts.c b/kernel/drivers/input/touchscreen/msg21xx/msg21xx_ts.c
deleted file mode 100644
index 4eb7fd4b1cc9..000000000000
--- a/kernel/drivers/input/touchscreen/msg21xx/msg21xx_ts.c
+++ /dev/null
@@ -1,1757 +0,0 @@
-/*
- * MStar MSG21XX touchscreen driver
- *
- * Copyright (c) 2006-2012 MStar Semiconductor, Inc.
- *
- * Copyright (C) 2012 Bruce Ding <bruce.ding@mstarsemi.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * 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.
- */
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/kernel.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 <mach/gpio.h>
-#include <linux/spinlock.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 <asm/unistd.h>
-#include <linux/cdev.h>
-#include <asm/uaccess.h>
-#if defined(CONFIG_HAS_EARLYSUSPEND)
-#include <linux/earlysuspend.h>
-#endif
-#include <linux/input.h>
-#if defined(CONFIG_FB)
-#include <linux/notifier.h>
-#include <linux/fb.h>
-#endif
-#ifdef CONFIG_TOUCHSCREEN_PROXIMITY_SENSOR
-#include <linux/input/vir_ps.h>
-#endif
-
-/*=============================================================*/
-// Macro Definition
-/*=============================================================*/
-
-#define TOUCH_DRIVER_DEBUG 0
-#if (TOUCH_DRIVER_DEBUG == 1)
-#define DBG(fmt, arg...) pr_err(fmt, ##arg) //pr_info(fmt, ##arg)
-#else
-#define DBG(fmt, arg...)
-#endif
-
-/*=============================================================*/
-// Constant Value & Variable Definition
-/*=============================================================*/
-
-#define U8 unsigned char
-#define U16 unsigned short
-#define U32 unsigned int
-#define S8 signed char
-#define S16 signed short
-#define S32 signed int
-
-#define TOUCH_SCREEN_X_MIN (0)
-#define TOUCH_SCREEN_Y_MIN (0)
-/*
- * Note.
- * Please change the below touch screen resolution according to the touch panel that you are using.
- */
-#define TOUCH_SCREEN_X_MAX (480)
-#define TOUCH_SCREEN_Y_MAX (800)
-/*
- * Note.
- * Please do not change the below setting.
- */
-#define TPD_WIDTH (2048)
-#define TPD_HEIGHT (2048)
-
-/*
- * Note.
- * Please change the below GPIO pin setting to follow the platform that you are using
- */
-static int int_gpio = 1;
-static int reset_gpio = 0;
-#define MS_TS_MSG21XX_GPIO_RST reset_gpio
-#define MS_TS_MSG21XX_GPIO_INT int_gpio
-//---------------------------------------------------------------------//
-
-//#define SYSFS_AUTHORITY_CHANGE_FOR_CTS_TEST
-
-#ifdef SYSFS_AUTHORITY_CHANGE_FOR_CTS_TEST
-#define SYSFS_AUTHORITY (0644)
-#else
-#define SYSFS_AUTHORITY (0777)
-#endif
-
-#define FIRMWARE_AUTOUPDATE
-#ifdef FIRMWARE_AUTOUPDATE
-typedef enum {
- SWID_START = 1,
- SWID_TRULY = SWID_START,
- SWID_NULL,
-} SWID_ENUM;
-
-unsigned char MSG_FIRMWARE[1][33*1024] =
-{
- {
- #include "msg21xx_truly_update_bin.h"
- }
-};
-#endif
-
-#define CONFIG_TP_HAVE_KEY
-
-/*
- * Note.
- * If the below virtual key value definition are not consistent with those that defined in key layout file of platform,
- * please change the below virtual key value to follow the platform that you are using.
- */
-#ifdef CONFIG_TP_HAVE_KEY
-#define TOUCH_KEY_MENU (139) //229
-#define TOUCH_KEY_HOME (172) //102
-#define TOUCH_KEY_BACK (158)
-#define TOUCH_KEY_SEARCH (217)
-
-const U16 tp_key_array[] = {TOUCH_KEY_MENU, TOUCH_KEY_HOME, TOUCH_KEY_BACK, TOUCH_KEY_SEARCH};
-#define MAX_KEY_NUM (sizeof(tp_key_array)/sizeof(tp_key_array[0]))
-#endif
-
-#define SLAVE_I2C_ID_DBBUS (0xC4>>1)
-#define SLAVE_I2C_ID_DWI2C (0x4C>>1)
-
-#define DEMO_MODE_PACKET_LENGTH (8)
-#define MAX_TOUCH_NUM (2) //5
-
-#define TP_PRINT
-#ifdef TP_PRINT
-static int tp_print_proc_read(void);
-static void tp_print_create_entry(void);
-#endif
-
-static char *fw_version = NULL; // customer firmware version
-static U16 fw_version_major = 0;
-static U16 fw_version_minor = 0;
-static U8 temp[94][1024];
-static U32 crc32_table[256];
-static int FwDataCnt = 0;
-static U8 bFwUpdating = 0;
-static struct class *firmware_class = NULL;
-static struct device *firmware_cmd_dev = NULL;
-
-static struct i2c_client *i2c_client = NULL;
-
-#if defined(CONFIG_FB)
-static int fb_notifier_callback(struct notifier_block *self, unsigned long event, void *data);
-static struct notifier_block msg21xx_fb_notif;
-#elif defined (CONFIG_HAS_EARLYSUSPEND)
-static struct early_suspend mstar_ts_early_suspend;
-#endif
-
-#ifdef CONFIG_TOUCHSCREEN_PROXIMITY_SENSOR
-static U8 bEnableTpProximity = 0;
-static U8 bFaceClosingTp = 0;
-#endif
-static U8 bTpInSuspend = 0;
-
-static int irq_msg21xx = -1;
-static struct work_struct msg21xx_wk;
-static struct mutex msg21xx_mutex;
-static struct input_dev *input_dev = NULL;
-
-/*=============================================================*/
-// Data Type Definition
-/*=============================================================*/
-
-typedef struct
-{
- U16 x;
- U16 y;
-} touchPoint_t;
-
-/// max 80+1+1 = 82 bytes
-typedef struct
-{
- touchPoint_t point[MAX_TOUCH_NUM];
- U8 count;
- U8 keycode;
-} touchInfo_t;
-
-enum i2c_speed
-{
- I2C_SLOW = 0,
- I2C_NORMAL = 1, /* Enable erasing/writing for 10 msec. */
- I2C_FAST = 2, /* Disable EWENB before 10 msec timeout. */
-};
-
-typedef enum
-{
- EMEM_ALL = 0,
- EMEM_MAIN,
- EMEM_INFO,
-} EMEM_TYPE_t;
-
-/*=============================================================*/
-// Function Definition
-/*=============================================================*/
-
-/// CRC
-static U32 _CRC_doReflect(U32 ref, S8 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 _CRC_getValue(U32 text, U32 prevCRC)
-{
- U32 ulCRC = prevCRC;
-
- ulCRC = (ulCRC >> 8) ^ crc32_table[(ulCRC & 0xFF) ^ text];
-
- return ulCRC;
-}
-
-static void _CRC_initTable(void)
-{
- U32 magic_number = 0x04c11db7;
- U32 i, j;
-
- for (i = 0; i <= 0xFF; i ++)
- {
- crc32_table[i] = _CRC_doReflect (i, 8) << 24;
- for (j = 0; j < 8; j ++)
- {
- crc32_table[i] = (crc32_table[i] << 1) ^ (crc32_table[i] & (0x80000000L) ? magic_number : 0);
- }
- crc32_table[i] = _CRC_doReflect(crc32_table[i], 32);
- }
-}
-
-static void reset_hw(void)
-{
- DBG("reset_hw()\n");
-
- gpio_direction_output(MS_TS_MSG21XX_GPIO_RST, 1);
- gpio_set_value(MS_TS_MSG21XX_GPIO_RST, 0);
- mdelay(100); /* Note that the RST must be in LOW 10ms at least */
- gpio_set_value(MS_TS_MSG21XX_GPIO_RST, 1);
- mdelay(100); /* Enable the interrupt service thread/routine for INT after 50ms */
-}
-
-static int read_i2c_seq(U8 addr, U8* buf, U16 size)
-{
- int rc = 0;
- struct i2c_msg msgs[] =
- {
- {
- .addr = addr,
- .flags = I2C_M_RD, // read flag
- .len = size,
- .buf = buf,
- },
- };
-
- /* If everything went ok (i.e. 1 msg transmitted), return #bytes
- transmitted, else error code. */
- if (i2c_client != NULL)
- {
- rc = i2c_transfer(i2c_client->adapter, msgs, 1);
- if (rc < 0)
- {
- DBG("read_i2c_seq() error %d\n", rc);
- }
- }
- else
- {
- DBG("i2c_client is NULL\n");
- }
-
- return rc;
-}
-
-static int write_i2c_seq(U8 addr, U8* buf, U16 size)
-{
- int rc = 0;
- struct i2c_msg msgs[] =
- {
- {
- .addr = addr,
- .flags = 0, // if read flag is undefined, then it means write flag.
- .len = size,
- .buf = buf,
- },
- };
-
- /* If everything went ok (i.e. 1 msg transmitted), return #bytes
- transmitted, else error code. */
- if (i2c_client != NULL)
- {
- rc = i2c_transfer(i2c_client->adapter, msgs, 1);
- if ( rc < 0 )
- {
- DBG("write_i2c_seq() error %d\n", rc);
- }
- }
- else
- {
- DBG("i2c_client is NULL\n");
- }
-
- return rc;
-}
-
-static U16 read_reg(U8 bank, U8 addr)
-{
- U8 tx_data[3] = {0x10, bank, addr};
- U8 rx_data[2] = {0};
-
- write_i2c_seq(SLAVE_I2C_ID_DBBUS, &tx_data[0], 3);
- read_i2c_seq(SLAVE_I2C_ID_DBBUS, &rx_data[0], 2);
-
- return (rx_data[1] << 8 | rx_data[0]);
-}
-
-static void write_reg(U8 bank, U8 addr, U16 data)
-{
- U8 tx_data[5] = {0x10, bank, addr, data & 0xFF, data >> 8};
- write_i2c_seq(SLAVE_I2C_ID_DBBUS, &tx_data[0], 5);
-}
-
-static void write_reg_8bit(U8 bank, U8 addr, U8 data)
-{
- U8 tx_data[4] = {0x10, bank, addr, data};
- write_i2c_seq(SLAVE_I2C_ID_DBBUS, &tx_data[0], 4);
-}
-
-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;
-
- write_i2c_seq(SLAVE_I2C_ID_DBBUS, data, 5);
-}
-
-void dbbusDWIICStopMCU(void)
-{
- U8 data[1];
-
- // Stop the MCU
- data[0] = 0x37;
-
- write_i2c_seq(SLAVE_I2C_ID_DBBUS, data, 1);
-}
-
-void dbbusDWIICIICUseBus(void)
-{
- U8 data[1];
-
- // IIC Use Bus
- data[0] = 0x35;
-
- write_i2c_seq(SLAVE_I2C_ID_DBBUS, data, 1);
-}
-
-void dbbusDWIICIICReshape(void)
-{
- U8 data[1];
-
- // IIC Re-shape
- data[0] = 0x71;
-
- write_i2c_seq(SLAVE_I2C_ID_DBBUS, data, 1);
-}
-
-void dbbusDWIICIICNotUseBus(void)
-{
- U8 data[1];
-
- // IIC Not Use Bus
- data[0] = 0x34;
-
- write_i2c_seq(SLAVE_I2C_ID_DBBUS, data, 1);
-}
-
-void dbbusDWIICNotStopMCU(void)
-{
- U8 data[1];
-
- // Not Stop the MCU
- data[0] = 0x36;
-
- write_i2c_seq(SLAVE_I2C_ID_DBBUS, data, 1);
-}
-
-void dbbusDWIICExitSerialDebugMode(void)
-{
- U8 data[1];
-
- // Exit the Serial Debug Mode
- data[0] = 0x45;
-
- write_i2c_seq(SLAVE_I2C_ID_DBBUS, data, 1);
-
- // Delay some interval to guard the next transaction
- //udelay ( 200 ); // delay about 0.2ms
-}
-
-//---------------------------------------------------------------------//
-
-static U8 get_ic_type(void)
-{
- U8 ic_type = 0;
-
- reset_hw();
- dbbusDWIICEnterSerialDebugMode();
- dbbusDWIICStopMCU();
- dbbusDWIICIICUseBus();
- dbbusDWIICIICReshape();
- mdelay ( 300 );
-
- // stop mcu
- write_reg_8bit ( 0x0F, 0xE6, 0x01 );
- // disable watch dog
- write_reg ( 0x3C, 0x60, 0xAA55 );
- // get ic type
- ic_type = (0xff)&(read_reg(0x1E, 0xCC));
-
- if (ic_type != 1 //msg2133
- && ic_type != 2 //msg21xxA
- && ic_type != 3) //msg26xxM
- {
- ic_type = 0;
- }
-
- reset_hw();
-
- return ic_type;
-}
-
-static int get_customer_firmware_version(void)
-{
- U8 dbbus_tx_data[3] = {0};
- U8 dbbus_rx_data[4] = {0};
- int ret = 0;
-
- DBG("get_customer_firmware_version()\n");
-
- dbbus_tx_data[0] = 0x53;
- dbbus_tx_data[1] = 0x00;
- dbbus_tx_data[2] = 0x2A;
- mutex_lock(&msg21xx_mutex);
- write_i2c_seq(SLAVE_I2C_ID_DWI2C, &dbbus_tx_data[0], 3);
- read_i2c_seq(SLAVE_I2C_ID_DWI2C, &dbbus_rx_data[0], 4);
- mutex_unlock(&msg21xx_mutex);
- fw_version_major = (dbbus_rx_data[1]<<8) + dbbus_rx_data[0];
- fw_version_minor = (dbbus_rx_data[3]<<8) + dbbus_rx_data[2];
-
- DBG("*** major = %d ***\n", fw_version_major);
- DBG("*** minor = %d ***\n", fw_version_minor);
-
- if (fw_version == NULL)
- {
- fw_version = kzalloc(sizeof(char), GFP_KERNEL);
- }
-
- sprintf(fw_version, "%03d%03d", fw_version_major, fw_version_minor);
-
- return ret;
-}
-
-static int firmware_erase_c33 ( EMEM_TYPE_t emem_type )
-{
- // stop mcu
- write_reg ( 0x0F, 0xE6, 0x0001 );
-
- //disable watch dog
- write_reg_8bit ( 0x3C, 0x60, 0x55 );
- write_reg_8bit ( 0x3C, 0x61, 0xAA );
-
- // set PROGRAM password
- write_reg_8bit ( 0x16, 0x1A, 0xBA );
- write_reg_8bit ( 0x16, 0x1B, 0xAB );
-
- write_reg_8bit ( 0x16, 0x18, 0x80 );
-
- if ( emem_type == EMEM_ALL )
- {
- write_reg_8bit ( 0x16, 0x08, 0x10 ); //mark
- }
-
- write_reg_8bit ( 0x16, 0x18, 0x40 );
- mdelay ( 10 );
-
- // clear pce
- write_reg_8bit ( 0x16, 0x18, 0x80 );
-
- // erase trigger
- if ( emem_type == EMEM_MAIN )
- {
- write_reg_8bit ( 0x16, 0x0E, 0x04 ); //erase main
- }
- else
- {
- write_reg_8bit ( 0x16, 0x0E, 0x08 ); //erase all block
- }
-
- 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 )
-{
- U32 i, j;
- U32 crc_main, crc_main_tp;
- U32 crc_info, crc_info_tp;
- U16 reg_data = 0;
- int update_pass = 1;
-
- crc_main = 0xffffffff;
- crc_info = 0xffffffff;
-
- reset_hw();
- dbbusDWIICEnterSerialDebugMode();
- dbbusDWIICStopMCU();
- dbbusDWIICIICUseBus();
- dbbusDWIICIICReshape();
- mdelay ( 300 );
-
- //erase main
- firmware_erase_c33 ( EMEM_MAIN );
- mdelay ( 1000 );
-
- reset_hw();
- dbbusDWIICEnterSerialDebugMode();
- dbbusDWIICStopMCU();
- dbbusDWIICIICUseBus();
- dbbusDWIICIICReshape();
- mdelay ( 300 );
-
- /////////////////////////
- // Program
- /////////////////////////
-
- //polling 0x3CE4 is 0x1C70
- if ( ( emem_type == EMEM_ALL ) || ( emem_type == EMEM_MAIN ) )
- {
- do
- {
- reg_data = read_reg ( 0x3C, 0xE4 );
- }
- while ( reg_data != 0x1C70 );
- }
-
- switch ( emem_type )
- {
- case EMEM_ALL:
- write_reg ( 0x3C, 0xE4, 0xE38F ); // for all-blocks
- break;
- case EMEM_MAIN:
- write_reg ( 0x3C, 0xE4, 0x7731 ); // for main block
- break;
- case EMEM_INFO:
- write_reg ( 0x3C, 0xE4, 0x7731 ); // for info block
-
- write_reg_8bit ( 0x0F, 0xE6, 0x01 );
-
- write_reg_8bit ( 0x3C, 0xE4, 0xC5 );
- write_reg_8bit ( 0x3C, 0xE5, 0x78 );
-
- write_reg_8bit ( 0x1E, 0x04, 0x9F );
- write_reg_8bit ( 0x1E, 0x05, 0x82 );
-
- write_reg_8bit ( 0x0F, 0xE6, 0x00 );
- mdelay ( 100 );
- break;
- }
-
- // polling 0x3CE4 is 0x2F43
- do
- {
- reg_data = read_reg ( 0x3C, 0xE4 );
- }
- while ( reg_data != 0x2F43 );
-
- // calculate CRC 32
- _CRC_initTable ();
-
- for ( i = 0; i < 32; i++ ) // total 32 KB : 2 byte per R/W
- {
- if ( i == 31 )
- {
- temp[i][1014] = 0x5A;
- temp[i][1015] = 0xA5;
-
- for ( j = 0; j < 1016; j++ )
- {
- crc_main = _CRC_getValue ( temp[i][j], crc_main);
- }
- }
- else
- {
- for ( j = 0; j < 1024; j++ )
- {
- crc_main = _CRC_getValue ( temp[i][j], crc_main);
- }
- }
-
- //write_i2c_seq(SLAVE_I2C_ID_DWI2C, temp[i], 1024);
- for (j = 0; j < 8; j++)
- {
- write_i2c_seq(SLAVE_I2C_ID_DWI2C, &temp[i][j*128], 128 );
- }
- msleep (100);
-
- // polling 0x3CE4 is 0xD0BC
- do
- {
- reg_data = read_reg ( 0x3C, 0xE4 );
- }
- while ( reg_data != 0xD0BC );
-
- write_reg ( 0x3C, 0xE4, 0x2F43 );
- }
-
- if ( ( emem_type == EMEM_ALL ) || ( emem_type == EMEM_MAIN ) )
- {
- // write file done and check crc
- write_reg ( 0x3C, 0xE4, 0x1380 );
- }
- mdelay ( 10 );
-
- if ( ( emem_type == EMEM_ALL ) || ( emem_type == EMEM_MAIN ) )
- {
- // polling 0x3CE4 is 0x9432
- do
- {
- reg_data = read_reg ( 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 = read_reg ( 0x3C, 0x80 );
- crc_main_tp = ( crc_main_tp << 16 ) | read_reg ( 0x3C, 0x82 );
-
- // CRC Info from TP
- crc_info_tp = read_reg ( 0x3C, 0xA0 );
- crc_info_tp = ( crc_info_tp << 16 ) | read_reg ( 0x3C, 0xA2 );
- }
-
- 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 )
- {
- DBG( "update_C33 failed\n" );
- reset_hw();
- FwDataCnt = 0;
- return 0;
- }
-
- DBG( "update_C33 OK\n" );
- reset_hw();
- FwDataCnt = 0;
- return size;
-}
-
-#ifdef FIRMWARE_AUTOUPDATE
-unsigned short main_sw_id = 0x7FF, info_sw_id = 0x7FF;
-U32 bin_conf_crc32 = 0;
-
-static U32 _CalMainCRC32(void)
-{
- U32 ret=0;
- U16 reg_data=0;
-
- reset_hw();
-
- dbbusDWIICEnterSerialDebugMode();
- dbbusDWIICStopMCU();
- dbbusDWIICIICUseBus();
- dbbusDWIICIICReshape();
- msleep ( 100 );
-
- //Stop MCU
- write_reg ( 0x0F, 0xE6, 0x0001 );
-
- // Stop Watchdog
- write_reg_8bit ( 0x3C, 0x60, 0x55 );
- write_reg_8bit ( 0x3C, 0x61, 0xAA );
-
- //cmd
- write_reg ( 0x3C, 0xE4, 0xDF4C );
- write_reg ( 0x1E, 0x04, 0x7d60 );
- // TP SW reset
- write_reg ( 0x1E, 0x04, 0x829F );
-
- //MCU run
- write_reg ( 0x0F, 0xE6, 0x0000 );
-
- //polling 0x3CE4
- do
- {
- reg_data = read_reg ( 0x3C, 0xE4 );
- }while ( reg_data != 0x9432 );
-
- // Cal CRC Main from TP
- ret = read_reg ( 0x3C, 0x80 );
- ret = ( ret << 16 ) | read_reg ( 0x3C, 0x82 );
-
- DBG("[21xxA]:Current main crc32=0x%x\n",ret);
- return (ret);
-}
-
-static void _ReadBinConfig ( void )
-{
- U8 dbbus_tx_data[5]={0};
- U8 dbbus_rx_data[4]={0};
- U16 reg_data=0;
-
- reset_hw();
-
- dbbusDWIICEnterSerialDebugMode();
- dbbusDWIICStopMCU();
- dbbusDWIICIICUseBus();
- dbbusDWIICIICReshape();
- msleep ( 100 );
-
- //Stop MCU
- write_reg ( 0x0F, 0xE6, 0x0001 );
-
- // Stop Watchdog
- write_reg_8bit ( 0x3C, 0x60, 0x55 );
- write_reg_8bit ( 0x3C, 0x61, 0xAA );
-
- //cmd
- write_reg ( 0x3C, 0xE4, 0xA4AB );
- write_reg ( 0x1E, 0x04, 0x7d60 );
-
- // TP SW reset
- write_reg ( 0x1E, 0x04, 0x829F );
-
- //MCU run
- write_reg ( 0x0F, 0xE6, 0x0000 );
-
- //polling 0x3CE4
- do
- {
- reg_data = read_reg ( 0x3C, 0xE4 );
- }
- while ( reg_data != 0x5B58 );
-
- dbbus_tx_data[0] = 0x72;
- dbbus_tx_data[1] = 0x7F;
- dbbus_tx_data[2] = 0x55;
- dbbus_tx_data[3] = 0x00;
- dbbus_tx_data[4] = 0x04;
- write_i2c_seq(SLAVE_I2C_ID_DWI2C, &dbbus_tx_data[0], 5 );
- read_i2c_seq(SLAVE_I2C_ID_DWI2C, &dbbus_rx_data[0], 4 );
- if ((dbbus_rx_data[0]>=0x30 && dbbus_rx_data[0]<=0x39)
- &&(dbbus_rx_data[1]>=0x30 && dbbus_rx_data[1]<=0x39)
- &&(dbbus_rx_data[2]>=0x31 && dbbus_rx_data[2]<=0x39))
- {
- main_sw_id = (dbbus_rx_data[0]-0x30)*100+(dbbus_rx_data[1]-0x30)*10+(dbbus_rx_data[2]-0x30);
- }
-
- dbbus_tx_data[0] = 0x72;
- dbbus_tx_data[1] = 0x7F;
- dbbus_tx_data[2] = 0xFC;
- dbbus_tx_data[3] = 0x00;
- dbbus_tx_data[4] = 0x04;
- write_i2c_seq(SLAVE_I2C_ID_DWI2C, &dbbus_tx_data[0], 5 );
- read_i2c_seq(SLAVE_I2C_ID_DWI2C, &dbbus_rx_data[0], 4 );
- bin_conf_crc32 = dbbus_rx_data[0];
- bin_conf_crc32 = (bin_conf_crc32<<8)|dbbus_rx_data[1];
- bin_conf_crc32 = (bin_conf_crc32<<8)|dbbus_rx_data[2];
- bin_conf_crc32 = (bin_conf_crc32<<8)|dbbus_rx_data[3];
-
- dbbus_tx_data[0] = 0x72;
- dbbus_tx_data[1] = 0x83;
- dbbus_tx_data[2] = 0x00;
- dbbus_tx_data[3] = 0x00;
- dbbus_tx_data[4] = 0x04;
- write_i2c_seq(SLAVE_I2C_ID_DWI2C, &dbbus_tx_data[0], 5 );
- read_i2c_seq(SLAVE_I2C_ID_DWI2C, &dbbus_rx_data[0], 4 );
- if ((dbbus_rx_data[0]>=0x30 && dbbus_rx_data[0]<=0x39)
- &&(dbbus_rx_data[1]>=0x30 && dbbus_rx_data[1]<=0x39)
- &&(dbbus_rx_data[2]>=0x31 && dbbus_rx_data[2]<=0x39))
- {
- info_sw_id = (dbbus_rx_data[0]-0x30)*100+(dbbus_rx_data[1]-0x30)*10+(dbbus_rx_data[2]-0x30);
- }
-
- DBG("[21xxA]:main_sw_id = %d, info_sw_id = %d, bin_conf_crc32=0x%x\n", main_sw_id, info_sw_id, bin_conf_crc32);
-}
-
-static int fwAutoUpdate(void *unused)
-{
- int time = 0;
- ssize_t ret = 0;
-
- for (time = 0; time < 5; time++)
- {
- DBG("fwAutoUpdate time = %d\n",time);
- ret = firmware_update_c33(NULL, NULL, NULL, 1, EMEM_MAIN);
- if (ret == 1)
- {
- DBG("AUTO_UPDATE OK!!!");
- break;
- }
- }
- if (time == 5)
- {
- DBG("AUTO_UPDATE failed!!!");
- }
- enable_irq(irq_msg21xx);
- return 0;
-}
-#endif
-
-//------------------------------------------------------------------------------//
-static ssize_t firmware_update_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- DBG("*** firmware_update_show() fw_version = %s ***\n", fw_version);
-
- 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)
-{
- bFwUpdating = 1;
- disable_irq(irq_msg21xx);
-
- DBG("*** update fw size = %d ***\n", FwDataCnt);
- size = firmware_update_c33 (dev, attr, buf, size, EMEM_MAIN);
-
- enable_irq(irq_msg21xx);
- bFwUpdating = 0;
-
- return size;
-}
-
-static DEVICE_ATTR(update, SYSFS_AUTHORITY, firmware_update_show, firmware_update_store);
-
-static ssize_t firmware_version_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- DBG("*** 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)
-{
- get_customer_firmware_version();
-
- DBG("*** firmware_version_store() fw_version = %s ***\n", fw_version);
-
- return size;
-}
-
-static DEVICE_ATTR(version, SYSFS_AUTHORITY, firmware_version_show, firmware_version_store);
-
-static ssize_t firmware_data_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- DBG("*** firmware_data_show() FwDataCnt = %d ***\n", FwDataCnt);
-
- return FwDataCnt;
-}
-
-static ssize_t firmware_data_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t size)
-{
- int count = size / 1024;
- int i;
-
- for (i = 0; i < count; i ++)
- {
- memcpy(temp[FwDataCnt], buf+(i*1024), 1024);
-
- FwDataCnt ++;
- }
-
- DBG("***FwDataCnt = %d ***\n", FwDataCnt);
-
- if (buf != NULL)
- {
- DBG("*** buf[0] = %c ***\n", buf[0]);
- }
-
- return size;
-}
-
-static DEVICE_ATTR(data, SYSFS_AUTHORITY, firmware_data_show, firmware_data_store);
-
-#ifdef TP_PRINT
-static ssize_t tp_print_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- tp_print_proc_read();
-
- return sprintf(buf, "%d\n", bTpInSuspend);
-}
-
-static ssize_t tp_print_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t size)
-{
- DBG("*** tp_print_store() ***\n");
-
- return size;
-}
-
-static DEVICE_ATTR(tpp, SYSFS_AUTHORITY, tp_print_show, tp_print_store);
-#endif
-
-//------------------------------------------------------------------------------//
-#ifdef CONFIG_TOUCHSCREEN_PROXIMITY_SENSOR
-static void _msg_enable_proximity(void)
-{
- U8 tx_data[4] = {0};
-
- DBG("_msg_enable_proximity!");
- tx_data[0] = 0x52;
- tx_data[1] = 0x00;
- tx_data[2] = 0x47;
- tx_data[3] = 0xa0;
- mutex_lock(&msg21xx_mutex);
- write_i2c_seq(SLAVE_I2C_ID_DWI2C, &tx_data[0], 4);
- mutex_unlock(&msg21xx_mutex);
-
- bEnableTpProximity = 1;
-}
-
-static void _msg_disable_proximity(void)
-{
- U8 tx_data[4] = {0};
-
- DBG("_msg_disable_proximity!");
- tx_data[0] = 0x52;
- tx_data[1] = 0x00;
- tx_data[2] = 0x47;
- tx_data[3] = 0xa1;
- mutex_lock(&msg21xx_mutex);
- write_i2c_seq(SLAVE_I2C_ID_DWI2C, &tx_data[0], 4);
- mutex_unlock(&msg21xx_mutex);
-
- bEnableTpProximity = 0;
- bFaceClosingTp = 0;
-}
-
-void tsps_msg21xx_enable(int en)
-{
- if (en)
- {
- _msg_enable_proximity();
- }
- else
- {
- _msg_disable_proximity();
- }
-}
-
-int tsps_msg21xx_data(void)
-{
- return bFaceClosingTp;
-}
-#endif
-
-static U8 calculate_checksum(U8 *msg, S32 length)
-{
- S32 Checksum = 0;
- S32 i;
-
- for (i = 0; i < length; i ++)
- {
- Checksum += msg[i];
- }
-
- return (U8)((-Checksum) & 0xFF);
-}
-
-static S32 parse_info(touchInfo_t *info)
-{
- U8 data[DEMO_MODE_PACKET_LENGTH] = {0};
- U8 checksum = 0;
- U32 x = 0, y = 0;
- U32 x2 = 0, y2 = 0;
- U32 delta_x = 0, delta_y = 0;
-
- mutex_lock(&msg21xx_mutex);
- read_i2c_seq(SLAVE_I2C_ID_DWI2C, &data[0], DEMO_MODE_PACKET_LENGTH);
- mutex_unlock(&msg21xx_mutex);
- checksum = calculate_checksum(&data[0], (DEMO_MODE_PACKET_LENGTH-1));
- DBG("check sum: [%x] == [%x]? \n", data[DEMO_MODE_PACKET_LENGTH-1], checksum);
-
- if(data[DEMO_MODE_PACKET_LENGTH-1] != checksum)
- {
- DBG("WRONG CHECKSUM\n");
- return -1;
- }
-
- if(data[0] != 0x52)
- {
- DBG("WRONG HEADER\n");
- return -1;
- }
-
- info->keycode = 0xFF;
- if ((data[1] == 0xFF) && (data[2] == 0xFF) && (data[3] == 0xFF) && (data[4] == 0xFF) && (data[6] == 0xFF))
- {
- if ((data[5] == 0xFF) || (data[5] == 0))
- {
- info->keycode = 0xFF;
- }
- else if ((data[5] == 1) || (data[5] == 2) || (data[5] == 4) || (data[5] == 8))
- {
- if (data[5] == 1)
- {
- info->keycode = 0;
- }
- else if (data[5] == 2)
- {
- info->keycode = 1;
- }
- else if (data[5] == 4)
- {
- info->keycode = 2;
- }
- else if (data[5] == 8)
- {
- info->keycode = 3;
- }
- }
- #ifdef CONFIG_TOUCHSCREEN_PROXIMITY_SENSOR
- else if (bEnableTpProximity &&((data[5] == 0x80) || (data[5] == 0x40)))
- {
- if (data[5] == 0x80)
- {
- bFaceClosingTp = 1;
- }
- else if (data[5] == 0x40)
- {
- bFaceClosingTp = 0;
- }
- DBG("bEnableTpProximity=%d; bFaceClosingTp=%d; data[5]=%x;\n", bEnableTpProximity, bFaceClosingTp, data[5]);
- return -1;
- }
- #endif
- else
- {
- DBG("WRONG KEY\n");
- return -1;
- }
- }
- else
- {
- x = (((data[1] & 0xF0 ) << 4) | data[2]);
- y = ((( data[1] & 0x0F) << 8) | data[3]);
- delta_x = (((data[4] & 0xF0) << 4 ) | data[5]);
- delta_y = (((data[4] & 0x0F) << 8 ) | data[6]);
-
- if ((delta_x == 0) && (delta_y == 0))
- {
- info->point[0].x = x * TOUCH_SCREEN_X_MAX / TPD_WIDTH;
- info->point[0].y = y * TOUCH_SCREEN_Y_MAX/ TPD_HEIGHT;
- info->count = 1;
- }
- else
- {
- if (delta_x > 2048)
- {
- delta_x -= 4096;
- }
- if (delta_y > 2048)
- {
- delta_y -= 4096;
- }
- x2 = (U32)((S16)x + (S16)delta_x);
- y2 = (U32)((S16)y + (S16)delta_y);
- info->point[0].x = x * TOUCH_SCREEN_X_MAX / TPD_WIDTH;
- info->point[0].y = y * TOUCH_SCREEN_Y_MAX/ TPD_HEIGHT;
- info->point[1].x = x2 * TOUCH_SCREEN_X_MAX / TPD_WIDTH;
- info->point[1].y = y2 * TOUCH_SCREEN_Y_MAX/ TPD_HEIGHT;
- info->count = 2;
- }
- }
-
- return 0;
-}
-
-static void touch_driver_touch_pressed(int x, int y)
-{
- DBG("point touch pressed");
-
- input_report_key(input_dev, BTN_TOUCH, 1);
- input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR, 1);
- input_report_abs(input_dev, ABS_MT_POSITION_X, x);
- input_report_abs(input_dev, ABS_MT_POSITION_Y, y);
- input_mt_sync(input_dev);
-}
-
-static void touch_driver_touch_released(void)
-{
- DBG("point touch released");
-
- input_report_key(input_dev, BTN_TOUCH, 0);
- input_mt_sync(input_dev);
-}
-
-/* read data through I2C then report data to input sub-system when interrupt occurred */
-void touch_driver_do_work(struct work_struct *work)
-{
- touchInfo_t info;
- int i = 0;
- static int last_keycode = 0xFF;
- static int last_count = 0;
-
- DBG("touch_driver_do_work()\n");
-
- memset(&info, 0x0, sizeof(info));
- if (0 == parse_info(&info))
- {
- #ifdef CONFIG_TP_HAVE_KEY
- if (info.keycode != 0xFF) //key touch pressed
- {
- DBG("touch_driver_do_work() info.keycode=%x, last_keycode=%x, tp_key_array[%d]=%d\n", info.keycode, last_keycode, info.keycode, tp_key_array[info.keycode]);
- if (info.keycode < MAX_KEY_NUM)
- {
- if (info.keycode != last_keycode)
- {
- DBG("key touch pressed");
-
- input_report_key(input_dev, BTN_TOUCH, 1);
- input_report_key(input_dev, tp_key_array[info.keycode], 1);
-
- last_keycode = info.keycode;
- }
- else
- {
- /// pass duplicate key-pressing
- DBG("REPEATED KEY\n");
- }
- }
- else
- {
- DBG("WRONG KEY\n");
- }
- }
- else //key touch released
- {
- if (last_keycode != 0xFF)
- {
- DBG("key touch released");
-
- input_report_key(input_dev, BTN_TOUCH, 0);
- input_report_key(input_dev, tp_key_array[last_keycode], 0);
-
- last_keycode = 0xFF;
- }
- }
- #endif //CONFIG_TP_HAVE_KEY
-
- if (info.count > 0) //point touch pressed
- {
- for (i = 0; i < info.count; i ++)
- {
- touch_driver_touch_pressed(info.point[i].x, info.point[i].y);
- }
- last_count = info.count;
- }
- else if (last_count > 0) //point touch released
- {
- touch_driver_touch_released();
- last_count = 0;
- }
-
- input_sync(input_dev);
- }
-
- enable_irq(irq_msg21xx);
-}
-
-/* The interrupt service routine will be triggered when interrupt occurred */
-irqreturn_t touch_driver_isr(int irq, void *dev_id)
-{
- DBG("touch_driver_isr()\n");
-
- disable_irq_nosync(irq_msg21xx);
- schedule_work(&msg21xx_wk);
-
- return IRQ_HANDLED;
-}
-
-#if defined(CONFIG_FB)
-static int fb_notifier_callback(struct notifier_block *self, unsigned long event, void *data)
-{
- struct fb_event *evdata = data;
- int *blank;
-
- if (evdata && evdata->data && event == FB_EVENT_BLANK )
- {
- blank = evdata->data;
- if (*blank == FB_BLANK_UNBLANK)
- {
- if (bTpInSuspend)
- {
- gpio_direction_output(MS_TS_MSG21XX_GPIO_RST, 1);
- mdelay(10);
- gpio_set_value(MS_TS_MSG21XX_GPIO_RST, 0);
- mdelay(10);
- gpio_set_value(MS_TS_MSG21XX_GPIO_RST, 1);
- mdelay(200);
-
- touch_driver_touch_released();
- input_sync(input_dev);
-
- enable_irq(irq_msg21xx);
- }
- bTpInSuspend = 0;
- }
- else if (*blank == FB_BLANK_POWERDOWN)
- {
- if (bFwUpdating)
- {
- DBG("suspend bFwUpdating=%d\n", bFwUpdating);
- return 0;
- }
-
- #ifdef CONFIG_TOUCHSCREEN_PROXIMITY_SENSOR
- if (bEnableTpProximity)
- {
- DBG("suspend bEnableTpProximity=%d\n", bEnableTpProximity);
- return 0;
- }
- #endif
-
- if (bTpInSuspend == 0)
- {
- disable_irq(irq_msg21xx);
- gpio_set_value(MS_TS_MSG21XX_GPIO_RST, 0);
- }
- bTpInSuspend = 1;
- }
- }
-
- return 0;
-}
-#endif
-
-#ifdef CONFIG_HAS_EARLYSUSPEND
-void touch_driver_early_suspend(struct early_suspend *p)
-{
- DBG("touch_driver_early_suspend()\n");
-
- if (bFwUpdating)
- {
- DBG("suspend bFwUpdating=%d\n", bFwUpdating);
- return;
- }
-
-#ifdef CONFIG_TOUCHSCREEN_PROXIMITY_SENSOR
- if (bEnableTpProximity)
- {
- DBG("suspend bEnableTpProximity=%d\n", bEnableTpProximity);
- return;
- }
-#endif
-
- if (bTpInSuspend == 0)
- {
- disable_irq(irq_msg21xx);
- gpio_set_value(MS_TS_MSG21XX_GPIO_RST, 0);
- }
- bTpInSuspend = 1;
-}
-
-void touch_driver_early_resume(struct early_suspend *p)
-{
- DBG("touch_driver_early_resume() bTpInSuspend=%d\n", bTpInSuspend);
-
- if (bTpInSuspend)
- {
- gpio_direction_output(MS_TS_MSG21XX_GPIO_RST, 1);
- mdelay(10);
- gpio_set_value(MS_TS_MSG21XX_GPIO_RST, 0);
- mdelay(10);
- gpio_set_value(MS_TS_MSG21XX_GPIO_RST, 1);
- mdelay(200);
-
- touch_driver_touch_released();
- input_sync(input_dev);
-
- enable_irq(irq_msg21xx);
- }
- bTpInSuspend = 0;
-}
-#endif
-
-/* probe function is used for matching and initializing input device */
-static int touch_driver_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
-{
-#ifdef FIRMWARE_AUTOUPDATE
- unsigned short update_bin_major = 0, update_bin_minor = 0;
- int i, update_flag = 0;
-#endif
- int ret = 0;
-
- if (input_dev != NULL)
- {
- DBG("input device has found\n");
- return -1;
- }
-
- DBG("*** %s ***\n", __FUNCTION__);
-
- i2c_client = client;
-
- ret = gpio_request(MS_TS_MSG21XX_GPIO_RST, "reset");
- if (ret < 0)
- {
- pr_err("*** Failed to request GPIO %d, error %d ***\n", MS_TS_MSG21XX_GPIO_RST, ret);
- goto err0;
- }
-
- // power on TP
- gpio_direction_output(MS_TS_MSG21XX_GPIO_RST, 1);
- mdelay(100);
- gpio_set_value(MS_TS_MSG21XX_GPIO_RST, 0);
- mdelay(10);
- gpio_set_value(MS_TS_MSG21XX_GPIO_RST, 1);
- mdelay(200);
- if (0 == get_ic_type())
- {
- pr_err("the currnet ic is not Mstar\n");
- ret = -1;
- goto err0;
- }
-
- mutex_init(&msg21xx_mutex);
-
- /* allocate an input device */
- input_dev = input_allocate_device();
- if (!input_dev)
- {
- ret = -ENOMEM;
- pr_err("*** input device allocation failed ***\n");
- goto err1;
- }
-
- input_dev->name = client->name;
- input_dev->phys = "I2C";
- input_dev->dev.parent = &client->dev;
- input_dev->id.bustype = BUS_I2C;
-
- /* set the supported event type for input device */
- set_bit(EV_ABS, input_dev->evbit);
- set_bit(EV_SYN, input_dev->evbit);
- set_bit(EV_KEY, input_dev->evbit);
- set_bit(BTN_TOUCH, input_dev->keybit);
- set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
-
-#ifdef CONFIG_TP_HAVE_KEY
- {
- int i;
- for (i = 0; i < MAX_KEY_NUM; i ++)
- {
- input_set_capability(input_dev, EV_KEY, tp_key_array[i]);
- }
- }
-#endif
-
- input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, 2, 0, 0);
- input_set_abs_params(input_dev, ABS_MT_POSITION_X, TOUCH_SCREEN_X_MIN, TOUCH_SCREEN_X_MAX, 0, 0);
- input_set_abs_params(input_dev, ABS_MT_POSITION_Y, TOUCH_SCREEN_Y_MIN, TOUCH_SCREEN_Y_MAX, 0, 0);
-
- /* register the input device to input sub-system */
- ret = input_register_device(input_dev);
- if (ret < 0)
- {
- pr_err("*** Unable to register ms-touchscreen input device ***\n");
- goto err1;
- }
-
- /* set sysfs for firmware */
- firmware_class = class_create(THIS_MODULE, "ms-touchscreen-msg20xx"); //client->name
- 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);
-
-#ifdef TP_PRINT
- tp_print_create_entry();
-#endif
-
- dev_set_drvdata(firmware_cmd_dev, NULL);
-
- /* initialize the work queue */
- INIT_WORK(&msg21xx_wk, touch_driver_do_work);
-
- ret = gpio_request(MS_TS_MSG21XX_GPIO_INT, "interrupt");
- if (ret < 0)
- {
- pr_err("*** Failed to request GPIO %d, error %d ***\n", MS_TS_MSG21XX_GPIO_INT, ret);
- goto err2;
- }
- gpio_direction_input(MS_TS_MSG21XX_GPIO_INT);
- gpio_set_value(MS_TS_MSG21XX_GPIO_INT, 1);
-
- irq_msg21xx = gpio_to_irq(MS_TS_MSG21XX_GPIO_INT);
-
- /* request an irq and register the isr */
- ret = request_irq(irq_msg21xx, touch_driver_isr, IRQF_TRIGGER_RISING, "msg21xx", NULL);
- if (ret != 0)
- {
- pr_err("*** Unable to claim irq %d; error %d ***\n", MS_TS_MSG21XX_GPIO_INT, ret);
- goto err3;
- }
-
- disable_irq(irq_msg21xx);
-
-#if defined(CONFIG_FB)
- msg21xx_fb_notif.notifier_call = fb_notifier_callback;
- ret = fb_register_client(&msg21xx_fb_notif);
-#elif defined (CONFIG_HAS_EARLYSUSPEND)
- mstar_ts_early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN;
- mstar_ts_early_suspend.suspend = touch_driver_early_suspend;
- mstar_ts_early_suspend.resume = touch_driver_early_resume;
- register_early_suspend(&mstar_ts_early_suspend);
-#endif
-
-#ifdef CONFIG_TOUCHSCREEN_PROXIMITY_SENSOR
- tsps_assist_register_callback("msg21xx", &tsps_msg21xx_enable, &tsps_msg21xx_data);
-#endif
-
-#ifdef FIRMWARE_AUTOUPDATE
- get_customer_firmware_version();
- _ReadBinConfig();
-
- if (main_sw_id == info_sw_id)
- {
- if (_CalMainCRC32() == bin_conf_crc32)
- {
- if ((main_sw_id >= SWID_START) && (main_sw_id < SWID_NULL))
- {
- update_bin_major= (MSG_FIRMWARE[main_sw_id-SWID_START][0x7f4f] << 8) + MSG_FIRMWARE[main_sw_id-SWID_START][0x7f4e];
- update_bin_minor= (MSG_FIRMWARE[main_sw_id-SWID_START][0x7f51] << 8) + MSG_FIRMWARE[main_sw_id-SWID_START][0x7f50];
-
- //check upgrading
- if ((update_bin_major == fw_version_major) && (update_bin_minor > fw_version_minor))
- {
- update_flag = 1;
- }
- }
- DBG("MAIN sw_id=%d,update_flag=%d,update_bin_major=%d,update_bin_minor=%d\n",main_sw_id,update_flag,update_bin_major,update_bin_minor);
- }
- else
- {
- if ((info_sw_id >= SWID_START) && (info_sw_id < SWID_NULL))
- {
- update_bin_major= (MSG_FIRMWARE[info_sw_id-SWID_START][0x7f4f] << 8) + MSG_FIRMWARE[info_sw_id-SWID_START][0x7f4e];
- update_bin_minor= (MSG_FIRMWARE[info_sw_id-SWID_START][0x7f51] << 8) + MSG_FIRMWARE[info_sw_id-SWID_START][0x7f50];
- update_flag = 1;
- }
- DBG("INFO1 sw_id=%d,update_flag=%d,update_bin_major=%d,update_bin_minor=%d\n",info_sw_id,update_flag,update_bin_major,update_bin_minor);
- }
- }
- else
- {
- if ((info_sw_id >= SWID_START) && (info_sw_id < SWID_NULL))
- {
- update_bin_major= (MSG_FIRMWARE[info_sw_id-SWID_START][0x7f4f] << 8) + MSG_FIRMWARE[info_sw_id-SWID_START][0x7f4e];
- update_bin_minor= (MSG_FIRMWARE[info_sw_id-SWID_START][0x7f51] << 8) + MSG_FIRMWARE[info_sw_id-SWID_START][0x7f50];
- update_flag = 1;
- }
- DBG("INFO2 sw_id=%d,update_flag=%d,update_bin_major=%d,update_bin_minor=%d\n",info_sw_id,update_flag,update_bin_major,update_bin_minor);
- }
-
- if (update_flag == 1)
- {
- DBG("MSG21XX_fw_auto_update begin....\n");
- //transfer data
- for (i = 0; i < 33; i++)
- {
- firmware_data_store(NULL, NULL, &(MSG_FIRMWARE[info_sw_id-SWID_START][i*1024]), 1024);
- }
-
- kthread_run(fwAutoUpdate, 0, "MSG21XX_fw_auto_update");
- DBG("*** mstar touch screen registered ***\n");
- return 0;
- }
-
- reset_hw();
-#endif
-
- DBG("*** mstar touch screen registered ***\n");
- enable_irq(irq_msg21xx);
- return 0;
-
-err3:
- free_irq(irq_msg21xx, input_dev);
-
-err2:
- gpio_free(MS_TS_MSG21XX_GPIO_INT);
-
-err1:
- mutex_destroy(&msg21xx_mutex);
- input_unregister_device(input_dev);
- input_free_device(input_dev);
- input_dev = NULL;
-
-err0:
- gpio_free(MS_TS_MSG21XX_GPIO_RST);
-
- return ret;
-}
-
-/* remove function is triggered when the input device is removed from input sub-system */
-static int touch_driver_remove(struct i2c_client *client)
-{
- DBG("touch_driver_remove()\n");
-
- free_irq(irq_msg21xx, input_dev);
- gpio_free(MS_TS_MSG21XX_GPIO_INT);
- gpio_free(MS_TS_MSG21XX_GPIO_RST);
- input_unregister_device(input_dev);
- mutex_destroy(&msg21xx_mutex);
-
- return 0;
-}
-
-/* The I2C device list is used for matching I2C device and I2C device driver. */
-static const struct i2c_device_id touch_device_id[] =
-{
- {"msg21xx", 0},
- {}, /* should not omitted */
-};
-
-MODULE_DEVICE_TABLE(i2c, touch_device_id);
-
-static struct i2c_driver touch_device_driver =
-{
- .driver = {
- .name = "msg21xx",
- .owner = THIS_MODULE,
- },
- .probe = touch_driver_probe,
- .remove = touch_driver_remove,
- .id_table = touch_device_id,
-};
-
-static int __init touch_driver_init(void)
-{
- int ret;
-
- /* register driver */
- ret = i2c_add_driver(&touch_device_driver);
- if (ret < 0)
- {
- DBG("add touch_device_driver i2c driver failed.\n");
- return -ENODEV;
- }
- DBG("add touch_device_driver i2c driver.\n");
-
- return ret;
-}
-
-static void __exit touch_driver_exit(void)
-{
- DBG("remove touch_device_driver i2c driver.\n");
-
- i2c_del_driver(&touch_device_driver);
-}
-
-#ifdef TP_PRINT
-#include <linux/proc_fs.h>
-
-static U16 InfoAddr = 0x0F, PoolAddr = 0x10, TransLen = 256;
-static U8 row, units, cnt;
-
-static int tp_print_proc_read(void)
-{
- U16 i, j;
- U16 left, offset = 0;
- U8 dbbus_tx_data[3] = {0};
- U8 u8Data;
- S16 s16Data;
- S32 s32Data;
- char *buf = NULL;
-
- left = cnt*row*units;
- if ((bTpInSuspend == 0) && (InfoAddr != 0x0F) && (PoolAddr != 0x10) && (left > 0))
- {
- buf = kmalloc(left, GFP_KERNEL);
- if (buf != NULL)
- {
- printk("tpp: \n");
-
- while (left > 0)
- {
- dbbus_tx_data[0] = 0x53;
- dbbus_tx_data[1] = ((PoolAddr + offset) >> 8) & 0xFF;
- dbbus_tx_data[2] = (PoolAddr + offset) & 0xFF;
- mutex_lock(&msg21xx_mutex);
- write_i2c_seq(SLAVE_I2C_ID_DWI2C, &dbbus_tx_data[0], 3);
- read_i2c_seq(SLAVE_I2C_ID_DWI2C, &buf[offset], left > TransLen ? TransLen : left);
- mutex_unlock(&msg21xx_mutex);
-
- if (left > TransLen)
- {
- left -= TransLen;
- offset += TransLen;
- }
- else
- {
- left = 0;
- }
- }
-
- for (i = 0; i < cnt; i++)
- {
- printk("tpp: ");
- for (j = 0; j < row; j++)
- {
- if (units == 1)
- {
- u8Data = buf[i*row*units + j*units];
- printk("%d\t", u8Data);
- }
- else if (units == 2)
- {
- s16Data = buf[i*row*units + j*units] + (buf[i*row*units + j*units + 1] << 8);
- printk("%d\t", s16Data);
- }
- else if (units == 4)
- {
- s32Data = buf[i*row*units + j*units] + (buf[i*row*units + j*units + 1] << 8) + (buf[i*row*units + j*units + 2] << 16) + (buf[i*row*units + j*units + 3] << 24);
- printk("%d\t", s32Data);
- }
- }
- printk("\n");
- }
-
- kfree(buf);
- }
- }
-
- return 0;
-}
-
-static void tp_print_create_entry(void)
-{
- U8 dbbus_tx_data[3] = {0};
- U8 dbbus_rx_data[8] = {0};
-
- dbbus_tx_data[0] = 0x53;
- dbbus_tx_data[1] = 0x00;
- dbbus_tx_data[2] = 0x58;
- mutex_lock(&msg21xx_mutex);
- write_i2c_seq(SLAVE_I2C_ID_DWI2C, &dbbus_tx_data[0], 3);
- read_i2c_seq(SLAVE_I2C_ID_DWI2C, &dbbus_rx_data[0], 4);
- mutex_unlock(&msg21xx_mutex);
- InfoAddr = (dbbus_rx_data[1]<<8) + dbbus_rx_data[0];
- PoolAddr = (dbbus_rx_data[3]<<8) + dbbus_rx_data[2];
- printk("InfoAddr=0x%X\n", InfoAddr);
- printk("PoolAddr=0x%X\n", PoolAddr);
-
- if ((InfoAddr != 0x0F) && (PoolAddr != 0x10))
- {
- msleep(10);
- dbbus_tx_data[0] = 0x53;
- dbbus_tx_data[1] = (InfoAddr >> 8) & 0xFF;
- dbbus_tx_data[2] = InfoAddr & 0xFF;
- mutex_lock(&msg21xx_mutex);
- write_i2c_seq(SLAVE_I2C_ID_DWI2C, &dbbus_tx_data[0], 3);
- read_i2c_seq(SLAVE_I2C_ID_DWI2C, &dbbus_rx_data[0], 8);
- mutex_unlock(&msg21xx_mutex);
-
- units = dbbus_rx_data[0];
- row = dbbus_rx_data[1];
- cnt = dbbus_rx_data[2];
- TransLen = (dbbus_rx_data[7]<<8) + dbbus_rx_data[6];
- printk("tpp: row=%d, units=%d\n", row, units);
- printk("tpp: cnt=%d, TransLen=%d\n", cnt, TransLen);
-
- // tpp
- if (device_create_file(firmware_cmd_dev, &dev_attr_tpp) < 0)
- {
- pr_err("Failed to create device file(%s)!\n", dev_attr_tpp.attr.name);
- }
- }
-}
-#endif
-
-module_init(touch_driver_init);
-module_exit(touch_driver_exit);
-MODULE_AUTHOR("MStar Semiconductor, Inc.");
-MODULE_LICENSE("GPL v2");
-
diff --git a/kernel/drivers/input/touchscreen/synaptics_fw_update.c b/kernel/drivers/input/touchscreen/synaptics_fw_update.c
index 4867d1f73c4d..8b6d7c7e368d 100644
--- a/kernel/drivers/input/touchscreen/synaptics_fw_update.c
+++ b/kernel/drivers/input/touchscreen/synaptics_fw_update.c
@@ -30,7 +30,10 @@
#define DEBUG_FW_UPDATE
#define SHOW_PROGRESS
-#define FW_IMAGE_NAME "PR12345678.img"
+#define FW_IMAGE_NAME "PR1063486-s7301_00000000.img"
+#define MAX_FIRMWARE_ID_LEN 10
+#define FORCE_UPDATE false
+#define INSIDE_FIRMWARE_UPDATE
#define CHECKSUM_OFFSET 0x00
#define BOOTLOADER_VERSION_OFFSET 0x07
@@ -73,6 +76,12 @@ enum flash_command {
CMD_ENABLE_FLASH_PROG = 0xF,
};
+enum flash_area {
+ NONE,
+ UI_FIRMWARE,
+ CONFIG_AREA
+};
+
#define SLEEP_MODE_NORMAL (0x00)
#define SLEEP_MODE_SENSOR_SLEEP (0x01)
#define SLEEP_MODE_RESERVED0 (0x02)
@@ -81,9 +90,9 @@ enum flash_command {
#define ENABLE_WAIT_MS (1 * 1000)
#define WRITE_WAIT_MS (3 * 1000)
#define ERASE_WAIT_MS (5 * 1000)
+#define RESET_WAIT_MS (500)
-#define MIN_SLEEP_TIME_US 50
-#define MAX_SLEEP_TIME_US 100
+#define SLEEP_TIME_US 50
static ssize_t fwu_sysfs_show_image(struct file *data_file,
struct kobject *kobj, struct bin_attribute *attributes,
@@ -204,6 +213,7 @@ struct f34_flash_properties {
struct synaptics_rmi4_fwu_handle {
bool initialized;
+ bool force_update;
char product_id[SYNAPTICS_RMI4_PRODUCT_ID_SIZE + 1];
unsigned int image_size;
unsigned int data_pos;
@@ -231,6 +241,8 @@ struct synaptics_rmi4_fwu_handle {
struct synaptics_rmi4_data *rmi4_data;
struct f34_flash_control flash_control;
struct f34_flash_properties flash_properties;
+ struct workqueue_struct *fwu_workqueue;
+ struct delayed_work fwu_work;
};
static struct bin_attribute dev_attr_data = {
@@ -313,53 +325,6 @@ static void parse_header(struct image_header *header,
return;
}
-static int fwu_check_version(void)
-{
- int retval;
- unsigned char firmware_id[4];
- unsigned char config_id[4];
- struct i2c_client *i2c_client = fwu->rmi4_data->i2c_client;
-
- /* device firmware id */
- retval = fwu->fn_ptr->read(fwu->rmi4_data,
- fwu->f01_fd.query_base_addr + 18,
- firmware_id,
- sizeof(firmware_id));
- if (retval < 0) {
- dev_err(&i2c_client->dev,
- "Failed to read firmware ID (code %d).\n", retval);
- return retval;
- }
- firmware_id[3] = 0;
-
- dev_info(&i2c_client->dev, "Device firmware ID%d\n",
- extract_uint(firmware_id));
-
- /* device config id */
- retval = fwu->fn_ptr->read(fwu->rmi4_data,
- fwu->f34_fd.ctrl_base_addr,
- config_id,
- sizeof(config_id));
- if (retval < 0) {
- dev_err(&i2c_client->dev,
- "Failed to read config ID (code %d).\n", retval);
- return retval;
- }
-
- dev_info(&i2c_client->dev,
- "Device config ID 0x%02X, 0x%02X, 0x%02X, 0x%02X\n",
- config_id[0], config_id[1], config_id[2], config_id[3]);
-
- /* .img config id */
- dev_info(&i2c_client->dev,
- ".img config ID 0x%02X, 0x%02X, 0x%02X, 0x%02X\n",
- fwu->config_data[0],
- fwu->config_data[1],
- fwu->config_data[2],
- fwu->config_data[3]);
- return 0;
-}
-
static int fwu_read_f01_device_status(struct f01_device_status *status)
{
int retval;
@@ -407,7 +372,7 @@ static int fwu_read_f34_queries(void)
return retval;
}
- dev_info(&i2c_client->dev, "%s perm:%d, bl%d, display:%d\n",
+ dev_info(&i2c_client->dev, "%s perm:%d, bl:%d, display:%d\n",
__func__,
fwu->flash_properties.has_perm_config,
fwu->flash_properties.has_bl_config,
@@ -506,25 +471,13 @@ static int fwu_read_f34_flash_status(void)
static int fwu_reset_device(void)
{
int retval;
- unsigned char reset = 0x01;
#ifdef DEBUG_FW_UPDATE
- dev_info(&fwu->rmi4_data->i2c_client->dev, "Reset device\n");
+ dev_info(&fwu->rmi4_data->i2c_client->dev,
+ "%s: Reset device\n",
+ __func__);
#endif
- retval = fwu->fn_ptr->write(fwu->rmi4_data,
- fwu->f01_fd.cmd_base_addr,
- &reset,
- sizeof(reset));
- if (retval < 0) {
- dev_err(&fwu->rmi4_data->i2c_client->dev,
- "%s: Failed to reset device (addr : 0x%02x)\n",
- __func__, fwu->f01_fd.cmd_base_addr);
- return retval;
- }
-
- fwu_wait_for_idle(WRITE_WAIT_MS);
-
retval = fwu->rmi4_data->reset_device(fwu->rmi4_data);
if (retval < 0) {
dev_err(&fwu->rmi4_data->i2c_client->dev,
@@ -539,37 +492,34 @@ static int fwu_write_f34_command(unsigned char cmd)
{
int retval;
+ fwu->flash_control.data[0] = cmd;
retval = fwu->fn_ptr->write(fwu->rmi4_data,
fwu->addr_f34_flash_control,
- &cmd,
- sizeof(cmd));
+ fwu->flash_control.data,
+ sizeof(fwu->flash_control.data));
if (retval < 0) {
dev_err(&fwu->rmi4_data->i2c_client->dev,
"%s: Failed to write command 0x%02x\n",
- __func__, cmd);
+ __func__, fwu->flash_control.data[0]);
return retval;
}
return 0;
}
-static unsigned char fwu_check_flash_status(void)
-{
- fwu_read_f34_flash_status();
- return fwu->flash_control.status;
-}
-
static int fwu_wait_for_idle(int timeout_ms)
{
int count = 0;
- int timeout_count = ((timeout_ms * 1000) / MAX_SLEEP_TIME_US) + 1;
-
+ int timeout_count = ((timeout_ms * 1000) / SLEEP_TIME_US) + 1;
do {
- if (fwu_read_interrupt_status() > 0)
+ if (fwu->flash_control.command == 0x00)
return 0;
- usleep_range(MIN_SLEEP_TIME_US, MAX_SLEEP_TIME_US);
- count++;
- } while (count < timeout_count);
+ usleep_range(SLEEP_TIME_US, SLEEP_TIME_US + 100);
+ } while (count++ < timeout_count);
+
+ fwu_read_f34_flash_status();
+ if (fwu->flash_control.command == 0x00)
+ return 0;
dev_err(&fwu->rmi4_data->i2c_client->dev,
"%s: Timed out waiting for idle status\n",
@@ -578,6 +528,133 @@ static int fwu_wait_for_idle(int timeout_ms)
return -ETIMEDOUT;
}
+static enum flash_area fwu_go_nogo(void)
+{
+ int retval = 0;
+ int index = 0;
+ int deviceFirmwareID;
+ int imageConfigID;
+ int deviceConfigID;
+ unsigned long imageFirmwareID;
+ unsigned char firmware_id[4];
+ unsigned char config_id[4];
+ char *strptr;
+ char *imagePR = kzalloc(sizeof(MAX_FIRMWARE_ID_LEN), GFP_KERNEL);
+ enum flash_area flash_area = NONE;
+ struct i2c_client *i2c_client = fwu->rmi4_data->i2c_client;
+ struct f01_device_status f01_device_status;
+
+ if (fwu->force_update) {
+ flash_area = UI_FIRMWARE;
+ goto exit;
+ }
+
+ retval = fwu_read_f01_device_status(&f01_device_status);
+ if (retval < 0) {
+ flash_area = NONE;
+ goto exit;
+ }
+
+ imagePR = kzalloc(sizeof(MAX_FIRMWARE_ID_LEN), GFP_KERNEL);
+
+ /* Force update firmware when device is in bootloader mode */
+ if (f01_device_status.flash_prog) {
+ dev_info(&i2c_client->dev,
+ "%s: In flash prog mode\n",
+ __func__);
+ flash_area = UI_FIRMWARE;
+ goto exit;
+ }
+
+
+ /* device firmware id */
+ retval = fwu->fn_ptr->read(fwu->rmi4_data,
+ fwu->f01_fd.query_base_addr + 18,
+ firmware_id,
+ sizeof(firmware_id));
+ if (retval < 0) {
+ dev_err(&i2c_client->dev,
+ "Failed to read firmware ID (code %d).\n", retval);
+ goto exit;
+ }
+ firmware_id[3] = 0;
+ deviceFirmwareID = extract_uint(firmware_id);
+
+ /* .img firmware id */
+ strptr = strstr(FW_IMAGE_NAME, "PR");
+ if (!strptr) {
+ dev_err(&i2c_client->dev,
+ "No valid PR number (PRxxxxxxx)" \
+ "found in image file name...\n");
+ goto exit;
+ }
+
+ strptr += 2;
+ while (strptr[index] >= '0' && strptr[index] <= '9') {
+ imagePR[index] = strptr[index];
+ index++;
+ }
+ imagePR[index] = 0;
+
+ retval = sstrtoul(imagePR, 10, &imageFirmwareID);
+ if (retval == -EINVAL) {
+ dev_err(&i2c_client->dev,
+ "invalid image firmware id...\n");
+ goto exit;
+ }
+
+ dev_info(&i2c_client->dev,
+ "Device firmware id %d, .img firmware id %d\n",
+ deviceFirmwareID,
+ (unsigned int)imageFirmwareID);
+ if (imageFirmwareID > deviceFirmwareID) {
+ flash_area = UI_FIRMWARE;
+ goto exit;
+ }
+
+ /* device config id */
+ retval = fwu->fn_ptr->read(fwu->rmi4_data,
+ fwu->f34_fd.ctrl_base_addr,
+ config_id,
+ sizeof(config_id));
+ if (retval < 0) {
+ dev_err(&i2c_client->dev,
+ "Failed to read config ID (code %d).\n", retval);
+ flash_area = NONE;
+ goto exit;
+ }
+ deviceConfigID = extract_uint(config_id);
+
+ dev_info(&i2c_client->dev,
+ "Device config ID 0x%02X, 0x%02X, 0x%02X, 0x%02X\n",
+ config_id[0], config_id[1], config_id[2], config_id[3]);
+
+ /* .img config id */
+ dev_info(&i2c_client->dev,
+ ".img config ID 0x%02X, 0x%02X, 0x%02X, 0x%02X\n",
+ fwu->config_data[0],
+ fwu->config_data[1],
+ fwu->config_data[2],
+ fwu->config_data[3]);
+ imageConfigID = extract_uint(fwu->config_data);
+
+ if (imageConfigID > deviceConfigID) {
+ flash_area = CONFIG_AREA;
+ goto exit;
+ }
+
+exit:
+ kfree(imagePR);
+ if (flash_area == NONE)
+ dev_info(&i2c_client->dev,
+ "Nothing needs to be updated\n");
+ else
+ dev_info(&i2c_client->dev,
+ "Update %s block\n",
+ flash_area == UI_FIRMWARE ? "UI FW" : "CONFIG");
+ return flash_area;
+}
+
static int fwu_scan_pdt(void)
{
int retval;
@@ -649,16 +726,25 @@ static int fwu_write_blocks(unsigned char *block_ptr, unsigned short block_cnt,
int retval;
unsigned char block_offset[] = {0, 0};
unsigned short block_num;
+ struct i2c_client *i2c_client = fwu->rmi4_data->i2c_client;
#ifdef SHOW_PROGRESS
unsigned int progress = (command == CMD_WRITE_CONFIG_BLOCK) ?
10 : 100;
#endif
+
+#ifdef DEBUG_FW_UPDATE
+ dev_info(&i2c_client->dev,
+ "%s: Start to update %s blocks\n",
+ __func__,
+ command == CMD_WRITE_CONFIG_BLOCK ?
+ "config" : "firmware");
+#endif
retval = fwu->fn_ptr->write(fwu->rmi4_data,
fwu->f34_fd.data_base_addr + BLOCK_NUMBER_OFFSET,
block_offset,
sizeof(block_offset));
if (retval < 0) {
- dev_err(&fwu->rmi4_data->i2c_client->dev,
+ dev_err(&i2c_client->dev,
"%s: Failed to write to block number registers\n",
__func__);
return retval;
@@ -667,20 +753,19 @@ static int fwu_write_blocks(unsigned char *block_ptr, unsigned short block_cnt,
for (block_num = 0; block_num < block_cnt; block_num++) {
#ifdef SHOW_PROGRESS
if (block_num % progress == 0)
- dev_info(&fwu->rmi4_data->i2c_client->dev,
- "%s: update %s %3d / %3d\n",
- __func__,
- command == CMD_WRITE_CONFIG_BLOCK ?
- "config" : "firmware",
- block_num,
- block_cnt);
+ dev_info(&i2c_client->dev,
+ "%s: update %s %3d / %3d\n",
+ __func__,
+ command == CMD_WRITE_CONFIG_BLOCK ?
+ "config" : "firmware",
+ block_num, block_cnt);
#endif
retval = fwu->fn_ptr->write(fwu->rmi4_data,
fwu->f34_fd.data_base_addr + BLOCK_DATA_OFFSET,
block_ptr,
fwu->block_size);
if (retval < 0) {
- dev_err(&fwu->rmi4_data->i2c_client->dev,
+ dev_err(&i2c_client->dev,
"%s: Failed to write block data (block %d)\n",
__func__, block_num);
return retval;
@@ -688,7 +773,7 @@ static int fwu_write_blocks(unsigned char *block_ptr, unsigned short block_cnt,
retval = fwu_write_f34_command(command);
if (retval < 0) {
- dev_err(&fwu->rmi4_data->i2c_client->dev,
+ dev_err(&i2c_client->dev,
"%s: Failed to write command for block %d\n",
__func__, block_num);
return retval;
@@ -696,30 +781,28 @@ static int fwu_write_blocks(unsigned char *block_ptr, unsigned short block_cnt,
retval = fwu_wait_for_idle(WRITE_WAIT_MS);
if (retval < 0) {
- dev_err(&fwu->rmi4_data->i2c_client->dev,
- "%s: Failed to wait for idle status \
- (block %d)\n",
- __func__, block_num);
+ dev_err(&i2c_client->dev,
+ "%s: Failed to wait for idle status (block %d)\n",
+ __func__, block_num);
return retval;
}
- retval = fwu_check_flash_status();
- if (retval != 0) {
- dev_err(&fwu->rmi4_data->i2c_client->dev,
- "%s: Flash block %d status %d\n",
+ if (fwu->flash_control.status != 0x00) {
+ dev_err(&i2c_client->dev,
+ "%s: Flash block %d failed, status 0x%02X\n",
__func__, block_num, retval);
return -1;
}
+
block_ptr += fwu->block_size;
}
#ifdef SHOW_PROGRESS
- dev_info(&fwu->rmi4_data->i2c_client->dev,
- "%s: update %s %3d / %3d\n",
- __func__,
- command == CMD_WRITE_CONFIG_BLOCK ?
- "config" : "firmware",
- block_cnt,
- block_cnt);
+ dev_info(&i2c_client->dev,
+ "%s: update %s %3d / %3d\n",
+ __func__,
+ command == CMD_WRITE_CONFIG_BLOCK ?
+ "config" : "firmware",
+ block_cnt, block_cnt);
#endif
return 0;
}
@@ -741,7 +824,10 @@ static int fwu_write_bootloader_id(void)
int retval;
#ifdef DEBUG_FW_UPDATE
- dev_info(&fwu->rmi4_data->i2c_client->dev, "Write bootloader ID\n");
+ dev_info(&fwu->rmi4_data->i2c_client->dev,
+ "Write bootloader ID 0x%02X 0x%02X\n",
+ fwu->bootloader_id[0],
+ fwu->bootloader_id[1]);
#endif
retval = fwu->fn_ptr->write(fwu->rmi4_data,
fwu->f34_fd.data_base_addr + BLOCK_DATA_OFFSET,
@@ -789,17 +875,6 @@ static int fwu_enter_flash_prog(void)
if (retval < 0)
return retval;
- retval = fwu_read_f01_device_status(&f01_device_status);
- if (retval < 0)
- return retval;
-
- if (!f01_device_status.flash_prog) {
- dev_err(&fwu->rmi4_data->i2c_client->dev,
- "%s: Program enabled bit not set\n",
- __func__);
- return -EINVAL;
- }
-
retval = fwu_scan_pdt();
if (retval < 0)
return retval;
@@ -879,9 +954,12 @@ static int fwu_do_reflash(void)
if (retval < 0)
return retval;
- dev_dbg(&fwu->rmi4_data->i2c_client->dev,
- "%s: Idle status detected\n",
- __func__);
+ if (fwu->flash_control.status != 0x00) {
+ dev_err(&fwu->rmi4_data->i2c_client->dev,
+ "%s: Erase all command failed, status 0x%02X\n",
+ __func__, retval);
+ return -1;
+ }
if (fwu->firmware_data) {
retval = fwu_write_firmware();
@@ -900,90 +978,6 @@ static int fwu_do_reflash(void)
return retval;
}
-static int fwu_start_reflash(void)
-{
- int retval;
- struct image_header header;
- const unsigned char *fw_image;
- const struct firmware *fw_entry = NULL;
- struct f01_device_status f01_device_status;
-
- pr_notice("%s: Start of reflash process\n", __func__);
-
- if (fwu->ext_data_source)
- fw_image = fwu->ext_data_source;
- else {
- dev_dbg(&fwu->rmi4_data->i2c_client->dev,
- "%s: Requesting firmware image %s\n",
- __func__, FW_IMAGE_NAME);
-
- retval = request_firmware(&fw_entry, FW_IMAGE_NAME,
- &fwu->rmi4_data->i2c_client->dev);
- if (retval != 0) {
- dev_err(&fwu->rmi4_data->i2c_client->dev,
- "%s: Firmware image %s not available\n",
- __func__, FW_IMAGE_NAME);
- retval = -EINVAL;
- goto exit;
- }
-
- dev_dbg(&fwu->rmi4_data->i2c_client->dev,
- "%s: Firmware image size = %d\n",
- __func__, fw_entry->size);
-
- fw_image = fw_entry->data;
- }
-
- parse_header(&header, fw_image);
-
- if (header.image_size)
- fwu->firmware_data = fw_image + FW_IMAGE_OFFSET;
- if (header.config_size) {
- fwu->config_data = fw_image + FW_IMAGE_OFFSET +
- header.image_size;
- }
-
- fwu->fn_ptr->enable(fwu->rmi4_data, false);
-
- fwu_check_version();
-
- retval = fwu_do_reflash();
- if (retval < 0) {
- dev_err(&fwu->rmi4_data->i2c_client->dev,
- "%s: Failed to do reflash\n",
- __func__);
- }
-
- /* reset device */
- fwu_reset_device();
-
- /* check device status */
- retval = fwu_read_f01_device_status(&f01_device_status);
- if (retval < 0)
- goto exit;
-
- dev_info(&fwu->rmi4_data->i2c_client->dev, "Device is in %s mode\n",
- f01_device_status.flash_prog == 1 ? "bootloader" : "UI");
- if (f01_device_status.flash_prog)
- dev_info(&fwu->rmi4_data->i2c_client->dev, "Flash status %d\n",
- f01_device_status.status_code);
-
- if (f01_device_status.flash_prog) {
- dev_info(&fwu->rmi4_data->i2c_client->dev,
- "%s: Device is in flash prog mode 0x%02X\n",
- __func__, f01_device_status.status_code);
- retval = 0;
- goto exit;
- }
- fwu->fn_ptr->enable(fwu->rmi4_data, true);
- if (fw_entry)
- release_firmware(fw_entry);
-
- pr_notice("%s: End of reflash process\n", __func__);
-exit:
- return retval;
-}
-
static int fwu_do_write_config(void)
{
int retval;
@@ -1205,6 +1199,110 @@ exit:
return retval;
}
+static int fwu_start_reflash(void)
+{
+ int retval;
+ struct image_header header;
+ const unsigned char *fw_image;
+ const struct firmware *fw_entry = NULL;
+ struct f01_device_status f01_device_status;
+ enum flash_area flash_area;
+
+ pr_notice("%s: Start of reflash process\n", __func__);
+
+ if (fwu->ext_data_source)
+ fw_image = fwu->ext_data_source;
+ else {
+ dev_dbg(&fwu->rmi4_data->i2c_client->dev,
+ "%s: Requesting firmware image %s\n",
+ __func__, FW_IMAGE_NAME);
+
+ retval = request_firmware(&fw_entry, FW_IMAGE_NAME,
+ &fwu->rmi4_data->i2c_client->dev);
+ if (retval != 0) {
+ dev_err(&fwu->rmi4_data->i2c_client->dev,
+ "%s: Firmware image %s not available\n",
+ __func__, FW_IMAGE_NAME);
+ retval = -EINVAL;
+ goto exit;
+ }
+
+ dev_dbg(&fwu->rmi4_data->i2c_client->dev,
+ "%s: Firmware image size = %d\n",
+ __func__, fw_entry->size);
+
+ fw_image = fw_entry->data;
+ }
+
+ parse_header(&header, fw_image);
+
+ if (header.image_size)
+ fwu->firmware_data = fw_image + FW_IMAGE_OFFSET;
+ if (header.config_size) {
+ fwu->config_data = fw_image + FW_IMAGE_OFFSET +
+ header.image_size;
+ }
+
+ if (fwu->ext_data_source)
+ flash_area = UI_FIRMWARE;
+ else
+ flash_area = fwu_go_nogo();
+
+ switch (flash_area) {
+ case NONE:
+ dev_info(&fwu->rmi4_data->i2c_client->dev,
+ "%s: No need to do reflash.\n",
+ __func__);
+ goto exit;
+ case UI_FIRMWARE:
+ retval = fwu_do_reflash();
+ break;
+ case CONFIG_AREA:
+ retval = fwu_do_write_config();
+ break;
+ default:
+ dev_err(&fwu->rmi4_data->i2c_client->dev,
+ "%s: Unknown flash area\n",
+ __func__);
+ goto exit;
+ }
+
+ if (retval < 0) {
+ dev_err(&fwu->rmi4_data->i2c_client->dev,
+ "%s: Failed to do reflash\n",
+ __func__);
+ }
+
+ /* reset device */
+ fwu_reset_device();
+
+ /* check device status */
+ retval = fwu_read_f01_device_status(&f01_device_status);
+ if (retval < 0)
+ goto exit;
+
+ dev_info(&fwu->rmi4_data->i2c_client->dev, "Device is in %s mode\n",
+ f01_device_status.flash_prog == 1 ? "bootloader" : "UI");
+ if (f01_device_status.flash_prog)
+ dev_info(&fwu->rmi4_data->i2c_client->dev, "Flash status %d\n",
+ f01_device_status.status_code);
+
+ if (f01_device_status.flash_prog) {
+ dev_info(&fwu->rmi4_data->i2c_client->dev,
+ "%s: Device is in flash prog mode 0x%02X\n",
+ __func__, f01_device_status.status_code);
+ retval = 0;
+ goto exit;
+ }
+
+ if (fw_entry)
+ release_firmware(fw_entry);
+
+ pr_notice("%s: End of reflash process\n", __func__);
+exit:
+ return retval;
+}
+
int synaptics_fw_updater(unsigned char *fw_data)
{
int retval;
@@ -1431,6 +1529,11 @@ static void synaptics_rmi4_fwu_attn(struct synaptics_rmi4_data *rmi4_data,
return;
}
+static void synaptics_rmi4_fwu_work(struct work_struct *work)
+{
+ fwu_start_reflash();
+}
+
static int synaptics_rmi4_fwu_init(struct synaptics_rmi4_data *rmi4_data)
{
int retval;
@@ -1497,6 +1600,7 @@ static int synaptics_rmi4_fwu_init(struct synaptics_rmi4_data *rmi4_data)
goto exit_free_mem;
fwu->initialized = true;
+ fwu->force_update = FORCE_UPDATE;
retval = sysfs_create_bin_file(&rmi4_data->input_dev->dev.kobj,
&dev_attr_data);
@@ -1519,6 +1623,13 @@ static int synaptics_rmi4_fwu_init(struct synaptics_rmi4_data *rmi4_data)
}
}
+#ifdef INSIDE_FIRMWARE_UPDATE
+ fwu->fwu_workqueue = create_singlethread_workqueue("fwu_workqueue");
+ INIT_DELAYED_WORK(&fwu->fwu_work, synaptics_rmi4_fwu_work);
+ queue_delayed_work(fwu->fwu_workqueue,
+ &fwu->fwu_work,
+ msecs_to_jiffies(1000));
+#endif
return 0;
exit_remove_attrs:
diff --git a/kernel/drivers/input/touchscreen/synaptics_i2c_rmi4.c b/kernel/drivers/input/touchscreen/synaptics_i2c_rmi4.c
index 85530225abd2..76f9155bd49c 100644
--- a/kernel/drivers/input/touchscreen/synaptics_i2c_rmi4.c
+++ b/kernel/drivers/input/touchscreen/synaptics_i2c_rmi4.c
@@ -347,28 +347,32 @@ static ssize_t synaptics_rmi4_0dbutton_store(struct device *dev,
if (rmi4_data->button_0d_enabled == input)
return count;
- list_for_each_entry(fhandler, &rmi->support_fn_list, link) {
- if (fhandler->fn_number == SYNAPTICS_RMI4_F1A) {
- ii = fhandler->intr_reg_num;
+ if (!list_empty(&rmi->support_fn_list)) {
+ list_for_each_entry(fhandler, &rmi->support_fn_list, link) {
+ if (fhandler->fn_number == SYNAPTICS_RMI4_F1A) {
+ ii = fhandler->intr_reg_num;
- retval = synaptics_rmi4_i2c_read(rmi4_data,
- rmi4_data->f01_ctrl_base_addr + 1 + ii,
- &intr_enable,
- sizeof(intr_enable));
- if (retval < 0)
- return retval;
+ retval = synaptics_rmi4_i2c_read(rmi4_data,
+ rmi4_data->f01_ctrl_base_addr +
+ 1 + ii,
+ &intr_enable,
+ sizeof(intr_enable));
+ if (retval < 0)
+ return retval;
- if (input == 1)
- intr_enable |= fhandler->intr_mask;
- else
- intr_enable &= ~fhandler->intr_mask;
+ if (input == 1)
+ intr_enable |= fhandler->intr_mask;
+ else
+ intr_enable &= ~fhandler->intr_mask;
- retval = synaptics_rmi4_i2c_write(rmi4_data,
- rmi4_data->f01_ctrl_base_addr + 1 + ii,
- &intr_enable,
- sizeof(intr_enable));
- if (retval < 0)
- return retval;
+ retval = synaptics_rmi4_i2c_write(rmi4_data,
+ rmi4_data->f01_ctrl_base_addr +
+ 1 + ii,
+ &intr_enable,
+ sizeof(intr_enable));
+ if (retval < 0)
+ return retval;
+ }
}
}
@@ -637,28 +641,22 @@ static int synaptics_rmi4_f11_abs_report(struct synaptics_rmi4_data *rmi4_data,
finger_status,
x, y, wx, wy);
-#ifdef TYPE_B_PROTOCOL
- input_report_abs(rmi4_data->input_dev,
- ABS_MT_POSITION_X, x);
- input_report_abs(rmi4_data->input_dev,
- ABS_MT_POSITION_Y, y);
-#ifdef REPORT_2D_W
- input_report_abs(rmi4_data->input_dev,
- ABS_MT_TOUCH_MAJOR, max(wx, wy));
- input_report_abs(rmi4_data->input_dev,
- ABS_MT_TOUCH_MINOR, min(wx, wy));
-#endif
-#else
+ input_report_key(rmi4_data->input_dev,
+ BTN_TOUCH, 1);
+ input_report_key(rmi4_data->input_dev,
+ BTN_TOOL_FINGER, 1);
input_report_abs(rmi4_data->input_dev,
ABS_MT_POSITION_X, x);
input_report_abs(rmi4_data->input_dev,
ABS_MT_POSITION_Y, y);
+
#ifdef REPORT_2D_W
input_report_abs(rmi4_data->input_dev,
ABS_MT_TOUCH_MAJOR, max(wx, wy));
input_report_abs(rmi4_data->input_dev,
ABS_MT_TOUCH_MINOR, min(wx, wy));
#endif
+#ifndef TYPE_B_PROTOCOL
input_mt_sync(rmi4_data->input_dev);
#endif
touch_count++;
@@ -853,12 +851,14 @@ static int synaptics_rmi4_sensor_report(struct synaptics_rmi4_data *rmi4_data)
* Traverse the function handler list and service the source(s)
* of the interrupt accordingly.
*/
- list_for_each_entry(fhandler, &rmi->support_fn_list, link) {
- if (fhandler->num_of_data_sources) {
- if (fhandler->intr_mask &
- intr[fhandler->intr_reg_num]) {
- synaptics_rmi4_report_touch(rmi4_data,
- fhandler, &touch_count);
+ if (!list_empty(&rmi->support_fn_list)) {
+ list_for_each_entry(fhandler, &rmi->support_fn_list, link) {
+ if (fhandler->num_of_data_sources) {
+ if (fhandler->intr_mask &
+ intr[fhandler->intr_reg_num]) {
+ synaptics_rmi4_report_touch(rmi4_data,
+ fhandler, &touch_count);
+ }
}
}
}
@@ -1088,8 +1088,8 @@ static int synaptics_rmi4_capacitance_button_map(
if (!pdata->capacitance_button_map) {
dev_err(&rmi4_data->i2c_client->dev,
- "%s: capacitance_button_map is \
- NULL in board file\n",
+ "%s: capacitance_button_map is" \
+ "NULL in board file\n",
__func__);
return -ENODEV;
} else if (!pdata->capacitance_button_map->map) {
@@ -1194,6 +1194,63 @@ static int synaptics_rmi4_alloc_fh(struct synaptics_rmi4_fn **fhandler,
return 0;
}
+
+ /**
+ * synaptics_rmi4_query_device_info()
+ *
+ * Called by synaptics_rmi4_query_device().
+ *
+ */
+static int synaptics_rmi4_query_device_info(
+ struct synaptics_rmi4_data *rmi4_data)
+{
+ int retval;
+ unsigned char f01_query[F01_STD_QUERY_LEN];
+ struct synaptics_rmi4_device_info *rmi = &(rmi4_data->rmi4_mod_info);
+
+ retval = synaptics_rmi4_i2c_read(rmi4_data,
+ rmi4_data->f01_query_base_addr,
+ f01_query,
+ sizeof(f01_query));
+ if (retval < 0)
+ return retval;
+
+ /* RMI Version 4.0 currently supported */
+ rmi->version_major = 4;
+ rmi->version_minor = 0;
+
+ rmi->manufacturer_id = f01_query[0];
+ rmi->product_props = f01_query[1];
+ rmi->product_info[0] = f01_query[2] & MASK_7BIT;
+ rmi->product_info[1] = f01_query[3] & MASK_7BIT;
+ rmi->date_code[0] = f01_query[4] & MASK_5BIT;
+ rmi->date_code[1] = f01_query[5] & MASK_4BIT;
+ rmi->date_code[2] = f01_query[6] & MASK_5BIT;
+ rmi->tester_id = ((f01_query[7] & MASK_7BIT) << 8) |
+ (f01_query[8] & MASK_7BIT);
+ rmi->serial_number = ((f01_query[9] & MASK_7BIT) << 8) |
+ (f01_query[10] & MASK_7BIT);
+ memcpy(rmi->product_id_string, &f01_query[11], 10);
+
+ if (rmi->manufacturer_id != 1) {
+ dev_err(&rmi4_data->i2c_client->dev,
+ "%s: Non-Synaptics device found, manufacturer ID = %d\n",
+ __func__, rmi->manufacturer_id);
+ }
+
+ retval = synaptics_rmi4_i2c_read(rmi4_data,
+ rmi4_data->f01_query_base_addr + F01_BUID_ID_OFFSET,
+ rmi->build_id,
+ sizeof(rmi->build_id));
+ if (retval < 0) {
+ dev_err(&rmi4_data->i2c_client->dev,
+ "%s: Failed to read firmware build id (code %d)\n",
+ __func__, retval);
+ return retval;
+ }
+ return retval;
+}
+
/**
* synaptics_rmi4_query_device()
*
@@ -1214,7 +1271,6 @@ static int synaptics_rmi4_query_device(struct synaptics_rmi4_data *rmi4_data)
unsigned char page_number;
unsigned char intr_count = 0;
unsigned char data_sources = 0;
- unsigned char f01_query[F01_STD_QUERY_LEN];
unsigned short pdt_entry_addr;
unsigned short intr_addr;
struct synaptics_rmi4_f01_device_status status;
@@ -1264,6 +1320,11 @@ static int synaptics_rmi4_query_device(struct synaptics_rmi4_data *rmi4_data)
rmi4_data->f01_cmd_base_addr =
rmi_fd.cmd_base_addr;
+ retval =
+ synaptics_rmi4_query_device_info(rmi4_data);
+ if (retval < 0)
+ return retval;
+
retval = synaptics_rmi4_i2c_read(rmi4_data,
rmi4_data->f01_data_base_addr,
status.data,
@@ -1277,7 +1338,17 @@ static int synaptics_rmi4_query_device(struct synaptics_rmi4_data *rmi4_data)
status.status_code);
goto flash_prog_mode;
}
- break;
+ break;
+
+ case SYNAPTICS_RMI4_F34:
+ retval = synaptics_rmi4_i2c_read(rmi4_data,
+ rmi_fd.ctrl_base_addr,
+ rmi->config_id,
+ sizeof(rmi->config_id));
+ if (retval < 0)
+ return retval;
+ break;
+
case SYNAPTICS_RMI4_F11:
if (rmi_fd.intr_src_count == 0)
break;
@@ -1335,56 +1406,24 @@ flash_prog_mode:
"%s: Number of interrupt registers = %d\n",
__func__, rmi4_data->num_of_intr_regs);
- retval = synaptics_rmi4_i2c_read(rmi4_data,
- rmi4_data->f01_query_base_addr,
- f01_query,
- sizeof(f01_query));
- if (retval < 0)
- return retval;
-
- /* RMI Version 4.0 currently supported */
- rmi->version_major = 4;
- rmi->version_minor = 0;
-
- rmi->manufacturer_id = f01_query[0];
- rmi->product_props = f01_query[1];
- rmi->product_info[0] = f01_query[2] & MASK_7BIT;
- rmi->product_info[1] = f01_query[3] & MASK_7BIT;
- rmi->date_code[0] = f01_query[4] & MASK_5BIT;
- rmi->date_code[1] = f01_query[5] & MASK_4BIT;
- rmi->date_code[2] = f01_query[6] & MASK_5BIT;
- rmi->tester_id = ((f01_query[7] & MASK_7BIT) << 8) |
- (f01_query[8] & MASK_7BIT);
- rmi->serial_number = ((f01_query[9] & MASK_7BIT) << 8) |
- (f01_query[10] & MASK_7BIT);
- memcpy(rmi->product_id_string, &f01_query[11], 10);
-
- if (rmi->manufacturer_id != 1) {
- dev_err(&rmi4_data->i2c_client->dev,
- "%s: Non-Synaptics device found, manufacturer ID = %d\n",
- __func__, rmi->manufacturer_id);
- }
-
- retval = synaptics_rmi4_i2c_read(rmi4_data,
- rmi4_data->f01_query_base_addr + F01_BUID_ID_OFFSET,
- rmi->build_id,
- sizeof(rmi->build_id));
- if (retval < 0)
- return retval;
-
memset(rmi4_data->intr_mask, 0x00, sizeof(rmi4_data->intr_mask));
/*
* Map out the interrupt bit masks for the interrupt sources
* from the registered function handlers.
*/
- list_for_each_entry(fhandler, &rmi->support_fn_list, link)
- data_sources += fhandler->num_of_data_sources;
+ if (!list_empty(&rmi->support_fn_list)) {
+ list_for_each_entry(fhandler, &rmi->support_fn_list, link)
+ data_sources += fhandler->num_of_data_sources;
+ }
if (data_sources) {
- list_for_each_entry(fhandler, &rmi->support_fn_list, link) {
- if (fhandler->num_of_data_sources) {
- rmi4_data->intr_mask[fhandler->intr_reg_num] |=
- fhandler->intr_mask;
+ if (!list_empty(&rmi->support_fn_list)) {
+ list_for_each_entry(fhandler,
+ &rmi->support_fn_list, link) {
+ if (fhandler->num_of_data_sources) {
+ rmi4_data->intr_mask[fhandler->intr_reg_num] |=
+ fhandler->intr_mask;
+ }
}
}
}
@@ -1430,12 +1469,14 @@ static int synaptics_rmi4_reset_device(struct synaptics_rmi4_data *rmi4_data)
msleep(100);
- list_for_each_entry(fhandler, &rmi->support_fn_list, link) {
- if (fhandler->fn_number == SYNAPTICS_RMI4_F1A)
- synaptics_rmi4_f1a_kfree(fhandler);
- else
- kfree(fhandler->data);
- kfree(fhandler);
+ if (!list_empty(&rmi->support_fn_list)) {
+ list_for_each_entry(fhandler, &rmi->support_fn_list, link) {
+ if (fhandler->fn_number == SYNAPTICS_RMI4_F1A)
+ synaptics_rmi4_f1a_kfree(fhandler);
+ else
+ kfree(fhandler->data);
+ kfree(fhandler);
+ }
}
retval = synaptics_rmi4_query_device(rmi4_data);
@@ -1534,12 +1575,14 @@ void synaptics_rmi4_new_function(enum exp_fn fn_type, bool insert,
exp_fhandler->inserted = false;
list_add_tail(&exp_fhandler->link, &exp_fn_list);
} else {
- list_for_each_entry(exp_fhandler, &exp_fn_list, link) {
- if (exp_fhandler->func_init == func_init) {
- exp_fhandler->inserted = false;
- exp_fhandler->func_init = NULL;
- exp_fhandler->func_attn = NULL;
- goto exit;
+ if (!list_empty(&exp_fn_list)) {
+ list_for_each_entry(exp_fhandler, &exp_fn_list, link) {
+ if (exp_fhandler->func_init == func_init) {
+ exp_fhandler->inserted = false;
+ exp_fhandler->func_init = NULL;
+ exp_fhandler->func_attn = NULL;
+ goto exit;
+ }
}
}
}
@@ -1611,7 +1654,7 @@ static int __devinit synaptics_rmi4_probe(struct i2c_client *client,
retval = -ENOMEM;
goto err_input_device;
}
-/*
+
if (platform_data->regulator_en) {
rmi4_data->regulator = regulator_get(&client->dev, "vdd");
if (IS_ERR(rmi4_data->regulator)) {
@@ -1623,7 +1666,7 @@ static int __devinit synaptics_rmi4_probe(struct i2c_client *client,
}
regulator_enable(rmi4_data->regulator);
}
-*/
+
rmi4_data->i2c_client = client;
rmi4_data->current_page = MASK_8BIT;
rmi4_data->board = platform_data;
@@ -1652,12 +1695,16 @@ static int __devinit synaptics_rmi4_probe(struct i2c_client *client,
rmi4_data->input_dev->name = DRIVER_NAME;
rmi4_data->input_dev->phys = INPUT_PHYS_NAME;
rmi4_data->input_dev->id.bustype = BUS_I2C;
+ rmi4_data->input_dev->id.product = SYNAPTICS_RMI4_DRIVER_PRODUCT;
+ rmi4_data->input_dev->id.version = SYNAPTICS_RMI4_DRIVER_VERSION;
rmi4_data->input_dev->dev.parent = &client->dev;
input_set_drvdata(rmi4_data->input_dev, rmi4_data);
set_bit(EV_SYN, rmi4_data->input_dev->evbit);
set_bit(EV_KEY, rmi4_data->input_dev->evbit);
set_bit(EV_ABS, rmi4_data->input_dev->evbit);
+ set_bit(BTN_TOUCH, rmi4_data->input_dev->keybit);
+ set_bit(BTN_TOOL_FINGER, rmi4_data->input_dev->keybit);
#ifdef INPUT_PROP_DIRECT
set_bit(INPUT_PROP_DIRECT, rmi4_data->input_dev->propbit);
@@ -1681,9 +1728,11 @@ static int __devinit synaptics_rmi4_probe(struct i2c_client *client,
#endif
f1a = NULL;
- list_for_each_entry(fhandler, &rmi->support_fn_list, link) {
- if (fhandler->fn_number == SYNAPTICS_RMI4_F1A)
- f1a = fhandler->data;
+ if (!list_empty(&rmi->support_fn_list)) {
+ list_for_each_entry(fhandler, &rmi->support_fn_list, link) {
+ if (fhandler->fn_number == SYNAPTICS_RMI4_F1A)
+ f1a = fhandler->data;
+ }
}
if (f1a) {
@@ -1775,16 +1824,17 @@ err_query_device:
regulator_put(rmi4_data->regulator);
}
- list_for_each_entry(fhandler, &rmi->support_fn_list, link) {
- if (fhandler->fn_number == SYNAPTICS_RMI4_F1A)
- synaptics_rmi4_f1a_kfree(fhandler);
- else
- kfree(fhandler->data);
- kfree(fhandler);
+ if (!list_empty(&rmi->support_fn_list)) {
+ list_for_each_entry(fhandler, &rmi->support_fn_list, link) {
+ if (fhandler->fn_number == SYNAPTICS_RMI4_F1A)
+ synaptics_rmi4_f1a_kfree(fhandler);
+ else
+ kfree(fhandler->data);
+ kfree(fhandler);
+ }
}
-/*
+
err_regulator:
-*/
input_free_device(rmi4_data->input_dev);
rmi4_data->input_dev = NULL;
@@ -1836,12 +1886,14 @@ static int __devexit synaptics_rmi4_remove(struct i2c_client *client)
regulator_put(rmi4_data->regulator);
}
- list_for_each_entry(fhandler, &rmi->support_fn_list, link) {
- if (fhandler->fn_number == SYNAPTICS_RMI4_F1A)
- synaptics_rmi4_f1a_kfree(fhandler);
- else
- kfree(fhandler->data);
- kfree(fhandler);
+ if (!list_empty(&rmi->support_fn_list)) {
+ list_for_each_entry(fhandler, &rmi->support_fn_list, link) {
+ if (fhandler->fn_number == SYNAPTICS_RMI4_F1A)
+ synaptics_rmi4_f1a_kfree(fhandler);
+ else
+ kfree(fhandler->data);
+ kfree(fhandler);
+ }
}
input_free_device(rmi4_data->input_dev);
diff --git a/kernel/drivers/input/touchscreen/synaptics_i2c_rmi4.h b/kernel/drivers/input/touchscreen/synaptics_i2c_rmi4.h
index 7ee0a925959a..ecb9b9415e8a 100644
--- a/kernel/drivers/input/touchscreen/synaptics_i2c_rmi4.h
+++ b/kernel/drivers/input/touchscreen/synaptics_i2c_rmi4.h
@@ -20,7 +20,10 @@
#ifndef _SYNAPTICS_DSX_RMI4_H_
#define _SYNAPTICS_DSX_RMI4_H_
-#define SYNAPTICS_RMI4_DRIVER_VERSION "DSX 1.0"
+#define SYNAPTICS_RMI4_DS4 0x0001
+#define SYNAPTICS_RMI4_DS5 0x0002
+#define SYNAPTICS_RMI4_DRIVER_PRODUCT SYNAPTICS_RMI4_DS4
+#define SYNAPTICS_RMI4_DRIVER_VERSION 0x1001
#include <linux/version.h>
#ifdef CONFIG_HAS_EARLYSUSPEND
@@ -158,6 +161,7 @@ struct synaptics_rmi4_device_info {
unsigned short serial_number;
unsigned char product_id_string[SYNAPTICS_RMI4_PRODUCT_ID_SIZE + 1];
unsigned char build_id[SYNAPTICS_RMI4_BUILD_ID_SIZE];
+ unsigned char config_id[3];
struct list_head support_fn_list;
};
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 1cb22d44ccbb..96100cc046c5 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -1584,14 +1584,14 @@ event_sched_out(struct perf_event *event,
perf_pmu_disable(event->pmu);
+ event->tstamp_stopped = tstamp;
+ event->pmu->del(event, 0);
+ event->oncpu = -1;
event->state = PERF_EVENT_STATE_INACTIVE;
if (event->pending_disable) {
event->pending_disable = 0;
event->state = PERF_EVENT_STATE_OFF;
}
- event->tstamp_stopped = tstamp;
- event->pmu->del(event, 0);
- event->oncpu = -1;
if (!is_software_event(event))
cpuctx->active_oncpu--;
@@ -8032,6 +8032,9 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu,
}
}
+ /* symmetric to unaccount_event() in _free_event() */
+ account_event(event);
+
return event;
err_per_task:
@@ -8398,8 +8401,6 @@ SYSCALL_DEFINE5(perf_event_open,
}
}
- account_event(event);
-
/*
* Special case software events and allow them to be part of
* any hardware group.
@@ -8638,7 +8639,12 @@ err_context:
perf_unpin_context(ctx);
put_ctx(ctx);
err_alloc:
- free_event(event);
+ /*
+ * If event_file is set, the fput() above will have called ->release()
+ * and that will take care of freeing the event.
+ */
+ if (!event_file)
+ free_event(event);
err_cpus:
put_online_cpus();
err_task:
@@ -8682,8 +8688,6 @@ perf_event_create_kernel_counter(struct perf_event_attr *attr, int cpu,
/* Mark owner so we could distinguish it from user events. */
event->owner = EVENT_OWNER_KERNEL;
- account_event(event);
-
ctx = find_get_context(event->pmu, task, event);
if (IS_ERR(ctx)) {
err = PTR_ERR(ctx);
diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c
index b7342a24f559..b7dd5718836e 100644
--- a/kernel/power/hibernate.c
+++ b/kernel/power/hibernate.c
@@ -339,6 +339,7 @@ int hibernation_snapshot(int platform_mode)
pm_message_t msg;
int error;
+ pm_suspend_clear_flags();
error = platform_begin(platform_mode);
if (error)
goto Close;
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index f640c0e3c7ea..58303b3dc356 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -8986,6 +8986,7 @@ migration_call(struct notifier_block *nfb, unsigned long action, void *hcpu)
set_window_start(rq);
raw_spin_unlock_irqrestore(&rq->lock, flags);
rq->calc_load_update = calc_load_update;
+ account_reset_rq(rq);
break;
case CPU_ONLINE:
diff --git a/kernel/sched/cputime.c b/kernel/sched/cputime.c
index 647f184f8aec..f29b132a9f8b 100644
--- a/kernel/sched/cputime.c
+++ b/kernel/sched/cputime.c
@@ -270,21 +270,21 @@ static __always_inline bool steal_account_process_tick(void)
#ifdef CONFIG_PARAVIRT
if (static_key_false(&paravirt_steal_enabled)) {
u64 steal;
- cputime_t steal_ct;
+ unsigned long steal_jiffies;
steal = paravirt_steal_clock(smp_processor_id());
steal -= this_rq()->prev_steal_time;
/*
- * cputime_t may be less precise than nsecs (eg: if it's
- * based on jiffies). Lets cast the result to cputime
+ * steal is in nsecs but our caller is expecting steal
+ * time in jiffies. Lets cast the result to jiffies
* granularity and account the rest on the next rounds.
*/
- steal_ct = nsecs_to_cputime(steal);
- this_rq()->prev_steal_time += cputime_to_nsecs(steal_ct);
+ steal_jiffies = nsecs_to_jiffies(steal);
+ this_rq()->prev_steal_time += jiffies_to_nsecs(steal_jiffies);
- account_steal_time(steal_ct);
- return steal_ct;
+ account_steal_time(jiffies_to_cputime(steal_jiffies));
+ return steal_jiffies;
}
#endif
return false;
diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h
index 45b76cfff1ec..b9566cf3ad37 100644
--- a/kernel/sched/sched.h
+++ b/kernel/sched/sched.h
@@ -2363,3 +2363,16 @@ static inline u64 irq_time_read(int cpu)
}
#endif /* CONFIG_64BIT */
#endif /* CONFIG_IRQ_TIME_ACCOUNTING */
+
+static inline void account_reset_rq(struct rq *rq)
+{
+#ifdef CONFIG_IRQ_TIME_ACCOUNTING
+ rq->prev_irq_time = 0;
+#endif
+#ifdef CONFIG_PARAVIRT
+ rq->prev_steal_time = 0;
+#endif
+#ifdef CONFIG_PARAVIRT_TIME_ACCOUNTING
+ rq->prev_steal_time_rq = 0;
+#endif
+}
diff --git a/kernel/sysctl_binary.c b/kernel/sysctl_binary.c
index b65c78c15ab3..4a816bab38a2 100644
--- a/kernel/sysctl_binary.c
+++ b/kernel/sysctl_binary.c
@@ -1324,7 +1324,7 @@ static ssize_t binary_sysctl(const int *name, int nlen,
}
mnt = task_active_pid_ns(current)->proc_mnt;
- file = file_open_root(mnt->mnt_root, mnt, pathname, flags);
+ file = file_open_root(mnt->mnt_root, mnt, pathname, flags, 0);
result = PTR_ERR(file);
if (IS_ERR(file))
goto out_putname;
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 530bbc44082c..ae68222c5a74 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -5044,7 +5044,10 @@ static ssize_t tracing_splice_read_pipe(struct file *filp,
spd.nr_pages = i;
- ret = splice_to_pipe(pipe, &spd);
+ if (i)
+ ret = splice_to_pipe(pipe, &spd);
+ else
+ ret = 0;
out:
splice_shrink_spd(&spd);
return ret;
diff --git a/kernel/trace/trace_irqsoff.c b/kernel/trace/trace_irqsoff.c
index e4e56589ec1d..be3222b7d72e 100644
--- a/kernel/trace/trace_irqsoff.c
+++ b/kernel/trace/trace_irqsoff.c
@@ -109,8 +109,12 @@ static int func_prolog_dec(struct trace_array *tr,
return 0;
local_save_flags(*flags);
- /* slight chance to get a false positive on tracing_cpu */
- if (!irqs_disabled_flags(*flags))
+ /*
+ * Slight chance to get a false positive on tracing_cpu,
+ * although I'm starting to think there isn't a chance.
+ * Leave this for now just to be paranoid.
+ */
+ if (!irqs_disabled_flags(*flags) && !preempt_count())
return 0;
*data = per_cpu_ptr(tr->trace_buffer.data, cpu);
diff --git a/kernel/trace/trace_printk.c b/kernel/trace/trace_printk.c
index 060df67dbdd1..f96f0383f6c6 100644
--- a/kernel/trace/trace_printk.c
+++ b/kernel/trace/trace_printk.c
@@ -296,6 +296,9 @@ static int t_show(struct seq_file *m, void *v)
const char *str = *fmt;
int i;
+ if (!*fmt)
+ return 0;
+
seq_printf(m, "0x%lx : \"", *(unsigned long *)fmt);
/*
diff --git a/kernel/watchdog.c b/kernel/watchdog.c
index b40f7f35413d..9472691c1eb0 100644
--- a/kernel/watchdog.c
+++ b/kernel/watchdog.c
@@ -1038,6 +1038,9 @@ static int proc_watchdog_common(int which, struct ctl_table *table, int write,
* both lockup detectors are disabled if proc_watchdog_update()
* returns an error.
*/
+ if (old == new)
+ goto out;
+
err = proc_watchdog_update();
}
out:
@@ -1082,7 +1085,7 @@ int proc_soft_watchdog(struct ctl_table *table, int write,
int proc_watchdog_thresh(struct ctl_table *table, int write,
void __user *buffer, size_t *lenp, loff_t *ppos)
{
- int err, old;
+ int err, old, new;
get_online_cpus();
mutex_lock(&watchdog_proc_mutex);
@@ -1102,6 +1105,10 @@ int proc_watchdog_thresh(struct ctl_table *table, int write,
/*
* Update the sample period. Restore on failure.
*/
+ new = ACCESS_ONCE(watchdog_thresh);
+ if (old == new)
+ goto out;
+
set_sample_period();
err = proc_watchdog_update();
if (err) {