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