aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/ata')
-rw-r--r--drivers/ata/ahci_xgene.c48
1 files changed, 34 insertions, 14 deletions
diff --git a/drivers/ata/ahci_xgene.c b/drivers/ata/ahci_xgene.c
index 37501fd0973d..f03aab187f4d 100644
--- a/drivers/ata/ahci_xgene.c
+++ b/drivers/ata/ahci_xgene.c
@@ -78,6 +78,9 @@
78#define CFG_MEM_RAM_SHUTDOWN 0x00000070 78#define CFG_MEM_RAM_SHUTDOWN 0x00000070
79#define BLOCK_MEM_RDY 0x00000074 79#define BLOCK_MEM_RDY 0x00000074
80 80
81/* Max retry for link down */
82#define MAX_LINK_DOWN_RETRY 3
83
81struct xgene_ahci_context { 84struct xgene_ahci_context {
82 struct ahci_host_priv *hpriv; 85 struct ahci_host_priv *hpriv;
83 struct device *dev; 86 struct device *dev;
@@ -237,8 +240,11 @@ static void xgene_ahci_set_phy_cfg(struct xgene_ahci_context *ctx, int channel)
237 * and Gen1 (1.5Gbps). Otherwise during long IO stress test, the PHY will 240 * and Gen1 (1.5Gbps). Otherwise during long IO stress test, the PHY will
238 * report disparity error and etc. In addition, during COMRESET, there can 241 * report disparity error and etc. In addition, during COMRESET, there can
239 * be error reported in the register PORT_SCR_ERR. For SERR_DISPARITY and 242 * be error reported in the register PORT_SCR_ERR. For SERR_DISPARITY and
240 * SERR_10B_8B_ERR, the PHY receiver line must be reseted. The following 243 * SERR_10B_8B_ERR, the PHY receiver line must be reseted. Also during long
241 * algorithm is followed to proper configure the hardware PHY during COMRESET: 244 * reboot cycle regression, sometimes the PHY reports link down even if the
245 * device is present because of speed negotiation failure. so need to retry
246 * the COMRESET to get the link up. The following algorithm is followed to
247 * proper configure the hardware PHY during COMRESET:
242 * 248 *
243 * Alg Part 1: 249 * Alg Part 1:
244 * 1. Start the PHY at Gen3 speed (default setting) 250 * 1. Start the PHY at Gen3 speed (default setting)
@@ -254,9 +260,15 @@ static void xgene_ahci_set_phy_cfg(struct xgene_ahci_context *ctx, int channel)
254 * Alg Part 2: 260 * Alg Part 2:
255 * 1. On link up, if there are any SERR_DISPARITY and SERR_10B_8B_ERR error 261 * 1. On link up, if there are any SERR_DISPARITY and SERR_10B_8B_ERR error
256 * reported in the register PORT_SCR_ERR, then reset the PHY receiver line 262 * reported in the register PORT_SCR_ERR, then reset the PHY receiver line
257 * 2. Go to Alg Part 3 263 * 2. Go to Alg Part 4
258 * 264 *
259 * Alg Part 3: 265 * Alg Part 3:
266 * 1. Check the PORT_SCR_STAT to see whether device presence detected but PHY
267 * communication establishment failed and maximum link down attempts are
268 * less than Max attempts 3 then goto Alg Part 1.
269 * 2. Go to Alg Part 4.
270 *
271 * Alg Part 4:
260 * 1. Clear any pending from register PORT_SCR_ERR. 272 * 1. Clear any pending from register PORT_SCR_ERR.
261 * 273 *
262 * NOTE: For the initial version, we will NOT support Gen1/Gen2. In addition 274 * NOTE: For the initial version, we will NOT support Gen1/Gen2. In addition
@@ -275,19 +287,27 @@ static int xgene_ahci_do_hardreset(struct ata_link *link,
275 u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG; 287 u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
276 void __iomem *port_mmio = ahci_port_base(ap); 288 void __iomem *port_mmio = ahci_port_base(ap);
277 struct ata_taskfile tf; 289 struct ata_taskfile tf;
290 int link_down_retry = 0;
278 int rc; 291 int rc;
279 u32 val; 292 u32 val, sstatus;
280 293
281 /* clear D2H reception area to properly wait for D2H FIS */ 294 do {
282 ata_tf_init(link->device, &tf); 295 /* clear D2H reception area to properly wait for D2H FIS */
283 tf.command = ATA_BUSY; 296 ata_tf_init(link->device, &tf);
284 ata_tf_to_fis(&tf, 0, 0, d2h_fis); 297 tf.command = ATA_BUSY;
285 rc = sata_link_hardreset(link, timing, deadline, online, 298 ata_tf_to_fis(&tf, 0, 0, d2h_fis);
299 rc = sata_link_hardreset(link, timing, deadline, online,
286 ahci_check_ready); 300 ahci_check_ready);
287 301 if (*online) {
288 val = readl(port_mmio + PORT_SCR_ERR); 302 val = readl(port_mmio + PORT_SCR_ERR);
289 if (val & (SERR_DISPARITY | SERR_10B_8B_ERR)) 303 if (val & (SERR_DISPARITY | SERR_10B_8B_ERR))
290 dev_warn(ctx->dev, "link has error\n"); 304 dev_warn(ctx->dev, "link has error\n");
305 break;
306 }
307
308 sata_scr_read(link, SCR_STATUS, &sstatus);
309 } while (link_down_retry++ < MAX_LINK_DOWN_RETRY &&
310 (sstatus & 0xff) == 0x1);
291 311
292 /* clear all errors if any pending */ 312 /* clear all errors if any pending */
293 val = readl(port_mmio + PORT_SCR_ERR); 313 val = readl(port_mmio + PORT_SCR_ERR);