diff options
| -rw-r--r-- | drivers/ata/pata_sil680.c | 61 |
1 files changed, 57 insertions, 4 deletions
diff --git a/drivers/ata/pata_sil680.c b/drivers/ata/pata_sil680.c index 2eb75cd74a96..4dc2e73298fd 100644 --- a/drivers/ata/pata_sil680.c +++ b/drivers/ata/pata_sil680.c | |||
| @@ -279,7 +279,7 @@ static struct ata_port_operations sil680_port_ops = { | |||
| 279 | * Returns the final clock settings. | 279 | * Returns the final clock settings. |
| 280 | */ | 280 | */ |
| 281 | 281 | ||
| 282 | static u8 sil680_init_chip(struct pci_dev *pdev) | 282 | static u8 sil680_init_chip(struct pci_dev *pdev, int *try_mmio) |
| 283 | { | 283 | { |
| 284 | u32 class_rev = 0; | 284 | u32 class_rev = 0; |
| 285 | u8 tmpbyte = 0; | 285 | u8 tmpbyte = 0; |
| @@ -297,6 +297,8 @@ static u8 sil680_init_chip(struct pci_dev *pdev) | |||
| 297 | dev_dbg(&pdev->dev, "sil680: BA5_EN = %d clock = %02X\n", | 297 | dev_dbg(&pdev->dev, "sil680: BA5_EN = %d clock = %02X\n", |
| 298 | tmpbyte & 1, tmpbyte & 0x30); | 298 | tmpbyte & 1, tmpbyte & 0x30); |
| 299 | 299 | ||
| 300 | *try_mmio = (tmpbyte & 1) || pci_resource_start(pdev, 5); | ||
| 301 | |||
| 300 | switch(tmpbyte & 0x30) { | 302 | switch(tmpbyte & 0x30) { |
| 301 | case 0x00: | 303 | case 0x00: |
| 302 | /* 133 clock attempt to force it on */ | 304 | /* 133 clock attempt to force it on */ |
| @@ -361,25 +363,76 @@ static int __devinit sil680_init_one(struct pci_dev *pdev, | |||
| 361 | }; | 363 | }; |
| 362 | const struct ata_port_info *ppi[] = { &info, NULL }; | 364 | const struct ata_port_info *ppi[] = { &info, NULL }; |
| 363 | static int printed_version; | 365 | static int printed_version; |
| 366 | struct ata_host *host; | ||
| 367 | void __iomem *mmio_base; | ||
| 368 | int rc, try_mmio; | ||
| 364 | 369 | ||
| 365 | if (!printed_version++) | 370 | if (!printed_version++) |
| 366 | dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); | 371 | dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); |
| 367 | 372 | ||
| 368 | switch(sil680_init_chip(pdev)) | 373 | switch (sil680_init_chip(pdev, &try_mmio)) { |
| 369 | { | ||
| 370 | case 0: | 374 | case 0: |
| 371 | ppi[0] = &info_slow; | 375 | ppi[0] = &info_slow; |
| 372 | break; | 376 | break; |
| 373 | case 0x30: | 377 | case 0x30: |
| 374 | return -ENODEV; | 378 | return -ENODEV; |
| 375 | } | 379 | } |
| 380 | |||
| 381 | if (!try_mmio) | ||
| 382 | goto use_ioports; | ||
| 383 | |||
| 384 | /* Try to acquire MMIO resources and fallback to PIO if | ||
| 385 | * that fails | ||
| 386 | */ | ||
| 387 | rc = pcim_enable_device(pdev); | ||
| 388 | if (rc) | ||
| 389 | return rc; | ||
| 390 | rc = pcim_iomap_regions(pdev, 1 << SIL680_MMIO_BAR, DRV_NAME); | ||
| 391 | if (rc) | ||
| 392 | goto use_ioports; | ||
| 393 | |||
| 394 | /* Allocate host and set it up */ | ||
| 395 | host = ata_host_alloc_pinfo(&pdev->dev, ppi, 2); | ||
| 396 | if (!host) | ||
| 397 | return -ENOMEM; | ||
| 398 | host->iomap = pcim_iomap_table(pdev); | ||
| 399 | |||
| 400 | /* Setup DMA masks */ | ||
| 401 | rc = pci_set_dma_mask(pdev, ATA_DMA_MASK); | ||
| 402 | if (rc) | ||
| 403 | return rc; | ||
| 404 | rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK); | ||
| 405 | if (rc) | ||
| 406 | return rc; | ||
| 407 | pci_set_master(pdev); | ||
| 408 | |||
| 409 | /* Get MMIO base and initialize port addresses */ | ||
| 410 | mmio_base = host->iomap[SIL680_MMIO_BAR]; | ||
| 411 | host->ports[0]->ioaddr.bmdma_addr = mmio_base + 0x00; | ||
| 412 | host->ports[0]->ioaddr.cmd_addr = mmio_base + 0x80; | ||
| 413 | host->ports[0]->ioaddr.ctl_addr = mmio_base + 0x8a; | ||
| 414 | host->ports[0]->ioaddr.altstatus_addr = mmio_base + 0x8a; | ||
| 415 | ata_std_ports(&host->ports[0]->ioaddr); | ||
| 416 | host->ports[1]->ioaddr.bmdma_addr = mmio_base + 0x08; | ||
| 417 | host->ports[1]->ioaddr.cmd_addr = mmio_base + 0xc0; | ||
| 418 | host->ports[1]->ioaddr.ctl_addr = mmio_base + 0xca; | ||
| 419 | host->ports[1]->ioaddr.altstatus_addr = mmio_base + 0xca; | ||
| 420 | ata_std_ports(&host->ports[1]->ioaddr); | ||
| 421 | |||
| 422 | /* Register & activate */ | ||
| 423 | return ata_host_activate(host, pdev->irq, ata_interrupt, IRQF_SHARED, | ||
| 424 | &sil680_sht); | ||
| 425 | |||
| 426 | use_ioports: | ||
| 376 | return ata_pci_init_one(pdev, ppi); | 427 | return ata_pci_init_one(pdev, ppi); |
| 377 | } | 428 | } |
| 378 | 429 | ||
| 379 | #ifdef CONFIG_PM | 430 | #ifdef CONFIG_PM |
| 380 | static int sil680_reinit_one(struct pci_dev *pdev) | 431 | static int sil680_reinit_one(struct pci_dev *pdev) |
| 381 | { | 432 | { |
| 382 | sil680_init_chip(pdev); | 433 | int try_mmio; |
| 434 | |||
| 435 | sil680_init_chip(pdev, &try_mmio); | ||
| 383 | return ata_pci_device_resume(pdev); | 436 | return ata_pci_device_resume(pdev); |
| 384 | } | 437 | } |
| 385 | #endif | 438 | #endif |
