summaryrefslogtreecommitdiffstats
path: root/drivers/ata
diff options
context:
space:
mode:
authorBartosz Golaszewski <bgolaszewski@baylibre.com>2017-01-30 11:02:07 +0100
committerSekhar Nori <nsekhar@ti.com>2017-01-31 17:48:29 +0530
commitd3d557cf646c52add72d050790bdf41670c96bab (patch)
tree5140b65fefba9d172d1ddff342655c4835530cfc /drivers/ata
parentd436501e06792dd44101e0e45c32f6c1ea965acb (diff)
downloadlinux-stable-d3d557cf646c52add72d050790bdf41670c96bab.tar.gz
linux-stable-d3d557cf646c52add72d050790bdf41670c96bab.tar.bz2
linux-stable-d3d557cf646c52add72d050790bdf41670c96bab.zip
sata: ahci-da850: add a workaround for controller instability
We have a use case with the da850 SATA controller where at PLL0 frequency of 456MHz (needed to properly service the LCD controller) the chip becomes unstable and the hardreset operation is ignored the first time 50% of times. The sata core driver already retries to resume the link because some controllers ignore writes to the SControl register, but just retrying the resume operation doesn't work - we need to issue he phy/wake reset again to make it work. Reimplement ahci_hardreset() in the driver and poke the controller a couple times before really giving up. Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com> Acked-by: Tejun Heo <tj@kernel.org> Signed-off-by: Sekhar Nori <nsekhar@ti.com>
Diffstat (limited to 'drivers/ata')
-rw-r--r--drivers/ata/ahci_da850.c28
1 files changed, 27 insertions, 1 deletions
diff --git a/drivers/ata/ahci_da850.c b/drivers/ata/ahci_da850.c
index 84c7805c0247..d65088a2fd5f 100644
--- a/drivers/ata/ahci_da850.c
+++ b/drivers/ata/ahci_da850.c
@@ -16,7 +16,8 @@
#include <linux/ahci_platform.h>
#include "ahci.h"
-#define DRV_NAME "ahci_da850"
+#define DRV_NAME "ahci_da850"
+#define HARDRESET_RETRIES 5
/* SATA PHY Control Register offset from AHCI base */
#define SATA_P0PHYCR_REG 0x178
@@ -76,6 +77,29 @@ static int ahci_da850_softreset(struct ata_link *link,
return ret;
}
+static int ahci_da850_hardreset(struct ata_link *link,
+ unsigned int *class, unsigned long deadline)
+{
+ int ret, retry = HARDRESET_RETRIES;
+ bool online;
+
+ /*
+ * In order to correctly service the LCD controller of the da850 SoC,
+ * we increased the PLL0 frequency to 456MHz from the default 300MHz.
+ *
+ * This made the SATA controller unstable and the hardreset operation
+ * does not always succeed the first time. Before really giving up to
+ * bring up the link, retry the reset a couple times.
+ */
+ do {
+ ret = ahci_do_hardreset(link, class, deadline, &online);
+ if (online)
+ return ret;
+ } while (retry--);
+
+ return ret;
+}
+
static struct ata_port_operations ahci_da850_port_ops = {
.inherits = &ahci_platform_ops,
.softreset = ahci_da850_softreset,
@@ -83,6 +107,8 @@ static struct ata_port_operations ahci_da850_port_ops = {
* No need to override .pmp_softreset - it's only used for actual
* PMP-enabled ports.
*/
+ .hardreset = ahci_da850_hardreset,
+ .pmp_hardreset = ahci_da850_hardreset,
};
static const struct ata_port_info ahci_da850_port_info = {