diff options
Diffstat (limited to 'drivers/ata/sata_via.c')
| -rw-r--r-- | drivers/ata/sata_via.c | 153 |
1 files changed, 143 insertions, 10 deletions
diff --git a/drivers/ata/sata_via.c b/drivers/ata/sata_via.c index 5b72e734300a..c18935f0bda2 100644 --- a/drivers/ata/sata_via.c +++ b/drivers/ata/sata_via.c | |||
| @@ -44,11 +44,16 @@ | |||
| 44 | #include <linux/libata.h> | 44 | #include <linux/libata.h> |
| 45 | 45 | ||
| 46 | #define DRV_NAME "sata_via" | 46 | #define DRV_NAME "sata_via" |
| 47 | #define DRV_VERSION "2.3" | 47 | #define DRV_VERSION "2.4" |
| 48 | 48 | ||
| 49 | /* | ||
| 50 | * vt8251 is different from other sata controllers of VIA. It has two | ||
| 51 | * channels, each channel has both Master and Slave slot. | ||
| 52 | */ | ||
| 49 | enum board_ids_enum { | 53 | enum board_ids_enum { |
| 50 | vt6420, | 54 | vt6420, |
| 51 | vt6421, | 55 | vt6421, |
| 56 | vt8251, | ||
| 52 | }; | 57 | }; |
| 53 | 58 | ||
| 54 | enum { | 59 | enum { |
| @@ -70,6 +75,8 @@ enum { | |||
| 70 | static int svia_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); | 75 | static int svia_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); |
| 71 | static int svia_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val); | 76 | static int svia_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val); |
| 72 | static int svia_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val); | 77 | static int svia_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val); |
| 78 | static int vt8251_scr_read(struct ata_link *link, unsigned int scr, u32 *val); | ||
| 79 | static int vt8251_scr_write(struct ata_link *link, unsigned int scr, u32 val); | ||
| 73 | static void svia_tf_load(struct ata_port *ap, const struct ata_taskfile *tf); | 80 | static void svia_tf_load(struct ata_port *ap, const struct ata_taskfile *tf); |
| 74 | static void svia_noop_freeze(struct ata_port *ap); | 81 | static void svia_noop_freeze(struct ata_port *ap); |
| 75 | static int vt6420_prereset(struct ata_link *link, unsigned long deadline); | 82 | static int vt6420_prereset(struct ata_link *link, unsigned long deadline); |
| @@ -79,12 +86,12 @@ static void vt6421_set_dma_mode(struct ata_port *ap, struct ata_device *adev); | |||
| 79 | 86 | ||
| 80 | static const struct pci_device_id svia_pci_tbl[] = { | 87 | static const struct pci_device_id svia_pci_tbl[] = { |
| 81 | { PCI_VDEVICE(VIA, 0x5337), vt6420 }, | 88 | { PCI_VDEVICE(VIA, 0x5337), vt6420 }, |
| 82 | { PCI_VDEVICE(VIA, 0x0591), vt6420 }, | 89 | { PCI_VDEVICE(VIA, 0x0591), vt6420 }, /* 2 sata chnls (Master) */ |
| 83 | { PCI_VDEVICE(VIA, 0x3149), vt6420 }, | 90 | { PCI_VDEVICE(VIA, 0x3149), vt6420 }, /* 2 sata chnls (Master) */ |
| 84 | { PCI_VDEVICE(VIA, 0x3249), vt6421 }, | 91 | { PCI_VDEVICE(VIA, 0x3249), vt6421 }, /* 2 sata chnls, 1 pata chnl */ |
| 85 | { PCI_VDEVICE(VIA, 0x5287), vt6420 }, | ||
| 86 | { PCI_VDEVICE(VIA, 0x5372), vt6420 }, | 92 | { PCI_VDEVICE(VIA, 0x5372), vt6420 }, |
| 87 | { PCI_VDEVICE(VIA, 0x7372), vt6420 }, | 93 | { PCI_VDEVICE(VIA, 0x7372), vt6420 }, |
| 94 | { PCI_VDEVICE(VIA, 0x5287), vt8251 }, /* 2 sata chnls (Master/Slave) */ | ||
| 88 | 95 | ||
| 89 | { } /* terminate list */ | 96 | { } /* terminate list */ |
| 90 | }; | 97 | }; |
| @@ -128,6 +135,13 @@ static struct ata_port_operations vt6421_sata_ops = { | |||
| 128 | .scr_write = svia_scr_write, | 135 | .scr_write = svia_scr_write, |
| 129 | }; | 136 | }; |
| 130 | 137 | ||
| 138 | static struct ata_port_operations vt8251_ops = { | ||
| 139 | .inherits = &svia_base_ops, | ||
| 140 | .hardreset = sata_std_hardreset, | ||
| 141 | .scr_read = vt8251_scr_read, | ||
| 142 | .scr_write = vt8251_scr_write, | ||
| 143 | }; | ||
| 144 | |||
| 131 | static const struct ata_port_info vt6420_port_info = { | 145 | static const struct ata_port_info vt6420_port_info = { |
| 132 | .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY, | 146 | .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY, |
| 133 | .pio_mask = 0x1f, | 147 | .pio_mask = 0x1f, |
| @@ -152,6 +166,15 @@ static struct ata_port_info vt6421_pport_info = { | |||
| 152 | .port_ops = &vt6421_pata_ops, | 166 | .port_ops = &vt6421_pata_ops, |
| 153 | }; | 167 | }; |
| 154 | 168 | ||
| 169 | static struct ata_port_info vt8251_port_info = { | ||
| 170 | .flags = ATA_FLAG_SATA | ATA_FLAG_SLAVE_POSS | | ||
| 171 | ATA_FLAG_NO_LEGACY, | ||
| 172 | .pio_mask = 0x1f, | ||
| 173 | .mwdma_mask = 0x07, | ||
| 174 | .udma_mask = ATA_UDMA6, | ||
| 175 | .port_ops = &vt8251_ops, | ||
| 176 | }; | ||
| 177 | |||
| 155 | MODULE_AUTHOR("Jeff Garzik"); | 178 | MODULE_AUTHOR("Jeff Garzik"); |
| 156 | MODULE_DESCRIPTION("SCSI low-level driver for VIA SATA controllers"); | 179 | MODULE_DESCRIPTION("SCSI low-level driver for VIA SATA controllers"); |
| 157 | MODULE_LICENSE("GPL"); | 180 | MODULE_LICENSE("GPL"); |
| @@ -174,6 +197,83 @@ static int svia_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val) | |||
| 174 | return 0; | 197 | return 0; |
| 175 | } | 198 | } |
| 176 | 199 | ||
| 200 | static int vt8251_scr_read(struct ata_link *link, unsigned int scr, u32 *val) | ||
| 201 | { | ||
| 202 | static const u8 ipm_tbl[] = { 1, 2, 6, 0 }; | ||
| 203 | struct pci_dev *pdev = to_pci_dev(link->ap->host->dev); | ||
| 204 | int slot = 2 * link->ap->port_no + link->pmp; | ||
| 205 | u32 v = 0; | ||
| 206 | u8 raw; | ||
| 207 | |||
| 208 | switch (scr) { | ||
| 209 | case SCR_STATUS: | ||
| 210 | pci_read_config_byte(pdev, 0xA0 + slot, &raw); | ||
| 211 | |||
| 212 | /* read the DET field, bit0 and 1 of the config byte */ | ||
| 213 | v |= raw & 0x03; | ||
| 214 | |||
| 215 | /* read the SPD field, bit4 of the configure byte */ | ||
| 216 | if (raw & (1 << 4)) | ||
| 217 | v |= 0x02 << 4; | ||
| 218 | else | ||
| 219 | v |= 0x01 << 4; | ||
| 220 | |||
| 221 | /* read the IPM field, bit2 and 3 of the config byte */ | ||
| 222 | v |= ipm_tbl[(raw >> 2) & 0x3]; | ||
| 223 | break; | ||
| 224 | |||
| 225 | case SCR_ERROR: | ||
| 226 | /* devices other than 5287 uses 0xA8 as base */ | ||
| 227 | WARN_ON(pdev->device != 0x5287); | ||
| 228 | pci_read_config_dword(pdev, 0xB0 + slot * 4, &v); | ||
| 229 | break; | ||
| 230 | |||
| 231 | case SCR_CONTROL: | ||
| 232 | pci_read_config_byte(pdev, 0xA4 + slot, &raw); | ||
| 233 | |||
| 234 | /* read the DET field, bit0 and bit1 */ | ||
| 235 | v |= ((raw & 0x02) << 1) | (raw & 0x01); | ||
| 236 | |||
| 237 | /* read the IPM field, bit2 and bit3 */ | ||
| 238 | v |= ((raw >> 2) & 0x03) << 8; | ||
| 239 | break; | ||
| 240 | |||
| 241 | default: | ||
| 242 | return -EINVAL; | ||
| 243 | } | ||
| 244 | |||
| 245 | *val = v; | ||
| 246 | return 0; | ||
| 247 | } | ||
| 248 | |||
| 249 | static int vt8251_scr_write(struct ata_link *link, unsigned int scr, u32 val) | ||
| 250 | { | ||
| 251 | struct pci_dev *pdev = to_pci_dev(link->ap->host->dev); | ||
| 252 | int slot = 2 * link->ap->port_no + link->pmp; | ||
| 253 | u32 v = 0; | ||
| 254 | |||
| 255 | switch (scr) { | ||
| 256 | case SCR_ERROR: | ||
| 257 | /* devices other than 5287 uses 0xA8 as base */ | ||
| 258 | WARN_ON(pdev->device != 0x5287); | ||
| 259 | pci_write_config_dword(pdev, 0xB0 + slot * 4, val); | ||
| 260 | return 0; | ||
| 261 | |||
| 262 | case SCR_CONTROL: | ||
| 263 | /* set the DET field */ | ||
| 264 | v |= ((val & 0x4) >> 1) | (val & 0x1); | ||
| 265 | |||
| 266 | /* set the IPM field */ | ||
| 267 | v |= ((val >> 8) & 0x3) << 2; | ||
| 268 | |||
| 269 | pci_write_config_byte(pdev, 0xA4 + slot, v); | ||
| 270 | return 0; | ||
| 271 | |||
| 272 | default: | ||
| 273 | return -EINVAL; | ||
| 274 | } | ||
| 275 | } | ||
| 276 | |||
| 177 | /** | 277 | /** |
| 178 | * svia_tf_load - send taskfile registers to host controller | 278 | * svia_tf_load - send taskfile registers to host controller |
| 179 | * @ap: Port to which output is sent | 279 | * @ap: Port to which output is sent |
| @@ -396,6 +496,30 @@ static int vt6421_prepare_host(struct pci_dev *pdev, struct ata_host **r_host) | |||
| 396 | return 0; | 496 | return 0; |
| 397 | } | 497 | } |
| 398 | 498 | ||
| 499 | static int vt8251_prepare_host(struct pci_dev *pdev, struct ata_host **r_host) | ||
| 500 | { | ||
| 501 | const struct ata_port_info *ppi[] = { &vt8251_port_info, NULL }; | ||
| 502 | struct ata_host *host; | ||
| 503 | int i, rc; | ||
| 504 | |||
| 505 | rc = ata_pci_sff_prepare_host(pdev, ppi, &host); | ||
| 506 | if (rc) | ||
| 507 | return rc; | ||
| 508 | *r_host = host; | ||
| 509 | |||
| 510 | rc = pcim_iomap_regions(pdev, 1 << 5, DRV_NAME); | ||
| 511 | if (rc) { | ||
| 512 | dev_printk(KERN_ERR, &pdev->dev, "failed to iomap PCI BAR 5\n"); | ||
| 513 | return rc; | ||
| 514 | } | ||
| 515 | |||
| 516 | /* 8251 hosts four sata ports as M/S of the two channels */ | ||
| 517 | for (i = 0; i < host->n_ports; i++) | ||
| 518 | ata_slave_link_init(host->ports[i]); | ||
| 519 | |||
| 520 | return 0; | ||
| 521 | } | ||
| 522 | |||
| 399 | static void svia_configure(struct pci_dev *pdev) | 523 | static void svia_configure(struct pci_dev *pdev) |
| 400 | { | 524 | { |
| 401 | u8 tmp8; | 525 | u8 tmp8; |
| @@ -451,10 +575,10 @@ static int svia_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
| 451 | if (rc) | 575 | if (rc) |
| 452 | return rc; | 576 | return rc; |
| 453 | 577 | ||
| 454 | if (board_id == vt6420) | 578 | if (board_id == vt6421) |
| 455 | bar_sizes = &svia_bar_sizes[0]; | ||
| 456 | else | ||
| 457 | bar_sizes = &vt6421_bar_sizes[0]; | 579 | bar_sizes = &vt6421_bar_sizes[0]; |
| 580 | else | ||
| 581 | bar_sizes = &svia_bar_sizes[0]; | ||
| 458 | 582 | ||
| 459 | for (i = 0; i < ARRAY_SIZE(svia_bar_sizes); i++) | 583 | for (i = 0; i < ARRAY_SIZE(svia_bar_sizes); i++) |
| 460 | if ((pci_resource_start(pdev, i) == 0) || | 584 | if ((pci_resource_start(pdev, i) == 0) || |
| @@ -467,10 +591,19 @@ static int svia_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
| 467 | return -ENODEV; | 591 | return -ENODEV; |
| 468 | } | 592 | } |
| 469 | 593 | ||
| 470 | if (board_id == vt6420) | 594 | switch (board_id) { |
| 595 | case vt6420: | ||
| 471 | rc = vt6420_prepare_host(pdev, &host); | 596 | rc = vt6420_prepare_host(pdev, &host); |
| 472 | else | 597 | break; |
| 598 | case vt6421: | ||
| 473 | rc = vt6421_prepare_host(pdev, &host); | 599 | rc = vt6421_prepare_host(pdev, &host); |
| 600 | break; | ||
| 601 | case vt8251: | ||
| 602 | rc = vt8251_prepare_host(pdev, &host); | ||
| 603 | break; | ||
| 604 | default: | ||
| 605 | rc = -EINVAL; | ||
| 606 | } | ||
| 474 | if (rc) | 607 | if (rc) |
| 475 | return rc; | 608 | return rc; |
| 476 | 609 | ||
