diff options
-rw-r--r-- | drivers/scsi/sata_sil.c | 49 |
1 files changed, 34 insertions, 15 deletions
diff --git a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c index bfcece18a7cb..aa63044eed2e 100644 --- a/drivers/scsi/sata_sil.c +++ b/drivers/scsi/sata_sil.c | |||
@@ -96,6 +96,8 @@ static void sil_dev_config(struct ata_port *ap, struct ata_device *dev); | |||
96 | static u32 sil_scr_read (struct ata_port *ap, unsigned int sc_reg); | 96 | static u32 sil_scr_read (struct ata_port *ap, unsigned int sc_reg); |
97 | static void sil_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val); | 97 | static void sil_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val); |
98 | static void sil_post_set_mode (struct ata_port *ap); | 98 | static void sil_post_set_mode (struct ata_port *ap); |
99 | static void sil_freeze(struct ata_port *ap); | ||
100 | static void sil_thaw(struct ata_port *ap); | ||
99 | 101 | ||
100 | 102 | ||
101 | static const struct pci_device_id sil_pci_tbl[] = { | 103 | static const struct pci_device_id sil_pci_tbl[] = { |
@@ -174,7 +176,10 @@ static const struct ata_port_operations sil_ops = { | |||
174 | .bmdma_status = ata_bmdma_status, | 176 | .bmdma_status = ata_bmdma_status, |
175 | .qc_prep = ata_qc_prep, | 177 | .qc_prep = ata_qc_prep, |
176 | .qc_issue = ata_qc_issue_prot, | 178 | .qc_issue = ata_qc_issue_prot, |
177 | .eng_timeout = ata_eng_timeout, | 179 | .freeze = sil_freeze, |
180 | .thaw = sil_thaw, | ||
181 | .error_handler = ata_bmdma_error_handler, | ||
182 | .post_internal_cmd = ata_bmdma_post_internal_cmd, | ||
178 | .irq_handler = ata_interrupt, | 183 | .irq_handler = ata_interrupt, |
179 | .irq_clear = ata_bmdma_irq_clear, | 184 | .irq_clear = ata_bmdma_irq_clear, |
180 | .scr_read = sil_scr_read, | 185 | .scr_read = sil_scr_read, |
@@ -314,6 +319,33 @@ static void sil_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val) | |||
314 | writel(val, mmio); | 319 | writel(val, mmio); |
315 | } | 320 | } |
316 | 321 | ||
322 | static void sil_freeze(struct ata_port *ap) | ||
323 | { | ||
324 | void __iomem *mmio_base = ap->host_set->mmio_base; | ||
325 | u32 tmp; | ||
326 | |||
327 | /* plug IRQ */ | ||
328 | tmp = readl(mmio_base + SIL_SYSCFG); | ||
329 | tmp |= SIL_MASK_IDE0_INT << ap->port_no; | ||
330 | writel(tmp, mmio_base + SIL_SYSCFG); | ||
331 | readl(mmio_base + SIL_SYSCFG); /* flush */ | ||
332 | } | ||
333 | |||
334 | static void sil_thaw(struct ata_port *ap) | ||
335 | { | ||
336 | void __iomem *mmio_base = ap->host_set->mmio_base; | ||
337 | u32 tmp; | ||
338 | |||
339 | /* clear IRQ */ | ||
340 | ata_chk_status(ap); | ||
341 | ata_bmdma_irq_clear(ap); | ||
342 | |||
343 | /* turn on IRQ */ | ||
344 | tmp = readl(mmio_base + SIL_SYSCFG); | ||
345 | tmp &= ~(SIL_MASK_IDE0_INT << ap->port_no); | ||
346 | writel(tmp, mmio_base + SIL_SYSCFG); | ||
347 | } | ||
348 | |||
317 | /** | 349 | /** |
318 | * sil_dev_config - Apply device/host-specific errata fixups | 350 | * sil_dev_config - Apply device/host-specific errata fixups |
319 | * @ap: Port containing device to be examined | 351 | * @ap: Port containing device to be examined |
@@ -384,7 +416,7 @@ static int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) | |||
384 | int rc; | 416 | int rc; |
385 | unsigned int i; | 417 | unsigned int i; |
386 | int pci_dev_busy = 0; | 418 | int pci_dev_busy = 0; |
387 | u32 tmp, irq_mask; | 419 | u32 tmp; |
388 | u8 cls; | 420 | u8 cls; |
389 | 421 | ||
390 | if (!printed_version++) | 422 | if (!printed_version++) |
@@ -474,24 +506,11 @@ static int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) | |||
474 | } | 506 | } |
475 | 507 | ||
476 | if (ent->driver_data == sil_3114) { | 508 | if (ent->driver_data == sil_3114) { |
477 | irq_mask = SIL_MASK_4PORT; | ||
478 | |||
479 | /* flip the magic "make 4 ports work" bit */ | 509 | /* flip the magic "make 4 ports work" bit */ |
480 | tmp = readl(mmio_base + sil_port[2].bmdma); | 510 | tmp = readl(mmio_base + sil_port[2].bmdma); |
481 | if ((tmp & SIL_INTR_STEERING) == 0) | 511 | if ((tmp & SIL_INTR_STEERING) == 0) |
482 | writel(tmp | SIL_INTR_STEERING, | 512 | writel(tmp | SIL_INTR_STEERING, |
483 | mmio_base + sil_port[2].bmdma); | 513 | mmio_base + sil_port[2].bmdma); |
484 | |||
485 | } else { | ||
486 | irq_mask = SIL_MASK_2PORT; | ||
487 | } | ||
488 | |||
489 | /* make sure IDE0/1/2/3 interrupts are not masked */ | ||
490 | tmp = readl(mmio_base + SIL_SYSCFG); | ||
491 | if (tmp & irq_mask) { | ||
492 | tmp &= ~irq_mask; | ||
493 | writel(tmp, mmio_base + SIL_SYSCFG); | ||
494 | readl(mmio_base + SIL_SYSCFG); /* flush */ | ||
495 | } | 514 | } |
496 | 515 | ||
497 | /* mask all SATA phy-related interrupts */ | 516 | /* mask all SATA phy-related interrupts */ |