diff options
author | Jeff Garzik <jgarzik@pobox.com> | 2005-11-13 17:47:51 -0500 |
---|---|---|
committer | Jeff Garzik <jgarzik@pobox.com> | 2005-11-13 17:47:51 -0500 |
commit | c9d39130123238ac18478a42e25cb7996eacfcc0 (patch) | |
tree | 7aaae5b14ebfb42f160fe3035ea28f1ba3475106 /drivers | |
parent | 2a47ce06d534692f9bd2bf4e90a20fc9b1054c39 (diff) |
[libata sata_mv] fix tons of 50XX bugs
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/scsi/sata_mv.c | 301 |
1 files changed, 252 insertions, 49 deletions
diff --git a/drivers/scsi/sata_mv.c b/drivers/scsi/sata_mv.c index 5defd056fe1c..722ab537b7a6 100644 --- a/drivers/scsi/sata_mv.c +++ b/drivers/scsi/sata_mv.c | |||
@@ -158,6 +158,9 @@ enum { | |||
158 | PHY_MODE3 = 0x310, | 158 | PHY_MODE3 = 0x310, |
159 | PHY_MODE4 = 0x314, | 159 | PHY_MODE4 = 0x314, |
160 | PHY_MODE2 = 0x330, | 160 | PHY_MODE2 = 0x330, |
161 | MV5_PHY_MODE = 0x74, | ||
162 | MV5_LT_MODE = 0x30, | ||
163 | MV5_PHY_CTL = 0x0C, | ||
161 | SATA_INTERFACE_CTL = 0x050, | 164 | SATA_INTERFACE_CTL = 0x050, |
162 | 165 | ||
163 | MV_M2_PREAMP_MASK = 0x7e0, | 166 | MV_M2_PREAMP_MASK = 0x7e0, |
@@ -214,6 +217,7 @@ enum { | |||
214 | EDMA_DS = (1 << 1), | 217 | EDMA_DS = (1 << 1), |
215 | ATA_RST = (1 << 2), | 218 | ATA_RST = (1 << 2), |
216 | 219 | ||
220 | EDMA_IORDY_TMOUT = 0x34, | ||
217 | EDMA_ARB_CFG = 0x38, | 221 | EDMA_ARB_CFG = 0x38, |
218 | 222 | ||
219 | /* Host private flags (hp_flags) */ | 223 | /* Host private flags (hp_flags) */ |
@@ -229,6 +233,7 @@ enum { | |||
229 | MV_PP_FLAG_EDMA_DS_ACT = (1 << 1), | 233 | MV_PP_FLAG_EDMA_DS_ACT = (1 << 1), |
230 | }; | 234 | }; |
231 | 235 | ||
236 | #define IS_50XX(hpriv) ((hpriv)->hp_flags & MV_HP_50XX) | ||
232 | #define IS_60XX(hpriv) (((hpriv)->hp_flags & MV_HP_50XX) == 0) | 237 | #define IS_60XX(hpriv) (((hpriv)->hp_flags & MV_HP_50XX) == 0) |
233 | 238 | ||
234 | enum { | 239 | enum { |
@@ -298,7 +303,8 @@ struct mv_hw_ops { | |||
298 | void (*enable_leds)(struct mv_host_priv *hpriv, void __iomem *mmio); | 303 | void (*enable_leds)(struct mv_host_priv *hpriv, void __iomem *mmio); |
299 | void (*read_preamp)(struct mv_host_priv *hpriv, int idx, | 304 | void (*read_preamp)(struct mv_host_priv *hpriv, int idx, |
300 | void __iomem *mmio); | 305 | void __iomem *mmio); |
301 | int (*reset_hc)(struct mv_host_priv *hpriv, void __iomem *mmio); | 306 | int (*reset_hc)(struct mv_host_priv *hpriv, void __iomem *mmio, |
307 | unsigned int n_hc); | ||
302 | void (*reset_flash)(struct mv_host_priv *hpriv, void __iomem *mmio); | 308 | void (*reset_flash)(struct mv_host_priv *hpriv, void __iomem *mmio); |
303 | void (*reset_bus)(struct pci_dev *pdev, void __iomem *mmio); | 309 | void (*reset_bus)(struct pci_dev *pdev, void __iomem *mmio); |
304 | }; | 310 | }; |
@@ -312,6 +318,8 @@ struct mv_host_priv { | |||
312 | static void mv_irq_clear(struct ata_port *ap); | 318 | static void mv_irq_clear(struct ata_port *ap); |
313 | static u32 mv_scr_read(struct ata_port *ap, unsigned int sc_reg_in); | 319 | static u32 mv_scr_read(struct ata_port *ap, unsigned int sc_reg_in); |
314 | static void mv_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val); | 320 | static void mv_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val); |
321 | static u32 mv5_scr_read(struct ata_port *ap, unsigned int sc_reg_in); | ||
322 | static void mv5_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val); | ||
315 | static void mv_phy_reset(struct ata_port *ap); | 323 | static void mv_phy_reset(struct ata_port *ap); |
316 | static void mv_host_stop(struct ata_host_set *host_set); | 324 | static void mv_host_stop(struct ata_host_set *host_set); |
317 | static int mv_port_start(struct ata_port *ap); | 325 | static int mv_port_start(struct ata_port *ap); |
@@ -328,7 +336,8 @@ static void mv5_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio, | |||
328 | static void mv5_enable_leds(struct mv_host_priv *hpriv, void __iomem *mmio); | 336 | static void mv5_enable_leds(struct mv_host_priv *hpriv, void __iomem *mmio); |
329 | static void mv5_read_preamp(struct mv_host_priv *hpriv, int idx, | 337 | static void mv5_read_preamp(struct mv_host_priv *hpriv, int idx, |
330 | void __iomem *mmio); | 338 | void __iomem *mmio); |
331 | static int mv5_reset_hc(struct mv_host_priv *hpriv, void __iomem *mmio); | 339 | static int mv5_reset_hc(struct mv_host_priv *hpriv, void __iomem *mmio, |
340 | unsigned int n_hc); | ||
332 | static void mv5_reset_flash(struct mv_host_priv *hpriv, void __iomem *mmio); | 341 | static void mv5_reset_flash(struct mv_host_priv *hpriv, void __iomem *mmio); |
333 | static void mv5_reset_bus(struct pci_dev *pdev, void __iomem *mmio); | 342 | static void mv5_reset_bus(struct pci_dev *pdev, void __iomem *mmio); |
334 | 343 | ||
@@ -337,9 +346,13 @@ static void mv6_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio, | |||
337 | static void mv6_enable_leds(struct mv_host_priv *hpriv, void __iomem *mmio); | 346 | static void mv6_enable_leds(struct mv_host_priv *hpriv, void __iomem *mmio); |
338 | static void mv6_read_preamp(struct mv_host_priv *hpriv, int idx, | 347 | static void mv6_read_preamp(struct mv_host_priv *hpriv, int idx, |
339 | void __iomem *mmio); | 348 | void __iomem *mmio); |
340 | static int mv6_reset_hc(struct mv_host_priv *hpriv, void __iomem *mmio); | 349 | static int mv6_reset_hc(struct mv_host_priv *hpriv, void __iomem *mmio, |
350 | unsigned int n_hc); | ||
341 | static void mv6_reset_flash(struct mv_host_priv *hpriv, void __iomem *mmio); | 351 | static void mv6_reset_flash(struct mv_host_priv *hpriv, void __iomem *mmio); |
342 | static void mv_reset_pci_bus(struct pci_dev *pdev, void __iomem *mmio); | 352 | static void mv_reset_pci_bus(struct pci_dev *pdev, void __iomem *mmio); |
353 | static void mv_channel_reset(struct mv_host_priv *hpriv, void __iomem *mmio, | ||
354 | unsigned int port_no); | ||
355 | static void mv_stop_and_reset(struct ata_port *ap); | ||
343 | 356 | ||
344 | static struct scsi_host_template mv_sht = { | 357 | static struct scsi_host_template mv_sht = { |
345 | .module = THIS_MODULE, | 358 | .module = THIS_MODULE, |
@@ -361,7 +374,34 @@ static struct scsi_host_template mv_sht = { | |||
361 | .ordered_flush = 1, | 374 | .ordered_flush = 1, |
362 | }; | 375 | }; |
363 | 376 | ||
364 | static const struct ata_port_operations mv_ops = { | 377 | static const struct ata_port_operations mv5_ops = { |
378 | .port_disable = ata_port_disable, | ||
379 | |||
380 | .tf_load = ata_tf_load, | ||
381 | .tf_read = ata_tf_read, | ||
382 | .check_status = ata_check_status, | ||
383 | .exec_command = ata_exec_command, | ||
384 | .dev_select = ata_std_dev_select, | ||
385 | |||
386 | .phy_reset = mv_phy_reset, | ||
387 | |||
388 | .qc_prep = mv_qc_prep, | ||
389 | .qc_issue = mv_qc_issue, | ||
390 | |||
391 | .eng_timeout = mv_eng_timeout, | ||
392 | |||
393 | .irq_handler = mv_interrupt, | ||
394 | .irq_clear = mv_irq_clear, | ||
395 | |||
396 | .scr_read = mv5_scr_read, | ||
397 | .scr_write = mv5_scr_write, | ||
398 | |||
399 | .port_start = mv_port_start, | ||
400 | .port_stop = mv_port_stop, | ||
401 | .host_stop = mv_host_stop, | ||
402 | }; | ||
403 | |||
404 | static const struct ata_port_operations mv6_ops = { | ||
365 | .port_disable = ata_port_disable, | 405 | .port_disable = ata_port_disable, |
366 | 406 | ||
367 | .tf_load = ata_tf_load, | 407 | .tf_load = ata_tf_load, |
@@ -393,29 +433,29 @@ static struct ata_port_info mv_port_info[] = { | |||
393 | .sht = &mv_sht, | 433 | .sht = &mv_sht, |
394 | .host_flags = MV_COMMON_FLAGS, | 434 | .host_flags = MV_COMMON_FLAGS, |
395 | .pio_mask = 0x1f, /* pio0-4 */ | 435 | .pio_mask = 0x1f, /* pio0-4 */ |
396 | .udma_mask = 0, /* 0x7f (udma0-6 disabled for now) */ | 436 | .udma_mask = 0x7f, /* udma0-6 */ |
397 | .port_ops = &mv_ops, | 437 | .port_ops = &mv5_ops, |
398 | }, | 438 | }, |
399 | { /* chip_508x */ | 439 | { /* chip_508x */ |
400 | .sht = &mv_sht, | 440 | .sht = &mv_sht, |
401 | .host_flags = (MV_COMMON_FLAGS | MV_FLAG_DUAL_HC), | 441 | .host_flags = (MV_COMMON_FLAGS | MV_FLAG_DUAL_HC), |
402 | .pio_mask = 0x1f, /* pio0-4 */ | 442 | .pio_mask = 0x1f, /* pio0-4 */ |
403 | .udma_mask = 0, /* 0x7f (udma0-6 disabled for now) */ | 443 | .udma_mask = 0x7f, /* udma0-6 */ |
404 | .port_ops = &mv_ops, | 444 | .port_ops = &mv5_ops, |
405 | }, | 445 | }, |
406 | { /* chip_5080 */ | 446 | { /* chip_5080 */ |
407 | .sht = &mv_sht, | 447 | .sht = &mv_sht, |
408 | .host_flags = (MV_COMMON_FLAGS | MV_FLAG_DUAL_HC), | 448 | .host_flags = (MV_COMMON_FLAGS | MV_FLAG_DUAL_HC), |
409 | .pio_mask = 0x1f, /* pio0-4 */ | 449 | .pio_mask = 0x1f, /* pio0-4 */ |
410 | .udma_mask = 0, /* 0x7f (udma0-6 disabled for now) */ | 450 | .udma_mask = 0x7f, /* udma0-6 */ |
411 | .port_ops = &mv_ops, | 451 | .port_ops = &mv5_ops, |
412 | }, | 452 | }, |
413 | { /* chip_604x */ | 453 | { /* chip_604x */ |
414 | .sht = &mv_sht, | 454 | .sht = &mv_sht, |
415 | .host_flags = (MV_COMMON_FLAGS | MV_6XXX_FLAGS), | 455 | .host_flags = (MV_COMMON_FLAGS | MV_6XXX_FLAGS), |
416 | .pio_mask = 0x1f, /* pio0-4 */ | 456 | .pio_mask = 0x1f, /* pio0-4 */ |
417 | .udma_mask = 0x7f, /* udma0-6 */ | 457 | .udma_mask = 0x7f, /* udma0-6 */ |
418 | .port_ops = &mv_ops, | 458 | .port_ops = &mv6_ops, |
419 | }, | 459 | }, |
420 | { /* chip_608x */ | 460 | { /* chip_608x */ |
421 | .sht = &mv_sht, | 461 | .sht = &mv_sht, |
@@ -423,17 +463,15 @@ static struct ata_port_info mv_port_info[] = { | |||
423 | MV_FLAG_DUAL_HC), | 463 | MV_FLAG_DUAL_HC), |
424 | .pio_mask = 0x1f, /* pio0-4 */ | 464 | .pio_mask = 0x1f, /* pio0-4 */ |
425 | .udma_mask = 0x7f, /* udma0-6 */ | 465 | .udma_mask = 0x7f, /* udma0-6 */ |
426 | .port_ops = &mv_ops, | 466 | .port_ops = &mv6_ops, |
427 | }, | 467 | }, |
428 | }; | 468 | }; |
429 | 469 | ||
430 | static const struct pci_device_id mv_pci_tbl[] = { | 470 | static const struct pci_device_id mv_pci_tbl[] = { |
431 | #if 0 /* unusably broken right now */ | ||
432 | {PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x5040), 0, 0, chip_504x}, | 471 | {PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x5040), 0, 0, chip_504x}, |
433 | {PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x5041), 0, 0, chip_504x}, | 472 | {PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x5041), 0, 0, chip_504x}, |
434 | {PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x5080), 0, 0, chip_5080}, | 473 | {PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x5080), 0, 0, chip_5080}, |
435 | {PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x5081), 0, 0, chip_508x}, | 474 | {PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x5081), 0, 0, chip_508x}, |
436 | #endif | ||
437 | 475 | ||
438 | {PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x6040), 0, 0, chip_604x}, | 476 | {PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x6040), 0, 0, chip_604x}, |
439 | {PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x6041), 0, 0, chip_604x}, | 477 | {PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x6041), 0, 0, chip_604x}, |
@@ -484,11 +522,27 @@ static inline void __iomem *mv_hc_base(void __iomem *base, unsigned int hc) | |||
484 | return (base + MV_SATAHC0_REG_BASE + (hc * MV_SATAHC_REG_SZ)); | 522 | return (base + MV_SATAHC0_REG_BASE + (hc * MV_SATAHC_REG_SZ)); |
485 | } | 523 | } |
486 | 524 | ||
525 | static inline unsigned int mv_hc_from_port(unsigned int port) | ||
526 | { | ||
527 | return port >> MV_PORT_HC_SHIFT; | ||
528 | } | ||
529 | |||
530 | static inline unsigned int mv_hardport_from_port(unsigned int port) | ||
531 | { | ||
532 | return port & MV_PORT_MASK; | ||
533 | } | ||
534 | |||
535 | static inline void __iomem *mv_hc_base_from_port(void __iomem *base, | ||
536 | unsigned int port) | ||
537 | { | ||
538 | return mv_hc_base(base, mv_hc_from_port(port)); | ||
539 | } | ||
540 | |||
487 | static inline void __iomem *mv_port_base(void __iomem *base, unsigned int port) | 541 | static inline void __iomem *mv_port_base(void __iomem *base, unsigned int port) |
488 | { | 542 | { |
489 | return (mv_hc_base(base, port >> MV_PORT_HC_SHIFT) + | 543 | return mv_hc_base_from_port(base, port) + |
490 | MV_SATAHC_ARBTR_REG_SZ + | 544 | MV_SATAHC_ARBTR_REG_SZ + |
491 | ((port & MV_PORT_MASK) * MV_PORT_REG_SZ)); | 545 | (mv_hardport_from_port(port) * MV_PORT_REG_SZ); |
492 | } | 546 | } |
493 | 547 | ||
494 | static inline void __iomem *mv_ap_base(struct ata_port *ap) | 548 | static inline void __iomem *mv_ap_base(struct ata_port *ap) |
@@ -1089,7 +1143,7 @@ static void mv_err_intr(struct ata_port *ap) | |||
1089 | 1143 | ||
1090 | /* check for fatal here and recover if needed */ | 1144 | /* check for fatal here and recover if needed */ |
1091 | if (EDMA_ERR_FATAL & edma_err_cause) { | 1145 | if (EDMA_ERR_FATAL & edma_err_cause) { |
1092 | mv_phy_reset(ap); | 1146 | mv_stop_and_reset(ap); |
1093 | } | 1147 | } |
1094 | } | 1148 | } |
1095 | 1149 | ||
@@ -1236,6 +1290,51 @@ static irqreturn_t mv_interrupt(int irq, void *dev_instance, | |||
1236 | return IRQ_RETVAL(handled); | 1290 | return IRQ_RETVAL(handled); |
1237 | } | 1291 | } |
1238 | 1292 | ||
1293 | static void __iomem *mv5_phy_base(void __iomem *mmio, unsigned int port) | ||
1294 | { | ||
1295 | void __iomem *hc_mmio = mv_hc_base_from_port(mmio, port); | ||
1296 | unsigned long ofs = (mv_hardport_from_port(port) + 1) * 0x100UL; | ||
1297 | |||
1298 | return hc_mmio + ofs; | ||
1299 | } | ||
1300 | |||
1301 | static unsigned int mv5_scr_offset(unsigned int sc_reg_in) | ||
1302 | { | ||
1303 | unsigned int ofs; | ||
1304 | |||
1305 | switch (sc_reg_in) { | ||
1306 | case SCR_STATUS: | ||
1307 | case SCR_ERROR: | ||
1308 | case SCR_CONTROL: | ||
1309 | ofs = sc_reg_in * sizeof(u32); | ||
1310 | break; | ||
1311 | default: | ||
1312 | ofs = 0xffffffffU; | ||
1313 | break; | ||
1314 | } | ||
1315 | return ofs; | ||
1316 | } | ||
1317 | |||
1318 | static u32 mv5_scr_read(struct ata_port *ap, unsigned int sc_reg_in) | ||
1319 | { | ||
1320 | void __iomem *mmio = mv5_phy_base(ap->host_set->mmio_base, ap->port_no); | ||
1321 | unsigned int ofs = mv5_scr_offset(sc_reg_in); | ||
1322 | |||
1323 | if (ofs != 0xffffffffU) | ||
1324 | return readl(mmio + ofs); | ||
1325 | else | ||
1326 | return (u32) ofs; | ||
1327 | } | ||
1328 | |||
1329 | static void mv5_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val) | ||
1330 | { | ||
1331 | void __iomem *mmio = mv5_phy_base(ap->host_set->mmio_base, ap->port_no); | ||
1332 | unsigned int ofs = mv5_scr_offset(sc_reg_in); | ||
1333 | |||
1334 | if (ofs != 0xffffffffU) | ||
1335 | writelfl(val, mmio + ofs); | ||
1336 | } | ||
1337 | |||
1239 | static void mv5_reset_bus(struct pci_dev *pdev, void __iomem *mmio) | 1338 | static void mv5_reset_bus(struct pci_dev *pdev, void __iomem *mmio) |
1240 | { | 1339 | { |
1241 | u8 rev_id; | 1340 | u8 rev_id; |
@@ -1262,7 +1361,13 @@ static void mv5_reset_flash(struct mv_host_priv *hpriv, void __iomem *mmio) | |||
1262 | static void mv5_read_preamp(struct mv_host_priv *hpriv, int idx, | 1361 | static void mv5_read_preamp(struct mv_host_priv *hpriv, int idx, |
1263 | void __iomem *mmio) | 1362 | void __iomem *mmio) |
1264 | { | 1363 | { |
1265 | /* FIXME */ | 1364 | void __iomem *phy_mmio = mv5_phy_base(mmio, idx); |
1365 | u32 tmp; | ||
1366 | |||
1367 | tmp = readl(phy_mmio + MV5_PHY_MODE); | ||
1368 | |||
1369 | hpriv->signal[idx].pre = tmp & 0x1800; /* bits 12:11 */ | ||
1370 | hpriv->signal[idx].amps = tmp & 0xe0; /* bits 7:5 */ | ||
1266 | } | 1371 | } |
1267 | 1372 | ||
1268 | static void mv5_enable_leds(struct mv_host_priv *hpriv, void __iomem *mmio) | 1373 | static void mv5_enable_leds(struct mv_host_priv *hpriv, void __iomem *mmio) |
@@ -1281,13 +1386,90 @@ static void mv5_enable_leds(struct mv_host_priv *hpriv, void __iomem *mmio) | |||
1281 | static void mv5_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio, | 1386 | static void mv5_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio, |
1282 | unsigned int port) | 1387 | unsigned int port) |
1283 | { | 1388 | { |
1284 | /* FIXME */ | 1389 | void __iomem *phy_mmio = mv5_phy_base(mmio, port); |
1390 | const u32 mask = (1<<12) | (1<<11) | (1<<7) | (1<<6) | (1<<5); | ||
1391 | u32 tmp; | ||
1392 | int fix_apm_sq = (hpriv->hp_flags & MV_HP_ERRATA_50XXB0); | ||
1393 | |||
1394 | if (fix_apm_sq) { | ||
1395 | tmp = readl(phy_mmio + MV5_LT_MODE); | ||
1396 | tmp |= (1 << 19); | ||
1397 | writel(tmp, phy_mmio + MV5_LT_MODE); | ||
1398 | |||
1399 | tmp = readl(phy_mmio + MV5_PHY_CTL); | ||
1400 | tmp &= ~0x3; | ||
1401 | tmp |= 0x1; | ||
1402 | writel(tmp, phy_mmio + MV5_PHY_CTL); | ||
1403 | } | ||
1404 | |||
1405 | tmp = readl(phy_mmio + MV5_PHY_MODE); | ||
1406 | tmp &= ~mask; | ||
1407 | tmp |= hpriv->signal[port].pre; | ||
1408 | tmp |= hpriv->signal[port].amps; | ||
1409 | writel(tmp, phy_mmio + MV5_PHY_MODE); | ||
1410 | } | ||
1411 | |||
1412 | |||
1413 | #undef ZERO | ||
1414 | #define ZERO(reg) writel(0, port_mmio + (reg)) | ||
1415 | static void mv5_reset_hc_port(struct mv_host_priv *hpriv, void __iomem *mmio, | ||
1416 | unsigned int port) | ||
1417 | { | ||
1418 | void __iomem *port_mmio = mv_port_base(mmio, port); | ||
1419 | |||
1420 | writelfl(EDMA_DS, port_mmio + EDMA_CMD_OFS); | ||
1421 | |||
1422 | mv_channel_reset(hpriv, mmio, port); | ||
1423 | |||
1424 | ZERO(0x028); /* command */ | ||
1425 | writel(0x11f, port_mmio + EDMA_CFG_OFS); | ||
1426 | ZERO(0x004); /* timer */ | ||
1427 | ZERO(0x008); /* irq err cause */ | ||
1428 | ZERO(0x00c); /* irq err mask */ | ||
1429 | ZERO(0x010); /* rq bah */ | ||
1430 | ZERO(0x014); /* rq inp */ | ||
1431 | ZERO(0x018); /* rq outp */ | ||
1432 | ZERO(0x01c); /* respq bah */ | ||
1433 | ZERO(0x024); /* respq outp */ | ||
1434 | ZERO(0x020); /* respq inp */ | ||
1435 | ZERO(0x02c); /* test control */ | ||
1436 | writel(0xbc, port_mmio + EDMA_IORDY_TMOUT); | ||
1285 | } | 1437 | } |
1438 | #undef ZERO | ||
1286 | 1439 | ||
1287 | static int mv5_reset_hc(struct mv_host_priv *hpriv, void __iomem *mmio) | 1440 | #define ZERO(reg) writel(0, hc_mmio + (reg)) |
1441 | static void mv5_reset_one_hc(struct mv_host_priv *hpriv, void __iomem *mmio, | ||
1442 | unsigned int hc) | ||
1288 | { | 1443 | { |
1289 | /* FIXME */ | 1444 | void __iomem *hc_mmio = mv_hc_base(mmio, hc); |
1290 | return 1; | 1445 | u32 tmp; |
1446 | |||
1447 | ZERO(0x00c); | ||
1448 | ZERO(0x010); | ||
1449 | ZERO(0x014); | ||
1450 | ZERO(0x018); | ||
1451 | |||
1452 | tmp = readl(hc_mmio + 0x20); | ||
1453 | tmp &= 0x1c1c1c1c; | ||
1454 | tmp |= 0x03030303; | ||
1455 | writel(tmp, hc_mmio + 0x20); | ||
1456 | } | ||
1457 | #undef ZERO | ||
1458 | |||
1459 | static int mv5_reset_hc(struct mv_host_priv *hpriv, void __iomem *mmio, | ||
1460 | unsigned int n_hc) | ||
1461 | { | ||
1462 | unsigned int hc, port; | ||
1463 | |||
1464 | for (hc = 0; hc < n_hc; hc++) { | ||
1465 | for (port = 0; port < MV_PORTS_PER_HC; port++) | ||
1466 | mv5_reset_hc_port(hpriv, mmio, | ||
1467 | (hc * MV_PORTS_PER_HC) + port); | ||
1468 | |||
1469 | mv5_reset_one_hc(hpriv, mmio, hc); | ||
1470 | } | ||
1471 | |||
1472 | return 0; | ||
1291 | } | 1473 | } |
1292 | 1474 | ||
1293 | #undef ZERO | 1475 | #undef ZERO |
@@ -1335,7 +1517,8 @@ static void mv6_reset_flash(struct mv_host_priv *hpriv, void __iomem *mmio) | |||
1335 | * LOCKING: | 1517 | * LOCKING: |
1336 | * Inherited from caller. | 1518 | * Inherited from caller. |
1337 | */ | 1519 | */ |
1338 | static int mv6_reset_hc(struct mv_host_priv *hpriv, void __iomem *mmio) | 1520 | static int mv6_reset_hc(struct mv_host_priv *hpriv, void __iomem *mmio, |
1521 | unsigned int n_hc) | ||
1339 | { | 1522 | { |
1340 | void __iomem *reg = mmio + PCI_MAIN_CMD_STS_OFS; | 1523 | void __iomem *reg = mmio + PCI_MAIN_CMD_STS_OFS; |
1341 | int i, rc = 0; | 1524 | int i, rc = 0; |
@@ -1415,9 +1598,11 @@ static void mv6_enable_leds(struct mv_host_priv *hpriv, void __iomem *mmio) | |||
1415 | writel(0x00000060, mmio + MV_GPIO_PORT_CTL); | 1598 | writel(0x00000060, mmio + MV_GPIO_PORT_CTL); |
1416 | } | 1599 | } |
1417 | 1600 | ||
1418 | static void mv6_phy_errata(struct mv_host_priv *hpriv, void __iomem *port_mmio, | 1601 | static void mv6_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio, |
1419 | unsigned int port) | 1602 | unsigned int port) |
1420 | { | 1603 | { |
1604 | void __iomem *port_mmio = mv_port_base(mmio, port); | ||
1605 | |||
1421 | u32 hp_flags = hpriv->hp_flags; | 1606 | u32 hp_flags = hpriv->hp_flags; |
1422 | int fix_phy_mode2 = | 1607 | int fix_phy_mode2 = |
1423 | hp_flags & (MV_HP_ERRATA_60X1B2 | MV_HP_ERRATA_60X1C0); | 1608 | hp_flags & (MV_HP_ERRATA_60X1B2 | MV_HP_ERRATA_60X1C0); |
@@ -1473,6 +1658,44 @@ static void mv6_phy_errata(struct mv_host_priv *hpriv, void __iomem *port_mmio, | |||
1473 | writel(m2, port_mmio + PHY_MODE2); | 1658 | writel(m2, port_mmio + PHY_MODE2); |
1474 | } | 1659 | } |
1475 | 1660 | ||
1661 | static void mv_channel_reset(struct mv_host_priv *hpriv, void __iomem *mmio, | ||
1662 | unsigned int port_no) | ||
1663 | { | ||
1664 | void __iomem *port_mmio = mv_port_base(mmio, port_no); | ||
1665 | |||
1666 | writelfl(ATA_RST, port_mmio + EDMA_CMD_OFS); | ||
1667 | |||
1668 | if (IS_60XX(hpriv)) { | ||
1669 | u32 ifctl = readl(port_mmio + SATA_INTERFACE_CTL); | ||
1670 | ifctl |= (1 << 12) | (1 << 7); | ||
1671 | writelfl(ifctl, port_mmio + SATA_INTERFACE_CTL); | ||
1672 | } | ||
1673 | |||
1674 | udelay(25); /* allow reset propagation */ | ||
1675 | |||
1676 | /* Spec never mentions clearing the bit. Marvell's driver does | ||
1677 | * clear the bit, however. | ||
1678 | */ | ||
1679 | writelfl(0, port_mmio + EDMA_CMD_OFS); | ||
1680 | |||
1681 | hpriv->ops->phy_errata(hpriv, mmio, port_no); | ||
1682 | |||
1683 | if (IS_50XX(hpriv)) | ||
1684 | mdelay(1); | ||
1685 | } | ||
1686 | |||
1687 | static void mv_stop_and_reset(struct ata_port *ap) | ||
1688 | { | ||
1689 | struct mv_host_priv *hpriv = ap->host_set->private_data; | ||
1690 | void __iomem *mmio = ap->host_set->mmio_base; | ||
1691 | |||
1692 | mv_stop_dma(ap); | ||
1693 | |||
1694 | mv_channel_reset(hpriv, mmio, ap->port_no); | ||
1695 | |||
1696 | mv_phy_reset(ap); | ||
1697 | } | ||
1698 | |||
1476 | /** | 1699 | /** |
1477 | * mv_phy_reset - Perform eDMA reset followed by COMRESET | 1700 | * mv_phy_reset - Perform eDMA reset followed by COMRESET |
1478 | * @ap: ATA channel to manipulate | 1701 | * @ap: ATA channel to manipulate |
@@ -1487,7 +1710,6 @@ static void mv6_phy_errata(struct mv_host_priv *hpriv, void __iomem *port_mmio, | |||
1487 | static void mv_phy_reset(struct ata_port *ap) | 1710 | static void mv_phy_reset(struct ata_port *ap) |
1488 | { | 1711 | { |
1489 | struct mv_port_priv *pp = ap->private_data; | 1712 | struct mv_port_priv *pp = ap->private_data; |
1490 | struct mv_host_priv *hpriv = ap->host_set->private_data; | ||
1491 | void __iomem *port_mmio = mv_ap_base(ap); | 1713 | void __iomem *port_mmio = mv_ap_base(ap); |
1492 | struct ata_taskfile tf; | 1714 | struct ata_taskfile tf; |
1493 | struct ata_device *dev = &ap->device[0]; | 1715 | struct ata_device *dev = &ap->device[0]; |
@@ -1495,25 +1717,6 @@ static void mv_phy_reset(struct ata_port *ap) | |||
1495 | 1717 | ||
1496 | VPRINTK("ENTER, port %u, mmio 0x%p\n", ap->port_no, port_mmio); | 1718 | VPRINTK("ENTER, port %u, mmio 0x%p\n", ap->port_no, port_mmio); |
1497 | 1719 | ||
1498 | mv_stop_dma(ap); | ||
1499 | |||
1500 | writelfl(ATA_RST, port_mmio + EDMA_CMD_OFS); | ||
1501 | |||
1502 | if (IS_60XX(hpriv)) { | ||
1503 | u32 ifctl = readl(port_mmio + SATA_INTERFACE_CTL); | ||
1504 | ifctl |= (1 << 12) | (1 << 7); | ||
1505 | writelfl(ifctl, port_mmio + SATA_INTERFACE_CTL); | ||
1506 | } | ||
1507 | |||
1508 | udelay(25); /* allow reset propagation */ | ||
1509 | |||
1510 | /* Spec never mentions clearing the bit. Marvell's driver does | ||
1511 | * clear the bit, however. | ||
1512 | */ | ||
1513 | writelfl(0, port_mmio + EDMA_CMD_OFS); | ||
1514 | |||
1515 | hpriv->ops->phy_errata(hpriv, port_mmio, ap->port_no); | ||
1516 | |||
1517 | DPRINTK("S-regs after ATA_RST: SStat 0x%08x SErr 0x%08x " | 1720 | DPRINTK("S-regs after ATA_RST: SStat 0x%08x SErr 0x%08x " |
1518 | "SCtrl 0x%08x\n", mv_scr_read(ap, SCR_STATUS), | 1721 | "SCtrl 0x%08x\n", mv_scr_read(ap, SCR_STATUS), |
1519 | mv_scr_read(ap, SCR_ERROR), mv_scr_read(ap, SCR_CONTROL)); | 1722 | mv_scr_read(ap, SCR_ERROR), mv_scr_read(ap, SCR_CONTROL)); |
@@ -1589,7 +1792,7 @@ static void mv_eng_timeout(struct ata_port *ap) | |||
1589 | &qc->scsicmd->cmnd); | 1792 | &qc->scsicmd->cmnd); |
1590 | 1793 | ||
1591 | mv_err_intr(ap); | 1794 | mv_err_intr(ap); |
1592 | mv_phy_reset(ap); | 1795 | mv_stop_and_reset(ap); |
1593 | 1796 | ||
1594 | if (!qc) { | 1797 | if (!qc) { |
1595 | printk(KERN_ERR "ata%u: BUG: timeout without command\n", | 1798 | printk(KERN_ERR "ata%u: BUG: timeout without command\n", |
@@ -1765,7 +1968,7 @@ static int mv_init_host(struct pci_dev *pdev, struct ata_probe_ent *probe_ent, | |||
1765 | for (port = 0; port < probe_ent->n_ports; port++) | 1968 | for (port = 0; port < probe_ent->n_ports; port++) |
1766 | hpriv->ops->read_preamp(hpriv, port, mmio); | 1969 | hpriv->ops->read_preamp(hpriv, port, mmio); |
1767 | 1970 | ||
1768 | rc = hpriv->ops->reset_hc(hpriv, mmio); | 1971 | rc = hpriv->ops->reset_hc(hpriv, mmio, n_hc); |
1769 | if (rc) | 1972 | if (rc) |
1770 | goto done; | 1973 | goto done; |
1771 | 1974 | ||
@@ -1774,15 +1977,15 @@ static int mv_init_host(struct pci_dev *pdev, struct ata_probe_ent *probe_ent, | |||
1774 | hpriv->ops->enable_leds(hpriv, mmio); | 1977 | hpriv->ops->enable_leds(hpriv, mmio); |
1775 | 1978 | ||
1776 | for (port = 0; port < probe_ent->n_ports; port++) { | 1979 | for (port = 0; port < probe_ent->n_ports; port++) { |
1777 | void __iomem *port_mmio = mv_port_base(mmio, port); | ||
1778 | |||
1779 | if (IS_60XX(hpriv)) { | 1980 | if (IS_60XX(hpriv)) { |
1981 | void __iomem *port_mmio = mv_port_base(mmio, port); | ||
1982 | |||
1780 | u32 ifctl = readl(port_mmio + SATA_INTERFACE_CTL); | 1983 | u32 ifctl = readl(port_mmio + SATA_INTERFACE_CTL); |
1781 | ifctl |= (1 << 12); | 1984 | ifctl |= (1 << 12); |
1782 | writelfl(ifctl, port_mmio + SATA_INTERFACE_CTL); | 1985 | writelfl(ifctl, port_mmio + SATA_INTERFACE_CTL); |
1783 | } | 1986 | } |
1784 | 1987 | ||
1785 | hpriv->ops->phy_errata(hpriv, port_mmio, port); | 1988 | hpriv->ops->phy_errata(hpriv, mmio, port); |
1786 | } | 1989 | } |
1787 | 1990 | ||
1788 | for (port = 0; port < probe_ent->n_ports; port++) { | 1991 | for (port = 0; port < probe_ent->n_ports; port++) { |