Blame view
drivers/ata/pata_sil680.c
11.4 KB
669a5db41
|
1 2 3 |
/* * pata_sil680.c - SIL680 PATA for new ATA layer * (C) 2005 Red Hat Inc |
669a5db41
|
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
|
14 |
* Documentation publicly available. |
669a5db41
|
15 16 17 |
* * If you have strange problems with nVidia chipset systems please * see the SI support documentation and update your system BIOS |
3a4fa0a25
|
18 |
* if necessary |
669a5db41
|
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
|
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
|
34 |
#define DRV_VERSION "0.4.9" |
669a5db41
|
35 |
|
79b0bde15
|
36 |
#define SIL680_MMIO_BAR 5 |
669a5db41
|
37 38 |
/** * sil680_selreg - return register base |
6352187ee
|
39 |
* @ap: ATA interface |
669a5db41
|
40 41 |
* @r: config offset * |
6352187ee
|
42 43 44 |
* Turn a config register offset into the right address in PCI space * to access the control register in question. * |
25985edce
|
45 |
* Thankfully this is a configuration operation so isn't performance |
669a5db41
|
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
|
58 |
* @ap: ATA interface |
669a5db41
|
59 60 |
* @r: config offset * |
6352187ee
|
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
|
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
|
82 83 |
static int sil680_cable_detect(struct ata_port *ap) { |
669a5db41
|
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
|
93 |
/** |
6352187ee
|
94 |
* sil680_set_piomode - set PIO mode data |
669a5db41
|
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
|
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
|
111 112 113 |
unsigned long tfaddr = sil680_selreg(ap, 0x02); unsigned long addr = sil680_seldev(ap, adev, 0x04); |
cb0e34ba5
|
114 |
unsigned long addr_mask = 0x80 + 4 * ap->port_no; |
669a5db41
|
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
|
118 |
int port_shift = 4 * adev->devno; |
669a5db41
|
119 |
u16 reg; |
cb0e34ba5
|
120 |
u8 mode; |
669a5db41
|
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
|
131 |
pci_read_config_byte(pdev, addr_mask, &mode); |
a84471fe2
|
132 |
|
669a5db41
|
133 |
reg &= ~0x0200; /* Clear IORDY */ |
cb0e34ba5
|
134 |
mode &= ~(3 << port_shift); /* Clear IORDY and DMA bits */ |
a84471fe2
|
135 |
|
cb0e34ba5
|
136 |
if (ata_pio_need_iordy(adev)) { |
669a5db41
|
137 |
reg |= 0x0200; /* Enable IORDY */ |
cb0e34ba5
|
138 139 |
mode |= 1 << port_shift; } |
669a5db41
|
140 |
pci_write_config_word(pdev, tfaddr-2, reg); |
cb0e34ba5
|
141 |
pci_write_config_byte(pdev, addr_mask, mode); |
669a5db41
|
142 143 144 |
} /** |
6352187ee
|
145 |
* sil680_set_dmamode - set DMA mode data |
669a5db41
|
146 147 148 |
* @ap: ATA interface * @adev: ATA device * |
6352187ee
|
149 150 151 |
* Program the MWDMA/UDMA modes for the sil680 chipset. * * The MWDMA mode values are pulled from a lookup table |
669a5db41
|
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
|
157 |
static const u8 ultra_table[2][7] = { |
669a5db41
|
158 159 160 |
{ 0x0C, 0x07, 0x05, 0x04, 0x02, 0x01, 0xFF }, /* 100MHz */ { 0x0F, 0x0B, 0x07, 0x05, 0x03, 0x02, 0x01 }, /* 133Mhz */ }; |
9b8ad4ac7
|
161 |
static const u16 dma_table[3] = { 0x2208, 0x10C2, 0x10C1 }; |
669a5db41
|
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
|
181 |
scsc = (scsc & 0x30) ? 1 : 0; |
669a5db41
|
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
|
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
|
207 208 |
static void sil680_sff_exec_command(struct ata_port *ap, const struct ata_taskfile *tf) |
c4acf99bd
|
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
|
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
|
225 |
static struct scsi_host_template sil680_sht = { |
68d1d07b5
|
226 |
ATA_BMDMA_SHT(DRV_NAME), |
669a5db41
|
227 |
}; |
c4acf99bd
|
228 |
|
669a5db41
|
229 |
static struct ata_port_operations sil680_port_ops = { |
c4acf99bd
|
230 231 |
.inherits = &ata_bmdma32_port_ops, .sff_exec_command = sil680_sff_exec_command, |
9b980e10f
|
232 |
.sff_irq_check = sil680_sff_irq_check, |
c4acf99bd
|
233 234 235 |
.cable_detect = sil680_cable_detect, .set_piomode = sil680_set_piomode, .set_dmamode = sil680_set_dmamode, |
669a5db41
|
236 |
}; |
8550c1637
|
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
|
245 |
|
2b9e68f72
|
246 |
static u8 sil680_init_chip(struct pci_dev *pdev, int *try_mmio) |
669a5db41
|
247 |
{ |
669a5db41
|
248 |
u8 tmpbyte = 0; |
7a113d384
|
249 |
/* FIXME: double check */ |
89d3b3603
|
250 251 |
pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, pdev->revision ? 1 : 255); |
669a5db41
|
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
|
257 258 259 |
dev_dbg(&pdev->dev, "sil680: BA5_EN = %d clock = %02X ", tmpbyte & 1, tmpbyte & 0x30); |
669a5db41
|
260 |
|
0f436eff5
|
261 |
*try_mmio = 0; |
47d692a94
|
262 |
#ifdef CONFIG_PPC |
0f436eff5
|
263 264 265 |
if (machine_is(cell)) *try_mmio = (tmpbyte & 1) || pci_resource_start(pdev, 5); #endif |
2b9e68f72
|
266 |
|
7a113d384
|
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
|
283 284 285 |
} pci_read_config_byte(pdev, 0x8A, &tmpbyte); |
79b0bde15
|
286 287 288 |
dev_dbg(&pdev->dev, "sil680: BA5_EN = %d clock = %02X ", tmpbyte & 1, tmpbyte & 0x30); |
669a5db41
|
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
|
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
|
317 318 319 |
} return tmpbyte & 0x30; } |
0ec249146
|
320 |
static int sil680_init_one(struct pci_dev *pdev, const struct pci_device_id *id) |
8550c1637
|
321 |
{ |
1626aeb88
|
322 |
static const struct ata_port_info info = { |
1d2808fd3
|
323 |
.flags = ATA_FLAG_SLAVE_POSS, |
14bdef982
|
324 325 |
.pio_mask = ATA_PIO4, .mwdma_mask = ATA_MWDMA2, |
bf6263a85
|
326 |
.udma_mask = ATA_UDMA6, |
8550c1637
|
327 328 |
.port_ops = &sil680_port_ops }; |
1626aeb88
|
329 |
static const struct ata_port_info info_slow = { |
1d2808fd3
|
330 |
.flags = ATA_FLAG_SLAVE_POSS, |
14bdef982
|
331 332 |
.pio_mask = ATA_PIO4, .mwdma_mask = ATA_MWDMA2, |
bf6263a85
|
333 |
.udma_mask = ATA_UDMA5, |
8550c1637
|
334 335 |
.port_ops = &sil680_port_ops }; |
1626aeb88
|
336 |
const struct ata_port_info *ppi[] = { &info, NULL }; |
2b9e68f72
|
337 338 339 |
struct ata_host *host; void __iomem *mmio_base; int rc, try_mmio; |
8550c1637
|
340 |
|
06296a1e6
|
341 |
ata_print_version_once(&pdev->dev, DRV_VERSION); |
8550c1637
|
342 |
|
f08048e94
|
343 344 345 |
rc = pcim_enable_device(pdev); if (rc) return rc; |
2b9e68f72
|
346 |
switch (sil680_init_chip(pdev, &try_mmio)) { |
8550c1637
|
347 |
case 0: |
1626aeb88
|
348 |
ppi[0] = &info_slow; |
8550c1637
|
349 350 351 |
break; case 0x30: return -ENODEV; |
669a5db41
|
352 |
} |
2b9e68f72
|
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
|
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 */ |
b5e555561
|
371 |
rc = dma_set_mask_and_coherent(&pdev->dev, ATA_DMA_MASK); |
2b9e68f72
|
372 373 374 375 376 377 378 379 380 381 |
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
|
382 |
ata_sff_std_ports(&host->ports[0]->ioaddr); |
2b9e68f72
|
383 384 385 386 |
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
|
387 |
ata_sff_std_ports(&host->ports[1]->ioaddr); |
2b9e68f72
|
388 389 |
/* Register & activate */ |
c3b288942
|
390 |
return ata_host_activate(host, pdev->irq, ata_bmdma_interrupt, |
9363c3825
|
391 |
IRQF_SHARED, &sil680_sht); |
2b9e68f72
|
392 393 |
use_ioports: |
1c5afdf7a
|
394 |
return ata_pci_bmdma_init_one(pdev, ppi, &sil680_sht, NULL, 0); |
669a5db41
|
395 |
} |
58eb8cd56
|
396 |
#ifdef CONFIG_PM_SLEEP |
8550c1637
|
397 398 |
static int sil680_reinit_one(struct pci_dev *pdev) { |
0a86e1c85
|
399 |
struct ata_host *host = pci_get_drvdata(pdev); |
f08048e94
|
400 |
int try_mmio, rc; |
2b9e68f72
|
401 |
|
f08048e94
|
402 403 404 |
rc = ata_pci_device_do_resume(pdev); if (rc) return rc; |
2b9e68f72
|
405 |
sil680_init_chip(pdev, &try_mmio); |
f08048e94
|
406 407 |
ata_host_resume(host); return 0; |
8550c1637
|
408 |
} |
438ac6d5e
|
409 |
#endif |
8550c1637
|
410 |
|
669a5db41
|
411 |
static const struct pci_device_id sil680[] = { |
2d2744fc8
|
412 413 414 |
{ PCI_VDEVICE(CMD, PCI_DEVICE_ID_SII_680), }, { }, |
669a5db41
|
415 416 417 |
}; static struct pci_driver sil680_pci_driver = { |
2d2744fc8
|
418 |
.name = DRV_NAME, |
669a5db41
|
419 420 |
.id_table = sil680, .probe = sil680_init_one, |
8550c1637
|
421 |
.remove = ata_pci_remove_one, |
58eb8cd56
|
422 |
#ifdef CONFIG_PM_SLEEP |
8550c1637
|
423 424 |
.suspend = ata_pci_device_suspend, .resume = sil680_reinit_one, |
438ac6d5e
|
425 |
#endif |
669a5db41
|
426 |
}; |
2fc75da0c
|
427 |
module_pci_driver(sil680_pci_driver); |
669a5db41
|
428 |
|
669a5db41
|
429 430 431 432 433 |
MODULE_AUTHOR("Alan Cox"); MODULE_DESCRIPTION("low-level driver for SI680 PATA"); MODULE_LICENSE("GPL"); MODULE_DEVICE_TABLE(pci, sil680); MODULE_VERSION(DRV_VERSION); |