162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Libata based driver for Apple "macio" family of PATA controllers 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright 2008/2009 Benjamin Herrenschmidt, IBM Corp 662306a36Sopenharmony_ci * <benh@kernel.crashing.org> 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci * Some bits and pieces from drivers/ide/ppc/pmac.c 962306a36Sopenharmony_ci * 1062306a36Sopenharmony_ci */ 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#undef DEBUG 1362306a36Sopenharmony_ci#undef DEBUG_DMA 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci#include <linux/kernel.h> 1662306a36Sopenharmony_ci#include <linux/module.h> 1762306a36Sopenharmony_ci#include <linux/init.h> 1862306a36Sopenharmony_ci#include <linux/blkdev.h> 1962306a36Sopenharmony_ci#include <linux/ata.h> 2062306a36Sopenharmony_ci#include <linux/libata.h> 2162306a36Sopenharmony_ci#include <linux/adb.h> 2262306a36Sopenharmony_ci#include <linux/pmu.h> 2362306a36Sopenharmony_ci#include <linux/scatterlist.h> 2462306a36Sopenharmony_ci#include <linux/irqdomain.h> 2562306a36Sopenharmony_ci#include <linux/of.h> 2662306a36Sopenharmony_ci#include <linux/gfp.h> 2762306a36Sopenharmony_ci#include <linux/pci.h> 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci#include <scsi/scsi.h> 3062306a36Sopenharmony_ci#include <scsi/scsi_host.h> 3162306a36Sopenharmony_ci#include <scsi/scsi_device.h> 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci#include <asm/macio.h> 3462306a36Sopenharmony_ci#include <asm/io.h> 3562306a36Sopenharmony_ci#include <asm/dbdma.h> 3662306a36Sopenharmony_ci#include <asm/machdep.h> 3762306a36Sopenharmony_ci#include <asm/pmac_feature.h> 3862306a36Sopenharmony_ci#include <asm/mediabay.h> 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci#ifdef DEBUG_DMA 4162306a36Sopenharmony_ci#define dev_dbgdma(dev, format, arg...) \ 4262306a36Sopenharmony_ci dev_printk(KERN_DEBUG , dev , format , ## arg) 4362306a36Sopenharmony_ci#else 4462306a36Sopenharmony_ci#define dev_dbgdma(dev, format, arg...) \ 4562306a36Sopenharmony_ci ({ if (0) dev_printk(KERN_DEBUG, dev, format, ##arg); 0; }) 4662306a36Sopenharmony_ci#endif 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ci#define DRV_NAME "pata_macio" 4962306a36Sopenharmony_ci#define DRV_VERSION "0.9" 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci/* Models of macio ATA controller */ 5262306a36Sopenharmony_cienum { 5362306a36Sopenharmony_ci controller_ohare, /* OHare based */ 5462306a36Sopenharmony_ci controller_heathrow, /* Heathrow/Paddington */ 5562306a36Sopenharmony_ci controller_kl_ata3, /* KeyLargo ATA-3 */ 5662306a36Sopenharmony_ci controller_kl_ata4, /* KeyLargo ATA-4 */ 5762306a36Sopenharmony_ci controller_un_ata6, /* UniNorth2 ATA-6 */ 5862306a36Sopenharmony_ci controller_k2_ata6, /* K2 ATA-6 */ 5962306a36Sopenharmony_ci controller_sh_ata6, /* Shasta ATA-6 */ 6062306a36Sopenharmony_ci}; 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_cistatic const char* macio_ata_names[] = { 6362306a36Sopenharmony_ci "OHare ATA", /* OHare based */ 6462306a36Sopenharmony_ci "Heathrow ATA", /* Heathrow/Paddington */ 6562306a36Sopenharmony_ci "KeyLargo ATA-3", /* KeyLargo ATA-3 (MDMA only) */ 6662306a36Sopenharmony_ci "KeyLargo ATA-4", /* KeyLargo ATA-4 (UDMA/66) */ 6762306a36Sopenharmony_ci "UniNorth ATA-6", /* UniNorth2 ATA-6 (UDMA/100) */ 6862306a36Sopenharmony_ci "K2 ATA-6", /* K2 ATA-6 (UDMA/100) */ 6962306a36Sopenharmony_ci "Shasta ATA-6", /* Shasta ATA-6 (UDMA/133) */ 7062306a36Sopenharmony_ci}; 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci/* 7362306a36Sopenharmony_ci * Extra registers, both 32-bit little-endian 7462306a36Sopenharmony_ci */ 7562306a36Sopenharmony_ci#define IDE_TIMING_CONFIG 0x200 7662306a36Sopenharmony_ci#define IDE_INTERRUPT 0x300 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci/* Kauai (U2) ATA has different register setup */ 7962306a36Sopenharmony_ci#define IDE_KAUAI_PIO_CONFIG 0x200 8062306a36Sopenharmony_ci#define IDE_KAUAI_ULTRA_CONFIG 0x210 8162306a36Sopenharmony_ci#define IDE_KAUAI_POLL_CONFIG 0x220 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ci/* 8462306a36Sopenharmony_ci * Timing configuration register definitions 8562306a36Sopenharmony_ci */ 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci/* Number of IDE_SYSCLK_NS ticks, argument is in nanoseconds */ 8862306a36Sopenharmony_ci#define SYSCLK_TICKS(t) (((t) + IDE_SYSCLK_NS - 1) / IDE_SYSCLK_NS) 8962306a36Sopenharmony_ci#define SYSCLK_TICKS_66(t) (((t) + IDE_SYSCLK_66_NS - 1) / IDE_SYSCLK_66_NS) 9062306a36Sopenharmony_ci#define IDE_SYSCLK_NS 30 /* 33Mhz cell */ 9162306a36Sopenharmony_ci#define IDE_SYSCLK_66_NS 15 /* 66Mhz cell */ 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci/* 133Mhz cell, found in shasta. 9462306a36Sopenharmony_ci * See comments about 100 Mhz Uninorth 2... 9562306a36Sopenharmony_ci * Note that PIO_MASK and MDMA_MASK seem to overlap, that's just 9662306a36Sopenharmony_ci * weird and I don't now why .. at this stage 9762306a36Sopenharmony_ci */ 9862306a36Sopenharmony_ci#define TR_133_PIOREG_PIO_MASK 0xff000fff 9962306a36Sopenharmony_ci#define TR_133_PIOREG_MDMA_MASK 0x00fff800 10062306a36Sopenharmony_ci#define TR_133_UDMAREG_UDMA_MASK 0x0003ffff 10162306a36Sopenharmony_ci#define TR_133_UDMAREG_UDMA_EN 0x00000001 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci/* 100Mhz cell, found in Uninorth 2 and K2. It appears as a pci device 10462306a36Sopenharmony_ci * (106b/0033) on uninorth or K2 internal PCI bus and it's clock is 10562306a36Sopenharmony_ci * controlled like gem or fw. It appears to be an evolution of keylargo 10662306a36Sopenharmony_ci * ATA4 with a timing register extended to 2x32bits registers (one 10762306a36Sopenharmony_ci * for PIO & MWDMA and one for UDMA, and a similar DBDMA channel. 10862306a36Sopenharmony_ci * It has it's own local feature control register as well. 10962306a36Sopenharmony_ci * 11062306a36Sopenharmony_ci * After scratching my mind over the timing values, at least for PIO 11162306a36Sopenharmony_ci * and MDMA, I think I've figured the format of the timing register, 11262306a36Sopenharmony_ci * though I use pre-calculated tables for UDMA as usual... 11362306a36Sopenharmony_ci */ 11462306a36Sopenharmony_ci#define TR_100_PIO_ADDRSETUP_MASK 0xff000000 /* Size of field unknown */ 11562306a36Sopenharmony_ci#define TR_100_PIO_ADDRSETUP_SHIFT 24 11662306a36Sopenharmony_ci#define TR_100_MDMA_MASK 0x00fff000 11762306a36Sopenharmony_ci#define TR_100_MDMA_RECOVERY_MASK 0x00fc0000 11862306a36Sopenharmony_ci#define TR_100_MDMA_RECOVERY_SHIFT 18 11962306a36Sopenharmony_ci#define TR_100_MDMA_ACCESS_MASK 0x0003f000 12062306a36Sopenharmony_ci#define TR_100_MDMA_ACCESS_SHIFT 12 12162306a36Sopenharmony_ci#define TR_100_PIO_MASK 0xff000fff 12262306a36Sopenharmony_ci#define TR_100_PIO_RECOVERY_MASK 0x00000fc0 12362306a36Sopenharmony_ci#define TR_100_PIO_RECOVERY_SHIFT 6 12462306a36Sopenharmony_ci#define TR_100_PIO_ACCESS_MASK 0x0000003f 12562306a36Sopenharmony_ci#define TR_100_PIO_ACCESS_SHIFT 0 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_ci#define TR_100_UDMAREG_UDMA_MASK 0x0000ffff 12862306a36Sopenharmony_ci#define TR_100_UDMAREG_UDMA_EN 0x00000001 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci/* 66Mhz cell, found in KeyLargo. Can do ultra mode 0 to 2 on 13262306a36Sopenharmony_ci * 40 connector cable and to 4 on 80 connector one. 13362306a36Sopenharmony_ci * Clock unit is 15ns (66Mhz) 13462306a36Sopenharmony_ci * 13562306a36Sopenharmony_ci * 3 Values can be programmed: 13662306a36Sopenharmony_ci * - Write data setup, which appears to match the cycle time. They 13762306a36Sopenharmony_ci * also call it DIOW setup. 13862306a36Sopenharmony_ci * - Ready to pause time (from spec) 13962306a36Sopenharmony_ci * - Address setup. That one is weird. I don't see where exactly 14062306a36Sopenharmony_ci * it fits in UDMA cycles, I got it's name from an obscure piece 14162306a36Sopenharmony_ci * of commented out code in Darwin. They leave it to 0, we do as 14262306a36Sopenharmony_ci * well, despite a comment that would lead to think it has a 14362306a36Sopenharmony_ci * min value of 45ns. 14462306a36Sopenharmony_ci * Apple also add 60ns to the write data setup (or cycle time ?) on 14562306a36Sopenharmony_ci * reads. 14662306a36Sopenharmony_ci */ 14762306a36Sopenharmony_ci#define TR_66_UDMA_MASK 0xfff00000 14862306a36Sopenharmony_ci#define TR_66_UDMA_EN 0x00100000 /* Enable Ultra mode for DMA */ 14962306a36Sopenharmony_ci#define TR_66_PIO_ADDRSETUP_MASK 0xe0000000 /* Address setup */ 15062306a36Sopenharmony_ci#define TR_66_PIO_ADDRSETUP_SHIFT 29 15162306a36Sopenharmony_ci#define TR_66_UDMA_RDY2PAUS_MASK 0x1e000000 /* Ready 2 pause time */ 15262306a36Sopenharmony_ci#define TR_66_UDMA_RDY2PAUS_SHIFT 25 15362306a36Sopenharmony_ci#define TR_66_UDMA_WRDATASETUP_MASK 0x01e00000 /* Write data setup time */ 15462306a36Sopenharmony_ci#define TR_66_UDMA_WRDATASETUP_SHIFT 21 15562306a36Sopenharmony_ci#define TR_66_MDMA_MASK 0x000ffc00 15662306a36Sopenharmony_ci#define TR_66_MDMA_RECOVERY_MASK 0x000f8000 15762306a36Sopenharmony_ci#define TR_66_MDMA_RECOVERY_SHIFT 15 15862306a36Sopenharmony_ci#define TR_66_MDMA_ACCESS_MASK 0x00007c00 15962306a36Sopenharmony_ci#define TR_66_MDMA_ACCESS_SHIFT 10 16062306a36Sopenharmony_ci#define TR_66_PIO_MASK 0xe00003ff 16162306a36Sopenharmony_ci#define TR_66_PIO_RECOVERY_MASK 0x000003e0 16262306a36Sopenharmony_ci#define TR_66_PIO_RECOVERY_SHIFT 5 16362306a36Sopenharmony_ci#define TR_66_PIO_ACCESS_MASK 0x0000001f 16462306a36Sopenharmony_ci#define TR_66_PIO_ACCESS_SHIFT 0 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_ci/* 33Mhz cell, found in OHare, Heathrow (& Paddington) and KeyLargo 16762306a36Sopenharmony_ci * Can do pio & mdma modes, clock unit is 30ns (33Mhz) 16862306a36Sopenharmony_ci * 16962306a36Sopenharmony_ci * The access time and recovery time can be programmed. Some older 17062306a36Sopenharmony_ci * Darwin code base limit OHare to 150ns cycle time. I decided to do 17162306a36Sopenharmony_ci * the same here fore safety against broken old hardware ;) 17262306a36Sopenharmony_ci * The HalfTick bit, when set, adds half a clock (15ns) to the access 17362306a36Sopenharmony_ci * time and removes one from recovery. It's not supported on KeyLargo 17462306a36Sopenharmony_ci * implementation afaik. The E bit appears to be set for PIO mode 0 and 17562306a36Sopenharmony_ci * is used to reach long timings used in this mode. 17662306a36Sopenharmony_ci */ 17762306a36Sopenharmony_ci#define TR_33_MDMA_MASK 0x003ff800 17862306a36Sopenharmony_ci#define TR_33_MDMA_RECOVERY_MASK 0x001f0000 17962306a36Sopenharmony_ci#define TR_33_MDMA_RECOVERY_SHIFT 16 18062306a36Sopenharmony_ci#define TR_33_MDMA_ACCESS_MASK 0x0000f800 18162306a36Sopenharmony_ci#define TR_33_MDMA_ACCESS_SHIFT 11 18262306a36Sopenharmony_ci#define TR_33_MDMA_HALFTICK 0x00200000 18362306a36Sopenharmony_ci#define TR_33_PIO_MASK 0x000007ff 18462306a36Sopenharmony_ci#define TR_33_PIO_E 0x00000400 18562306a36Sopenharmony_ci#define TR_33_PIO_RECOVERY_MASK 0x000003e0 18662306a36Sopenharmony_ci#define TR_33_PIO_RECOVERY_SHIFT 5 18762306a36Sopenharmony_ci#define TR_33_PIO_ACCESS_MASK 0x0000001f 18862306a36Sopenharmony_ci#define TR_33_PIO_ACCESS_SHIFT 0 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_ci/* 19162306a36Sopenharmony_ci * Interrupt register definitions. Only present on newer cells 19262306a36Sopenharmony_ci * (Keylargo and later afaik) so we don't use it. 19362306a36Sopenharmony_ci */ 19462306a36Sopenharmony_ci#define IDE_INTR_DMA 0x80000000 19562306a36Sopenharmony_ci#define IDE_INTR_DEVICE 0x40000000 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ci/* 19862306a36Sopenharmony_ci * FCR Register on Kauai. Not sure what bit 0x4 is ... 19962306a36Sopenharmony_ci */ 20062306a36Sopenharmony_ci#define KAUAI_FCR_UATA_MAGIC 0x00000004 20162306a36Sopenharmony_ci#define KAUAI_FCR_UATA_RESET_N 0x00000002 20262306a36Sopenharmony_ci#define KAUAI_FCR_UATA_ENABLE 0x00000001 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_ci/* Allow up to 256 DBDMA commands per xfer */ 20662306a36Sopenharmony_ci#define MAX_DCMDS 256 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_ci/* Don't let a DMA segment go all the way to 64K */ 20962306a36Sopenharmony_ci#define MAX_DBDMA_SEG 0xff00 21062306a36Sopenharmony_ci 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_ci/* 21362306a36Sopenharmony_ci * Wait 1s for disk to answer on IDE bus after a hard reset 21462306a36Sopenharmony_ci * of the device (via GPIO/FCR). 21562306a36Sopenharmony_ci * 21662306a36Sopenharmony_ci * Some devices seem to "pollute" the bus even after dropping 21762306a36Sopenharmony_ci * the BSY bit (typically some combo drives slave on the UDMA 21862306a36Sopenharmony_ci * bus) after a hard reset. Since we hard reset all drives on 21962306a36Sopenharmony_ci * KeyLargo ATA66, we have to keep that delay around. I may end 22062306a36Sopenharmony_ci * up not hard resetting anymore on these and keep the delay only 22162306a36Sopenharmony_ci * for older interfaces instead (we have to reset when coming 22262306a36Sopenharmony_ci * from MacOS...) --BenH. 22362306a36Sopenharmony_ci */ 22462306a36Sopenharmony_ci#define IDE_WAKEUP_DELAY_MS 1000 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_cistruct pata_macio_timing; 22762306a36Sopenharmony_ci 22862306a36Sopenharmony_cistruct pata_macio_priv { 22962306a36Sopenharmony_ci int kind; 23062306a36Sopenharmony_ci int aapl_bus_id; 23162306a36Sopenharmony_ci int mediabay : 1; 23262306a36Sopenharmony_ci struct device_node *node; 23362306a36Sopenharmony_ci struct macio_dev *mdev; 23462306a36Sopenharmony_ci struct pci_dev *pdev; 23562306a36Sopenharmony_ci struct device *dev; 23662306a36Sopenharmony_ci int irq; 23762306a36Sopenharmony_ci u32 treg[2][2]; 23862306a36Sopenharmony_ci void __iomem *tfregs; 23962306a36Sopenharmony_ci void __iomem *kauai_fcr; 24062306a36Sopenharmony_ci struct dbdma_cmd * dma_table_cpu; 24162306a36Sopenharmony_ci dma_addr_t dma_table_dma; 24262306a36Sopenharmony_ci struct ata_host *host; 24362306a36Sopenharmony_ci const struct pata_macio_timing *timings; 24462306a36Sopenharmony_ci}; 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_ci/* Previous variants of this driver used to calculate timings 24762306a36Sopenharmony_ci * for various variants of the chip and use tables for others. 24862306a36Sopenharmony_ci * 24962306a36Sopenharmony_ci * Not only was this confusing, but in addition, it isn't clear 25062306a36Sopenharmony_ci * whether our calculation code was correct. It didn't entirely 25162306a36Sopenharmony_ci * match the darwin code and whatever documentation I could find 25262306a36Sopenharmony_ci * on these cells 25362306a36Sopenharmony_ci * 25462306a36Sopenharmony_ci * I decided to entirely rely on a table instead for this version 25562306a36Sopenharmony_ci * of the driver. Also, because I don't really care about derated 25662306a36Sopenharmony_ci * modes and really old HW other than making it work, I'm not going 25762306a36Sopenharmony_ci * to calculate / snoop timing values for something else than the 25862306a36Sopenharmony_ci * standard modes. 25962306a36Sopenharmony_ci */ 26062306a36Sopenharmony_cistruct pata_macio_timing { 26162306a36Sopenharmony_ci int mode; 26262306a36Sopenharmony_ci u32 reg1; /* Bits to set in first timing reg */ 26362306a36Sopenharmony_ci u32 reg2; /* Bits to set in second timing reg */ 26462306a36Sopenharmony_ci}; 26562306a36Sopenharmony_ci 26662306a36Sopenharmony_cistatic const struct pata_macio_timing pata_macio_ohare_timings[] = { 26762306a36Sopenharmony_ci { XFER_PIO_0, 0x00000526, 0, }, 26862306a36Sopenharmony_ci { XFER_PIO_1, 0x00000085, 0, }, 26962306a36Sopenharmony_ci { XFER_PIO_2, 0x00000025, 0, }, 27062306a36Sopenharmony_ci { XFER_PIO_3, 0x00000025, 0, }, 27162306a36Sopenharmony_ci { XFER_PIO_4, 0x00000025, 0, }, 27262306a36Sopenharmony_ci { XFER_MW_DMA_0, 0x00074000, 0, }, 27362306a36Sopenharmony_ci { XFER_MW_DMA_1, 0x00221000, 0, }, 27462306a36Sopenharmony_ci { XFER_MW_DMA_2, 0x00211000, 0, }, 27562306a36Sopenharmony_ci { -1, 0, 0 } 27662306a36Sopenharmony_ci}; 27762306a36Sopenharmony_ci 27862306a36Sopenharmony_cistatic const struct pata_macio_timing pata_macio_heathrow_timings[] = { 27962306a36Sopenharmony_ci { XFER_PIO_0, 0x00000526, 0, }, 28062306a36Sopenharmony_ci { XFER_PIO_1, 0x00000085, 0, }, 28162306a36Sopenharmony_ci { XFER_PIO_2, 0x00000025, 0, }, 28262306a36Sopenharmony_ci { XFER_PIO_3, 0x00000025, 0, }, 28362306a36Sopenharmony_ci { XFER_PIO_4, 0x00000025, 0, }, 28462306a36Sopenharmony_ci { XFER_MW_DMA_0, 0x00074000, 0, }, 28562306a36Sopenharmony_ci { XFER_MW_DMA_1, 0x00221000, 0, }, 28662306a36Sopenharmony_ci { XFER_MW_DMA_2, 0x00211000, 0, }, 28762306a36Sopenharmony_ci { -1, 0, 0 } 28862306a36Sopenharmony_ci}; 28962306a36Sopenharmony_ci 29062306a36Sopenharmony_cistatic const struct pata_macio_timing pata_macio_kl33_timings[] = { 29162306a36Sopenharmony_ci { XFER_PIO_0, 0x00000526, 0, }, 29262306a36Sopenharmony_ci { XFER_PIO_1, 0x00000085, 0, }, 29362306a36Sopenharmony_ci { XFER_PIO_2, 0x00000025, 0, }, 29462306a36Sopenharmony_ci { XFER_PIO_3, 0x00000025, 0, }, 29562306a36Sopenharmony_ci { XFER_PIO_4, 0x00000025, 0, }, 29662306a36Sopenharmony_ci { XFER_MW_DMA_0, 0x00084000, 0, }, 29762306a36Sopenharmony_ci { XFER_MW_DMA_1, 0x00021800, 0, }, 29862306a36Sopenharmony_ci { XFER_MW_DMA_2, 0x00011800, 0, }, 29962306a36Sopenharmony_ci { -1, 0, 0 } 30062306a36Sopenharmony_ci}; 30162306a36Sopenharmony_ci 30262306a36Sopenharmony_cistatic const struct pata_macio_timing pata_macio_kl66_timings[] = { 30362306a36Sopenharmony_ci { XFER_PIO_0, 0x0000038c, 0, }, 30462306a36Sopenharmony_ci { XFER_PIO_1, 0x0000020a, 0, }, 30562306a36Sopenharmony_ci { XFER_PIO_2, 0x00000127, 0, }, 30662306a36Sopenharmony_ci { XFER_PIO_3, 0x000000c6, 0, }, 30762306a36Sopenharmony_ci { XFER_PIO_4, 0x00000065, 0, }, 30862306a36Sopenharmony_ci { XFER_MW_DMA_0, 0x00084000, 0, }, 30962306a36Sopenharmony_ci { XFER_MW_DMA_1, 0x00029800, 0, }, 31062306a36Sopenharmony_ci { XFER_MW_DMA_2, 0x00019400, 0, }, 31162306a36Sopenharmony_ci { XFER_UDMA_0, 0x19100000, 0, }, 31262306a36Sopenharmony_ci { XFER_UDMA_1, 0x14d00000, 0, }, 31362306a36Sopenharmony_ci { XFER_UDMA_2, 0x10900000, 0, }, 31462306a36Sopenharmony_ci { XFER_UDMA_3, 0x0c700000, 0, }, 31562306a36Sopenharmony_ci { XFER_UDMA_4, 0x0c500000, 0, }, 31662306a36Sopenharmony_ci { -1, 0, 0 } 31762306a36Sopenharmony_ci}; 31862306a36Sopenharmony_ci 31962306a36Sopenharmony_cistatic const struct pata_macio_timing pata_macio_kauai_timings[] = { 32062306a36Sopenharmony_ci { XFER_PIO_0, 0x08000a92, 0, }, 32162306a36Sopenharmony_ci { XFER_PIO_1, 0x0800060f, 0, }, 32262306a36Sopenharmony_ci { XFER_PIO_2, 0x0800038b, 0, }, 32362306a36Sopenharmony_ci { XFER_PIO_3, 0x05000249, 0, }, 32462306a36Sopenharmony_ci { XFER_PIO_4, 0x04000148, 0, }, 32562306a36Sopenharmony_ci { XFER_MW_DMA_0, 0x00618000, 0, }, 32662306a36Sopenharmony_ci { XFER_MW_DMA_1, 0x00209000, 0, }, 32762306a36Sopenharmony_ci { XFER_MW_DMA_2, 0x00148000, 0, }, 32862306a36Sopenharmony_ci { XFER_UDMA_0, 0, 0x000070c1, }, 32962306a36Sopenharmony_ci { XFER_UDMA_1, 0, 0x00005d81, }, 33062306a36Sopenharmony_ci { XFER_UDMA_2, 0, 0x00004a61, }, 33162306a36Sopenharmony_ci { XFER_UDMA_3, 0, 0x00003a51, }, 33262306a36Sopenharmony_ci { XFER_UDMA_4, 0, 0x00002a31, }, 33362306a36Sopenharmony_ci { XFER_UDMA_5, 0, 0x00002921, }, 33462306a36Sopenharmony_ci { -1, 0, 0 } 33562306a36Sopenharmony_ci}; 33662306a36Sopenharmony_ci 33762306a36Sopenharmony_cistatic const struct pata_macio_timing pata_macio_shasta_timings[] = { 33862306a36Sopenharmony_ci { XFER_PIO_0, 0x0a000c97, 0, }, 33962306a36Sopenharmony_ci { XFER_PIO_1, 0x07000712, 0, }, 34062306a36Sopenharmony_ci { XFER_PIO_2, 0x040003cd, 0, }, 34162306a36Sopenharmony_ci { XFER_PIO_3, 0x0500028b, 0, }, 34262306a36Sopenharmony_ci { XFER_PIO_4, 0x0400010a, 0, }, 34362306a36Sopenharmony_ci { XFER_MW_DMA_0, 0x00820800, 0, }, 34462306a36Sopenharmony_ci { XFER_MW_DMA_1, 0x0028b000, 0, }, 34562306a36Sopenharmony_ci { XFER_MW_DMA_2, 0x001ca000, 0, }, 34662306a36Sopenharmony_ci { XFER_UDMA_0, 0, 0x00035901, }, 34762306a36Sopenharmony_ci { XFER_UDMA_1, 0, 0x000348b1, }, 34862306a36Sopenharmony_ci { XFER_UDMA_2, 0, 0x00033881, }, 34962306a36Sopenharmony_ci { XFER_UDMA_3, 0, 0x00033861, }, 35062306a36Sopenharmony_ci { XFER_UDMA_4, 0, 0x00033841, }, 35162306a36Sopenharmony_ci { XFER_UDMA_5, 0, 0x00033031, }, 35262306a36Sopenharmony_ci { XFER_UDMA_6, 0, 0x00033021, }, 35362306a36Sopenharmony_ci { -1, 0, 0 } 35462306a36Sopenharmony_ci}; 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_cistatic const struct pata_macio_timing *pata_macio_find_timing( 35762306a36Sopenharmony_ci struct pata_macio_priv *priv, 35862306a36Sopenharmony_ci int mode) 35962306a36Sopenharmony_ci{ 36062306a36Sopenharmony_ci int i; 36162306a36Sopenharmony_ci 36262306a36Sopenharmony_ci for (i = 0; priv->timings[i].mode > 0; i++) { 36362306a36Sopenharmony_ci if (priv->timings[i].mode == mode) 36462306a36Sopenharmony_ci return &priv->timings[i]; 36562306a36Sopenharmony_ci } 36662306a36Sopenharmony_ci return NULL; 36762306a36Sopenharmony_ci} 36862306a36Sopenharmony_ci 36962306a36Sopenharmony_ci 37062306a36Sopenharmony_cistatic void pata_macio_apply_timings(struct ata_port *ap, unsigned int device) 37162306a36Sopenharmony_ci{ 37262306a36Sopenharmony_ci struct pata_macio_priv *priv = ap->private_data; 37362306a36Sopenharmony_ci void __iomem *rbase = ap->ioaddr.cmd_addr; 37462306a36Sopenharmony_ci 37562306a36Sopenharmony_ci if (priv->kind == controller_sh_ata6 || 37662306a36Sopenharmony_ci priv->kind == controller_un_ata6 || 37762306a36Sopenharmony_ci priv->kind == controller_k2_ata6) { 37862306a36Sopenharmony_ci writel(priv->treg[device][0], rbase + IDE_KAUAI_PIO_CONFIG); 37962306a36Sopenharmony_ci writel(priv->treg[device][1], rbase + IDE_KAUAI_ULTRA_CONFIG); 38062306a36Sopenharmony_ci } else 38162306a36Sopenharmony_ci writel(priv->treg[device][0], rbase + IDE_TIMING_CONFIG); 38262306a36Sopenharmony_ci} 38362306a36Sopenharmony_ci 38462306a36Sopenharmony_cistatic void pata_macio_dev_select(struct ata_port *ap, unsigned int device) 38562306a36Sopenharmony_ci{ 38662306a36Sopenharmony_ci ata_sff_dev_select(ap, device); 38762306a36Sopenharmony_ci 38862306a36Sopenharmony_ci /* Apply timings */ 38962306a36Sopenharmony_ci pata_macio_apply_timings(ap, device); 39062306a36Sopenharmony_ci} 39162306a36Sopenharmony_ci 39262306a36Sopenharmony_cistatic void pata_macio_set_timings(struct ata_port *ap, 39362306a36Sopenharmony_ci struct ata_device *adev) 39462306a36Sopenharmony_ci{ 39562306a36Sopenharmony_ci struct pata_macio_priv *priv = ap->private_data; 39662306a36Sopenharmony_ci const struct pata_macio_timing *t; 39762306a36Sopenharmony_ci 39862306a36Sopenharmony_ci dev_dbg(priv->dev, "Set timings: DEV=%d,PIO=0x%x (%s),DMA=0x%x (%s)\n", 39962306a36Sopenharmony_ci adev->devno, 40062306a36Sopenharmony_ci adev->pio_mode, 40162306a36Sopenharmony_ci ata_mode_string(ata_xfer_mode2mask(adev->pio_mode)), 40262306a36Sopenharmony_ci adev->dma_mode, 40362306a36Sopenharmony_ci ata_mode_string(ata_xfer_mode2mask(adev->dma_mode))); 40462306a36Sopenharmony_ci 40562306a36Sopenharmony_ci /* First clear timings */ 40662306a36Sopenharmony_ci priv->treg[adev->devno][0] = priv->treg[adev->devno][1] = 0; 40762306a36Sopenharmony_ci 40862306a36Sopenharmony_ci /* Now get the PIO timings */ 40962306a36Sopenharmony_ci t = pata_macio_find_timing(priv, adev->pio_mode); 41062306a36Sopenharmony_ci if (t == NULL) { 41162306a36Sopenharmony_ci dev_warn(priv->dev, "Invalid PIO timing requested: 0x%x\n", 41262306a36Sopenharmony_ci adev->pio_mode); 41362306a36Sopenharmony_ci t = pata_macio_find_timing(priv, XFER_PIO_0); 41462306a36Sopenharmony_ci } 41562306a36Sopenharmony_ci BUG_ON(t == NULL); 41662306a36Sopenharmony_ci 41762306a36Sopenharmony_ci /* PIO timings only ever use the first treg */ 41862306a36Sopenharmony_ci priv->treg[adev->devno][0] |= t->reg1; 41962306a36Sopenharmony_ci 42062306a36Sopenharmony_ci /* Now get DMA timings */ 42162306a36Sopenharmony_ci t = pata_macio_find_timing(priv, adev->dma_mode); 42262306a36Sopenharmony_ci if (t == NULL || (t->reg1 == 0 && t->reg2 == 0)) { 42362306a36Sopenharmony_ci dev_dbg(priv->dev, "DMA timing not set yet, using MW_DMA_0\n"); 42462306a36Sopenharmony_ci t = pata_macio_find_timing(priv, XFER_MW_DMA_0); 42562306a36Sopenharmony_ci } 42662306a36Sopenharmony_ci BUG_ON(t == NULL); 42762306a36Sopenharmony_ci 42862306a36Sopenharmony_ci /* DMA timings can use both tregs */ 42962306a36Sopenharmony_ci priv->treg[adev->devno][0] |= t->reg1; 43062306a36Sopenharmony_ci priv->treg[adev->devno][1] |= t->reg2; 43162306a36Sopenharmony_ci 43262306a36Sopenharmony_ci dev_dbg(priv->dev, " -> %08x %08x\n", 43362306a36Sopenharmony_ci priv->treg[adev->devno][0], 43462306a36Sopenharmony_ci priv->treg[adev->devno][1]); 43562306a36Sopenharmony_ci 43662306a36Sopenharmony_ci /* Apply to hardware */ 43762306a36Sopenharmony_ci pata_macio_apply_timings(ap, adev->devno); 43862306a36Sopenharmony_ci} 43962306a36Sopenharmony_ci 44062306a36Sopenharmony_ci/* 44162306a36Sopenharmony_ci * Blast some well known "safe" values to the timing registers at init or 44262306a36Sopenharmony_ci * wakeup from sleep time, before we do real calculation 44362306a36Sopenharmony_ci */ 44462306a36Sopenharmony_cistatic void pata_macio_default_timings(struct pata_macio_priv *priv) 44562306a36Sopenharmony_ci{ 44662306a36Sopenharmony_ci unsigned int value, value2 = 0; 44762306a36Sopenharmony_ci 44862306a36Sopenharmony_ci switch(priv->kind) { 44962306a36Sopenharmony_ci case controller_sh_ata6: 45062306a36Sopenharmony_ci value = 0x0a820c97; 45162306a36Sopenharmony_ci value2 = 0x00033031; 45262306a36Sopenharmony_ci break; 45362306a36Sopenharmony_ci case controller_un_ata6: 45462306a36Sopenharmony_ci case controller_k2_ata6: 45562306a36Sopenharmony_ci value = 0x08618a92; 45662306a36Sopenharmony_ci value2 = 0x00002921; 45762306a36Sopenharmony_ci break; 45862306a36Sopenharmony_ci case controller_kl_ata4: 45962306a36Sopenharmony_ci value = 0x0008438c; 46062306a36Sopenharmony_ci break; 46162306a36Sopenharmony_ci case controller_kl_ata3: 46262306a36Sopenharmony_ci value = 0x00084526; 46362306a36Sopenharmony_ci break; 46462306a36Sopenharmony_ci case controller_heathrow: 46562306a36Sopenharmony_ci case controller_ohare: 46662306a36Sopenharmony_ci default: 46762306a36Sopenharmony_ci value = 0x00074526; 46862306a36Sopenharmony_ci break; 46962306a36Sopenharmony_ci } 47062306a36Sopenharmony_ci priv->treg[0][0] = priv->treg[1][0] = value; 47162306a36Sopenharmony_ci priv->treg[0][1] = priv->treg[1][1] = value2; 47262306a36Sopenharmony_ci} 47362306a36Sopenharmony_ci 47462306a36Sopenharmony_cistatic int pata_macio_cable_detect(struct ata_port *ap) 47562306a36Sopenharmony_ci{ 47662306a36Sopenharmony_ci struct pata_macio_priv *priv = ap->private_data; 47762306a36Sopenharmony_ci 47862306a36Sopenharmony_ci /* Get cable type from device-tree */ 47962306a36Sopenharmony_ci if (priv->kind == controller_kl_ata4 || 48062306a36Sopenharmony_ci priv->kind == controller_un_ata6 || 48162306a36Sopenharmony_ci priv->kind == controller_k2_ata6 || 48262306a36Sopenharmony_ci priv->kind == controller_sh_ata6) { 48362306a36Sopenharmony_ci const char* cable = of_get_property(priv->node, "cable-type", 48462306a36Sopenharmony_ci NULL); 48562306a36Sopenharmony_ci struct device_node *root = of_find_node_by_path("/"); 48662306a36Sopenharmony_ci const char *model = of_get_property(root, "model", NULL); 48762306a36Sopenharmony_ci 48862306a36Sopenharmony_ci of_node_put(root); 48962306a36Sopenharmony_ci 49062306a36Sopenharmony_ci if (cable && !strncmp(cable, "80-", 3)) { 49162306a36Sopenharmony_ci /* Some drives fail to detect 80c cable in PowerBook 49262306a36Sopenharmony_ci * These machine use proprietary short IDE cable 49362306a36Sopenharmony_ci * anyway 49462306a36Sopenharmony_ci */ 49562306a36Sopenharmony_ci if (!strncmp(model, "PowerBook", 9)) 49662306a36Sopenharmony_ci return ATA_CBL_PATA40_SHORT; 49762306a36Sopenharmony_ci else 49862306a36Sopenharmony_ci return ATA_CBL_PATA80; 49962306a36Sopenharmony_ci } 50062306a36Sopenharmony_ci } 50162306a36Sopenharmony_ci 50262306a36Sopenharmony_ci /* G5's seem to have incorrect cable type in device-tree. 50362306a36Sopenharmony_ci * Let's assume they always have a 80 conductor cable, this seem to 50462306a36Sopenharmony_ci * be always the case unless the user mucked around 50562306a36Sopenharmony_ci */ 50662306a36Sopenharmony_ci if (of_device_is_compatible(priv->node, "K2-UATA") || 50762306a36Sopenharmony_ci of_device_is_compatible(priv->node, "shasta-ata")) 50862306a36Sopenharmony_ci return ATA_CBL_PATA80; 50962306a36Sopenharmony_ci 51062306a36Sopenharmony_ci /* Anything else is 40 connectors */ 51162306a36Sopenharmony_ci return ATA_CBL_PATA40; 51262306a36Sopenharmony_ci} 51362306a36Sopenharmony_ci 51462306a36Sopenharmony_cistatic enum ata_completion_errors pata_macio_qc_prep(struct ata_queued_cmd *qc) 51562306a36Sopenharmony_ci{ 51662306a36Sopenharmony_ci unsigned int write = (qc->tf.flags & ATA_TFLAG_WRITE); 51762306a36Sopenharmony_ci struct ata_port *ap = qc->ap; 51862306a36Sopenharmony_ci struct pata_macio_priv *priv = ap->private_data; 51962306a36Sopenharmony_ci struct scatterlist *sg; 52062306a36Sopenharmony_ci struct dbdma_cmd *table; 52162306a36Sopenharmony_ci unsigned int si, pi; 52262306a36Sopenharmony_ci 52362306a36Sopenharmony_ci dev_dbgdma(priv->dev, "%s: qc %p flags %lx, write %d dev %d\n", 52462306a36Sopenharmony_ci __func__, qc, qc->flags, write, qc->dev->devno); 52562306a36Sopenharmony_ci 52662306a36Sopenharmony_ci if (!(qc->flags & ATA_QCFLAG_DMAMAP)) 52762306a36Sopenharmony_ci return AC_ERR_OK; 52862306a36Sopenharmony_ci 52962306a36Sopenharmony_ci table = (struct dbdma_cmd *) priv->dma_table_cpu; 53062306a36Sopenharmony_ci 53162306a36Sopenharmony_ci pi = 0; 53262306a36Sopenharmony_ci for_each_sg(qc->sg, sg, qc->n_elem, si) { 53362306a36Sopenharmony_ci u32 addr, sg_len, len; 53462306a36Sopenharmony_ci 53562306a36Sopenharmony_ci /* determine if physical DMA addr spans 64K boundary. 53662306a36Sopenharmony_ci * Note h/w doesn't support 64-bit, so we unconditionally 53762306a36Sopenharmony_ci * truncate dma_addr_t to u32. 53862306a36Sopenharmony_ci */ 53962306a36Sopenharmony_ci addr = (u32) sg_dma_address(sg); 54062306a36Sopenharmony_ci sg_len = sg_dma_len(sg); 54162306a36Sopenharmony_ci 54262306a36Sopenharmony_ci while (sg_len) { 54362306a36Sopenharmony_ci /* table overflow should never happen */ 54462306a36Sopenharmony_ci BUG_ON (pi++ >= MAX_DCMDS); 54562306a36Sopenharmony_ci 54662306a36Sopenharmony_ci len = (sg_len < MAX_DBDMA_SEG) ? sg_len : MAX_DBDMA_SEG; 54762306a36Sopenharmony_ci table->command = cpu_to_le16(write ? OUTPUT_MORE: INPUT_MORE); 54862306a36Sopenharmony_ci table->req_count = cpu_to_le16(len); 54962306a36Sopenharmony_ci table->phy_addr = cpu_to_le32(addr); 55062306a36Sopenharmony_ci table->cmd_dep = 0; 55162306a36Sopenharmony_ci table->xfer_status = 0; 55262306a36Sopenharmony_ci table->res_count = 0; 55362306a36Sopenharmony_ci addr += len; 55462306a36Sopenharmony_ci sg_len -= len; 55562306a36Sopenharmony_ci ++table; 55662306a36Sopenharmony_ci } 55762306a36Sopenharmony_ci } 55862306a36Sopenharmony_ci 55962306a36Sopenharmony_ci /* Should never happen according to Tejun */ 56062306a36Sopenharmony_ci BUG_ON(!pi); 56162306a36Sopenharmony_ci 56262306a36Sopenharmony_ci /* Convert the last command to an input/output */ 56362306a36Sopenharmony_ci table--; 56462306a36Sopenharmony_ci table->command = cpu_to_le16(write ? OUTPUT_LAST: INPUT_LAST); 56562306a36Sopenharmony_ci table++; 56662306a36Sopenharmony_ci 56762306a36Sopenharmony_ci /* Add the stop command to the end of the list */ 56862306a36Sopenharmony_ci memset(table, 0, sizeof(struct dbdma_cmd)); 56962306a36Sopenharmony_ci table->command = cpu_to_le16(DBDMA_STOP); 57062306a36Sopenharmony_ci 57162306a36Sopenharmony_ci dev_dbgdma(priv->dev, "%s: %d DMA list entries\n", __func__, pi); 57262306a36Sopenharmony_ci 57362306a36Sopenharmony_ci return AC_ERR_OK; 57462306a36Sopenharmony_ci} 57562306a36Sopenharmony_ci 57662306a36Sopenharmony_ci 57762306a36Sopenharmony_cistatic void pata_macio_freeze(struct ata_port *ap) 57862306a36Sopenharmony_ci{ 57962306a36Sopenharmony_ci struct dbdma_regs __iomem *dma_regs = ap->ioaddr.bmdma_addr; 58062306a36Sopenharmony_ci 58162306a36Sopenharmony_ci if (dma_regs) { 58262306a36Sopenharmony_ci unsigned int timeout = 1000000; 58362306a36Sopenharmony_ci 58462306a36Sopenharmony_ci /* Make sure DMA controller is stopped */ 58562306a36Sopenharmony_ci writel((RUN|PAUSE|FLUSH|WAKE|DEAD) << 16, &dma_regs->control); 58662306a36Sopenharmony_ci while (--timeout && (readl(&dma_regs->status) & RUN)) 58762306a36Sopenharmony_ci udelay(1); 58862306a36Sopenharmony_ci } 58962306a36Sopenharmony_ci 59062306a36Sopenharmony_ci ata_sff_freeze(ap); 59162306a36Sopenharmony_ci} 59262306a36Sopenharmony_ci 59362306a36Sopenharmony_ci 59462306a36Sopenharmony_cistatic void pata_macio_bmdma_setup(struct ata_queued_cmd *qc) 59562306a36Sopenharmony_ci{ 59662306a36Sopenharmony_ci struct ata_port *ap = qc->ap; 59762306a36Sopenharmony_ci struct pata_macio_priv *priv = ap->private_data; 59862306a36Sopenharmony_ci struct dbdma_regs __iomem *dma_regs = ap->ioaddr.bmdma_addr; 59962306a36Sopenharmony_ci int dev = qc->dev->devno; 60062306a36Sopenharmony_ci 60162306a36Sopenharmony_ci dev_dbgdma(priv->dev, "%s: qc %p\n", __func__, qc); 60262306a36Sopenharmony_ci 60362306a36Sopenharmony_ci /* Make sure DMA commands updates are visible */ 60462306a36Sopenharmony_ci writel(priv->dma_table_dma, &dma_regs->cmdptr); 60562306a36Sopenharmony_ci 60662306a36Sopenharmony_ci /* On KeyLargo 66Mhz cell, we need to add 60ns to wrDataSetup on 60762306a36Sopenharmony_ci * UDMA reads 60862306a36Sopenharmony_ci */ 60962306a36Sopenharmony_ci if (priv->kind == controller_kl_ata4 && 61062306a36Sopenharmony_ci (priv->treg[dev][0] & TR_66_UDMA_EN)) { 61162306a36Sopenharmony_ci void __iomem *rbase = ap->ioaddr.cmd_addr; 61262306a36Sopenharmony_ci u32 reg = priv->treg[dev][0]; 61362306a36Sopenharmony_ci 61462306a36Sopenharmony_ci if (!(qc->tf.flags & ATA_TFLAG_WRITE)) 61562306a36Sopenharmony_ci reg += 0x00800000; 61662306a36Sopenharmony_ci writel(reg, rbase + IDE_TIMING_CONFIG); 61762306a36Sopenharmony_ci } 61862306a36Sopenharmony_ci 61962306a36Sopenharmony_ci /* issue r/w command */ 62062306a36Sopenharmony_ci ap->ops->sff_exec_command(ap, &qc->tf); 62162306a36Sopenharmony_ci} 62262306a36Sopenharmony_ci 62362306a36Sopenharmony_cistatic void pata_macio_bmdma_start(struct ata_queued_cmd *qc) 62462306a36Sopenharmony_ci{ 62562306a36Sopenharmony_ci struct ata_port *ap = qc->ap; 62662306a36Sopenharmony_ci struct pata_macio_priv *priv = ap->private_data; 62762306a36Sopenharmony_ci struct dbdma_regs __iomem *dma_regs = ap->ioaddr.bmdma_addr; 62862306a36Sopenharmony_ci 62962306a36Sopenharmony_ci dev_dbgdma(priv->dev, "%s: qc %p\n", __func__, qc); 63062306a36Sopenharmony_ci 63162306a36Sopenharmony_ci writel((RUN << 16) | RUN, &dma_regs->control); 63262306a36Sopenharmony_ci /* Make sure it gets to the controller right now */ 63362306a36Sopenharmony_ci (void)readl(&dma_regs->control); 63462306a36Sopenharmony_ci} 63562306a36Sopenharmony_ci 63662306a36Sopenharmony_cistatic void pata_macio_bmdma_stop(struct ata_queued_cmd *qc) 63762306a36Sopenharmony_ci{ 63862306a36Sopenharmony_ci struct ata_port *ap = qc->ap; 63962306a36Sopenharmony_ci struct pata_macio_priv *priv = ap->private_data; 64062306a36Sopenharmony_ci struct dbdma_regs __iomem *dma_regs = ap->ioaddr.bmdma_addr; 64162306a36Sopenharmony_ci unsigned int timeout = 1000000; 64262306a36Sopenharmony_ci 64362306a36Sopenharmony_ci dev_dbgdma(priv->dev, "%s: qc %p\n", __func__, qc); 64462306a36Sopenharmony_ci 64562306a36Sopenharmony_ci /* Stop the DMA engine and wait for it to full halt */ 64662306a36Sopenharmony_ci writel (((RUN|WAKE|DEAD) << 16), &dma_regs->control); 64762306a36Sopenharmony_ci while (--timeout && (readl(&dma_regs->status) & RUN)) 64862306a36Sopenharmony_ci udelay(1); 64962306a36Sopenharmony_ci} 65062306a36Sopenharmony_ci 65162306a36Sopenharmony_cistatic u8 pata_macio_bmdma_status(struct ata_port *ap) 65262306a36Sopenharmony_ci{ 65362306a36Sopenharmony_ci struct pata_macio_priv *priv = ap->private_data; 65462306a36Sopenharmony_ci struct dbdma_regs __iomem *dma_regs = ap->ioaddr.bmdma_addr; 65562306a36Sopenharmony_ci u32 dstat, rstat = ATA_DMA_INTR; 65662306a36Sopenharmony_ci unsigned long timeout = 0; 65762306a36Sopenharmony_ci 65862306a36Sopenharmony_ci dstat = readl(&dma_regs->status); 65962306a36Sopenharmony_ci 66062306a36Sopenharmony_ci dev_dbgdma(priv->dev, "%s: dstat=%x\n", __func__, dstat); 66162306a36Sopenharmony_ci 66262306a36Sopenharmony_ci /* We have two things to deal with here: 66362306a36Sopenharmony_ci * 66462306a36Sopenharmony_ci * - The dbdma won't stop if the command was started 66562306a36Sopenharmony_ci * but completed with an error without transferring all 66662306a36Sopenharmony_ci * datas. This happens when bad blocks are met during 66762306a36Sopenharmony_ci * a multi-block transfer. 66862306a36Sopenharmony_ci * 66962306a36Sopenharmony_ci * - The dbdma fifo hasn't yet finished flushing to 67062306a36Sopenharmony_ci * system memory when the disk interrupt occurs. 67162306a36Sopenharmony_ci */ 67262306a36Sopenharmony_ci 67362306a36Sopenharmony_ci /* First check for errors */ 67462306a36Sopenharmony_ci if ((dstat & (RUN|DEAD)) != RUN) 67562306a36Sopenharmony_ci rstat |= ATA_DMA_ERR; 67662306a36Sopenharmony_ci 67762306a36Sopenharmony_ci /* If ACTIVE is cleared, the STOP command has been hit and 67862306a36Sopenharmony_ci * the transfer is complete. If not, we have to flush the 67962306a36Sopenharmony_ci * channel. 68062306a36Sopenharmony_ci */ 68162306a36Sopenharmony_ci if ((dstat & ACTIVE) == 0) 68262306a36Sopenharmony_ci return rstat; 68362306a36Sopenharmony_ci 68462306a36Sopenharmony_ci dev_dbgdma(priv->dev, "%s: DMA still active, flushing...\n", __func__); 68562306a36Sopenharmony_ci 68662306a36Sopenharmony_ci /* If dbdma didn't execute the STOP command yet, the 68762306a36Sopenharmony_ci * active bit is still set. We consider that we aren't 68862306a36Sopenharmony_ci * sharing interrupts (which is hopefully the case with 68962306a36Sopenharmony_ci * those controllers) and so we just try to flush the 69062306a36Sopenharmony_ci * channel for pending data in the fifo 69162306a36Sopenharmony_ci */ 69262306a36Sopenharmony_ci udelay(1); 69362306a36Sopenharmony_ci writel((FLUSH << 16) | FLUSH, &dma_regs->control); 69462306a36Sopenharmony_ci for (;;) { 69562306a36Sopenharmony_ci udelay(1); 69662306a36Sopenharmony_ci dstat = readl(&dma_regs->status); 69762306a36Sopenharmony_ci if ((dstat & FLUSH) == 0) 69862306a36Sopenharmony_ci break; 69962306a36Sopenharmony_ci if (++timeout > 1000) { 70062306a36Sopenharmony_ci dev_warn(priv->dev, "timeout flushing DMA\n"); 70162306a36Sopenharmony_ci rstat |= ATA_DMA_ERR; 70262306a36Sopenharmony_ci break; 70362306a36Sopenharmony_ci } 70462306a36Sopenharmony_ci } 70562306a36Sopenharmony_ci return rstat; 70662306a36Sopenharmony_ci} 70762306a36Sopenharmony_ci 70862306a36Sopenharmony_ci/* port_start is when we allocate the DMA command list */ 70962306a36Sopenharmony_cistatic int pata_macio_port_start(struct ata_port *ap) 71062306a36Sopenharmony_ci{ 71162306a36Sopenharmony_ci struct pata_macio_priv *priv = ap->private_data; 71262306a36Sopenharmony_ci 71362306a36Sopenharmony_ci if (ap->ioaddr.bmdma_addr == NULL) 71462306a36Sopenharmony_ci return 0; 71562306a36Sopenharmony_ci 71662306a36Sopenharmony_ci /* Allocate space for the DBDMA commands. 71762306a36Sopenharmony_ci * 71862306a36Sopenharmony_ci * The +2 is +1 for the stop command and +1 to allow for 71962306a36Sopenharmony_ci * aligning the start address to a multiple of 16 bytes. 72062306a36Sopenharmony_ci */ 72162306a36Sopenharmony_ci priv->dma_table_cpu = 72262306a36Sopenharmony_ci dmam_alloc_coherent(priv->dev, 72362306a36Sopenharmony_ci (MAX_DCMDS + 2) * sizeof(struct dbdma_cmd), 72462306a36Sopenharmony_ci &priv->dma_table_dma, GFP_KERNEL); 72562306a36Sopenharmony_ci if (priv->dma_table_cpu == NULL) { 72662306a36Sopenharmony_ci dev_err(priv->dev, "Unable to allocate DMA command list\n"); 72762306a36Sopenharmony_ci ap->ioaddr.bmdma_addr = NULL; 72862306a36Sopenharmony_ci ap->mwdma_mask = 0; 72962306a36Sopenharmony_ci ap->udma_mask = 0; 73062306a36Sopenharmony_ci } 73162306a36Sopenharmony_ci return 0; 73262306a36Sopenharmony_ci} 73362306a36Sopenharmony_ci 73462306a36Sopenharmony_cistatic void pata_macio_irq_clear(struct ata_port *ap) 73562306a36Sopenharmony_ci{ 73662306a36Sopenharmony_ci struct pata_macio_priv *priv = ap->private_data; 73762306a36Sopenharmony_ci 73862306a36Sopenharmony_ci /* Nothing to do here */ 73962306a36Sopenharmony_ci 74062306a36Sopenharmony_ci dev_dbgdma(priv->dev, "%s\n", __func__); 74162306a36Sopenharmony_ci} 74262306a36Sopenharmony_ci 74362306a36Sopenharmony_cistatic void pata_macio_reset_hw(struct pata_macio_priv *priv, int resume) 74462306a36Sopenharmony_ci{ 74562306a36Sopenharmony_ci dev_dbg(priv->dev, "Enabling & resetting... \n"); 74662306a36Sopenharmony_ci 74762306a36Sopenharmony_ci if (priv->mediabay) 74862306a36Sopenharmony_ci return; 74962306a36Sopenharmony_ci 75062306a36Sopenharmony_ci if (priv->kind == controller_ohare && !resume) { 75162306a36Sopenharmony_ci /* The code below is having trouble on some ohare machines 75262306a36Sopenharmony_ci * (timing related ?). Until I can put my hand on one of these 75362306a36Sopenharmony_ci * units, I keep the old way 75462306a36Sopenharmony_ci */ 75562306a36Sopenharmony_ci ppc_md.feature_call(PMAC_FTR_IDE_ENABLE, priv->node, 0, 1); 75662306a36Sopenharmony_ci } else { 75762306a36Sopenharmony_ci int rc; 75862306a36Sopenharmony_ci 75962306a36Sopenharmony_ci /* Reset and enable controller */ 76062306a36Sopenharmony_ci rc = ppc_md.feature_call(PMAC_FTR_IDE_RESET, 76162306a36Sopenharmony_ci priv->node, priv->aapl_bus_id, 1); 76262306a36Sopenharmony_ci ppc_md.feature_call(PMAC_FTR_IDE_ENABLE, 76362306a36Sopenharmony_ci priv->node, priv->aapl_bus_id, 1); 76462306a36Sopenharmony_ci msleep(10); 76562306a36Sopenharmony_ci /* Only bother waiting if there's a reset control */ 76662306a36Sopenharmony_ci if (rc == 0) { 76762306a36Sopenharmony_ci ppc_md.feature_call(PMAC_FTR_IDE_RESET, 76862306a36Sopenharmony_ci priv->node, priv->aapl_bus_id, 0); 76962306a36Sopenharmony_ci msleep(IDE_WAKEUP_DELAY_MS); 77062306a36Sopenharmony_ci } 77162306a36Sopenharmony_ci } 77262306a36Sopenharmony_ci 77362306a36Sopenharmony_ci /* If resuming a PCI device, restore the config space here */ 77462306a36Sopenharmony_ci if (priv->pdev && resume) { 77562306a36Sopenharmony_ci int rc; 77662306a36Sopenharmony_ci 77762306a36Sopenharmony_ci pci_restore_state(priv->pdev); 77862306a36Sopenharmony_ci rc = pcim_enable_device(priv->pdev); 77962306a36Sopenharmony_ci if (rc) 78062306a36Sopenharmony_ci dev_err(&priv->pdev->dev, 78162306a36Sopenharmony_ci "Failed to enable device after resume (%d)\n", 78262306a36Sopenharmony_ci rc); 78362306a36Sopenharmony_ci else 78462306a36Sopenharmony_ci pci_set_master(priv->pdev); 78562306a36Sopenharmony_ci } 78662306a36Sopenharmony_ci 78762306a36Sopenharmony_ci /* On Kauai, initialize the FCR. We don't perform a reset, doesn't really 78862306a36Sopenharmony_ci * seem necessary and speeds up the boot process 78962306a36Sopenharmony_ci */ 79062306a36Sopenharmony_ci if (priv->kauai_fcr) 79162306a36Sopenharmony_ci writel(KAUAI_FCR_UATA_MAGIC | 79262306a36Sopenharmony_ci KAUAI_FCR_UATA_RESET_N | 79362306a36Sopenharmony_ci KAUAI_FCR_UATA_ENABLE, priv->kauai_fcr); 79462306a36Sopenharmony_ci} 79562306a36Sopenharmony_ci 79662306a36Sopenharmony_ci/* Hook the standard slave config to fixup some HW related alignment 79762306a36Sopenharmony_ci * restrictions 79862306a36Sopenharmony_ci */ 79962306a36Sopenharmony_cistatic int pata_macio_slave_config(struct scsi_device *sdev) 80062306a36Sopenharmony_ci{ 80162306a36Sopenharmony_ci struct ata_port *ap = ata_shost_to_port(sdev->host); 80262306a36Sopenharmony_ci struct pata_macio_priv *priv = ap->private_data; 80362306a36Sopenharmony_ci struct ata_device *dev; 80462306a36Sopenharmony_ci u16 cmd; 80562306a36Sopenharmony_ci int rc; 80662306a36Sopenharmony_ci 80762306a36Sopenharmony_ci /* First call original */ 80862306a36Sopenharmony_ci rc = ata_scsi_slave_config(sdev); 80962306a36Sopenharmony_ci if (rc) 81062306a36Sopenharmony_ci return rc; 81162306a36Sopenharmony_ci 81262306a36Sopenharmony_ci /* This is lifted from sata_nv */ 81362306a36Sopenharmony_ci dev = &ap->link.device[sdev->id]; 81462306a36Sopenharmony_ci 81562306a36Sopenharmony_ci /* OHare has issues with non cache aligned DMA on some chipsets */ 81662306a36Sopenharmony_ci if (priv->kind == controller_ohare) { 81762306a36Sopenharmony_ci blk_queue_update_dma_alignment(sdev->request_queue, 31); 81862306a36Sopenharmony_ci blk_queue_update_dma_pad(sdev->request_queue, 31); 81962306a36Sopenharmony_ci 82062306a36Sopenharmony_ci /* Tell the world about it */ 82162306a36Sopenharmony_ci ata_dev_info(dev, "OHare alignment limits applied\n"); 82262306a36Sopenharmony_ci return 0; 82362306a36Sopenharmony_ci } 82462306a36Sopenharmony_ci 82562306a36Sopenharmony_ci /* We only have issues with ATAPI */ 82662306a36Sopenharmony_ci if (dev->class != ATA_DEV_ATAPI) 82762306a36Sopenharmony_ci return 0; 82862306a36Sopenharmony_ci 82962306a36Sopenharmony_ci /* Shasta and K2 seem to have "issues" with reads ... */ 83062306a36Sopenharmony_ci if (priv->kind == controller_sh_ata6 || priv->kind == controller_k2_ata6) { 83162306a36Sopenharmony_ci /* Allright these are bad, apply restrictions */ 83262306a36Sopenharmony_ci blk_queue_update_dma_alignment(sdev->request_queue, 15); 83362306a36Sopenharmony_ci blk_queue_update_dma_pad(sdev->request_queue, 15); 83462306a36Sopenharmony_ci 83562306a36Sopenharmony_ci /* We enable MWI and hack cache line size directly here, this 83662306a36Sopenharmony_ci * is specific to this chipset and not normal values, we happen 83762306a36Sopenharmony_ci * to somewhat know what we are doing here (which is basically 83862306a36Sopenharmony_ci * to do the same Apple does and pray they did not get it wrong :-) 83962306a36Sopenharmony_ci */ 84062306a36Sopenharmony_ci BUG_ON(!priv->pdev); 84162306a36Sopenharmony_ci pci_write_config_byte(priv->pdev, PCI_CACHE_LINE_SIZE, 0x08); 84262306a36Sopenharmony_ci pci_read_config_word(priv->pdev, PCI_COMMAND, &cmd); 84362306a36Sopenharmony_ci pci_write_config_word(priv->pdev, PCI_COMMAND, 84462306a36Sopenharmony_ci cmd | PCI_COMMAND_INVALIDATE); 84562306a36Sopenharmony_ci 84662306a36Sopenharmony_ci /* Tell the world about it */ 84762306a36Sopenharmony_ci ata_dev_info(dev, "K2/Shasta alignment limits applied\n"); 84862306a36Sopenharmony_ci } 84962306a36Sopenharmony_ci 85062306a36Sopenharmony_ci return 0; 85162306a36Sopenharmony_ci} 85262306a36Sopenharmony_ci 85362306a36Sopenharmony_ci#ifdef CONFIG_PM_SLEEP 85462306a36Sopenharmony_cistatic int pata_macio_do_suspend(struct pata_macio_priv *priv, pm_message_t mesg) 85562306a36Sopenharmony_ci{ 85662306a36Sopenharmony_ci /* First, core libata suspend to do most of the work */ 85762306a36Sopenharmony_ci ata_host_suspend(priv->host, mesg); 85862306a36Sopenharmony_ci 85962306a36Sopenharmony_ci /* Restore to default timings */ 86062306a36Sopenharmony_ci pata_macio_default_timings(priv); 86162306a36Sopenharmony_ci 86262306a36Sopenharmony_ci /* Mask interrupt. Not strictly necessary but old driver did 86362306a36Sopenharmony_ci * it and I'd rather not change that here */ 86462306a36Sopenharmony_ci disable_irq(priv->irq); 86562306a36Sopenharmony_ci 86662306a36Sopenharmony_ci /* The media bay will handle itself just fine */ 86762306a36Sopenharmony_ci if (priv->mediabay) 86862306a36Sopenharmony_ci return 0; 86962306a36Sopenharmony_ci 87062306a36Sopenharmony_ci /* Kauai has bus control FCRs directly here */ 87162306a36Sopenharmony_ci if (priv->kauai_fcr) { 87262306a36Sopenharmony_ci u32 fcr = readl(priv->kauai_fcr); 87362306a36Sopenharmony_ci fcr &= ~(KAUAI_FCR_UATA_RESET_N | KAUAI_FCR_UATA_ENABLE); 87462306a36Sopenharmony_ci writel(fcr, priv->kauai_fcr); 87562306a36Sopenharmony_ci } 87662306a36Sopenharmony_ci 87762306a36Sopenharmony_ci /* For PCI, save state and disable DMA. No need to call 87862306a36Sopenharmony_ci * pci_set_power_state(), the HW doesn't do D states that 87962306a36Sopenharmony_ci * way, the platform code will take care of suspending the 88062306a36Sopenharmony_ci * ASIC properly 88162306a36Sopenharmony_ci */ 88262306a36Sopenharmony_ci if (priv->pdev) { 88362306a36Sopenharmony_ci pci_save_state(priv->pdev); 88462306a36Sopenharmony_ci pci_disable_device(priv->pdev); 88562306a36Sopenharmony_ci } 88662306a36Sopenharmony_ci 88762306a36Sopenharmony_ci /* Disable the bus on older machines and the cell on kauai */ 88862306a36Sopenharmony_ci ppc_md.feature_call(PMAC_FTR_IDE_ENABLE, priv->node, 88962306a36Sopenharmony_ci priv->aapl_bus_id, 0); 89062306a36Sopenharmony_ci 89162306a36Sopenharmony_ci return 0; 89262306a36Sopenharmony_ci} 89362306a36Sopenharmony_ci 89462306a36Sopenharmony_cistatic int pata_macio_do_resume(struct pata_macio_priv *priv) 89562306a36Sopenharmony_ci{ 89662306a36Sopenharmony_ci /* Reset and re-enable the HW */ 89762306a36Sopenharmony_ci pata_macio_reset_hw(priv, 1); 89862306a36Sopenharmony_ci 89962306a36Sopenharmony_ci /* Sanitize drive timings */ 90062306a36Sopenharmony_ci pata_macio_apply_timings(priv->host->ports[0], 0); 90162306a36Sopenharmony_ci 90262306a36Sopenharmony_ci /* We want our IRQ back ! */ 90362306a36Sopenharmony_ci enable_irq(priv->irq); 90462306a36Sopenharmony_ci 90562306a36Sopenharmony_ci /* Let the libata core take it from there */ 90662306a36Sopenharmony_ci ata_host_resume(priv->host); 90762306a36Sopenharmony_ci 90862306a36Sopenharmony_ci return 0; 90962306a36Sopenharmony_ci} 91062306a36Sopenharmony_ci#endif /* CONFIG_PM_SLEEP */ 91162306a36Sopenharmony_ci 91262306a36Sopenharmony_cistatic const struct scsi_host_template pata_macio_sht = { 91362306a36Sopenharmony_ci __ATA_BASE_SHT(DRV_NAME), 91462306a36Sopenharmony_ci .sg_tablesize = MAX_DCMDS, 91562306a36Sopenharmony_ci /* We may not need that strict one */ 91662306a36Sopenharmony_ci .dma_boundary = ATA_DMA_BOUNDARY, 91762306a36Sopenharmony_ci /* Not sure what the real max is but we know it's less than 64K, let's 91862306a36Sopenharmony_ci * use 64K minus 256 91962306a36Sopenharmony_ci */ 92062306a36Sopenharmony_ci .max_segment_size = MAX_DBDMA_SEG, 92162306a36Sopenharmony_ci .slave_configure = pata_macio_slave_config, 92262306a36Sopenharmony_ci .sdev_groups = ata_common_sdev_groups, 92362306a36Sopenharmony_ci .can_queue = ATA_DEF_QUEUE, 92462306a36Sopenharmony_ci .tag_alloc_policy = BLK_TAG_ALLOC_RR, 92562306a36Sopenharmony_ci}; 92662306a36Sopenharmony_ci 92762306a36Sopenharmony_cistatic struct ata_port_operations pata_macio_ops = { 92862306a36Sopenharmony_ci .inherits = &ata_bmdma_port_ops, 92962306a36Sopenharmony_ci 93062306a36Sopenharmony_ci .freeze = pata_macio_freeze, 93162306a36Sopenharmony_ci .set_piomode = pata_macio_set_timings, 93262306a36Sopenharmony_ci .set_dmamode = pata_macio_set_timings, 93362306a36Sopenharmony_ci .cable_detect = pata_macio_cable_detect, 93462306a36Sopenharmony_ci .sff_dev_select = pata_macio_dev_select, 93562306a36Sopenharmony_ci .qc_prep = pata_macio_qc_prep, 93662306a36Sopenharmony_ci .bmdma_setup = pata_macio_bmdma_setup, 93762306a36Sopenharmony_ci .bmdma_start = pata_macio_bmdma_start, 93862306a36Sopenharmony_ci .bmdma_stop = pata_macio_bmdma_stop, 93962306a36Sopenharmony_ci .bmdma_status = pata_macio_bmdma_status, 94062306a36Sopenharmony_ci .port_start = pata_macio_port_start, 94162306a36Sopenharmony_ci .sff_irq_clear = pata_macio_irq_clear, 94262306a36Sopenharmony_ci}; 94362306a36Sopenharmony_ci 94462306a36Sopenharmony_cistatic void pata_macio_invariants(struct pata_macio_priv *priv) 94562306a36Sopenharmony_ci{ 94662306a36Sopenharmony_ci const int *bidp; 94762306a36Sopenharmony_ci 94862306a36Sopenharmony_ci /* Identify the type of controller */ 94962306a36Sopenharmony_ci if (of_device_is_compatible(priv->node, "shasta-ata")) { 95062306a36Sopenharmony_ci priv->kind = controller_sh_ata6; 95162306a36Sopenharmony_ci priv->timings = pata_macio_shasta_timings; 95262306a36Sopenharmony_ci } else if (of_device_is_compatible(priv->node, "kauai-ata")) { 95362306a36Sopenharmony_ci priv->kind = controller_un_ata6; 95462306a36Sopenharmony_ci priv->timings = pata_macio_kauai_timings; 95562306a36Sopenharmony_ci } else if (of_device_is_compatible(priv->node, "K2-UATA")) { 95662306a36Sopenharmony_ci priv->kind = controller_k2_ata6; 95762306a36Sopenharmony_ci priv->timings = pata_macio_kauai_timings; 95862306a36Sopenharmony_ci } else if (of_device_is_compatible(priv->node, "keylargo-ata")) { 95962306a36Sopenharmony_ci if (of_node_name_eq(priv->node, "ata-4")) { 96062306a36Sopenharmony_ci priv->kind = controller_kl_ata4; 96162306a36Sopenharmony_ci priv->timings = pata_macio_kl66_timings; 96262306a36Sopenharmony_ci } else { 96362306a36Sopenharmony_ci priv->kind = controller_kl_ata3; 96462306a36Sopenharmony_ci priv->timings = pata_macio_kl33_timings; 96562306a36Sopenharmony_ci } 96662306a36Sopenharmony_ci } else if (of_device_is_compatible(priv->node, "heathrow-ata")) { 96762306a36Sopenharmony_ci priv->kind = controller_heathrow; 96862306a36Sopenharmony_ci priv->timings = pata_macio_heathrow_timings; 96962306a36Sopenharmony_ci } else { 97062306a36Sopenharmony_ci priv->kind = controller_ohare; 97162306a36Sopenharmony_ci priv->timings = pata_macio_ohare_timings; 97262306a36Sopenharmony_ci } 97362306a36Sopenharmony_ci 97462306a36Sopenharmony_ci /* XXX FIXME --- setup priv->mediabay here */ 97562306a36Sopenharmony_ci 97662306a36Sopenharmony_ci /* Get Apple bus ID (for clock and ASIC control) */ 97762306a36Sopenharmony_ci bidp = of_get_property(priv->node, "AAPL,bus-id", NULL); 97862306a36Sopenharmony_ci priv->aapl_bus_id = bidp ? *bidp : 0; 97962306a36Sopenharmony_ci 98062306a36Sopenharmony_ci /* Fixup missing Apple bus ID in case of media-bay */ 98162306a36Sopenharmony_ci if (priv->mediabay && !bidp) 98262306a36Sopenharmony_ci priv->aapl_bus_id = 1; 98362306a36Sopenharmony_ci} 98462306a36Sopenharmony_ci 98562306a36Sopenharmony_cistatic void pata_macio_setup_ios(struct ata_ioports *ioaddr, 98662306a36Sopenharmony_ci void __iomem * base, void __iomem * dma) 98762306a36Sopenharmony_ci{ 98862306a36Sopenharmony_ci /* cmd_addr is the base of regs for that port */ 98962306a36Sopenharmony_ci ioaddr->cmd_addr = base; 99062306a36Sopenharmony_ci 99162306a36Sopenharmony_ci /* taskfile registers */ 99262306a36Sopenharmony_ci ioaddr->data_addr = base + (ATA_REG_DATA << 4); 99362306a36Sopenharmony_ci ioaddr->error_addr = base + (ATA_REG_ERR << 4); 99462306a36Sopenharmony_ci ioaddr->feature_addr = base + (ATA_REG_FEATURE << 4); 99562306a36Sopenharmony_ci ioaddr->nsect_addr = base + (ATA_REG_NSECT << 4); 99662306a36Sopenharmony_ci ioaddr->lbal_addr = base + (ATA_REG_LBAL << 4); 99762306a36Sopenharmony_ci ioaddr->lbam_addr = base + (ATA_REG_LBAM << 4); 99862306a36Sopenharmony_ci ioaddr->lbah_addr = base + (ATA_REG_LBAH << 4); 99962306a36Sopenharmony_ci ioaddr->device_addr = base + (ATA_REG_DEVICE << 4); 100062306a36Sopenharmony_ci ioaddr->status_addr = base + (ATA_REG_STATUS << 4); 100162306a36Sopenharmony_ci ioaddr->command_addr = base + (ATA_REG_CMD << 4); 100262306a36Sopenharmony_ci ioaddr->altstatus_addr = base + 0x160; 100362306a36Sopenharmony_ci ioaddr->ctl_addr = base + 0x160; 100462306a36Sopenharmony_ci ioaddr->bmdma_addr = dma; 100562306a36Sopenharmony_ci} 100662306a36Sopenharmony_ci 100762306a36Sopenharmony_cistatic void pmac_macio_calc_timing_masks(struct pata_macio_priv *priv, 100862306a36Sopenharmony_ci struct ata_port_info *pinfo) 100962306a36Sopenharmony_ci{ 101062306a36Sopenharmony_ci int i = 0; 101162306a36Sopenharmony_ci 101262306a36Sopenharmony_ci pinfo->pio_mask = 0; 101362306a36Sopenharmony_ci pinfo->mwdma_mask = 0; 101462306a36Sopenharmony_ci pinfo->udma_mask = 0; 101562306a36Sopenharmony_ci 101662306a36Sopenharmony_ci while (priv->timings[i].mode > 0) { 101762306a36Sopenharmony_ci unsigned int mask = 1U << (priv->timings[i].mode & 0x0f); 101862306a36Sopenharmony_ci switch(priv->timings[i].mode & 0xf0) { 101962306a36Sopenharmony_ci case 0x00: /* PIO */ 102062306a36Sopenharmony_ci pinfo->pio_mask |= (mask >> 8); 102162306a36Sopenharmony_ci break; 102262306a36Sopenharmony_ci case 0x20: /* MWDMA */ 102362306a36Sopenharmony_ci pinfo->mwdma_mask |= mask; 102462306a36Sopenharmony_ci break; 102562306a36Sopenharmony_ci case 0x40: /* UDMA */ 102662306a36Sopenharmony_ci pinfo->udma_mask |= mask; 102762306a36Sopenharmony_ci break; 102862306a36Sopenharmony_ci } 102962306a36Sopenharmony_ci i++; 103062306a36Sopenharmony_ci } 103162306a36Sopenharmony_ci dev_dbg(priv->dev, "Supported masks: PIO=%x, MWDMA=%x, UDMA=%x\n", 103262306a36Sopenharmony_ci pinfo->pio_mask, pinfo->mwdma_mask, pinfo->udma_mask); 103362306a36Sopenharmony_ci} 103462306a36Sopenharmony_ci 103562306a36Sopenharmony_cistatic int pata_macio_common_init(struct pata_macio_priv *priv, 103662306a36Sopenharmony_ci resource_size_t tfregs, 103762306a36Sopenharmony_ci resource_size_t dmaregs, 103862306a36Sopenharmony_ci resource_size_t fcregs, 103962306a36Sopenharmony_ci unsigned long irq) 104062306a36Sopenharmony_ci{ 104162306a36Sopenharmony_ci struct ata_port_info pinfo; 104262306a36Sopenharmony_ci const struct ata_port_info *ppi[] = { &pinfo, NULL }; 104362306a36Sopenharmony_ci void __iomem *dma_regs = NULL; 104462306a36Sopenharmony_ci 104562306a36Sopenharmony_ci /* Fill up privates with various invariants collected from the 104662306a36Sopenharmony_ci * device-tree 104762306a36Sopenharmony_ci */ 104862306a36Sopenharmony_ci pata_macio_invariants(priv); 104962306a36Sopenharmony_ci 105062306a36Sopenharmony_ci /* Make sure we have sane initial timings in the cache */ 105162306a36Sopenharmony_ci pata_macio_default_timings(priv); 105262306a36Sopenharmony_ci 105362306a36Sopenharmony_ci /* Allocate libata host for 1 port */ 105462306a36Sopenharmony_ci memset(&pinfo, 0, sizeof(struct ata_port_info)); 105562306a36Sopenharmony_ci pmac_macio_calc_timing_masks(priv, &pinfo); 105662306a36Sopenharmony_ci pinfo.flags = ATA_FLAG_SLAVE_POSS; 105762306a36Sopenharmony_ci pinfo.port_ops = &pata_macio_ops; 105862306a36Sopenharmony_ci pinfo.private_data = priv; 105962306a36Sopenharmony_ci 106062306a36Sopenharmony_ci priv->host = ata_host_alloc_pinfo(priv->dev, ppi, 1); 106162306a36Sopenharmony_ci if (priv->host == NULL) { 106262306a36Sopenharmony_ci dev_err(priv->dev, "Failed to allocate ATA port structure\n"); 106362306a36Sopenharmony_ci return -ENOMEM; 106462306a36Sopenharmony_ci } 106562306a36Sopenharmony_ci 106662306a36Sopenharmony_ci /* Setup the private data in host too */ 106762306a36Sopenharmony_ci priv->host->private_data = priv; 106862306a36Sopenharmony_ci 106962306a36Sopenharmony_ci /* Map base registers */ 107062306a36Sopenharmony_ci priv->tfregs = devm_ioremap(priv->dev, tfregs, 0x100); 107162306a36Sopenharmony_ci if (priv->tfregs == NULL) { 107262306a36Sopenharmony_ci dev_err(priv->dev, "Failed to map ATA ports\n"); 107362306a36Sopenharmony_ci return -ENOMEM; 107462306a36Sopenharmony_ci } 107562306a36Sopenharmony_ci priv->host->iomap = &priv->tfregs; 107662306a36Sopenharmony_ci 107762306a36Sopenharmony_ci /* Map DMA regs */ 107862306a36Sopenharmony_ci if (dmaregs != 0) { 107962306a36Sopenharmony_ci dma_regs = devm_ioremap(priv->dev, dmaregs, 108062306a36Sopenharmony_ci sizeof(struct dbdma_regs)); 108162306a36Sopenharmony_ci if (dma_regs == NULL) 108262306a36Sopenharmony_ci dev_warn(priv->dev, "Failed to map ATA DMA registers\n"); 108362306a36Sopenharmony_ci } 108462306a36Sopenharmony_ci 108562306a36Sopenharmony_ci /* If chip has local feature control, map those regs too */ 108662306a36Sopenharmony_ci if (fcregs != 0) { 108762306a36Sopenharmony_ci priv->kauai_fcr = devm_ioremap(priv->dev, fcregs, 4); 108862306a36Sopenharmony_ci if (priv->kauai_fcr == NULL) { 108962306a36Sopenharmony_ci dev_err(priv->dev, "Failed to map ATA FCR register\n"); 109062306a36Sopenharmony_ci return -ENOMEM; 109162306a36Sopenharmony_ci } 109262306a36Sopenharmony_ci } 109362306a36Sopenharmony_ci 109462306a36Sopenharmony_ci /* Setup port data structure */ 109562306a36Sopenharmony_ci pata_macio_setup_ios(&priv->host->ports[0]->ioaddr, 109662306a36Sopenharmony_ci priv->tfregs, dma_regs); 109762306a36Sopenharmony_ci priv->host->ports[0]->private_data = priv; 109862306a36Sopenharmony_ci 109962306a36Sopenharmony_ci /* hard-reset the controller */ 110062306a36Sopenharmony_ci pata_macio_reset_hw(priv, 0); 110162306a36Sopenharmony_ci pata_macio_apply_timings(priv->host->ports[0], 0); 110262306a36Sopenharmony_ci 110362306a36Sopenharmony_ci /* Enable bus master if necessary */ 110462306a36Sopenharmony_ci if (priv->pdev && dma_regs) 110562306a36Sopenharmony_ci pci_set_master(priv->pdev); 110662306a36Sopenharmony_ci 110762306a36Sopenharmony_ci dev_info(priv->dev, "Activating pata-macio chipset %s, Apple bus ID %d\n", 110862306a36Sopenharmony_ci macio_ata_names[priv->kind], priv->aapl_bus_id); 110962306a36Sopenharmony_ci 111062306a36Sopenharmony_ci /* Start it up */ 111162306a36Sopenharmony_ci priv->irq = irq; 111262306a36Sopenharmony_ci return ata_host_activate(priv->host, irq, ata_bmdma_interrupt, 0, 111362306a36Sopenharmony_ci &pata_macio_sht); 111462306a36Sopenharmony_ci} 111562306a36Sopenharmony_ci 111662306a36Sopenharmony_cistatic int pata_macio_attach(struct macio_dev *mdev, 111762306a36Sopenharmony_ci const struct of_device_id *match) 111862306a36Sopenharmony_ci{ 111962306a36Sopenharmony_ci struct pata_macio_priv *priv; 112062306a36Sopenharmony_ci resource_size_t tfregs, dmaregs = 0; 112162306a36Sopenharmony_ci unsigned long irq; 112262306a36Sopenharmony_ci int rc; 112362306a36Sopenharmony_ci 112462306a36Sopenharmony_ci /* Check for broken device-trees */ 112562306a36Sopenharmony_ci if (macio_resource_count(mdev) == 0) { 112662306a36Sopenharmony_ci dev_err(&mdev->ofdev.dev, 112762306a36Sopenharmony_ci "No addresses for controller\n"); 112862306a36Sopenharmony_ci return -ENXIO; 112962306a36Sopenharmony_ci } 113062306a36Sopenharmony_ci 113162306a36Sopenharmony_ci /* Enable managed resources */ 113262306a36Sopenharmony_ci macio_enable_devres(mdev); 113362306a36Sopenharmony_ci 113462306a36Sopenharmony_ci /* Allocate and init private data structure */ 113562306a36Sopenharmony_ci priv = devm_kzalloc(&mdev->ofdev.dev, 113662306a36Sopenharmony_ci sizeof(struct pata_macio_priv), GFP_KERNEL); 113762306a36Sopenharmony_ci if (!priv) 113862306a36Sopenharmony_ci return -ENOMEM; 113962306a36Sopenharmony_ci 114062306a36Sopenharmony_ci priv->node = of_node_get(mdev->ofdev.dev.of_node); 114162306a36Sopenharmony_ci priv->mdev = mdev; 114262306a36Sopenharmony_ci priv->dev = &mdev->ofdev.dev; 114362306a36Sopenharmony_ci 114462306a36Sopenharmony_ci /* Request memory resource for taskfile registers */ 114562306a36Sopenharmony_ci if (macio_request_resource(mdev, 0, "pata-macio")) { 114662306a36Sopenharmony_ci dev_err(&mdev->ofdev.dev, 114762306a36Sopenharmony_ci "Cannot obtain taskfile resource\n"); 114862306a36Sopenharmony_ci return -EBUSY; 114962306a36Sopenharmony_ci } 115062306a36Sopenharmony_ci tfregs = macio_resource_start(mdev, 0); 115162306a36Sopenharmony_ci 115262306a36Sopenharmony_ci /* Request resources for DMA registers if any */ 115362306a36Sopenharmony_ci if (macio_resource_count(mdev) >= 2) { 115462306a36Sopenharmony_ci if (macio_request_resource(mdev, 1, "pata-macio-dma")) 115562306a36Sopenharmony_ci dev_err(&mdev->ofdev.dev, 115662306a36Sopenharmony_ci "Cannot obtain DMA resource\n"); 115762306a36Sopenharmony_ci else 115862306a36Sopenharmony_ci dmaregs = macio_resource_start(mdev, 1); 115962306a36Sopenharmony_ci } 116062306a36Sopenharmony_ci 116162306a36Sopenharmony_ci /* 116262306a36Sopenharmony_ci * Fixup missing IRQ for some old implementations with broken 116362306a36Sopenharmony_ci * device-trees. 116462306a36Sopenharmony_ci * 116562306a36Sopenharmony_ci * This is a bit bogus, it should be fixed in the device-tree itself, 116662306a36Sopenharmony_ci * via the existing macio fixups, based on the type of interrupt 116762306a36Sopenharmony_ci * controller in the machine. However, I have no test HW for this case, 116862306a36Sopenharmony_ci * and this trick works well enough on those old machines... 116962306a36Sopenharmony_ci */ 117062306a36Sopenharmony_ci if (macio_irq_count(mdev) == 0) { 117162306a36Sopenharmony_ci dev_warn(&mdev->ofdev.dev, 117262306a36Sopenharmony_ci "No interrupts for controller, using 13\n"); 117362306a36Sopenharmony_ci irq = irq_create_mapping(NULL, 13); 117462306a36Sopenharmony_ci } else 117562306a36Sopenharmony_ci irq = macio_irq(mdev, 0); 117662306a36Sopenharmony_ci 117762306a36Sopenharmony_ci /* Prevvent media bay callbacks until fully registered */ 117862306a36Sopenharmony_ci lock_media_bay(priv->mdev->media_bay); 117962306a36Sopenharmony_ci 118062306a36Sopenharmony_ci /* Get register addresses and call common initialization */ 118162306a36Sopenharmony_ci rc = pata_macio_common_init(priv, 118262306a36Sopenharmony_ci tfregs, /* Taskfile regs */ 118362306a36Sopenharmony_ci dmaregs, /* DBDMA regs */ 118462306a36Sopenharmony_ci 0, /* Feature control */ 118562306a36Sopenharmony_ci irq); 118662306a36Sopenharmony_ci unlock_media_bay(priv->mdev->media_bay); 118762306a36Sopenharmony_ci 118862306a36Sopenharmony_ci return rc; 118962306a36Sopenharmony_ci} 119062306a36Sopenharmony_ci 119162306a36Sopenharmony_cistatic int pata_macio_detach(struct macio_dev *mdev) 119262306a36Sopenharmony_ci{ 119362306a36Sopenharmony_ci struct ata_host *host = macio_get_drvdata(mdev); 119462306a36Sopenharmony_ci struct pata_macio_priv *priv = host->private_data; 119562306a36Sopenharmony_ci 119662306a36Sopenharmony_ci lock_media_bay(priv->mdev->media_bay); 119762306a36Sopenharmony_ci 119862306a36Sopenharmony_ci /* Make sure the mediabay callback doesn't try to access 119962306a36Sopenharmony_ci * dead stuff 120062306a36Sopenharmony_ci */ 120162306a36Sopenharmony_ci priv->host->private_data = NULL; 120262306a36Sopenharmony_ci 120362306a36Sopenharmony_ci ata_host_detach(host); 120462306a36Sopenharmony_ci 120562306a36Sopenharmony_ci unlock_media_bay(priv->mdev->media_bay); 120662306a36Sopenharmony_ci 120762306a36Sopenharmony_ci return 0; 120862306a36Sopenharmony_ci} 120962306a36Sopenharmony_ci 121062306a36Sopenharmony_ci#ifdef CONFIG_PM_SLEEP 121162306a36Sopenharmony_cistatic int pata_macio_suspend(struct macio_dev *mdev, pm_message_t mesg) 121262306a36Sopenharmony_ci{ 121362306a36Sopenharmony_ci struct ata_host *host = macio_get_drvdata(mdev); 121462306a36Sopenharmony_ci 121562306a36Sopenharmony_ci return pata_macio_do_suspend(host->private_data, mesg); 121662306a36Sopenharmony_ci} 121762306a36Sopenharmony_ci 121862306a36Sopenharmony_cistatic int pata_macio_resume(struct macio_dev *mdev) 121962306a36Sopenharmony_ci{ 122062306a36Sopenharmony_ci struct ata_host *host = macio_get_drvdata(mdev); 122162306a36Sopenharmony_ci 122262306a36Sopenharmony_ci return pata_macio_do_resume(host->private_data); 122362306a36Sopenharmony_ci} 122462306a36Sopenharmony_ci#endif /* CONFIG_PM_SLEEP */ 122562306a36Sopenharmony_ci 122662306a36Sopenharmony_ci#ifdef CONFIG_PMAC_MEDIABAY 122762306a36Sopenharmony_cistatic void pata_macio_mb_event(struct macio_dev* mdev, int mb_state) 122862306a36Sopenharmony_ci{ 122962306a36Sopenharmony_ci struct ata_host *host = macio_get_drvdata(mdev); 123062306a36Sopenharmony_ci struct ata_port *ap; 123162306a36Sopenharmony_ci struct ata_eh_info *ehi; 123262306a36Sopenharmony_ci struct ata_device *dev; 123362306a36Sopenharmony_ci unsigned long flags; 123462306a36Sopenharmony_ci 123562306a36Sopenharmony_ci if (!host || !host->private_data) 123662306a36Sopenharmony_ci return; 123762306a36Sopenharmony_ci ap = host->ports[0]; 123862306a36Sopenharmony_ci spin_lock_irqsave(ap->lock, flags); 123962306a36Sopenharmony_ci ehi = &ap->link.eh_info; 124062306a36Sopenharmony_ci if (mb_state == MB_CD) { 124162306a36Sopenharmony_ci ata_ehi_push_desc(ehi, "mediabay plug"); 124262306a36Sopenharmony_ci ata_ehi_hotplugged(ehi); 124362306a36Sopenharmony_ci ata_port_freeze(ap); 124462306a36Sopenharmony_ci } else { 124562306a36Sopenharmony_ci ata_ehi_push_desc(ehi, "mediabay unplug"); 124662306a36Sopenharmony_ci ata_for_each_dev(dev, &ap->link, ALL) 124762306a36Sopenharmony_ci dev->flags |= ATA_DFLAG_DETACH; 124862306a36Sopenharmony_ci ata_port_abort(ap); 124962306a36Sopenharmony_ci } 125062306a36Sopenharmony_ci spin_unlock_irqrestore(ap->lock, flags); 125162306a36Sopenharmony_ci 125262306a36Sopenharmony_ci} 125362306a36Sopenharmony_ci#endif /* CONFIG_PMAC_MEDIABAY */ 125462306a36Sopenharmony_ci 125562306a36Sopenharmony_ci 125662306a36Sopenharmony_cistatic int pata_macio_pci_attach(struct pci_dev *pdev, 125762306a36Sopenharmony_ci const struct pci_device_id *id) 125862306a36Sopenharmony_ci{ 125962306a36Sopenharmony_ci struct pata_macio_priv *priv; 126062306a36Sopenharmony_ci struct device_node *np; 126162306a36Sopenharmony_ci resource_size_t rbase; 126262306a36Sopenharmony_ci 126362306a36Sopenharmony_ci /* We cannot use a MacIO controller without its OF device node */ 126462306a36Sopenharmony_ci np = pci_device_to_OF_node(pdev); 126562306a36Sopenharmony_ci if (np == NULL) { 126662306a36Sopenharmony_ci dev_err(&pdev->dev, 126762306a36Sopenharmony_ci "Cannot find OF device node for controller\n"); 126862306a36Sopenharmony_ci return -ENODEV; 126962306a36Sopenharmony_ci } 127062306a36Sopenharmony_ci 127162306a36Sopenharmony_ci /* Check that it can be enabled */ 127262306a36Sopenharmony_ci if (pcim_enable_device(pdev)) { 127362306a36Sopenharmony_ci dev_err(&pdev->dev, 127462306a36Sopenharmony_ci "Cannot enable controller PCI device\n"); 127562306a36Sopenharmony_ci return -ENXIO; 127662306a36Sopenharmony_ci } 127762306a36Sopenharmony_ci 127862306a36Sopenharmony_ci /* Allocate and init private data structure */ 127962306a36Sopenharmony_ci priv = devm_kzalloc(&pdev->dev, 128062306a36Sopenharmony_ci sizeof(struct pata_macio_priv), GFP_KERNEL); 128162306a36Sopenharmony_ci if (!priv) 128262306a36Sopenharmony_ci return -ENOMEM; 128362306a36Sopenharmony_ci 128462306a36Sopenharmony_ci priv->node = of_node_get(np); 128562306a36Sopenharmony_ci priv->pdev = pdev; 128662306a36Sopenharmony_ci priv->dev = &pdev->dev; 128762306a36Sopenharmony_ci 128862306a36Sopenharmony_ci /* Get MMIO regions */ 128962306a36Sopenharmony_ci if (pci_request_regions(pdev, "pata-macio")) { 129062306a36Sopenharmony_ci dev_err(&pdev->dev, 129162306a36Sopenharmony_ci "Cannot obtain PCI resources\n"); 129262306a36Sopenharmony_ci return -EBUSY; 129362306a36Sopenharmony_ci } 129462306a36Sopenharmony_ci 129562306a36Sopenharmony_ci /* Get register addresses and call common initialization */ 129662306a36Sopenharmony_ci rbase = pci_resource_start(pdev, 0); 129762306a36Sopenharmony_ci if (pata_macio_common_init(priv, 129862306a36Sopenharmony_ci rbase + 0x2000, /* Taskfile regs */ 129962306a36Sopenharmony_ci rbase + 0x1000, /* DBDMA regs */ 130062306a36Sopenharmony_ci rbase, /* Feature control */ 130162306a36Sopenharmony_ci pdev->irq)) 130262306a36Sopenharmony_ci return -ENXIO; 130362306a36Sopenharmony_ci 130462306a36Sopenharmony_ci return 0; 130562306a36Sopenharmony_ci} 130662306a36Sopenharmony_ci 130762306a36Sopenharmony_cistatic void pata_macio_pci_detach(struct pci_dev *pdev) 130862306a36Sopenharmony_ci{ 130962306a36Sopenharmony_ci struct ata_host *host = pci_get_drvdata(pdev); 131062306a36Sopenharmony_ci 131162306a36Sopenharmony_ci ata_host_detach(host); 131262306a36Sopenharmony_ci} 131362306a36Sopenharmony_ci 131462306a36Sopenharmony_ci#ifdef CONFIG_PM_SLEEP 131562306a36Sopenharmony_cistatic int pata_macio_pci_suspend(struct pci_dev *pdev, pm_message_t mesg) 131662306a36Sopenharmony_ci{ 131762306a36Sopenharmony_ci struct ata_host *host = pci_get_drvdata(pdev); 131862306a36Sopenharmony_ci 131962306a36Sopenharmony_ci return pata_macio_do_suspend(host->private_data, mesg); 132062306a36Sopenharmony_ci} 132162306a36Sopenharmony_ci 132262306a36Sopenharmony_cistatic int pata_macio_pci_resume(struct pci_dev *pdev) 132362306a36Sopenharmony_ci{ 132462306a36Sopenharmony_ci struct ata_host *host = pci_get_drvdata(pdev); 132562306a36Sopenharmony_ci 132662306a36Sopenharmony_ci return pata_macio_do_resume(host->private_data); 132762306a36Sopenharmony_ci} 132862306a36Sopenharmony_ci#endif /* CONFIG_PM_SLEEP */ 132962306a36Sopenharmony_ci 133062306a36Sopenharmony_cistatic const struct of_device_id pata_macio_match[] = 133162306a36Sopenharmony_ci{ 133262306a36Sopenharmony_ci { .name = "IDE", }, 133362306a36Sopenharmony_ci { .name = "ATA", }, 133462306a36Sopenharmony_ci { .type = "ide", }, 133562306a36Sopenharmony_ci { .type = "ata", }, 133662306a36Sopenharmony_ci { /* sentinel */ } 133762306a36Sopenharmony_ci}; 133862306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, pata_macio_match); 133962306a36Sopenharmony_ci 134062306a36Sopenharmony_cistatic struct macio_driver pata_macio_driver = 134162306a36Sopenharmony_ci{ 134262306a36Sopenharmony_ci .driver = { 134362306a36Sopenharmony_ci .name = "pata-macio", 134462306a36Sopenharmony_ci .owner = THIS_MODULE, 134562306a36Sopenharmony_ci .of_match_table = pata_macio_match, 134662306a36Sopenharmony_ci }, 134762306a36Sopenharmony_ci .probe = pata_macio_attach, 134862306a36Sopenharmony_ci .remove = pata_macio_detach, 134962306a36Sopenharmony_ci#ifdef CONFIG_PM_SLEEP 135062306a36Sopenharmony_ci .suspend = pata_macio_suspend, 135162306a36Sopenharmony_ci .resume = pata_macio_resume, 135262306a36Sopenharmony_ci#endif 135362306a36Sopenharmony_ci#ifdef CONFIG_PMAC_MEDIABAY 135462306a36Sopenharmony_ci .mediabay_event = pata_macio_mb_event, 135562306a36Sopenharmony_ci#endif 135662306a36Sopenharmony_ci}; 135762306a36Sopenharmony_ci 135862306a36Sopenharmony_cistatic const struct pci_device_id pata_macio_pci_match[] = { 135962306a36Sopenharmony_ci { PCI_VDEVICE(APPLE, PCI_DEVICE_ID_APPLE_UNI_N_ATA), 0 }, 136062306a36Sopenharmony_ci { PCI_VDEVICE(APPLE, PCI_DEVICE_ID_APPLE_IPID_ATA100), 0 }, 136162306a36Sopenharmony_ci { PCI_VDEVICE(APPLE, PCI_DEVICE_ID_APPLE_K2_ATA100), 0 }, 136262306a36Sopenharmony_ci { PCI_VDEVICE(APPLE, PCI_DEVICE_ID_APPLE_SH_ATA), 0 }, 136362306a36Sopenharmony_ci { PCI_VDEVICE(APPLE, PCI_DEVICE_ID_APPLE_IPID2_ATA), 0 }, 136462306a36Sopenharmony_ci {}, 136562306a36Sopenharmony_ci}; 136662306a36Sopenharmony_ci 136762306a36Sopenharmony_cistatic struct pci_driver pata_macio_pci_driver = { 136862306a36Sopenharmony_ci .name = "pata-pci-macio", 136962306a36Sopenharmony_ci .id_table = pata_macio_pci_match, 137062306a36Sopenharmony_ci .probe = pata_macio_pci_attach, 137162306a36Sopenharmony_ci .remove = pata_macio_pci_detach, 137262306a36Sopenharmony_ci#ifdef CONFIG_PM_SLEEP 137362306a36Sopenharmony_ci .suspend = pata_macio_pci_suspend, 137462306a36Sopenharmony_ci .resume = pata_macio_pci_resume, 137562306a36Sopenharmony_ci#endif 137662306a36Sopenharmony_ci .driver = { 137762306a36Sopenharmony_ci .owner = THIS_MODULE, 137862306a36Sopenharmony_ci }, 137962306a36Sopenharmony_ci}; 138062306a36Sopenharmony_ciMODULE_DEVICE_TABLE(pci, pata_macio_pci_match); 138162306a36Sopenharmony_ci 138262306a36Sopenharmony_ci 138362306a36Sopenharmony_cistatic int __init pata_macio_init(void) 138462306a36Sopenharmony_ci{ 138562306a36Sopenharmony_ci int rc; 138662306a36Sopenharmony_ci 138762306a36Sopenharmony_ci if (!machine_is(powermac)) 138862306a36Sopenharmony_ci return -ENODEV; 138962306a36Sopenharmony_ci 139062306a36Sopenharmony_ci rc = pci_register_driver(&pata_macio_pci_driver); 139162306a36Sopenharmony_ci if (rc) 139262306a36Sopenharmony_ci return rc; 139362306a36Sopenharmony_ci rc = macio_register_driver(&pata_macio_driver); 139462306a36Sopenharmony_ci if (rc) { 139562306a36Sopenharmony_ci pci_unregister_driver(&pata_macio_pci_driver); 139662306a36Sopenharmony_ci return rc; 139762306a36Sopenharmony_ci } 139862306a36Sopenharmony_ci return 0; 139962306a36Sopenharmony_ci} 140062306a36Sopenharmony_ci 140162306a36Sopenharmony_cistatic void __exit pata_macio_exit(void) 140262306a36Sopenharmony_ci{ 140362306a36Sopenharmony_ci macio_unregister_driver(&pata_macio_driver); 140462306a36Sopenharmony_ci pci_unregister_driver(&pata_macio_pci_driver); 140562306a36Sopenharmony_ci} 140662306a36Sopenharmony_ci 140762306a36Sopenharmony_cimodule_init(pata_macio_init); 140862306a36Sopenharmony_cimodule_exit(pata_macio_exit); 140962306a36Sopenharmony_ci 141062306a36Sopenharmony_ciMODULE_AUTHOR("Benjamin Herrenschmidt"); 141162306a36Sopenharmony_ciMODULE_DESCRIPTION("Apple MacIO PATA driver"); 141262306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 141362306a36Sopenharmony_ciMODULE_VERSION(DRV_VERSION); 1414