/** *Name : hynitron_esd_check.c *Author : steven *Version : V2.0 *Create : 2018-1-23 *Copyright : zxzz */ #include "hynitron_core.h" /*****************************************************************************/ #if HYN_ESDCHECK_EN #define SWITCH_ESD_OFF 0 #define SWITCH_ESD_ON 1 extern int hyn_reset_proc(int hdelayms); /************************************************************************ * Name: hyn_esd_show * Brief: no * Input: device, device attribute, char buf * Output: no * Return: ***********************************************************************/ static ssize_t hyn_esd_show(struct device *dev, struct device_attribute *attr, char *buf) { int count; //struct i2c_client *client = container_of(dev, struct i2c_client, dev); HYN_FUNC_ENTER(); mutex_lock(&hyn_ts_data->hyn_esd_lock); count = sprintf(buf,"ESD Mode: %d,ESD running = %d\n", hyn_ts_data->hyn_esd_mode,hyn_ts_data->hyn_esd_running); mutex_unlock(&hyn_ts_data->hyn_esd_lock); HYN_FUNC_EXIT(); return count; } /************************************************************************ * Name: hyn_esd_store * Brief: no * Input: device, device attribute, char buf, char count * Output: no * Return: ***********************************************************************/ static ssize_t hyn_esd_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { HYN_FUNC_ENTER(); mutex_lock(&hyn_ts_data->hyn_esd_lock); if (buf[0]==1) { HYN_INFO("[ESD]enable ESD"); hyn_ts_data->hyn_esd_mode = ENABLE; } else if (buf[0]==0) { HYN_INFO("[ESD]disable ESD"); hyn_ts_data->hyn_esd_mode = DISABLE; } mutex_unlock(&hyn_ts_data->hyn_esd_lock); HYN_FUNC_EXIT(); return count; } /************************************************************************ * Name: hyn_esd_buf_show * Brief: no * Input: device, device attribute, char buf * Output: no * Return: ***********************************************************************/ static ssize_t hyn_esd_buf_show(struct device *dev, struct device_attribute *attr, char *buf) { int count; HYN_FUNC_ENTER(); mutex_lock(&hyn_ts_data->hyn_esd_lock); count = snprintf(buf, PAGE_SIZE, "ESD running: 0x%x\n", hyn_ts_data->hyn_esd_running); count += snprintf(buf + count, PAGE_SIZE, "ESD pre_counter:0x%x\n", hyn_ts_data->hyn_esd_pre_counter); count += snprintf(buf + count, PAGE_SIZE, "ESD cur_counter:0x%x\n", hyn_ts_data->hyn_esd_cur_counter); count += snprintf(buf + count, PAGE_SIZE, "ESD work_cycle:0x%x\n", hyn_ts_data->hyn_esd_work_cycle); mutex_unlock(&hyn_ts_data->hyn_esd_lock); HYN_FUNC_EXIT(); return count; } /************************************************************************ * Name: hyn_esd_buf_store * Brief: no * Input: device, device attribute, char buf, char count * Output: no * Return: ***********************************************************************/ static ssize_t hyn_esd_buf_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { /* place holder for future use */ return -EPERM; } static DEVICE_ATTR (hyn_esd_mode, S_IRUGO|S_IWUSR, hyn_esd_show, hyn_esd_store); /* * read example: cat hyn_esd_buf ---read esd buf */ static DEVICE_ATTR (hyn_esd_buf, S_IRUGO|S_IWUSR, hyn_esd_buf_show, hyn_esd_buf_store); static struct attribute *hyn_esd_mode_attrs[] = { &dev_attr_hyn_esd_mode.attr, &dev_attr_hyn_esd_buf.attr, NULL, }; static struct attribute_group hyn_esd_group = { .attrs = hyn_esd_mode_attrs, }; void hyn_create_esd_sysfs(struct i2c_client *client) { int ret = 0; HYN_FUNC_ENTER(); //if(hyn_ts_data->k_obj==NULL) if(!hyn_ts_data->k_obj) return; ret = sysfs_create_group(hyn_ts_data->k_obj, &hyn_esd_group); if ( ret != 0) { HYN_ERROR( "[GESTURE]hyn_gesture_mode_group(sysfs) create failed!"); sysfs_remove_group(hyn_ts_data->k_obj, &hyn_esd_group); return; } HYN_FUNC_EXIT(); return; } static void hyn_esd_poweron_ic(unsigned int ms) { HYN_FUNC_ENTER(); hyn_reset_proc(10); HYN_FUNC_EXIT(); } void hyn_esd_suspend(void) { HYN_FUNC_ENTER(); if(hyn_ts_data->hyn_esd_mode) hyn_esd_switch(SWITCH_ESD_OFF); HYN_FUNC_EXIT(); } void hyn_esd_resume(void) { HYN_FUNC_ENTER(); if(hyn_ts_data->hyn_esd_mode) hyn_esd_switch(SWITCH_ESD_ON); HYN_FUNC_EXIT(); } void hyn_esd_switch(s32 on) { HYN_FUNC_ENTER(); if(!hyn_ts_data->hyn_esd_mode) return; mutex_lock(&hyn_ts_data->hyn_esd_lock); if (SWITCH_ESD_ON == on) { /* switch on esd check */ if (!hyn_ts_data->hyn_esd_running) { hyn_ts_data->hyn_esd_running = 1; hyn_ts_data->hyn_esd_pre_counter = 0; hyn_ts_data->hyn_esd_cur_counter = 0; HYN_DEBUG(" Esd protector started!"); queue_delayed_work(hyn_ts_data->hyn_esd_workqueue, &hyn_ts_data->hyn_esd_check_work, hyn_ts_data->hyn_esd_work_cycle); } } else { /* switch off esd check */ if (hyn_ts_data->hyn_esd_running) { hyn_ts_data->hyn_esd_running = 0; hyn_ts_data->hyn_esd_pre_counter = 0; hyn_ts_data->hyn_esd_cur_counter = 0; HYN_DEBUG(" Esd protector stopped!"); cancel_delayed_work(&hyn_ts_data->hyn_esd_check_work); } } mutex_unlock(&hyn_ts_data->hyn_esd_lock); HYN_FUNC_EXIT(); } static void hyn_esd_check_func(struct work_struct *work) { int retry = 0; int ret; int check_sum; unsigned char buf[8]; HYN_FUNC_ENTER(); if(!hyn_ts_data->hyn_esd_mode){ HYN_DEBUG("Esd protector hyn_esd_mode is disable !"); return; } if(hyn_ts_data->work_mode!=0){ HYN_DEBUG("Esd protector work_mode is false !"); return; } if (!hyn_ts_data->hyn_esd_running) { HYN_DEBUG("Esd protector hyn_esd_running is not running!"); return; } if((hyn_ts_data->hyn_esd_i2c_lock_flag != 0)||(hyn_ts_data->apk_rdwr_flag!=0)||(hyn_ts_data->fw_updating!=0)) goto END; else hyn_ts_data->hyn_esd_i2c_lock_flag = 1; if(hyn_ts_data->config_chip_product_line==HYN_CHIP_PRODUCT_LINE_MUT_CAP){ while(retry++ < 5) { buf[0] = HYN_REG_MUT_ESD_VALUE>>8; buf[1] = HYN_REG_MUT_ESD_VALUE&0xff; ret = cst3xx_i2c_read_register(hyn_ts_data->client, buf, 6); if (ret > 0){ check_sum = buf[0]+buf[1]+buf[2]+buf[3]+0xA5; if(check_sum != ( (buf[4]<<8)+ buf[5])){ HYN_ERROR("hyn_esd_check_func iic read check_sum error.\n"); }else{ break; } }else{ HYN_ERROR("hyn_esd_check_func iic error" ); goto hyn_esd_check_init; } mdelay(2); } }else if(hyn_ts_data->config_chip_product_line==HYN_CHIP_PRODUCT_LINE_SEL_CAP){ } if((retry==6)||(retry==0)|| (ret<0)){ HYN_ERROR("hyn_esd_check_func iic read esd data error,please check firmware,driver and hardware.\n"); goto END; } hyn_ts_data->hyn_esd_cur_counter = buf[3]+(buf[2]<<8)+(buf[1]<<16)+(buf[0]<<24); if(((hyn_ts_data->hyn_esd_cur_counter-hyn_ts_data->hyn_esd_pre_counter)<20) &&(hyn_ts_data->hyn_esd_pre_counter>100)) { HYN_ERROR("hyn_esd_check_func hyn_esd_cur_counter is :0x%x. hyn_esd_pre_counter is:0x%x.------\n",hyn_ts_data->hyn_esd_cur_counter,hyn_ts_data->hyn_esd_pre_counter); goto hyn_esd_check_init; } goto END; hyn_esd_check_init: HYN_ERROR("hyn_esd_check_func reset.\n"); hyn_esd_poweron_ic(10); mdelay(100); hyn_ts_data->hyn_esd_cur_counter=0; END: hyn_ts_data->hyn_esd_i2c_lock_flag = 0; hyn_ts_data->hyn_esd_pre_counter=hyn_ts_data->hyn_esd_cur_counter; mutex_lock(&hyn_ts_data->hyn_esd_lock); if (hyn_ts_data->hyn_esd_running) queue_delayed_work(hyn_ts_data->hyn_esd_workqueue, &hyn_ts_data->hyn_esd_check_work, hyn_ts_data->hyn_esd_work_cycle); else HYN_DEBUG(" Esd protector suspended!"); mutex_unlock(&hyn_ts_data->hyn_esd_lock); HYN_FUNC_EXIT(); } int hyn_esd_get_status(void) { u8 buf[7]; int ret=-1; u16 check_sum=0; HYN_FUNC_ENTER(); buf[0] = HYN_REG_MUT_ESD_VALUE>>8; buf[1] = HYN_REG_MUT_ESD_VALUE&0xff; ret = cst3xx_i2c_read_register(hyn_ts_data->client, buf, 6); check_sum = buf[0]+buf[1]+buf[2]+buf[3]+0xA5; if(check_sum != ( (buf[4]<<8)+ buf[5])){ HYN_ERROR(" esd check sum error.\n "); return -1; } HYN_FUNC_EXIT(); return 1; } void hyn_esd_init(void) { HYN_FUNC_ENTER(); if(hyn_esd_get_status() < 0) { HYN_ERROR(" hyn_esd_get_status failed!"); return; } hyn_ts_data->hyn_esd_workqueue = create_singlethread_workqueue("hyn_esd_workqueue"); if(!hyn_ts_data->hyn_esd_workqueue) HYN_ERROR(" hyn_esd_workqueue failed!"); else{ hyn_init_esd_protect(); hyn_esd_switch(SWITCH_ESD_ON); hyn_ts_data->hyn_esd_running=ENABLE; } hyn_create_esd_sysfs(hyn_ts_data->client); HYN_FUNC_EXIT(); } void hyn_init_esd_protect(void) { HYN_FUNC_ENTER(); hyn_ts_data->hyn_esd_work_cycle=1000; hyn_ts_data->hyn_esd_mode=ENABLE; HYN_DEBUG(" Clock ticks for an esd cycle: %d", hyn_ts_data->hyn_esd_work_cycle); INIT_DELAYED_WORK(&hyn_ts_data->hyn_esd_check_work, hyn_esd_check_func); mutex_init(&hyn_ts_data->hyn_esd_lock); HYN_FUNC_EXIT(); } void hyn_esd_exit(void) { HYN_FUNC_ENTER(); if (hyn_ts_data->hyn_esd_workqueue){ destroy_workqueue(hyn_ts_data->hyn_esd_workqueue); hyn_ts_data->hyn_esd_workqueue = NULL; } mutex_destroy(&hyn_ts_data->hyn_esd_lock); HYN_FUNC_EXIT(); } #endif