aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/ata/sata_via.c35
1 files changed, 32 insertions, 3 deletions
diff --git a/drivers/ata/sata_via.c b/drivers/ata/sata_via.c
index 1cfa74535d91..5b72e734300a 100644
--- a/drivers/ata/sata_via.c
+++ b/drivers/ata/sata_via.c
@@ -70,6 +70,7 @@ enum {
70static int svia_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); 70static int svia_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
71static int svia_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val); 71static int svia_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val);
72static int svia_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val); 72static int svia_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val);
73static void svia_tf_load(struct ata_port *ap, const struct ata_taskfile *tf);
73static void svia_noop_freeze(struct ata_port *ap); 74static void svia_noop_freeze(struct ata_port *ap);
74static int vt6420_prereset(struct ata_link *link, unsigned long deadline); 75static int vt6420_prereset(struct ata_link *link, unsigned long deadline);
75static int vt6421_pata_cable_detect(struct ata_port *ap); 76static int vt6421_pata_cable_detect(struct ata_port *ap);
@@ -103,21 +104,26 @@ static struct scsi_host_template svia_sht = {
103 ATA_BMDMA_SHT(DRV_NAME), 104 ATA_BMDMA_SHT(DRV_NAME),
104}; 105};
105 106
106static struct ata_port_operations vt6420_sata_ops = { 107static struct ata_port_operations svia_base_ops = {
107 .inherits = &ata_bmdma_port_ops, 108 .inherits = &ata_bmdma_port_ops,
109 .sff_tf_load = svia_tf_load,
110};
111
112static struct ata_port_operations vt6420_sata_ops = {
113 .inherits = &svia_base_ops,
108 .freeze = svia_noop_freeze, 114 .freeze = svia_noop_freeze,
109 .prereset = vt6420_prereset, 115 .prereset = vt6420_prereset,
110}; 116};
111 117
112static struct ata_port_operations vt6421_pata_ops = { 118static struct ata_port_operations vt6421_pata_ops = {
113 .inherits = &ata_bmdma_port_ops, 119 .inherits = &svia_base_ops,
114 .cable_detect = vt6421_pata_cable_detect, 120 .cable_detect = vt6421_pata_cable_detect,
115 .set_piomode = vt6421_set_pio_mode, 121 .set_piomode = vt6421_set_pio_mode,
116 .set_dmamode = vt6421_set_dma_mode, 122 .set_dmamode = vt6421_set_dma_mode,
117}; 123};
118 124
119static struct ata_port_operations vt6421_sata_ops = { 125static struct ata_port_operations vt6421_sata_ops = {
120 .inherits = &ata_bmdma_port_ops, 126 .inherits = &svia_base_ops,
121 .scr_read = svia_scr_read, 127 .scr_read = svia_scr_read,
122 .scr_write = svia_scr_write, 128 .scr_write = svia_scr_write,
123}; 129};
@@ -168,6 +174,29 @@ static int svia_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val)
168 return 0; 174 return 0;
169} 175}
170 176
177/**
178 * svia_tf_load - send taskfile registers to host controller
179 * @ap: Port to which output is sent
180 * @tf: ATA taskfile register set
181 *
182 * Outputs ATA taskfile to standard ATA host controller.
183 *
184 * This is to fix the internal bug of via chipsets, which will
185 * reset the device register after changing the IEN bit on ctl
186 * register.
187 */
188static void svia_tf_load(struct ata_port *ap, const struct ata_taskfile *tf)
189{
190 struct ata_taskfile ttf;
191
192 if (tf->ctl != ap->last_ctl) {
193 ttf = *tf;
194 ttf.flags |= ATA_TFLAG_DEVICE;
195 tf = &ttf;
196 }
197 ata_sff_tf_load(ap, tf);
198}
199
171static void svia_noop_freeze(struct ata_port *ap) 200static void svia_noop_freeze(struct ata_port *ap)
172{ 201{
173 /* Some VIA controllers choke if ATA_NIEN is manipulated in 202 /* Some VIA controllers choke if ATA_NIEN is manipulated in