Blame view
drivers/ata/pata_optidma.c
12.1 KB
669a5db41 [libata] Add a bu... |
1 2 3 |
/* * pata_optidma.c - Opti DMA PATA for new ATA layer * (C) 2006 Red Hat Inc |
669a5db41 [libata] Add a bu... |
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
* * The Opti DMA controllers are related to the older PIO PCI controllers * and indeed the VLB ones. The main differences are that the timing * numbers are now based off PCI clocks not VLB and differ, and that * MWDMA is supported. * * This driver should support Viper-N+, FireStar, FireStar Plus. * * These devices support virtual DMA for read (aka the CS5520). Later * chips support UDMA33, but only if the rest of the board logic does, * so you have to get this right. We don't support the virtual DMA * but we do handle UDMA. * * Bits that are worth knowing * Most control registers are shadowed into I/O registers * 0x1F5 bit 0 tells you if the PCI/VLB clock is 33 or 25Mhz * Virtual DMA registers *move* between rev 0x02 and rev 0x10 * UDMA requires a 66MHz FSB * */ #include <linux/kernel.h> #include <linux/module.h> #include <linux/pci.h> #include <linux/init.h> #include <linux/blkdev.h> #include <linux/delay.h> #include <scsi/scsi_host.h> #include <linux/libata.h> #define DRV_NAME "pata_optidma" |
5c25bf0d2 pata_optidma: rew... |
35 |
#define DRV_VERSION "0.3.2" |
669a5db41 [libata] Add a bu... |
36 37 38 39 40 41 42 43 44 45 46 47 48 |
enum { READ_REG = 0, /* index of Read cycle timing register */ WRITE_REG = 1, /* index of Write cycle timing register */ CNTRL_REG = 3, /* index of Control register */ STRAP_REG = 5, /* index of Strap register */ MISC_REG = 6 /* index of Miscellaneous register */ }; static int pci_clock; /* 0 = 33 1 = 25 */ /** * optidma_pre_reset - probe begin |
cc0680a58 libata-link: link... |
49 |
* @link: ATA link |
d4b2bab4f libata: add deadl... |
50 |
* @deadline: deadline jiffies for the operation |
669a5db41 [libata] Add a bu... |
51 52 53 |
* * Set up cable type and use generic probe init */ |
85cd7251b [libata #pata-dri... |
54 |
|
cc0680a58 libata-link: link... |
55 |
static int optidma_pre_reset(struct ata_link *link, unsigned long deadline) |
669a5db41 [libata] Add a bu... |
56 |
{ |
cc0680a58 libata-link: link... |
57 |
struct ata_port *ap = link->ap; |
669a5db41 [libata] Add a bu... |
58 |
struct pci_dev *pdev = to_pci_dev(ap->host->dev); |
85cd7251b [libata #pata-dri... |
59 |
static const struct pci_bits optidma_enable_bits = { |
669a5db41 [libata] Add a bu... |
60 61 |
0x40, 1, 0x08, 0x00 }; |
c961922b7 [PATCH] libata-eh... |
62 63 |
if (ap->port_no && !pci_test_config_bits(pdev, &optidma_enable_bits)) return -ENOENT; |
9363c3825 libata: rename SF... |
64 |
return ata_sff_prereset(link, deadline); |
669a5db41 [libata] Add a bu... |
65 66 67 |
} /** |
669a5db41 [libata] Add a bu... |
68 69 70 71 72 73 |
* optidma_unlock - unlock control registers * @ap: ATA port * * Unlock the control register block for this adapter. Registers must not * be unlocked in a situation where libata might look at them. */ |
85cd7251b [libata #pata-dri... |
74 |
|
669a5db41 [libata] Add a bu... |
75 76 |
static void optidma_unlock(struct ata_port *ap) { |
0d5ff5667 libata: convert t... |
77 |
void __iomem *regio = ap->ioaddr.cmd_addr; |
85cd7251b [libata #pata-dri... |
78 |
|
669a5db41 [libata] Add a bu... |
79 |
/* These 3 unlock the control register access */ |
0d5ff5667 libata: convert t... |
80 81 82 |
ioread16(regio + 1); ioread16(regio + 1); iowrite8(3, regio + 2); |
669a5db41 [libata] Add a bu... |
83 84 85 86 87 88 89 90 |
} /** * optidma_lock - issue temporary relock * @ap: ATA port * * Re-lock the configuration register settings. */ |
85cd7251b [libata #pata-dri... |
91 |
|
669a5db41 [libata] Add a bu... |
92 93 |
static void optidma_lock(struct ata_port *ap) { |
0d5ff5667 libata: convert t... |
94 |
void __iomem *regio = ap->ioaddr.cmd_addr; |
85cd7251b [libata #pata-dri... |
95 |
|
669a5db41 [libata] Add a bu... |
96 |
/* Relock */ |
0d5ff5667 libata: convert t... |
97 |
iowrite8(0x83, regio + 2); |
669a5db41 [libata] Add a bu... |
98 99 100 |
} /** |
5c25bf0d2 pata_optidma: rew... |
101 |
* optidma_mode_setup - set mode data |
669a5db41 [libata] Add a bu... |
102 103 104 105 106 107 108 109 110 111 112 |
* @ap: ATA interface * @adev: ATA device * @mode: Mode to set * * Called to do the DMA or PIO mode setup. Timing numbers are all * pre computed to keep the code clean. There are two tables depending * on the hardware clock speed. * * WARNING: While we do this the IDE registers vanish. If we take an * IRQ here we depend on the host set locking to avoid catastrophe. */ |
5c25bf0d2 pata_optidma: rew... |
113 |
static void optidma_mode_setup(struct ata_port *ap, struct ata_device *adev, u8 mode) |
669a5db41 [libata] Add a bu... |
114 115 116 117 |
{ struct ata_device *pair = ata_dev_pair(adev); int pio = adev->pio_mode - XFER_PIO_0; int dma = adev->dma_mode - XFER_MW_DMA_0; |
0d5ff5667 libata: convert t... |
118 |
void __iomem *regio = ap->ioaddr.cmd_addr; |
669a5db41 [libata] Add a bu... |
119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 |
u8 addr; /* Address table precomputed with a DCLK of 2 */ static const u8 addr_timing[2][5] = { { 0x30, 0x20, 0x20, 0x10, 0x10 }, { 0x20, 0x20, 0x10, 0x10, 0x10 } }; static const u8 data_rec_timing[2][5] = { { 0x59, 0x46, 0x30, 0x20, 0x20 }, { 0x46, 0x32, 0x20, 0x20, 0x10 } }; static const u8 dma_data_rec_timing[2][3] = { { 0x76, 0x20, 0x20 }, { 0x54, 0x20, 0x10 } }; /* Switch from IDE to control mode */ optidma_unlock(ap); |
85cd7251b [libata #pata-dri... |
137 |
|
669a5db41 [libata] Add a bu... |
138 139 140 141 142 143 144 145 146 147 148 |
/* * As with many controllers the address setup time is shared * and must suit both devices if present. FIXME: Check if we * need to look at slowest of PIO/DMA mode of either device */ if (mode >= XFER_MW_DMA_0) addr = 0; else addr = addr_timing[pci_clock][pio]; |
85cd7251b [libata #pata-dri... |
149 |
|
669a5db41 [libata] Add a bu... |
150 151 152 153 154 155 156 157 158 159 |
if (pair) { u8 pair_addr; /* Hardware constraint */ if (pair->dma_mode) pair_addr = 0; else pair_addr = addr_timing[pci_clock][pair->pio_mode - XFER_PIO_0]; if (pair_addr > addr) addr = pair_addr; } |
85cd7251b [libata #pata-dri... |
160 |
|
669a5db41 [libata] Add a bu... |
161 162 |
/* Commence primary programming sequence */ /* First we load the device number into the timing select */ |
0d5ff5667 libata: convert t... |
163 |
iowrite8(adev->devno, regio + MISC_REG); |
669a5db41 [libata] Add a bu... |
164 165 |
/* Now we load the data timings into read data/write data */ if (mode < XFER_MW_DMA_0) { |
0d5ff5667 libata: convert t... |
166 167 |
iowrite8(data_rec_timing[pci_clock][pio], regio + READ_REG); iowrite8(data_rec_timing[pci_clock][pio], regio + WRITE_REG); |
669a5db41 [libata] Add a bu... |
168 |
} else if (mode < XFER_UDMA_0) { |
0d5ff5667 libata: convert t... |
169 170 |
iowrite8(dma_data_rec_timing[pci_clock][dma], regio + READ_REG); iowrite8(dma_data_rec_timing[pci_clock][dma], regio + WRITE_REG); |
669a5db41 [libata] Add a bu... |
171 172 |
} /* Finally we load the address setup into the misc register */ |
0d5ff5667 libata: convert t... |
173 |
iowrite8(addr | adev->devno, regio + MISC_REG); |
669a5db41 [libata] Add a bu... |
174 175 |
/* Programming sequence complete, timing 0 dev 0, timing 1 dev 1 */ |
0d5ff5667 libata: convert t... |
176 |
iowrite8(0x85, regio + CNTRL_REG); |
85cd7251b [libata #pata-dri... |
177 |
|
669a5db41 [libata] Add a bu... |
178 179 |
/* Switch back to IDE mode */ optidma_lock(ap); |
85cd7251b [libata #pata-dri... |
180 |
|
669a5db41 [libata] Add a bu... |
181 182 183 184 185 186 |
/* Note: at this point our programming is incomplete. We are not supposed to program PCI 0x43 "things we hacked onto the chip" until we've done both sets of PIO/DMA timings */ } /** |
5c25bf0d2 pata_optidma: rew... |
187 |
* optiplus_mode_setup - DMA setup for Firestar Plus |
669a5db41 [libata] Add a bu... |
188 189 190 191 192 193 194 195 196 |
* @ap: ATA port * @adev: device * @mode: desired mode * * The Firestar plus has additional UDMA functionality for UDMA0-2 and * requires we do some additional work. Because the base work we must do * is mostly shared we wrap the Firestar setup functionality in this * one */ |
5c25bf0d2 pata_optidma: rew... |
197 |
static void optiplus_mode_setup(struct ata_port *ap, struct ata_device *adev, u8 mode) |
669a5db41 [libata] Add a bu... |
198 199 200 201 202 203 204 |
{ struct pci_dev *pdev = to_pci_dev(ap->host->dev); u8 udcfg; u8 udslave; int dev2 = 2 * adev->devno; int unit = 2 * ap->port_no + adev->devno; int udma = mode - XFER_UDMA_0; |
85cd7251b [libata #pata-dri... |
205 |
|
669a5db41 [libata] Add a bu... |
206 207 208 |
pci_read_config_byte(pdev, 0x44, &udcfg); if (mode <= XFER_UDMA_0) { udcfg &= ~(1 << unit); |
5c25bf0d2 pata_optidma: rew... |
209 |
optidma_mode_setup(ap, adev, adev->dma_mode); |
669a5db41 [libata] Add a bu... |
210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 |
} else { udcfg |= (1 << unit); if (ap->port_no) { pci_read_config_byte(pdev, 0x45, &udslave); udslave &= ~(0x03 << dev2); udslave |= (udma << dev2); pci_write_config_byte(pdev, 0x45, udslave); } else { udcfg &= ~(0x30 << dev2); udcfg |= (udma << dev2); } } pci_write_config_byte(pdev, 0x44, udcfg); } /** * optidma_set_pio_mode - PIO setup callback * @ap: ATA port * @adev: Device * * The libata core provides separate functions for handling PIO and * DMA programming. The architecture of the Firestar makes it easier * for us to have a common function so we provide wrappers */ |
85cd7251b [libata #pata-dri... |
234 |
|
669a5db41 [libata] Add a bu... |
235 236 |
static void optidma_set_pio_mode(struct ata_port *ap, struct ata_device *adev) { |
5c25bf0d2 pata_optidma: rew... |
237 |
optidma_mode_setup(ap, adev, adev->pio_mode); |
669a5db41 [libata] Add a bu... |
238 239 240 241 242 243 244 245 246 247 248 |
} /** * optidma_set_dma_mode - DMA setup callback * @ap: ATA port * @adev: Device * * The libata core provides separate functions for handling PIO and * DMA programming. The architecture of the Firestar makes it easier * for us to have a common function so we provide wrappers */ |
85cd7251b [libata #pata-dri... |
249 |
|
669a5db41 [libata] Add a bu... |
250 251 |
static void optidma_set_dma_mode(struct ata_port *ap, struct ata_device *adev) { |
5c25bf0d2 pata_optidma: rew... |
252 |
optidma_mode_setup(ap, adev, adev->dma_mode); |
669a5db41 [libata] Add a bu... |
253 254 255 256 257 258 259 260 261 262 263 |
} /** * optiplus_set_pio_mode - PIO setup callback * @ap: ATA port * @adev: Device * * The libata core provides separate functions for handling PIO and * DMA programming. The architecture of the Firestar makes it easier * for us to have a common function so we provide wrappers */ |
85cd7251b [libata #pata-dri... |
264 |
|
669a5db41 [libata] Add a bu... |
265 266 |
static void optiplus_set_pio_mode(struct ata_port *ap, struct ata_device *adev) { |
5c25bf0d2 pata_optidma: rew... |
267 |
optiplus_mode_setup(ap, adev, adev->pio_mode); |
669a5db41 [libata] Add a bu... |
268 269 270 271 272 273 274 275 276 277 278 |
} /** * optiplus_set_dma_mode - DMA setup callback * @ap: ATA port * @adev: Device * * The libata core provides separate functions for handling PIO and * DMA programming. The architecture of the Firestar makes it easier * for us to have a common function so we provide wrappers */ |
85cd7251b [libata #pata-dri... |
279 |
|
669a5db41 [libata] Add a bu... |
280 281 |
static void optiplus_set_dma_mode(struct ata_port *ap, struct ata_device *adev) { |
5c25bf0d2 pata_optidma: rew... |
282 |
optiplus_mode_setup(ap, adev, adev->dma_mode); |
669a5db41 [libata] Add a bu... |
283 284 285 286 287 288 289 290 291 |
} /** * optidma_make_bits - PCI setup helper * @adev: ATA device * * Turn the ATA device setup into PCI configuration bits * for register 0x43 and return the two bits needed. */ |
85cd7251b [libata #pata-dri... |
292 |
|
669a5db41 [libata] Add a bu... |
293 294 295 296 297 298 299 300 301 302 303 304 305 |
static u8 optidma_make_bits43(struct ata_device *adev) { static const u8 bits43[5] = { 0, 0, 0, 1, 2 }; if (!ata_dev_enabled(adev)) return 0; if (adev->dma_mode) return adev->dma_mode - XFER_MW_DMA_0; return bits43[adev->pio_mode - XFER_PIO_0]; } /** |
5c25bf0d2 pata_optidma: rew... |
306 |
* optidma_set_mode - mode setup |
0260731f0 libata-link: link... |
307 |
* @link: link to set up |
669a5db41 [libata] Add a bu... |
308 |
* |
5c25bf0d2 pata_optidma: rew... |
309 310 311 |
* Use the standard setup to tune the chipset and then finalise the * configuration by writing the nibble of extra bits of data into * the chip. |
669a5db41 [libata] Add a bu... |
312 |
*/ |
85cd7251b [libata #pata-dri... |
313 |
|
0260731f0 libata-link: link... |
314 |
static int optidma_set_mode(struct ata_link *link, struct ata_device **r_failed) |
669a5db41 [libata] Add a bu... |
315 |
{ |
0260731f0 libata-link: link... |
316 |
struct ata_port *ap = link->ap; |
669a5db41 [libata] Add a bu... |
317 318 319 |
u8 r; int nybble = 4 * ap->port_no; struct pci_dev *pdev = to_pci_dev(ap->host->dev); |
0260731f0 libata-link: link... |
320 |
int rc = ata_do_set_mode(link, r_failed); |
5c25bf0d2 pata_optidma: rew... |
321 322 323 324 |
if (rc == 0) { pci_read_config_byte(pdev, 0x43, &r); r &= (0x0F << nybble); |
0260731f0 libata-link: link... |
325 326 |
r |= (optidma_make_bits43(&link->device[0]) + (optidma_make_bits43(&link->device[0]) << 2)) << nybble; |
5c25bf0d2 pata_optidma: rew... |
327 328 329 |
pci_write_config_byte(pdev, 0x43, r); } return rc; |
669a5db41 [libata] Add a bu... |
330 331 332 |
} static struct scsi_host_template optidma_sht = { |
68d1d07b5 libata: implement... |
333 |
ATA_BMDMA_SHT(DRV_NAME), |
669a5db41 [libata] Add a bu... |
334 335 336 |
}; static struct ata_port_operations optidma_port_ops = { |
029cfd6b7 libata: implement... |
337 338 |
.inherits = &ata_bmdma_port_ops, .cable_detect = ata_cable_40wire, |
669a5db41 [libata] Add a bu... |
339 340 |
.set_piomode = optidma_set_pio_mode, .set_dmamode = optidma_set_dma_mode, |
5c25bf0d2 pata_optidma: rew... |
341 |
.set_mode = optidma_set_mode, |
a1efdaba2 libata: make rese... |
342 |
.prereset = optidma_pre_reset, |
669a5db41 [libata] Add a bu... |
343 344 345 |
}; static struct ata_port_operations optiplus_port_ops = { |
029cfd6b7 libata: implement... |
346 |
.inherits = &optidma_port_ops, |
669a5db41 [libata] Add a bu... |
347 348 |
.set_piomode = optiplus_set_pio_mode, .set_dmamode = optiplus_set_dma_mode, |
669a5db41 [libata] Add a bu... |
349 350 351 352 353 354 |
}; /** * optiplus_with_udma - Look for UDMA capable setup * @pdev; ATA controller */ |
85cd7251b [libata #pata-dri... |
355 |
|
669a5db41 [libata] Add a bu... |
356 357 358 359 360 361 |
static int optiplus_with_udma(struct pci_dev *pdev) { u8 r; int ret = 0; int ioport = 0x22; struct pci_dev *dev1; |
85cd7251b [libata #pata-dri... |
362 |
|
669a5db41 [libata] Add a bu... |
363 364 |
/* Find function 1 */ dev1 = pci_get_device(0x1045, 0xC701, NULL); |
b447916e2 [libata] fix 'if(... |
365 |
if (dev1 == NULL) |
669a5db41 [libata] Add a bu... |
366 |
return 0; |
85cd7251b [libata #pata-dri... |
367 |
|
669a5db41 [libata] Add a bu... |
368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 |
/* Rev must be >= 0x10 */ pci_read_config_byte(dev1, 0x08, &r); if (r < 0x10) goto done_nomsg; /* Read the chipset system configuration to check our mode */ pci_read_config_byte(dev1, 0x5F, &r); ioport |= (r << 8); outb(0x10, ioport); /* Must be 66Mhz sync */ if ((inb(ioport + 2) & 1) == 0) goto done; /* Check the ATA arbitration/timing is suitable */ pci_read_config_byte(pdev, 0x42, &r); if ((r & 0x36) != 0x36) goto done; pci_read_config_byte(dev1, 0x52, &r); if (r & 0x80) /* IDEDIR disabled */ ret = 1; |
85cd7251b [libata #pata-dri... |
387 |
done: |
669a5db41 [libata] Add a bu... |
388 389 390 391 392 393 394 395 396 |
printk(KERN_WARNING "UDMA not supported in this configuration. "); done_nomsg: /* Wrong chip revision */ pci_dev_put(dev1); return ret; } static int optidma_init_one(struct pci_dev *dev, const struct pci_device_id *id) { |
1626aeb88 libata: clean up ... |
397 |
static const struct ata_port_info info_82c700 = { |
1d2808fd3 [libata] PATA dri... |
398 |
.flags = ATA_FLAG_SLAVE_POSS, |
14bdef982 [libata] convert ... |
399 400 |
.pio_mask = ATA_PIO4, .mwdma_mask = ATA_MWDMA2, |
669a5db41 [libata] Add a bu... |
401 402 |
.port_ops = &optidma_port_ops }; |
1626aeb88 libata: clean up ... |
403 |
static const struct ata_port_info info_82c700_udma = { |
1d2808fd3 [libata] PATA dri... |
404 |
.flags = ATA_FLAG_SLAVE_POSS, |
14bdef982 [libata] convert ... |
405 406 407 |
.pio_mask = ATA_PIO4, .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA2, |
669a5db41 [libata] Add a bu... |
408 409 |
.port_ops = &optiplus_port_ops }; |
1626aeb88 libata: clean up ... |
410 |
const struct ata_port_info *ppi[] = { &info_82c700, NULL }; |
f08048e94 libata: PCI devic... |
411 |
int rc; |
669a5db41 [libata] Add a bu... |
412 |
|
06296a1e6 ata: Add and use ... |
413 |
ata_print_version_once(&dev->dev, DRV_VERSION); |
669a5db41 [libata] Add a bu... |
414 |
|
f08048e94 libata: PCI devic... |
415 416 417 |
rc = pcim_enable_device(dev); if (rc) return rc; |
669a5db41 [libata] Add a bu... |
418 419 420 421 |
/* Fixed location chipset magic */ inw(0x1F1); inw(0x1F1); pci_clock = inb(0x1F5) & 1; /* 0 = 33Mhz, 1 = 25Mhz */ |
85cd7251b [libata #pata-dri... |
422 |
|
669a5db41 [libata] Add a bu... |
423 |
if (optiplus_with_udma(dev)) |
1626aeb88 libata: clean up ... |
424 |
ppi[0] = &info_82c700_udma; |
669a5db41 [libata] Add a bu... |
425 |
|
1c5afdf7a libata-sff: separ... |
426 |
return ata_pci_bmdma_init_one(dev, ppi, &optidma_sht, NULL, 0); |
669a5db41 [libata] Add a bu... |
427 428 429 |
} static const struct pci_device_id optidma[] = { |
2d2744fc8 [libata] PCI ID t... |
430 431 432 |
{ PCI_VDEVICE(OPTI, 0xD568), }, /* Opti 82C700 */ { }, |
669a5db41 [libata] Add a bu... |
433 434 435 |
}; static struct pci_driver optidma_pci_driver = { |
2d2744fc8 [libata] PCI ID t... |
436 |
.name = DRV_NAME, |
669a5db41 [libata] Add a bu... |
437 438 |
.id_table = optidma, .probe = optidma_init_one, |
30ced0f0d [PATCH] PATA liba... |
439 |
.remove = ata_pci_remove_one, |
438ac6d5e libata: add missi... |
440 |
#ifdef CONFIG_PM |
30ced0f0d [PATCH] PATA liba... |
441 442 |
.suspend = ata_pci_device_suspend, .resume = ata_pci_device_resume, |
438ac6d5e libata: add missi... |
443 |
#endif |
669a5db41 [libata] Add a bu... |
444 445 446 447 448 449 |
}; static int __init optidma_init(void) { return pci_register_driver(&optidma_pci_driver); } |
669a5db41 [libata] Add a bu... |
450 451 452 453 |
static void __exit optidma_exit(void) { pci_unregister_driver(&optidma_pci_driver); } |
669a5db41 [libata] Add a bu... |
454 455 456 457 458 459 460 461 |
MODULE_AUTHOR("Alan Cox"); MODULE_DESCRIPTION("low-level driver for Opti Firestar/Firestar Plus"); MODULE_LICENSE("GPL"); MODULE_DEVICE_TABLE(pci, optidma); MODULE_VERSION(DRV_VERSION); module_init(optidma_init); module_exit(optidma_exit); |