aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata/sata_via.c
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2008-10-21 11:45:57 -0400
committerJeff Garzik <jgarzik@redhat.com>2008-10-22 20:42:47 -0400
commitb78152e9dbab6d6175e2adcbd8c62959e8f0f922 (patch)
tree323680259a4b2a6515f30ee7bf2b167e4a9b9c59 /drivers/ata/sata_via.c
parent816ab89782ac139a8b65147cca990822bb7e8675 (diff)
sata_via: load DEVICE register when CTL changes
VIA controllers clear DEVICE register when IEN changes. Make sure DEVICE is updated along with CTL. This change is separated from Joseph Chan's larger patch. http://thread.gmane.org/gmane.linux.kernel.commits.mm/40640 Signed-off-by: Tejun Heo <tj@kernel.org> Cc: Joseph Chan <JosephChan@via.com.tw> Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
Diffstat (limited to 'drivers/ata/sata_via.c')
-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