diff options
author | Djamil Elaidi <d-elaidi@ti.com> | 2011-06-28 11:25:12 +0200 |
---|---|---|
committer | Sebastien Jan <s-jan@ti.com> | 2011-07-05 14:29:52 +0200 |
commit | 7d16749e4d0366c21e04a5a50e6c8e06b9e4ad0f (patch) | |
tree | b0515561ad6331644c7f9666cd0fb03c50bcd2be /drivers | |
parent | 7b3ce51ea4f579f1f352e437bdc88494a6fdab54 (diff) |
OMAP4: HSI: SW WA for HSR in dead state after SW reset with pending errors
SW WA for HSI-C1BUG00088 "OMAP4430 HSI : No recovery from SW reset
under specific circumstances"
Description of issue:
It seems that in certain cases after some errors are detected by
HSR (frame timeout and/or tailing bit error and/or overrun), writing
the SW reset bit (SYSCONFIG.SOFTERESET to 1) may put the HSI in a
"dead" state in which it does not answer anymore to L4 OCP commands.
It seems that in certain cases after some errors are detected by HSR
(frame timeout and/or tailing bit error and/or overrun), writing the
SW reset bit (SYSCONFIG.SOFTERESET to 1) may put the HSI in a "dead"
state in which it does not answer anymore to L4 OCP commands.
Workaround is:
* Set HSR_MODE_P1.MODE_VAL = sleep and HSR_MODE_P2.MODE_VAL = sleep
* Acknowledge all errors (do not care if there is any) by writing
HSR_ERRORACK_P1 and HSR_ERRORACK_P2
* Set SW reset
HW fix will be available for OMAP5430
Other changes:
* Removed write to Read only register HSI_HSR_BREAK_REG
Change-Id: I023d0fc8656808a8c294d7cfaec1bf3cb46da93f
Signed-off-by: Djamil Elaidi <d-elaidi@ti.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/staging/omap_hsi/hsi_driver.c | 24 | ||||
-rw-r--r-- | drivers/staging/omap_hsi/hsi_driver_if.c | 2 | ||||
-rw-r--r-- | drivers/staging/omap_hsi/hsi_driver_int.c | 1 |
3 files changed, 24 insertions, 3 deletions
diff --git a/drivers/staging/omap_hsi/hsi_driver.c b/drivers/staging/omap_hsi/hsi_driver.c index 8912dc0fc346..06368ea31886 100644 --- a/drivers/staging/omap_hsi/hsi_driver.c +++ b/drivers/staging/omap_hsi/hsi_driver.c @@ -272,12 +272,27 @@ void hsi_set_pm_force_hsi_on(struct hsi_dev *hsi_ctrl) /* HSI_TODO : use the HWMOD API : omap_hwmod_set_slave_idlemode() */ } +/** +* hsi_softreset - Force a SW RESET of HSI (core + DMA) +* +* @hsi_ctrl - reference to the hsi controller to be reset. +* +*/ int hsi_softreset(struct hsi_dev *hsi_ctrl) { unsigned int ind = 0; + unsigned int port; void __iomem *base = hsi_ctrl->base; u32 status; + /* SW WA for HSI-C1BUG00088 OMAP4430 HSI : No recovery from SW reset */ + /* under specific circumstances */ + for (port = 1; port <= hsi_ctrl->max_p; port++) { + hsi_outl_and(HSI_HSR_MODE_MODE_VAL_SLEEP, base, + HSI_HSR_MODE_REG(port)); + hsi_outl(HSI_HSR_ERROR_ALL, base, HSI_HSR_ERRORACK_REG(port)); + } + /* Reseting HSI Block */ hsi_outl_or(HSI_SOFTRESET, base, HSI_SYS_SYSCONFIG_REG); do { @@ -405,6 +420,13 @@ static int hsi_port_channels_reset(struct hsi_port *port) return 0; } +/** +* hsi_softreset_driver - Must be called following HSI SW RESET, to re-align +* variable states with new HW state. +* +* @hsi_ctrl - reference to the hsi controller to be re-aligned. +* +*/ void hsi_softreset_driver(struct hsi_dev *hsi_ctrl) { struct platform_device *pd = to_platform_device(hsi_ctrl->dev); @@ -1000,7 +1022,7 @@ int hsi_runtime_suspend(struct device *dev) HSI_HSR_MODE_REG(port)); } - /* HSI is going to INA/RET/OFF, it needs IO wakeup mechanism enabled */ + /* HSI is going to IDLE, it needs IO wakeup mechanism enabled */ if (device_may_wakeup(dev)) pdata->wakeup_enable(0); else diff --git a/drivers/staging/omap_hsi/hsi_driver_if.c b/drivers/staging/omap_hsi/hsi_driver_if.c index 6a106e71922c..929bb938b914 100644 --- a/drivers/staging/omap_hsi/hsi_driver_if.c +++ b/drivers/staging/omap_hsi/hsi_driver_if.c @@ -676,7 +676,7 @@ EXPORT_SYMBOL(hsi_unpoll); * @command - HSI I/O control command * @arg - parameter associated to the control command. NULL, if no parameter. * - * Return 0 on sucess, a negative value on failure. + * Return 0 on success, a negative value on failure. * */ int hsi_ioctl(struct hsi_device *dev, unsigned int command, void *arg) diff --git a/drivers/staging/omap_hsi/hsi_driver_int.c b/drivers/staging/omap_hsi/hsi_driver_int.c index 1a6117c4ed06..94d859ab3f2c 100644 --- a/drivers/staging/omap_hsi/hsi_driver_int.c +++ b/drivers/staging/omap_hsi/hsi_driver_int.c @@ -562,7 +562,6 @@ static u32 hsi_driver_int_proc(struct hsi_port *pport, if (status_reg & HSI_BREAKDETECTED) { dev_info(hsi_ctrl->dev, "Hardware BREAK on port %d\n", port); - hsi_outl(0, base, HSI_HSR_BREAK_REG(port)); spin_unlock(&hsi_ctrl->lock); hsi_port_event_handler(pport, HSI_EVENT_BREAK_DETECTED, NULL); spin_lock(&hsi_ctrl->lock); |