synaptics_mmi: firmware recovery with DRM

DRM framework is not sending resume event, thus recovery needs
another trigger. Then we cannot rely on touch IC reporting
flash programming mode if firmware has been wiped with erase
all (and this is the case when touch IC comes w/o any firmware
pre-flashed). Thus we load F34 handler first to ensure solid
flash mode detection.

Change-Id: I084188dec58d2dc690f5c7c7415329d0adb92bd9
Signed-off-by: Konstantin Makariev <hcv867@motorola.com>
Reviewed-on: https://gerrit.mot.com/1310296
SLTApproved: Slta Waiver
SME-Granted: SME Approvals Granted
Tested-by: Jira Key
Reviewed-by: Konstantin Makariev <kmakariev@motorola.com>
Submit-Approved: Jira Key
This commit is contained in:
Konstantin Makariev 2019-02-18 16:18:23 -06:00 • committed by Konstantin Makariev
commit b57eb61423

View file

@ -2782,15 +2782,31 @@ static int synaptics_dsx_sensor_ready_state(
int retval, state, i;
for (i = 0; i < 10; ++i) {
retval = rmi4_data->get_status(rmi4_data);
retval = synaptics_rmi4_f01_flashprog_status(rmi4_data);
dev_dbg(&rmi4_data->i2c_client->dev,
"%s: (%d): flashprog bit=%d\n",
__func__, i, retval);
/* if simple flashprog bit check reports BL mode */
/* then do not bother checking F34 flash status */
if (!retval &&
rmi4_data->get_status != synaptics_rmi4_f01_flashprog_status) {
retval = rmi4_data->get_status(rmi4_data);
dev_dbg(&rmi4_data->i2c_client->dev,
"%s: (%d): f34 flash status %d\n",
__func__, i, retval);
}
if (retval < 0) {
pr_err("(%d) Failed to query touch ic status\n", i);
dev_err(&rmi4_data->i2c_client->dev,
"%s: (%d) Failed to query touch ic status\n",
__func__, i);
return retval;
}
ui_mode = retval == 0;
pr_debug("(%d) UI mode: %s\n", i, ui_mode ? "true" : "false");
dev_dbg(&rmi4_data->i2c_client->dev,
"%s: (%d) UI mode: %s\n",
__func__, i, ui_mode ? "true" : "false");
if (ui_mode)
break;
@ -2801,7 +2817,9 @@ static int synaptics_dsx_sensor_ready_state(
if (!ui_mode && state == STATE_SUSPEND && rmi4_data->input_registered) {
/* expecting touch IC to enter UI mode based on */
/* its previous known good state */
pr_err("Timed out waiting for UI mode - UI mode forced\n");
dev_err(&rmi4_data->i2c_client->dev,
"%s: Timed out waiting for UI mode - UI mode forced\n",
__func__);
ui_mode = 1;
}
@ -6553,7 +6571,8 @@ static void synaptics_rmi4_detection_work(struct work_struct *work)
struct synaptics_rmi4_exp_fn *exp_fhandler, *next_list_entry;
struct device *dev = &rmi4_data->i2c_client->dev;
int state, error, probe_status;
bool all_inserted = true;
unsigned int scheduled_delay = 0;
bool f34_inserted = false;
bool terminate = false;
bool panel_ready = true;
char *pname = NULL;
@ -6608,9 +6627,10 @@ static void synaptics_rmi4_detection_work(struct work_struct *work)
list_for_each_entry(exp_fhandler,
&exp_fn_ctrl->fn_list,
link) {
if (!exp_fhandler->inserted) {
all_inserted = false;
dev_dbg(dev, "%s: not all inserted; keep waiting...\n", __func__);
if (exp_fhandler->fn_type == RMI_FW_UPDATER &&
exp_fhandler->inserted) {
f34_inserted = true;
dev_dbg(dev, "%s: F34 handler inserted\n", __func__);
break;
}
}
@ -6626,58 +6646,84 @@ static void synaptics_rmi4_detection_work(struct work_struct *work)
exp_fhandler->func_init = NULL;
}
if (exp_fhandler->func_init == NULL) {
if (exp_fhandler->inserted == true) {
dev_dbg(dev, "%s: calling remove func for handler: %d\n",
if (exp_fhandler->inserted == true) {
if (exp_fhandler->func_init) {
dev_dbg(dev, "%s: handler %d already inserted\n",
__func__, exp_fhandler->fn_type);
exp_fhandler->func_remove(rmi4_data);
/* need to restore status function on F34 removal */
if (exp_fhandler->fn_type == RMI_FW_UPDATER &&
exp_fhandler->func_status == rmi4_data->get_status) {
rmi4_data->get_status = synaptics_rmi4_f01_flashprog_status;
dev_info(dev,
"%s: using default status retrieval function\n",
__func__);
}
if (exp_fhandler->fn_type == RMI_DRM_FRAMEWORK) {
if (terminate) {
cancel_delayed_work_sync(&rmi4_data->exp_fn_ctrl.det_work);
flush_workqueue(det_workqueue);
i2c_set_clientdata(rmi4_data->i2c_client, NULL);
kfree(rmi4_data);
dev_info(dev, "%s: driver removed\n", __func__);
} else if (all_inserted) {
synaptics_rmi4_resume(&(rmi4_data->i2c_client->dev));
dev_info(dev, "%s: drm panel ready\n", __func__);
} else {
queue_delayed_work(det_workqueue,
&exp_fn_ctrl->det_work,
msecs_to_jiffies(EXP_FN_DET_INTERVAL));
dev_dbg(dev, "%s: keep drm fhandler\n", __func__);
continue;
}
}
list_del(&exp_fhandler->link);
kfree(exp_fhandler);
continue;
}
dev_dbg(dev, "%s: calling remove func for handler: %d\n",
__func__, exp_fhandler->fn_type);
exp_fhandler->func_remove(rmi4_data);
/* need to restore status function on F34 removal */
if (exp_fhandler->fn_type == RMI_FW_UPDATER &&
exp_fhandler->func_status == rmi4_data->get_status) {
rmi4_data->get_status = synaptics_rmi4_f01_flashprog_status;
dev_info(dev,
"%s: using default status retrieval function\n",
__func__);
}
if (exp_fhandler->fn_type == RMI_DRM_FRAMEWORK) {
if (terminate) {
cancel_delayed_work_sync(&rmi4_data->exp_fn_ctrl.det_work);
flush_workqueue(det_workqueue);
i2c_set_clientdata(rmi4_data->i2c_client, NULL);
kfree(rmi4_data);
dev_info(dev, "%s: driver removed\n", __func__);
} else if (f34_inserted) {
synaptics_rmi4_resume(&(rmi4_data->i2c_client->dev));
dev_info(dev, "%s: drm panel ready\n", __func__);
dev_err(dev, "%s: touch_stopped=%d, flash_enabled=%d\n",
__func__,
atomic_read(&rmi4_data->touch_stopped),
rmi4_data->flash_enabled);
} else {
queue_delayed_work(det_workqueue,
&exp_fn_ctrl->det_work,
msecs_to_jiffies(EXP_FN_DET_INTERVAL));
dev_dbg(dev, "%s: keep drm fhandler\n", __func__);
continue;
}
}
list_del(&exp_fhandler->link);
kfree(exp_fhandler);
continue;
}
if (exp_fhandler->inserted == true)
/* postpone all handlers, except for RMI_DRM_FRAMEWORK */
/* until RMI_FW_UPDATER processed */
if (!f34_inserted &&
!(exp_fhandler->fn_type == RMI_FW_UPDATER ||
exp_fhandler->fn_type == RMI_DRM_FRAMEWORK)) {
dev_dbg(dev, "%s: hold handler %d until f34 inserted\n",
__func__, exp_fhandler->fn_type);
continue;
}
if (rmi4_data->in_bootloader &&
(exp_fhandler->mode == IC_MODE_UI))
continue;
state = synaptics_dsx_get_state_safe(rmi4_data);
dev_dbg(dev, "%s: current state: %s, in_bootloader: %s\n",
__func__, synaptics_dsx_state_name(state),
rmi4_data->in_bootloader ? "true" : "false");
if (exp_fhandler->mode == IC_MODE_UI) {
if (rmi4_data->in_bootloader) {
dev_err(dev, "%s: handler %d requires UI mode\n",
__func__, exp_fhandler->fn_type);
continue;
}
}
exp_fhandler->func_init(rmi4_data);
state = synaptics_dsx_get_state_safe(rmi4_data);
exp_fhandler->inserted = true;
dev_dbg(dev, "%s: handler %d inserted\n",
__func__, exp_fhandler->fn_type);
if (exp_fhandler->fn_type == RMI_F54 && rmi4_data->f54_data) {
int scan_failures = 0;
struct synaptics_rmi4_func_packet_regs *regs;
@ -6749,12 +6795,19 @@ static void synaptics_rmi4_detection_work(struct work_struct *work)
rmi = &(rmi4_data->rmi4_mod_info);
rmi4_data->in_bootloader = true;
synaptics_dsx_set_state_safe(rmi4_data, STATE_BL);
state = synaptics_dsx_get_state_safe(rmi4_data);
dev_dbg(dev, "%s: current state %s\n",
__func__, synaptics_dsx_state_name(state));
dev_info(dev, "%s: Product: %s is in bootloader mode\n",
__func__, rmi->product_id_string);
}
/* replace default status retrieval function */
rmi4_data->get_status = exp_fhandler->func_status;
dev_info(dev, "%s: using F34 status retrieval function\n", __func__);
/* allowing sufficient time for possible upgrade to start */
scheduled_delay = 3000;
}
if (exp_fhandler->fn_type == RMI_DRM_FRAMEWORK) {
@ -6768,12 +6821,14 @@ static void synaptics_rmi4_detection_work(struct work_struct *work)
exp_fhandler->func_init = NULL;
dev_dbg(dev, "%s: removing DRM\n", __func__);
/* allowing sufficient time for F34 to complete */
queue_delayed_work(det_workqueue,
&exp_fn_ctrl->det_work,
msecs_to_jiffies(5000));
scheduled_delay = 3000;
}
}
if (scheduled_delay)
queue_delayed_work(det_workqueue, &exp_fn_ctrl->det_work,
msecs_to_jiffies(scheduled_delay));
release_mutex:
mutex_unlock(&exp_fn_ctrl->list_mutex);