diff options
Diffstat (limited to 'drivers/ata/sata_via.c')
-rw-r--r-- | drivers/ata/sata_via.c | 188 |
1 files changed, 175 insertions, 13 deletions
diff --git a/drivers/ata/sata_via.c b/drivers/ata/sata_via.c index 1cfa74535d9..c18935f0bda 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,9 @@ 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); | ||
80 | static void svia_tf_load(struct ata_port *ap, const struct ata_taskfile *tf); | ||
73 | static void svia_noop_freeze(struct ata_port *ap); | 81 | static void svia_noop_freeze(struct ata_port *ap); |
74 | static int vt6420_prereset(struct ata_link *link, unsigned long deadline); | 82 | static int vt6420_prereset(struct ata_link *link, unsigned long deadline); |
75 | static int vt6421_pata_cable_detect(struct ata_port *ap); | 83 | static int vt6421_pata_cable_detect(struct ata_port *ap); |
@@ -78,12 +86,12 @@ static void vt6421_set_dma_mode(struct ata_port *ap, struct ata_device *adev); | |||
78 | 86 | ||
79 | static const struct pci_device_id svia_pci_tbl[] = { | 87 | static const struct pci_device_id svia_pci_tbl[] = { |
80 | { PCI_VDEVICE(VIA, 0x5337), vt6420 }, | 88 | { PCI_VDEVICE(VIA, 0x5337), vt6420 }, |
81 | { PCI_VDEVICE(VIA, 0x0591), vt6420 }, | 89 | { PCI_VDEVICE(VIA, 0x0591), vt6420 }, /* 2 sata chnls (Master) */ |
82 | { PCI_VDEVICE(VIA, 0x3149), vt6420 }, | 90 | { PCI_VDEVICE(VIA, 0x3149), vt6420 }, /* 2 sata chnls (Master) */ |
83 | { PCI_VDEVICE(VIA, 0x3249), vt6421 }, | 91 | { PCI_VDEVICE(VIA, 0x3249), vt6421 }, /* 2 sata chnls, 1 pata chnl */ |
84 | { PCI_VDEVICE(VIA, 0x5287), vt6420 }, | ||
85 | { PCI_VDEVICE(VIA, 0x5372), vt6420 }, | 92 | { PCI_VDEVICE(VIA, 0x5372), vt6420 }, |
86 | { PCI_VDEVICE(VIA, 0x7372), vt6420 }, | 93 | { PCI_VDEVICE(VIA, 0x7372), vt6420 }, |
94 | { PCI_VDEVICE(VIA, 0x5287), vt8251 }, /* 2 sata chnls (Master/Slave) */ | ||
87 | 95 | ||
88 | { } /* terminate list */ | 96 | { } /* terminate list */ |
89 | }; | 97 | }; |
@@ -103,25 +111,37 @@ static struct scsi_host_template svia_sht = { | |||
103 | ATA_BMDMA_SHT(DRV_NAME), | 111 | ATA_BMDMA_SHT(DRV_NAME), |
104 | }; | 112 | }; |
105 | 113 | ||
106 | static struct ata_port_operations vt6420_sata_ops = { | 114 | static struct ata_port_operations svia_base_ops = { |
107 | .inherits = &ata_bmdma_port_ops, | 115 | .inherits = &ata_bmdma_port_ops, |
116 | .sff_tf_load = svia_tf_load, | ||
117 | }; | ||
118 | |||
119 | static struct ata_port_operations vt6420_sata_ops = { | ||
120 | .inherits = &svia_base_ops, | ||
108 | .freeze = svia_noop_freeze, | 121 | .freeze = svia_noop_freeze, |
109 | .prereset = vt6420_prereset, | 122 | .prereset = vt6420_prereset, |
110 | }; | 123 | }; |
111 | 124 | ||
112 | static struct ata_port_operations vt6421_pata_ops = { | 125 | static struct ata_port_operations vt6421_pata_ops = { |
113 | .inherits = &ata_bmdma_port_ops, | 126 | .inherits = &svia_base_ops, |
114 | .cable_detect = vt6421_pata_cable_detect, | 127 | .cable_detect = vt6421_pata_cable_detect, |
115 | .set_piomode = vt6421_set_pio_mode, | 128 | .set_piomode = vt6421_set_pio_mode, |
116 | .set_dmamode = vt6421_set_dma_mode, | 129 | .set_dmamode = vt6421_set_dma_mode, |
117 | }; | 130 | }; |
118 | 131 | ||
119 | static struct ata_port_operations vt6421_sata_ops = { | 132 | static struct ata_port_operations vt6421_sata_ops = { |
120 | .inherits = &ata_bmdma_port_ops, | 133 | .inherits = &svia_base_ops, |
121 | .scr_read = svia_scr_read, | 134 | .scr_read = svia_scr_read, |
122 | .scr_write = svia_scr_write, | 135 | .scr_write = svia_scr_write, |
123 | }; | 136 | }; |
124 | 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 | |||
125 | static const struct ata_port_info vt6420_port_info = { | 145 | static const struct ata_port_info vt6420_port_info = { |
126 | .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY, | 146 | .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY, |
127 | .pio_mask = 0x1f, | 147 | .pio_mask = 0x1f, |
@@ -146,6 +166,15 @@ static struct ata_port_info vt6421_pport_info = { | |||
146 | .port_ops = &vt6421_pata_ops, | 166 | .port_ops = &vt6421_pata_ops, |
147 | }; | 167 | }; |
148 | 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 | |||
149 | MODULE_AUTHOR("Jeff Garzik"); | 178 | MODULE_AUTHOR("Jeff Garzik"); |
150 | MODULE_DESCRIPTION("SCSI low-level driver for VIA SATA controllers"); | 179 | MODULE_DESCRIPTION("SCSI low-level driver for VIA SATA controllers"); |
151 | MODULE_LICENSE("GPL"); | 180 | MODULE_LICENSE("GPL"); |
@@ -168,6 +197,106 @@ static int svia_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val) | |||
168 | return 0; | 197 | return 0; |
169 | } | 198 | } |
170 | 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 | |||
277 | /** | ||
278 | * svia_tf_load - send taskfile registers to host controller | ||
279 | * @ap: Port to which output is sent | ||
280 | * @tf: ATA taskfile register set | ||
281 | * | ||
282 | * Outputs ATA taskfile to standard ATA host controller. | ||
283 | * | ||
284 | * This is to fix the internal bug of via chipsets, which will | ||
285 | * reset the device register after changing the IEN bit on ctl | ||
286 | * register. | ||
287 | */ | ||
288 | static void svia_tf_load(struct ata_port *ap, const struct ata_taskfile *tf) | ||
289 | { | ||
290 | struct ata_taskfile ttf; | ||
291 | |||
292 | if (tf->ctl != ap->last_ctl) { | ||
293 | ttf = *tf; | ||
294 | ttf.flags |= ATA_TFLAG_DEVICE; | ||
295 | tf = &ttf; | ||
296 | } | ||
297 | ata_sff_tf_load(ap, tf); | ||
298 | } | ||
299 | |||
171 | static void svia_noop_freeze(struct ata_port *ap) | 300 | static void svia_noop_freeze(struct ata_port *ap) |
172 | { | 301 | { |
173 | /* Some VIA controllers choke if ATA_NIEN is manipulated in | 302 | /* Some VIA controllers choke if ATA_NIEN is manipulated in |
@@ -367,6 +496,30 @@ static int vt6421_prepare_host(struct pci_dev *pdev, struct ata_host **r_host) | |||
367 | return 0; | 496 | return 0; |
368 | } | 497 | } |
369 | 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 | |||
370 | static void svia_configure(struct pci_dev *pdev) | 523 | static void svia_configure(struct pci_dev *pdev) |
371 | { | 524 | { |
372 | u8 tmp8; | 525 | u8 tmp8; |
@@ -422,10 +575,10 @@ static int svia_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
422 | if (rc) | 575 | if (rc) |
423 | return rc; | 576 | return rc; |
424 | 577 | ||
425 | if (board_id == vt6420) | 578 | if (board_id == vt6421) |
426 | bar_sizes = &svia_bar_sizes[0]; | ||
427 | else | ||
428 | bar_sizes = &vt6421_bar_sizes[0]; | 579 | bar_sizes = &vt6421_bar_sizes[0]; |
580 | else | ||
581 | bar_sizes = &svia_bar_sizes[0]; | ||
429 | 582 | ||
430 | for (i = 0; i < ARRAY_SIZE(svia_bar_sizes); i++) | 583 | for (i = 0; i < ARRAY_SIZE(svia_bar_sizes); i++) |
431 | if ((pci_resource_start(pdev, i) == 0) || | 584 | if ((pci_resource_start(pdev, i) == 0) || |
@@ -438,10 +591,19 @@ static int svia_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
438 | return -ENODEV; | 591 | return -ENODEV; |
439 | } | 592 | } |
440 | 593 | ||
441 | if (board_id == vt6420) | 594 | switch (board_id) { |
595 | case vt6420: | ||
442 | rc = vt6420_prepare_host(pdev, &host); | 596 | rc = vt6420_prepare_host(pdev, &host); |
443 | else | 597 | break; |
598 | case vt6421: | ||
444 | 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 | } | ||
445 | if (rc) | 607 | if (rc) |
446 | return rc; | 608 | return rc; |
447 | 609 | ||