aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata/sata_sil24.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/ata/sata_sil24.c')
-rw-r--r--drivers/ata/sata_sil24.c111
1 files changed, 40 insertions, 71 deletions
diff --git a/drivers/ata/sata_sil24.c b/drivers/ata/sata_sil24.c
index 4f522ec04049..e6223ba667da 100644
--- a/drivers/ata/sata_sil24.c
+++ b/drivers/ata/sata_sil24.c
@@ -331,7 +331,6 @@ static void sil24_tf_read(struct ata_port *ap, struct ata_taskfile *tf);
331static void sil24_qc_prep(struct ata_queued_cmd *qc); 331static void sil24_qc_prep(struct ata_queued_cmd *qc);
332static unsigned int sil24_qc_issue(struct ata_queued_cmd *qc); 332static unsigned int sil24_qc_issue(struct ata_queued_cmd *qc);
333static void sil24_irq_clear(struct ata_port *ap); 333static void sil24_irq_clear(struct ata_port *ap);
334static irqreturn_t sil24_interrupt(int irq, void *dev_instance);
335static void sil24_freeze(struct ata_port *ap); 334static void sil24_freeze(struct ata_port *ap);
336static void sil24_thaw(struct ata_port *ap); 335static void sil24_thaw(struct ata_port *ap);
337static void sil24_error_handler(struct ata_port *ap); 336static void sil24_error_handler(struct ata_port *ap);
@@ -401,7 +400,6 @@ static const struct ata_port_operations sil24_ops = {
401 .qc_prep = sil24_qc_prep, 400 .qc_prep = sil24_qc_prep,
402 .qc_issue = sil24_qc_issue, 401 .qc_issue = sil24_qc_issue,
403 402
404 .irq_handler = sil24_interrupt,
405 .irq_clear = sil24_irq_clear, 403 .irq_clear = sil24_irq_clear,
406 .irq_on = ata_dummy_irq_on, 404 .irq_on = ata_dummy_irq_on,
407 .irq_ack = ata_dummy_irq_ack, 405 .irq_ack = ata_dummy_irq_ack,
@@ -424,10 +422,9 @@ static const struct ata_port_operations sil24_ops = {
424#define SIL24_NPORTS2FLAG(nports) ((((unsigned)(nports) - 1) & 0x3) << 30) 422#define SIL24_NPORTS2FLAG(nports) ((((unsigned)(nports) - 1) & 0x3) << 30)
425#define SIL24_FLAG2NPORTS(flag) ((((flag) >> 30) & 0x3) + 1) 423#define SIL24_FLAG2NPORTS(flag) ((((flag) >> 30) & 0x3) + 1)
426 424
427static struct ata_port_info sil24_port_info[] = { 425static const struct ata_port_info sil24_port_info[] = {
428 /* sil_3124 */ 426 /* sil_3124 */
429 { 427 {
430 .sht = &sil24_sht,
431 .flags = SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(4) | 428 .flags = SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(4) |
432 SIL24_FLAG_PCIX_IRQ_WOC, 429 SIL24_FLAG_PCIX_IRQ_WOC,
433 .pio_mask = 0x1f, /* pio0-4 */ 430 .pio_mask = 0x1f, /* pio0-4 */
@@ -437,7 +434,6 @@ static struct ata_port_info sil24_port_info[] = {
437 }, 434 },
438 /* sil_3132 */ 435 /* sil_3132 */
439 { 436 {
440 .sht = &sil24_sht,
441 .flags = SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(2), 437 .flags = SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(2),
442 .pio_mask = 0x1f, /* pio0-4 */ 438 .pio_mask = 0x1f, /* pio0-4 */
443 .mwdma_mask = 0x07, /* mwdma0-2 */ 439 .mwdma_mask = 0x07, /* mwdma0-2 */
@@ -446,7 +442,6 @@ static struct ata_port_info sil24_port_info[] = {
446 }, 442 },
447 /* sil_3131/sil_3531 */ 443 /* sil_3131/sil_3531 */
448 { 444 {
449 .sht = &sil24_sht,
450 .flags = SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(1), 445 .flags = SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(1),
451 .pio_mask = 0x1f, /* pio0-4 */ 446 .pio_mask = 0x1f, /* pio0-4 */
452 .mwdma_mask = 0x07, /* mwdma0-2 */ 447 .mwdma_mask = 0x07, /* mwdma0-2 */
@@ -961,11 +956,10 @@ static int sil24_port_start(struct ata_port *ap)
961 return 0; 956 return 0;
962} 957}
963 958
964static void sil24_init_controller(struct pci_dev *pdev, int n_ports, 959static void sil24_init_controller(struct ata_host *host)
965 unsigned long port_flags,
966 void __iomem *host_base,
967 void __iomem *port_base)
968{ 960{
961 void __iomem *host_base = host->iomap[SIL24_HOST_BAR];
962 void __iomem *port_base = host->iomap[SIL24_PORT_BAR];
969 u32 tmp; 963 u32 tmp;
970 int i; 964 int i;
971 965
@@ -976,7 +970,7 @@ static void sil24_init_controller(struct pci_dev *pdev, int n_ports,
976 writel(0, host_base + HOST_CTRL); 970 writel(0, host_base + HOST_CTRL);
977 971
978 /* init ports */ 972 /* init ports */
979 for (i = 0; i < n_ports; i++) { 973 for (i = 0; i < host->n_ports; i++) {
980 void __iomem *port = port_base + i * PORT_REGS_SIZE; 974 void __iomem *port = port_base + i * PORT_REGS_SIZE;
981 975
982 /* Initial PHY setting */ 976 /* Initial PHY setting */
@@ -990,12 +984,12 @@ static void sil24_init_controller(struct pci_dev *pdev, int n_ports,
990 PORT_CS_PORT_RST, 984 PORT_CS_PORT_RST,
991 PORT_CS_PORT_RST, 10, 100); 985 PORT_CS_PORT_RST, 10, 100);
992 if (tmp & PORT_CS_PORT_RST) 986 if (tmp & PORT_CS_PORT_RST)
993 dev_printk(KERN_ERR, &pdev->dev, 987 dev_printk(KERN_ERR, host->dev,
994 "failed to clear port RST\n"); 988 "failed to clear port RST\n");
995 } 989 }
996 990
997 /* Configure IRQ WoC */ 991 /* Configure IRQ WoC */
998 if (port_flags & SIL24_FLAG_PCIX_IRQ_WOC) 992 if (host->ports[0]->flags & SIL24_FLAG_PCIX_IRQ_WOC)
999 writel(PORT_CS_IRQ_WOC, port + PORT_CTRL_STAT); 993 writel(PORT_CS_IRQ_WOC, port + PORT_CTRL_STAT);
1000 else 994 else
1001 writel(PORT_CS_IRQ_WOC, port + PORT_CTRL_CLR); 995 writel(PORT_CS_IRQ_WOC, port + PORT_CTRL_CLR);
@@ -1023,18 +1017,17 @@ static void sil24_init_controller(struct pci_dev *pdev, int n_ports,
1023static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) 1017static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
1024{ 1018{
1025 static int printed_version = 0; 1019 static int printed_version = 0;
1026 struct device *dev = &pdev->dev; 1020 struct ata_port_info pi = sil24_port_info[ent->driver_data];
1027 unsigned int board_id = (unsigned int)ent->driver_data; 1021 const struct ata_port_info *ppi[] = { &pi, NULL };
1028 struct ata_port_info *pinfo = &sil24_port_info[board_id]; 1022 void __iomem * const *iomap;
1029 struct ata_probe_ent *probe_ent; 1023 struct ata_host *host;
1030 void __iomem *host_base;
1031 void __iomem *port_base;
1032 int i, rc; 1024 int i, rc;
1033 u32 tmp; 1025 u32 tmp;
1034 1026
1035 if (!printed_version++) 1027 if (!printed_version++)
1036 dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); 1028 dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
1037 1029
1030 /* acquire resources */
1038 rc = pcim_enable_device(pdev); 1031 rc = pcim_enable_device(pdev);
1039 if (rc) 1032 if (rc)
1040 return rc; 1033 return rc;
@@ -1044,33 +1037,36 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
1044 DRV_NAME); 1037 DRV_NAME);
1045 if (rc) 1038 if (rc)
1046 return rc; 1039 return rc;
1040 iomap = pcim_iomap_table(pdev);
1047 1041
1048 /* allocate & init probe_ent */ 1042 /* apply workaround for completion IRQ loss on PCI-X errata */
1049 probe_ent = devm_kzalloc(dev, sizeof(*probe_ent), GFP_KERNEL); 1043 if (pi.flags & SIL24_FLAG_PCIX_IRQ_WOC) {
1050 if (!probe_ent) 1044 tmp = readl(iomap[SIL24_HOST_BAR] + HOST_CTRL);
1051 return -ENOMEM; 1045 if (tmp & (HOST_CTRL_TRDY | HOST_CTRL_STOP | HOST_CTRL_DEVSEL))
1046 dev_printk(KERN_INFO, &pdev->dev,
1047 "Applying completion IRQ loss on PCI-X "
1048 "errata fix\n");
1049 else
1050 pi.flags &= ~SIL24_FLAG_PCIX_IRQ_WOC;
1051 }
1052 1052
1053 probe_ent->dev = pci_dev_to_dev(pdev); 1053 /* allocate and fill host */
1054 INIT_LIST_HEAD(&probe_ent->node); 1054 host = ata_host_alloc_pinfo(&pdev->dev, ppi,
1055 SIL24_FLAG2NPORTS(ppi[0]->flags));
1056 if (!host)
1057 return -ENOMEM;
1058 host->iomap = iomap;
1055 1059
1056 probe_ent->sht = pinfo->sht; 1060 for (i = 0; i < host->n_ports; i++) {
1057 probe_ent->port_flags = pinfo->flags; 1061 void __iomem *port = iomap[SIL24_PORT_BAR] + i * PORT_REGS_SIZE;
1058 probe_ent->pio_mask = pinfo->pio_mask;
1059 probe_ent->mwdma_mask = pinfo->mwdma_mask;
1060 probe_ent->udma_mask = pinfo->udma_mask;
1061 probe_ent->port_ops = pinfo->port_ops;
1062 probe_ent->n_ports = SIL24_FLAG2NPORTS(pinfo->flags);
1063 1062
1064 probe_ent->irq = pdev->irq; 1063 host->ports[i]->ioaddr.cmd_addr = port;
1065 probe_ent->irq_flags = IRQF_SHARED; 1064 host->ports[i]->ioaddr.scr_addr = port + PORT_SCONTROL;
1066 probe_ent->iomap = pcim_iomap_table(pdev);
1067 1065
1068 host_base = probe_ent->iomap[SIL24_HOST_BAR]; 1066 ata_std_ports(&host->ports[i]->ioaddr);
1069 port_base = probe_ent->iomap[SIL24_PORT_BAR]; 1067 }
1070 1068
1071 /* 1069 /* configure and activate the device */
1072 * Configure the device
1073 */
1074 if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) { 1070 if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) {
1075 rc = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK); 1071 rc = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK);
1076 if (rc) { 1072 if (rc) {
@@ -1096,36 +1092,11 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
1096 } 1092 }
1097 } 1093 }
1098 1094
1099 /* Apply workaround for completion IRQ loss on PCI-X errata */ 1095 sil24_init_controller(host);
1100 if (probe_ent->port_flags & SIL24_FLAG_PCIX_IRQ_WOC) {
1101 tmp = readl(host_base + HOST_CTRL);
1102 if (tmp & (HOST_CTRL_TRDY | HOST_CTRL_STOP | HOST_CTRL_DEVSEL))
1103 dev_printk(KERN_INFO, &pdev->dev,
1104 "Applying completion IRQ loss on PCI-X "
1105 "errata fix\n");
1106 else
1107 probe_ent->port_flags &= ~SIL24_FLAG_PCIX_IRQ_WOC;
1108 }
1109
1110 for (i = 0; i < probe_ent->n_ports; i++) {
1111 void __iomem *port = port_base + i * PORT_REGS_SIZE;
1112
1113 probe_ent->port[i].cmd_addr = port;
1114 probe_ent->port[i].scr_addr = port + PORT_SCONTROL;
1115
1116 ata_std_ports(&probe_ent->port[i]);
1117 }
1118
1119 sil24_init_controller(pdev, probe_ent->n_ports, probe_ent->port_flags,
1120 host_base, port_base);
1121 1096
1122 pci_set_master(pdev); 1097 pci_set_master(pdev);
1123 1098 return ata_host_activate(host, pdev->irq, sil24_interrupt, IRQF_SHARED,
1124 if (!ata_device_add(probe_ent)) 1099 &sil24_sht);
1125 return -ENODEV;
1126
1127 devm_kfree(dev, probe_ent);
1128 return 0;
1129} 1100}
1130 1101
1131#ifdef CONFIG_PM 1102#ifdef CONFIG_PM
@@ -1133,7 +1104,6 @@ static int sil24_pci_device_resume(struct pci_dev *pdev)
1133{ 1104{
1134 struct ata_host *host = dev_get_drvdata(&pdev->dev); 1105 struct ata_host *host = dev_get_drvdata(&pdev->dev);
1135 void __iomem *host_base = host->iomap[SIL24_HOST_BAR]; 1106 void __iomem *host_base = host->iomap[SIL24_HOST_BAR];
1136 void __iomem *port_base = host->iomap[SIL24_PORT_BAR];
1137 int rc; 1107 int rc;
1138 1108
1139 rc = ata_pci_device_do_resume(pdev); 1109 rc = ata_pci_device_do_resume(pdev);
@@ -1143,8 +1113,7 @@ static int sil24_pci_device_resume(struct pci_dev *pdev)
1143 if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) 1113 if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND)
1144 writel(HOST_CTRL_GLOBAL_RST, host_base + HOST_CTRL); 1114 writel(HOST_CTRL_GLOBAL_RST, host_base + HOST_CTRL);
1145 1115
1146 sil24_init_controller(pdev, host->n_ports, host->ports[0]->flags, 1116 sil24_init_controller(host);
1147 host_base, port_base);
1148 1117
1149 ata_host_resume(host); 1118 ata_host_resume(host);
1150 1119