109c434b8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 288358ab0SBenjamin Herrenschmidt /* 388358ab0SBenjamin Herrenschmidt * Libata based driver for Apple "macio" family of PATA controllers 488358ab0SBenjamin Herrenschmidt * 588358ab0SBenjamin Herrenschmidt * Copyright 2008/2009 Benjamin Herrenschmidt, IBM Corp 688358ab0SBenjamin Herrenschmidt * <benh@kernel.crashing.org> 788358ab0SBenjamin Herrenschmidt * 888358ab0SBenjamin Herrenschmidt * Some bits and pieces from drivers/ide/ppc/pmac.c 988358ab0SBenjamin Herrenschmidt * 1088358ab0SBenjamin Herrenschmidt */ 1188358ab0SBenjamin Herrenschmidt 1288358ab0SBenjamin Herrenschmidt #undef DEBUG 1388358ab0SBenjamin Herrenschmidt #undef DEBUG_DMA 1488358ab0SBenjamin Herrenschmidt 1588358ab0SBenjamin Herrenschmidt #include <linux/kernel.h> 1688358ab0SBenjamin Herrenschmidt #include <linux/module.h> 1788358ab0SBenjamin Herrenschmidt #include <linux/init.h> 1888358ab0SBenjamin Herrenschmidt #include <linux/blkdev.h> 1988358ab0SBenjamin Herrenschmidt #include <linux/ata.h> 2088358ab0SBenjamin Herrenschmidt #include <linux/libata.h> 2188358ab0SBenjamin Herrenschmidt #include <linux/adb.h> 2288358ab0SBenjamin Herrenschmidt #include <linux/pmu.h> 2388358ab0SBenjamin Herrenschmidt #include <linux/scatterlist.h> 2488358ab0SBenjamin Herrenschmidt #include <linux/of.h> 255a0e3ad6STejun Heo #include <linux/gfp.h> 26952bbcb0SBjorn Helgaas #include <linux/pci.h> 2788358ab0SBenjamin Herrenschmidt 2888358ab0SBenjamin Herrenschmidt #include <scsi/scsi.h> 2988358ab0SBenjamin Herrenschmidt #include <scsi/scsi_host.h> 3088358ab0SBenjamin Herrenschmidt #include <scsi/scsi_device.h> 3188358ab0SBenjamin Herrenschmidt 3288358ab0SBenjamin Herrenschmidt #include <asm/macio.h> 3388358ab0SBenjamin Herrenschmidt #include <asm/io.h> 3488358ab0SBenjamin Herrenschmidt #include <asm/dbdma.h> 3588358ab0SBenjamin Herrenschmidt #include <asm/machdep.h> 3688358ab0SBenjamin Herrenschmidt #include <asm/pmac_feature.h> 3788358ab0SBenjamin Herrenschmidt #include <asm/mediabay.h> 3888358ab0SBenjamin Herrenschmidt 3988358ab0SBenjamin Herrenschmidt #ifdef DEBUG_DMA 4088358ab0SBenjamin Herrenschmidt #define dev_dbgdma(dev, format, arg...) \ 4188358ab0SBenjamin Herrenschmidt dev_printk(KERN_DEBUG , dev , format , ## arg) 4288358ab0SBenjamin Herrenschmidt #else 4388358ab0SBenjamin Herrenschmidt #define dev_dbgdma(dev, format, arg...) \ 4488358ab0SBenjamin Herrenschmidt ({ if (0) dev_printk(KERN_DEBUG, dev, format, ##arg); 0; }) 4588358ab0SBenjamin Herrenschmidt #endif 4688358ab0SBenjamin Herrenschmidt 4788358ab0SBenjamin Herrenschmidt #define DRV_NAME "pata_macio" 4888358ab0SBenjamin Herrenschmidt #define DRV_VERSION "0.9" 4988358ab0SBenjamin Herrenschmidt 5088358ab0SBenjamin Herrenschmidt /* Models of macio ATA controller */ 5188358ab0SBenjamin Herrenschmidt enum { 5288358ab0SBenjamin Herrenschmidt controller_ohare, /* OHare based */ 5388358ab0SBenjamin Herrenschmidt controller_heathrow, /* Heathrow/Paddington */ 5488358ab0SBenjamin Herrenschmidt controller_kl_ata3, /* KeyLargo ATA-3 */ 5588358ab0SBenjamin Herrenschmidt controller_kl_ata4, /* KeyLargo ATA-4 */ 5688358ab0SBenjamin Herrenschmidt controller_un_ata6, /* UniNorth2 ATA-6 */ 5788358ab0SBenjamin Herrenschmidt controller_k2_ata6, /* K2 ATA-6 */ 5888358ab0SBenjamin Herrenschmidt controller_sh_ata6, /* Shasta ATA-6 */ 5988358ab0SBenjamin Herrenschmidt }; 6088358ab0SBenjamin Herrenschmidt 6188358ab0SBenjamin Herrenschmidt static const char* macio_ata_names[] = { 6288358ab0SBenjamin Herrenschmidt "OHare ATA", /* OHare based */ 6388358ab0SBenjamin Herrenschmidt "Heathrow ATA", /* Heathrow/Paddington */ 6488358ab0SBenjamin Herrenschmidt "KeyLargo ATA-3", /* KeyLargo ATA-3 (MDMA only) */ 6588358ab0SBenjamin Herrenschmidt "KeyLargo ATA-4", /* KeyLargo ATA-4 (UDMA/66) */ 6688358ab0SBenjamin Herrenschmidt "UniNorth ATA-6", /* UniNorth2 ATA-6 (UDMA/100) */ 6788358ab0SBenjamin Herrenschmidt "K2 ATA-6", /* K2 ATA-6 (UDMA/100) */ 6888358ab0SBenjamin Herrenschmidt "Shasta ATA-6", /* Shasta ATA-6 (UDMA/133) */ 6988358ab0SBenjamin Herrenschmidt }; 7088358ab0SBenjamin Herrenschmidt 7188358ab0SBenjamin Herrenschmidt /* 7288358ab0SBenjamin Herrenschmidt * Extra registers, both 32-bit little-endian 7388358ab0SBenjamin Herrenschmidt */ 7488358ab0SBenjamin Herrenschmidt #define IDE_TIMING_CONFIG 0x200 7588358ab0SBenjamin Herrenschmidt #define IDE_INTERRUPT 0x300 7688358ab0SBenjamin Herrenschmidt 7788358ab0SBenjamin Herrenschmidt /* Kauai (U2) ATA has different register setup */ 7888358ab0SBenjamin Herrenschmidt #define IDE_KAUAI_PIO_CONFIG 0x200 7988358ab0SBenjamin Herrenschmidt #define IDE_KAUAI_ULTRA_CONFIG 0x210 8088358ab0SBenjamin Herrenschmidt #define IDE_KAUAI_POLL_CONFIG 0x220 8188358ab0SBenjamin Herrenschmidt 8288358ab0SBenjamin Herrenschmidt /* 8388358ab0SBenjamin Herrenschmidt * Timing configuration register definitions 8488358ab0SBenjamin Herrenschmidt */ 8588358ab0SBenjamin Herrenschmidt 8688358ab0SBenjamin Herrenschmidt /* Number of IDE_SYSCLK_NS ticks, argument is in nanoseconds */ 8788358ab0SBenjamin Herrenschmidt #define SYSCLK_TICKS(t) (((t) + IDE_SYSCLK_NS - 1) / IDE_SYSCLK_NS) 8888358ab0SBenjamin Herrenschmidt #define SYSCLK_TICKS_66(t) (((t) + IDE_SYSCLK_66_NS - 1) / IDE_SYSCLK_66_NS) 8988358ab0SBenjamin Herrenschmidt #define IDE_SYSCLK_NS 30 /* 33Mhz cell */ 9088358ab0SBenjamin Herrenschmidt #define IDE_SYSCLK_66_NS 15 /* 66Mhz cell */ 9188358ab0SBenjamin Herrenschmidt 9288358ab0SBenjamin Herrenschmidt /* 133Mhz cell, found in shasta. 9388358ab0SBenjamin Herrenschmidt * See comments about 100 Mhz Uninorth 2... 9488358ab0SBenjamin Herrenschmidt * Note that PIO_MASK and MDMA_MASK seem to overlap, that's just 9588358ab0SBenjamin Herrenschmidt * weird and I don't now why .. at this stage 9688358ab0SBenjamin Herrenschmidt */ 9788358ab0SBenjamin Herrenschmidt #define TR_133_PIOREG_PIO_MASK 0xff000fff 9888358ab0SBenjamin Herrenschmidt #define TR_133_PIOREG_MDMA_MASK 0x00fff800 9988358ab0SBenjamin Herrenschmidt #define TR_133_UDMAREG_UDMA_MASK 0x0003ffff 10088358ab0SBenjamin Herrenschmidt #define TR_133_UDMAREG_UDMA_EN 0x00000001 10188358ab0SBenjamin Herrenschmidt 10288358ab0SBenjamin Herrenschmidt /* 100Mhz cell, found in Uninorth 2 and K2. It appears as a pci device 10388358ab0SBenjamin Herrenschmidt * (106b/0033) on uninorth or K2 internal PCI bus and it's clock is 10488358ab0SBenjamin Herrenschmidt * controlled like gem or fw. It appears to be an evolution of keylargo 10588358ab0SBenjamin Herrenschmidt * ATA4 with a timing register extended to 2x32bits registers (one 10688358ab0SBenjamin Herrenschmidt * for PIO & MWDMA and one for UDMA, and a similar DBDMA channel. 10788358ab0SBenjamin Herrenschmidt * It has it's own local feature control register as well. 10888358ab0SBenjamin Herrenschmidt * 10988358ab0SBenjamin Herrenschmidt * After scratching my mind over the timing values, at least for PIO 11088358ab0SBenjamin Herrenschmidt * and MDMA, I think I've figured the format of the timing register, 11188358ab0SBenjamin Herrenschmidt * though I use pre-calculated tables for UDMA as usual... 11288358ab0SBenjamin Herrenschmidt */ 11388358ab0SBenjamin Herrenschmidt #define TR_100_PIO_ADDRSETUP_MASK 0xff000000 /* Size of field unknown */ 11488358ab0SBenjamin Herrenschmidt #define TR_100_PIO_ADDRSETUP_SHIFT 24 11588358ab0SBenjamin Herrenschmidt #define TR_100_MDMA_MASK 0x00fff000 11688358ab0SBenjamin Herrenschmidt #define TR_100_MDMA_RECOVERY_MASK 0x00fc0000 11788358ab0SBenjamin Herrenschmidt #define TR_100_MDMA_RECOVERY_SHIFT 18 11888358ab0SBenjamin Herrenschmidt #define TR_100_MDMA_ACCESS_MASK 0x0003f000 11988358ab0SBenjamin Herrenschmidt #define TR_100_MDMA_ACCESS_SHIFT 12 12088358ab0SBenjamin Herrenschmidt #define TR_100_PIO_MASK 0xff000fff 12188358ab0SBenjamin Herrenschmidt #define TR_100_PIO_RECOVERY_MASK 0x00000fc0 12288358ab0SBenjamin Herrenschmidt #define TR_100_PIO_RECOVERY_SHIFT 6 12388358ab0SBenjamin Herrenschmidt #define TR_100_PIO_ACCESS_MASK 0x0000003f 12488358ab0SBenjamin Herrenschmidt #define TR_100_PIO_ACCESS_SHIFT 0 12588358ab0SBenjamin Herrenschmidt 12688358ab0SBenjamin Herrenschmidt #define TR_100_UDMAREG_UDMA_MASK 0x0000ffff 12788358ab0SBenjamin Herrenschmidt #define TR_100_UDMAREG_UDMA_EN 0x00000001 12888358ab0SBenjamin Herrenschmidt 12988358ab0SBenjamin Herrenschmidt 13088358ab0SBenjamin Herrenschmidt /* 66Mhz cell, found in KeyLargo. Can do ultra mode 0 to 2 on 13188358ab0SBenjamin Herrenschmidt * 40 connector cable and to 4 on 80 connector one. 13288358ab0SBenjamin Herrenschmidt * Clock unit is 15ns (66Mhz) 13388358ab0SBenjamin Herrenschmidt * 13488358ab0SBenjamin Herrenschmidt * 3 Values can be programmed: 13588358ab0SBenjamin Herrenschmidt * - Write data setup, which appears to match the cycle time. They 13688358ab0SBenjamin Herrenschmidt * also call it DIOW setup. 13788358ab0SBenjamin Herrenschmidt * - Ready to pause time (from spec) 13888358ab0SBenjamin Herrenschmidt * - Address setup. That one is weird. I don't see where exactly 13988358ab0SBenjamin Herrenschmidt * it fits in UDMA cycles, I got it's name from an obscure piece 14088358ab0SBenjamin Herrenschmidt * of commented out code in Darwin. They leave it to 0, we do as 14188358ab0SBenjamin Herrenschmidt * well, despite a comment that would lead to think it has a 14288358ab0SBenjamin Herrenschmidt * min value of 45ns. 14388358ab0SBenjamin Herrenschmidt * Apple also add 60ns to the write data setup (or cycle time ?) on 14488358ab0SBenjamin Herrenschmidt * reads. 14588358ab0SBenjamin Herrenschmidt */ 14688358ab0SBenjamin Herrenschmidt #define TR_66_UDMA_MASK 0xfff00000 14788358ab0SBenjamin Herrenschmidt #define TR_66_UDMA_EN 0x00100000 /* Enable Ultra mode for DMA */ 14888358ab0SBenjamin Herrenschmidt #define TR_66_PIO_ADDRSETUP_MASK 0xe0000000 /* Address setup */ 14988358ab0SBenjamin Herrenschmidt #define TR_66_PIO_ADDRSETUP_SHIFT 29 15088358ab0SBenjamin Herrenschmidt #define TR_66_UDMA_RDY2PAUS_MASK 0x1e000000 /* Ready 2 pause time */ 15188358ab0SBenjamin Herrenschmidt #define TR_66_UDMA_RDY2PAUS_SHIFT 25 15288358ab0SBenjamin Herrenschmidt #define TR_66_UDMA_WRDATASETUP_MASK 0x01e00000 /* Write data setup time */ 15388358ab0SBenjamin Herrenschmidt #define TR_66_UDMA_WRDATASETUP_SHIFT 21 15488358ab0SBenjamin Herrenschmidt #define TR_66_MDMA_MASK 0x000ffc00 15588358ab0SBenjamin Herrenschmidt #define TR_66_MDMA_RECOVERY_MASK 0x000f8000 15688358ab0SBenjamin Herrenschmidt #define TR_66_MDMA_RECOVERY_SHIFT 15 15788358ab0SBenjamin Herrenschmidt #define TR_66_MDMA_ACCESS_MASK 0x00007c00 15888358ab0SBenjamin Herrenschmidt #define TR_66_MDMA_ACCESS_SHIFT 10 15988358ab0SBenjamin Herrenschmidt #define TR_66_PIO_MASK 0xe00003ff 16088358ab0SBenjamin Herrenschmidt #define TR_66_PIO_RECOVERY_MASK 0x000003e0 16188358ab0SBenjamin Herrenschmidt #define TR_66_PIO_RECOVERY_SHIFT 5 16288358ab0SBenjamin Herrenschmidt #define TR_66_PIO_ACCESS_MASK 0x0000001f 16388358ab0SBenjamin Herrenschmidt #define TR_66_PIO_ACCESS_SHIFT 0 16488358ab0SBenjamin Herrenschmidt 16588358ab0SBenjamin Herrenschmidt /* 33Mhz cell, found in OHare, Heathrow (& Paddington) and KeyLargo 16688358ab0SBenjamin Herrenschmidt * Can do pio & mdma modes, clock unit is 30ns (33Mhz) 16788358ab0SBenjamin Herrenschmidt * 16888358ab0SBenjamin Herrenschmidt * The access time and recovery time can be programmed. Some older 16988358ab0SBenjamin Herrenschmidt * Darwin code base limit OHare to 150ns cycle time. I decided to do 17088358ab0SBenjamin Herrenschmidt * the same here fore safety against broken old hardware ;) 17188358ab0SBenjamin Herrenschmidt * The HalfTick bit, when set, adds half a clock (15ns) to the access 17288358ab0SBenjamin Herrenschmidt * time and removes one from recovery. It's not supported on KeyLargo 17388358ab0SBenjamin Herrenschmidt * implementation afaik. The E bit appears to be set for PIO mode 0 and 17488358ab0SBenjamin Herrenschmidt * is used to reach long timings used in this mode. 17588358ab0SBenjamin Herrenschmidt */ 17688358ab0SBenjamin Herrenschmidt #define TR_33_MDMA_MASK 0x003ff800 17788358ab0SBenjamin Herrenschmidt #define TR_33_MDMA_RECOVERY_MASK 0x001f0000 17888358ab0SBenjamin Herrenschmidt #define TR_33_MDMA_RECOVERY_SHIFT 16 17988358ab0SBenjamin Herrenschmidt #define TR_33_MDMA_ACCESS_MASK 0x0000f800 18088358ab0SBenjamin Herrenschmidt #define TR_33_MDMA_ACCESS_SHIFT 11 18188358ab0SBenjamin Herrenschmidt #define TR_33_MDMA_HALFTICK 0x00200000 18288358ab0SBenjamin Herrenschmidt #define TR_33_PIO_MASK 0x000007ff 18388358ab0SBenjamin Herrenschmidt #define TR_33_PIO_E 0x00000400 18488358ab0SBenjamin Herrenschmidt #define TR_33_PIO_RECOVERY_MASK 0x000003e0 18588358ab0SBenjamin Herrenschmidt #define TR_33_PIO_RECOVERY_SHIFT 5 18688358ab0SBenjamin Herrenschmidt #define TR_33_PIO_ACCESS_MASK 0x0000001f 18788358ab0SBenjamin Herrenschmidt #define TR_33_PIO_ACCESS_SHIFT 0 18888358ab0SBenjamin Herrenschmidt 18988358ab0SBenjamin Herrenschmidt /* 19088358ab0SBenjamin Herrenschmidt * Interrupt register definitions. Only present on newer cells 19188358ab0SBenjamin Herrenschmidt * (Keylargo and later afaik) so we don't use it. 19288358ab0SBenjamin Herrenschmidt */ 19388358ab0SBenjamin Herrenschmidt #define IDE_INTR_DMA 0x80000000 19488358ab0SBenjamin Herrenschmidt #define IDE_INTR_DEVICE 0x40000000 19588358ab0SBenjamin Herrenschmidt 19688358ab0SBenjamin Herrenschmidt /* 19788358ab0SBenjamin Herrenschmidt * FCR Register on Kauai. Not sure what bit 0x4 is ... 19888358ab0SBenjamin Herrenschmidt */ 19988358ab0SBenjamin Herrenschmidt #define KAUAI_FCR_UATA_MAGIC 0x00000004 20088358ab0SBenjamin Herrenschmidt #define KAUAI_FCR_UATA_RESET_N 0x00000002 20188358ab0SBenjamin Herrenschmidt #define KAUAI_FCR_UATA_ENABLE 0x00000001 20288358ab0SBenjamin Herrenschmidt 20388358ab0SBenjamin Herrenschmidt 20488358ab0SBenjamin Herrenschmidt /* Allow up to 256 DBDMA commands per xfer */ 20588358ab0SBenjamin Herrenschmidt #define MAX_DCMDS 256 20688358ab0SBenjamin Herrenschmidt 20788358ab0SBenjamin Herrenschmidt /* Don't let a DMA segment go all the way to 64K */ 20888358ab0SBenjamin Herrenschmidt #define MAX_DBDMA_SEG 0xff00 20988358ab0SBenjamin Herrenschmidt 21088358ab0SBenjamin Herrenschmidt 21188358ab0SBenjamin Herrenschmidt /* 21288358ab0SBenjamin Herrenschmidt * Wait 1s for disk to answer on IDE bus after a hard reset 21388358ab0SBenjamin Herrenschmidt * of the device (via GPIO/FCR). 21488358ab0SBenjamin Herrenschmidt * 21588358ab0SBenjamin Herrenschmidt * Some devices seem to "pollute" the bus even after dropping 21688358ab0SBenjamin Herrenschmidt * the BSY bit (typically some combo drives slave on the UDMA 21788358ab0SBenjamin Herrenschmidt * bus) after a hard reset. Since we hard reset all drives on 21888358ab0SBenjamin Herrenschmidt * KeyLargo ATA66, we have to keep that delay around. I may end 21988358ab0SBenjamin Herrenschmidt * up not hard resetting anymore on these and keep the delay only 22088358ab0SBenjamin Herrenschmidt * for older interfaces instead (we have to reset when coming 22188358ab0SBenjamin Herrenschmidt * from MacOS...) --BenH. 22288358ab0SBenjamin Herrenschmidt */ 22388358ab0SBenjamin Herrenschmidt #define IDE_WAKEUP_DELAY_MS 1000 22488358ab0SBenjamin Herrenschmidt 22588358ab0SBenjamin Herrenschmidt struct pata_macio_timing; 22688358ab0SBenjamin Herrenschmidt 22788358ab0SBenjamin Herrenschmidt struct pata_macio_priv { 22888358ab0SBenjamin Herrenschmidt int kind; 22988358ab0SBenjamin Herrenschmidt int aapl_bus_id; 23088358ab0SBenjamin Herrenschmidt int mediabay : 1; 23188358ab0SBenjamin Herrenschmidt struct device_node *node; 23288358ab0SBenjamin Herrenschmidt struct macio_dev *mdev; 23388358ab0SBenjamin Herrenschmidt struct pci_dev *pdev; 23488358ab0SBenjamin Herrenschmidt struct device *dev; 23588358ab0SBenjamin Herrenschmidt int irq; 23688358ab0SBenjamin Herrenschmidt u32 treg[2][2]; 23788358ab0SBenjamin Herrenschmidt void __iomem *tfregs; 23888358ab0SBenjamin Herrenschmidt void __iomem *kauai_fcr; 23988358ab0SBenjamin Herrenschmidt struct dbdma_cmd * dma_table_cpu; 24088358ab0SBenjamin Herrenschmidt dma_addr_t dma_table_dma; 24188358ab0SBenjamin Herrenschmidt struct ata_host *host; 24288358ab0SBenjamin Herrenschmidt const struct pata_macio_timing *timings; 24388358ab0SBenjamin Herrenschmidt }; 24488358ab0SBenjamin Herrenschmidt 24588358ab0SBenjamin Herrenschmidt /* Previous variants of this driver used to calculate timings 24688358ab0SBenjamin Herrenschmidt * for various variants of the chip and use tables for others. 24788358ab0SBenjamin Herrenschmidt * 24888358ab0SBenjamin Herrenschmidt * Not only was this confusing, but in addition, it isn't clear 24988358ab0SBenjamin Herrenschmidt * whether our calculation code was correct. It didn't entirely 25088358ab0SBenjamin Herrenschmidt * match the darwin code and whatever documentation I could find 25188358ab0SBenjamin Herrenschmidt * on these cells 25288358ab0SBenjamin Herrenschmidt * 25388358ab0SBenjamin Herrenschmidt * I decided to entirely rely on a table instead for this version 25488358ab0SBenjamin Herrenschmidt * of the driver. Also, because I don't really care about derated 25588358ab0SBenjamin Herrenschmidt * modes and really old HW other than making it work, I'm not going 25688358ab0SBenjamin Herrenschmidt * to calculate / snoop timing values for something else than the 25788358ab0SBenjamin Herrenschmidt * standard modes. 25888358ab0SBenjamin Herrenschmidt */ 25988358ab0SBenjamin Herrenschmidt struct pata_macio_timing { 26088358ab0SBenjamin Herrenschmidt int mode; 26188358ab0SBenjamin Herrenschmidt u32 reg1; /* Bits to set in first timing reg */ 26288358ab0SBenjamin Herrenschmidt u32 reg2; /* Bits to set in second timing reg */ 26388358ab0SBenjamin Herrenschmidt }; 26488358ab0SBenjamin Herrenschmidt 26588358ab0SBenjamin Herrenschmidt static const struct pata_macio_timing pata_macio_ohare_timings[] = { 26688358ab0SBenjamin Herrenschmidt { XFER_PIO_0, 0x00000526, 0, }, 26788358ab0SBenjamin Herrenschmidt { XFER_PIO_1, 0x00000085, 0, }, 26888358ab0SBenjamin Herrenschmidt { XFER_PIO_2, 0x00000025, 0, }, 26988358ab0SBenjamin Herrenschmidt { XFER_PIO_3, 0x00000025, 0, }, 27088358ab0SBenjamin Herrenschmidt { XFER_PIO_4, 0x00000025, 0, }, 27188358ab0SBenjamin Herrenschmidt { XFER_MW_DMA_0, 0x00074000, 0, }, 27288358ab0SBenjamin Herrenschmidt { XFER_MW_DMA_1, 0x00221000, 0, }, 27388358ab0SBenjamin Herrenschmidt { XFER_MW_DMA_2, 0x00211000, 0, }, 27488358ab0SBenjamin Herrenschmidt { -1, 0, 0 } 27588358ab0SBenjamin Herrenschmidt }; 27688358ab0SBenjamin Herrenschmidt 27788358ab0SBenjamin Herrenschmidt static const struct pata_macio_timing pata_macio_heathrow_timings[] = { 27888358ab0SBenjamin Herrenschmidt { XFER_PIO_0, 0x00000526, 0, }, 27988358ab0SBenjamin Herrenschmidt { XFER_PIO_1, 0x00000085, 0, }, 28088358ab0SBenjamin Herrenschmidt { XFER_PIO_2, 0x00000025, 0, }, 28188358ab0SBenjamin Herrenschmidt { XFER_PIO_3, 0x00000025, 0, }, 28288358ab0SBenjamin Herrenschmidt { XFER_PIO_4, 0x00000025, 0, }, 28388358ab0SBenjamin Herrenschmidt { XFER_MW_DMA_0, 0x00074000, 0, }, 28488358ab0SBenjamin Herrenschmidt { XFER_MW_DMA_1, 0x00221000, 0, }, 28588358ab0SBenjamin Herrenschmidt { XFER_MW_DMA_2, 0x00211000, 0, }, 28688358ab0SBenjamin Herrenschmidt { -1, 0, 0 } 28788358ab0SBenjamin Herrenschmidt }; 28888358ab0SBenjamin Herrenschmidt 28988358ab0SBenjamin Herrenschmidt static const struct pata_macio_timing pata_macio_kl33_timings[] = { 29088358ab0SBenjamin Herrenschmidt { XFER_PIO_0, 0x00000526, 0, }, 29188358ab0SBenjamin Herrenschmidt { XFER_PIO_1, 0x00000085, 0, }, 29288358ab0SBenjamin Herrenschmidt { XFER_PIO_2, 0x00000025, 0, }, 29388358ab0SBenjamin Herrenschmidt { XFER_PIO_3, 0x00000025, 0, }, 29488358ab0SBenjamin Herrenschmidt { XFER_PIO_4, 0x00000025, 0, }, 29588358ab0SBenjamin Herrenschmidt { XFER_MW_DMA_0, 0x00084000, 0, }, 29688358ab0SBenjamin Herrenschmidt { XFER_MW_DMA_1, 0x00021800, 0, }, 29788358ab0SBenjamin Herrenschmidt { XFER_MW_DMA_2, 0x00011800, 0, }, 29888358ab0SBenjamin Herrenschmidt { -1, 0, 0 } 29988358ab0SBenjamin Herrenschmidt }; 30088358ab0SBenjamin Herrenschmidt 30188358ab0SBenjamin Herrenschmidt static const struct pata_macio_timing pata_macio_kl66_timings[] = { 30288358ab0SBenjamin Herrenschmidt { XFER_PIO_0, 0x0000038c, 0, }, 30388358ab0SBenjamin Herrenschmidt { XFER_PIO_1, 0x0000020a, 0, }, 30488358ab0SBenjamin Herrenschmidt { XFER_PIO_2, 0x00000127, 0, }, 30588358ab0SBenjamin Herrenschmidt { XFER_PIO_3, 0x000000c6, 0, }, 30688358ab0SBenjamin Herrenschmidt { XFER_PIO_4, 0x00000065, 0, }, 30788358ab0SBenjamin Herrenschmidt { XFER_MW_DMA_0, 0x00084000, 0, }, 30888358ab0SBenjamin Herrenschmidt { XFER_MW_DMA_1, 0x00029800, 0, }, 30988358ab0SBenjamin Herrenschmidt { XFER_MW_DMA_2, 0x00019400, 0, }, 31088358ab0SBenjamin Herrenschmidt { XFER_UDMA_0, 0x19100000, 0, }, 31188358ab0SBenjamin Herrenschmidt { XFER_UDMA_1, 0x14d00000, 0, }, 31288358ab0SBenjamin Herrenschmidt { XFER_UDMA_2, 0x10900000, 0, }, 31388358ab0SBenjamin Herrenschmidt { XFER_UDMA_3, 0x0c700000, 0, }, 31488358ab0SBenjamin Herrenschmidt { XFER_UDMA_4, 0x0c500000, 0, }, 31588358ab0SBenjamin Herrenschmidt { -1, 0, 0 } 31688358ab0SBenjamin Herrenschmidt }; 31788358ab0SBenjamin Herrenschmidt 31888358ab0SBenjamin Herrenschmidt static const struct pata_macio_timing pata_macio_kauai_timings[] = { 31988358ab0SBenjamin Herrenschmidt { XFER_PIO_0, 0x08000a92, 0, }, 32088358ab0SBenjamin Herrenschmidt { XFER_PIO_1, 0x0800060f, 0, }, 32188358ab0SBenjamin Herrenschmidt { XFER_PIO_2, 0x0800038b, 0, }, 32288358ab0SBenjamin Herrenschmidt { XFER_PIO_3, 0x05000249, 0, }, 32388358ab0SBenjamin Herrenschmidt { XFER_PIO_4, 0x04000148, 0, }, 32488358ab0SBenjamin Herrenschmidt { XFER_MW_DMA_0, 0x00618000, 0, }, 32588358ab0SBenjamin Herrenschmidt { XFER_MW_DMA_1, 0x00209000, 0, }, 32688358ab0SBenjamin Herrenschmidt { XFER_MW_DMA_2, 0x00148000, 0, }, 32788358ab0SBenjamin Herrenschmidt { XFER_UDMA_0, 0, 0x000070c1, }, 32888358ab0SBenjamin Herrenschmidt { XFER_UDMA_1, 0, 0x00005d81, }, 32988358ab0SBenjamin Herrenschmidt { XFER_UDMA_2, 0, 0x00004a61, }, 33088358ab0SBenjamin Herrenschmidt { XFER_UDMA_3, 0, 0x00003a51, }, 33188358ab0SBenjamin Herrenschmidt { XFER_UDMA_4, 0, 0x00002a31, }, 33288358ab0SBenjamin Herrenschmidt { XFER_UDMA_5, 0, 0x00002921, }, 33388358ab0SBenjamin Herrenschmidt { -1, 0, 0 } 33488358ab0SBenjamin Herrenschmidt }; 33588358ab0SBenjamin Herrenschmidt 33688358ab0SBenjamin Herrenschmidt static const struct pata_macio_timing pata_macio_shasta_timings[] = { 33788358ab0SBenjamin Herrenschmidt { XFER_PIO_0, 0x0a000c97, 0, }, 33888358ab0SBenjamin Herrenschmidt { XFER_PIO_1, 0x07000712, 0, }, 33988358ab0SBenjamin Herrenschmidt { XFER_PIO_2, 0x040003cd, 0, }, 34088358ab0SBenjamin Herrenschmidt { XFER_PIO_3, 0x0500028b, 0, }, 34188358ab0SBenjamin Herrenschmidt { XFER_PIO_4, 0x0400010a, 0, }, 34288358ab0SBenjamin Herrenschmidt { XFER_MW_DMA_0, 0x00820800, 0, }, 34388358ab0SBenjamin Herrenschmidt { XFER_MW_DMA_1, 0x0028b000, 0, }, 34488358ab0SBenjamin Herrenschmidt { XFER_MW_DMA_2, 0x001ca000, 0, }, 34588358ab0SBenjamin Herrenschmidt { XFER_UDMA_0, 0, 0x00035901, }, 34688358ab0SBenjamin Herrenschmidt { XFER_UDMA_1, 0, 0x000348b1, }, 34788358ab0SBenjamin Herrenschmidt { XFER_UDMA_2, 0, 0x00033881, }, 34888358ab0SBenjamin Herrenschmidt { XFER_UDMA_3, 0, 0x00033861, }, 34988358ab0SBenjamin Herrenschmidt { XFER_UDMA_4, 0, 0x00033841, }, 35088358ab0SBenjamin Herrenschmidt { XFER_UDMA_5, 0, 0x00033031, }, 35188358ab0SBenjamin Herrenschmidt { XFER_UDMA_6, 0, 0x00033021, }, 35288358ab0SBenjamin Herrenschmidt { -1, 0, 0 } 35388358ab0SBenjamin Herrenschmidt }; 35488358ab0SBenjamin Herrenschmidt 35588358ab0SBenjamin Herrenschmidt static const struct pata_macio_timing *pata_macio_find_timing( 35688358ab0SBenjamin Herrenschmidt struct pata_macio_priv *priv, 35788358ab0SBenjamin Herrenschmidt int mode) 35888358ab0SBenjamin Herrenschmidt { 35988358ab0SBenjamin Herrenschmidt int i; 36088358ab0SBenjamin Herrenschmidt 36188358ab0SBenjamin Herrenschmidt for (i = 0; priv->timings[i].mode > 0; i++) { 36288358ab0SBenjamin Herrenschmidt if (priv->timings[i].mode == mode) 36388358ab0SBenjamin Herrenschmidt return &priv->timings[i]; 36488358ab0SBenjamin Herrenschmidt } 36588358ab0SBenjamin Herrenschmidt return NULL; 36688358ab0SBenjamin Herrenschmidt } 36788358ab0SBenjamin Herrenschmidt 36888358ab0SBenjamin Herrenschmidt 36988358ab0SBenjamin Herrenschmidt static void pata_macio_apply_timings(struct ata_port *ap, unsigned int device) 37088358ab0SBenjamin Herrenschmidt { 37188358ab0SBenjamin Herrenschmidt struct pata_macio_priv *priv = ap->private_data; 37288358ab0SBenjamin Herrenschmidt void __iomem *rbase = ap->ioaddr.cmd_addr; 37388358ab0SBenjamin Herrenschmidt 37488358ab0SBenjamin Herrenschmidt if (priv->kind == controller_sh_ata6 || 37588358ab0SBenjamin Herrenschmidt priv->kind == controller_un_ata6 || 37688358ab0SBenjamin Herrenschmidt priv->kind == controller_k2_ata6) { 37788358ab0SBenjamin Herrenschmidt writel(priv->treg[device][0], rbase + IDE_KAUAI_PIO_CONFIG); 37888358ab0SBenjamin Herrenschmidt writel(priv->treg[device][1], rbase + IDE_KAUAI_ULTRA_CONFIG); 37988358ab0SBenjamin Herrenschmidt } else 38088358ab0SBenjamin Herrenschmidt writel(priv->treg[device][0], rbase + IDE_TIMING_CONFIG); 38188358ab0SBenjamin Herrenschmidt } 38288358ab0SBenjamin Herrenschmidt 38388358ab0SBenjamin Herrenschmidt static void pata_macio_dev_select(struct ata_port *ap, unsigned int device) 38488358ab0SBenjamin Herrenschmidt { 38588358ab0SBenjamin Herrenschmidt ata_sff_dev_select(ap, device); 38688358ab0SBenjamin Herrenschmidt 38788358ab0SBenjamin Herrenschmidt /* Apply timings */ 38888358ab0SBenjamin Herrenschmidt pata_macio_apply_timings(ap, device); 38988358ab0SBenjamin Herrenschmidt } 39088358ab0SBenjamin Herrenschmidt 39188358ab0SBenjamin Herrenschmidt static void pata_macio_set_timings(struct ata_port *ap, 39288358ab0SBenjamin Herrenschmidt struct ata_device *adev) 39388358ab0SBenjamin Herrenschmidt { 39488358ab0SBenjamin Herrenschmidt struct pata_macio_priv *priv = ap->private_data; 39588358ab0SBenjamin Herrenschmidt const struct pata_macio_timing *t; 39688358ab0SBenjamin Herrenschmidt 39788358ab0SBenjamin Herrenschmidt dev_dbg(priv->dev, "Set timings: DEV=%d,PIO=0x%x (%s),DMA=0x%x (%s)\n", 39888358ab0SBenjamin Herrenschmidt adev->devno, 39988358ab0SBenjamin Herrenschmidt adev->pio_mode, 40088358ab0SBenjamin Herrenschmidt ata_mode_string(ata_xfer_mode2mask(adev->pio_mode)), 40188358ab0SBenjamin Herrenschmidt adev->dma_mode, 40288358ab0SBenjamin Herrenschmidt ata_mode_string(ata_xfer_mode2mask(adev->dma_mode))); 40388358ab0SBenjamin Herrenschmidt 40488358ab0SBenjamin Herrenschmidt /* First clear timings */ 40588358ab0SBenjamin Herrenschmidt priv->treg[adev->devno][0] = priv->treg[adev->devno][1] = 0; 40688358ab0SBenjamin Herrenschmidt 40788358ab0SBenjamin Herrenschmidt /* Now get the PIO timings */ 40888358ab0SBenjamin Herrenschmidt t = pata_macio_find_timing(priv, adev->pio_mode); 40988358ab0SBenjamin Herrenschmidt if (t == NULL) { 41088358ab0SBenjamin Herrenschmidt dev_warn(priv->dev, "Invalid PIO timing requested: 0x%x\n", 41188358ab0SBenjamin Herrenschmidt adev->pio_mode); 41288358ab0SBenjamin Herrenschmidt t = pata_macio_find_timing(priv, XFER_PIO_0); 41388358ab0SBenjamin Herrenschmidt } 41488358ab0SBenjamin Herrenschmidt BUG_ON(t == NULL); 41588358ab0SBenjamin Herrenschmidt 41688358ab0SBenjamin Herrenschmidt /* PIO timings only ever use the first treg */ 41788358ab0SBenjamin Herrenschmidt priv->treg[adev->devno][0] |= t->reg1; 41888358ab0SBenjamin Herrenschmidt 41988358ab0SBenjamin Herrenschmidt /* Now get DMA timings */ 42088358ab0SBenjamin Herrenschmidt t = pata_macio_find_timing(priv, adev->dma_mode); 42188358ab0SBenjamin Herrenschmidt if (t == NULL || (t->reg1 == 0 && t->reg2 == 0)) { 42288358ab0SBenjamin Herrenschmidt dev_dbg(priv->dev, "DMA timing not set yet, using MW_DMA_0\n"); 42388358ab0SBenjamin Herrenschmidt t = pata_macio_find_timing(priv, XFER_MW_DMA_0); 42488358ab0SBenjamin Herrenschmidt } 42588358ab0SBenjamin Herrenschmidt BUG_ON(t == NULL); 42688358ab0SBenjamin Herrenschmidt 42788358ab0SBenjamin Herrenschmidt /* DMA timings can use both tregs */ 42888358ab0SBenjamin Herrenschmidt priv->treg[adev->devno][0] |= t->reg1; 42988358ab0SBenjamin Herrenschmidt priv->treg[adev->devno][1] |= t->reg2; 43088358ab0SBenjamin Herrenschmidt 43188358ab0SBenjamin Herrenschmidt dev_dbg(priv->dev, " -> %08x %08x\n", 43288358ab0SBenjamin Herrenschmidt priv->treg[adev->devno][0], 43388358ab0SBenjamin Herrenschmidt priv->treg[adev->devno][1]); 43488358ab0SBenjamin Herrenschmidt 43588358ab0SBenjamin Herrenschmidt /* Apply to hardware */ 43688358ab0SBenjamin Herrenschmidt pata_macio_apply_timings(ap, adev->devno); 43788358ab0SBenjamin Herrenschmidt } 43888358ab0SBenjamin Herrenschmidt 43988358ab0SBenjamin Herrenschmidt /* 44088358ab0SBenjamin Herrenschmidt * Blast some well known "safe" values to the timing registers at init or 44188358ab0SBenjamin Herrenschmidt * wakeup from sleep time, before we do real calculation 44288358ab0SBenjamin Herrenschmidt */ 44388358ab0SBenjamin Herrenschmidt static void pata_macio_default_timings(struct pata_macio_priv *priv) 44488358ab0SBenjamin Herrenschmidt { 44588358ab0SBenjamin Herrenschmidt unsigned int value, value2 = 0; 44688358ab0SBenjamin Herrenschmidt 44788358ab0SBenjamin Herrenschmidt switch(priv->kind) { 44888358ab0SBenjamin Herrenschmidt case controller_sh_ata6: 44988358ab0SBenjamin Herrenschmidt value = 0x0a820c97; 45088358ab0SBenjamin Herrenschmidt value2 = 0x00033031; 45188358ab0SBenjamin Herrenschmidt break; 45288358ab0SBenjamin Herrenschmidt case controller_un_ata6: 45388358ab0SBenjamin Herrenschmidt case controller_k2_ata6: 45488358ab0SBenjamin Herrenschmidt value = 0x08618a92; 45588358ab0SBenjamin Herrenschmidt value2 = 0x00002921; 45688358ab0SBenjamin Herrenschmidt break; 45788358ab0SBenjamin Herrenschmidt case controller_kl_ata4: 45888358ab0SBenjamin Herrenschmidt value = 0x0008438c; 45988358ab0SBenjamin Herrenschmidt break; 46088358ab0SBenjamin Herrenschmidt case controller_kl_ata3: 46188358ab0SBenjamin Herrenschmidt value = 0x00084526; 46288358ab0SBenjamin Herrenschmidt break; 46388358ab0SBenjamin Herrenschmidt case controller_heathrow: 46488358ab0SBenjamin Herrenschmidt case controller_ohare: 46588358ab0SBenjamin Herrenschmidt default: 46688358ab0SBenjamin Herrenschmidt value = 0x00074526; 46788358ab0SBenjamin Herrenschmidt break; 46888358ab0SBenjamin Herrenschmidt } 46988358ab0SBenjamin Herrenschmidt priv->treg[0][0] = priv->treg[1][0] = value; 47088358ab0SBenjamin Herrenschmidt priv->treg[0][1] = priv->treg[1][1] = value2; 47188358ab0SBenjamin Herrenschmidt } 47288358ab0SBenjamin Herrenschmidt 47388358ab0SBenjamin Herrenschmidt static int pata_macio_cable_detect(struct ata_port *ap) 47488358ab0SBenjamin Herrenschmidt { 47588358ab0SBenjamin Herrenschmidt struct pata_macio_priv *priv = ap->private_data; 47688358ab0SBenjamin Herrenschmidt 47788358ab0SBenjamin Herrenschmidt /* Get cable type from device-tree */ 47888358ab0SBenjamin Herrenschmidt if (priv->kind == controller_kl_ata4 || 47988358ab0SBenjamin Herrenschmidt priv->kind == controller_un_ata6 || 48088358ab0SBenjamin Herrenschmidt priv->kind == controller_k2_ata6 || 48188358ab0SBenjamin Herrenschmidt priv->kind == controller_sh_ata6) { 48288358ab0SBenjamin Herrenschmidt const char* cable = of_get_property(priv->node, "cable-type", 48388358ab0SBenjamin Herrenschmidt NULL); 48488358ab0SBenjamin Herrenschmidt struct device_node *root = of_find_node_by_path("/"); 48588358ab0SBenjamin Herrenschmidt const char *model = of_get_property(root, "model", NULL); 48688358ab0SBenjamin Herrenschmidt 487745d51dcSYangtao Li of_node_put(root); 488745d51dcSYangtao Li 48988358ab0SBenjamin Herrenschmidt if (cable && !strncmp(cable, "80-", 3)) { 49088358ab0SBenjamin Herrenschmidt /* Some drives fail to detect 80c cable in PowerBook 49188358ab0SBenjamin Herrenschmidt * These machine use proprietary short IDE cable 49288358ab0SBenjamin Herrenschmidt * anyway 49388358ab0SBenjamin Herrenschmidt */ 49488358ab0SBenjamin Herrenschmidt if (!strncmp(model, "PowerBook", 9)) 49588358ab0SBenjamin Herrenschmidt return ATA_CBL_PATA40_SHORT; 49688358ab0SBenjamin Herrenschmidt else 49788358ab0SBenjamin Herrenschmidt return ATA_CBL_PATA80; 49888358ab0SBenjamin Herrenschmidt } 49988358ab0SBenjamin Herrenschmidt } 50088358ab0SBenjamin Herrenschmidt 50188358ab0SBenjamin Herrenschmidt /* G5's seem to have incorrect cable type in device-tree. 50288358ab0SBenjamin Herrenschmidt * Let's assume they always have a 80 conductor cable, this seem to 50388358ab0SBenjamin Herrenschmidt * be always the case unless the user mucked around 50488358ab0SBenjamin Herrenschmidt */ 50588358ab0SBenjamin Herrenschmidt if (of_device_is_compatible(priv->node, "K2-UATA") || 50688358ab0SBenjamin Herrenschmidt of_device_is_compatible(priv->node, "shasta-ata")) 50788358ab0SBenjamin Herrenschmidt return ATA_CBL_PATA80; 50888358ab0SBenjamin Herrenschmidt 50988358ab0SBenjamin Herrenschmidt /* Anything else is 40 connectors */ 51088358ab0SBenjamin Herrenschmidt return ATA_CBL_PATA40; 51188358ab0SBenjamin Herrenschmidt } 51288358ab0SBenjamin Herrenschmidt 513*95364f36SJiri Slaby static enum ata_completion_errors pata_macio_qc_prep(struct ata_queued_cmd *qc) 51488358ab0SBenjamin Herrenschmidt { 51588358ab0SBenjamin Herrenschmidt unsigned int write = (qc->tf.flags & ATA_TFLAG_WRITE); 51688358ab0SBenjamin Herrenschmidt struct ata_port *ap = qc->ap; 51788358ab0SBenjamin Herrenschmidt struct pata_macio_priv *priv = ap->private_data; 51888358ab0SBenjamin Herrenschmidt struct scatterlist *sg; 51988358ab0SBenjamin Herrenschmidt struct dbdma_cmd *table; 52088358ab0SBenjamin Herrenschmidt unsigned int si, pi; 52188358ab0SBenjamin Herrenschmidt 52288358ab0SBenjamin Herrenschmidt dev_dbgdma(priv->dev, "%s: qc %p flags %lx, write %d dev %d\n", 52388358ab0SBenjamin Herrenschmidt __func__, qc, qc->flags, write, qc->dev->devno); 52488358ab0SBenjamin Herrenschmidt 52588358ab0SBenjamin Herrenschmidt if (!(qc->flags & ATA_QCFLAG_DMAMAP)) 526*95364f36SJiri Slaby return AC_ERR_OK; 52788358ab0SBenjamin Herrenschmidt 52888358ab0SBenjamin Herrenschmidt table = (struct dbdma_cmd *) priv->dma_table_cpu; 52988358ab0SBenjamin Herrenschmidt 53088358ab0SBenjamin Herrenschmidt pi = 0; 53188358ab0SBenjamin Herrenschmidt for_each_sg(qc->sg, sg, qc->n_elem, si) { 53288358ab0SBenjamin Herrenschmidt u32 addr, sg_len, len; 53388358ab0SBenjamin Herrenschmidt 53488358ab0SBenjamin Herrenschmidt /* determine if physical DMA addr spans 64K boundary. 53588358ab0SBenjamin Herrenschmidt * Note h/w doesn't support 64-bit, so we unconditionally 53688358ab0SBenjamin Herrenschmidt * truncate dma_addr_t to u32. 53788358ab0SBenjamin Herrenschmidt */ 53888358ab0SBenjamin Herrenschmidt addr = (u32) sg_dma_address(sg); 53988358ab0SBenjamin Herrenschmidt sg_len = sg_dma_len(sg); 54088358ab0SBenjamin Herrenschmidt 54188358ab0SBenjamin Herrenschmidt while (sg_len) { 54288358ab0SBenjamin Herrenschmidt /* table overflow should never happen */ 54388358ab0SBenjamin Herrenschmidt BUG_ON (pi++ >= MAX_DCMDS); 54488358ab0SBenjamin Herrenschmidt 54588358ab0SBenjamin Herrenschmidt len = (sg_len < MAX_DBDMA_SEG) ? sg_len : MAX_DBDMA_SEG; 546f5718726SDavid Gibson table->command = cpu_to_le16(write ? OUTPUT_MORE: INPUT_MORE); 547f5718726SDavid Gibson table->req_count = cpu_to_le16(len); 548f5718726SDavid Gibson table->phy_addr = cpu_to_le32(addr); 54988358ab0SBenjamin Herrenschmidt table->cmd_dep = 0; 55088358ab0SBenjamin Herrenschmidt table->xfer_status = 0; 55188358ab0SBenjamin Herrenschmidt table->res_count = 0; 55288358ab0SBenjamin Herrenschmidt addr += len; 55388358ab0SBenjamin Herrenschmidt sg_len -= len; 55488358ab0SBenjamin Herrenschmidt ++table; 55588358ab0SBenjamin Herrenschmidt } 55688358ab0SBenjamin Herrenschmidt } 55788358ab0SBenjamin Herrenschmidt 55888358ab0SBenjamin Herrenschmidt /* Should never happen according to Tejun */ 55988358ab0SBenjamin Herrenschmidt BUG_ON(!pi); 56088358ab0SBenjamin Herrenschmidt 56188358ab0SBenjamin Herrenschmidt /* Convert the last command to an input/output */ 56288358ab0SBenjamin Herrenschmidt table--; 563f5718726SDavid Gibson table->command = cpu_to_le16(write ? OUTPUT_LAST: INPUT_LAST); 56488358ab0SBenjamin Herrenschmidt table++; 56588358ab0SBenjamin Herrenschmidt 56688358ab0SBenjamin Herrenschmidt /* Add the stop command to the end of the list */ 56788358ab0SBenjamin Herrenschmidt memset(table, 0, sizeof(struct dbdma_cmd)); 568f5718726SDavid Gibson table->command = cpu_to_le16(DBDMA_STOP); 56988358ab0SBenjamin Herrenschmidt 57088358ab0SBenjamin Herrenschmidt dev_dbgdma(priv->dev, "%s: %d DMA list entries\n", __func__, pi); 571*95364f36SJiri Slaby 572*95364f36SJiri Slaby return AC_ERR_OK; 57388358ab0SBenjamin Herrenschmidt } 57488358ab0SBenjamin Herrenschmidt 57588358ab0SBenjamin Herrenschmidt 57688358ab0SBenjamin Herrenschmidt static void pata_macio_freeze(struct ata_port *ap) 57788358ab0SBenjamin Herrenschmidt { 57888358ab0SBenjamin Herrenschmidt struct dbdma_regs __iomem *dma_regs = ap->ioaddr.bmdma_addr; 57988358ab0SBenjamin Herrenschmidt 58088358ab0SBenjamin Herrenschmidt if (dma_regs) { 58188358ab0SBenjamin Herrenschmidt unsigned int timeout = 1000000; 58288358ab0SBenjamin Herrenschmidt 58388358ab0SBenjamin Herrenschmidt /* Make sure DMA controller is stopped */ 58488358ab0SBenjamin Herrenschmidt writel((RUN|PAUSE|FLUSH|WAKE|DEAD) << 16, &dma_regs->control); 58588358ab0SBenjamin Herrenschmidt while (--timeout && (readl(&dma_regs->status) & RUN)) 58688358ab0SBenjamin Herrenschmidt udelay(1); 58788358ab0SBenjamin Herrenschmidt } 58888358ab0SBenjamin Herrenschmidt 58988358ab0SBenjamin Herrenschmidt ata_sff_freeze(ap); 59088358ab0SBenjamin Herrenschmidt } 59188358ab0SBenjamin Herrenschmidt 59288358ab0SBenjamin Herrenschmidt 59388358ab0SBenjamin Herrenschmidt static void pata_macio_bmdma_setup(struct ata_queued_cmd *qc) 59488358ab0SBenjamin Herrenschmidt { 59588358ab0SBenjamin Herrenschmidt struct ata_port *ap = qc->ap; 59688358ab0SBenjamin Herrenschmidt struct pata_macio_priv *priv = ap->private_data; 59788358ab0SBenjamin Herrenschmidt struct dbdma_regs __iomem *dma_regs = ap->ioaddr.bmdma_addr; 59888358ab0SBenjamin Herrenschmidt int dev = qc->dev->devno; 59988358ab0SBenjamin Herrenschmidt 60088358ab0SBenjamin Herrenschmidt dev_dbgdma(priv->dev, "%s: qc %p\n", __func__, qc); 60188358ab0SBenjamin Herrenschmidt 60288358ab0SBenjamin Herrenschmidt /* Make sure DMA commands updates are visible */ 60388358ab0SBenjamin Herrenschmidt writel(priv->dma_table_dma, &dma_regs->cmdptr); 60488358ab0SBenjamin Herrenschmidt 60588358ab0SBenjamin Herrenschmidt /* On KeyLargo 66Mhz cell, we need to add 60ns to wrDataSetup on 60688358ab0SBenjamin Herrenschmidt * UDMA reads 60788358ab0SBenjamin Herrenschmidt */ 60888358ab0SBenjamin Herrenschmidt if (priv->kind == controller_kl_ata4 && 60988358ab0SBenjamin Herrenschmidt (priv->treg[dev][0] & TR_66_UDMA_EN)) { 61088358ab0SBenjamin Herrenschmidt void __iomem *rbase = ap->ioaddr.cmd_addr; 61188358ab0SBenjamin Herrenschmidt u32 reg = priv->treg[dev][0]; 61288358ab0SBenjamin Herrenschmidt 61388358ab0SBenjamin Herrenschmidt if (!(qc->tf.flags & ATA_TFLAG_WRITE)) 61488358ab0SBenjamin Herrenschmidt reg += 0x00800000; 61588358ab0SBenjamin Herrenschmidt writel(reg, rbase + IDE_TIMING_CONFIG); 61688358ab0SBenjamin Herrenschmidt } 61788358ab0SBenjamin Herrenschmidt 61888358ab0SBenjamin Herrenschmidt /* issue r/w command */ 61988358ab0SBenjamin Herrenschmidt ap->ops->sff_exec_command(ap, &qc->tf); 62088358ab0SBenjamin Herrenschmidt } 62188358ab0SBenjamin Herrenschmidt 62288358ab0SBenjamin Herrenschmidt static void pata_macio_bmdma_start(struct ata_queued_cmd *qc) 62388358ab0SBenjamin Herrenschmidt { 62488358ab0SBenjamin Herrenschmidt struct ata_port *ap = qc->ap; 62588358ab0SBenjamin Herrenschmidt struct pata_macio_priv *priv = ap->private_data; 62688358ab0SBenjamin Herrenschmidt struct dbdma_regs __iomem *dma_regs = ap->ioaddr.bmdma_addr; 62788358ab0SBenjamin Herrenschmidt 62888358ab0SBenjamin Herrenschmidt dev_dbgdma(priv->dev, "%s: qc %p\n", __func__, qc); 62988358ab0SBenjamin Herrenschmidt 63088358ab0SBenjamin Herrenschmidt writel((RUN << 16) | RUN, &dma_regs->control); 63188358ab0SBenjamin Herrenschmidt /* Make sure it gets to the controller right now */ 63288358ab0SBenjamin Herrenschmidt (void)readl(&dma_regs->control); 63388358ab0SBenjamin Herrenschmidt } 63488358ab0SBenjamin Herrenschmidt 63588358ab0SBenjamin Herrenschmidt static void pata_macio_bmdma_stop(struct ata_queued_cmd *qc) 63688358ab0SBenjamin Herrenschmidt { 63788358ab0SBenjamin Herrenschmidt struct ata_port *ap = qc->ap; 63888358ab0SBenjamin Herrenschmidt struct pata_macio_priv *priv = ap->private_data; 63988358ab0SBenjamin Herrenschmidt struct dbdma_regs __iomem *dma_regs = ap->ioaddr.bmdma_addr; 64088358ab0SBenjamin Herrenschmidt unsigned int timeout = 1000000; 64188358ab0SBenjamin Herrenschmidt 64288358ab0SBenjamin Herrenschmidt dev_dbgdma(priv->dev, "%s: qc %p\n", __func__, qc); 64388358ab0SBenjamin Herrenschmidt 64488358ab0SBenjamin Herrenschmidt /* Stop the DMA engine and wait for it to full halt */ 64588358ab0SBenjamin Herrenschmidt writel (((RUN|WAKE|DEAD) << 16), &dma_regs->control); 64688358ab0SBenjamin Herrenschmidt while (--timeout && (readl(&dma_regs->status) & RUN)) 64788358ab0SBenjamin Herrenschmidt udelay(1); 64888358ab0SBenjamin Herrenschmidt } 64988358ab0SBenjamin Herrenschmidt 65088358ab0SBenjamin Herrenschmidt static u8 pata_macio_bmdma_status(struct ata_port *ap) 65188358ab0SBenjamin Herrenschmidt { 65288358ab0SBenjamin Herrenschmidt struct pata_macio_priv *priv = ap->private_data; 65388358ab0SBenjamin Herrenschmidt struct dbdma_regs __iomem *dma_regs = ap->ioaddr.bmdma_addr; 65488358ab0SBenjamin Herrenschmidt u32 dstat, rstat = ATA_DMA_INTR; 65588358ab0SBenjamin Herrenschmidt unsigned long timeout = 0; 65688358ab0SBenjamin Herrenschmidt 65788358ab0SBenjamin Herrenschmidt dstat = readl(&dma_regs->status); 65888358ab0SBenjamin Herrenschmidt 65988358ab0SBenjamin Herrenschmidt dev_dbgdma(priv->dev, "%s: dstat=%x\n", __func__, dstat); 66088358ab0SBenjamin Herrenschmidt 66188358ab0SBenjamin Herrenschmidt /* We have two things to deal with here: 66288358ab0SBenjamin Herrenschmidt * 66388358ab0SBenjamin Herrenschmidt * - The dbdma won't stop if the command was started 66488358ab0SBenjamin Herrenschmidt * but completed with an error without transferring all 66588358ab0SBenjamin Herrenschmidt * datas. This happens when bad blocks are met during 66688358ab0SBenjamin Herrenschmidt * a multi-block transfer. 66788358ab0SBenjamin Herrenschmidt * 66888358ab0SBenjamin Herrenschmidt * - The dbdma fifo hasn't yet finished flushing to 66988358ab0SBenjamin Herrenschmidt * to system memory when the disk interrupt occurs. 67088358ab0SBenjamin Herrenschmidt * 67188358ab0SBenjamin Herrenschmidt */ 67288358ab0SBenjamin Herrenschmidt 67388358ab0SBenjamin Herrenschmidt /* First check for errors */ 67488358ab0SBenjamin Herrenschmidt if ((dstat & (RUN|DEAD)) != RUN) 67588358ab0SBenjamin Herrenschmidt rstat |= ATA_DMA_ERR; 67688358ab0SBenjamin Herrenschmidt 67788358ab0SBenjamin Herrenschmidt /* If ACTIVE is cleared, the STOP command has been hit and 67888358ab0SBenjamin Herrenschmidt * the transfer is complete. If not, we have to flush the 67988358ab0SBenjamin Herrenschmidt * channel. 68088358ab0SBenjamin Herrenschmidt */ 68188358ab0SBenjamin Herrenschmidt if ((dstat & ACTIVE) == 0) 68288358ab0SBenjamin Herrenschmidt return rstat; 68388358ab0SBenjamin Herrenschmidt 68488358ab0SBenjamin Herrenschmidt dev_dbgdma(priv->dev, "%s: DMA still active, flushing...\n", __func__); 68588358ab0SBenjamin Herrenschmidt 68688358ab0SBenjamin Herrenschmidt /* If dbdma didn't execute the STOP command yet, the 68788358ab0SBenjamin Herrenschmidt * active bit is still set. We consider that we aren't 68888358ab0SBenjamin Herrenschmidt * sharing interrupts (which is hopefully the case with 68988358ab0SBenjamin Herrenschmidt * those controllers) and so we just try to flush the 69088358ab0SBenjamin Herrenschmidt * channel for pending data in the fifo 69188358ab0SBenjamin Herrenschmidt */ 69288358ab0SBenjamin Herrenschmidt udelay(1); 69388358ab0SBenjamin Herrenschmidt writel((FLUSH << 16) | FLUSH, &dma_regs->control); 69488358ab0SBenjamin Herrenschmidt for (;;) { 69588358ab0SBenjamin Herrenschmidt udelay(1); 69688358ab0SBenjamin Herrenschmidt dstat = readl(&dma_regs->status); 69788358ab0SBenjamin Herrenschmidt if ((dstat & FLUSH) == 0) 69888358ab0SBenjamin Herrenschmidt break; 69988358ab0SBenjamin Herrenschmidt if (++timeout > 1000) { 70088358ab0SBenjamin Herrenschmidt dev_warn(priv->dev, "timeout flushing DMA\n"); 70188358ab0SBenjamin Herrenschmidt rstat |= ATA_DMA_ERR; 70288358ab0SBenjamin Herrenschmidt break; 70388358ab0SBenjamin Herrenschmidt } 70488358ab0SBenjamin Herrenschmidt } 70588358ab0SBenjamin Herrenschmidt return rstat; 70688358ab0SBenjamin Herrenschmidt } 70788358ab0SBenjamin Herrenschmidt 70888358ab0SBenjamin Herrenschmidt /* port_start is when we allocate the DMA command list */ 70988358ab0SBenjamin Herrenschmidt static int pata_macio_port_start(struct ata_port *ap) 71088358ab0SBenjamin Herrenschmidt { 71188358ab0SBenjamin Herrenschmidt struct pata_macio_priv *priv = ap->private_data; 71288358ab0SBenjamin Herrenschmidt 71388358ab0SBenjamin Herrenschmidt if (ap->ioaddr.bmdma_addr == NULL) 71488358ab0SBenjamin Herrenschmidt return 0; 71588358ab0SBenjamin Herrenschmidt 71688358ab0SBenjamin Herrenschmidt /* Allocate space for the DBDMA commands. 71788358ab0SBenjamin Herrenschmidt * 71888358ab0SBenjamin Herrenschmidt * The +2 is +1 for the stop command and +1 to allow for 71988358ab0SBenjamin Herrenschmidt * aligning the start address to a multiple of 16 bytes. 72088358ab0SBenjamin Herrenschmidt */ 72188358ab0SBenjamin Herrenschmidt priv->dma_table_cpu = 72288358ab0SBenjamin Herrenschmidt dmam_alloc_coherent(priv->dev, 72388358ab0SBenjamin Herrenschmidt (MAX_DCMDS + 2) * sizeof(struct dbdma_cmd), 72488358ab0SBenjamin Herrenschmidt &priv->dma_table_dma, GFP_KERNEL); 72588358ab0SBenjamin Herrenschmidt if (priv->dma_table_cpu == NULL) { 72688358ab0SBenjamin Herrenschmidt dev_err(priv->dev, "Unable to allocate DMA command list\n"); 72788358ab0SBenjamin Herrenschmidt ap->ioaddr.bmdma_addr = NULL; 728c7087652STejun Heo ap->mwdma_mask = 0; 729c7087652STejun Heo ap->udma_mask = 0; 73088358ab0SBenjamin Herrenschmidt } 73188358ab0SBenjamin Herrenschmidt return 0; 73288358ab0SBenjamin Herrenschmidt } 73388358ab0SBenjamin Herrenschmidt 73488358ab0SBenjamin Herrenschmidt static void pata_macio_irq_clear(struct ata_port *ap) 73588358ab0SBenjamin Herrenschmidt { 73688358ab0SBenjamin Herrenschmidt struct pata_macio_priv *priv = ap->private_data; 73788358ab0SBenjamin Herrenschmidt 73888358ab0SBenjamin Herrenschmidt /* Nothing to do here */ 73988358ab0SBenjamin Herrenschmidt 74088358ab0SBenjamin Herrenschmidt dev_dbgdma(priv->dev, "%s\n", __func__); 74188358ab0SBenjamin Herrenschmidt } 74288358ab0SBenjamin Herrenschmidt 74388358ab0SBenjamin Herrenschmidt static void pata_macio_reset_hw(struct pata_macio_priv *priv, int resume) 74488358ab0SBenjamin Herrenschmidt { 74588358ab0SBenjamin Herrenschmidt dev_dbg(priv->dev, "Enabling & resetting... \n"); 74688358ab0SBenjamin Herrenschmidt 74788358ab0SBenjamin Herrenschmidt if (priv->mediabay) 74888358ab0SBenjamin Herrenschmidt return; 74988358ab0SBenjamin Herrenschmidt 75088358ab0SBenjamin Herrenschmidt if (priv->kind == controller_ohare && !resume) { 75188358ab0SBenjamin Herrenschmidt /* The code below is having trouble on some ohare machines 75288358ab0SBenjamin Herrenschmidt * (timing related ?). Until I can put my hand on one of these 75388358ab0SBenjamin Herrenschmidt * units, I keep the old way 75488358ab0SBenjamin Herrenschmidt */ 75588358ab0SBenjamin Herrenschmidt ppc_md.feature_call(PMAC_FTR_IDE_ENABLE, priv->node, 0, 1); 75688358ab0SBenjamin Herrenschmidt } else { 75788358ab0SBenjamin Herrenschmidt int rc; 75888358ab0SBenjamin Herrenschmidt 75988358ab0SBenjamin Herrenschmidt /* Reset and enable controller */ 76088358ab0SBenjamin Herrenschmidt rc = ppc_md.feature_call(PMAC_FTR_IDE_RESET, 76188358ab0SBenjamin Herrenschmidt priv->node, priv->aapl_bus_id, 1); 76288358ab0SBenjamin Herrenschmidt ppc_md.feature_call(PMAC_FTR_IDE_ENABLE, 76388358ab0SBenjamin Herrenschmidt priv->node, priv->aapl_bus_id, 1); 76488358ab0SBenjamin Herrenschmidt msleep(10); 76588358ab0SBenjamin Herrenschmidt /* Only bother waiting if there's a reset control */ 76688358ab0SBenjamin Herrenschmidt if (rc == 0) { 76788358ab0SBenjamin Herrenschmidt ppc_md.feature_call(PMAC_FTR_IDE_RESET, 76888358ab0SBenjamin Herrenschmidt priv->node, priv->aapl_bus_id, 0); 76988358ab0SBenjamin Herrenschmidt msleep(IDE_WAKEUP_DELAY_MS); 77088358ab0SBenjamin Herrenschmidt } 77188358ab0SBenjamin Herrenschmidt } 77288358ab0SBenjamin Herrenschmidt 77388358ab0SBenjamin Herrenschmidt /* If resuming a PCI device, restore the config space here */ 77488358ab0SBenjamin Herrenschmidt if (priv->pdev && resume) { 77588358ab0SBenjamin Herrenschmidt int rc; 77688358ab0SBenjamin Herrenschmidt 77788358ab0SBenjamin Herrenschmidt pci_restore_state(priv->pdev); 77888358ab0SBenjamin Herrenschmidt rc = pcim_enable_device(priv->pdev); 77988358ab0SBenjamin Herrenschmidt if (rc) 780a44fec1fSJoe Perches dev_err(&priv->pdev->dev, 781a44fec1fSJoe Perches "Failed to enable device after resume (%d)\n", 782a44fec1fSJoe Perches rc); 78388358ab0SBenjamin Herrenschmidt else 78488358ab0SBenjamin Herrenschmidt pci_set_master(priv->pdev); 78588358ab0SBenjamin Herrenschmidt } 78688358ab0SBenjamin Herrenschmidt 78788358ab0SBenjamin Herrenschmidt /* On Kauai, initialize the FCR. We don't perform a reset, doesn't really 78888358ab0SBenjamin Herrenschmidt * seem necessary and speeds up the boot process 78988358ab0SBenjamin Herrenschmidt */ 79088358ab0SBenjamin Herrenschmidt if (priv->kauai_fcr) 79188358ab0SBenjamin Herrenschmidt writel(KAUAI_FCR_UATA_MAGIC | 79288358ab0SBenjamin Herrenschmidt KAUAI_FCR_UATA_RESET_N | 79388358ab0SBenjamin Herrenschmidt KAUAI_FCR_UATA_ENABLE, priv->kauai_fcr); 79488358ab0SBenjamin Herrenschmidt } 79588358ab0SBenjamin Herrenschmidt 79688358ab0SBenjamin Herrenschmidt /* Hook the standard slave config to fixup some HW related alignment 79788358ab0SBenjamin Herrenschmidt * restrictions 79888358ab0SBenjamin Herrenschmidt */ 79988358ab0SBenjamin Herrenschmidt static int pata_macio_slave_config(struct scsi_device *sdev) 80088358ab0SBenjamin Herrenschmidt { 80188358ab0SBenjamin Herrenschmidt struct ata_port *ap = ata_shost_to_port(sdev->host); 80288358ab0SBenjamin Herrenschmidt struct pata_macio_priv *priv = ap->private_data; 80388358ab0SBenjamin Herrenschmidt struct ata_device *dev; 80488358ab0SBenjamin Herrenschmidt u16 cmd; 80588358ab0SBenjamin Herrenschmidt int rc; 80688358ab0SBenjamin Herrenschmidt 80788358ab0SBenjamin Herrenschmidt /* First call original */ 80888358ab0SBenjamin Herrenschmidt rc = ata_scsi_slave_config(sdev); 80988358ab0SBenjamin Herrenschmidt if (rc) 81088358ab0SBenjamin Herrenschmidt return rc; 81188358ab0SBenjamin Herrenschmidt 81288358ab0SBenjamin Herrenschmidt /* This is lifted from sata_nv */ 81388358ab0SBenjamin Herrenschmidt dev = &ap->link.device[sdev->id]; 81488358ab0SBenjamin Herrenschmidt 81588358ab0SBenjamin Herrenschmidt /* OHare has issues with non cache aligned DMA on some chipsets */ 81688358ab0SBenjamin Herrenschmidt if (priv->kind == controller_ohare) { 81788358ab0SBenjamin Herrenschmidt blk_queue_update_dma_alignment(sdev->request_queue, 31); 81888358ab0SBenjamin Herrenschmidt blk_queue_update_dma_pad(sdev->request_queue, 31); 81988358ab0SBenjamin Herrenschmidt 82088358ab0SBenjamin Herrenschmidt /* Tell the world about it */ 821a9a79dfeSJoe Perches ata_dev_info(dev, "OHare alignment limits applied\n"); 82288358ab0SBenjamin Herrenschmidt return 0; 82388358ab0SBenjamin Herrenschmidt } 82488358ab0SBenjamin Herrenschmidt 82588358ab0SBenjamin Herrenschmidt /* We only have issues with ATAPI */ 82688358ab0SBenjamin Herrenschmidt if (dev->class != ATA_DEV_ATAPI) 82788358ab0SBenjamin Herrenschmidt return 0; 82888358ab0SBenjamin Herrenschmidt 82988358ab0SBenjamin Herrenschmidt /* Shasta and K2 seem to have "issues" with reads ... */ 83088358ab0SBenjamin Herrenschmidt if (priv->kind == controller_sh_ata6 || priv->kind == controller_k2_ata6) { 83188358ab0SBenjamin Herrenschmidt /* Allright these are bad, apply restrictions */ 83288358ab0SBenjamin Herrenschmidt blk_queue_update_dma_alignment(sdev->request_queue, 15); 83388358ab0SBenjamin Herrenschmidt blk_queue_update_dma_pad(sdev->request_queue, 15); 83488358ab0SBenjamin Herrenschmidt 83588358ab0SBenjamin Herrenschmidt /* We enable MWI and hack cache line size directly here, this 83688358ab0SBenjamin Herrenschmidt * is specific to this chipset and not normal values, we happen 83788358ab0SBenjamin Herrenschmidt * to somewhat know what we are doing here (which is basically 83888358ab0SBenjamin Herrenschmidt * to do the same Apple does and pray they did not get it wrong :-) 83988358ab0SBenjamin Herrenschmidt */ 84088358ab0SBenjamin Herrenschmidt BUG_ON(!priv->pdev); 84188358ab0SBenjamin Herrenschmidt pci_write_config_byte(priv->pdev, PCI_CACHE_LINE_SIZE, 0x08); 84288358ab0SBenjamin Herrenschmidt pci_read_config_word(priv->pdev, PCI_COMMAND, &cmd); 84388358ab0SBenjamin Herrenschmidt pci_write_config_word(priv->pdev, PCI_COMMAND, 84488358ab0SBenjamin Herrenschmidt cmd | PCI_COMMAND_INVALIDATE); 84588358ab0SBenjamin Herrenschmidt 84688358ab0SBenjamin Herrenschmidt /* Tell the world about it */ 847a9a79dfeSJoe Perches ata_dev_info(dev, "K2/Shasta alignment limits applied\n"); 84888358ab0SBenjamin Herrenschmidt } 84988358ab0SBenjamin Herrenschmidt 85088358ab0SBenjamin Herrenschmidt return 0; 85188358ab0SBenjamin Herrenschmidt } 85288358ab0SBenjamin Herrenschmidt 85358eb8cd5SBartlomiej Zolnierkiewicz #ifdef CONFIG_PM_SLEEP 85488358ab0SBenjamin Herrenschmidt static int pata_macio_do_suspend(struct pata_macio_priv *priv, pm_message_t mesg) 85588358ab0SBenjamin Herrenschmidt { 85688358ab0SBenjamin Herrenschmidt int rc; 85788358ab0SBenjamin Herrenschmidt 85888358ab0SBenjamin Herrenschmidt /* First, core libata suspend to do most of the work */ 85988358ab0SBenjamin Herrenschmidt rc = ata_host_suspend(priv->host, mesg); 86088358ab0SBenjamin Herrenschmidt if (rc) 86188358ab0SBenjamin Herrenschmidt return rc; 86288358ab0SBenjamin Herrenschmidt 86388358ab0SBenjamin Herrenschmidt /* Restore to default timings */ 86488358ab0SBenjamin Herrenschmidt pata_macio_default_timings(priv); 86588358ab0SBenjamin Herrenschmidt 86688358ab0SBenjamin Herrenschmidt /* Mask interrupt. Not strictly necessary but old driver did 86788358ab0SBenjamin Herrenschmidt * it and I'd rather not change that here */ 86888358ab0SBenjamin Herrenschmidt disable_irq(priv->irq); 86988358ab0SBenjamin Herrenschmidt 87088358ab0SBenjamin Herrenschmidt /* The media bay will handle itself just fine */ 87188358ab0SBenjamin Herrenschmidt if (priv->mediabay) 87288358ab0SBenjamin Herrenschmidt return 0; 87388358ab0SBenjamin Herrenschmidt 87488358ab0SBenjamin Herrenschmidt /* Kauai has bus control FCRs directly here */ 87588358ab0SBenjamin Herrenschmidt if (priv->kauai_fcr) { 87688358ab0SBenjamin Herrenschmidt u32 fcr = readl(priv->kauai_fcr); 87788358ab0SBenjamin Herrenschmidt fcr &= ~(KAUAI_FCR_UATA_RESET_N | KAUAI_FCR_UATA_ENABLE); 87888358ab0SBenjamin Herrenschmidt writel(fcr, priv->kauai_fcr); 87988358ab0SBenjamin Herrenschmidt } 88088358ab0SBenjamin Herrenschmidt 88188358ab0SBenjamin Herrenschmidt /* For PCI, save state and disable DMA. No need to call 88288358ab0SBenjamin Herrenschmidt * pci_set_power_state(), the HW doesn't do D states that 88388358ab0SBenjamin Herrenschmidt * way, the platform code will take care of suspending the 88488358ab0SBenjamin Herrenschmidt * ASIC properly 88588358ab0SBenjamin Herrenschmidt */ 88688358ab0SBenjamin Herrenschmidt if (priv->pdev) { 88788358ab0SBenjamin Herrenschmidt pci_save_state(priv->pdev); 88888358ab0SBenjamin Herrenschmidt pci_disable_device(priv->pdev); 88988358ab0SBenjamin Herrenschmidt } 89088358ab0SBenjamin Herrenschmidt 89188358ab0SBenjamin Herrenschmidt /* Disable the bus on older machines and the cell on kauai */ 89288358ab0SBenjamin Herrenschmidt ppc_md.feature_call(PMAC_FTR_IDE_ENABLE, priv->node, 89388358ab0SBenjamin Herrenschmidt priv->aapl_bus_id, 0); 89488358ab0SBenjamin Herrenschmidt 89588358ab0SBenjamin Herrenschmidt return 0; 89688358ab0SBenjamin Herrenschmidt } 89788358ab0SBenjamin Herrenschmidt 89888358ab0SBenjamin Herrenschmidt static int pata_macio_do_resume(struct pata_macio_priv *priv) 89988358ab0SBenjamin Herrenschmidt { 90088358ab0SBenjamin Herrenschmidt /* Reset and re-enable the HW */ 90188358ab0SBenjamin Herrenschmidt pata_macio_reset_hw(priv, 1); 90288358ab0SBenjamin Herrenschmidt 90388358ab0SBenjamin Herrenschmidt /* Sanitize drive timings */ 90488358ab0SBenjamin Herrenschmidt pata_macio_apply_timings(priv->host->ports[0], 0); 90588358ab0SBenjamin Herrenschmidt 90688358ab0SBenjamin Herrenschmidt /* We want our IRQ back ! */ 90788358ab0SBenjamin Herrenschmidt enable_irq(priv->irq); 90888358ab0SBenjamin Herrenschmidt 90988358ab0SBenjamin Herrenschmidt /* Let the libata core take it from there */ 91088358ab0SBenjamin Herrenschmidt ata_host_resume(priv->host); 91188358ab0SBenjamin Herrenschmidt 91288358ab0SBenjamin Herrenschmidt return 0; 91388358ab0SBenjamin Herrenschmidt } 91458eb8cd5SBartlomiej Zolnierkiewicz #endif /* CONFIG_PM_SLEEP */ 91588358ab0SBenjamin Herrenschmidt 91688358ab0SBenjamin Herrenschmidt static struct scsi_host_template pata_macio_sht = { 91788358ab0SBenjamin Herrenschmidt ATA_BASE_SHT(DRV_NAME), 91888358ab0SBenjamin Herrenschmidt .sg_tablesize = MAX_DCMDS, 91988358ab0SBenjamin Herrenschmidt /* We may not need that strict one */ 92088358ab0SBenjamin Herrenschmidt .dma_boundary = ATA_DMA_BOUNDARY, 921a8cf59a6SChristoph Hellwig /* Not sure what the real max is but we know it's less than 64K, let's 922a8cf59a6SChristoph Hellwig * use 64K minus 256 923a8cf59a6SChristoph Hellwig */ 924a8cf59a6SChristoph Hellwig .max_segment_size = MAX_DBDMA_SEG, 92588358ab0SBenjamin Herrenschmidt .slave_configure = pata_macio_slave_config, 92688358ab0SBenjamin Herrenschmidt }; 92788358ab0SBenjamin Herrenschmidt 92888358ab0SBenjamin Herrenschmidt static struct ata_port_operations pata_macio_ops = { 9298930ff25STejun Heo .inherits = &ata_bmdma_port_ops, 93088358ab0SBenjamin Herrenschmidt 93188358ab0SBenjamin Herrenschmidt .freeze = pata_macio_freeze, 93288358ab0SBenjamin Herrenschmidt .set_piomode = pata_macio_set_timings, 93388358ab0SBenjamin Herrenschmidt .set_dmamode = pata_macio_set_timings, 93488358ab0SBenjamin Herrenschmidt .cable_detect = pata_macio_cable_detect, 93588358ab0SBenjamin Herrenschmidt .sff_dev_select = pata_macio_dev_select, 93688358ab0SBenjamin Herrenschmidt .qc_prep = pata_macio_qc_prep, 93788358ab0SBenjamin Herrenschmidt .bmdma_setup = pata_macio_bmdma_setup, 93888358ab0SBenjamin Herrenschmidt .bmdma_start = pata_macio_bmdma_start, 93988358ab0SBenjamin Herrenschmidt .bmdma_stop = pata_macio_bmdma_stop, 94088358ab0SBenjamin Herrenschmidt .bmdma_status = pata_macio_bmdma_status, 94188358ab0SBenjamin Herrenschmidt .port_start = pata_macio_port_start, 94288358ab0SBenjamin Herrenschmidt .sff_irq_clear = pata_macio_irq_clear, 94388358ab0SBenjamin Herrenschmidt }; 94488358ab0SBenjamin Herrenschmidt 9450ec24914SGreg Kroah-Hartman static void pata_macio_invariants(struct pata_macio_priv *priv) 94688358ab0SBenjamin Herrenschmidt { 94788358ab0SBenjamin Herrenschmidt const int *bidp; 94888358ab0SBenjamin Herrenschmidt 94988358ab0SBenjamin Herrenschmidt /* Identify the type of controller */ 95088358ab0SBenjamin Herrenschmidt if (of_device_is_compatible(priv->node, "shasta-ata")) { 95188358ab0SBenjamin Herrenschmidt priv->kind = controller_sh_ata6; 95288358ab0SBenjamin Herrenschmidt priv->timings = pata_macio_shasta_timings; 95388358ab0SBenjamin Herrenschmidt } else if (of_device_is_compatible(priv->node, "kauai-ata")) { 95488358ab0SBenjamin Herrenschmidt priv->kind = controller_un_ata6; 95588358ab0SBenjamin Herrenschmidt priv->timings = pata_macio_kauai_timings; 95688358ab0SBenjamin Herrenschmidt } else if (of_device_is_compatible(priv->node, "K2-UATA")) { 95788358ab0SBenjamin Herrenschmidt priv->kind = controller_k2_ata6; 95888358ab0SBenjamin Herrenschmidt priv->timings = pata_macio_kauai_timings; 95988358ab0SBenjamin Herrenschmidt } else if (of_device_is_compatible(priv->node, "keylargo-ata")) { 9606c826b68SRob Herring if (of_node_name_eq(priv->node, "ata-4")) { 96188358ab0SBenjamin Herrenschmidt priv->kind = controller_kl_ata4; 96288358ab0SBenjamin Herrenschmidt priv->timings = pata_macio_kl66_timings; 96388358ab0SBenjamin Herrenschmidt } else { 96488358ab0SBenjamin Herrenschmidt priv->kind = controller_kl_ata3; 96588358ab0SBenjamin Herrenschmidt priv->timings = pata_macio_kl33_timings; 96688358ab0SBenjamin Herrenschmidt } 96788358ab0SBenjamin Herrenschmidt } else if (of_device_is_compatible(priv->node, "heathrow-ata")) { 96888358ab0SBenjamin Herrenschmidt priv->kind = controller_heathrow; 96988358ab0SBenjamin Herrenschmidt priv->timings = pata_macio_heathrow_timings; 97088358ab0SBenjamin Herrenschmidt } else { 97188358ab0SBenjamin Herrenschmidt priv->kind = controller_ohare; 97288358ab0SBenjamin Herrenschmidt priv->timings = pata_macio_ohare_timings; 97388358ab0SBenjamin Herrenschmidt } 97488358ab0SBenjamin Herrenschmidt 97588358ab0SBenjamin Herrenschmidt /* XXX FIXME --- setup priv->mediabay here */ 97688358ab0SBenjamin Herrenschmidt 97788358ab0SBenjamin Herrenschmidt /* Get Apple bus ID (for clock and ASIC control) */ 97888358ab0SBenjamin Herrenschmidt bidp = of_get_property(priv->node, "AAPL,bus-id", NULL); 97988358ab0SBenjamin Herrenschmidt priv->aapl_bus_id = bidp ? *bidp : 0; 98088358ab0SBenjamin Herrenschmidt 98188358ab0SBenjamin Herrenschmidt /* Fixup missing Apple bus ID in case of media-bay */ 98288358ab0SBenjamin Herrenschmidt if (priv->mediabay && bidp == 0) 98388358ab0SBenjamin Herrenschmidt priv->aapl_bus_id = 1; 98488358ab0SBenjamin Herrenschmidt } 98588358ab0SBenjamin Herrenschmidt 9860ec24914SGreg Kroah-Hartman static void pata_macio_setup_ios(struct ata_ioports *ioaddr, 9870ec24914SGreg Kroah-Hartman void __iomem * base, void __iomem * dma) 98888358ab0SBenjamin Herrenschmidt { 98988358ab0SBenjamin Herrenschmidt /* cmd_addr is the base of regs for that port */ 99088358ab0SBenjamin Herrenschmidt ioaddr->cmd_addr = base; 99188358ab0SBenjamin Herrenschmidt 99288358ab0SBenjamin Herrenschmidt /* taskfile registers */ 99388358ab0SBenjamin Herrenschmidt ioaddr->data_addr = base + (ATA_REG_DATA << 4); 99488358ab0SBenjamin Herrenschmidt ioaddr->error_addr = base + (ATA_REG_ERR << 4); 99588358ab0SBenjamin Herrenschmidt ioaddr->feature_addr = base + (ATA_REG_FEATURE << 4); 99688358ab0SBenjamin Herrenschmidt ioaddr->nsect_addr = base + (ATA_REG_NSECT << 4); 99788358ab0SBenjamin Herrenschmidt ioaddr->lbal_addr = base + (ATA_REG_LBAL << 4); 99888358ab0SBenjamin Herrenschmidt ioaddr->lbam_addr = base + (ATA_REG_LBAM << 4); 99988358ab0SBenjamin Herrenschmidt ioaddr->lbah_addr = base + (ATA_REG_LBAH << 4); 100088358ab0SBenjamin Herrenschmidt ioaddr->device_addr = base + (ATA_REG_DEVICE << 4); 100188358ab0SBenjamin Herrenschmidt ioaddr->status_addr = base + (ATA_REG_STATUS << 4); 100288358ab0SBenjamin Herrenschmidt ioaddr->command_addr = base + (ATA_REG_CMD << 4); 100388358ab0SBenjamin Herrenschmidt ioaddr->altstatus_addr = base + 0x160; 100488358ab0SBenjamin Herrenschmidt ioaddr->ctl_addr = base + 0x160; 100588358ab0SBenjamin Herrenschmidt ioaddr->bmdma_addr = dma; 100688358ab0SBenjamin Herrenschmidt } 100788358ab0SBenjamin Herrenschmidt 10080ec24914SGreg Kroah-Hartman static void pmac_macio_calc_timing_masks(struct pata_macio_priv *priv, 100988358ab0SBenjamin Herrenschmidt struct ata_port_info *pinfo) 101088358ab0SBenjamin Herrenschmidt { 101188358ab0SBenjamin Herrenschmidt int i = 0; 101288358ab0SBenjamin Herrenschmidt 101388358ab0SBenjamin Herrenschmidt pinfo->pio_mask = 0; 101488358ab0SBenjamin Herrenschmidt pinfo->mwdma_mask = 0; 101588358ab0SBenjamin Herrenschmidt pinfo->udma_mask = 0; 101688358ab0SBenjamin Herrenschmidt 101788358ab0SBenjamin Herrenschmidt while (priv->timings[i].mode > 0) { 101888358ab0SBenjamin Herrenschmidt unsigned int mask = 1U << (priv->timings[i].mode & 0x0f); 101988358ab0SBenjamin Herrenschmidt switch(priv->timings[i].mode & 0xf0) { 102088358ab0SBenjamin Herrenschmidt case 0x00: /* PIO */ 102188358ab0SBenjamin Herrenschmidt pinfo->pio_mask |= (mask >> 8); 102288358ab0SBenjamin Herrenschmidt break; 102388358ab0SBenjamin Herrenschmidt case 0x20: /* MWDMA */ 102488358ab0SBenjamin Herrenschmidt pinfo->mwdma_mask |= mask; 102588358ab0SBenjamin Herrenschmidt break; 102688358ab0SBenjamin Herrenschmidt case 0x40: /* UDMA */ 102788358ab0SBenjamin Herrenschmidt pinfo->udma_mask |= mask; 102888358ab0SBenjamin Herrenschmidt break; 102988358ab0SBenjamin Herrenschmidt } 103088358ab0SBenjamin Herrenschmidt i++; 103188358ab0SBenjamin Herrenschmidt } 103288358ab0SBenjamin Herrenschmidt dev_dbg(priv->dev, "Supported masks: PIO=%lx, MWDMA=%lx, UDMA=%lx\n", 103388358ab0SBenjamin Herrenschmidt pinfo->pio_mask, pinfo->mwdma_mask, pinfo->udma_mask); 103488358ab0SBenjamin Herrenschmidt } 103588358ab0SBenjamin Herrenschmidt 10360ec24914SGreg Kroah-Hartman static int pata_macio_common_init(struct pata_macio_priv *priv, 103788358ab0SBenjamin Herrenschmidt resource_size_t tfregs, 103888358ab0SBenjamin Herrenschmidt resource_size_t dmaregs, 103988358ab0SBenjamin Herrenschmidt resource_size_t fcregs, 104088358ab0SBenjamin Herrenschmidt unsigned long irq) 104188358ab0SBenjamin Herrenschmidt { 104288358ab0SBenjamin Herrenschmidt struct ata_port_info pinfo; 104388358ab0SBenjamin Herrenschmidt const struct ata_port_info *ppi[] = { &pinfo, NULL }; 104488358ab0SBenjamin Herrenschmidt void __iomem *dma_regs = NULL; 104588358ab0SBenjamin Herrenschmidt 104688358ab0SBenjamin Herrenschmidt /* Fill up privates with various invariants collected from the 104788358ab0SBenjamin Herrenschmidt * device-tree 104888358ab0SBenjamin Herrenschmidt */ 104988358ab0SBenjamin Herrenschmidt pata_macio_invariants(priv); 105088358ab0SBenjamin Herrenschmidt 105188358ab0SBenjamin Herrenschmidt /* Make sure we have sane initial timings in the cache */ 105288358ab0SBenjamin Herrenschmidt pata_macio_default_timings(priv); 105388358ab0SBenjamin Herrenschmidt 105488358ab0SBenjamin Herrenschmidt /* Allocate libata host for 1 port */ 105588358ab0SBenjamin Herrenschmidt memset(&pinfo, 0, sizeof(struct ata_port_info)); 105688358ab0SBenjamin Herrenschmidt pmac_macio_calc_timing_masks(priv, &pinfo); 10579cbe056fSSergei Shtylyov pinfo.flags = ATA_FLAG_SLAVE_POSS; 105888358ab0SBenjamin Herrenschmidt pinfo.port_ops = &pata_macio_ops; 105988358ab0SBenjamin Herrenschmidt pinfo.private_data = priv; 106088358ab0SBenjamin Herrenschmidt 106188358ab0SBenjamin Herrenschmidt priv->host = ata_host_alloc_pinfo(priv->dev, ppi, 1); 106288358ab0SBenjamin Herrenschmidt if (priv->host == NULL) { 106388358ab0SBenjamin Herrenschmidt dev_err(priv->dev, "Failed to allocate ATA port structure\n"); 106488358ab0SBenjamin Herrenschmidt return -ENOMEM; 106588358ab0SBenjamin Herrenschmidt } 106688358ab0SBenjamin Herrenschmidt 106788358ab0SBenjamin Herrenschmidt /* Setup the private data in host too */ 106888358ab0SBenjamin Herrenschmidt priv->host->private_data = priv; 106988358ab0SBenjamin Herrenschmidt 107088358ab0SBenjamin Herrenschmidt /* Map base registers */ 107188358ab0SBenjamin Herrenschmidt priv->tfregs = devm_ioremap(priv->dev, tfregs, 0x100); 107288358ab0SBenjamin Herrenschmidt if (priv->tfregs == NULL) { 107388358ab0SBenjamin Herrenschmidt dev_err(priv->dev, "Failed to map ATA ports\n"); 107488358ab0SBenjamin Herrenschmidt return -ENOMEM; 107588358ab0SBenjamin Herrenschmidt } 107688358ab0SBenjamin Herrenschmidt priv->host->iomap = &priv->tfregs; 107788358ab0SBenjamin Herrenschmidt 107888358ab0SBenjamin Herrenschmidt /* Map DMA regs */ 107988358ab0SBenjamin Herrenschmidt if (dmaregs != 0) { 108088358ab0SBenjamin Herrenschmidt dma_regs = devm_ioremap(priv->dev, dmaregs, 108188358ab0SBenjamin Herrenschmidt sizeof(struct dbdma_regs)); 108288358ab0SBenjamin Herrenschmidt if (dma_regs == NULL) 108388358ab0SBenjamin Herrenschmidt dev_warn(priv->dev, "Failed to map ATA DMA registers\n"); 108488358ab0SBenjamin Herrenschmidt } 108588358ab0SBenjamin Herrenschmidt 108688358ab0SBenjamin Herrenschmidt /* If chip has local feature control, map those regs too */ 108788358ab0SBenjamin Herrenschmidt if (fcregs != 0) { 108888358ab0SBenjamin Herrenschmidt priv->kauai_fcr = devm_ioremap(priv->dev, fcregs, 4); 108988358ab0SBenjamin Herrenschmidt if (priv->kauai_fcr == NULL) { 109088358ab0SBenjamin Herrenschmidt dev_err(priv->dev, "Failed to map ATA FCR register\n"); 109188358ab0SBenjamin Herrenschmidt return -ENOMEM; 109288358ab0SBenjamin Herrenschmidt } 109388358ab0SBenjamin Herrenschmidt } 109488358ab0SBenjamin Herrenschmidt 109588358ab0SBenjamin Herrenschmidt /* Setup port data structure */ 109688358ab0SBenjamin Herrenschmidt pata_macio_setup_ios(&priv->host->ports[0]->ioaddr, 109788358ab0SBenjamin Herrenschmidt priv->tfregs, dma_regs); 109888358ab0SBenjamin Herrenschmidt priv->host->ports[0]->private_data = priv; 109988358ab0SBenjamin Herrenschmidt 110088358ab0SBenjamin Herrenschmidt /* hard-reset the controller */ 110188358ab0SBenjamin Herrenschmidt pata_macio_reset_hw(priv, 0); 110288358ab0SBenjamin Herrenschmidt pata_macio_apply_timings(priv->host->ports[0], 0); 110388358ab0SBenjamin Herrenschmidt 110488358ab0SBenjamin Herrenschmidt /* Enable bus master if necessary */ 110588358ab0SBenjamin Herrenschmidt if (priv->pdev && dma_regs) 110688358ab0SBenjamin Herrenschmidt pci_set_master(priv->pdev); 110788358ab0SBenjamin Herrenschmidt 110888358ab0SBenjamin Herrenschmidt dev_info(priv->dev, "Activating pata-macio chipset %s, Apple bus ID %d\n", 110988358ab0SBenjamin Herrenschmidt macio_ata_names[priv->kind], priv->aapl_bus_id); 111088358ab0SBenjamin Herrenschmidt 111188358ab0SBenjamin Herrenschmidt /* Start it up */ 111288358ab0SBenjamin Herrenschmidt priv->irq = irq; 1113c3b28894STejun Heo return ata_host_activate(priv->host, irq, ata_bmdma_interrupt, 0, 111488358ab0SBenjamin Herrenschmidt &pata_macio_sht); 111588358ab0SBenjamin Herrenschmidt } 111688358ab0SBenjamin Herrenschmidt 11170ec24914SGreg Kroah-Hartman static int pata_macio_attach(struct macio_dev *mdev, 111888358ab0SBenjamin Herrenschmidt const struct of_device_id *match) 111988358ab0SBenjamin Herrenschmidt { 112088358ab0SBenjamin Herrenschmidt struct pata_macio_priv *priv; 112188358ab0SBenjamin Herrenschmidt resource_size_t tfregs, dmaregs = 0; 112288358ab0SBenjamin Herrenschmidt unsigned long irq; 112388358ab0SBenjamin Herrenschmidt int rc; 112488358ab0SBenjamin Herrenschmidt 112588358ab0SBenjamin Herrenschmidt /* Check for broken device-trees */ 112688358ab0SBenjamin Herrenschmidt if (macio_resource_count(mdev) == 0) { 112788358ab0SBenjamin Herrenschmidt dev_err(&mdev->ofdev.dev, 112888358ab0SBenjamin Herrenschmidt "No addresses for controller\n"); 112988358ab0SBenjamin Herrenschmidt return -ENXIO; 113088358ab0SBenjamin Herrenschmidt } 113188358ab0SBenjamin Herrenschmidt 113288358ab0SBenjamin Herrenschmidt /* Enable managed resources */ 113388358ab0SBenjamin Herrenschmidt macio_enable_devres(mdev); 113488358ab0SBenjamin Herrenschmidt 113588358ab0SBenjamin Herrenschmidt /* Allocate and init private data structure */ 113688358ab0SBenjamin Herrenschmidt priv = devm_kzalloc(&mdev->ofdev.dev, 113788358ab0SBenjamin Herrenschmidt sizeof(struct pata_macio_priv), GFP_KERNEL); 11383e342770SMarkus Elfring if (!priv) 113988358ab0SBenjamin Herrenschmidt return -ENOMEM; 11403e342770SMarkus Elfring 114161c7a080SGrant Likely priv->node = of_node_get(mdev->ofdev.dev.of_node); 114288358ab0SBenjamin Herrenschmidt priv->mdev = mdev; 114388358ab0SBenjamin Herrenschmidt priv->dev = &mdev->ofdev.dev; 114488358ab0SBenjamin Herrenschmidt 114588358ab0SBenjamin Herrenschmidt /* Request memory resource for taskfile registers */ 114688358ab0SBenjamin Herrenschmidt if (macio_request_resource(mdev, 0, "pata-macio")) { 114788358ab0SBenjamin Herrenschmidt dev_err(&mdev->ofdev.dev, 114888358ab0SBenjamin Herrenschmidt "Cannot obtain taskfile resource\n"); 114988358ab0SBenjamin Herrenschmidt return -EBUSY; 115088358ab0SBenjamin Herrenschmidt } 115188358ab0SBenjamin Herrenschmidt tfregs = macio_resource_start(mdev, 0); 115288358ab0SBenjamin Herrenschmidt 115388358ab0SBenjamin Herrenschmidt /* Request resources for DMA registers if any */ 115488358ab0SBenjamin Herrenschmidt if (macio_resource_count(mdev) >= 2) { 115588358ab0SBenjamin Herrenschmidt if (macio_request_resource(mdev, 1, "pata-macio-dma")) 115688358ab0SBenjamin Herrenschmidt dev_err(&mdev->ofdev.dev, 115788358ab0SBenjamin Herrenschmidt "Cannot obtain DMA resource\n"); 115888358ab0SBenjamin Herrenschmidt else 115988358ab0SBenjamin Herrenschmidt dmaregs = macio_resource_start(mdev, 1); 116088358ab0SBenjamin Herrenschmidt } 116188358ab0SBenjamin Herrenschmidt 116288358ab0SBenjamin Herrenschmidt /* 116388358ab0SBenjamin Herrenschmidt * Fixup missing IRQ for some old implementations with broken 116488358ab0SBenjamin Herrenschmidt * device-trees. 116588358ab0SBenjamin Herrenschmidt * 116688358ab0SBenjamin Herrenschmidt * This is a bit bogus, it should be fixed in the device-tree itself, 116788358ab0SBenjamin Herrenschmidt * via the existing macio fixups, based on the type of interrupt 116888358ab0SBenjamin Herrenschmidt * controller in the machine. However, I have no test HW for this case, 116988358ab0SBenjamin Herrenschmidt * and this trick works well enough on those old machines... 117088358ab0SBenjamin Herrenschmidt */ 117188358ab0SBenjamin Herrenschmidt if (macio_irq_count(mdev) == 0) { 117288358ab0SBenjamin Herrenschmidt dev_warn(&mdev->ofdev.dev, 117388358ab0SBenjamin Herrenschmidt "No interrupts for controller, using 13\n"); 117488358ab0SBenjamin Herrenschmidt irq = irq_create_mapping(NULL, 13); 117588358ab0SBenjamin Herrenschmidt } else 117688358ab0SBenjamin Herrenschmidt irq = macio_irq(mdev, 0); 117788358ab0SBenjamin Herrenschmidt 117888358ab0SBenjamin Herrenschmidt /* Prevvent media bay callbacks until fully registered */ 117988358ab0SBenjamin Herrenschmidt lock_media_bay(priv->mdev->media_bay); 118088358ab0SBenjamin Herrenschmidt 118188358ab0SBenjamin Herrenschmidt /* Get register addresses and call common initialization */ 118288358ab0SBenjamin Herrenschmidt rc = pata_macio_common_init(priv, 118388358ab0SBenjamin Herrenschmidt tfregs, /* Taskfile regs */ 118488358ab0SBenjamin Herrenschmidt dmaregs, /* DBDMA regs */ 118588358ab0SBenjamin Herrenschmidt 0, /* Feature control */ 118688358ab0SBenjamin Herrenschmidt irq); 118788358ab0SBenjamin Herrenschmidt unlock_media_bay(priv->mdev->media_bay); 118888358ab0SBenjamin Herrenschmidt 118988358ab0SBenjamin Herrenschmidt return rc; 119088358ab0SBenjamin Herrenschmidt } 119188358ab0SBenjamin Herrenschmidt 11920ec24914SGreg Kroah-Hartman static int pata_macio_detach(struct macio_dev *mdev) 119388358ab0SBenjamin Herrenschmidt { 119488358ab0SBenjamin Herrenschmidt struct ata_host *host = macio_get_drvdata(mdev); 119588358ab0SBenjamin Herrenschmidt struct pata_macio_priv *priv = host->private_data; 119688358ab0SBenjamin Herrenschmidt 119788358ab0SBenjamin Herrenschmidt lock_media_bay(priv->mdev->media_bay); 119888358ab0SBenjamin Herrenschmidt 119988358ab0SBenjamin Herrenschmidt /* Make sure the mediabay callback doesn't try to access 120088358ab0SBenjamin Herrenschmidt * dead stuff 120188358ab0SBenjamin Herrenschmidt */ 120288358ab0SBenjamin Herrenschmidt priv->host->private_data = NULL; 120388358ab0SBenjamin Herrenschmidt 120488358ab0SBenjamin Herrenschmidt ata_host_detach(host); 120588358ab0SBenjamin Herrenschmidt 120688358ab0SBenjamin Herrenschmidt unlock_media_bay(priv->mdev->media_bay); 120788358ab0SBenjamin Herrenschmidt 120888358ab0SBenjamin Herrenschmidt return 0; 120988358ab0SBenjamin Herrenschmidt } 121088358ab0SBenjamin Herrenschmidt 121158eb8cd5SBartlomiej Zolnierkiewicz #ifdef CONFIG_PM_SLEEP 121288358ab0SBenjamin Herrenschmidt static int pata_macio_suspend(struct macio_dev *mdev, pm_message_t mesg) 121388358ab0SBenjamin Herrenschmidt { 121488358ab0SBenjamin Herrenschmidt struct ata_host *host = macio_get_drvdata(mdev); 121588358ab0SBenjamin Herrenschmidt 121688358ab0SBenjamin Herrenschmidt return pata_macio_do_suspend(host->private_data, mesg); 121788358ab0SBenjamin Herrenschmidt } 121888358ab0SBenjamin Herrenschmidt 121988358ab0SBenjamin Herrenschmidt static int pata_macio_resume(struct macio_dev *mdev) 122088358ab0SBenjamin Herrenschmidt { 122188358ab0SBenjamin Herrenschmidt struct ata_host *host = macio_get_drvdata(mdev); 122288358ab0SBenjamin Herrenschmidt 122388358ab0SBenjamin Herrenschmidt return pata_macio_do_resume(host->private_data); 122488358ab0SBenjamin Herrenschmidt } 122558eb8cd5SBartlomiej Zolnierkiewicz #endif /* CONFIG_PM_SLEEP */ 122688358ab0SBenjamin Herrenschmidt 122788358ab0SBenjamin Herrenschmidt #ifdef CONFIG_PMAC_MEDIABAY 122888358ab0SBenjamin Herrenschmidt static void pata_macio_mb_event(struct macio_dev* mdev, int mb_state) 122988358ab0SBenjamin Herrenschmidt { 123088358ab0SBenjamin Herrenschmidt struct ata_host *host = macio_get_drvdata(mdev); 123188358ab0SBenjamin Herrenschmidt struct ata_port *ap; 123288358ab0SBenjamin Herrenschmidt struct ata_eh_info *ehi; 123388358ab0SBenjamin Herrenschmidt struct ata_device *dev; 123488358ab0SBenjamin Herrenschmidt unsigned long flags; 123588358ab0SBenjamin Herrenschmidt 123688358ab0SBenjamin Herrenschmidt if (!host || !host->private_data) 123788358ab0SBenjamin Herrenschmidt return; 123888358ab0SBenjamin Herrenschmidt ap = host->ports[0]; 123988358ab0SBenjamin Herrenschmidt spin_lock_irqsave(ap->lock, flags); 124088358ab0SBenjamin Herrenschmidt ehi = &ap->link.eh_info; 124188358ab0SBenjamin Herrenschmidt if (mb_state == MB_CD) { 124288358ab0SBenjamin Herrenschmidt ata_ehi_push_desc(ehi, "mediabay plug"); 124388358ab0SBenjamin Herrenschmidt ata_ehi_hotplugged(ehi); 124488358ab0SBenjamin Herrenschmidt ata_port_freeze(ap); 124588358ab0SBenjamin Herrenschmidt } else { 124688358ab0SBenjamin Herrenschmidt ata_ehi_push_desc(ehi, "mediabay unplug"); 124788358ab0SBenjamin Herrenschmidt ata_for_each_dev(dev, &ap->link, ALL) 124888358ab0SBenjamin Herrenschmidt dev->flags |= ATA_DFLAG_DETACH; 124988358ab0SBenjamin Herrenschmidt ata_port_abort(ap); 125088358ab0SBenjamin Herrenschmidt } 125188358ab0SBenjamin Herrenschmidt spin_unlock_irqrestore(ap->lock, flags); 125288358ab0SBenjamin Herrenschmidt 125388358ab0SBenjamin Herrenschmidt } 125488358ab0SBenjamin Herrenschmidt #endif /* CONFIG_PMAC_MEDIABAY */ 125588358ab0SBenjamin Herrenschmidt 125688358ab0SBenjamin Herrenschmidt 12570ec24914SGreg Kroah-Hartman static int pata_macio_pci_attach(struct pci_dev *pdev, 125888358ab0SBenjamin Herrenschmidt const struct pci_device_id *id) 125988358ab0SBenjamin Herrenschmidt { 126088358ab0SBenjamin Herrenschmidt struct pata_macio_priv *priv; 126188358ab0SBenjamin Herrenschmidt struct device_node *np; 126288358ab0SBenjamin Herrenschmidt resource_size_t rbase; 126388358ab0SBenjamin Herrenschmidt 126488358ab0SBenjamin Herrenschmidt /* We cannot use a MacIO controller without its OF device node */ 126588358ab0SBenjamin Herrenschmidt np = pci_device_to_OF_node(pdev); 126688358ab0SBenjamin Herrenschmidt if (np == NULL) { 126788358ab0SBenjamin Herrenschmidt dev_err(&pdev->dev, 126888358ab0SBenjamin Herrenschmidt "Cannot find OF device node for controller\n"); 126988358ab0SBenjamin Herrenschmidt return -ENODEV; 127088358ab0SBenjamin Herrenschmidt } 127188358ab0SBenjamin Herrenschmidt 127288358ab0SBenjamin Herrenschmidt /* Check that it can be enabled */ 127388358ab0SBenjamin Herrenschmidt if (pcim_enable_device(pdev)) { 127488358ab0SBenjamin Herrenschmidt dev_err(&pdev->dev, 127588358ab0SBenjamin Herrenschmidt "Cannot enable controller PCI device\n"); 127688358ab0SBenjamin Herrenschmidt return -ENXIO; 127788358ab0SBenjamin Herrenschmidt } 127888358ab0SBenjamin Herrenschmidt 127988358ab0SBenjamin Herrenschmidt /* Allocate and init private data structure */ 128088358ab0SBenjamin Herrenschmidt priv = devm_kzalloc(&pdev->dev, 128188358ab0SBenjamin Herrenschmidt sizeof(struct pata_macio_priv), GFP_KERNEL); 12823e342770SMarkus Elfring if (!priv) 128388358ab0SBenjamin Herrenschmidt return -ENOMEM; 12843e342770SMarkus Elfring 128588358ab0SBenjamin Herrenschmidt priv->node = of_node_get(np); 128688358ab0SBenjamin Herrenschmidt priv->pdev = pdev; 128788358ab0SBenjamin Herrenschmidt priv->dev = &pdev->dev; 128888358ab0SBenjamin Herrenschmidt 128988358ab0SBenjamin Herrenschmidt /* Get MMIO regions */ 129088358ab0SBenjamin Herrenschmidt if (pci_request_regions(pdev, "pata-macio")) { 129188358ab0SBenjamin Herrenschmidt dev_err(&pdev->dev, 129288358ab0SBenjamin Herrenschmidt "Cannot obtain PCI resources\n"); 129388358ab0SBenjamin Herrenschmidt return -EBUSY; 129488358ab0SBenjamin Herrenschmidt } 129588358ab0SBenjamin Herrenschmidt 129688358ab0SBenjamin Herrenschmidt /* Get register addresses and call common initialization */ 129788358ab0SBenjamin Herrenschmidt rbase = pci_resource_start(pdev, 0); 129888358ab0SBenjamin Herrenschmidt if (pata_macio_common_init(priv, 129988358ab0SBenjamin Herrenschmidt rbase + 0x2000, /* Taskfile regs */ 130088358ab0SBenjamin Herrenschmidt rbase + 0x1000, /* DBDMA regs */ 130188358ab0SBenjamin Herrenschmidt rbase, /* Feature control */ 130288358ab0SBenjamin Herrenschmidt pdev->irq)) 130388358ab0SBenjamin Herrenschmidt return -ENXIO; 130488358ab0SBenjamin Herrenschmidt 130588358ab0SBenjamin Herrenschmidt return 0; 130688358ab0SBenjamin Herrenschmidt } 130788358ab0SBenjamin Herrenschmidt 13080ec24914SGreg Kroah-Hartman static void pata_macio_pci_detach(struct pci_dev *pdev) 130988358ab0SBenjamin Herrenschmidt { 13100a86e1c8SJingoo Han struct ata_host *host = pci_get_drvdata(pdev); 131188358ab0SBenjamin Herrenschmidt 131288358ab0SBenjamin Herrenschmidt ata_host_detach(host); 131388358ab0SBenjamin Herrenschmidt } 131488358ab0SBenjamin Herrenschmidt 131558eb8cd5SBartlomiej Zolnierkiewicz #ifdef CONFIG_PM_SLEEP 131688358ab0SBenjamin Herrenschmidt static int pata_macio_pci_suspend(struct pci_dev *pdev, pm_message_t mesg) 131788358ab0SBenjamin Herrenschmidt { 13180a86e1c8SJingoo Han struct ata_host *host = pci_get_drvdata(pdev); 131988358ab0SBenjamin Herrenschmidt 132088358ab0SBenjamin Herrenschmidt return pata_macio_do_suspend(host->private_data, mesg); 132188358ab0SBenjamin Herrenschmidt } 132288358ab0SBenjamin Herrenschmidt 132388358ab0SBenjamin Herrenschmidt static int pata_macio_pci_resume(struct pci_dev *pdev) 132488358ab0SBenjamin Herrenschmidt { 13250a86e1c8SJingoo Han struct ata_host *host = pci_get_drvdata(pdev); 132688358ab0SBenjamin Herrenschmidt 132788358ab0SBenjamin Herrenschmidt return pata_macio_do_resume(host->private_data); 132888358ab0SBenjamin Herrenschmidt } 132958eb8cd5SBartlomiej Zolnierkiewicz #endif /* CONFIG_PM_SLEEP */ 133088358ab0SBenjamin Herrenschmidt 1331e3779f6aSBhumika Goyal static const struct of_device_id pata_macio_match[] = 133288358ab0SBenjamin Herrenschmidt { 133388358ab0SBenjamin Herrenschmidt { 133488358ab0SBenjamin Herrenschmidt .name = "IDE", 133588358ab0SBenjamin Herrenschmidt }, 133688358ab0SBenjamin Herrenschmidt { 133788358ab0SBenjamin Herrenschmidt .name = "ATA", 133888358ab0SBenjamin Herrenschmidt }, 133988358ab0SBenjamin Herrenschmidt { 134088358ab0SBenjamin Herrenschmidt .type = "ide", 134188358ab0SBenjamin Herrenschmidt }, 134288358ab0SBenjamin Herrenschmidt { 134388358ab0SBenjamin Herrenschmidt .type = "ata", 134488358ab0SBenjamin Herrenschmidt }, 134588358ab0SBenjamin Herrenschmidt {}, 134688358ab0SBenjamin Herrenschmidt }; 1347469eabb3SLuis de Bethencourt MODULE_DEVICE_TABLE(of, pata_macio_match); 134888358ab0SBenjamin Herrenschmidt 134988358ab0SBenjamin Herrenschmidt static struct macio_driver pata_macio_driver = 135088358ab0SBenjamin Herrenschmidt { 1351c2cdf6abSBenjamin Herrenschmidt .driver = { 135288358ab0SBenjamin Herrenschmidt .name = "pata-macio", 1353c2cdf6abSBenjamin Herrenschmidt .owner = THIS_MODULE, 1354c2cdf6abSBenjamin Herrenschmidt .of_match_table = pata_macio_match, 1355c2cdf6abSBenjamin Herrenschmidt }, 135688358ab0SBenjamin Herrenschmidt .probe = pata_macio_attach, 135788358ab0SBenjamin Herrenschmidt .remove = pata_macio_detach, 135858eb8cd5SBartlomiej Zolnierkiewicz #ifdef CONFIG_PM_SLEEP 135988358ab0SBenjamin Herrenschmidt .suspend = pata_macio_suspend, 136088358ab0SBenjamin Herrenschmidt .resume = pata_macio_resume, 136188358ab0SBenjamin Herrenschmidt #endif 136288358ab0SBenjamin Herrenschmidt #ifdef CONFIG_PMAC_MEDIABAY 136388358ab0SBenjamin Herrenschmidt .mediabay_event = pata_macio_mb_event, 136488358ab0SBenjamin Herrenschmidt #endif 136588358ab0SBenjamin Herrenschmidt }; 136688358ab0SBenjamin Herrenschmidt 136788358ab0SBenjamin Herrenschmidt static const struct pci_device_id pata_macio_pci_match[] = { 136888358ab0SBenjamin Herrenschmidt { PCI_VDEVICE(APPLE, PCI_DEVICE_ID_APPLE_UNI_N_ATA), 0 }, 136988358ab0SBenjamin Herrenschmidt { PCI_VDEVICE(APPLE, PCI_DEVICE_ID_APPLE_IPID_ATA100), 0 }, 137088358ab0SBenjamin Herrenschmidt { PCI_VDEVICE(APPLE, PCI_DEVICE_ID_APPLE_K2_ATA100), 0 }, 137188358ab0SBenjamin Herrenschmidt { PCI_VDEVICE(APPLE, PCI_DEVICE_ID_APPLE_SH_ATA), 0 }, 137288358ab0SBenjamin Herrenschmidt { PCI_VDEVICE(APPLE, PCI_DEVICE_ID_APPLE_IPID2_ATA), 0 }, 137388358ab0SBenjamin Herrenschmidt {}, 137488358ab0SBenjamin Herrenschmidt }; 137588358ab0SBenjamin Herrenschmidt 137688358ab0SBenjamin Herrenschmidt static struct pci_driver pata_macio_pci_driver = { 137788358ab0SBenjamin Herrenschmidt .name = "pata-pci-macio", 137888358ab0SBenjamin Herrenschmidt .id_table = pata_macio_pci_match, 137988358ab0SBenjamin Herrenschmidt .probe = pata_macio_pci_attach, 138088358ab0SBenjamin Herrenschmidt .remove = pata_macio_pci_detach, 138158eb8cd5SBartlomiej Zolnierkiewicz #ifdef CONFIG_PM_SLEEP 138288358ab0SBenjamin Herrenschmidt .suspend = pata_macio_pci_suspend, 138388358ab0SBenjamin Herrenschmidt .resume = pata_macio_pci_resume, 138488358ab0SBenjamin Herrenschmidt #endif 138588358ab0SBenjamin Herrenschmidt .driver = { 138688358ab0SBenjamin Herrenschmidt .owner = THIS_MODULE, 138788358ab0SBenjamin Herrenschmidt }, 138888358ab0SBenjamin Herrenschmidt }; 138988358ab0SBenjamin Herrenschmidt MODULE_DEVICE_TABLE(pci, pata_macio_pci_match); 139088358ab0SBenjamin Herrenschmidt 139188358ab0SBenjamin Herrenschmidt 139288358ab0SBenjamin Herrenschmidt static int __init pata_macio_init(void) 139388358ab0SBenjamin Herrenschmidt { 139488358ab0SBenjamin Herrenschmidt int rc; 139588358ab0SBenjamin Herrenschmidt 139688358ab0SBenjamin Herrenschmidt if (!machine_is(powermac)) 139788358ab0SBenjamin Herrenschmidt return -ENODEV; 139888358ab0SBenjamin Herrenschmidt 139988358ab0SBenjamin Herrenschmidt rc = pci_register_driver(&pata_macio_pci_driver); 140088358ab0SBenjamin Herrenschmidt if (rc) 140188358ab0SBenjamin Herrenschmidt return rc; 140288358ab0SBenjamin Herrenschmidt rc = macio_register_driver(&pata_macio_driver); 140388358ab0SBenjamin Herrenschmidt if (rc) { 140488358ab0SBenjamin Herrenschmidt pci_unregister_driver(&pata_macio_pci_driver); 140588358ab0SBenjamin Herrenschmidt return rc; 140688358ab0SBenjamin Herrenschmidt } 140788358ab0SBenjamin Herrenschmidt return 0; 140888358ab0SBenjamin Herrenschmidt } 140988358ab0SBenjamin Herrenschmidt 141088358ab0SBenjamin Herrenschmidt static void __exit pata_macio_exit(void) 141188358ab0SBenjamin Herrenschmidt { 141288358ab0SBenjamin Herrenschmidt macio_unregister_driver(&pata_macio_driver); 141388358ab0SBenjamin Herrenschmidt pci_unregister_driver(&pata_macio_pci_driver); 141488358ab0SBenjamin Herrenschmidt } 141588358ab0SBenjamin Herrenschmidt 141688358ab0SBenjamin Herrenschmidt module_init(pata_macio_init); 141788358ab0SBenjamin Herrenschmidt module_exit(pata_macio_exit); 141888358ab0SBenjamin Herrenschmidt 141988358ab0SBenjamin Herrenschmidt MODULE_AUTHOR("Benjamin Herrenschmidt"); 142088358ab0SBenjamin Herrenschmidt MODULE_DESCRIPTION("Apple MacIO PATA driver"); 142188358ab0SBenjamin Herrenschmidt MODULE_LICENSE("GPL"); 142288358ab0SBenjamin Herrenschmidt MODULE_VERSION(DRV_VERSION); 1423