diff options
-rw-r--r-- | drivers/scsi/sata_nv.c | 115 |
1 files changed, 89 insertions, 26 deletions
diff --git a/drivers/scsi/sata_nv.c b/drivers/scsi/sata_nv.c index 94cb17903fae..2a1bd85404e0 100644 --- a/drivers/scsi/sata_nv.c +++ b/drivers/scsi/sata_nv.c | |||
@@ -68,6 +68,9 @@ enum { | |||
68 | 68 | ||
69 | NV_INT_PORT_SHIFT = 4, /* each port occupies 4 bits */ | 69 | NV_INT_PORT_SHIFT = 4, /* each port occupies 4 bits */ |
70 | 70 | ||
71 | NV_INT_ALL = 0x0f, | ||
72 | NV_INT_MASK = NV_INT_DEV, | ||
73 | |||
71 | /* INT_CONFIG */ | 74 | /* INT_CONFIG */ |
72 | NV_INT_CONFIG = 0x12, | 75 | NV_INT_CONFIG = 0x12, |
73 | NV_INT_CONFIG_METHD = 0x01, // 0 = INT, 1 = SMI | 76 | NV_INT_CONFIG_METHD = 0x01, // 0 = INT, 1 = SMI |
@@ -88,6 +91,12 @@ static irqreturn_t nv_ck804_interrupt(int irq, void *dev_instance, | |||
88 | static u32 nv_scr_read (struct ata_port *ap, unsigned int sc_reg); | 91 | static u32 nv_scr_read (struct ata_port *ap, unsigned int sc_reg); |
89 | static void nv_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val); | 92 | static void nv_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val); |
90 | 93 | ||
94 | static void nv_nf2_freeze(struct ata_port *ap); | ||
95 | static void nv_nf2_thaw(struct ata_port *ap); | ||
96 | static void nv_ck804_freeze(struct ata_port *ap); | ||
97 | static void nv_ck804_thaw(struct ata_port *ap); | ||
98 | static void nv_error_handler(struct ata_port *ap); | ||
99 | |||
91 | enum nv_host_type | 100 | enum nv_host_type |
92 | { | 101 | { |
93 | GENERIC, | 102 | GENERIC, |
@@ -166,14 +175,16 @@ static const struct ata_port_operations nv_generic_ops = { | |||
166 | .exec_command = ata_exec_command, | 175 | .exec_command = ata_exec_command, |
167 | .check_status = ata_check_status, | 176 | .check_status = ata_check_status, |
168 | .dev_select = ata_std_dev_select, | 177 | .dev_select = ata_std_dev_select, |
169 | .phy_reset = sata_phy_reset, | ||
170 | .bmdma_setup = ata_bmdma_setup, | 178 | .bmdma_setup = ata_bmdma_setup, |
171 | .bmdma_start = ata_bmdma_start, | 179 | .bmdma_start = ata_bmdma_start, |
172 | .bmdma_stop = ata_bmdma_stop, | 180 | .bmdma_stop = ata_bmdma_stop, |
173 | .bmdma_status = ata_bmdma_status, | 181 | .bmdma_status = ata_bmdma_status, |
174 | .qc_prep = ata_qc_prep, | 182 | .qc_prep = ata_qc_prep, |
175 | .qc_issue = ata_qc_issue_prot, | 183 | .qc_issue = ata_qc_issue_prot, |
176 | .eng_timeout = ata_eng_timeout, | 184 | .freeze = ata_bmdma_freeze, |
185 | .thaw = ata_bmdma_thaw, | ||
186 | .error_handler = nv_error_handler, | ||
187 | .post_internal_cmd = ata_bmdma_post_internal_cmd, | ||
177 | .data_xfer = ata_pio_data_xfer, | 188 | .data_xfer = ata_pio_data_xfer, |
178 | .irq_handler = nv_generic_interrupt, | 189 | .irq_handler = nv_generic_interrupt, |
179 | .irq_clear = ata_bmdma_irq_clear, | 190 | .irq_clear = ata_bmdma_irq_clear, |
@@ -191,14 +202,16 @@ static const struct ata_port_operations nv_nf2_ops = { | |||
191 | .exec_command = ata_exec_command, | 202 | .exec_command = ata_exec_command, |
192 | .check_status = ata_check_status, | 203 | .check_status = ata_check_status, |
193 | .dev_select = ata_std_dev_select, | 204 | .dev_select = ata_std_dev_select, |
194 | .phy_reset = sata_phy_reset, | ||
195 | .bmdma_setup = ata_bmdma_setup, | 205 | .bmdma_setup = ata_bmdma_setup, |
196 | .bmdma_start = ata_bmdma_start, | 206 | .bmdma_start = ata_bmdma_start, |
197 | .bmdma_stop = ata_bmdma_stop, | 207 | .bmdma_stop = ata_bmdma_stop, |
198 | .bmdma_status = ata_bmdma_status, | 208 | .bmdma_status = ata_bmdma_status, |
199 | .qc_prep = ata_qc_prep, | 209 | .qc_prep = ata_qc_prep, |
200 | .qc_issue = ata_qc_issue_prot, | 210 | .qc_issue = ata_qc_issue_prot, |
201 | .eng_timeout = ata_eng_timeout, | 211 | .freeze = nv_nf2_freeze, |
212 | .thaw = nv_nf2_thaw, | ||
213 | .error_handler = nv_error_handler, | ||
214 | .post_internal_cmd = ata_bmdma_post_internal_cmd, | ||
202 | .data_xfer = ata_pio_data_xfer, | 215 | .data_xfer = ata_pio_data_xfer, |
203 | .irq_handler = nv_nf2_interrupt, | 216 | .irq_handler = nv_nf2_interrupt, |
204 | .irq_clear = ata_bmdma_irq_clear, | 217 | .irq_clear = ata_bmdma_irq_clear, |
@@ -216,14 +229,16 @@ static const struct ata_port_operations nv_ck804_ops = { | |||
216 | .exec_command = ata_exec_command, | 229 | .exec_command = ata_exec_command, |
217 | .check_status = ata_check_status, | 230 | .check_status = ata_check_status, |
218 | .dev_select = ata_std_dev_select, | 231 | .dev_select = ata_std_dev_select, |
219 | .phy_reset = sata_phy_reset, | ||
220 | .bmdma_setup = ata_bmdma_setup, | 232 | .bmdma_setup = ata_bmdma_setup, |
221 | .bmdma_start = ata_bmdma_start, | 233 | .bmdma_start = ata_bmdma_start, |
222 | .bmdma_stop = ata_bmdma_stop, | 234 | .bmdma_stop = ata_bmdma_stop, |
223 | .bmdma_status = ata_bmdma_status, | 235 | .bmdma_status = ata_bmdma_status, |
224 | .qc_prep = ata_qc_prep, | 236 | .qc_prep = ata_qc_prep, |
225 | .qc_issue = ata_qc_issue_prot, | 237 | .qc_issue = ata_qc_issue_prot, |
226 | .eng_timeout = ata_eng_timeout, | 238 | .freeze = nv_ck804_freeze, |
239 | .thaw = nv_ck804_thaw, | ||
240 | .error_handler = nv_error_handler, | ||
241 | .post_internal_cmd = ata_bmdma_post_internal_cmd, | ||
227 | .data_xfer = ata_pio_data_xfer, | 242 | .data_xfer = ata_pio_data_xfer, |
228 | .irq_handler = nv_ck804_interrupt, | 243 | .irq_handler = nv_ck804_interrupt, |
229 | .irq_clear = ata_bmdma_irq_clear, | 244 | .irq_clear = ata_bmdma_irq_clear, |
@@ -234,22 +249,11 @@ static const struct ata_port_operations nv_ck804_ops = { | |||
234 | .host_stop = nv_ck804_host_stop, | 249 | .host_stop = nv_ck804_host_stop, |
235 | }; | 250 | }; |
236 | 251 | ||
237 | /* FIXME: The hardware provides the necessary SATA PHY controls | ||
238 | * to support ATA_FLAG_SATA_RESET. However, it is currently | ||
239 | * necessary to disable that flag, to solve misdetection problems. | ||
240 | * See http://bugme.osdl.org/show_bug.cgi?id=3352 for more info. | ||
241 | * | ||
242 | * This problem really needs to be investigated further. But in the | ||
243 | * meantime, we avoid ATA_FLAG_SATA_RESET to get people working. | ||
244 | */ | ||
245 | static struct ata_port_info nv_port_info[] = { | 252 | static struct ata_port_info nv_port_info[] = { |
246 | /* generic */ | 253 | /* generic */ |
247 | { | 254 | { |
248 | .sht = &nv_sht, | 255 | .sht = &nv_sht, |
249 | .host_flags = ATA_FLAG_SATA | | 256 | .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY, |
250 | /* ATA_FLAG_SATA_RESET | */ | ||
251 | ATA_FLAG_SRST | | ||
252 | ATA_FLAG_NO_LEGACY, | ||
253 | .pio_mask = NV_PIO_MASK, | 257 | .pio_mask = NV_PIO_MASK, |
254 | .mwdma_mask = NV_MWDMA_MASK, | 258 | .mwdma_mask = NV_MWDMA_MASK, |
255 | .udma_mask = NV_UDMA_MASK, | 259 | .udma_mask = NV_UDMA_MASK, |
@@ -258,10 +262,7 @@ static struct ata_port_info nv_port_info[] = { | |||
258 | /* nforce2/3 */ | 262 | /* nforce2/3 */ |
259 | { | 263 | { |
260 | .sht = &nv_sht, | 264 | .sht = &nv_sht, |
261 | .host_flags = ATA_FLAG_SATA | | 265 | .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY, |
262 | /* ATA_FLAG_SATA_RESET | */ | ||
263 | ATA_FLAG_SRST | | ||
264 | ATA_FLAG_NO_LEGACY, | ||
265 | .pio_mask = NV_PIO_MASK, | 266 | .pio_mask = NV_PIO_MASK, |
266 | .mwdma_mask = NV_MWDMA_MASK, | 267 | .mwdma_mask = NV_MWDMA_MASK, |
267 | .udma_mask = NV_UDMA_MASK, | 268 | .udma_mask = NV_UDMA_MASK, |
@@ -270,10 +271,7 @@ static struct ata_port_info nv_port_info[] = { | |||
270 | /* ck804 */ | 271 | /* ck804 */ |
271 | { | 272 | { |
272 | .sht = &nv_sht, | 273 | .sht = &nv_sht, |
273 | .host_flags = ATA_FLAG_SATA | | 274 | .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY, |
274 | /* ATA_FLAG_SATA_RESET | */ | ||
275 | ATA_FLAG_SRST | | ||
276 | ATA_FLAG_NO_LEGACY, | ||
277 | .pio_mask = NV_PIO_MASK, | 275 | .pio_mask = NV_PIO_MASK, |
278 | .mwdma_mask = NV_MWDMA_MASK, | 276 | .mwdma_mask = NV_MWDMA_MASK, |
279 | .udma_mask = NV_UDMA_MASK, | 277 | .udma_mask = NV_UDMA_MASK, |
@@ -410,6 +408,71 @@ static void nv_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val) | |||
410 | iowrite32(val, (void __iomem *)ap->ioaddr.scr_addr + (sc_reg * 4)); | 408 | iowrite32(val, (void __iomem *)ap->ioaddr.scr_addr + (sc_reg * 4)); |
411 | } | 409 | } |
412 | 410 | ||
411 | static void nv_nf2_freeze(struct ata_port *ap) | ||
412 | { | ||
413 | unsigned long scr_addr = ap->host_set->ports[0]->ioaddr.scr_addr; | ||
414 | int shift = ap->port_no * NV_INT_PORT_SHIFT; | ||
415 | u8 mask; | ||
416 | |||
417 | mask = inb(scr_addr + NV_INT_ENABLE); | ||
418 | mask &= ~(NV_INT_ALL << shift); | ||
419 | outb(mask, scr_addr + NV_INT_ENABLE); | ||
420 | } | ||
421 | |||
422 | static void nv_nf2_thaw(struct ata_port *ap) | ||
423 | { | ||
424 | unsigned long scr_addr = ap->host_set->ports[0]->ioaddr.scr_addr; | ||
425 | int shift = ap->port_no * NV_INT_PORT_SHIFT; | ||
426 | u8 mask; | ||
427 | |||
428 | outb(NV_INT_ALL << shift, scr_addr + NV_INT_STATUS); | ||
429 | |||
430 | mask = inb(scr_addr + NV_INT_ENABLE); | ||
431 | mask |= (NV_INT_MASK << shift); | ||
432 | outb(mask, scr_addr + NV_INT_ENABLE); | ||
433 | } | ||
434 | |||
435 | static void nv_ck804_freeze(struct ata_port *ap) | ||
436 | { | ||
437 | void __iomem *mmio_base = ap->host_set->mmio_base; | ||
438 | int shift = ap->port_no * NV_INT_PORT_SHIFT; | ||
439 | u8 mask; | ||
440 | |||
441 | mask = readb(mmio_base + NV_INT_ENABLE_CK804); | ||
442 | mask &= ~(NV_INT_ALL << shift); | ||
443 | writeb(mask, mmio_base + NV_INT_ENABLE_CK804); | ||
444 | } | ||
445 | |||
446 | static void nv_ck804_thaw(struct ata_port *ap) | ||
447 | { | ||
448 | void __iomem *mmio_base = ap->host_set->mmio_base; | ||
449 | int shift = ap->port_no * NV_INT_PORT_SHIFT; | ||
450 | u8 mask; | ||
451 | |||
452 | writeb(NV_INT_ALL << shift, mmio_base + NV_INT_STATUS_CK804); | ||
453 | |||
454 | mask = readb(mmio_base + NV_INT_ENABLE_CK804); | ||
455 | mask |= (NV_INT_MASK << shift); | ||
456 | writeb(mask, mmio_base + NV_INT_ENABLE_CK804); | ||
457 | } | ||
458 | |||
459 | static int nv_hardreset(struct ata_port *ap, unsigned int *class) | ||
460 | { | ||
461 | unsigned int dummy; | ||
462 | |||
463 | /* SATA hardreset fails to retrieve proper device signature on | ||
464 | * some controllers. Don't classify on hardreset. For more | ||
465 | * info, see http://bugme.osdl.org/show_bug.cgi?id=3352 | ||
466 | */ | ||
467 | return sata_std_hardreset(ap, &dummy); | ||
468 | } | ||
469 | |||
470 | static void nv_error_handler(struct ata_port *ap) | ||
471 | { | ||
472 | ata_bmdma_drive_eh(ap, ata_std_prereset, ata_std_softreset, | ||
473 | nv_hardreset, ata_std_postreset); | ||
474 | } | ||
475 | |||
413 | static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) | 476 | static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) |
414 | { | 477 | { |
415 | static int printed_version = 0; | 478 | static int printed_version = 0; |