diff options
| -rw-r--r-- | arch/mips/include/asm/txx9/tx4938.h | 13 | ||||
| -rw-r--r-- | arch/mips/txx9/generic/setup_tx4938.c | 47 | ||||
| -rw-r--r-- | arch/mips/txx9/rbtx4938/setup.c | 1 | ||||
| -rw-r--r-- | drivers/ide/Kconfig | 10 | ||||
| -rw-r--r-- | drivers/ide/Makefile | 4 | ||||
| -rw-r--r-- | drivers/ide/ide-cd.c | 1 | ||||
| -rw-r--r-- | drivers/ide/ide-disk.c | 8 | ||||
| -rw-r--r-- | drivers/ide/ide-pci-generic.c (renamed from drivers/ide/generic.c) | 0 | ||||
| -rw-r--r-- | drivers/ide/scc_pata.c | 10 | ||||
| -rw-r--r-- | drivers/ide/sgiioc4.c | 24 | ||||
| -rw-r--r-- | drivers/ide/siimage.c | 2 | ||||
| -rw-r--r-- | drivers/ide/tx4938ide.c | 310 | ||||
| -rw-r--r-- | drivers/ide/tx4939ide.c | 754 |
13 files changed, 1157 insertions, 27 deletions
diff --git a/arch/mips/include/asm/txx9/tx4938.h b/arch/mips/include/asm/txx9/tx4938.h index 989e7751135a..0b068154054c 100644 --- a/arch/mips/include/asm/txx9/tx4938.h +++ b/arch/mips/include/asm/txx9/tx4938.h | |||
| @@ -292,4 +292,17 @@ void tx4938_setup_pcierr_irq(void); | |||
| 292 | void tx4938_irq_init(void); | 292 | void tx4938_irq_init(void); |
| 293 | void tx4938_mtd_init(int ch); | 293 | void tx4938_mtd_init(int ch); |
| 294 | 294 | ||
| 295 | struct tx4938ide_platform_info { | ||
| 296 | /* | ||
| 297 | * I/O port shift, for platforms with ports that are | ||
| 298 | * constantly spaced and need larger than the 1-byte | ||
| 299 | * spacing used by ata_std_ports(). | ||
| 300 | */ | ||
| 301 | unsigned int ioport_shift; | ||
| 302 | unsigned int gbus_clock; /* 0 means no PIO mode tuning. */ | ||
| 303 | unsigned int ebus_ch; | ||
| 304 | }; | ||
| 305 | |||
| 306 | void tx4938_ata_init(unsigned int irq, unsigned int shift, int tune); | ||
| 307 | |||
| 295 | #endif | 308 | #endif |
diff --git a/arch/mips/txx9/generic/setup_tx4938.c b/arch/mips/txx9/generic/setup_tx4938.c index af724e53ef91..25819ff1c350 100644 --- a/arch/mips/txx9/generic/setup_tx4938.c +++ b/arch/mips/txx9/generic/setup_tx4938.c | |||
| @@ -16,6 +16,7 @@ | |||
| 16 | #include <linux/param.h> | 16 | #include <linux/param.h> |
| 17 | #include <linux/ptrace.h> | 17 | #include <linux/ptrace.h> |
| 18 | #include <linux/mtd/physmap.h> | 18 | #include <linux/mtd/physmap.h> |
| 19 | #include <linux/platform_device.h> | ||
| 19 | #include <asm/reboot.h> | 20 | #include <asm/reboot.h> |
| 20 | #include <asm/traps.h> | 21 | #include <asm/traps.h> |
| 21 | #include <asm/txx9irq.h> | 22 | #include <asm/txx9irq.h> |
| @@ -335,6 +336,52 @@ void __init tx4938_mtd_init(int ch) | |||
| 335 | txx9_physmap_flash_init(ch, start, size, &pdata); | 336 | txx9_physmap_flash_init(ch, start, size, &pdata); |
| 336 | } | 337 | } |
| 337 | 338 | ||
| 339 | void __init tx4938_ata_init(unsigned int irq, unsigned int shift, int tune) | ||
| 340 | { | ||
| 341 | struct platform_device *pdev; | ||
| 342 | struct resource res[] = { | ||
| 343 | { | ||
| 344 | /* .start and .end are filled in later */ | ||
| 345 | .flags = IORESOURCE_MEM, | ||
| 346 | }, { | ||
| 347 | .start = irq, | ||
| 348 | .flags = IORESOURCE_IRQ, | ||
| 349 | }, | ||
| 350 | }; | ||
| 351 | struct tx4938ide_platform_info pdata = { | ||
| 352 | .ioport_shift = shift, | ||
| 353 | /* | ||
| 354 | * The IDE driver should not change bus timings if other ISA | ||
| 355 | * devices existed. | ||
| 356 | */ | ||
| 357 | .gbus_clock = tune ? txx9_gbus_clock : 0, | ||
| 358 | }; | ||
| 359 | u64 ebccr; | ||
| 360 | int i; | ||
| 361 | |||
| 362 | if ((__raw_readq(&tx4938_ccfgptr->pcfg) & | ||
| 363 | (TX4938_PCFG_ATA_SEL | TX4938_PCFG_NDF_SEL)) | ||
| 364 | != TX4938_PCFG_ATA_SEL) | ||
| 365 | return; | ||
| 366 | for (i = 0; i < 8; i++) { | ||
| 367 | /* check EBCCRn.ISA, EBCCRn.BSZ, EBCCRn.ME */ | ||
| 368 | ebccr = __raw_readq(&tx4938_ebuscptr->cr[i]); | ||
| 369 | if ((ebccr & 0x00f00008) == 0x00e00008) | ||
| 370 | break; | ||
| 371 | } | ||
| 372 | if (i == 8) | ||
| 373 | return; | ||
| 374 | pdata.ebus_ch = i; | ||
| 375 | res[0].start = ((ebccr >> 48) << 20) + 0x10000; | ||
| 376 | res[0].end = res[0].start + 0x20000 - 1; | ||
| 377 | pdev = platform_device_alloc("tx4938ide", -1); | ||
| 378 | if (!pdev || | ||
| 379 | platform_device_add_resources(pdev, res, ARRAY_SIZE(res)) || | ||
| 380 | platform_device_add_data(pdev, &pdata, sizeof(pdata)) || | ||
| 381 | platform_device_add(pdev)) | ||
| 382 | platform_device_put(pdev); | ||
| 383 | } | ||
| 384 | |||
| 338 | static void __init tx4938_stop_unused_modules(void) | 385 | static void __init tx4938_stop_unused_modules(void) |
| 339 | { | 386 | { |
| 340 | __u64 pcfg, rst = 0, ckd = 0; | 387 | __u64 pcfg, rst = 0, ckd = 0; |
diff --git a/arch/mips/txx9/rbtx4938/setup.c b/arch/mips/txx9/rbtx4938/setup.c index e077cc4d3a59..547ff2920bf0 100644 --- a/arch/mips/txx9/rbtx4938/setup.c +++ b/arch/mips/txx9/rbtx4938/setup.c | |||
| @@ -352,6 +352,7 @@ static void __init rbtx4938_device_init(void) | |||
| 352 | rbtx4938_ne_init(); | 352 | rbtx4938_ne_init(); |
| 353 | tx4938_wdt_init(); | 353 | tx4938_wdt_init(); |
| 354 | rbtx4938_mtd_init(); | 354 | rbtx4938_mtd_init(); |
| 355 | tx4938_ata_init(RBTX4938_IRQ_IOC_ATA, 0, 1); | ||
| 355 | txx9_iocled_init(RBTX4938_LED_ADDR - IO_BASE, -1, 8, 1, "green", NULL); | 356 | txx9_iocled_init(RBTX4938_LED_ADDR - IO_BASE, -1, 8, 1, "green", NULL); |
| 356 | } | 357 | } |
| 357 | 358 | ||
diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig index a820ca6fc327..6d7401772a8f 100644 --- a/drivers/ide/Kconfig +++ b/drivers/ide/Kconfig | |||
| @@ -720,6 +720,16 @@ config BLK_DEV_IDE_AU1XXX_SEQTS_PER_RQ | |||
| 720 | default "128" | 720 | default "128" |
| 721 | depends on BLK_DEV_IDE_AU1XXX | 721 | depends on BLK_DEV_IDE_AU1XXX |
| 722 | 722 | ||
| 723 | config BLK_DEV_IDE_TX4938 | ||
| 724 | tristate "TX4938 internal IDE support" | ||
| 725 | depends on SOC_TX4938 | ||
| 726 | select IDE_TIMINGS | ||
| 727 | |||
| 728 | config BLK_DEV_IDE_TX4939 | ||
| 729 | tristate "TX4939 internal IDE support" | ||
| 730 | depends on SOC_TX4939 | ||
| 731 | select BLK_DEV_IDEDMA_SFF | ||
| 732 | |||
| 723 | config IDE_ARM | 733 | config IDE_ARM |
| 724 | tristate "ARM IDE support" | 734 | tristate "ARM IDE support" |
| 725 | depends on ARM && (ARCH_CLPS7500 || ARCH_RPC || ARCH_SHARK) | 735 | depends on ARM && (ARCH_CLPS7500 || ARCH_RPC || ARCH_SHARK) |
diff --git a/drivers/ide/Makefile b/drivers/ide/Makefile index 9cf92ac939d2..7818d402b188 100644 --- a/drivers/ide/Makefile +++ b/drivers/ide/Makefile | |||
| @@ -68,7 +68,6 @@ obj-$(CONFIG_BLK_DEV_VIA82CXXX) += via82cxxx.o | |||
| 68 | 68 | ||
| 69 | # Must appear at the end of the block | 69 | # Must appear at the end of the block |
| 70 | obj-$(CONFIG_BLK_DEV_GENERIC) += ide-pci-generic.o | 70 | obj-$(CONFIG_BLK_DEV_GENERIC) += ide-pci-generic.o |
| 71 | ide-pci-generic-y += generic.o | ||
| 72 | 71 | ||
| 73 | obj-$(CONFIG_IDEPCI_PCIBUS_ORDER) += ide-scan-pci.o | 72 | obj-$(CONFIG_IDEPCI_PCIBUS_ORDER) += ide-scan-pci.o |
| 74 | 73 | ||
| @@ -111,3 +110,6 @@ obj-$(CONFIG_BLK_DEV_IDE_RAPIDE) += rapide.o | |||
| 111 | obj-$(CONFIG_BLK_DEV_PALMCHIP_BK3710) += palm_bk3710.o | 110 | obj-$(CONFIG_BLK_DEV_PALMCHIP_BK3710) += palm_bk3710.o |
| 112 | 111 | ||
| 113 | obj-$(CONFIG_BLK_DEV_IDE_AU1XXX) += au1xxx-ide.o | 112 | obj-$(CONFIG_BLK_DEV_IDE_AU1XXX) += au1xxx-ide.o |
| 113 | |||
| 114 | obj-$(CONFIG_BLK_DEV_IDE_TX4938) += tx4938ide.o | ||
| 115 | obj-$(CONFIG_BLK_DEV_IDE_TX4939) += tx4939ide.o | ||
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index 133afd09843c..48b5eda3ab41 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c | |||
| @@ -1966,6 +1966,7 @@ static const struct cd_list_entry ide_cd_quirks_list[] = { | |||
| 1966 | { "Optiarc DVD RW AD-5200A", NULL, IDE_AFLAG_PLAY_AUDIO_OK }, | 1966 | { "Optiarc DVD RW AD-5200A", NULL, IDE_AFLAG_PLAY_AUDIO_OK }, |
| 1967 | { "Optiarc DVD RW AD-7200A", NULL, IDE_AFLAG_PLAY_AUDIO_OK }, | 1967 | { "Optiarc DVD RW AD-7200A", NULL, IDE_AFLAG_PLAY_AUDIO_OK }, |
| 1968 | { "Optiarc DVD RW AD-7543A", NULL, IDE_AFLAG_NO_AUTOCLOSE }, | 1968 | { "Optiarc DVD RW AD-7543A", NULL, IDE_AFLAG_NO_AUTOCLOSE }, |
| 1969 | { "TEAC CD-ROM CD-224E", NULL, IDE_AFLAG_NO_AUTOCLOSE }, | ||
| 1969 | { NULL, NULL, 0 } | 1970 | { NULL, NULL, 0 } |
| 1970 | }; | 1971 | }; |
| 1971 | 1972 | ||
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index 223750c1b5a6..e5adebe8ac2c 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c | |||
| @@ -600,6 +600,7 @@ static int ide_disk_check(ide_drive_t *drive, const char *s) | |||
| 600 | static void ide_disk_setup(ide_drive_t *drive) | 600 | static void ide_disk_setup(ide_drive_t *drive) |
| 601 | { | 601 | { |
| 602 | struct ide_disk_obj *idkp = drive->driver_data; | 602 | struct ide_disk_obj *idkp = drive->driver_data; |
| 603 | struct request_queue *q = drive->queue; | ||
| 603 | ide_hwif_t *hwif = drive->hwif; | 604 | ide_hwif_t *hwif = drive->hwif; |
| 604 | u16 *id = drive->id; | 605 | u16 *id = drive->id; |
| 605 | char *m = (char *)&id[ATA_ID_PROD]; | 606 | char *m = (char *)&id[ATA_ID_PROD]; |
| @@ -626,11 +627,14 @@ static void ide_disk_setup(ide_drive_t *drive) | |||
| 626 | if (max_s > hwif->rqsize) | 627 | if (max_s > hwif->rqsize) |
| 627 | max_s = hwif->rqsize; | 628 | max_s = hwif->rqsize; |
| 628 | 629 | ||
| 629 | blk_queue_max_sectors(drive->queue, max_s); | 630 | blk_queue_max_sectors(q, max_s); |
| 630 | } | 631 | } |
| 631 | 632 | ||
| 632 | printk(KERN_INFO "%s: max request size: %dKiB\n", drive->name, | 633 | printk(KERN_INFO "%s: max request size: %dKiB\n", drive->name, |
| 633 | drive->queue->max_sectors / 2); | 634 | q->max_sectors / 2); |
| 635 | |||
| 636 | if (ata_id_is_ssd(id) || ata_id_is_cfa(id)) | ||
| 637 | queue_flag_set_unlocked(QUEUE_FLAG_NONROT, q); | ||
| 634 | 638 | ||
| 635 | /* calculate drive capacity, and select LBA if possible */ | 639 | /* calculate drive capacity, and select LBA if possible */ |
| 636 | ide_disk_get_capacity(drive); | 640 | ide_disk_get_capacity(drive); |
diff --git a/drivers/ide/generic.c b/drivers/ide/ide-pci-generic.c index 474f96a7c076..474f96a7c076 100644 --- a/drivers/ide/generic.c +++ b/drivers/ide/ide-pci-generic.c | |||
diff --git a/drivers/ide/scc_pata.c b/drivers/ide/scc_pata.c index 49f163aa51e3..f26aa5d54efb 100644 --- a/drivers/ide/scc_pata.c +++ b/drivers/ide/scc_pata.c | |||
| @@ -536,10 +536,6 @@ static u8 scc_udma_filter(ide_drive_t *drive) | |||
| 536 | 536 | ||
| 537 | static int setup_mmio_scc (struct pci_dev *dev, const char *name) | 537 | static int setup_mmio_scc (struct pci_dev *dev, const char *name) |
| 538 | { | 538 | { |
| 539 | unsigned long ctl_base = pci_resource_start(dev, 0); | ||
| 540 | unsigned long dma_base = pci_resource_start(dev, 1); | ||
| 541 | unsigned long ctl_size = pci_resource_len(dev, 0); | ||
| 542 | unsigned long dma_size = pci_resource_len(dev, 1); | ||
| 543 | void __iomem *ctl_addr; | 539 | void __iomem *ctl_addr; |
| 544 | void __iomem *dma_addr; | 540 | void __iomem *dma_addr; |
| 545 | int i, ret; | 541 | int i, ret; |
| @@ -557,10 +553,12 @@ static int setup_mmio_scc (struct pci_dev *dev, const char *name) | |||
| 557 | return ret; | 553 | return ret; |
| 558 | } | 554 | } |
| 559 | 555 | ||
| 560 | if ((ctl_addr = ioremap(ctl_base, ctl_size)) == NULL) | 556 | ctl_addr = pci_ioremap_bar(dev, 0); |
| 557 | if (!ctl_addr) | ||
| 561 | goto fail_0; | 558 | goto fail_0; |
| 562 | 559 | ||
| 563 | if ((dma_addr = ioremap(dma_base, dma_size)) == NULL) | 560 | dma_addr = pci_ioremap_bar(dev, 1); |
| 561 | if (!dma_addr) | ||
| 564 | goto fail_1; | 562 | goto fail_1; |
| 565 | 563 | ||
| 566 | pci_set_master(dev); | 564 | pci_set_master(dev); |
diff --git a/drivers/ide/sgiioc4.c b/drivers/ide/sgiioc4.c index 8af9b23499fd..7defa0ae2014 100644 --- a/drivers/ide/sgiioc4.c +++ b/drivers/ide/sgiioc4.c | |||
| @@ -567,14 +567,12 @@ sgiioc4_ide_setup_pci_device(struct pci_dev *dev) | |||
| 567 | unsigned long cmd_base, irqport; | 567 | unsigned long cmd_base, irqport; |
| 568 | unsigned long bar0, cmd_phys_base, ctl; | 568 | unsigned long bar0, cmd_phys_base, ctl; |
| 569 | void __iomem *virt_base; | 569 | void __iomem *virt_base; |
| 570 | struct ide_host *host; | ||
| 571 | hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL }; | 570 | hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL }; |
| 572 | struct ide_port_info d = sgiioc4_port_info; | ||
| 573 | int rc; | 571 | int rc; |
| 574 | 572 | ||
| 575 | /* Get the CmdBlk and CtrlBlk Base Registers */ | 573 | /* Get the CmdBlk and CtrlBlk Base Registers */ |
| 576 | bar0 = pci_resource_start(dev, 0); | 574 | bar0 = pci_resource_start(dev, 0); |
| 577 | virt_base = ioremap(bar0, pci_resource_len(dev, 0)); | 575 | virt_base = pci_ioremap_bar(dev, 0); |
| 578 | if (virt_base == NULL) { | 576 | if (virt_base == NULL) { |
| 579 | printk(KERN_ERR "%s: Unable to remap BAR 0 address: 0x%lx\n", | 577 | printk(KERN_ERR "%s: Unable to remap BAR 0 address: 0x%lx\n", |
| 580 | DRV_NAME, bar0); | 578 | DRV_NAME, bar0); |
| @@ -590,7 +588,8 @@ sgiioc4_ide_setup_pci_device(struct pci_dev *dev) | |||
| 590 | printk(KERN_ERR "%s %s -- ERROR: addresses 0x%08lx to 0x%08lx " | 588 | printk(KERN_ERR "%s %s -- ERROR: addresses 0x%08lx to 0x%08lx " |
| 591 | "already in use\n", DRV_NAME, pci_name(dev), | 589 | "already in use\n", DRV_NAME, pci_name(dev), |
| 592 | cmd_phys_base, cmd_phys_base + IOC4_CMD_CTL_BLK_SIZE); | 590 | cmd_phys_base, cmd_phys_base + IOC4_CMD_CTL_BLK_SIZE); |
| 593 | return -EBUSY; | 591 | rc = -EBUSY; |
| 592 | goto req_mem_rgn_err; | ||
| 594 | } | 593 | } |
| 595 | 594 | ||
| 596 | /* Initialize the IO registers */ | 595 | /* Initialize the IO registers */ |
| @@ -603,21 +602,12 @@ sgiioc4_ide_setup_pci_device(struct pci_dev *dev) | |||
| 603 | /* Initializing chipset IRQ Registers */ | 602 | /* Initializing chipset IRQ Registers */ |
| 604 | writel(0x03, (void __iomem *)(irqport + IOC4_INTR_SET * 4)); | 603 | writel(0x03, (void __iomem *)(irqport + IOC4_INTR_SET * 4)); |
| 605 | 604 | ||
| 606 | host = ide_host_alloc(&d, hws); | 605 | rc = ide_host_add(&sgiioc4_port_info, hws, NULL); |
| 607 | if (host == NULL) { | 606 | if (!rc) |
| 608 | rc = -ENOMEM; | 607 | return 0; |
| 609 | goto err; | ||
| 610 | } | ||
| 611 | |||
| 612 | rc = ide_host_register(host, &d, hws); | ||
| 613 | if (rc) | ||
| 614 | goto err_free; | ||
| 615 | 608 | ||
| 616 | return 0; | ||
| 617 | err_free: | ||
| 618 | ide_host_free(host); | ||
| 619 | err: | ||
| 620 | release_mem_region(cmd_phys_base, IOC4_CMD_CTL_BLK_SIZE); | 609 | release_mem_region(cmd_phys_base, IOC4_CMD_CTL_BLK_SIZE); |
| 610 | req_mem_rgn_err: | ||
| 621 | iounmap(virt_base); | 611 | iounmap(virt_base); |
| 622 | return rc; | 612 | return rc; |
| 623 | } | 613 | } |
diff --git a/drivers/ide/siimage.c b/drivers/ide/siimage.c index eb4faf92c571..c3107df7773d 100644 --- a/drivers/ide/siimage.c +++ b/drivers/ide/siimage.c | |||
| @@ -784,7 +784,7 @@ static int __devinit siimage_init_one(struct pci_dev *dev, | |||
| 784 | printk(KERN_WARNING DRV_NAME " %s: MMIO ports not " | 784 | printk(KERN_WARNING DRV_NAME " %s: MMIO ports not " |
| 785 | "available\n", pci_name(dev)); | 785 | "available\n", pci_name(dev)); |
| 786 | } else { | 786 | } else { |
| 787 | ioaddr = ioremap(bar5, barsize); | 787 | ioaddr = pci_ioremap_bar(dev, 5); |
| 788 | if (ioaddr == NULL) | 788 | if (ioaddr == NULL) |
| 789 | release_mem_region(bar5, barsize); | 789 | release_mem_region(bar5, barsize); |
| 790 | } | 790 | } |
diff --git a/drivers/ide/tx4938ide.c b/drivers/ide/tx4938ide.c new file mode 100644 index 000000000000..fa660f931a11 --- /dev/null +++ b/drivers/ide/tx4938ide.c | |||
| @@ -0,0 +1,310 @@ | |||
| 1 | /* | ||
| 2 | * TX4938 internal IDE driver | ||
| 3 | * Based on tx4939ide.c. | ||
| 4 | * | ||
| 5 | * This file is subject to the terms and conditions of the GNU General Public | ||
| 6 | * License. See the file "COPYING" in the main directory of this archive | ||
| 7 | * for more details. | ||
| 8 | * | ||
| 9 | * (C) Copyright TOSHIBA CORPORATION 2005-2007 | ||
| 10 | */ | ||
| 11 | |||
| 12 | #include <linux/module.h> | ||
| 13 | #include <linux/types.h> | ||
| 14 | #include <linux/ide.h> | ||
| 15 | #include <linux/init.h> | ||
| 16 | #include <linux/platform_device.h> | ||
| 17 | #include <linux/io.h> | ||
| 18 | #include <asm/txx9/tx4938.h> | ||
| 19 | |||
| 20 | static void tx4938ide_tune_ebusc(unsigned int ebus_ch, | ||
| 21 | unsigned int gbus_clock, | ||
| 22 | u8 pio) | ||
| 23 | { | ||
| 24 | struct ide_timing *t = ide_timing_find_mode(XFER_PIO_0 + pio); | ||
| 25 | u64 cr = __raw_readq(&tx4938_ebuscptr->cr[ebus_ch]); | ||
| 26 | unsigned int sp = (cr >> 4) & 3; | ||
| 27 | unsigned int clock = gbus_clock / (4 - sp); | ||
| 28 | unsigned int cycle = 1000000000 / clock; | ||
| 29 | unsigned int wt, shwt; | ||
| 30 | |||
| 31 | /* Minimum DIOx- active time */ | ||
| 32 | wt = DIV_ROUND_UP(t->act8b, cycle) - 2; | ||
| 33 | /* IORDY setup time: 35ns */ | ||
| 34 | wt = max(wt, DIV_ROUND_UP(35, cycle)); | ||
| 35 | /* actual wait-cycle is max(wt & ~1, 1) */ | ||
| 36 | if (wt > 2 && (wt & 1)) | ||
| 37 | wt++; | ||
| 38 | wt &= ~1; | ||
| 39 | /* Address-valid to DIOR/DIOW setup */ | ||
| 40 | shwt = DIV_ROUND_UP(t->setup, cycle); | ||
| 41 | |||
| 42 | pr_debug("tx4938ide: ebus %d, bus cycle %dns, WT %d, SHWT %d\n", | ||
| 43 | ebus_ch, cycle, wt, shwt); | ||
| 44 | |||
| 45 | __raw_writeq((cr & ~(0x3f007ull)) | (wt << 12) | shwt, | ||
| 46 | &tx4938_ebuscptr->cr[ebus_ch]); | ||
| 47 | } | ||
| 48 | |||
| 49 | static void tx4938ide_set_pio_mode(ide_drive_t *drive, const u8 pio) | ||
| 50 | { | ||
| 51 | ide_hwif_t *hwif = drive->hwif; | ||
| 52 | struct tx4938ide_platform_info *pdata = hwif->dev->platform_data; | ||
| 53 | u8 safe = pio; | ||
| 54 | ide_drive_t *pair; | ||
| 55 | |||
| 56 | pair = ide_get_pair_dev(drive); | ||
| 57 | if (pair) | ||
| 58 | safe = min(safe, ide_get_best_pio_mode(pair, 255, 5)); | ||
| 59 | tx4938ide_tune_ebusc(pdata->ebus_ch, pdata->gbus_clock, safe); | ||
| 60 | } | ||
| 61 | |||
| 62 | #ifdef __BIG_ENDIAN | ||
| 63 | |||
| 64 | /* custom iops (independent from SWAP_IO_SPACE) */ | ||
| 65 | static u8 tx4938ide_inb(unsigned long port) | ||
| 66 | { | ||
| 67 | return __raw_readb((void __iomem *)port); | ||
| 68 | } | ||
| 69 | |||
| 70 | static void tx4938ide_outb(u8 value, unsigned long port) | ||
| 71 | { | ||
| 72 | __raw_writeb(value, (void __iomem *)port); | ||
| 73 | } | ||
| 74 | |||
| 75 | static void tx4938ide_tf_load(ide_drive_t *drive, ide_task_t *task) | ||
| 76 | { | ||
| 77 | ide_hwif_t *hwif = drive->hwif; | ||
| 78 | struct ide_io_ports *io_ports = &hwif->io_ports; | ||
| 79 | struct ide_taskfile *tf = &task->tf; | ||
| 80 | u8 HIHI = task->tf_flags & IDE_TFLAG_LBA48 ? 0xE0 : 0xEF; | ||
| 81 | |||
| 82 | if (task->tf_flags & IDE_TFLAG_FLAGGED) | ||
| 83 | HIHI = 0xFF; | ||
| 84 | |||
| 85 | if (task->tf_flags & IDE_TFLAG_OUT_DATA) { | ||
| 86 | u16 data = (tf->hob_data << 8) | tf->data; | ||
| 87 | |||
| 88 | /* no endian swap */ | ||
| 89 | __raw_writew(data, (void __iomem *)io_ports->data_addr); | ||
| 90 | } | ||
| 91 | |||
| 92 | if (task->tf_flags & IDE_TFLAG_OUT_HOB_FEATURE) | ||
| 93 | tx4938ide_outb(tf->hob_feature, io_ports->feature_addr); | ||
| 94 | if (task->tf_flags & IDE_TFLAG_OUT_HOB_NSECT) | ||
| 95 | tx4938ide_outb(tf->hob_nsect, io_ports->nsect_addr); | ||
| 96 | if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAL) | ||
| 97 | tx4938ide_outb(tf->hob_lbal, io_ports->lbal_addr); | ||
| 98 | if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAM) | ||
| 99 | tx4938ide_outb(tf->hob_lbam, io_ports->lbam_addr); | ||
| 100 | if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAH) | ||
| 101 | tx4938ide_outb(tf->hob_lbah, io_ports->lbah_addr); | ||
| 102 | |||
| 103 | if (task->tf_flags & IDE_TFLAG_OUT_FEATURE) | ||
| 104 | tx4938ide_outb(tf->feature, io_ports->feature_addr); | ||
| 105 | if (task->tf_flags & IDE_TFLAG_OUT_NSECT) | ||
| 106 | tx4938ide_outb(tf->nsect, io_ports->nsect_addr); | ||
| 107 | if (task->tf_flags & IDE_TFLAG_OUT_LBAL) | ||
| 108 | tx4938ide_outb(tf->lbal, io_ports->lbal_addr); | ||
| 109 | if (task->tf_flags & IDE_TFLAG_OUT_LBAM) | ||
| 110 | tx4938ide_outb(tf->lbam, io_ports->lbam_addr); | ||
| 111 | if (task->tf_flags & IDE_TFLAG_OUT_LBAH) | ||
| 112 | tx4938ide_outb(tf->lbah, io_ports->lbah_addr); | ||
| 113 | |||
| 114 | if (task->tf_flags & IDE_TFLAG_OUT_DEVICE) | ||
| 115 | tx4938ide_outb((tf->device & HIHI) | drive->select, | ||
| 116 | io_ports->device_addr); | ||
| 117 | } | ||
| 118 | |||
| 119 | static void tx4938ide_tf_read(ide_drive_t *drive, ide_task_t *task) | ||
| 120 | { | ||
| 121 | ide_hwif_t *hwif = drive->hwif; | ||
| 122 | struct ide_io_ports *io_ports = &hwif->io_ports; | ||
| 123 | struct ide_taskfile *tf = &task->tf; | ||
| 124 | |||
| 125 | if (task->tf_flags & IDE_TFLAG_IN_DATA) { | ||
| 126 | u16 data; | ||
| 127 | |||
| 128 | /* no endian swap */ | ||
| 129 | data = __raw_readw((void __iomem *)io_ports->data_addr); | ||
| 130 | tf->data = data & 0xff; | ||
| 131 | tf->hob_data = (data >> 8) & 0xff; | ||
| 132 | } | ||
| 133 | |||
| 134 | /* be sure we're looking at the low order bits */ | ||
| 135 | tx4938ide_outb(ATA_DEVCTL_OBS & ~0x80, io_ports->ctl_addr); | ||
| 136 | |||
| 137 | if (task->tf_flags & IDE_TFLAG_IN_FEATURE) | ||
| 138 | tf->feature = tx4938ide_inb(io_ports->feature_addr); | ||
| 139 | if (task->tf_flags & IDE_TFLAG_IN_NSECT) | ||
| 140 | tf->nsect = tx4938ide_inb(io_ports->nsect_addr); | ||
| 141 | if (task->tf_flags & IDE_TFLAG_IN_LBAL) | ||
| 142 | tf->lbal = tx4938ide_inb(io_ports->lbal_addr); | ||
| 143 | if (task->tf_flags & IDE_TFLAG_IN_LBAM) | ||
| 144 | tf->lbam = tx4938ide_inb(io_ports->lbam_addr); | ||
| 145 | if (task->tf_flags & IDE_TFLAG_IN_LBAH) | ||
| 146 | tf->lbah = tx4938ide_inb(io_ports->lbah_addr); | ||
| 147 | if (task->tf_flags & IDE_TFLAG_IN_DEVICE) | ||
| 148 | tf->device = tx4938ide_inb(io_ports->device_addr); | ||
| 149 | |||
| 150 | if (task->tf_flags & IDE_TFLAG_LBA48) { | ||
| 151 | tx4938ide_outb(ATA_DEVCTL_OBS | 0x80, io_ports->ctl_addr); | ||
| 152 | |||
| 153 | if (task->tf_flags & IDE_TFLAG_IN_HOB_FEATURE) | ||
| 154 | tf->hob_feature = | ||
| 155 | tx4938ide_inb(io_ports->feature_addr); | ||
| 156 | if (task->tf_flags & IDE_TFLAG_IN_HOB_NSECT) | ||
| 157 | tf->hob_nsect = tx4938ide_inb(io_ports->nsect_addr); | ||
| 158 | if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAL) | ||
| 159 | tf->hob_lbal = tx4938ide_inb(io_ports->lbal_addr); | ||
| 160 | if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAM) | ||
| 161 | tf->hob_lbam = tx4938ide_inb(io_ports->lbam_addr); | ||
| 162 | if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAH) | ||
| 163 | tf->hob_lbah = tx4938ide_inb(io_ports->lbah_addr); | ||
| 164 | } | ||
| 165 | } | ||
| 166 | |||
| 167 | static void tx4938ide_input_data_swap(ide_drive_t *drive, struct request *rq, | ||
| 168 | void *buf, unsigned int len) | ||
| 169 | { | ||
| 170 | unsigned long port = drive->hwif->io_ports.data_addr; | ||
| 171 | unsigned short *ptr = buf; | ||
| 172 | unsigned int count = (len + 1) / 2; | ||
| 173 | |||
| 174 | while (count--) | ||
| 175 | *ptr++ = cpu_to_le16(__raw_readw((void __iomem *)port)); | ||
| 176 | __ide_flush_dcache_range((unsigned long)buf, count * 2); | ||
| 177 | } | ||
| 178 | |||
| 179 | static void tx4938ide_output_data_swap(ide_drive_t *drive, struct request *rq, | ||
| 180 | void *buf, unsigned int len) | ||
| 181 | { | ||
| 182 | unsigned long port = drive->hwif->io_ports.data_addr; | ||
| 183 | unsigned short *ptr = buf; | ||
| 184 | unsigned int count = (len + 1) / 2; | ||
| 185 | |||
| 186 | while (count--) { | ||
| 187 | __raw_writew(le16_to_cpu(*ptr), (void __iomem *)port); | ||
| 188 | ptr++; | ||
| 189 | } | ||
| 190 | __ide_flush_dcache_range((unsigned long)buf, count * 2); | ||
| 191 | } | ||
| 192 | |||
| 193 | static const struct ide_tp_ops tx4938ide_tp_ops = { | ||
| 194 | .exec_command = ide_exec_command, | ||
| 195 | .read_status = ide_read_status, | ||
| 196 | .read_altstatus = ide_read_altstatus, | ||
| 197 | .read_sff_dma_status = ide_read_sff_dma_status, | ||
| 198 | |||
| 199 | .set_irq = ide_set_irq, | ||
| 200 | |||
| 201 | .tf_load = tx4938ide_tf_load, | ||
| 202 | .tf_read = tx4938ide_tf_read, | ||
| 203 | |||
| 204 | .input_data = tx4938ide_input_data_swap, | ||
| 205 | .output_data = tx4938ide_output_data_swap, | ||
| 206 | }; | ||
| 207 | |||
| 208 | #endif /* __BIG_ENDIAN */ | ||
| 209 | |||
| 210 | static const struct ide_port_ops tx4938ide_port_ops = { | ||
| 211 | .set_pio_mode = tx4938ide_set_pio_mode, | ||
| 212 | }; | ||
| 213 | |||
| 214 | static const struct ide_port_info tx4938ide_port_info __initdata = { | ||
| 215 | .port_ops = &tx4938ide_port_ops, | ||
| 216 | #ifdef __BIG_ENDIAN | ||
| 217 | .tp_ops = &tx4938ide_tp_ops, | ||
| 218 | #endif | ||
| 219 | .host_flags = IDE_HFLAG_MMIO | IDE_HFLAG_NO_DMA, | ||
| 220 | .pio_mask = ATA_PIO5, | ||
| 221 | }; | ||
| 222 | |||
| 223 | static int __init tx4938ide_probe(struct platform_device *pdev) | ||
| 224 | { | ||
| 225 | hw_regs_t hw; | ||
| 226 | hw_regs_t *hws[] = { &hw, NULL, NULL, NULL }; | ||
| 227 | struct ide_host *host; | ||
| 228 | struct resource *res; | ||
| 229 | struct tx4938ide_platform_info *pdata = pdev->dev.platform_data; | ||
| 230 | int irq, ret, i; | ||
| 231 | unsigned long mapbase; | ||
| 232 | struct ide_port_info d = tx4938ide_port_info; | ||
| 233 | |||
| 234 | irq = platform_get_irq(pdev, 0); | ||
| 235 | if (irq < 0) | ||
| 236 | return -ENODEV; | ||
| 237 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 238 | if (!res) | ||
| 239 | return -ENODEV; | ||
| 240 | |||
| 241 | if (!devm_request_mem_region(&pdev->dev, res->start, | ||
| 242 | res->end - res->start + 1, "tx4938ide")) | ||
| 243 | return -EBUSY; | ||
| 244 | mapbase = (unsigned long)devm_ioremap(&pdev->dev, res->start, | ||
| 245 | res->end - res->start + 1); | ||
| 246 | if (!mapbase) | ||
| 247 | return -EBUSY; | ||
| 248 | |||
| 249 | memset(&hw, 0, sizeof(hw)); | ||
| 250 | if (pdata->ioport_shift) { | ||
| 251 | unsigned long port = mapbase; | ||
| 252 | |||
| 253 | hw.io_ports_array[0] = port; | ||
| 254 | #ifdef __BIG_ENDIAN | ||
| 255 | port++; | ||
| 256 | #endif | ||
| 257 | for (i = 1; i <= 7; i++) | ||
| 258 | hw.io_ports_array[i] = | ||
| 259 | port + (i << pdata->ioport_shift); | ||
| 260 | hw.io_ports.ctl_addr = | ||
| 261 | port + 0x10000 + (6 << pdata->ioport_shift); | ||
| 262 | } else | ||
| 263 | ide_std_init_ports(&hw, mapbase, mapbase + 0x10006); | ||
| 264 | hw.irq = irq; | ||
| 265 | hw.dev = &pdev->dev; | ||
| 266 | |||
| 267 | pr_info("TX4938 IDE interface (base %#lx, irq %d)\n", mapbase, hw.irq); | ||
| 268 | if (pdata->gbus_clock) | ||
| 269 | tx4938ide_tune_ebusc(pdata->ebus_ch, pdata->gbus_clock, 0); | ||
| 270 | else | ||
| 271 | d.port_ops = NULL; | ||
| 272 | ret = ide_host_add(&d, hws, &host); | ||
| 273 | if (ret) | ||
| 274 | return ret; | ||
| 275 | platform_set_drvdata(pdev, host); | ||
| 276 | return 0; | ||
| 277 | } | ||
| 278 | |||
| 279 | static int __exit tx4938ide_remove(struct platform_device *pdev) | ||
| 280 | { | ||
| 281 | struct ide_host *host = platform_get_drvdata(pdev); | ||
| 282 | |||
| 283 | ide_host_remove(host); | ||
| 284 | return 0; | ||
| 285 | } | ||
| 286 | |||
| 287 | static struct platform_driver tx4938ide_driver = { | ||
| 288 | .driver = { | ||
| 289 | .name = "tx4938ide", | ||
| 290 | .owner = THIS_MODULE, | ||
| 291 | }, | ||
| 292 | .remove = __exit_p(tx4938ide_remove), | ||
| 293 | }; | ||
| 294 | |||
| 295 | static int __init tx4938ide_init(void) | ||
| 296 | { | ||
| 297 | return platform_driver_probe(&tx4938ide_driver, tx4938ide_probe); | ||
| 298 | } | ||
| 299 | |||
| 300 | static void __exit tx4938ide_exit(void) | ||
| 301 | { | ||
| 302 | platform_driver_unregister(&tx4938ide_driver); | ||
| 303 | } | ||
| 304 | |||
| 305 | module_init(tx4938ide_init); | ||
| 306 | module_exit(tx4938ide_exit); | ||
| 307 | |||
| 308 | MODULE_DESCRIPTION("TX4938 internal IDE driver"); | ||
| 309 | MODULE_LICENSE("GPL"); | ||
| 310 | MODULE_ALIAS("platform:tx4938ide"); | ||
diff --git a/drivers/ide/tx4939ide.c b/drivers/ide/tx4939ide.c new file mode 100644 index 000000000000..bafb7d1a22e2 --- /dev/null +++ b/drivers/ide/tx4939ide.c | |||
| @@ -0,0 +1,754 @@ | |||
| 1 | /* | ||
| 2 | * TX4939 internal IDE driver | ||
| 3 | * Based on RBTX49xx patch from CELF patch archive. | ||
| 4 | * | ||
| 5 | * This file is subject to the terms and conditions of the GNU General Public | ||
| 6 | * License. See the file "COPYING" in the main directory of this archive | ||
| 7 | * for more details. | ||
| 8 | * | ||
| 9 | * (C) Copyright TOSHIBA CORPORATION 2005-2007 | ||
| 10 | */ | ||
| 11 | |||
| 12 | #include <linux/module.h> | ||
| 13 | #include <linux/types.h> | ||
| 14 | #include <linux/ide.h> | ||
| 15 | #include <linux/init.h> | ||
| 16 | #include <linux/delay.h> | ||
| 17 | #include <linux/platform_device.h> | ||
| 18 | #include <linux/io.h> | ||
| 19 | #include <linux/scatterlist.h> | ||
| 20 | |||
| 21 | #define MODNAME "tx4939ide" | ||
| 22 | |||
| 23 | /* ATA Shadow Registers (8-bit except for Data which is 16-bit) */ | ||
| 24 | #define TX4939IDE_Data 0x000 | ||
| 25 | #define TX4939IDE_Error_Feature 0x001 | ||
| 26 | #define TX4939IDE_Sec 0x002 | ||
| 27 | #define TX4939IDE_LBA0 0x003 | ||
| 28 | #define TX4939IDE_LBA1 0x004 | ||
| 29 | #define TX4939IDE_LBA2 0x005 | ||
| 30 | #define TX4939IDE_DevHead 0x006 | ||
| 31 | #define TX4939IDE_Stat_Cmd 0x007 | ||
| 32 | #define TX4939IDE_AltStat_DevCtl 0x402 | ||
| 33 | /* H/W DMA Registers */ | ||
| 34 | #define TX4939IDE_DMA_Cmd 0x800 /* 8-bit */ | ||
| 35 | #define TX4939IDE_DMA_Stat 0x802 /* 8-bit */ | ||
| 36 | #define TX4939IDE_PRD_Ptr 0x804 /* 32-bit */ | ||
| 37 | /* ATA100 CORE Registers (16-bit) */ | ||
| 38 | #define TX4939IDE_Sys_Ctl 0xc00 | ||
| 39 | #define TX4939IDE_Xfer_Cnt_1 0xc08 | ||
| 40 | #define TX4939IDE_Xfer_Cnt_2 0xc0a | ||
| 41 | #define TX4939IDE_Sec_Cnt 0xc10 | ||
| 42 | #define TX4939IDE_Start_Lo_Addr 0xc18 | ||
| 43 | #define TX4939IDE_Start_Up_Addr 0xc20 | ||
| 44 | #define TX4939IDE_Add_Ctl 0xc28 | ||
| 45 | #define TX4939IDE_Lo_Burst_Cnt 0xc30 | ||
| 46 | #define TX4939IDE_Up_Burst_Cnt 0xc38 | ||
| 47 | #define TX4939IDE_PIO_Addr 0xc88 | ||
| 48 | #define TX4939IDE_H_Rst_Tim 0xc90 | ||
| 49 | #define TX4939IDE_Int_Ctl 0xc98 | ||
| 50 | #define TX4939IDE_Pkt_Cmd 0xcb8 | ||
| 51 | #define TX4939IDE_Bxfer_Cnt_Hi 0xcc0 | ||
| 52 | #define TX4939IDE_Bxfer_Cnt_Lo 0xcc8 | ||
| 53 | #define TX4939IDE_Dev_TErr 0xcd0 | ||
| 54 | #define TX4939IDE_Pkt_Xfer_Ctl 0xcd8 | ||
| 55 | #define TX4939IDE_Start_TAddr 0xce0 | ||
| 56 | |||
| 57 | /* bits for Int_Ctl */ | ||
| 58 | #define TX4939IDE_INT_ADDRERR 0x80 | ||
| 59 | #define TX4939IDE_INT_REACHMUL 0x40 | ||
| 60 | #define TX4939IDE_INT_DEVTIMING 0x20 | ||
| 61 | #define TX4939IDE_INT_UDMATERM 0x10 | ||
| 62 | #define TX4939IDE_INT_TIMER 0x08 | ||
| 63 | #define TX4939IDE_INT_BUSERR 0x04 | ||
| 64 | #define TX4939IDE_INT_XFEREND 0x02 | ||
| 65 | #define TX4939IDE_INT_HOST 0x01 | ||
| 66 | |||
| 67 | #define TX4939IDE_IGNORE_INTS \ | ||
| 68 | (TX4939IDE_INT_ADDRERR | TX4939IDE_INT_REACHMUL | \ | ||
| 69 | TX4939IDE_INT_DEVTIMING | TX4939IDE_INT_UDMATERM | \ | ||
| 70 | TX4939IDE_INT_TIMER | TX4939IDE_INT_XFEREND) | ||
| 71 | |||
| 72 | #ifdef __BIG_ENDIAN | ||
| 73 | #define tx4939ide_swizzlel(a) ((a) ^ 4) | ||
| 74 | #define tx4939ide_swizzlew(a) ((a) ^ 6) | ||
| 75 | #define tx4939ide_swizzleb(a) ((a) ^ 7) | ||
| 76 | #else | ||
| 77 | #define tx4939ide_swizzlel(a) (a) | ||
| 78 | #define tx4939ide_swizzlew(a) (a) | ||
| 79 | #define tx4939ide_swizzleb(a) (a) | ||
| 80 | #endif | ||
| 81 | |||
| 82 | static u16 tx4939ide_readw(void __iomem *base, u32 reg) | ||
| 83 | { | ||
| 84 | return __raw_readw(base + tx4939ide_swizzlew(reg)); | ||
| 85 | } | ||
| 86 | static u8 tx4939ide_readb(void __iomem *base, u32 reg) | ||
| 87 | { | ||
| 88 | return __raw_readb(base + tx4939ide_swizzleb(reg)); | ||
| 89 | } | ||
| 90 | static void tx4939ide_writel(u32 val, void __iomem *base, u32 reg) | ||
| 91 | { | ||
| 92 | __raw_writel(val, base + tx4939ide_swizzlel(reg)); | ||
| 93 | } | ||
| 94 | static void tx4939ide_writew(u16 val, void __iomem *base, u32 reg) | ||
| 95 | { | ||
| 96 | __raw_writew(val, base + tx4939ide_swizzlew(reg)); | ||
| 97 | } | ||
| 98 | static void tx4939ide_writeb(u8 val, void __iomem *base, u32 reg) | ||
| 99 | { | ||
| 100 | __raw_writeb(val, base + tx4939ide_swizzleb(reg)); | ||
| 101 | } | ||
| 102 | |||
| 103 | #define TX4939IDE_BASE(hwif) ((void __iomem *)(hwif)->extra_base) | ||
| 104 | |||
| 105 | static void tx4939ide_set_pio_mode(ide_drive_t *drive, const u8 pio) | ||
| 106 | { | ||
| 107 | ide_hwif_t *hwif = drive->hwif; | ||
| 108 | int is_slave = drive->dn; | ||
| 109 | u32 mask, val; | ||
| 110 | u8 safe = pio; | ||
| 111 | ide_drive_t *pair; | ||
| 112 | |||
| 113 | pair = ide_get_pair_dev(drive); | ||
| 114 | if (pair) | ||
| 115 | safe = min(safe, ide_get_best_pio_mode(pair, 255, 4)); | ||
| 116 | /* | ||
| 117 | * Update Command Transfer Mode for master/slave and Data | ||
| 118 | * Transfer Mode for this drive. | ||
| 119 | */ | ||
| 120 | mask = is_slave ? 0x07f00000 : 0x000007f0; | ||
| 121 | val = ((safe << 8) | (pio << 4)) << (is_slave ? 16 : 0); | ||
| 122 | hwif->select_data = (hwif->select_data & ~mask) | val; | ||
| 123 | /* tx4939ide_tf_load_fixup() will set the Sys_Ctl register */ | ||
| 124 | } | ||
| 125 | |||
| 126 | static void tx4939ide_set_dma_mode(ide_drive_t *drive, const u8 mode) | ||
| 127 | { | ||
| 128 | ide_hwif_t *hwif = drive->hwif; | ||
| 129 | u32 mask, val; | ||
| 130 | |||
| 131 | /* Update Data Transfer Mode for this drive. */ | ||
| 132 | if (mode >= XFER_UDMA_0) | ||
| 133 | val = mode - XFER_UDMA_0 + 8; | ||
| 134 | else | ||
| 135 | val = mode - XFER_MW_DMA_0 + 5; | ||
| 136 | if (drive->dn) { | ||
| 137 | mask = 0x00f00000; | ||
| 138 | val <<= 20; | ||
| 139 | } else { | ||
| 140 | mask = 0x000000f0; | ||
| 141 | val <<= 4; | ||
| 142 | } | ||
| 143 | hwif->select_data = (hwif->select_data & ~mask) | val; | ||
| 144 | /* tx4939ide_tf_load_fixup() will set the Sys_Ctl register */ | ||
| 145 | } | ||
| 146 | |||
| 147 | static u16 tx4939ide_check_error_ints(ide_hwif_t *hwif) | ||
| 148 | { | ||
| 149 | void __iomem *base = TX4939IDE_BASE(hwif); | ||
| 150 | u16 ctl = tx4939ide_readw(base, TX4939IDE_Int_Ctl); | ||
| 151 | |||
| 152 | if (ctl & TX4939IDE_INT_BUSERR) { | ||
| 153 | /* reset FIFO */ | ||
| 154 | u16 sysctl = tx4939ide_readw(base, TX4939IDE_Sys_Ctl); | ||
| 155 | |||
| 156 | tx4939ide_writew(sysctl | 0x4000, base, TX4939IDE_Sys_Ctl); | ||
| 157 | mmiowb(); | ||
| 158 | /* wait 12GBUSCLK (typ. 60ns @ GBUS200MHz, max 270ns) */ | ||
| 159 | ndelay(270); | ||
| 160 | tx4939ide_writew(sysctl, base, TX4939IDE_Sys_Ctl); | ||
| 161 | } | ||
| 162 | if (ctl & (TX4939IDE_INT_ADDRERR | | ||
| 163 | TX4939IDE_INT_DEVTIMING | TX4939IDE_INT_BUSERR)) | ||
| 164 | pr_err("%s: Error interrupt %#x (%s%s%s )\n", | ||
| 165 | hwif->name, ctl, | ||
| 166 | ctl & TX4939IDE_INT_ADDRERR ? " Address-Error" : "", | ||
| 167 | ctl & TX4939IDE_INT_DEVTIMING ? " DEV-Timing" : "", | ||
| 168 | ctl & TX4939IDE_INT_BUSERR ? " Bus-Error" : ""); | ||
| 169 | return ctl; | ||
| 170 | } | ||
| 171 | |||
| 172 | static void tx4939ide_clear_irq(ide_drive_t *drive) | ||
| 173 | { | ||
| 174 | ide_hwif_t *hwif; | ||
| 175 | void __iomem *base; | ||
| 176 | u16 ctl; | ||
| 177 | |||
| 178 | /* | ||
| 179 | * tx4939ide_dma_test_irq() and tx4939ide_dma_end() do all job | ||
| 180 | * for DMA case. | ||
| 181 | */ | ||
| 182 | if (drive->waiting_for_dma) | ||
| 183 | return; | ||
| 184 | hwif = drive->hwif; | ||
| 185 | base = TX4939IDE_BASE(hwif); | ||
| 186 | ctl = tx4939ide_check_error_ints(hwif); | ||
| 187 | tx4939ide_writew(ctl, base, TX4939IDE_Int_Ctl); | ||
| 188 | } | ||
| 189 | |||
| 190 | static u8 tx4939ide_cable_detect(ide_hwif_t *hwif) | ||
| 191 | { | ||
| 192 | void __iomem *base = TX4939IDE_BASE(hwif); | ||
| 193 | |||
| 194 | return tx4939ide_readw(base, TX4939IDE_Sys_Ctl) & 0x2000 ? | ||
| 195 | ATA_CBL_PATA40 : ATA_CBL_PATA80; | ||
| 196 | } | ||
| 197 | |||
| 198 | #ifdef __BIG_ENDIAN | ||
| 199 | static void tx4939ide_dma_host_set(ide_drive_t *drive, int on) | ||
| 200 | { | ||
| 201 | ide_hwif_t *hwif = drive->hwif; | ||
| 202 | u8 unit = drive->dn; | ||
| 203 | void __iomem *base = TX4939IDE_BASE(hwif); | ||
| 204 | u8 dma_stat = tx4939ide_readb(base, TX4939IDE_DMA_Stat); | ||
| 205 | |||
| 206 | if (on) | ||
| 207 | dma_stat |= (1 << (5 + unit)); | ||
| 208 | else | ||
| 209 | dma_stat &= ~(1 << (5 + unit)); | ||
| 210 | |||
| 211 | tx4939ide_writeb(dma_stat, base, TX4939IDE_DMA_Stat); | ||
| 212 | } | ||
| 213 | #else | ||
| 214 | #define tx4939ide_dma_host_set ide_dma_host_set | ||
| 215 | #endif | ||
| 216 | |||
| 217 | static u8 tx4939ide_clear_dma_status(void __iomem *base) | ||
| 218 | { | ||
| 219 | u8 dma_stat; | ||
| 220 | |||
| 221 | /* read DMA status for INTR & ERROR flags */ | ||
| 222 | dma_stat = tx4939ide_readb(base, TX4939IDE_DMA_Stat); | ||
| 223 | /* clear INTR & ERROR flags */ | ||
| 224 | tx4939ide_writeb(dma_stat | ATA_DMA_INTR | ATA_DMA_ERR, base, | ||
| 225 | TX4939IDE_DMA_Stat); | ||
| 226 | /* recover intmask cleared by writing to bit2 of DMA_Stat */ | ||
| 227 | tx4939ide_writew(TX4939IDE_IGNORE_INTS << 8, base, TX4939IDE_Int_Ctl); | ||
| 228 | return dma_stat; | ||
| 229 | } | ||
| 230 | |||
| 231 | #ifdef __BIG_ENDIAN | ||
| 232 | /* custom ide_build_dmatable to handle swapped layout */ | ||
| 233 | static int tx4939ide_build_dmatable(ide_drive_t *drive, struct request *rq) | ||
| 234 | { | ||
| 235 | ide_hwif_t *hwif = drive->hwif; | ||
| 236 | u32 *table = (u32 *)hwif->dmatable_cpu; | ||
| 237 | unsigned int count = 0; | ||
| 238 | int i; | ||
| 239 | struct scatterlist *sg; | ||
| 240 | |||
| 241 | hwif->sg_nents = ide_build_sglist(drive, rq); | ||
| 242 | if (hwif->sg_nents == 0) | ||
| 243 | return 0; | ||
| 244 | |||
| 245 | for_each_sg(hwif->sg_table, sg, hwif->sg_nents, i) { | ||
| 246 | u32 cur_addr, cur_len, bcount; | ||
| 247 | |||
| 248 | cur_addr = sg_dma_address(sg); | ||
| 249 | cur_len = sg_dma_len(sg); | ||
| 250 | |||
| 251 | /* | ||
| 252 | * Fill in the DMA table, without crossing any 64kB boundaries. | ||
| 253 | */ | ||
| 254 | |||
| 255 | while (cur_len) { | ||
| 256 | if (count++ >= PRD_ENTRIES) | ||
| 257 | goto use_pio_instead; | ||
| 258 | |||
| 259 | bcount = 0x10000 - (cur_addr & 0xffff); | ||
| 260 | if (bcount > cur_len) | ||
| 261 | bcount = cur_len; | ||
| 262 | *table++ = bcount & 0xffff; | ||
| 263 | *table++ = cur_addr; | ||
| 264 | cur_addr += bcount; | ||
| 265 | cur_len -= bcount; | ||
| 266 | } | ||
| 267 | } | ||
| 268 | |||
| 269 | if (count) { | ||
| 270 | *(table - 2) |= 0x80000000; | ||
| 271 | return count; | ||
| 272 | } | ||
| 273 | |||
| 274 | use_pio_instead: | ||
| 275 | printk(KERN_ERR "%s: %s\n", drive->name, | ||
| 276 | count ? "DMA table too small" : "empty DMA table?"); | ||
| 277 | |||
| 278 | ide_destroy_dmatable(drive); | ||
| 279 | |||
| 280 | return 0; /* revert to PIO for this request */ | ||
| 281 | } | ||
| 282 | #else | ||
| 283 | #define tx4939ide_build_dmatable ide_build_dmatable | ||
| 284 | #endif | ||
| 285 | |||
| 286 | static int tx4939ide_dma_setup(ide_drive_t *drive) | ||
| 287 | { | ||
| 288 | ide_hwif_t *hwif = drive->hwif; | ||
| 289 | void __iomem *base = TX4939IDE_BASE(hwif); | ||
| 290 | struct request *rq = hwif->hwgroup->rq; | ||
| 291 | u8 reading; | ||
| 292 | int nent; | ||
| 293 | |||
| 294 | if (rq_data_dir(rq)) | ||
| 295 | reading = 0; | ||
| 296 | else | ||
| 297 | reading = ATA_DMA_WR; | ||
| 298 | |||
| 299 | /* fall back to PIO! */ | ||
| 300 | nent = tx4939ide_build_dmatable(drive, rq); | ||
| 301 | if (!nent) { | ||
| 302 | ide_map_sg(drive, rq); | ||
| 303 | return 1; | ||
| 304 | } | ||
| 305 | |||
| 306 | /* PRD table */ | ||
| 307 | tx4939ide_writel(hwif->dmatable_dma, base, TX4939IDE_PRD_Ptr); | ||
| 308 | |||
| 309 | /* specify r/w */ | ||
| 310 | tx4939ide_writeb(reading, base, TX4939IDE_DMA_Cmd); | ||
| 311 | |||
| 312 | /* clear INTR & ERROR flags */ | ||
| 313 | tx4939ide_clear_dma_status(base); | ||
| 314 | |||
| 315 | drive->waiting_for_dma = 1; | ||
| 316 | |||
| 317 | tx4939ide_writew(SECTOR_SIZE / 2, base, drive->dn ? | ||
| 318 | TX4939IDE_Xfer_Cnt_2 : TX4939IDE_Xfer_Cnt_1); | ||
| 319 | tx4939ide_writew(rq->nr_sectors, base, TX4939IDE_Sec_Cnt); | ||
| 320 | return 0; | ||
| 321 | } | ||
| 322 | |||
| 323 | static int tx4939ide_dma_end(ide_drive_t *drive) | ||
| 324 | { | ||
| 325 | ide_hwif_t *hwif = drive->hwif; | ||
| 326 | u8 dma_stat, dma_cmd; | ||
| 327 | void __iomem *base = TX4939IDE_BASE(hwif); | ||
| 328 | u16 ctl = tx4939ide_readw(base, TX4939IDE_Int_Ctl); | ||
| 329 | |||
| 330 | drive->waiting_for_dma = 0; | ||
| 331 | |||
| 332 | /* get DMA command mode */ | ||
| 333 | dma_cmd = tx4939ide_readb(base, TX4939IDE_DMA_Cmd); | ||
| 334 | /* stop DMA */ | ||
| 335 | tx4939ide_writeb(dma_cmd & ~ATA_DMA_START, base, TX4939IDE_DMA_Cmd); | ||
| 336 | |||
| 337 | /* read and clear the INTR & ERROR bits */ | ||
| 338 | dma_stat = tx4939ide_clear_dma_status(base); | ||
| 339 | |||
| 340 | /* purge DMA mappings */ | ||
| 341 | ide_destroy_dmatable(drive); | ||
| 342 | /* verify good DMA status */ | ||
| 343 | wmb(); | ||
| 344 | |||
| 345 | if ((dma_stat & (ATA_DMA_INTR | ATA_DMA_ERR | ATA_DMA_ACTIVE)) == 0 && | ||
| 346 | (ctl & (TX4939IDE_INT_XFEREND | TX4939IDE_INT_HOST)) == | ||
| 347 | (TX4939IDE_INT_XFEREND | TX4939IDE_INT_HOST)) | ||
| 348 | /* INT_IDE lost... bug? */ | ||
| 349 | return 0; | ||
| 350 | return ((dma_stat & (ATA_DMA_INTR | ATA_DMA_ERR | ATA_DMA_ACTIVE)) != | ||
| 351 | ATA_DMA_INTR) ? 0x10 | dma_stat : 0; | ||
| 352 | } | ||
| 353 | |||
| 354 | /* returns 1 if DMA IRQ issued, 0 otherwise */ | ||
| 355 | static int tx4939ide_dma_test_irq(ide_drive_t *drive) | ||
| 356 | { | ||
| 357 | ide_hwif_t *hwif = drive->hwif; | ||
| 358 | void __iomem *base = TX4939IDE_BASE(hwif); | ||
| 359 | u16 ctl, ide_int; | ||
| 360 | u8 dma_stat, stat; | ||
| 361 | int found = 0; | ||
| 362 | |||
| 363 | ctl = tx4939ide_check_error_ints(hwif); | ||
| 364 | ide_int = ctl & (TX4939IDE_INT_XFEREND | TX4939IDE_INT_HOST); | ||
| 365 | switch (ide_int) { | ||
| 366 | case TX4939IDE_INT_HOST: | ||
| 367 | /* On error, XFEREND might not be asserted. */ | ||
| 368 | stat = tx4939ide_readb(base, TX4939IDE_AltStat_DevCtl); | ||
| 369 | if ((stat & (ATA_BUSY | ATA_DRQ | ATA_ERR)) == ATA_ERR) | ||
| 370 | found = 1; | ||
| 371 | else | ||
| 372 | /* Wait for XFEREND (Mask HOST and unmask XFEREND) */ | ||
| 373 | ctl &= ~TX4939IDE_INT_XFEREND << 8; | ||
| 374 | ctl |= ide_int << 8; | ||
| 375 | break; | ||
| 376 | case TX4939IDE_INT_HOST | TX4939IDE_INT_XFEREND: | ||
| 377 | dma_stat = tx4939ide_readb(base, TX4939IDE_DMA_Stat); | ||
| 378 | if (!(dma_stat & ATA_DMA_INTR)) | ||
| 379 | pr_warning("%s: weird interrupt status. " | ||
| 380 | "DMA_Stat %#02x int_ctl %#04x\n", | ||
| 381 | hwif->name, dma_stat, ctl); | ||
| 382 | found = 1; | ||
| 383 | break; | ||
| 384 | } | ||
| 385 | /* | ||
| 386 | * Do not clear XFEREND, HOST now. They will be cleared by | ||
| 387 | * clearing bit2 of DMA_Stat. | ||
| 388 | */ | ||
| 389 | ctl &= ~ide_int; | ||
| 390 | tx4939ide_writew(ctl, base, TX4939IDE_Int_Ctl); | ||
| 391 | return found; | ||
| 392 | } | ||
| 393 | |||
| 394 | static void tx4939ide_init_hwif(ide_hwif_t *hwif) | ||
| 395 | { | ||
| 396 | void __iomem *base = TX4939IDE_BASE(hwif); | ||
| 397 | |||
| 398 | /* Soft Reset */ | ||
| 399 | tx4939ide_writew(0x8000, base, TX4939IDE_Sys_Ctl); | ||
| 400 | mmiowb(); | ||
| 401 | /* at least 20 GBUSCLK (typ. 100ns @ GBUS200MHz, max 450ns) */ | ||
| 402 | ndelay(450); | ||
| 403 | tx4939ide_writew(0x0000, base, TX4939IDE_Sys_Ctl); | ||
| 404 | /* mask some interrupts and clear all interrupts */ | ||
| 405 | tx4939ide_writew((TX4939IDE_IGNORE_INTS << 8) | 0xff, base, | ||
| 406 | TX4939IDE_Int_Ctl); | ||
| 407 | |||
| 408 | tx4939ide_writew(0x0008, base, TX4939IDE_Lo_Burst_Cnt); | ||
| 409 | tx4939ide_writew(0, base, TX4939IDE_Up_Burst_Cnt); | ||
| 410 | } | ||
| 411 | |||
| 412 | static int tx4939ide_init_dma(ide_hwif_t *hwif, const struct ide_port_info *d) | ||
| 413 | { | ||
| 414 | hwif->dma_base = | ||
| 415 | hwif->extra_base + tx4939ide_swizzleb(TX4939IDE_DMA_Cmd); | ||
| 416 | /* | ||
| 417 | * Note that we cannot use ATA_DMA_TABLE_OFS, ATA_DMA_STATUS | ||
| 418 | * for big endian. | ||
| 419 | */ | ||
| 420 | return ide_allocate_dma_engine(hwif); | ||
| 421 | } | ||
| 422 | |||
| 423 | static void tx4939ide_tf_load_fixup(ide_drive_t *drive, ide_task_t *task) | ||
| 424 | { | ||
| 425 | ide_hwif_t *hwif = drive->hwif; | ||
| 426 | void __iomem *base = TX4939IDE_BASE(hwif); | ||
| 427 | u16 sysctl = hwif->select_data >> (drive->dn ? 16 : 0); | ||
| 428 | |||
| 429 | /* | ||
| 430 | * Fix ATA100 CORE System Control Register. (The write to the | ||
| 431 | * Device/Head register may write wrong data to the System | ||
| 432 | * Control Register) | ||
| 433 | * While Sys_Ctl is written here, selectproc is not needed. | ||
| 434 | */ | ||
| 435 | tx4939ide_writew(sysctl, base, TX4939IDE_Sys_Ctl); | ||
| 436 | } | ||
| 437 | |||
| 438 | #ifdef __BIG_ENDIAN | ||
| 439 | |||
| 440 | static u8 tx4939ide_read_sff_dma_status(ide_hwif_t *hwif) | ||
| 441 | { | ||
| 442 | void __iomem *base = TX4939IDE_BASE(hwif); | ||
| 443 | |||
| 444 | return tx4939ide_readb(base, TX4939IDE_DMA_Stat); | ||
| 445 | } | ||
| 446 | |||
| 447 | /* custom iops (independent from SWAP_IO_SPACE) */ | ||
| 448 | static u8 tx4939ide_inb(unsigned long port) | ||
| 449 | { | ||
| 450 | return __raw_readb((void __iomem *)port); | ||
| 451 | } | ||
| 452 | |||
| 453 | static void tx4939ide_outb(u8 value, unsigned long port) | ||
| 454 | { | ||
| 455 | __raw_writeb(value, (void __iomem *)port); | ||
| 456 | } | ||
| 457 | |||
| 458 | static void tx4939ide_tf_load(ide_drive_t *drive, ide_task_t *task) | ||
| 459 | { | ||
| 460 | ide_hwif_t *hwif = drive->hwif; | ||
| 461 | struct ide_io_ports *io_ports = &hwif->io_ports; | ||
| 462 | struct ide_taskfile *tf = &task->tf; | ||
| 463 | u8 HIHI = task->tf_flags & IDE_TFLAG_LBA48 ? 0xE0 : 0xEF; | ||
| 464 | |||
| 465 | if (task->tf_flags & IDE_TFLAG_FLAGGED) | ||
| 466 | HIHI = 0xFF; | ||
| 467 | |||
| 468 | if (task->tf_flags & IDE_TFLAG_OUT_DATA) { | ||
| 469 | u16 data = (tf->hob_data << 8) | tf->data; | ||
| 470 | |||
| 471 | /* no endian swap */ | ||
| 472 | __raw_writew(data, (void __iomem *)io_ports->data_addr); | ||
| 473 | } | ||
| 474 | |||
| 475 | if (task->tf_flags & IDE_TFLAG_OUT_HOB_FEATURE) | ||
| 476 | tx4939ide_outb(tf->hob_feature, io_ports->feature_addr); | ||
| 477 | if (task->tf_flags & IDE_TFLAG_OUT_HOB_NSECT) | ||
| 478 | tx4939ide_outb(tf->hob_nsect, io_ports->nsect_addr); | ||
| 479 | if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAL) | ||
| 480 | tx4939ide_outb(tf->hob_lbal, io_ports->lbal_addr); | ||
| 481 | if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAM) | ||
| 482 | tx4939ide_outb(tf->hob_lbam, io_ports->lbam_addr); | ||
| 483 | if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAH) | ||
| 484 | tx4939ide_outb(tf->hob_lbah, io_ports->lbah_addr); | ||
| 485 | |||
| 486 | if (task->tf_flags & IDE_TFLAG_OUT_FEATURE) | ||
| 487 | tx4939ide_outb(tf->feature, io_ports->feature_addr); | ||
| 488 | if (task->tf_flags & IDE_TFLAG_OUT_NSECT) | ||
| 489 | tx4939ide_outb(tf->nsect, io_ports->nsect_addr); | ||
| 490 | if (task->tf_flags & IDE_TFLAG_OUT_LBAL) | ||
| 491 | tx4939ide_outb(tf->lbal, io_ports->lbal_addr); | ||
| 492 | if (task->tf_flags & IDE_TFLAG_OUT_LBAM) | ||
| 493 | tx4939ide_outb(tf->lbam, io_ports->lbam_addr); | ||
| 494 | if (task->tf_flags & IDE_TFLAG_OUT_LBAH) | ||
| 495 | tx4939ide_outb(tf->lbah, io_ports->lbah_addr); | ||
| 496 | |||
| 497 | if (task->tf_flags & IDE_TFLAG_OUT_DEVICE) { | ||
| 498 | tx4939ide_outb((tf->device & HIHI) | drive->select, | ||
| 499 | io_ports->device_addr); | ||
| 500 | tx4939ide_tf_load_fixup(drive, task); | ||
| 501 | } | ||
| 502 | } | ||
| 503 | |||
| 504 | static void tx4939ide_tf_read(ide_drive_t *drive, ide_task_t *task) | ||
| 505 | { | ||
| 506 | ide_hwif_t *hwif = drive->hwif; | ||
| 507 | struct ide_io_ports *io_ports = &hwif->io_ports; | ||
| 508 | struct ide_taskfile *tf = &task->tf; | ||
| 509 | |||
| 510 | if (task->tf_flags & IDE_TFLAG_IN_DATA) { | ||
| 511 | u16 data; | ||
| 512 | |||
| 513 | /* no endian swap */ | ||
| 514 | data = __raw_readw((void __iomem *)io_ports->data_addr); | ||
| 515 | tf->data = data & 0xff; | ||
| 516 | tf->hob_data = (data >> 8) & 0xff; | ||
| 517 | } | ||
| 518 | |||
| 519 | /* be sure we're looking at the low order bits */ | ||
| 520 | tx4939ide_outb(ATA_DEVCTL_OBS & ~0x80, io_ports->ctl_addr); | ||
| 521 | |||
| 522 | if (task->tf_flags & IDE_TFLAG_IN_FEATURE) | ||
| 523 | tf->feature = tx4939ide_inb(io_ports->feature_addr); | ||
| 524 | if (task->tf_flags & IDE_TFLAG_IN_NSECT) | ||
| 525 | tf->nsect = tx4939ide_inb(io_ports->nsect_addr); | ||
| 526 | if (task->tf_flags & IDE_TFLAG_IN_LBAL) | ||
| 527 | tf->lbal = tx4939ide_inb(io_ports->lbal_addr); | ||
| 528 | if (task->tf_flags & IDE_TFLAG_IN_LBAM) | ||
| 529 | tf->lbam = tx4939ide_inb(io_ports->lbam_addr); | ||
| 530 | if (task->tf_flags & IDE_TFLAG_IN_LBAH) | ||
| 531 | tf->lbah = tx4939ide_inb(io_ports->lbah_addr); | ||
| 532 | if (task->tf_flags & IDE_TFLAG_IN_DEVICE) | ||
| 533 | tf->device = tx4939ide_inb(io_ports->device_addr); | ||
| 534 | |||
| 535 | if (task->tf_flags & IDE_TFLAG_LBA48) { | ||
| 536 | tx4939ide_outb(ATA_DEVCTL_OBS | 0x80, io_ports->ctl_addr); | ||
| 537 | |||
| 538 | if (task->tf_flags & IDE_TFLAG_IN_HOB_FEATURE) | ||
| 539 | tf->hob_feature = | ||
| 540 | tx4939ide_inb(io_ports->feature_addr); | ||
| 541 | if (task->tf_flags & IDE_TFLAG_IN_HOB_NSECT) | ||
| 542 | tf->hob_nsect = tx4939ide_inb(io_ports->nsect_addr); | ||
| 543 | if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAL) | ||
| 544 | tf->hob_lbal = tx4939ide_inb(io_ports->lbal_addr); | ||
| 545 | if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAM) | ||
| 546 | tf->hob_lbam = tx4939ide_inb(io_ports->lbam_addr); | ||
| 547 | if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAH) | ||
| 548 | tf->hob_lbah = tx4939ide_inb(io_ports->lbah_addr); | ||
| 549 | } | ||
| 550 | } | ||
| 551 | |||
| 552 | static void tx4939ide_input_data_swap(ide_drive_t *drive, struct request *rq, | ||
| 553 | void *buf, unsigned int len) | ||
| 554 | { | ||
| 555 | unsigned long port = drive->hwif->io_ports.data_addr; | ||
| 556 | unsigned short *ptr = buf; | ||
| 557 | unsigned int count = (len + 1) / 2; | ||
| 558 | |||
| 559 | while (count--) | ||
| 560 | *ptr++ = cpu_to_le16(__raw_readw((void __iomem *)port)); | ||
| 561 | __ide_flush_dcache_range((unsigned long)buf, count * 2); | ||
| 562 | } | ||
| 563 | |||
| 564 | static void tx4939ide_output_data_swap(ide_drive_t *drive, struct request *rq, | ||
| 565 | void *buf, unsigned int len) | ||
| 566 | { | ||
| 567 | unsigned long port = drive->hwif->io_ports.data_addr; | ||
| 568 | unsigned short *ptr = buf; | ||
| 569 | unsigned int count = (len + 1) / 2; | ||
| 570 | |||
| 571 | while (count--) { | ||
| 572 | __raw_writew(le16_to_cpu(*ptr), (void __iomem *)port); | ||
| 573 | ptr++; | ||
| 574 | } | ||
| 575 | __ide_flush_dcache_range((unsigned long)buf, count * 2); | ||
| 576 | } | ||
| 577 | |||
| 578 | static const struct ide_tp_ops tx4939ide_tp_ops = { | ||
| 579 | .exec_command = ide_exec_command, | ||
| 580 | .read_status = ide_read_status, | ||
| 581 | .read_altstatus = ide_read_altstatus, | ||
| 582 | .read_sff_dma_status = tx4939ide_read_sff_dma_status, | ||
| 583 | |||
| 584 | .set_irq = ide_set_irq, | ||
| 585 | |||
| 586 | .tf_load = tx4939ide_tf_load, | ||
| 587 | .tf_read = tx4939ide_tf_read, | ||
| 588 | |||
| 589 | .input_data = tx4939ide_input_data_swap, | ||
| 590 | .output_data = tx4939ide_output_data_swap, | ||
| 591 | }; | ||
| 592 | |||
| 593 | #else /* __LITTLE_ENDIAN */ | ||
| 594 | |||
| 595 | static void tx4939ide_tf_load(ide_drive_t *drive, ide_task_t *task) | ||
| 596 | { | ||
| 597 | ide_tf_load(drive, task); | ||
| 598 | if (task->tf_flags & IDE_TFLAG_OUT_DEVICE) | ||
| 599 | tx4939ide_tf_load_fixup(drive, task); | ||
| 600 | } | ||
| 601 | |||
| 602 | static const struct ide_tp_ops tx4939ide_tp_ops = { | ||
| 603 | .exec_command = ide_exec_command, | ||
| 604 | .read_status = ide_read_status, | ||
| 605 | .read_altstatus = ide_read_altstatus, | ||
| 606 | .read_sff_dma_status = ide_read_sff_dma_status, | ||
| 607 | |||
| 608 | .set_irq = ide_set_irq, | ||
| 609 | |||
| 610 | .tf_load = tx4939ide_tf_load, | ||
| 611 | .tf_read = ide_tf_read, | ||
| 612 | |||
| 613 | .input_data = ide_input_data, | ||
| 614 | .output_data = ide_output_data, | ||
| 615 | }; | ||
| 616 | |||
| 617 | #endif /* __LITTLE_ENDIAN */ | ||
| 618 | |||
| 619 | static const struct ide_port_ops tx4939ide_port_ops = { | ||
| 620 | .set_pio_mode = tx4939ide_set_pio_mode, | ||
| 621 | .set_dma_mode = tx4939ide_set_dma_mode, | ||
| 622 | .clear_irq = tx4939ide_clear_irq, | ||
| 623 | .cable_detect = tx4939ide_cable_detect, | ||
| 624 | }; | ||
| 625 | |||
| 626 | static const struct ide_dma_ops tx4939ide_dma_ops = { | ||
| 627 | .dma_host_set = tx4939ide_dma_host_set, | ||
| 628 | .dma_setup = tx4939ide_dma_setup, | ||
| 629 | .dma_exec_cmd = ide_dma_exec_cmd, | ||
| 630 | .dma_start = ide_dma_start, | ||
| 631 | .dma_end = tx4939ide_dma_end, | ||
| 632 | .dma_test_irq = tx4939ide_dma_test_irq, | ||
| 633 | .dma_lost_irq = ide_dma_lost_irq, | ||
| 634 | .dma_timeout = ide_dma_timeout, | ||
| 635 | }; | ||
| 636 | |||
| 637 | static const struct ide_port_info tx4939ide_port_info __initdata = { | ||
| 638 | .init_hwif = tx4939ide_init_hwif, | ||
| 639 | .init_dma = tx4939ide_init_dma, | ||
| 640 | .port_ops = &tx4939ide_port_ops, | ||
| 641 | .dma_ops = &tx4939ide_dma_ops, | ||
| 642 | .tp_ops = &tx4939ide_tp_ops, | ||
| 643 | .host_flags = IDE_HFLAG_MMIO, | ||
| 644 | .pio_mask = ATA_PIO4, | ||
| 645 | .mwdma_mask = ATA_MWDMA2, | ||
| 646 | .udma_mask = ATA_UDMA5, | ||
| 647 | }; | ||
| 648 | |||
| 649 | static int __init tx4939ide_probe(struct platform_device *pdev) | ||
| 650 | { | ||
| 651 | hw_regs_t hw; | ||
| 652 | hw_regs_t *hws[] = { &hw, NULL, NULL, NULL }; | ||
| 653 | struct ide_host *host; | ||
| 654 | struct resource *res; | ||
| 655 | int irq, ret; | ||
| 656 | unsigned long mapbase; | ||
| 657 | |||
| 658 | irq = platform_get_irq(pdev, 0); | ||
| 659 | if (irq < 0) | ||
| 660 | return -ENODEV; | ||
| 661 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 662 | if (!res) | ||
| 663 | return -ENODEV; | ||
| 664 | |||
| 665 | if (!devm_request_mem_region(&pdev->dev, res->start, | ||
| 666 | res->end - res->start + 1, "tx4938ide")) | ||
| 667 | return -EBUSY; | ||
| 668 | mapbase = (unsigned long)devm_ioremap(&pdev->dev, res->start, | ||
| 669 | res->end - res->start + 1); | ||
| 670 | if (!mapbase) | ||
| 671 | return -EBUSY; | ||
| 672 | memset(&hw, 0, sizeof(hw)); | ||
| 673 | hw.io_ports.data_addr = | ||
| 674 | mapbase + tx4939ide_swizzlew(TX4939IDE_Data); | ||
| 675 | hw.io_ports.error_addr = | ||
| 676 | mapbase + tx4939ide_swizzleb(TX4939IDE_Error_Feature); | ||
| 677 | hw.io_ports.nsect_addr = | ||
| 678 | mapbase + tx4939ide_swizzleb(TX4939IDE_Sec); | ||
| 679 | hw.io_ports.lbal_addr = | ||
| 680 | mapbase + tx4939ide_swizzleb(TX4939IDE_LBA0); | ||
| 681 | hw.io_ports.lbam_addr = | ||
| 682 | mapbase + tx4939ide_swizzleb(TX4939IDE_LBA1); | ||
| 683 | hw.io_ports.lbah_addr = | ||
| 684 | mapbase + tx4939ide_swizzleb(TX4939IDE_LBA2); | ||
| 685 | hw.io_ports.device_addr = | ||
| 686 | mapbase + tx4939ide_swizzleb(TX4939IDE_DevHead); | ||
| 687 | hw.io_ports.command_addr = | ||
| 688 | mapbase + tx4939ide_swizzleb(TX4939IDE_Stat_Cmd); | ||
| 689 | hw.io_ports.ctl_addr = | ||
| 690 | mapbase + tx4939ide_swizzleb(TX4939IDE_AltStat_DevCtl); | ||
| 691 | hw.irq = irq; | ||
| 692 | hw.dev = &pdev->dev; | ||
| 693 | |||
| 694 | pr_info("TX4939 IDE interface (base %#lx, irq %d)\n", mapbase, irq); | ||
| 695 | host = ide_host_alloc(&tx4939ide_port_info, hws); | ||
| 696 | if (!host) | ||
| 697 | return -ENOMEM; | ||
| 698 | /* use extra_base for base address of the all registers */ | ||
| 699 | host->ports[0]->extra_base = mapbase; | ||
| 700 | ret = ide_host_register(host, &tx4939ide_port_info, hws); | ||
| 701 | if (ret) { | ||
| 702 | ide_host_free(host); | ||
| 703 | return ret; | ||
| 704 | } | ||
| 705 | platform_set_drvdata(pdev, host); | ||
| 706 | return 0; | ||
| 707 | } | ||
| 708 | |||
| 709 | static int __exit tx4939ide_remove(struct platform_device *pdev) | ||
| 710 | { | ||
| 711 | struct ide_host *host = platform_get_drvdata(pdev); | ||
| 712 | |||
| 713 | ide_host_remove(host); | ||
| 714 | return 0; | ||
| 715 | } | ||
| 716 | |||
| 717 | #ifdef CONFIG_PM | ||
| 718 | static int tx4939ide_resume(struct platform_device *dev) | ||
| 719 | { | ||
| 720 | struct ide_host *host = platform_get_drvdata(dev); | ||
| 721 | ide_hwif_t *hwif = host->ports[0]; | ||
| 722 | |||
| 723 | tx4939ide_init_hwif(hwif); | ||
| 724 | return 0; | ||
| 725 | } | ||
| 726 | #else | ||
| 727 | #define tx4939ide_resume NULL | ||
| 728 | #endif | ||
| 729 | |||
| 730 | static struct platform_driver tx4939ide_driver = { | ||
| 731 | .driver = { | ||
| 732 | .name = MODNAME, | ||
| 733 | .owner = THIS_MODULE, | ||
| 734 | }, | ||
| 735 | .remove = __exit_p(tx4939ide_remove), | ||
| 736 | .resume = tx4939ide_resume, | ||
| 737 | }; | ||
| 738 | |||
| 739 | static int __init tx4939ide_init(void) | ||
| 740 | { | ||
| 741 | return platform_driver_probe(&tx4939ide_driver, tx4939ide_probe); | ||
| 742 | } | ||
| 743 | |||
| 744 | static void __exit tx4939ide_exit(void) | ||
| 745 | { | ||
| 746 | platform_driver_unregister(&tx4939ide_driver); | ||
| 747 | } | ||
| 748 | |||
| 749 | module_init(tx4939ide_init); | ||
| 750 | module_exit(tx4939ide_exit); | ||
| 751 | |||
| 752 | MODULE_DESCRIPTION("TX4939 internal IDE driver"); | ||
| 753 | MODULE_LICENSE("GPL"); | ||
| 754 | MODULE_ALIAS("platform:tx4939ide"); | ||
