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> 24*cf02f71cSRob Herring #include <linux/irqdomain.h> 2588358ab0SBenjamin Herrenschmidt #include <linux/of.h> 265a0e3ad6STejun Heo #include <linux/gfp.h> 27952bbcb0SBjorn Helgaas #include <linux/pci.h> 2888358ab0SBenjamin Herrenschmidt 2988358ab0SBenjamin Herrenschmidt #include <scsi/scsi.h> 3088358ab0SBenjamin Herrenschmidt #include <scsi/scsi_host.h> 3188358ab0SBenjamin Herrenschmidt #include <scsi/scsi_device.h> 3288358ab0SBenjamin Herrenschmidt 3388358ab0SBenjamin Herrenschmidt #include <asm/macio.h> 3488358ab0SBenjamin Herrenschmidt #include <asm/io.h> 3588358ab0SBenjamin Herrenschmidt #include <asm/dbdma.h> 3688358ab0SBenjamin Herrenschmidt #include <asm/machdep.h> 3788358ab0SBenjamin Herrenschmidt #include <asm/pmac_feature.h> 3888358ab0SBenjamin Herrenschmidt #include <asm/mediabay.h> 3988358ab0SBenjamin Herrenschmidt 4088358ab0SBenjamin Herrenschmidt #ifdef DEBUG_DMA 4188358ab0SBenjamin Herrenschmidt #define dev_dbgdma(dev, format, arg...) \ 4288358ab0SBenjamin Herrenschmidt dev_printk(KERN_DEBUG , dev , format , ## arg) 4388358ab0SBenjamin Herrenschmidt #else 4488358ab0SBenjamin Herrenschmidt #define dev_dbgdma(dev, format, arg...) \ 4588358ab0SBenjamin Herrenschmidt ({ if (0) dev_printk(KERN_DEBUG, dev, format, ##arg); 0; }) 4688358ab0SBenjamin Herrenschmidt #endif 4788358ab0SBenjamin Herrenschmidt 4888358ab0SBenjamin Herrenschmidt #define DRV_NAME "pata_macio" 4988358ab0SBenjamin Herrenschmidt #define DRV_VERSION "0.9" 5088358ab0SBenjamin Herrenschmidt 5188358ab0SBenjamin Herrenschmidt /* Models of macio ATA controller */ 5288358ab0SBenjamin Herrenschmidt enum { 5388358ab0SBenjamin Herrenschmidt controller_ohare, /* OHare based */ 5488358ab0SBenjamin Herrenschmidt controller_heathrow, /* Heathrow/Paddington */ 5588358ab0SBenjamin Herrenschmidt controller_kl_ata3, /* KeyLargo ATA-3 */ 5688358ab0SBenjamin Herrenschmidt controller_kl_ata4, /* KeyLargo ATA-4 */ 5788358ab0SBenjamin Herrenschmidt controller_un_ata6, /* UniNorth2 ATA-6 */ 5888358ab0SBenjamin Herrenschmidt controller_k2_ata6, /* K2 ATA-6 */ 5988358ab0SBenjamin Herrenschmidt controller_sh_ata6, /* Shasta ATA-6 */ 6088358ab0SBenjamin Herrenschmidt }; 6188358ab0SBenjamin Herrenschmidt 6288358ab0SBenjamin Herrenschmidt static const char* macio_ata_names[] = { 6388358ab0SBenjamin Herrenschmidt "OHare ATA", /* OHare based */ 6488358ab0SBenjamin Herrenschmidt "Heathrow ATA", /* Heathrow/Paddington */ 6588358ab0SBenjamin Herrenschmidt "KeyLargo ATA-3", /* KeyLargo ATA-3 (MDMA only) */ 6688358ab0SBenjamin Herrenschmidt "KeyLargo ATA-4", /* KeyLargo ATA-4 (UDMA/66) */ 6788358ab0SBenjamin Herrenschmidt "UniNorth ATA-6", /* UniNorth2 ATA-6 (UDMA/100) */ 6888358ab0SBenjamin Herrenschmidt "K2 ATA-6", /* K2 ATA-6 (UDMA/100) */ 6988358ab0SBenjamin Herrenschmidt "Shasta ATA-6", /* Shasta ATA-6 (UDMA/133) */ 7088358ab0SBenjamin Herrenschmidt }; 7188358ab0SBenjamin Herrenschmidt 7288358ab0SBenjamin Herrenschmidt /* 7388358ab0SBenjamin Herrenschmidt * Extra registers, both 32-bit little-endian 7488358ab0SBenjamin Herrenschmidt */ 7588358ab0SBenjamin Herrenschmidt #define IDE_TIMING_CONFIG 0x200 7688358ab0SBenjamin Herrenschmidt #define IDE_INTERRUPT 0x300 7788358ab0SBenjamin Herrenschmidt 7888358ab0SBenjamin Herrenschmidt /* Kauai (U2) ATA has different register setup */ 7988358ab0SBenjamin Herrenschmidt #define IDE_KAUAI_PIO_CONFIG 0x200 8088358ab0SBenjamin Herrenschmidt #define IDE_KAUAI_ULTRA_CONFIG 0x210 8188358ab0SBenjamin Herrenschmidt #define IDE_KAUAI_POLL_CONFIG 0x220 8288358ab0SBenjamin Herrenschmidt 8388358ab0SBenjamin Herrenschmidt /* 8488358ab0SBenjamin Herrenschmidt * Timing configuration register definitions 8588358ab0SBenjamin Herrenschmidt */ 8688358ab0SBenjamin Herrenschmidt 8788358ab0SBenjamin Herrenschmidt /* Number of IDE_SYSCLK_NS ticks, argument is in nanoseconds */ 8888358ab0SBenjamin Herrenschmidt #define SYSCLK_TICKS(t) (((t) + IDE_SYSCLK_NS - 1) / IDE_SYSCLK_NS) 8988358ab0SBenjamin Herrenschmidt #define SYSCLK_TICKS_66(t) (((t) + IDE_SYSCLK_66_NS - 1) / IDE_SYSCLK_66_NS) 9088358ab0SBenjamin Herrenschmidt #define IDE_SYSCLK_NS 30 /* 33Mhz cell */ 9188358ab0SBenjamin Herrenschmidt #define IDE_SYSCLK_66_NS 15 /* 66Mhz cell */ 9288358ab0SBenjamin Herrenschmidt 9388358ab0SBenjamin Herrenschmidt /* 133Mhz cell, found in shasta. 9488358ab0SBenjamin Herrenschmidt * See comments about 100 Mhz Uninorth 2... 9588358ab0SBenjamin Herrenschmidt * Note that PIO_MASK and MDMA_MASK seem to overlap, that's just 9688358ab0SBenjamin Herrenschmidt * weird and I don't now why .. at this stage 9788358ab0SBenjamin Herrenschmidt */ 9888358ab0SBenjamin Herrenschmidt #define TR_133_PIOREG_PIO_MASK 0xff000fff 9988358ab0SBenjamin Herrenschmidt #define TR_133_PIOREG_MDMA_MASK 0x00fff800 10088358ab0SBenjamin Herrenschmidt #define TR_133_UDMAREG_UDMA_MASK 0x0003ffff 10188358ab0SBenjamin Herrenschmidt #define TR_133_UDMAREG_UDMA_EN 0x00000001 10288358ab0SBenjamin Herrenschmidt 10388358ab0SBenjamin Herrenschmidt /* 100Mhz cell, found in Uninorth 2 and K2. It appears as a pci device 10488358ab0SBenjamin Herrenschmidt * (106b/0033) on uninorth or K2 internal PCI bus and it's clock is 10588358ab0SBenjamin Herrenschmidt * controlled like gem or fw. It appears to be an evolution of keylargo 10688358ab0SBenjamin Herrenschmidt * ATA4 with a timing register extended to 2x32bits registers (one 10788358ab0SBenjamin Herrenschmidt * for PIO & MWDMA and one for UDMA, and a similar DBDMA channel. 10888358ab0SBenjamin Herrenschmidt * It has it's own local feature control register as well. 10988358ab0SBenjamin Herrenschmidt * 11088358ab0SBenjamin Herrenschmidt * After scratching my mind over the timing values, at least for PIO 11188358ab0SBenjamin Herrenschmidt * and MDMA, I think I've figured the format of the timing register, 11288358ab0SBenjamin Herrenschmidt * though I use pre-calculated tables for UDMA as usual... 11388358ab0SBenjamin Herrenschmidt */ 11488358ab0SBenjamin Herrenschmidt #define TR_100_PIO_ADDRSETUP_MASK 0xff000000 /* Size of field unknown */ 11588358ab0SBenjamin Herrenschmidt #define TR_100_PIO_ADDRSETUP_SHIFT 24 11688358ab0SBenjamin Herrenschmidt #define TR_100_MDMA_MASK 0x00fff000 11788358ab0SBenjamin Herrenschmidt #define TR_100_MDMA_RECOVERY_MASK 0x00fc0000 11888358ab0SBenjamin Herrenschmidt #define TR_100_MDMA_RECOVERY_SHIFT 18 11988358ab0SBenjamin Herrenschmidt #define TR_100_MDMA_ACCESS_MASK 0x0003f000 12088358ab0SBenjamin Herrenschmidt #define TR_100_MDMA_ACCESS_SHIFT 12 12188358ab0SBenjamin Herrenschmidt #define TR_100_PIO_MASK 0xff000fff 12288358ab0SBenjamin Herrenschmidt #define TR_100_PIO_RECOVERY_MASK 0x00000fc0 12388358ab0SBenjamin Herrenschmidt #define TR_100_PIO_RECOVERY_SHIFT 6 12488358ab0SBenjamin Herrenschmidt #define TR_100_PIO_ACCESS_MASK 0x0000003f 12588358ab0SBenjamin Herrenschmidt #define TR_100_PIO_ACCESS_SHIFT 0 12688358ab0SBenjamin Herrenschmidt 12788358ab0SBenjamin Herrenschmidt #define TR_100_UDMAREG_UDMA_MASK 0x0000ffff 12888358ab0SBenjamin Herrenschmidt #define TR_100_UDMAREG_UDMA_EN 0x00000001 12988358ab0SBenjamin Herrenschmidt 13088358ab0SBenjamin Herrenschmidt 13188358ab0SBenjamin Herrenschmidt /* 66Mhz cell, found in KeyLargo. Can do ultra mode 0 to 2 on 13288358ab0SBenjamin Herrenschmidt * 40 connector cable and to 4 on 80 connector one. 13388358ab0SBenjamin Herrenschmidt * Clock unit is 15ns (66Mhz) 13488358ab0SBenjamin Herrenschmidt * 13588358ab0SBenjamin Herrenschmidt * 3 Values can be programmed: 13688358ab0SBenjamin Herrenschmidt * - Write data setup, which appears to match the cycle time. They 13788358ab0SBenjamin Herrenschmidt * also call it DIOW setup. 13888358ab0SBenjamin Herrenschmidt * - Ready to pause time (from spec) 13988358ab0SBenjamin Herrenschmidt * - Address setup. That one is weird. I don't see where exactly 14088358ab0SBenjamin Herrenschmidt * it fits in UDMA cycles, I got it's name from an obscure piece 14188358ab0SBenjamin Herrenschmidt * of commented out code in Darwin. They leave it to 0, we do as 14288358ab0SBenjamin Herrenschmidt * well, despite a comment that would lead to think it has a 14388358ab0SBenjamin Herrenschmidt * min value of 45ns. 14488358ab0SBenjamin Herrenschmidt * Apple also add 60ns to the write data setup (or cycle time ?) on 14588358ab0SBenjamin Herrenschmidt * reads. 14688358ab0SBenjamin Herrenschmidt */ 14788358ab0SBenjamin Herrenschmidt #define TR_66_UDMA_MASK 0xfff00000 14888358ab0SBenjamin Herrenschmidt #define TR_66_UDMA_EN 0x00100000 /* Enable Ultra mode for DMA */ 14988358ab0SBenjamin Herrenschmidt #define TR_66_PIO_ADDRSETUP_MASK 0xe0000000 /* Address setup */ 15088358ab0SBenjamin Herrenschmidt #define TR_66_PIO_ADDRSETUP_SHIFT 29 15188358ab0SBenjamin Herrenschmidt #define TR_66_UDMA_RDY2PAUS_MASK 0x1e000000 /* Ready 2 pause time */ 15288358ab0SBenjamin Herrenschmidt #define TR_66_UDMA_RDY2PAUS_SHIFT 25 15388358ab0SBenjamin Herrenschmidt #define TR_66_UDMA_WRDATASETUP_MASK 0x01e00000 /* Write data setup time */ 15488358ab0SBenjamin Herrenschmidt #define TR_66_UDMA_WRDATASETUP_SHIFT 21 15588358ab0SBenjamin Herrenschmidt #define TR_66_MDMA_MASK 0x000ffc00 15688358ab0SBenjamin Herrenschmidt #define TR_66_MDMA_RECOVERY_MASK 0x000f8000 15788358ab0SBenjamin Herrenschmidt #define TR_66_MDMA_RECOVERY_SHIFT 15 15888358ab0SBenjamin Herrenschmidt #define TR_66_MDMA_ACCESS_MASK 0x00007c00 15988358ab0SBenjamin Herrenschmidt #define TR_66_MDMA_ACCESS_SHIFT 10 16088358ab0SBenjamin Herrenschmidt #define TR_66_PIO_MASK 0xe00003ff 16188358ab0SBenjamin Herrenschmidt #define TR_66_PIO_RECOVERY_MASK 0x000003e0 16288358ab0SBenjamin Herrenschmidt #define TR_66_PIO_RECOVERY_SHIFT 5 16388358ab0SBenjamin Herrenschmidt #define TR_66_PIO_ACCESS_MASK 0x0000001f 16488358ab0SBenjamin Herrenschmidt #define TR_66_PIO_ACCESS_SHIFT 0 16588358ab0SBenjamin Herrenschmidt 16688358ab0SBenjamin Herrenschmidt /* 33Mhz cell, found in OHare, Heathrow (& Paddington) and KeyLargo 16788358ab0SBenjamin Herrenschmidt * Can do pio & mdma modes, clock unit is 30ns (33Mhz) 16888358ab0SBenjamin Herrenschmidt * 16988358ab0SBenjamin Herrenschmidt * The access time and recovery time can be programmed. Some older 17088358ab0SBenjamin Herrenschmidt * Darwin code base limit OHare to 150ns cycle time. I decided to do 17188358ab0SBenjamin Herrenschmidt * the same here fore safety against broken old hardware ;) 17288358ab0SBenjamin Herrenschmidt * The HalfTick bit, when set, adds half a clock (15ns) to the access 17388358ab0SBenjamin Herrenschmidt * time and removes one from recovery. It's not supported on KeyLargo 17488358ab0SBenjamin Herrenschmidt * implementation afaik. The E bit appears to be set for PIO mode 0 and 17588358ab0SBenjamin Herrenschmidt * is used to reach long timings used in this mode. 17688358ab0SBenjamin Herrenschmidt */ 17788358ab0SBenjamin Herrenschmidt #define TR_33_MDMA_MASK 0x003ff800 17888358ab0SBenjamin Herrenschmidt #define TR_33_MDMA_RECOVERY_MASK 0x001f0000 17988358ab0SBenjamin Herrenschmidt #define TR_33_MDMA_RECOVERY_SHIFT 16 18088358ab0SBenjamin Herrenschmidt #define TR_33_MDMA_ACCESS_MASK 0x0000f800 18188358ab0SBenjamin Herrenschmidt #define TR_33_MDMA_ACCESS_SHIFT 11 18288358ab0SBenjamin Herrenschmidt #define TR_33_MDMA_HALFTICK 0x00200000 18388358ab0SBenjamin Herrenschmidt #define TR_33_PIO_MASK 0x000007ff 18488358ab0SBenjamin Herrenschmidt #define TR_33_PIO_E 0x00000400 18588358ab0SBenjamin Herrenschmidt #define TR_33_PIO_RECOVERY_MASK 0x000003e0 18688358ab0SBenjamin Herrenschmidt #define TR_33_PIO_RECOVERY_SHIFT 5 18788358ab0SBenjamin Herrenschmidt #define TR_33_PIO_ACCESS_MASK 0x0000001f 18888358ab0SBenjamin Herrenschmidt #define TR_33_PIO_ACCESS_SHIFT 0 18988358ab0SBenjamin Herrenschmidt 19088358ab0SBenjamin Herrenschmidt /* 19188358ab0SBenjamin Herrenschmidt * Interrupt register definitions. Only present on newer cells 19288358ab0SBenjamin Herrenschmidt * (Keylargo and later afaik) so we don't use it. 19388358ab0SBenjamin Herrenschmidt */ 19488358ab0SBenjamin Herrenschmidt #define IDE_INTR_DMA 0x80000000 19588358ab0SBenjamin Herrenschmidt #define IDE_INTR_DEVICE 0x40000000 19688358ab0SBenjamin Herrenschmidt 19788358ab0SBenjamin Herrenschmidt /* 19888358ab0SBenjamin Herrenschmidt * FCR Register on Kauai. Not sure what bit 0x4 is ... 19988358ab0SBenjamin Herrenschmidt */ 20088358ab0SBenjamin Herrenschmidt #define KAUAI_FCR_UATA_MAGIC 0x00000004 20188358ab0SBenjamin Herrenschmidt #define KAUAI_FCR_UATA_RESET_N 0x00000002 20288358ab0SBenjamin Herrenschmidt #define KAUAI_FCR_UATA_ENABLE 0x00000001 20388358ab0SBenjamin Herrenschmidt 20488358ab0SBenjamin Herrenschmidt 20588358ab0SBenjamin Herrenschmidt /* Allow up to 256 DBDMA commands per xfer */ 20688358ab0SBenjamin Herrenschmidt #define MAX_DCMDS 256 20788358ab0SBenjamin Herrenschmidt 20888358ab0SBenjamin Herrenschmidt /* Don't let a DMA segment go all the way to 64K */ 20988358ab0SBenjamin Herrenschmidt #define MAX_DBDMA_SEG 0xff00 21088358ab0SBenjamin Herrenschmidt 21188358ab0SBenjamin Herrenschmidt 21288358ab0SBenjamin Herrenschmidt /* 21388358ab0SBenjamin Herrenschmidt * Wait 1s for disk to answer on IDE bus after a hard reset 21488358ab0SBenjamin Herrenschmidt * of the device (via GPIO/FCR). 21588358ab0SBenjamin Herrenschmidt * 21688358ab0SBenjamin Herrenschmidt * Some devices seem to "pollute" the bus even after dropping 21788358ab0SBenjamin Herrenschmidt * the BSY bit (typically some combo drives slave on the UDMA 21888358ab0SBenjamin Herrenschmidt * bus) after a hard reset. Since we hard reset all drives on 21988358ab0SBenjamin Herrenschmidt * KeyLargo ATA66, we have to keep that delay around. I may end 22088358ab0SBenjamin Herrenschmidt * up not hard resetting anymore on these and keep the delay only 22188358ab0SBenjamin Herrenschmidt * for older interfaces instead (we have to reset when coming 22288358ab0SBenjamin Herrenschmidt * from MacOS...) --BenH. 22388358ab0SBenjamin Herrenschmidt */ 22488358ab0SBenjamin Herrenschmidt #define IDE_WAKEUP_DELAY_MS 1000 22588358ab0SBenjamin Herrenschmidt 22688358ab0SBenjamin Herrenschmidt struct pata_macio_timing; 22788358ab0SBenjamin Herrenschmidt 22888358ab0SBenjamin Herrenschmidt struct pata_macio_priv { 22988358ab0SBenjamin Herrenschmidt int kind; 23088358ab0SBenjamin Herrenschmidt int aapl_bus_id; 23188358ab0SBenjamin Herrenschmidt int mediabay : 1; 23288358ab0SBenjamin Herrenschmidt struct device_node *node; 23388358ab0SBenjamin Herrenschmidt struct macio_dev *mdev; 23488358ab0SBenjamin Herrenschmidt struct pci_dev *pdev; 23588358ab0SBenjamin Herrenschmidt struct device *dev; 23688358ab0SBenjamin Herrenschmidt int irq; 23788358ab0SBenjamin Herrenschmidt u32 treg[2][2]; 23888358ab0SBenjamin Herrenschmidt void __iomem *tfregs; 23988358ab0SBenjamin Herrenschmidt void __iomem *kauai_fcr; 24088358ab0SBenjamin Herrenschmidt struct dbdma_cmd * dma_table_cpu; 24188358ab0SBenjamin Herrenschmidt dma_addr_t dma_table_dma; 24288358ab0SBenjamin Herrenschmidt struct ata_host *host; 24388358ab0SBenjamin Herrenschmidt const struct pata_macio_timing *timings; 24488358ab0SBenjamin Herrenschmidt }; 24588358ab0SBenjamin Herrenschmidt 24688358ab0SBenjamin Herrenschmidt /* Previous variants of this driver used to calculate timings 24788358ab0SBenjamin Herrenschmidt * for various variants of the chip and use tables for others. 24888358ab0SBenjamin Herrenschmidt * 24988358ab0SBenjamin Herrenschmidt * Not only was this confusing, but in addition, it isn't clear 25088358ab0SBenjamin Herrenschmidt * whether our calculation code was correct. It didn't entirely 25188358ab0SBenjamin Herrenschmidt * match the darwin code and whatever documentation I could find 25288358ab0SBenjamin Herrenschmidt * on these cells 25388358ab0SBenjamin Herrenschmidt * 25488358ab0SBenjamin Herrenschmidt * I decided to entirely rely on a table instead for this version 25588358ab0SBenjamin Herrenschmidt * of the driver. Also, because I don't really care about derated 25688358ab0SBenjamin Herrenschmidt * modes and really old HW other than making it work, I'm not going 25788358ab0SBenjamin Herrenschmidt * to calculate / snoop timing values for something else than the 25888358ab0SBenjamin Herrenschmidt * standard modes. 25988358ab0SBenjamin Herrenschmidt */ 26088358ab0SBenjamin Herrenschmidt struct pata_macio_timing { 26188358ab0SBenjamin Herrenschmidt int mode; 26288358ab0SBenjamin Herrenschmidt u32 reg1; /* Bits to set in first timing reg */ 26388358ab0SBenjamin Herrenschmidt u32 reg2; /* Bits to set in second timing reg */ 26488358ab0SBenjamin Herrenschmidt }; 26588358ab0SBenjamin Herrenschmidt 26688358ab0SBenjamin Herrenschmidt static const struct pata_macio_timing pata_macio_ohare_timings[] = { 26788358ab0SBenjamin Herrenschmidt { XFER_PIO_0, 0x00000526, 0, }, 26888358ab0SBenjamin Herrenschmidt { XFER_PIO_1, 0x00000085, 0, }, 26988358ab0SBenjamin Herrenschmidt { XFER_PIO_2, 0x00000025, 0, }, 27088358ab0SBenjamin Herrenschmidt { XFER_PIO_3, 0x00000025, 0, }, 27188358ab0SBenjamin Herrenschmidt { XFER_PIO_4, 0x00000025, 0, }, 27288358ab0SBenjamin Herrenschmidt { XFER_MW_DMA_0, 0x00074000, 0, }, 27388358ab0SBenjamin Herrenschmidt { XFER_MW_DMA_1, 0x00221000, 0, }, 27488358ab0SBenjamin Herrenschmidt { XFER_MW_DMA_2, 0x00211000, 0, }, 27588358ab0SBenjamin Herrenschmidt { -1, 0, 0 } 27688358ab0SBenjamin Herrenschmidt }; 27788358ab0SBenjamin Herrenschmidt 27888358ab0SBenjamin Herrenschmidt static const struct pata_macio_timing pata_macio_heathrow_timings[] = { 27988358ab0SBenjamin Herrenschmidt { XFER_PIO_0, 0x00000526, 0, }, 28088358ab0SBenjamin Herrenschmidt { XFER_PIO_1, 0x00000085, 0, }, 28188358ab0SBenjamin Herrenschmidt { XFER_PIO_2, 0x00000025, 0, }, 28288358ab0SBenjamin Herrenschmidt { XFER_PIO_3, 0x00000025, 0, }, 28388358ab0SBenjamin Herrenschmidt { XFER_PIO_4, 0x00000025, 0, }, 28488358ab0SBenjamin Herrenschmidt { XFER_MW_DMA_0, 0x00074000, 0, }, 28588358ab0SBenjamin Herrenschmidt { XFER_MW_DMA_1, 0x00221000, 0, }, 28688358ab0SBenjamin Herrenschmidt { XFER_MW_DMA_2, 0x00211000, 0, }, 28788358ab0SBenjamin Herrenschmidt { -1, 0, 0 } 28888358ab0SBenjamin Herrenschmidt }; 28988358ab0SBenjamin Herrenschmidt 29088358ab0SBenjamin Herrenschmidt static const struct pata_macio_timing pata_macio_kl33_timings[] = { 29188358ab0SBenjamin Herrenschmidt { XFER_PIO_0, 0x00000526, 0, }, 29288358ab0SBenjamin Herrenschmidt { XFER_PIO_1, 0x00000085, 0, }, 29388358ab0SBenjamin Herrenschmidt { XFER_PIO_2, 0x00000025, 0, }, 29488358ab0SBenjamin Herrenschmidt { XFER_PIO_3, 0x00000025, 0, }, 29588358ab0SBenjamin Herrenschmidt { XFER_PIO_4, 0x00000025, 0, }, 29688358ab0SBenjamin Herrenschmidt { XFER_MW_DMA_0, 0x00084000, 0, }, 29788358ab0SBenjamin Herrenschmidt { XFER_MW_DMA_1, 0x00021800, 0, }, 29888358ab0SBenjamin Herrenschmidt { XFER_MW_DMA_2, 0x00011800, 0, }, 29988358ab0SBenjamin Herrenschmidt { -1, 0, 0 } 30088358ab0SBenjamin Herrenschmidt }; 30188358ab0SBenjamin Herrenschmidt 30288358ab0SBenjamin Herrenschmidt static const struct pata_macio_timing pata_macio_kl66_timings[] = { 30388358ab0SBenjamin Herrenschmidt { XFER_PIO_0, 0x0000038c, 0, }, 30488358ab0SBenjamin Herrenschmidt { XFER_PIO_1, 0x0000020a, 0, }, 30588358ab0SBenjamin Herrenschmidt { XFER_PIO_2, 0x00000127, 0, }, 30688358ab0SBenjamin Herrenschmidt { XFER_PIO_3, 0x000000c6, 0, }, 30788358ab0SBenjamin Herrenschmidt { XFER_PIO_4, 0x00000065, 0, }, 30888358ab0SBenjamin Herrenschmidt { XFER_MW_DMA_0, 0x00084000, 0, }, 30988358ab0SBenjamin Herrenschmidt { XFER_MW_DMA_1, 0x00029800, 0, }, 31088358ab0SBenjamin Herrenschmidt { XFER_MW_DMA_2, 0x00019400, 0, }, 31188358ab0SBenjamin Herrenschmidt { XFER_UDMA_0, 0x19100000, 0, }, 31288358ab0SBenjamin Herrenschmidt { XFER_UDMA_1, 0x14d00000, 0, }, 31388358ab0SBenjamin Herrenschmidt { XFER_UDMA_2, 0x10900000, 0, }, 31488358ab0SBenjamin Herrenschmidt { XFER_UDMA_3, 0x0c700000, 0, }, 31588358ab0SBenjamin Herrenschmidt { XFER_UDMA_4, 0x0c500000, 0, }, 31688358ab0SBenjamin Herrenschmidt { -1, 0, 0 } 31788358ab0SBenjamin Herrenschmidt }; 31888358ab0SBenjamin Herrenschmidt 31988358ab0SBenjamin Herrenschmidt static const struct pata_macio_timing pata_macio_kauai_timings[] = { 32088358ab0SBenjamin Herrenschmidt { XFER_PIO_0, 0x08000a92, 0, }, 32188358ab0SBenjamin Herrenschmidt { XFER_PIO_1, 0x0800060f, 0, }, 32288358ab0SBenjamin Herrenschmidt { XFER_PIO_2, 0x0800038b, 0, }, 32388358ab0SBenjamin Herrenschmidt { XFER_PIO_3, 0x05000249, 0, }, 32488358ab0SBenjamin Herrenschmidt { XFER_PIO_4, 0x04000148, 0, }, 32588358ab0SBenjamin Herrenschmidt { XFER_MW_DMA_0, 0x00618000, 0, }, 32688358ab0SBenjamin Herrenschmidt { XFER_MW_DMA_1, 0x00209000, 0, }, 32788358ab0SBenjamin Herrenschmidt { XFER_MW_DMA_2, 0x00148000, 0, }, 32888358ab0SBenjamin Herrenschmidt { XFER_UDMA_0, 0, 0x000070c1, }, 32988358ab0SBenjamin Herrenschmidt { XFER_UDMA_1, 0, 0x00005d81, }, 33088358ab0SBenjamin Herrenschmidt { XFER_UDMA_2, 0, 0x00004a61, }, 33188358ab0SBenjamin Herrenschmidt { XFER_UDMA_3, 0, 0x00003a51, }, 33288358ab0SBenjamin Herrenschmidt { XFER_UDMA_4, 0, 0x00002a31, }, 33388358ab0SBenjamin Herrenschmidt { XFER_UDMA_5, 0, 0x00002921, }, 33488358ab0SBenjamin Herrenschmidt { -1, 0, 0 } 33588358ab0SBenjamin Herrenschmidt }; 33688358ab0SBenjamin Herrenschmidt 33788358ab0SBenjamin Herrenschmidt static const struct pata_macio_timing pata_macio_shasta_timings[] = { 33888358ab0SBenjamin Herrenschmidt { XFER_PIO_0, 0x0a000c97, 0, }, 33988358ab0SBenjamin Herrenschmidt { XFER_PIO_1, 0x07000712, 0, }, 34088358ab0SBenjamin Herrenschmidt { XFER_PIO_2, 0x040003cd, 0, }, 34188358ab0SBenjamin Herrenschmidt { XFER_PIO_3, 0x0500028b, 0, }, 34288358ab0SBenjamin Herrenschmidt { XFER_PIO_4, 0x0400010a, 0, }, 34388358ab0SBenjamin Herrenschmidt { XFER_MW_DMA_0, 0x00820800, 0, }, 34488358ab0SBenjamin Herrenschmidt { XFER_MW_DMA_1, 0x0028b000, 0, }, 34588358ab0SBenjamin Herrenschmidt { XFER_MW_DMA_2, 0x001ca000, 0, }, 34688358ab0SBenjamin Herrenschmidt { XFER_UDMA_0, 0, 0x00035901, }, 34788358ab0SBenjamin Herrenschmidt { XFER_UDMA_1, 0, 0x000348b1, }, 34888358ab0SBenjamin Herrenschmidt { XFER_UDMA_2, 0, 0x00033881, }, 34988358ab0SBenjamin Herrenschmidt { XFER_UDMA_3, 0, 0x00033861, }, 35088358ab0SBenjamin Herrenschmidt { XFER_UDMA_4, 0, 0x00033841, }, 35188358ab0SBenjamin Herrenschmidt { XFER_UDMA_5, 0, 0x00033031, }, 35288358ab0SBenjamin Herrenschmidt { XFER_UDMA_6, 0, 0x00033021, }, 35388358ab0SBenjamin Herrenschmidt { -1, 0, 0 } 35488358ab0SBenjamin Herrenschmidt }; 35588358ab0SBenjamin Herrenschmidt 35688358ab0SBenjamin Herrenschmidt static const struct pata_macio_timing *pata_macio_find_timing( 35788358ab0SBenjamin Herrenschmidt struct pata_macio_priv *priv, 35888358ab0SBenjamin Herrenschmidt int mode) 35988358ab0SBenjamin Herrenschmidt { 36088358ab0SBenjamin Herrenschmidt int i; 36188358ab0SBenjamin Herrenschmidt 36288358ab0SBenjamin Herrenschmidt for (i = 0; priv->timings[i].mode > 0; i++) { 36388358ab0SBenjamin Herrenschmidt if (priv->timings[i].mode == mode) 36488358ab0SBenjamin Herrenschmidt return &priv->timings[i]; 36588358ab0SBenjamin Herrenschmidt } 36688358ab0SBenjamin Herrenschmidt return NULL; 36788358ab0SBenjamin Herrenschmidt } 36888358ab0SBenjamin Herrenschmidt 36988358ab0SBenjamin Herrenschmidt 37088358ab0SBenjamin Herrenschmidt static void pata_macio_apply_timings(struct ata_port *ap, unsigned int device) 37188358ab0SBenjamin Herrenschmidt { 37288358ab0SBenjamin Herrenschmidt struct pata_macio_priv *priv = ap->private_data; 37388358ab0SBenjamin Herrenschmidt void __iomem *rbase = ap->ioaddr.cmd_addr; 37488358ab0SBenjamin Herrenschmidt 37588358ab0SBenjamin Herrenschmidt if (priv->kind == controller_sh_ata6 || 37688358ab0SBenjamin Herrenschmidt priv->kind == controller_un_ata6 || 37788358ab0SBenjamin Herrenschmidt priv->kind == controller_k2_ata6) { 37888358ab0SBenjamin Herrenschmidt writel(priv->treg[device][0], rbase + IDE_KAUAI_PIO_CONFIG); 37988358ab0SBenjamin Herrenschmidt writel(priv->treg[device][1], rbase + IDE_KAUAI_ULTRA_CONFIG); 38088358ab0SBenjamin Herrenschmidt } else 38188358ab0SBenjamin Herrenschmidt writel(priv->treg[device][0], rbase + IDE_TIMING_CONFIG); 38288358ab0SBenjamin Herrenschmidt } 38388358ab0SBenjamin Herrenschmidt 38488358ab0SBenjamin Herrenschmidt static void pata_macio_dev_select(struct ata_port *ap, unsigned int device) 38588358ab0SBenjamin Herrenschmidt { 38688358ab0SBenjamin Herrenschmidt ata_sff_dev_select(ap, device); 38788358ab0SBenjamin Herrenschmidt 38888358ab0SBenjamin Herrenschmidt /* Apply timings */ 38988358ab0SBenjamin Herrenschmidt pata_macio_apply_timings(ap, device); 39088358ab0SBenjamin Herrenschmidt } 39188358ab0SBenjamin Herrenschmidt 39288358ab0SBenjamin Herrenschmidt static void pata_macio_set_timings(struct ata_port *ap, 39388358ab0SBenjamin Herrenschmidt struct ata_device *adev) 39488358ab0SBenjamin Herrenschmidt { 39588358ab0SBenjamin Herrenschmidt struct pata_macio_priv *priv = ap->private_data; 39688358ab0SBenjamin Herrenschmidt const struct pata_macio_timing *t; 39788358ab0SBenjamin Herrenschmidt 39888358ab0SBenjamin Herrenschmidt dev_dbg(priv->dev, "Set timings: DEV=%d,PIO=0x%x (%s),DMA=0x%x (%s)\n", 39988358ab0SBenjamin Herrenschmidt adev->devno, 40088358ab0SBenjamin Herrenschmidt adev->pio_mode, 40188358ab0SBenjamin Herrenschmidt ata_mode_string(ata_xfer_mode2mask(adev->pio_mode)), 40288358ab0SBenjamin Herrenschmidt adev->dma_mode, 40388358ab0SBenjamin Herrenschmidt ata_mode_string(ata_xfer_mode2mask(adev->dma_mode))); 40488358ab0SBenjamin Herrenschmidt 40588358ab0SBenjamin Herrenschmidt /* First clear timings */ 40688358ab0SBenjamin Herrenschmidt priv->treg[adev->devno][0] = priv->treg[adev->devno][1] = 0; 40788358ab0SBenjamin Herrenschmidt 40888358ab0SBenjamin Herrenschmidt /* Now get the PIO timings */ 40988358ab0SBenjamin Herrenschmidt t = pata_macio_find_timing(priv, adev->pio_mode); 41088358ab0SBenjamin Herrenschmidt if (t == NULL) { 41188358ab0SBenjamin Herrenschmidt dev_warn(priv->dev, "Invalid PIO timing requested: 0x%x\n", 41288358ab0SBenjamin Herrenschmidt adev->pio_mode); 41388358ab0SBenjamin Herrenschmidt t = pata_macio_find_timing(priv, XFER_PIO_0); 41488358ab0SBenjamin Herrenschmidt } 41588358ab0SBenjamin Herrenschmidt BUG_ON(t == NULL); 41688358ab0SBenjamin Herrenschmidt 41788358ab0SBenjamin Herrenschmidt /* PIO timings only ever use the first treg */ 41888358ab0SBenjamin Herrenschmidt priv->treg[adev->devno][0] |= t->reg1; 41988358ab0SBenjamin Herrenschmidt 42088358ab0SBenjamin Herrenschmidt /* Now get DMA timings */ 42188358ab0SBenjamin Herrenschmidt t = pata_macio_find_timing(priv, adev->dma_mode); 42288358ab0SBenjamin Herrenschmidt if (t == NULL || (t->reg1 == 0 && t->reg2 == 0)) { 42388358ab0SBenjamin Herrenschmidt dev_dbg(priv->dev, "DMA timing not set yet, using MW_DMA_0\n"); 42488358ab0SBenjamin Herrenschmidt t = pata_macio_find_timing(priv, XFER_MW_DMA_0); 42588358ab0SBenjamin Herrenschmidt } 42688358ab0SBenjamin Herrenschmidt BUG_ON(t == NULL); 42788358ab0SBenjamin Herrenschmidt 42888358ab0SBenjamin Herrenschmidt /* DMA timings can use both tregs */ 42988358ab0SBenjamin Herrenschmidt priv->treg[adev->devno][0] |= t->reg1; 43088358ab0SBenjamin Herrenschmidt priv->treg[adev->devno][1] |= t->reg2; 43188358ab0SBenjamin Herrenschmidt 43288358ab0SBenjamin Herrenschmidt dev_dbg(priv->dev, " -> %08x %08x\n", 43388358ab0SBenjamin Herrenschmidt priv->treg[adev->devno][0], 43488358ab0SBenjamin Herrenschmidt priv->treg[adev->devno][1]); 43588358ab0SBenjamin Herrenschmidt 43688358ab0SBenjamin Herrenschmidt /* Apply to hardware */ 43788358ab0SBenjamin Herrenschmidt pata_macio_apply_timings(ap, adev->devno); 43888358ab0SBenjamin Herrenschmidt } 43988358ab0SBenjamin Herrenschmidt 44088358ab0SBenjamin Herrenschmidt /* 44188358ab0SBenjamin Herrenschmidt * Blast some well known "safe" values to the timing registers at init or 44288358ab0SBenjamin Herrenschmidt * wakeup from sleep time, before we do real calculation 44388358ab0SBenjamin Herrenschmidt */ 44488358ab0SBenjamin Herrenschmidt static void pata_macio_default_timings(struct pata_macio_priv *priv) 44588358ab0SBenjamin Herrenschmidt { 44688358ab0SBenjamin Herrenschmidt unsigned int value, value2 = 0; 44788358ab0SBenjamin Herrenschmidt 44888358ab0SBenjamin Herrenschmidt switch(priv->kind) { 44988358ab0SBenjamin Herrenschmidt case controller_sh_ata6: 45088358ab0SBenjamin Herrenschmidt value = 0x0a820c97; 45188358ab0SBenjamin Herrenschmidt value2 = 0x00033031; 45288358ab0SBenjamin Herrenschmidt break; 45388358ab0SBenjamin Herrenschmidt case controller_un_ata6: 45488358ab0SBenjamin Herrenschmidt case controller_k2_ata6: 45588358ab0SBenjamin Herrenschmidt value = 0x08618a92; 45688358ab0SBenjamin Herrenschmidt value2 = 0x00002921; 45788358ab0SBenjamin Herrenschmidt break; 45888358ab0SBenjamin Herrenschmidt case controller_kl_ata4: 45988358ab0SBenjamin Herrenschmidt value = 0x0008438c; 46088358ab0SBenjamin Herrenschmidt break; 46188358ab0SBenjamin Herrenschmidt case controller_kl_ata3: 46288358ab0SBenjamin Herrenschmidt value = 0x00084526; 46388358ab0SBenjamin Herrenschmidt break; 46488358ab0SBenjamin Herrenschmidt case controller_heathrow: 46588358ab0SBenjamin Herrenschmidt case controller_ohare: 46688358ab0SBenjamin Herrenschmidt default: 46788358ab0SBenjamin Herrenschmidt value = 0x00074526; 46888358ab0SBenjamin Herrenschmidt break; 46988358ab0SBenjamin Herrenschmidt } 47088358ab0SBenjamin Herrenschmidt priv->treg[0][0] = priv->treg[1][0] = value; 47188358ab0SBenjamin Herrenschmidt priv->treg[0][1] = priv->treg[1][1] = value2; 47288358ab0SBenjamin Herrenschmidt } 47388358ab0SBenjamin Herrenschmidt 47488358ab0SBenjamin Herrenschmidt static int pata_macio_cable_detect(struct ata_port *ap) 47588358ab0SBenjamin Herrenschmidt { 47688358ab0SBenjamin Herrenschmidt struct pata_macio_priv *priv = ap->private_data; 47788358ab0SBenjamin Herrenschmidt 47888358ab0SBenjamin Herrenschmidt /* Get cable type from device-tree */ 47988358ab0SBenjamin Herrenschmidt if (priv->kind == controller_kl_ata4 || 48088358ab0SBenjamin Herrenschmidt priv->kind == controller_un_ata6 || 48188358ab0SBenjamin Herrenschmidt priv->kind == controller_k2_ata6 || 48288358ab0SBenjamin Herrenschmidt priv->kind == controller_sh_ata6) { 48388358ab0SBenjamin Herrenschmidt const char* cable = of_get_property(priv->node, "cable-type", 48488358ab0SBenjamin Herrenschmidt NULL); 48588358ab0SBenjamin Herrenschmidt struct device_node *root = of_find_node_by_path("/"); 48688358ab0SBenjamin Herrenschmidt const char *model = of_get_property(root, "model", NULL); 48788358ab0SBenjamin Herrenschmidt 488745d51dcSYangtao Li of_node_put(root); 489745d51dcSYangtao Li 49088358ab0SBenjamin Herrenschmidt if (cable && !strncmp(cable, "80-", 3)) { 49188358ab0SBenjamin Herrenschmidt /* Some drives fail to detect 80c cable in PowerBook 49288358ab0SBenjamin Herrenschmidt * These machine use proprietary short IDE cable 49388358ab0SBenjamin Herrenschmidt * anyway 49488358ab0SBenjamin Herrenschmidt */ 49588358ab0SBenjamin Herrenschmidt if (!strncmp(model, "PowerBook", 9)) 49688358ab0SBenjamin Herrenschmidt return ATA_CBL_PATA40_SHORT; 49788358ab0SBenjamin Herrenschmidt else 49888358ab0SBenjamin Herrenschmidt return ATA_CBL_PATA80; 49988358ab0SBenjamin Herrenschmidt } 50088358ab0SBenjamin Herrenschmidt } 50188358ab0SBenjamin Herrenschmidt 50288358ab0SBenjamin Herrenschmidt /* G5's seem to have incorrect cable type in device-tree. 50388358ab0SBenjamin Herrenschmidt * Let's assume they always have a 80 conductor cable, this seem to 50488358ab0SBenjamin Herrenschmidt * be always the case unless the user mucked around 50588358ab0SBenjamin Herrenschmidt */ 50688358ab0SBenjamin Herrenschmidt if (of_device_is_compatible(priv->node, "K2-UATA") || 50788358ab0SBenjamin Herrenschmidt of_device_is_compatible(priv->node, "shasta-ata")) 50888358ab0SBenjamin Herrenschmidt return ATA_CBL_PATA80; 50988358ab0SBenjamin Herrenschmidt 51088358ab0SBenjamin Herrenschmidt /* Anything else is 40 connectors */ 51188358ab0SBenjamin Herrenschmidt return ATA_CBL_PATA40; 51288358ab0SBenjamin Herrenschmidt } 51388358ab0SBenjamin Herrenschmidt 51495364f36SJiri Slaby static enum ata_completion_errors pata_macio_qc_prep(struct ata_queued_cmd *qc) 51588358ab0SBenjamin Herrenschmidt { 51688358ab0SBenjamin Herrenschmidt unsigned int write = (qc->tf.flags & ATA_TFLAG_WRITE); 51788358ab0SBenjamin Herrenschmidt struct ata_port *ap = qc->ap; 51888358ab0SBenjamin Herrenschmidt struct pata_macio_priv *priv = ap->private_data; 51988358ab0SBenjamin Herrenschmidt struct scatterlist *sg; 52088358ab0SBenjamin Herrenschmidt struct dbdma_cmd *table; 52188358ab0SBenjamin Herrenschmidt unsigned int si, pi; 52288358ab0SBenjamin Herrenschmidt 52388358ab0SBenjamin Herrenschmidt dev_dbgdma(priv->dev, "%s: qc %p flags %lx, write %d dev %d\n", 52488358ab0SBenjamin Herrenschmidt __func__, qc, qc->flags, write, qc->dev->devno); 52588358ab0SBenjamin Herrenschmidt 52688358ab0SBenjamin Herrenschmidt if (!(qc->flags & ATA_QCFLAG_DMAMAP)) 52795364f36SJiri Slaby return AC_ERR_OK; 52888358ab0SBenjamin Herrenschmidt 52988358ab0SBenjamin Herrenschmidt table = (struct dbdma_cmd *) priv->dma_table_cpu; 53088358ab0SBenjamin Herrenschmidt 53188358ab0SBenjamin Herrenschmidt pi = 0; 53288358ab0SBenjamin Herrenschmidt for_each_sg(qc->sg, sg, qc->n_elem, si) { 53388358ab0SBenjamin Herrenschmidt u32 addr, sg_len, len; 53488358ab0SBenjamin Herrenschmidt 53588358ab0SBenjamin Herrenschmidt /* determine if physical DMA addr spans 64K boundary. 53688358ab0SBenjamin Herrenschmidt * Note h/w doesn't support 64-bit, so we unconditionally 53788358ab0SBenjamin Herrenschmidt * truncate dma_addr_t to u32. 53888358ab0SBenjamin Herrenschmidt */ 53988358ab0SBenjamin Herrenschmidt addr = (u32) sg_dma_address(sg); 54088358ab0SBenjamin Herrenschmidt sg_len = sg_dma_len(sg); 54188358ab0SBenjamin Herrenschmidt 54288358ab0SBenjamin Herrenschmidt while (sg_len) { 54388358ab0SBenjamin Herrenschmidt /* table overflow should never happen */ 54488358ab0SBenjamin Herrenschmidt BUG_ON (pi++ >= MAX_DCMDS); 54588358ab0SBenjamin Herrenschmidt 54688358ab0SBenjamin Herrenschmidt len = (sg_len < MAX_DBDMA_SEG) ? sg_len : MAX_DBDMA_SEG; 547f5718726SDavid Gibson table->command = cpu_to_le16(write ? OUTPUT_MORE: INPUT_MORE); 548f5718726SDavid Gibson table->req_count = cpu_to_le16(len); 549f5718726SDavid Gibson table->phy_addr = cpu_to_le32(addr); 55088358ab0SBenjamin Herrenschmidt table->cmd_dep = 0; 55188358ab0SBenjamin Herrenschmidt table->xfer_status = 0; 55288358ab0SBenjamin Herrenschmidt table->res_count = 0; 55388358ab0SBenjamin Herrenschmidt addr += len; 55488358ab0SBenjamin Herrenschmidt sg_len -= len; 55588358ab0SBenjamin Herrenschmidt ++table; 55688358ab0SBenjamin Herrenschmidt } 55788358ab0SBenjamin Herrenschmidt } 55888358ab0SBenjamin Herrenschmidt 55988358ab0SBenjamin Herrenschmidt /* Should never happen according to Tejun */ 56088358ab0SBenjamin Herrenschmidt BUG_ON(!pi); 56188358ab0SBenjamin Herrenschmidt 56288358ab0SBenjamin Herrenschmidt /* Convert the last command to an input/output */ 56388358ab0SBenjamin Herrenschmidt table--; 564f5718726SDavid Gibson table->command = cpu_to_le16(write ? OUTPUT_LAST: INPUT_LAST); 56588358ab0SBenjamin Herrenschmidt table++; 56688358ab0SBenjamin Herrenschmidt 56788358ab0SBenjamin Herrenschmidt /* Add the stop command to the end of the list */ 56888358ab0SBenjamin Herrenschmidt memset(table, 0, sizeof(struct dbdma_cmd)); 569f5718726SDavid Gibson table->command = cpu_to_le16(DBDMA_STOP); 57088358ab0SBenjamin Herrenschmidt 57188358ab0SBenjamin Herrenschmidt dev_dbgdma(priv->dev, "%s: %d DMA list entries\n", __func__, pi); 57295364f36SJiri Slaby 57395364f36SJiri Slaby return AC_ERR_OK; 57488358ab0SBenjamin Herrenschmidt } 57588358ab0SBenjamin Herrenschmidt 57688358ab0SBenjamin Herrenschmidt 57788358ab0SBenjamin Herrenschmidt static void pata_macio_freeze(struct ata_port *ap) 57888358ab0SBenjamin Herrenschmidt { 57988358ab0SBenjamin Herrenschmidt struct dbdma_regs __iomem *dma_regs = ap->ioaddr.bmdma_addr; 58088358ab0SBenjamin Herrenschmidt 58188358ab0SBenjamin Herrenschmidt if (dma_regs) { 58288358ab0SBenjamin Herrenschmidt unsigned int timeout = 1000000; 58388358ab0SBenjamin Herrenschmidt 58488358ab0SBenjamin Herrenschmidt /* Make sure DMA controller is stopped */ 58588358ab0SBenjamin Herrenschmidt writel((RUN|PAUSE|FLUSH|WAKE|DEAD) << 16, &dma_regs->control); 58688358ab0SBenjamin Herrenschmidt while (--timeout && (readl(&dma_regs->status) & RUN)) 58788358ab0SBenjamin Herrenschmidt udelay(1); 58888358ab0SBenjamin Herrenschmidt } 58988358ab0SBenjamin Herrenschmidt 59088358ab0SBenjamin Herrenschmidt ata_sff_freeze(ap); 59188358ab0SBenjamin Herrenschmidt } 59288358ab0SBenjamin Herrenschmidt 59388358ab0SBenjamin Herrenschmidt 59488358ab0SBenjamin Herrenschmidt static void pata_macio_bmdma_setup(struct ata_queued_cmd *qc) 59588358ab0SBenjamin Herrenschmidt { 59688358ab0SBenjamin Herrenschmidt struct ata_port *ap = qc->ap; 59788358ab0SBenjamin Herrenschmidt struct pata_macio_priv *priv = ap->private_data; 59888358ab0SBenjamin Herrenschmidt struct dbdma_regs __iomem *dma_regs = ap->ioaddr.bmdma_addr; 59988358ab0SBenjamin Herrenschmidt int dev = qc->dev->devno; 60088358ab0SBenjamin Herrenschmidt 60188358ab0SBenjamin Herrenschmidt dev_dbgdma(priv->dev, "%s: qc %p\n", __func__, qc); 60288358ab0SBenjamin Herrenschmidt 60388358ab0SBenjamin Herrenschmidt /* Make sure DMA commands updates are visible */ 60488358ab0SBenjamin Herrenschmidt writel(priv->dma_table_dma, &dma_regs->cmdptr); 60588358ab0SBenjamin Herrenschmidt 60688358ab0SBenjamin Herrenschmidt /* On KeyLargo 66Mhz cell, we need to add 60ns to wrDataSetup on 60788358ab0SBenjamin Herrenschmidt * UDMA reads 60888358ab0SBenjamin Herrenschmidt */ 60988358ab0SBenjamin Herrenschmidt if (priv->kind == controller_kl_ata4 && 61088358ab0SBenjamin Herrenschmidt (priv->treg[dev][0] & TR_66_UDMA_EN)) { 61188358ab0SBenjamin Herrenschmidt void __iomem *rbase = ap->ioaddr.cmd_addr; 61288358ab0SBenjamin Herrenschmidt u32 reg = priv->treg[dev][0]; 61388358ab0SBenjamin Herrenschmidt 61488358ab0SBenjamin Herrenschmidt if (!(qc->tf.flags & ATA_TFLAG_WRITE)) 61588358ab0SBenjamin Herrenschmidt reg += 0x00800000; 61688358ab0SBenjamin Herrenschmidt writel(reg, rbase + IDE_TIMING_CONFIG); 61788358ab0SBenjamin Herrenschmidt } 61888358ab0SBenjamin Herrenschmidt 61988358ab0SBenjamin Herrenschmidt /* issue r/w command */ 62088358ab0SBenjamin Herrenschmidt ap->ops->sff_exec_command(ap, &qc->tf); 62188358ab0SBenjamin Herrenschmidt } 62288358ab0SBenjamin Herrenschmidt 62388358ab0SBenjamin Herrenschmidt static void pata_macio_bmdma_start(struct ata_queued_cmd *qc) 62488358ab0SBenjamin Herrenschmidt { 62588358ab0SBenjamin Herrenschmidt struct ata_port *ap = qc->ap; 62688358ab0SBenjamin Herrenschmidt struct pata_macio_priv *priv = ap->private_data; 62788358ab0SBenjamin Herrenschmidt struct dbdma_regs __iomem *dma_regs = ap->ioaddr.bmdma_addr; 62888358ab0SBenjamin Herrenschmidt 62988358ab0SBenjamin Herrenschmidt dev_dbgdma(priv->dev, "%s: qc %p\n", __func__, qc); 63088358ab0SBenjamin Herrenschmidt 63188358ab0SBenjamin Herrenschmidt writel((RUN << 16) | RUN, &dma_regs->control); 63288358ab0SBenjamin Herrenschmidt /* Make sure it gets to the controller right now */ 63388358ab0SBenjamin Herrenschmidt (void)readl(&dma_regs->control); 63488358ab0SBenjamin Herrenschmidt } 63588358ab0SBenjamin Herrenschmidt 63688358ab0SBenjamin Herrenschmidt static void pata_macio_bmdma_stop(struct ata_queued_cmd *qc) 63788358ab0SBenjamin Herrenschmidt { 63888358ab0SBenjamin Herrenschmidt struct ata_port *ap = qc->ap; 63988358ab0SBenjamin Herrenschmidt struct pata_macio_priv *priv = ap->private_data; 64088358ab0SBenjamin Herrenschmidt struct dbdma_regs __iomem *dma_regs = ap->ioaddr.bmdma_addr; 64188358ab0SBenjamin Herrenschmidt unsigned int timeout = 1000000; 64288358ab0SBenjamin Herrenschmidt 64388358ab0SBenjamin Herrenschmidt dev_dbgdma(priv->dev, "%s: qc %p\n", __func__, qc); 64488358ab0SBenjamin Herrenschmidt 64588358ab0SBenjamin Herrenschmidt /* Stop the DMA engine and wait for it to full halt */ 64688358ab0SBenjamin Herrenschmidt writel (((RUN|WAKE|DEAD) << 16), &dma_regs->control); 64788358ab0SBenjamin Herrenschmidt while (--timeout && (readl(&dma_regs->status) & RUN)) 64888358ab0SBenjamin Herrenschmidt udelay(1); 64988358ab0SBenjamin Herrenschmidt } 65088358ab0SBenjamin Herrenschmidt 65188358ab0SBenjamin Herrenschmidt static u8 pata_macio_bmdma_status(struct ata_port *ap) 65288358ab0SBenjamin Herrenschmidt { 65388358ab0SBenjamin Herrenschmidt struct pata_macio_priv *priv = ap->private_data; 65488358ab0SBenjamin Herrenschmidt struct dbdma_regs __iomem *dma_regs = ap->ioaddr.bmdma_addr; 65588358ab0SBenjamin Herrenschmidt u32 dstat, rstat = ATA_DMA_INTR; 65688358ab0SBenjamin Herrenschmidt unsigned long timeout = 0; 65788358ab0SBenjamin Herrenschmidt 65888358ab0SBenjamin Herrenschmidt dstat = readl(&dma_regs->status); 65988358ab0SBenjamin Herrenschmidt 66088358ab0SBenjamin Herrenschmidt dev_dbgdma(priv->dev, "%s: dstat=%x\n", __func__, dstat); 66188358ab0SBenjamin Herrenschmidt 66288358ab0SBenjamin Herrenschmidt /* We have two things to deal with here: 66388358ab0SBenjamin Herrenschmidt * 66488358ab0SBenjamin Herrenschmidt * - The dbdma won't stop if the command was started 66588358ab0SBenjamin Herrenschmidt * but completed with an error without transferring all 66688358ab0SBenjamin Herrenschmidt * datas. This happens when bad blocks are met during 66788358ab0SBenjamin Herrenschmidt * a multi-block transfer. 66888358ab0SBenjamin Herrenschmidt * 66988358ab0SBenjamin Herrenschmidt * - The dbdma fifo hasn't yet finished flushing to 6700b2436d3SShaomin Deng * system memory when the disk interrupt occurs. 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 /* First, core libata suspend to do most of the work */ 857ec87cf37SSergey Shtylyov ata_host_suspend(priv->host, mesg); 85888358ab0SBenjamin Herrenschmidt 85988358ab0SBenjamin Herrenschmidt /* Restore to default timings */ 86088358ab0SBenjamin Herrenschmidt pata_macio_default_timings(priv); 86188358ab0SBenjamin Herrenschmidt 86288358ab0SBenjamin Herrenschmidt /* Mask interrupt. Not strictly necessary but old driver did 86388358ab0SBenjamin Herrenschmidt * it and I'd rather not change that here */ 86488358ab0SBenjamin Herrenschmidt disable_irq(priv->irq); 86588358ab0SBenjamin Herrenschmidt 86688358ab0SBenjamin Herrenschmidt /* The media bay will handle itself just fine */ 86788358ab0SBenjamin Herrenschmidt if (priv->mediabay) 86888358ab0SBenjamin Herrenschmidt return 0; 86988358ab0SBenjamin Herrenschmidt 87088358ab0SBenjamin Herrenschmidt /* Kauai has bus control FCRs directly here */ 87188358ab0SBenjamin Herrenschmidt if (priv->kauai_fcr) { 87288358ab0SBenjamin Herrenschmidt u32 fcr = readl(priv->kauai_fcr); 87388358ab0SBenjamin Herrenschmidt fcr &= ~(KAUAI_FCR_UATA_RESET_N | KAUAI_FCR_UATA_ENABLE); 87488358ab0SBenjamin Herrenschmidt writel(fcr, priv->kauai_fcr); 87588358ab0SBenjamin Herrenschmidt } 87688358ab0SBenjamin Herrenschmidt 87788358ab0SBenjamin Herrenschmidt /* For PCI, save state and disable DMA. No need to call 87888358ab0SBenjamin Herrenschmidt * pci_set_power_state(), the HW doesn't do D states that 87988358ab0SBenjamin Herrenschmidt * way, the platform code will take care of suspending the 88088358ab0SBenjamin Herrenschmidt * ASIC properly 88188358ab0SBenjamin Herrenschmidt */ 88288358ab0SBenjamin Herrenschmidt if (priv->pdev) { 88388358ab0SBenjamin Herrenschmidt pci_save_state(priv->pdev); 88488358ab0SBenjamin Herrenschmidt pci_disable_device(priv->pdev); 88588358ab0SBenjamin Herrenschmidt } 88688358ab0SBenjamin Herrenschmidt 88788358ab0SBenjamin Herrenschmidt /* Disable the bus on older machines and the cell on kauai */ 88888358ab0SBenjamin Herrenschmidt ppc_md.feature_call(PMAC_FTR_IDE_ENABLE, priv->node, 88988358ab0SBenjamin Herrenschmidt priv->aapl_bus_id, 0); 89088358ab0SBenjamin Herrenschmidt 89188358ab0SBenjamin Herrenschmidt return 0; 89288358ab0SBenjamin Herrenschmidt } 89388358ab0SBenjamin Herrenschmidt 89488358ab0SBenjamin Herrenschmidt static int pata_macio_do_resume(struct pata_macio_priv *priv) 89588358ab0SBenjamin Herrenschmidt { 89688358ab0SBenjamin Herrenschmidt /* Reset and re-enable the HW */ 89788358ab0SBenjamin Herrenschmidt pata_macio_reset_hw(priv, 1); 89888358ab0SBenjamin Herrenschmidt 89988358ab0SBenjamin Herrenschmidt /* Sanitize drive timings */ 90088358ab0SBenjamin Herrenschmidt pata_macio_apply_timings(priv->host->ports[0], 0); 90188358ab0SBenjamin Herrenschmidt 90288358ab0SBenjamin Herrenschmidt /* We want our IRQ back ! */ 90388358ab0SBenjamin Herrenschmidt enable_irq(priv->irq); 90488358ab0SBenjamin Herrenschmidt 90588358ab0SBenjamin Herrenschmidt /* Let the libata core take it from there */ 90688358ab0SBenjamin Herrenschmidt ata_host_resume(priv->host); 90788358ab0SBenjamin Herrenschmidt 90888358ab0SBenjamin Herrenschmidt return 0; 90988358ab0SBenjamin Herrenschmidt } 91058eb8cd5SBartlomiej Zolnierkiewicz #endif /* CONFIG_PM_SLEEP */ 91188358ab0SBenjamin Herrenschmidt 91288358ab0SBenjamin Herrenschmidt static struct scsi_host_template pata_macio_sht = { 913827b3e84SLee Jones __ATA_BASE_SHT(DRV_NAME), 91488358ab0SBenjamin Herrenschmidt .sg_tablesize = MAX_DCMDS, 91588358ab0SBenjamin Herrenschmidt /* We may not need that strict one */ 91688358ab0SBenjamin Herrenschmidt .dma_boundary = ATA_DMA_BOUNDARY, 917a8cf59a6SChristoph Hellwig /* Not sure what the real max is but we know it's less than 64K, let's 918a8cf59a6SChristoph Hellwig * use 64K minus 256 919a8cf59a6SChristoph Hellwig */ 920a8cf59a6SChristoph Hellwig .max_segment_size = MAX_DBDMA_SEG, 92188358ab0SBenjamin Herrenschmidt .slave_configure = pata_macio_slave_config, 922c3f69c7fSBart Van Assche .sdev_groups = ata_common_sdev_groups, 923827b3e84SLee Jones .can_queue = ATA_DEF_QUEUE, 924827b3e84SLee Jones .tag_alloc_policy = BLK_TAG_ALLOC_RR, 92588358ab0SBenjamin Herrenschmidt }; 92688358ab0SBenjamin Herrenschmidt 92788358ab0SBenjamin Herrenschmidt static struct ata_port_operations pata_macio_ops = { 9288930ff25STejun Heo .inherits = &ata_bmdma_port_ops, 92988358ab0SBenjamin Herrenschmidt 93088358ab0SBenjamin Herrenschmidt .freeze = pata_macio_freeze, 93188358ab0SBenjamin Herrenschmidt .set_piomode = pata_macio_set_timings, 93288358ab0SBenjamin Herrenschmidt .set_dmamode = pata_macio_set_timings, 93388358ab0SBenjamin Herrenschmidt .cable_detect = pata_macio_cable_detect, 93488358ab0SBenjamin Herrenschmidt .sff_dev_select = pata_macio_dev_select, 93588358ab0SBenjamin Herrenschmidt .qc_prep = pata_macio_qc_prep, 93688358ab0SBenjamin Herrenschmidt .bmdma_setup = pata_macio_bmdma_setup, 93788358ab0SBenjamin Herrenschmidt .bmdma_start = pata_macio_bmdma_start, 93888358ab0SBenjamin Herrenschmidt .bmdma_stop = pata_macio_bmdma_stop, 93988358ab0SBenjamin Herrenschmidt .bmdma_status = pata_macio_bmdma_status, 94088358ab0SBenjamin Herrenschmidt .port_start = pata_macio_port_start, 94188358ab0SBenjamin Herrenschmidt .sff_irq_clear = pata_macio_irq_clear, 94288358ab0SBenjamin Herrenschmidt }; 94388358ab0SBenjamin Herrenschmidt 9440ec24914SGreg Kroah-Hartman static void pata_macio_invariants(struct pata_macio_priv *priv) 94588358ab0SBenjamin Herrenschmidt { 94688358ab0SBenjamin Herrenschmidt const int *bidp; 94788358ab0SBenjamin Herrenschmidt 94888358ab0SBenjamin Herrenschmidt /* Identify the type of controller */ 94988358ab0SBenjamin Herrenschmidt if (of_device_is_compatible(priv->node, "shasta-ata")) { 95088358ab0SBenjamin Herrenschmidt priv->kind = controller_sh_ata6; 95188358ab0SBenjamin Herrenschmidt priv->timings = pata_macio_shasta_timings; 95288358ab0SBenjamin Herrenschmidt } else if (of_device_is_compatible(priv->node, "kauai-ata")) { 95388358ab0SBenjamin Herrenschmidt priv->kind = controller_un_ata6; 95488358ab0SBenjamin Herrenschmidt priv->timings = pata_macio_kauai_timings; 95588358ab0SBenjamin Herrenschmidt } else if (of_device_is_compatible(priv->node, "K2-UATA")) { 95688358ab0SBenjamin Herrenschmidt priv->kind = controller_k2_ata6; 95788358ab0SBenjamin Herrenschmidt priv->timings = pata_macio_kauai_timings; 95888358ab0SBenjamin Herrenschmidt } else if (of_device_is_compatible(priv->node, "keylargo-ata")) { 9596c826b68SRob Herring if (of_node_name_eq(priv->node, "ata-4")) { 96088358ab0SBenjamin Herrenschmidt priv->kind = controller_kl_ata4; 96188358ab0SBenjamin Herrenschmidt priv->timings = pata_macio_kl66_timings; 96288358ab0SBenjamin Herrenschmidt } else { 96388358ab0SBenjamin Herrenschmidt priv->kind = controller_kl_ata3; 96488358ab0SBenjamin Herrenschmidt priv->timings = pata_macio_kl33_timings; 96588358ab0SBenjamin Herrenschmidt } 96688358ab0SBenjamin Herrenschmidt } else if (of_device_is_compatible(priv->node, "heathrow-ata")) { 96788358ab0SBenjamin Herrenschmidt priv->kind = controller_heathrow; 96888358ab0SBenjamin Herrenschmidt priv->timings = pata_macio_heathrow_timings; 96988358ab0SBenjamin Herrenschmidt } else { 97088358ab0SBenjamin Herrenschmidt priv->kind = controller_ohare; 97188358ab0SBenjamin Herrenschmidt priv->timings = pata_macio_ohare_timings; 97288358ab0SBenjamin Herrenschmidt } 97388358ab0SBenjamin Herrenschmidt 97488358ab0SBenjamin Herrenschmidt /* XXX FIXME --- setup priv->mediabay here */ 97588358ab0SBenjamin Herrenschmidt 97688358ab0SBenjamin Herrenschmidt /* Get Apple bus ID (for clock and ASIC control) */ 97788358ab0SBenjamin Herrenschmidt bidp = of_get_property(priv->node, "AAPL,bus-id", NULL); 97888358ab0SBenjamin Herrenschmidt priv->aapl_bus_id = bidp ? *bidp : 0; 97988358ab0SBenjamin Herrenschmidt 98088358ab0SBenjamin Herrenschmidt /* Fixup missing Apple bus ID in case of media-bay */ 981ffa302efSChen Zhou if (priv->mediabay && !bidp) 98288358ab0SBenjamin Herrenschmidt priv->aapl_bus_id = 1; 98388358ab0SBenjamin Herrenschmidt } 98488358ab0SBenjamin Herrenschmidt 9850ec24914SGreg Kroah-Hartman static void pata_macio_setup_ios(struct ata_ioports *ioaddr, 9860ec24914SGreg Kroah-Hartman void __iomem * base, void __iomem * dma) 98788358ab0SBenjamin Herrenschmidt { 98888358ab0SBenjamin Herrenschmidt /* cmd_addr is the base of regs for that port */ 98988358ab0SBenjamin Herrenschmidt ioaddr->cmd_addr = base; 99088358ab0SBenjamin Herrenschmidt 99188358ab0SBenjamin Herrenschmidt /* taskfile registers */ 99288358ab0SBenjamin Herrenschmidt ioaddr->data_addr = base + (ATA_REG_DATA << 4); 99388358ab0SBenjamin Herrenschmidt ioaddr->error_addr = base + (ATA_REG_ERR << 4); 99488358ab0SBenjamin Herrenschmidt ioaddr->feature_addr = base + (ATA_REG_FEATURE << 4); 99588358ab0SBenjamin Herrenschmidt ioaddr->nsect_addr = base + (ATA_REG_NSECT << 4); 99688358ab0SBenjamin Herrenschmidt ioaddr->lbal_addr = base + (ATA_REG_LBAL << 4); 99788358ab0SBenjamin Herrenschmidt ioaddr->lbam_addr = base + (ATA_REG_LBAM << 4); 99888358ab0SBenjamin Herrenschmidt ioaddr->lbah_addr = base + (ATA_REG_LBAH << 4); 99988358ab0SBenjamin Herrenschmidt ioaddr->device_addr = base + (ATA_REG_DEVICE << 4); 100088358ab0SBenjamin Herrenschmidt ioaddr->status_addr = base + (ATA_REG_STATUS << 4); 100188358ab0SBenjamin Herrenschmidt ioaddr->command_addr = base + (ATA_REG_CMD << 4); 100288358ab0SBenjamin Herrenschmidt ioaddr->altstatus_addr = base + 0x160; 100388358ab0SBenjamin Herrenschmidt ioaddr->ctl_addr = base + 0x160; 100488358ab0SBenjamin Herrenschmidt ioaddr->bmdma_addr = dma; 100588358ab0SBenjamin Herrenschmidt } 100688358ab0SBenjamin Herrenschmidt 10070ec24914SGreg Kroah-Hartman static void pmac_macio_calc_timing_masks(struct pata_macio_priv *priv, 100888358ab0SBenjamin Herrenschmidt struct ata_port_info *pinfo) 100988358ab0SBenjamin Herrenschmidt { 101088358ab0SBenjamin Herrenschmidt int i = 0; 101188358ab0SBenjamin Herrenschmidt 101288358ab0SBenjamin Herrenschmidt pinfo->pio_mask = 0; 101388358ab0SBenjamin Herrenschmidt pinfo->mwdma_mask = 0; 101488358ab0SBenjamin Herrenschmidt pinfo->udma_mask = 0; 101588358ab0SBenjamin Herrenschmidt 101688358ab0SBenjamin Herrenschmidt while (priv->timings[i].mode > 0) { 101788358ab0SBenjamin Herrenschmidt unsigned int mask = 1U << (priv->timings[i].mode & 0x0f); 101888358ab0SBenjamin Herrenschmidt switch(priv->timings[i].mode & 0xf0) { 101988358ab0SBenjamin Herrenschmidt case 0x00: /* PIO */ 102088358ab0SBenjamin Herrenschmidt pinfo->pio_mask |= (mask >> 8); 102188358ab0SBenjamin Herrenschmidt break; 102288358ab0SBenjamin Herrenschmidt case 0x20: /* MWDMA */ 102388358ab0SBenjamin Herrenschmidt pinfo->mwdma_mask |= mask; 102488358ab0SBenjamin Herrenschmidt break; 102588358ab0SBenjamin Herrenschmidt case 0x40: /* UDMA */ 102688358ab0SBenjamin Herrenschmidt pinfo->udma_mask |= mask; 102788358ab0SBenjamin Herrenschmidt break; 102888358ab0SBenjamin Herrenschmidt } 102988358ab0SBenjamin Herrenschmidt i++; 103088358ab0SBenjamin Herrenschmidt } 10312b5960a0SDamien Le Moal dev_dbg(priv->dev, "Supported masks: PIO=%x, MWDMA=%x, UDMA=%x\n", 103288358ab0SBenjamin Herrenschmidt pinfo->pio_mask, pinfo->mwdma_mask, pinfo->udma_mask); 103388358ab0SBenjamin Herrenschmidt } 103488358ab0SBenjamin Herrenschmidt 10350ec24914SGreg Kroah-Hartman static int pata_macio_common_init(struct pata_macio_priv *priv, 103688358ab0SBenjamin Herrenschmidt resource_size_t tfregs, 103788358ab0SBenjamin Herrenschmidt resource_size_t dmaregs, 103888358ab0SBenjamin Herrenschmidt resource_size_t fcregs, 103988358ab0SBenjamin Herrenschmidt unsigned long irq) 104088358ab0SBenjamin Herrenschmidt { 104188358ab0SBenjamin Herrenschmidt struct ata_port_info pinfo; 104288358ab0SBenjamin Herrenschmidt const struct ata_port_info *ppi[] = { &pinfo, NULL }; 104388358ab0SBenjamin Herrenschmidt void __iomem *dma_regs = NULL; 104488358ab0SBenjamin Herrenschmidt 104588358ab0SBenjamin Herrenschmidt /* Fill up privates with various invariants collected from the 104688358ab0SBenjamin Herrenschmidt * device-tree 104788358ab0SBenjamin Herrenschmidt */ 104888358ab0SBenjamin Herrenschmidt pata_macio_invariants(priv); 104988358ab0SBenjamin Herrenschmidt 105088358ab0SBenjamin Herrenschmidt /* Make sure we have sane initial timings in the cache */ 105188358ab0SBenjamin Herrenschmidt pata_macio_default_timings(priv); 105288358ab0SBenjamin Herrenschmidt 105388358ab0SBenjamin Herrenschmidt /* Allocate libata host for 1 port */ 105488358ab0SBenjamin Herrenschmidt memset(&pinfo, 0, sizeof(struct ata_port_info)); 105588358ab0SBenjamin Herrenschmidt pmac_macio_calc_timing_masks(priv, &pinfo); 10569cbe056fSSergei Shtylyov pinfo.flags = ATA_FLAG_SLAVE_POSS; 105788358ab0SBenjamin Herrenschmidt pinfo.port_ops = &pata_macio_ops; 105888358ab0SBenjamin Herrenschmidt pinfo.private_data = priv; 105988358ab0SBenjamin Herrenschmidt 106088358ab0SBenjamin Herrenschmidt priv->host = ata_host_alloc_pinfo(priv->dev, ppi, 1); 106188358ab0SBenjamin Herrenschmidt if (priv->host == NULL) { 106288358ab0SBenjamin Herrenschmidt dev_err(priv->dev, "Failed to allocate ATA port structure\n"); 106388358ab0SBenjamin Herrenschmidt return -ENOMEM; 106488358ab0SBenjamin Herrenschmidt } 106588358ab0SBenjamin Herrenschmidt 106688358ab0SBenjamin Herrenschmidt /* Setup the private data in host too */ 106788358ab0SBenjamin Herrenschmidt priv->host->private_data = priv; 106888358ab0SBenjamin Herrenschmidt 106988358ab0SBenjamin Herrenschmidt /* Map base registers */ 107088358ab0SBenjamin Herrenschmidt priv->tfregs = devm_ioremap(priv->dev, tfregs, 0x100); 107188358ab0SBenjamin Herrenschmidt if (priv->tfregs == NULL) { 107288358ab0SBenjamin Herrenschmidt dev_err(priv->dev, "Failed to map ATA ports\n"); 107388358ab0SBenjamin Herrenschmidt return -ENOMEM; 107488358ab0SBenjamin Herrenschmidt } 107588358ab0SBenjamin Herrenschmidt priv->host->iomap = &priv->tfregs; 107688358ab0SBenjamin Herrenschmidt 107788358ab0SBenjamin Herrenschmidt /* Map DMA regs */ 107888358ab0SBenjamin Herrenschmidt if (dmaregs != 0) { 107988358ab0SBenjamin Herrenschmidt dma_regs = devm_ioremap(priv->dev, dmaregs, 108088358ab0SBenjamin Herrenschmidt sizeof(struct dbdma_regs)); 108188358ab0SBenjamin Herrenschmidt if (dma_regs == NULL) 108288358ab0SBenjamin Herrenschmidt dev_warn(priv->dev, "Failed to map ATA DMA registers\n"); 108388358ab0SBenjamin Herrenschmidt } 108488358ab0SBenjamin Herrenschmidt 108588358ab0SBenjamin Herrenschmidt /* If chip has local feature control, map those regs too */ 108688358ab0SBenjamin Herrenschmidt if (fcregs != 0) { 108788358ab0SBenjamin Herrenschmidt priv->kauai_fcr = devm_ioremap(priv->dev, fcregs, 4); 108888358ab0SBenjamin Herrenschmidt if (priv->kauai_fcr == NULL) { 108988358ab0SBenjamin Herrenschmidt dev_err(priv->dev, "Failed to map ATA FCR register\n"); 109088358ab0SBenjamin Herrenschmidt return -ENOMEM; 109188358ab0SBenjamin Herrenschmidt } 109288358ab0SBenjamin Herrenschmidt } 109388358ab0SBenjamin Herrenschmidt 109488358ab0SBenjamin Herrenschmidt /* Setup port data structure */ 109588358ab0SBenjamin Herrenschmidt pata_macio_setup_ios(&priv->host->ports[0]->ioaddr, 109688358ab0SBenjamin Herrenschmidt priv->tfregs, dma_regs); 109788358ab0SBenjamin Herrenschmidt priv->host->ports[0]->private_data = priv; 109888358ab0SBenjamin Herrenschmidt 109988358ab0SBenjamin Herrenschmidt /* hard-reset the controller */ 110088358ab0SBenjamin Herrenschmidt pata_macio_reset_hw(priv, 0); 110188358ab0SBenjamin Herrenschmidt pata_macio_apply_timings(priv->host->ports[0], 0); 110288358ab0SBenjamin Herrenschmidt 110388358ab0SBenjamin Herrenschmidt /* Enable bus master if necessary */ 110488358ab0SBenjamin Herrenschmidt if (priv->pdev && dma_regs) 110588358ab0SBenjamin Herrenschmidt pci_set_master(priv->pdev); 110688358ab0SBenjamin Herrenschmidt 110788358ab0SBenjamin Herrenschmidt dev_info(priv->dev, "Activating pata-macio chipset %s, Apple bus ID %d\n", 110888358ab0SBenjamin Herrenschmidt macio_ata_names[priv->kind], priv->aapl_bus_id); 110988358ab0SBenjamin Herrenschmidt 111088358ab0SBenjamin Herrenschmidt /* Start it up */ 111188358ab0SBenjamin Herrenschmidt priv->irq = irq; 1112c3b28894STejun Heo return ata_host_activate(priv->host, irq, ata_bmdma_interrupt, 0, 111388358ab0SBenjamin Herrenschmidt &pata_macio_sht); 111488358ab0SBenjamin Herrenschmidt } 111588358ab0SBenjamin Herrenschmidt 11160ec24914SGreg Kroah-Hartman static int pata_macio_attach(struct macio_dev *mdev, 111788358ab0SBenjamin Herrenschmidt const struct of_device_id *match) 111888358ab0SBenjamin Herrenschmidt { 111988358ab0SBenjamin Herrenschmidt struct pata_macio_priv *priv; 112088358ab0SBenjamin Herrenschmidt resource_size_t tfregs, dmaregs = 0; 112188358ab0SBenjamin Herrenschmidt unsigned long irq; 112288358ab0SBenjamin Herrenschmidt int rc; 112388358ab0SBenjamin Herrenschmidt 112488358ab0SBenjamin Herrenschmidt /* Check for broken device-trees */ 112588358ab0SBenjamin Herrenschmidt if (macio_resource_count(mdev) == 0) { 112688358ab0SBenjamin Herrenschmidt dev_err(&mdev->ofdev.dev, 112788358ab0SBenjamin Herrenschmidt "No addresses for controller\n"); 112888358ab0SBenjamin Herrenschmidt return -ENXIO; 112988358ab0SBenjamin Herrenschmidt } 113088358ab0SBenjamin Herrenschmidt 113188358ab0SBenjamin Herrenschmidt /* Enable managed resources */ 113288358ab0SBenjamin Herrenschmidt macio_enable_devres(mdev); 113388358ab0SBenjamin Herrenschmidt 113488358ab0SBenjamin Herrenschmidt /* Allocate and init private data structure */ 113588358ab0SBenjamin Herrenschmidt priv = devm_kzalloc(&mdev->ofdev.dev, 113688358ab0SBenjamin Herrenschmidt sizeof(struct pata_macio_priv), GFP_KERNEL); 11373e342770SMarkus Elfring if (!priv) 113888358ab0SBenjamin Herrenschmidt return -ENOMEM; 11393e342770SMarkus Elfring 114061c7a080SGrant Likely priv->node = of_node_get(mdev->ofdev.dev.of_node); 114188358ab0SBenjamin Herrenschmidt priv->mdev = mdev; 114288358ab0SBenjamin Herrenschmidt priv->dev = &mdev->ofdev.dev; 114388358ab0SBenjamin Herrenschmidt 114488358ab0SBenjamin Herrenschmidt /* Request memory resource for taskfile registers */ 114588358ab0SBenjamin Herrenschmidt if (macio_request_resource(mdev, 0, "pata-macio")) { 114688358ab0SBenjamin Herrenschmidt dev_err(&mdev->ofdev.dev, 114788358ab0SBenjamin Herrenschmidt "Cannot obtain taskfile resource\n"); 114888358ab0SBenjamin Herrenschmidt return -EBUSY; 114988358ab0SBenjamin Herrenschmidt } 115088358ab0SBenjamin Herrenschmidt tfregs = macio_resource_start(mdev, 0); 115188358ab0SBenjamin Herrenschmidt 115288358ab0SBenjamin Herrenschmidt /* Request resources for DMA registers if any */ 115388358ab0SBenjamin Herrenschmidt if (macio_resource_count(mdev) >= 2) { 115488358ab0SBenjamin Herrenschmidt if (macio_request_resource(mdev, 1, "pata-macio-dma")) 115588358ab0SBenjamin Herrenschmidt dev_err(&mdev->ofdev.dev, 115688358ab0SBenjamin Herrenschmidt "Cannot obtain DMA resource\n"); 115788358ab0SBenjamin Herrenschmidt else 115888358ab0SBenjamin Herrenschmidt dmaregs = macio_resource_start(mdev, 1); 115988358ab0SBenjamin Herrenschmidt } 116088358ab0SBenjamin Herrenschmidt 116188358ab0SBenjamin Herrenschmidt /* 116288358ab0SBenjamin Herrenschmidt * Fixup missing IRQ for some old implementations with broken 116388358ab0SBenjamin Herrenschmidt * device-trees. 116488358ab0SBenjamin Herrenschmidt * 116588358ab0SBenjamin Herrenschmidt * This is a bit bogus, it should be fixed in the device-tree itself, 116688358ab0SBenjamin Herrenschmidt * via the existing macio fixups, based on the type of interrupt 116788358ab0SBenjamin Herrenschmidt * controller in the machine. However, I have no test HW for this case, 116888358ab0SBenjamin Herrenschmidt * and this trick works well enough on those old machines... 116988358ab0SBenjamin Herrenschmidt */ 117088358ab0SBenjamin Herrenschmidt if (macio_irq_count(mdev) == 0) { 117188358ab0SBenjamin Herrenschmidt dev_warn(&mdev->ofdev.dev, 117288358ab0SBenjamin Herrenschmidt "No interrupts for controller, using 13\n"); 117388358ab0SBenjamin Herrenschmidt irq = irq_create_mapping(NULL, 13); 117488358ab0SBenjamin Herrenschmidt } else 117588358ab0SBenjamin Herrenschmidt irq = macio_irq(mdev, 0); 117688358ab0SBenjamin Herrenschmidt 117788358ab0SBenjamin Herrenschmidt /* Prevvent media bay callbacks until fully registered */ 117888358ab0SBenjamin Herrenschmidt lock_media_bay(priv->mdev->media_bay); 117988358ab0SBenjamin Herrenschmidt 118088358ab0SBenjamin Herrenschmidt /* Get register addresses and call common initialization */ 118188358ab0SBenjamin Herrenschmidt rc = pata_macio_common_init(priv, 118288358ab0SBenjamin Herrenschmidt tfregs, /* Taskfile regs */ 118388358ab0SBenjamin Herrenschmidt dmaregs, /* DBDMA regs */ 118488358ab0SBenjamin Herrenschmidt 0, /* Feature control */ 118588358ab0SBenjamin Herrenschmidt irq); 118688358ab0SBenjamin Herrenschmidt unlock_media_bay(priv->mdev->media_bay); 118788358ab0SBenjamin Herrenschmidt 118888358ab0SBenjamin Herrenschmidt return rc; 118988358ab0SBenjamin Herrenschmidt } 119088358ab0SBenjamin Herrenschmidt 11910ec24914SGreg Kroah-Hartman static int pata_macio_detach(struct macio_dev *mdev) 119288358ab0SBenjamin Herrenschmidt { 119388358ab0SBenjamin Herrenschmidt struct ata_host *host = macio_get_drvdata(mdev); 119488358ab0SBenjamin Herrenschmidt struct pata_macio_priv *priv = host->private_data; 119588358ab0SBenjamin Herrenschmidt 119688358ab0SBenjamin Herrenschmidt lock_media_bay(priv->mdev->media_bay); 119788358ab0SBenjamin Herrenschmidt 119888358ab0SBenjamin Herrenschmidt /* Make sure the mediabay callback doesn't try to access 119988358ab0SBenjamin Herrenschmidt * dead stuff 120088358ab0SBenjamin Herrenschmidt */ 120188358ab0SBenjamin Herrenschmidt priv->host->private_data = NULL; 120288358ab0SBenjamin Herrenschmidt 120388358ab0SBenjamin Herrenschmidt ata_host_detach(host); 120488358ab0SBenjamin Herrenschmidt 120588358ab0SBenjamin Herrenschmidt unlock_media_bay(priv->mdev->media_bay); 120688358ab0SBenjamin Herrenschmidt 120788358ab0SBenjamin Herrenschmidt return 0; 120888358ab0SBenjamin Herrenschmidt } 120988358ab0SBenjamin Herrenschmidt 121058eb8cd5SBartlomiej Zolnierkiewicz #ifdef CONFIG_PM_SLEEP 121188358ab0SBenjamin Herrenschmidt static int pata_macio_suspend(struct macio_dev *mdev, pm_message_t mesg) 121288358ab0SBenjamin Herrenschmidt { 121388358ab0SBenjamin Herrenschmidt struct ata_host *host = macio_get_drvdata(mdev); 121488358ab0SBenjamin Herrenschmidt 121588358ab0SBenjamin Herrenschmidt return pata_macio_do_suspend(host->private_data, mesg); 121688358ab0SBenjamin Herrenschmidt } 121788358ab0SBenjamin Herrenschmidt 121888358ab0SBenjamin Herrenschmidt static int pata_macio_resume(struct macio_dev *mdev) 121988358ab0SBenjamin Herrenschmidt { 122088358ab0SBenjamin Herrenschmidt struct ata_host *host = macio_get_drvdata(mdev); 122188358ab0SBenjamin Herrenschmidt 122288358ab0SBenjamin Herrenschmidt return pata_macio_do_resume(host->private_data); 122388358ab0SBenjamin Herrenschmidt } 122458eb8cd5SBartlomiej Zolnierkiewicz #endif /* CONFIG_PM_SLEEP */ 122588358ab0SBenjamin Herrenschmidt 122688358ab0SBenjamin Herrenschmidt #ifdef CONFIG_PMAC_MEDIABAY 122788358ab0SBenjamin Herrenschmidt static void pata_macio_mb_event(struct macio_dev* mdev, int mb_state) 122888358ab0SBenjamin Herrenschmidt { 122988358ab0SBenjamin Herrenschmidt struct ata_host *host = macio_get_drvdata(mdev); 123088358ab0SBenjamin Herrenschmidt struct ata_port *ap; 123188358ab0SBenjamin Herrenschmidt struct ata_eh_info *ehi; 123288358ab0SBenjamin Herrenschmidt struct ata_device *dev; 123388358ab0SBenjamin Herrenschmidt unsigned long flags; 123488358ab0SBenjamin Herrenschmidt 123588358ab0SBenjamin Herrenschmidt if (!host || !host->private_data) 123688358ab0SBenjamin Herrenschmidt return; 123788358ab0SBenjamin Herrenschmidt ap = host->ports[0]; 123888358ab0SBenjamin Herrenschmidt spin_lock_irqsave(ap->lock, flags); 123988358ab0SBenjamin Herrenschmidt ehi = &ap->link.eh_info; 124088358ab0SBenjamin Herrenschmidt if (mb_state == MB_CD) { 124188358ab0SBenjamin Herrenschmidt ata_ehi_push_desc(ehi, "mediabay plug"); 124288358ab0SBenjamin Herrenschmidt ata_ehi_hotplugged(ehi); 124388358ab0SBenjamin Herrenschmidt ata_port_freeze(ap); 124488358ab0SBenjamin Herrenschmidt } else { 124588358ab0SBenjamin Herrenschmidt ata_ehi_push_desc(ehi, "mediabay unplug"); 124688358ab0SBenjamin Herrenschmidt ata_for_each_dev(dev, &ap->link, ALL) 124788358ab0SBenjamin Herrenschmidt dev->flags |= ATA_DFLAG_DETACH; 124888358ab0SBenjamin Herrenschmidt ata_port_abort(ap); 124988358ab0SBenjamin Herrenschmidt } 125088358ab0SBenjamin Herrenschmidt spin_unlock_irqrestore(ap->lock, flags); 125188358ab0SBenjamin Herrenschmidt 125288358ab0SBenjamin Herrenschmidt } 125388358ab0SBenjamin Herrenschmidt #endif /* CONFIG_PMAC_MEDIABAY */ 125488358ab0SBenjamin Herrenschmidt 125588358ab0SBenjamin Herrenschmidt 12560ec24914SGreg Kroah-Hartman static int pata_macio_pci_attach(struct pci_dev *pdev, 125788358ab0SBenjamin Herrenschmidt const struct pci_device_id *id) 125888358ab0SBenjamin Herrenschmidt { 125988358ab0SBenjamin Herrenschmidt struct pata_macio_priv *priv; 126088358ab0SBenjamin Herrenschmidt struct device_node *np; 126188358ab0SBenjamin Herrenschmidt resource_size_t rbase; 126288358ab0SBenjamin Herrenschmidt 126388358ab0SBenjamin Herrenschmidt /* We cannot use a MacIO controller without its OF device node */ 126488358ab0SBenjamin Herrenschmidt np = pci_device_to_OF_node(pdev); 126588358ab0SBenjamin Herrenschmidt if (np == NULL) { 126688358ab0SBenjamin Herrenschmidt dev_err(&pdev->dev, 126788358ab0SBenjamin Herrenschmidt "Cannot find OF device node for controller\n"); 126888358ab0SBenjamin Herrenschmidt return -ENODEV; 126988358ab0SBenjamin Herrenschmidt } 127088358ab0SBenjamin Herrenschmidt 127188358ab0SBenjamin Herrenschmidt /* Check that it can be enabled */ 127288358ab0SBenjamin Herrenschmidt if (pcim_enable_device(pdev)) { 127388358ab0SBenjamin Herrenschmidt dev_err(&pdev->dev, 127488358ab0SBenjamin Herrenschmidt "Cannot enable controller PCI device\n"); 127588358ab0SBenjamin Herrenschmidt return -ENXIO; 127688358ab0SBenjamin Herrenschmidt } 127788358ab0SBenjamin Herrenschmidt 127888358ab0SBenjamin Herrenschmidt /* Allocate and init private data structure */ 127988358ab0SBenjamin Herrenschmidt priv = devm_kzalloc(&pdev->dev, 128088358ab0SBenjamin Herrenschmidt sizeof(struct pata_macio_priv), GFP_KERNEL); 12813e342770SMarkus Elfring if (!priv) 128288358ab0SBenjamin Herrenschmidt return -ENOMEM; 12833e342770SMarkus Elfring 128488358ab0SBenjamin Herrenschmidt priv->node = of_node_get(np); 128588358ab0SBenjamin Herrenschmidt priv->pdev = pdev; 128688358ab0SBenjamin Herrenschmidt priv->dev = &pdev->dev; 128788358ab0SBenjamin Herrenschmidt 128888358ab0SBenjamin Herrenschmidt /* Get MMIO regions */ 128988358ab0SBenjamin Herrenschmidt if (pci_request_regions(pdev, "pata-macio")) { 129088358ab0SBenjamin Herrenschmidt dev_err(&pdev->dev, 129188358ab0SBenjamin Herrenschmidt "Cannot obtain PCI resources\n"); 129288358ab0SBenjamin Herrenschmidt return -EBUSY; 129388358ab0SBenjamin Herrenschmidt } 129488358ab0SBenjamin Herrenschmidt 129588358ab0SBenjamin Herrenschmidt /* Get register addresses and call common initialization */ 129688358ab0SBenjamin Herrenschmidt rbase = pci_resource_start(pdev, 0); 129788358ab0SBenjamin Herrenschmidt if (pata_macio_common_init(priv, 129888358ab0SBenjamin Herrenschmidt rbase + 0x2000, /* Taskfile regs */ 129988358ab0SBenjamin Herrenschmidt rbase + 0x1000, /* DBDMA regs */ 130088358ab0SBenjamin Herrenschmidt rbase, /* Feature control */ 130188358ab0SBenjamin Herrenschmidt pdev->irq)) 130288358ab0SBenjamin Herrenschmidt return -ENXIO; 130388358ab0SBenjamin Herrenschmidt 130488358ab0SBenjamin Herrenschmidt return 0; 130588358ab0SBenjamin Herrenschmidt } 130688358ab0SBenjamin Herrenschmidt 13070ec24914SGreg Kroah-Hartman static void pata_macio_pci_detach(struct pci_dev *pdev) 130888358ab0SBenjamin Herrenschmidt { 13090a86e1c8SJingoo Han struct ata_host *host = pci_get_drvdata(pdev); 131088358ab0SBenjamin Herrenschmidt 131188358ab0SBenjamin Herrenschmidt ata_host_detach(host); 131288358ab0SBenjamin Herrenschmidt } 131388358ab0SBenjamin Herrenschmidt 131458eb8cd5SBartlomiej Zolnierkiewicz #ifdef CONFIG_PM_SLEEP 131588358ab0SBenjamin Herrenschmidt static int pata_macio_pci_suspend(struct pci_dev *pdev, pm_message_t mesg) 131688358ab0SBenjamin Herrenschmidt { 13170a86e1c8SJingoo Han struct ata_host *host = pci_get_drvdata(pdev); 131888358ab0SBenjamin Herrenschmidt 131988358ab0SBenjamin Herrenschmidt return pata_macio_do_suspend(host->private_data, mesg); 132088358ab0SBenjamin Herrenschmidt } 132188358ab0SBenjamin Herrenschmidt 132288358ab0SBenjamin Herrenschmidt static int pata_macio_pci_resume(struct pci_dev *pdev) 132388358ab0SBenjamin Herrenschmidt { 13240a86e1c8SJingoo Han struct ata_host *host = pci_get_drvdata(pdev); 132588358ab0SBenjamin Herrenschmidt 132688358ab0SBenjamin Herrenschmidt return pata_macio_do_resume(host->private_data); 132788358ab0SBenjamin Herrenschmidt } 132858eb8cd5SBartlomiej Zolnierkiewicz #endif /* CONFIG_PM_SLEEP */ 132988358ab0SBenjamin Herrenschmidt 1330e3779f6aSBhumika Goyal static const struct of_device_id pata_macio_match[] = 133188358ab0SBenjamin Herrenschmidt { 13325e776d7bSGeert Uytterhoeven { .name = "IDE", }, 13335e776d7bSGeert Uytterhoeven { .name = "ATA", }, 13345e776d7bSGeert Uytterhoeven { .type = "ide", }, 13355e776d7bSGeert Uytterhoeven { .type = "ata", }, 13365e776d7bSGeert Uytterhoeven { /* sentinel */ } 133788358ab0SBenjamin Herrenschmidt }; 1338469eabb3SLuis de Bethencourt MODULE_DEVICE_TABLE(of, pata_macio_match); 133988358ab0SBenjamin Herrenschmidt 134088358ab0SBenjamin Herrenschmidt static struct macio_driver pata_macio_driver = 134188358ab0SBenjamin Herrenschmidt { 1342c2cdf6abSBenjamin Herrenschmidt .driver = { 134388358ab0SBenjamin Herrenschmidt .name = "pata-macio", 1344c2cdf6abSBenjamin Herrenschmidt .owner = THIS_MODULE, 1345c2cdf6abSBenjamin Herrenschmidt .of_match_table = pata_macio_match, 1346c2cdf6abSBenjamin Herrenschmidt }, 134788358ab0SBenjamin Herrenschmidt .probe = pata_macio_attach, 134888358ab0SBenjamin Herrenschmidt .remove = pata_macio_detach, 134958eb8cd5SBartlomiej Zolnierkiewicz #ifdef CONFIG_PM_SLEEP 135088358ab0SBenjamin Herrenschmidt .suspend = pata_macio_suspend, 135188358ab0SBenjamin Herrenschmidt .resume = pata_macio_resume, 135288358ab0SBenjamin Herrenschmidt #endif 135388358ab0SBenjamin Herrenschmidt #ifdef CONFIG_PMAC_MEDIABAY 135488358ab0SBenjamin Herrenschmidt .mediabay_event = pata_macio_mb_event, 135588358ab0SBenjamin Herrenschmidt #endif 135688358ab0SBenjamin Herrenschmidt }; 135788358ab0SBenjamin Herrenschmidt 135888358ab0SBenjamin Herrenschmidt static const struct pci_device_id pata_macio_pci_match[] = { 135988358ab0SBenjamin Herrenschmidt { PCI_VDEVICE(APPLE, PCI_DEVICE_ID_APPLE_UNI_N_ATA), 0 }, 136088358ab0SBenjamin Herrenschmidt { PCI_VDEVICE(APPLE, PCI_DEVICE_ID_APPLE_IPID_ATA100), 0 }, 136188358ab0SBenjamin Herrenschmidt { PCI_VDEVICE(APPLE, PCI_DEVICE_ID_APPLE_K2_ATA100), 0 }, 136288358ab0SBenjamin Herrenschmidt { PCI_VDEVICE(APPLE, PCI_DEVICE_ID_APPLE_SH_ATA), 0 }, 136388358ab0SBenjamin Herrenschmidt { PCI_VDEVICE(APPLE, PCI_DEVICE_ID_APPLE_IPID2_ATA), 0 }, 136488358ab0SBenjamin Herrenschmidt {}, 136588358ab0SBenjamin Herrenschmidt }; 136688358ab0SBenjamin Herrenschmidt 136788358ab0SBenjamin Herrenschmidt static struct pci_driver pata_macio_pci_driver = { 136888358ab0SBenjamin Herrenschmidt .name = "pata-pci-macio", 136988358ab0SBenjamin Herrenschmidt .id_table = pata_macio_pci_match, 137088358ab0SBenjamin Herrenschmidt .probe = pata_macio_pci_attach, 137188358ab0SBenjamin Herrenschmidt .remove = pata_macio_pci_detach, 137258eb8cd5SBartlomiej Zolnierkiewicz #ifdef CONFIG_PM_SLEEP 137388358ab0SBenjamin Herrenschmidt .suspend = pata_macio_pci_suspend, 137488358ab0SBenjamin Herrenschmidt .resume = pata_macio_pci_resume, 137588358ab0SBenjamin Herrenschmidt #endif 137688358ab0SBenjamin Herrenschmidt .driver = { 137788358ab0SBenjamin Herrenschmidt .owner = THIS_MODULE, 137888358ab0SBenjamin Herrenschmidt }, 137988358ab0SBenjamin Herrenschmidt }; 138088358ab0SBenjamin Herrenschmidt MODULE_DEVICE_TABLE(pci, pata_macio_pci_match); 138188358ab0SBenjamin Herrenschmidt 138288358ab0SBenjamin Herrenschmidt 138388358ab0SBenjamin Herrenschmidt static int __init pata_macio_init(void) 138488358ab0SBenjamin Herrenschmidt { 138588358ab0SBenjamin Herrenschmidt int rc; 138688358ab0SBenjamin Herrenschmidt 138788358ab0SBenjamin Herrenschmidt if (!machine_is(powermac)) 138888358ab0SBenjamin Herrenschmidt return -ENODEV; 138988358ab0SBenjamin Herrenschmidt 139088358ab0SBenjamin Herrenschmidt rc = pci_register_driver(&pata_macio_pci_driver); 139188358ab0SBenjamin Herrenschmidt if (rc) 139288358ab0SBenjamin Herrenschmidt return rc; 139388358ab0SBenjamin Herrenschmidt rc = macio_register_driver(&pata_macio_driver); 139488358ab0SBenjamin Herrenschmidt if (rc) { 139588358ab0SBenjamin Herrenschmidt pci_unregister_driver(&pata_macio_pci_driver); 139688358ab0SBenjamin Herrenschmidt return rc; 139788358ab0SBenjamin Herrenschmidt } 139888358ab0SBenjamin Herrenschmidt return 0; 139988358ab0SBenjamin Herrenschmidt } 140088358ab0SBenjamin Herrenschmidt 140188358ab0SBenjamin Herrenschmidt static void __exit pata_macio_exit(void) 140288358ab0SBenjamin Herrenschmidt { 140388358ab0SBenjamin Herrenschmidt macio_unregister_driver(&pata_macio_driver); 140488358ab0SBenjamin Herrenschmidt pci_unregister_driver(&pata_macio_pci_driver); 140588358ab0SBenjamin Herrenschmidt } 140688358ab0SBenjamin Herrenschmidt 140788358ab0SBenjamin Herrenschmidt module_init(pata_macio_init); 140888358ab0SBenjamin Herrenschmidt module_exit(pata_macio_exit); 140988358ab0SBenjamin Herrenschmidt 141088358ab0SBenjamin Herrenschmidt MODULE_AUTHOR("Benjamin Herrenschmidt"); 141188358ab0SBenjamin Herrenschmidt MODULE_DESCRIPTION("Apple MacIO PATA driver"); 141288358ab0SBenjamin Herrenschmidt MODULE_LICENSE("GPL"); 141388358ab0SBenjamin Herrenschmidt MODULE_VERSION(DRV_VERSION); 1414