|
@@ -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 = {
|