Blame view
drivers/ata/pata_sil680.c
11.4 KB
669a5db41 [libata] Add a bu... |
1 2 3 |
/* * pata_sil680.c - SIL680 PATA for new ATA layer * (C) 2005 Red Hat Inc |
669a5db41 [libata] Add a bu... |
4 5 6 7 8 9 10 11 12 13 |
* * based upon * * linux/drivers/ide/pci/siimage.c Version 1.07 Nov 30, 2003 * * Copyright (C) 2001-2002 Andre Hedrick <andre@linux-ide.org> * Copyright (C) 2003 Red Hat <alan@redhat.com> * * May be copied or modified under the terms of the GNU General Public License * |
25985edce Fix common misspe... |
14 |
* Documentation publicly available. |
669a5db41 [libata] Add a bu... |
15 16 17 |
* * If you have strange problems with nVidia chipset systems please * see the SI support documentation and update your system BIOS |
3a4fa0a25 Fix misspellings ... |
18 |
* if necessary |
669a5db41 [libata] Add a bu... |
19 20 21 22 23 24 25 26 27 |
* * TODO * If we know all our devices are LBA28 (or LBA28 sized) we could use * the command fifo mode. */ #include <linux/kernel.h> #include <linux/module.h> #include <linux/pci.h> |
669a5db41 [libata] Add a bu... |
28 29 30 31 32 33 |
#include <linux/blkdev.h> #include <linux/delay.h> #include <scsi/scsi_host.h> #include <linux/libata.h> #define DRV_NAME "pata_sil680" |
871af1210 libata: Add 32bit... |
34 |
#define DRV_VERSION "0.4.9" |
669a5db41 [libata] Add a bu... |
35 |
|
79b0bde15 [libata] pata_sil... |
36 |
#define SIL680_MMIO_BAR 5 |
669a5db41 [libata] Add a bu... |
37 38 |
/** * sil680_selreg - return register base |
6352187ee pata_sil680: docu... |
39 |
* @ap: ATA interface |
669a5db41 [libata] Add a bu... |
40 41 |
* @r: config offset * |
6352187ee pata_sil680: docu... |
42 43 44 |
* Turn a config register offset into the right address in PCI space * to access the control register in question. * |
25985edce Fix common misspe... |
45 |
* Thankfully this is a configuration operation so isn't performance |
669a5db41 [libata] Add a bu... |
46 47 48 49 50 51 52 53 54 55 56 57 |
* criticial. */ static unsigned long sil680_selreg(struct ata_port *ap, int r) { unsigned long base = 0xA0 + r; base += (ap->port_no << 4); return base; } /** * sil680_seldev - return register base |
6352187ee pata_sil680: docu... |
58 |
* @ap: ATA interface |
669a5db41 [libata] Add a bu... |
59 60 |
* @r: config offset * |
6352187ee pata_sil680: docu... |
61 62 63 |
* Turn a config register offset into the right address in PCI space * to access the control register in question including accounting for * the unit shift. |
669a5db41 [libata] Add a bu... |
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 |
*/ static unsigned long sil680_seldev(struct ata_port *ap, struct ata_device *adev, int r) { unsigned long base = 0xA0 + r; base += (ap->port_no << 4); base |= adev->devno ? 2 : 0; return base; } /** * sil680_cable_detect - cable detection * @ap: ATA port * * Perform cable detection. The SIL680 stores this in PCI config * space for us. */ |
7a113d384 pata_sil680: mino... |
82 83 |
static int sil680_cable_detect(struct ata_port *ap) { |
669a5db41 [libata] Add a bu... |
84 85 86 87 88 89 90 91 92 |
struct pci_dev *pdev = to_pci_dev(ap->host->dev); unsigned long addr = sil680_selreg(ap, 0); u8 ata66; pci_read_config_byte(pdev, addr, &ata66); if (ata66 & 1) return ATA_CBL_PATA80; else return ATA_CBL_PATA40; } |
669a5db41 [libata] Add a bu... |
93 |
/** |
6352187ee pata_sil680: docu... |
94 |
* sil680_set_piomode - set PIO mode data |
669a5db41 [libata] Add a bu... |
95 96 97 98 99 100 101 102 103 104 |
* @ap: ATA interface * @adev: ATA device * * Program the SIL680 registers for PIO mode. Note that the task speed * registers are shared between the devices so we must pick the lowest * mode for command work. */ static void sil680_set_piomode(struct ata_port *ap, struct ata_device *adev) { |
9b8ad4ac7 pata_sil680: cons... |
105 106 107 108 109 110 |
static const u16 speed_p[5] = { 0x328A, 0x2283, 0x1104, 0x10C3, 0x10C1 }; static const u16 speed_t[5] = { 0x328A, 0x2283, 0x1281, 0x10C3, 0x10C1 }; |
669a5db41 [libata] Add a bu... |
111 112 113 |
unsigned long tfaddr = sil680_selreg(ap, 0x02); unsigned long addr = sil680_seldev(ap, adev, 0x04); |
cb0e34ba5 pata_sil680: Asso... |
114 |
unsigned long addr_mask = 0x80 + 4 * ap->port_no; |
669a5db41 [libata] Add a bu... |
115 116 117 |
struct pci_dev *pdev = to_pci_dev(ap->host->dev); int pio = adev->pio_mode - XFER_PIO_0; int lowest_pio = pio; |
cb0e34ba5 pata_sil680: Asso... |
118 |
int port_shift = 4 * adev->devno; |
669a5db41 [libata] Add a bu... |
119 |
u16 reg; |
cb0e34ba5 pata_sil680: Asso... |
120 |
u8 mode; |
669a5db41 [libata] Add a bu... |
121 122 123 124 125 126 127 128 129 130 |
struct ata_device *pair = ata_dev_pair(adev); if (pair != NULL && adev->pio_mode > pair->pio_mode) lowest_pio = pair->pio_mode - XFER_PIO_0; pci_write_config_word(pdev, addr, speed_p[pio]); pci_write_config_word(pdev, tfaddr, speed_t[lowest_pio]); pci_read_config_word(pdev, tfaddr-2, ®); |
cb0e34ba5 pata_sil680: Asso... |
131 |
pci_read_config_byte(pdev, addr_mask, &mode); |
a84471fe2 [libata] Trim tra... |
132 |
|
669a5db41 [libata] Add a bu... |
133 |
reg &= ~0x0200; /* Clear IORDY */ |
cb0e34ba5 pata_sil680: Asso... |
134 |
mode &= ~(3 << port_shift); /* Clear IORDY and DMA bits */ |
a84471fe2 [libata] Trim tra... |
135 |
|
cb0e34ba5 pata_sil680: Asso... |
136 |
if (ata_pio_need_iordy(adev)) { |
669a5db41 [libata] Add a bu... |
137 |
reg |= 0x0200; /* Enable IORDY */ |
cb0e34ba5 pata_sil680: Asso... |
138 139 |
mode |= 1 << port_shift; } |
669a5db41 [libata] Add a bu... |
140 |
pci_write_config_word(pdev, tfaddr-2, reg); |
cb0e34ba5 pata_sil680: Asso... |
141 |
pci_write_config_byte(pdev, addr_mask, mode); |
669a5db41 [libata] Add a bu... |
142 143 144 |
} /** |
6352187ee pata_sil680: docu... |
145 |
* sil680_set_dmamode - set DMA mode data |
669a5db41 [libata] Add a bu... |
146 147 148 |
* @ap: ATA interface * @adev: ATA device * |
6352187ee pata_sil680: docu... |
149 150 151 |
* Program the MWDMA/UDMA modes for the sil680 chipset. * * The MWDMA mode values are pulled from a lookup table |
669a5db41 [libata] Add a bu... |
152 153 154 155 156 |
* while the chipset uses mode number for UDMA. */ static void sil680_set_dmamode(struct ata_port *ap, struct ata_device *adev) { |
9b8ad4ac7 pata_sil680: cons... |
157 |
static const u8 ultra_table[2][7] = { |
669a5db41 [libata] Add a bu... |
158 159 160 |
{ 0x0C, 0x07, 0x05, 0x04, 0x02, 0x01, 0xFF }, /* 100MHz */ { 0x0F, 0x0B, 0x07, 0x05, 0x03, 0x02, 0x01 }, /* 133Mhz */ }; |
9b8ad4ac7 pata_sil680: cons... |
161 |
static const u16 dma_table[3] = { 0x2208, 0x10C2, 0x10C1 }; |
669a5db41 [libata] Add a bu... |
162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 |
struct pci_dev *pdev = to_pci_dev(ap->host->dev); unsigned long ma = sil680_seldev(ap, adev, 0x08); unsigned long ua = sil680_seldev(ap, adev, 0x0C); unsigned long addr_mask = 0x80 + 4 * ap->port_no; int port_shift = adev->devno * 4; u8 scsc, mode; u16 multi, ultra; pci_read_config_byte(pdev, 0x8A, &scsc); pci_read_config_byte(pdev, addr_mask, &mode); pci_read_config_word(pdev, ma, &multi); pci_read_config_word(pdev, ua, &ultra); /* Mask timing bits */ ultra &= ~0x3F; mode &= ~(0x03 << port_shift); /* Extract scsc */ |
7a113d384 pata_sil680: mino... |
181 |
scsc = (scsc & 0x30) ? 1 : 0; |
669a5db41 [libata] Add a bu... |
182 183 184 185 186 187 188 189 190 191 192 193 194 |
if (adev->dma_mode >= XFER_UDMA_0) { multi = 0x10C1; ultra |= ultra_table[scsc][adev->dma_mode - XFER_UDMA_0]; mode |= (0x03 << port_shift); } else { multi = dma_table[adev->dma_mode - XFER_MW_DMA_0]; mode |= (0x02 << port_shift); } pci_write_config_byte(pdev, addr_mask, mode); pci_write_config_word(pdev, ma, multi); pci_write_config_word(pdev, ua, ultra); } |
c4acf99bd pata_sil680: Do o... |
195 196 197 198 199 200 201 202 203 204 205 206 |
/** * sil680_sff_exec_command - issue ATA command to host controller * @ap: port to which command is being issued * @tf: ATA taskfile register set * * Issues ATA command, with proper synchronization with interrupt * handler / other threads. Use our MMIO space for PCI posting to avoid * a hideously slow cycle all the way to the device. * * LOCKING: * spin_lock_irqsave(host lock) */ |
ada5b12ec pata_sil680: make... |
207 208 |
static void sil680_sff_exec_command(struct ata_port *ap, const struct ata_taskfile *tf) |
c4acf99bd pata_sil680: Do o... |
209 210 211 212 213 214 |
{ DPRINTK("ata%u: cmd 0x%X ", ap->print_id, tf->command); iowrite8(tf->command, ap->ioaddr.command_addr); ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_CMD); } |
9b980e10f pata_sil680: impl... |
215 216 217 218 219 220 221 222 223 224 |
static bool sil680_sff_irq_check(struct ata_port *ap) { struct pci_dev *pdev = to_pci_dev(ap->host->dev); unsigned long addr = sil680_selreg(ap, 1); u8 val; pci_read_config_byte(pdev, addr, &val); return val & 0x08; } |
669a5db41 [libata] Add a bu... |
225 |
static struct scsi_host_template sil680_sht = { |
68d1d07b5 libata: implement... |
226 |
ATA_BMDMA_SHT(DRV_NAME), |
669a5db41 [libata] Add a bu... |
227 |
}; |
c4acf99bd pata_sil680: Do o... |
228 |
|
669a5db41 [libata] Add a bu... |
229 |
static struct ata_port_operations sil680_port_ops = { |
c4acf99bd pata_sil680: Do o... |
230 231 |
.inherits = &ata_bmdma32_port_ops, .sff_exec_command = sil680_sff_exec_command, |
9b980e10f pata_sil680: impl... |
232 |
.sff_irq_check = sil680_sff_irq_check, |
c4acf99bd pata_sil680: Do o... |
233 234 235 |
.cable_detect = sil680_cable_detect, .set_piomode = sil680_set_piomode, .set_dmamode = sil680_set_dmamode, |
669a5db41 [libata] Add a bu... |
236 |
}; |
8550c1637 [PATCH] pata_sil6... |
237 238 239 240 241 242 243 244 |
/** * sil680_init_chip - chip setup * @pdev: PCI device * * Perform all the chip setup which must be done both when the device * is powered up on boot and when we resume in case we resumed from RAM. * Returns the final clock settings. */ |
f20b16ff7 [libata] trim tra... |
245 |
|
2b9e68f72 [libata] pata_sil... |
246 |
static u8 sil680_init_chip(struct pci_dev *pdev, int *try_mmio) |
669a5db41 [libata] Add a bu... |
247 |
{ |
669a5db41 [libata] Add a bu... |
248 |
u8 tmpbyte = 0; |
7a113d384 pata_sil680: mino... |
249 |
/* FIXME: double check */ |
89d3b3603 ata: use pci_dev-... |
250 251 |
pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, pdev->revision ? 1 : 255); |
669a5db41 [libata] Add a bu... |
252 253 254 255 256 |
pci_write_config_byte(pdev, 0x80, 0x00); pci_write_config_byte(pdev, 0x84, 0x00); pci_read_config_byte(pdev, 0x8A, &tmpbyte); |
79b0bde15 [libata] pata_sil... |
257 258 259 |
dev_dbg(&pdev->dev, "sil680: BA5_EN = %d clock = %02X ", tmpbyte & 1, tmpbyte & 0x30); |
669a5db41 [libata] Add a bu... |
260 |
|
0f436eff5 pata_sil680: only... |
261 |
*try_mmio = 0; |
47d692a94 pata_sil680: conv... |
262 |
#ifdef CONFIG_PPC |
0f436eff5 pata_sil680: only... |
263 264 265 |
if (machine_is(cell)) *try_mmio = (tmpbyte & 1) || pci_resource_start(pdev, 5); #endif |
2b9e68f72 [libata] pata_sil... |
266 |
|
7a113d384 pata_sil680: mino... |
267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 |
switch (tmpbyte & 0x30) { case 0x00: /* 133 clock attempt to force it on */ pci_write_config_byte(pdev, 0x8A, tmpbyte|0x10); break; case 0x30: /* if clocking is disabled */ /* 133 clock attempt to force it on */ pci_write_config_byte(pdev, 0x8A, tmpbyte & ~0x20); break; case 0x10: /* 133 already */ break; case 0x20: /* BIOS set PCI x2 clocking */ break; |
669a5db41 [libata] Add a bu... |
283 284 285 |
} pci_read_config_byte(pdev, 0x8A, &tmpbyte); |
79b0bde15 [libata] pata_sil... |
286 287 288 |
dev_dbg(&pdev->dev, "sil680: BA5_EN = %d clock = %02X ", tmpbyte & 1, tmpbyte & 0x30); |
669a5db41 [libata] Add a bu... |
289 290 291 292 293 294 295 296 297 298 299 |
pci_write_config_byte(pdev, 0xA1, 0x72); pci_write_config_word(pdev, 0xA2, 0x328A); pci_write_config_dword(pdev, 0xA4, 0x62DD62DD); pci_write_config_dword(pdev, 0xA8, 0x43924392); pci_write_config_dword(pdev, 0xAC, 0x40094009); pci_write_config_byte(pdev, 0xB1, 0x72); pci_write_config_word(pdev, 0xB2, 0x328A); pci_write_config_dword(pdev, 0xB4, 0x62DD62DD); pci_write_config_dword(pdev, 0xB8, 0x43924392); pci_write_config_dword(pdev, 0xBC, 0x40094009); |
7a113d384 pata_sil680: mino... |
300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 |
switch (tmpbyte & 0x30) { case 0x00: printk(KERN_INFO "sil680: 100MHz clock. "); break; case 0x10: printk(KERN_INFO "sil680: 133MHz clock. "); break; case 0x20: printk(KERN_INFO "sil680: Using PCI clock. "); break; /* This last case is _NOT_ ok */ case 0x30: printk(KERN_ERR "sil680: Clock disabled ? "); |
8550c1637 [PATCH] pata_sil6... |
317 318 319 |
} return tmpbyte & 0x30; } |
0ec249146 Drivers: ata: rem... |
320 |
static int sil680_init_one(struct pci_dev *pdev, const struct pci_device_id *id) |
8550c1637 [PATCH] pata_sil6... |
321 |
{ |
1626aeb88 libata: clean up ... |
322 |
static const struct ata_port_info info = { |
1d2808fd3 [libata] PATA dri... |
323 |
.flags = ATA_FLAG_SLAVE_POSS, |
14bdef982 [libata] convert ... |
324 325 |
.pio_mask = ATA_PIO4, .mwdma_mask = ATA_MWDMA2, |
bf6263a85 [libata] Use ATA_... |
326 |
.udma_mask = ATA_UDMA6, |
8550c1637 [PATCH] pata_sil6... |
327 328 |
.port_ops = &sil680_port_ops }; |
1626aeb88 libata: clean up ... |
329 |
static const struct ata_port_info info_slow = { |
1d2808fd3 [libata] PATA dri... |
330 |
.flags = ATA_FLAG_SLAVE_POSS, |
14bdef982 [libata] convert ... |
331 332 |
.pio_mask = ATA_PIO4, .mwdma_mask = ATA_MWDMA2, |
bf6263a85 [libata] Use ATA_... |
333 |
.udma_mask = ATA_UDMA5, |
8550c1637 [PATCH] pata_sil6... |
334 335 |
.port_ops = &sil680_port_ops }; |
1626aeb88 libata: clean up ... |
336 |
const struct ata_port_info *ppi[] = { &info, NULL }; |
2b9e68f72 [libata] pata_sil... |
337 338 339 |
struct ata_host *host; void __iomem *mmio_base; int rc, try_mmio; |
8550c1637 [PATCH] pata_sil6... |
340 |
|
06296a1e6 ata: Add and use ... |
341 |
ata_print_version_once(&pdev->dev, DRV_VERSION); |
8550c1637 [PATCH] pata_sil6... |
342 |
|
f08048e94 libata: PCI devic... |
343 344 345 |
rc = pcim_enable_device(pdev); if (rc) return rc; |
2b9e68f72 [libata] pata_sil... |
346 |
switch (sil680_init_chip(pdev, &try_mmio)) { |
8550c1637 [PATCH] pata_sil6... |
347 |
case 0: |
1626aeb88 libata: clean up ... |
348 |
ppi[0] = &info_slow; |
8550c1637 [PATCH] pata_sil6... |
349 350 351 |
break; case 0x30: return -ENODEV; |
669a5db41 [libata] Add a bu... |
352 |
} |
2b9e68f72 [libata] pata_sil... |
353 354 355 356 357 358 359 |
if (!try_mmio) goto use_ioports; /* Try to acquire MMIO resources and fallback to PIO if * that fails */ |
2b9e68f72 [libata] pata_sil... |
360 361 362 363 364 365 366 367 368 369 370 |
rc = pcim_iomap_regions(pdev, 1 << SIL680_MMIO_BAR, DRV_NAME); if (rc) goto use_ioports; /* Allocate host and set it up */ host = ata_host_alloc_pinfo(&pdev->dev, ppi, 2); if (!host) return -ENOMEM; host->iomap = pcim_iomap_table(pdev); /* Setup DMA masks */ |
c54c719b5 ata: remove depre... |
371 |
rc = dma_set_mask(&pdev->dev, ATA_DMA_MASK); |
2b9e68f72 [libata] pata_sil... |
372 373 |
if (rc) return rc; |
c54c719b5 ata: remove depre... |
374 |
rc = dma_set_coherent_mask(&pdev->dev, ATA_DMA_MASK); |
2b9e68f72 [libata] pata_sil... |
375 376 377 378 379 380 381 382 383 384 |
if (rc) return rc; pci_set_master(pdev); /* Get MMIO base and initialize port addresses */ mmio_base = host->iomap[SIL680_MMIO_BAR]; host->ports[0]->ioaddr.bmdma_addr = mmio_base + 0x00; host->ports[0]->ioaddr.cmd_addr = mmio_base + 0x80; host->ports[0]->ioaddr.ctl_addr = mmio_base + 0x8a; host->ports[0]->ioaddr.altstatus_addr = mmio_base + 0x8a; |
9363c3825 libata: rename SF... |
385 |
ata_sff_std_ports(&host->ports[0]->ioaddr); |
2b9e68f72 [libata] pata_sil... |
386 387 388 389 |
host->ports[1]->ioaddr.bmdma_addr = mmio_base + 0x08; host->ports[1]->ioaddr.cmd_addr = mmio_base + 0xc0; host->ports[1]->ioaddr.ctl_addr = mmio_base + 0xca; host->ports[1]->ioaddr.altstatus_addr = mmio_base + 0xca; |
9363c3825 libata: rename SF... |
390 |
ata_sff_std_ports(&host->ports[1]->ioaddr); |
2b9e68f72 [libata] pata_sil... |
391 392 |
/* Register & activate */ |
c3b288942 libata-sff: separ... |
393 |
return ata_host_activate(host, pdev->irq, ata_bmdma_interrupt, |
9363c3825 libata: rename SF... |
394 |
IRQF_SHARED, &sil680_sht); |
2b9e68f72 [libata] pata_sil... |
395 396 |
use_ioports: |
1c5afdf7a libata-sff: separ... |
397 |
return ata_pci_bmdma_init_one(pdev, ppi, &sil680_sht, NULL, 0); |
669a5db41 [libata] Add a bu... |
398 |
} |
58eb8cd56 ata: use CONFIG_P... |
399 |
#ifdef CONFIG_PM_SLEEP |
8550c1637 [PATCH] pata_sil6... |
400 401 |
static int sil680_reinit_one(struct pci_dev *pdev) { |
0a86e1c85 ata: use pci_get_... |
402 |
struct ata_host *host = pci_get_drvdata(pdev); |
f08048e94 libata: PCI devic... |
403 |
int try_mmio, rc; |
2b9e68f72 [libata] pata_sil... |
404 |
|
f08048e94 libata: PCI devic... |
405 406 407 |
rc = ata_pci_device_do_resume(pdev); if (rc) return rc; |
2b9e68f72 [libata] pata_sil... |
408 |
sil680_init_chip(pdev, &try_mmio); |
f08048e94 libata: PCI devic... |
409 410 |
ata_host_resume(host); return 0; |
8550c1637 [PATCH] pata_sil6... |
411 |
} |
438ac6d5e libata: add missi... |
412 |
#endif |
8550c1637 [PATCH] pata_sil6... |
413 |
|
669a5db41 [libata] Add a bu... |
414 |
static const struct pci_device_id sil680[] = { |
2d2744fc8 [libata] PCI ID t... |
415 416 417 |
{ PCI_VDEVICE(CMD, PCI_DEVICE_ID_SII_680), }, { }, |
669a5db41 [libata] Add a bu... |
418 419 420 |
}; static struct pci_driver sil680_pci_driver = { |
2d2744fc8 [libata] PCI ID t... |
421 |
.name = DRV_NAME, |
669a5db41 [libata] Add a bu... |
422 423 |
.id_table = sil680, .probe = sil680_init_one, |
8550c1637 [PATCH] pata_sil6... |
424 |
.remove = ata_pci_remove_one, |
58eb8cd56 ata: use CONFIG_P... |
425 |
#ifdef CONFIG_PM_SLEEP |
8550c1637 [PATCH] pata_sil6... |
426 427 |
.suspend = ata_pci_device_suspend, .resume = sil680_reinit_one, |
438ac6d5e libata: add missi... |
428 |
#endif |
669a5db41 [libata] Add a bu... |
429 |
}; |
2fc75da0c ata: use module_p... |
430 |
module_pci_driver(sil680_pci_driver); |
669a5db41 [libata] Add a bu... |
431 |
|
669a5db41 [libata] Add a bu... |
432 433 434 435 436 |
MODULE_AUTHOR("Alan Cox"); MODULE_DESCRIPTION("low-level driver for SI680 PATA"); MODULE_LICENSE("GPL"); MODULE_DEVICE_TABLE(pci, sil680); MODULE_VERSION(DRV_VERSION); |