aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata/pata_cs5536.c
diff options
context:
space:
mode:
authorBartlomiej Zolnierkiewicz <bzolnier@gmail.com>2011-10-13 07:05:24 -0400
committerJeff Garzik <jgarzik@redhat.com>2012-01-08 19:14:58 -0500
commitd63e94a442df14c4e7b02763c3230374218b41f1 (patch)
treecc7483203a367109b2aa31e9585362b1b140557b /drivers/ata/pata_cs5536.c
parent002ae08448e241ea8e304008f9cb4bc836f9ff16 (diff)
pata_cs5536: forward port changes from cs5536
* Fix cable detection to also account for the slave device cable bit. * Disable UDMA when programming MWDMA in cs5536_set_dmamode(). * Don't change UDMA settings in cs5536_set_piomode(). * Add cs5536_program_dtc() helper. * Cleanup and uninline cs5536_[read,write]() methods. Cc: Martin K. Petersen <mkp@mkp.net> Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
Diffstat (limited to 'drivers/ata/pata_cs5536.c')
-rw-r--r--drivers/ata/pata_cs5536.c99
1 files changed, 42 insertions, 57 deletions
diff --git a/drivers/ata/pata_cs5536.c b/drivers/ata/pata_cs5536.c
index 628c8fae5937..7a402c75ab90 100644
--- a/drivers/ata/pata_cs5536.c
+++ b/drivers/ata/pata_cs5536.c
@@ -1,6 +1,7 @@
1/* 1/*
2 * pata_cs5536.c - CS5536 PATA for new ATA layer 2 * pata_cs5536.c - CS5536 PATA for new ATA layer
3 * (C) 2007 Martin K. Petersen <mkp@mkp.net> 3 * (C) 2007 Martin K. Petersen <mkp@mkp.net>
4 * (C) 2011 Bartlomiej Zolnierkiewicz
4 * 5 *
5 * This program is free software; you can redistribute it and/or modify 6 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as 7 * it under the terms of the GNU General Public License version 2 as
@@ -55,24 +56,16 @@ MODULE_PARM_DESC(msr, "Force using MSR to configure IDE function (Default: 0)");
55#define DRV_VERSION "0.0.8" 56#define DRV_VERSION "0.0.8"
56 57
57enum { 58enum {
58 CFG = 0, 59 MSR_IDE_CFG = 0x51300010,
59 DTC = 1,
60 CAST = 2,
61 ETC = 3,
62
63 MSR_IDE_BASE = 0x51300000,
64 MSR_IDE_CFG = (MSR_IDE_BASE + 0x10),
65 MSR_IDE_DTC = (MSR_IDE_BASE + 0x12),
66 MSR_IDE_CAST = (MSR_IDE_BASE + 0x13),
67 MSR_IDE_ETC = (MSR_IDE_BASE + 0x14),
68
69 PCI_IDE_CFG = 0x40, 60 PCI_IDE_CFG = 0x40,
70 PCI_IDE_DTC = 0x48,
71 PCI_IDE_CAST = 0x4c,
72 PCI_IDE_ETC = 0x50,
73 61
74 IDE_CFG_CHANEN = 0x2, 62 CFG = 0,
75 IDE_CFG_CABLE = 0x10000, 63 DTC = 2,
64 CAST = 3,
65 ETC = 4,
66
67 IDE_CFG_CHANEN = (1 << 1),
68 IDE_CFG_CABLE = (1 << 17) | (1 << 16),
76 69
77 IDE_D0_SHIFT = 24, 70 IDE_D0_SHIFT = 24,
78 IDE_D1_SHIFT = 16, 71 IDE_D1_SHIFT = 16,
@@ -84,45 +77,50 @@ enum {
84 IDE_CAST_CMD_MASK = 0xff, 77 IDE_CAST_CMD_MASK = 0xff,
85 IDE_CAST_CMD_SHIFT = 24, 78 IDE_CAST_CMD_SHIFT = 24,
86 79
87 IDE_ETC_NODMA = 0x03, 80 IDE_ETC_UDMA_MASK = 0xc0,
88};
89
90static const u32 msr_reg[4] = {
91 MSR_IDE_CFG, MSR_IDE_DTC, MSR_IDE_CAST, MSR_IDE_ETC,
92};
93
94static const u8 pci_reg[4] = {
95 PCI_IDE_CFG, PCI_IDE_DTC, PCI_IDE_CAST, PCI_IDE_ETC,
96}; 81};
97 82
98static inline int cs5536_read(struct pci_dev *pdev, int reg, u32 *val) 83static int cs5536_read(struct pci_dev *pdev, int reg, u32 *val)
99{ 84{
100 if (unlikely(use_msr)) { 85 if (unlikely(use_msr)) {
101 u32 dummy __maybe_unused; 86 u32 dummy __maybe_unused;
102 87
103 rdmsr(msr_reg[reg], *val, dummy); 88 rdmsr(MSR_IDE_CFG + reg, *val, dummy);
104 return 0; 89 return 0;
105 } 90 }
106 91
107 return pci_read_config_dword(pdev, pci_reg[reg], val); 92 return pci_read_config_dword(pdev, PCI_IDE_CFG + reg * 4, val);
108} 93}
109 94
110static inline int cs5536_write(struct pci_dev *pdev, int reg, int val) 95static int cs5536_write(struct pci_dev *pdev, int reg, int val)
111{ 96{
112 if (unlikely(use_msr)) { 97 if (unlikely(use_msr)) {
113 wrmsr(msr_reg[reg], val, 0); 98 wrmsr(MSR_IDE_CFG + reg, val, 0);
114 return 0; 99 return 0;
115 } 100 }
116 101
117 return pci_write_config_dword(pdev, pci_reg[reg], val); 102 return pci_write_config_dword(pdev, PCI_IDE_CFG + reg * 4, val);
103}
104
105static void cs5536_program_dtc(struct ata_device *adev, u8 tim)
106{
107 struct pci_dev *pdev = to_pci_dev(adev->link->ap->host->dev);
108 int dshift = adev->devno ? IDE_D1_SHIFT : IDE_D0_SHIFT;
109 u32 dtc;
110
111 cs5536_read(pdev, DTC, &dtc);
112 dtc &= ~(IDE_DRV_MASK << dshift);
113 dtc |= tim << dshift;
114 cs5536_write(pdev, DTC, dtc);
118} 115}
119 116
120/** 117/**
121 * cs5536_cable_detect - detect cable type 118 * cs5536_cable_detect - detect cable type
122 * @ap: Port to detect on 119 * @ap: Port to detect on
123 * 120 *
124 * Perform cable detection for ATA66 capable cable. Return a libata 121 * Perform cable detection for ATA66 capable cable.
125 * cable type. 122 *
123 * Returns a cable type.
126 */ 124 */
127 125
128static int cs5536_cable_detect(struct ata_port *ap) 126static int cs5536_cable_detect(struct ata_port *ap)
@@ -132,7 +130,7 @@ static int cs5536_cable_detect(struct ata_port *ap)
132 130
133 cs5536_read(pdev, CFG, &cfg); 131 cs5536_read(pdev, CFG, &cfg);
134 132
135 if (cfg & (IDE_CFG_CABLE << ap->port_no)) 133 if (cfg & IDE_CFG_CABLE)
136 return ATA_CBL_PATA80; 134 return ATA_CBL_PATA80;
137 else 135 else
138 return ATA_CBL_PATA40; 136 return ATA_CBL_PATA40;
@@ -162,19 +160,15 @@ static void cs5536_set_piomode(struct ata_port *ap, struct ata_device *adev)
162 struct ata_device *pair = ata_dev_pair(adev); 160 struct ata_device *pair = ata_dev_pair(adev);
163 int mode = adev->pio_mode - XFER_PIO_0; 161 int mode = adev->pio_mode - XFER_PIO_0;
164 int cmdmode = mode; 162 int cmdmode = mode;
165 int dshift = adev->devno ? IDE_D1_SHIFT : IDE_D0_SHIFT;
166 int cshift = adev->devno ? IDE_CAST_D1_SHIFT : IDE_CAST_D0_SHIFT; 163 int cshift = adev->devno ? IDE_CAST_D1_SHIFT : IDE_CAST_D0_SHIFT;
167 u32 dtc, cast, etc; 164 u32 cast;
168 165
169 if (pair) 166 if (pair)
170 cmdmode = min(mode, pair->pio_mode - XFER_PIO_0); 167 cmdmode = min(mode, pair->pio_mode - XFER_PIO_0);
171 168
172 cs5536_read(pdev, DTC, &dtc); 169 cs5536_program_dtc(adev, drv_timings[mode]);
173 cs5536_read(pdev, CAST, &cast);
174 cs5536_read(pdev, ETC, &etc);
175 170
176 dtc &= ~(IDE_DRV_MASK << dshift); 171 cs5536_read(pdev, CAST, &cast);
177 dtc |= drv_timings[mode] << dshift;
178 172
179 cast &= ~(IDE_CAST_DRV_MASK << cshift); 173 cast &= ~(IDE_CAST_DRV_MASK << cshift);
180 cast |= addr_timings[mode] << cshift; 174 cast |= addr_timings[mode] << cshift;
@@ -182,12 +176,7 @@ static void cs5536_set_piomode(struct ata_port *ap, struct ata_device *adev)
182 cast &= ~(IDE_CAST_CMD_MASK << IDE_CAST_CMD_SHIFT); 176 cast &= ~(IDE_CAST_CMD_MASK << IDE_CAST_CMD_SHIFT);
183 cast |= cmd_timings[cmdmode] << IDE_CAST_CMD_SHIFT; 177 cast |= cmd_timings[cmdmode] << IDE_CAST_CMD_SHIFT;
184 178
185 etc &= ~(IDE_DRV_MASK << dshift);
186 etc |= IDE_ETC_NODMA << dshift;
187
188 cs5536_write(pdev, DTC, dtc);
189 cs5536_write(pdev, CAST, cast); 179 cs5536_write(pdev, CAST, cast);
190 cs5536_write(pdev, ETC, etc);
191} 180}
192 181
193/** 182/**
@@ -208,25 +197,21 @@ static void cs5536_set_dmamode(struct ata_port *ap, struct ata_device *adev)
208 }; 197 };
209 198
210 struct pci_dev *pdev = to_pci_dev(ap->host->dev); 199 struct pci_dev *pdev = to_pci_dev(ap->host->dev);
211 u32 dtc, etc; 200 u32 etc;
212 int mode = adev->dma_mode; 201 int mode = adev->dma_mode;
213 int dshift = adev->devno ? IDE_D1_SHIFT : IDE_D0_SHIFT; 202 int dshift = adev->devno ? IDE_D1_SHIFT : IDE_D0_SHIFT;
214 203
215 if (mode >= XFER_UDMA_0) { 204 cs5536_read(pdev, ETC, &etc);
216 cs5536_read(pdev, ETC, &etc);
217 205
206 if (mode >= XFER_UDMA_0) {
218 etc &= ~(IDE_DRV_MASK << dshift); 207 etc &= ~(IDE_DRV_MASK << dshift);
219 etc |= udma_timings[mode - XFER_UDMA_0] << dshift; 208 etc |= udma_timings[mode - XFER_UDMA_0] << dshift;
220
221 cs5536_write(pdev, ETC, etc);
222 } else { /* MWDMA */ 209 } else { /* MWDMA */
223 cs5536_read(pdev, DTC, &dtc); 210 etc &= ~(IDE_ETC_UDMA_MASK << dshift);
224 211 cs5536_program_dtc(adev, mwdma_timings[mode - XFER_MW_DMA_0]);
225 dtc &= ~(IDE_DRV_MASK << dshift);
226 dtc |= mwdma_timings[mode - XFER_MW_DMA_0] << dshift;
227
228 cs5536_write(pdev, DTC, dtc);
229 } 212 }
213
214 cs5536_write(pdev, ETC, etc);
230} 215}
231 216
232static struct scsi_host_template cs5536_sht = { 217static struct scsi_host_template cs5536_sht = {