xref: /openbmc/linux/drivers/ata/pata_atp867x.c (revision a44fec1f)
1d15d6e6cSJohn(Jung-Ik) Lee /*
2d15d6e6cSJohn(Jung-Ik) Lee  * pata_atp867x.c - ARTOP 867X 64bit 4-channel UDMA133 ATA controller driver
3d15d6e6cSJohn(Jung-Ik) Lee  *
4d15d6e6cSJohn(Jung-Ik) Lee  *	(C) 2009 Google Inc. John(Jung-Ik) Lee <jilee@google.com>
5d15d6e6cSJohn(Jung-Ik) Lee  *
6d15d6e6cSJohn(Jung-Ik) Lee  * Per Atp867 data sheet rev 1.2, Acard.
7d15d6e6cSJohn(Jung-Ik) Lee  * Based in part on early ide code from
8d15d6e6cSJohn(Jung-Ik) Lee  *	2003-2004 by Eric Uhrhane, Google, Inc.
9d15d6e6cSJohn(Jung-Ik) Lee  *
10d15d6e6cSJohn(Jung-Ik) Lee  * This program is free software; you can redistribute it and/or modify
11d15d6e6cSJohn(Jung-Ik) Lee  * it under the terms of the GNU General Public License as published by
12d15d6e6cSJohn(Jung-Ik) Lee  * the Free Software Foundation; either version 2 of the License, or
13d15d6e6cSJohn(Jung-Ik) Lee  * (at your option) any later version.
14d15d6e6cSJohn(Jung-Ik) Lee  *
15d15d6e6cSJohn(Jung-Ik) Lee  * This program is distributed in the hope that it will be useful,
16d15d6e6cSJohn(Jung-Ik) Lee  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17d15d6e6cSJohn(Jung-Ik) Lee  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18d15d6e6cSJohn(Jung-Ik) Lee  * GNU General Public License for more details.
19d15d6e6cSJohn(Jung-Ik) Lee  *
20d15d6e6cSJohn(Jung-Ik) Lee  * You should have received a copy of the GNU General Public License
21d15d6e6cSJohn(Jung-Ik) Lee  * along with this program; if not, write to the Free Software
22d15d6e6cSJohn(Jung-Ik) Lee  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23d15d6e6cSJohn(Jung-Ik) Lee  *
24d15d6e6cSJohn(Jung-Ik) Lee  *
25d15d6e6cSJohn(Jung-Ik) Lee  * TODO:
26d15d6e6cSJohn(Jung-Ik) Lee  *   1. RAID features [comparison, XOR, striping, mirroring, etc.]
27d15d6e6cSJohn(Jung-Ik) Lee  */
28d15d6e6cSJohn(Jung-Ik) Lee 
29d15d6e6cSJohn(Jung-Ik) Lee #include <linux/kernel.h>
30d15d6e6cSJohn(Jung-Ik) Lee #include <linux/module.h>
31d15d6e6cSJohn(Jung-Ik) Lee #include <linux/pci.h>
32d15d6e6cSJohn(Jung-Ik) Lee #include <linux/init.h>
33d15d6e6cSJohn(Jung-Ik) Lee #include <linux/blkdev.h>
34d15d6e6cSJohn(Jung-Ik) Lee #include <linux/delay.h>
35d15d6e6cSJohn(Jung-Ik) Lee #include <linux/device.h>
365a0e3ad6STejun Heo #include <linux/gfp.h>
37d15d6e6cSJohn(Jung-Ik) Lee #include <scsi/scsi_host.h>
38d15d6e6cSJohn(Jung-Ik) Lee #include <linux/libata.h>
39d15d6e6cSJohn(Jung-Ik) Lee 
40d15d6e6cSJohn(Jung-Ik) Lee #define	DRV_NAME	"pata_atp867x"
41d15d6e6cSJohn(Jung-Ik) Lee #define	DRV_VERSION	"0.7.5"
42d15d6e6cSJohn(Jung-Ik) Lee 
43d15d6e6cSJohn(Jung-Ik) Lee /*
44d15d6e6cSJohn(Jung-Ik) Lee  * IO Registers
45d15d6e6cSJohn(Jung-Ik) Lee  * Note that all runtime hot priv ports are cached in ap private_data
46d15d6e6cSJohn(Jung-Ik) Lee  */
47d15d6e6cSJohn(Jung-Ik) Lee 
48d15d6e6cSJohn(Jung-Ik) Lee enum {
49d15d6e6cSJohn(Jung-Ik) Lee 	ATP867X_IO_CHANNEL_OFFSET	= 0x10,
50d15d6e6cSJohn(Jung-Ik) Lee 
51d15d6e6cSJohn(Jung-Ik) Lee 	/*
52d15d6e6cSJohn(Jung-Ik) Lee 	 * IO Register Bitfields
53d15d6e6cSJohn(Jung-Ik) Lee 	 */
54d15d6e6cSJohn(Jung-Ik) Lee 
55d15d6e6cSJohn(Jung-Ik) Lee 	ATP867X_IO_PIOSPD_ACTIVE_SHIFT	= 4,
56d15d6e6cSJohn(Jung-Ik) Lee 	ATP867X_IO_PIOSPD_RECOVER_SHIFT	= 0,
57d15d6e6cSJohn(Jung-Ik) Lee 
58d15d6e6cSJohn(Jung-Ik) Lee 	ATP867X_IO_DMAMODE_MSTR_SHIFT	= 0,
59d15d6e6cSJohn(Jung-Ik) Lee 	ATP867X_IO_DMAMODE_MSTR_MASK	= 0x07,
60d15d6e6cSJohn(Jung-Ik) Lee 	ATP867X_IO_DMAMODE_SLAVE_SHIFT	= 4,
61d15d6e6cSJohn(Jung-Ik) Lee 	ATP867X_IO_DMAMODE_SLAVE_MASK	= 0x70,
62d15d6e6cSJohn(Jung-Ik) Lee 
63d15d6e6cSJohn(Jung-Ik) Lee 	ATP867X_IO_DMAMODE_UDMA_6	= 0x07,
64d15d6e6cSJohn(Jung-Ik) Lee 	ATP867X_IO_DMAMODE_UDMA_5	= 0x06,
65d15d6e6cSJohn(Jung-Ik) Lee 	ATP867X_IO_DMAMODE_UDMA_4	= 0x05,
66d15d6e6cSJohn(Jung-Ik) Lee 	ATP867X_IO_DMAMODE_UDMA_3	= 0x04,
67d15d6e6cSJohn(Jung-Ik) Lee 	ATP867X_IO_DMAMODE_UDMA_2	= 0x03,
68d15d6e6cSJohn(Jung-Ik) Lee 	ATP867X_IO_DMAMODE_UDMA_1	= 0x02,
69d15d6e6cSJohn(Jung-Ik) Lee 	ATP867X_IO_DMAMODE_UDMA_0	= 0x01,
70d15d6e6cSJohn(Jung-Ik) Lee 	ATP867X_IO_DMAMODE_DISABLE	= 0x00,
71d15d6e6cSJohn(Jung-Ik) Lee 
72d15d6e6cSJohn(Jung-Ik) Lee 	ATP867X_IO_SYS_INFO_66MHZ	= 0x04,
73d15d6e6cSJohn(Jung-Ik) Lee 	ATP867X_IO_SYS_INFO_SLOW_UDMA5	= 0x02,
74d15d6e6cSJohn(Jung-Ik) Lee 	ATP867X_IO_SYS_MASK_RESERVED	= (~0xf1),
75d15d6e6cSJohn(Jung-Ik) Lee 
76d15d6e6cSJohn(Jung-Ik) Lee 	ATP867X_IO_PORTSPD_VAL		= 0x1143,
77d15d6e6cSJohn(Jung-Ik) Lee 	ATP867X_PREREAD_VAL		= 0x0200,
78d15d6e6cSJohn(Jung-Ik) Lee 
79d15d6e6cSJohn(Jung-Ik) Lee 	ATP867X_NUM_PORTS		= 4,
80d15d6e6cSJohn(Jung-Ik) Lee 	ATP867X_BAR_IOBASE		= 0,
81d15d6e6cSJohn(Jung-Ik) Lee 	ATP867X_BAR_ROMBASE		= 6,
82d15d6e6cSJohn(Jung-Ik) Lee };
83d15d6e6cSJohn(Jung-Ik) Lee 
84d15d6e6cSJohn(Jung-Ik) Lee #define ATP867X_IOBASE(ap)		((ap)->host->iomap[0])
85d15d6e6cSJohn(Jung-Ik) Lee #define ATP867X_SYS_INFO(ap)		(0x3F + ATP867X_IOBASE(ap))
86d15d6e6cSJohn(Jung-Ik) Lee 
87d15d6e6cSJohn(Jung-Ik) Lee #define ATP867X_IO_PORTBASE(ap, port)	(0x00 + ATP867X_IOBASE(ap) + \
88d15d6e6cSJohn(Jung-Ik) Lee 					(port) * ATP867X_IO_CHANNEL_OFFSET)
89d15d6e6cSJohn(Jung-Ik) Lee #define ATP867X_IO_DMABASE(ap, port)	(0x40 + \
90d15d6e6cSJohn(Jung-Ik) Lee 					ATP867X_IO_PORTBASE((ap), (port)))
91d15d6e6cSJohn(Jung-Ik) Lee 
92d15d6e6cSJohn(Jung-Ik) Lee #define ATP867X_IO_STATUS(ap, port)	(0x07 + \
93d15d6e6cSJohn(Jung-Ik) Lee 					ATP867X_IO_PORTBASE((ap), (port)))
94d15d6e6cSJohn(Jung-Ik) Lee #define ATP867X_IO_ALTSTATUS(ap, port)	(0x0E + \
95d15d6e6cSJohn(Jung-Ik) Lee 					ATP867X_IO_PORTBASE((ap), (port)))
96d15d6e6cSJohn(Jung-Ik) Lee 
97d15d6e6cSJohn(Jung-Ik) Lee /*
98d15d6e6cSJohn(Jung-Ik) Lee  * hot priv ports
99d15d6e6cSJohn(Jung-Ik) Lee  */
100d15d6e6cSJohn(Jung-Ik) Lee #define ATP867X_IO_MSTRPIOSPD(ap, port)	(0x08 + \
101d15d6e6cSJohn(Jung-Ik) Lee 					ATP867X_IO_DMABASE((ap), (port)))
102d15d6e6cSJohn(Jung-Ik) Lee #define ATP867X_IO_SLAVPIOSPD(ap, port)	(0x09 + \
103d15d6e6cSJohn(Jung-Ik) Lee 					ATP867X_IO_DMABASE((ap), (port)))
104d15d6e6cSJohn(Jung-Ik) Lee #define ATP867X_IO_8BPIOSPD(ap, port)	(0x0A + \
105d15d6e6cSJohn(Jung-Ik) Lee 					ATP867X_IO_DMABASE((ap), (port)))
106d15d6e6cSJohn(Jung-Ik) Lee #define ATP867X_IO_DMAMODE(ap, port)	(0x0B + \
107d15d6e6cSJohn(Jung-Ik) Lee 					ATP867X_IO_DMABASE((ap), (port)))
108d15d6e6cSJohn(Jung-Ik) Lee 
109d15d6e6cSJohn(Jung-Ik) Lee #define ATP867X_IO_PORTSPD(ap, port)	(0x4A + \
110d15d6e6cSJohn(Jung-Ik) Lee 					ATP867X_IO_PORTBASE((ap), (port)))
111d15d6e6cSJohn(Jung-Ik) Lee #define ATP867X_IO_PREREAD(ap, port)	(0x4C + \
112d15d6e6cSJohn(Jung-Ik) Lee 					ATP867X_IO_PORTBASE((ap), (port)))
113d15d6e6cSJohn(Jung-Ik) Lee 
114d15d6e6cSJohn(Jung-Ik) Lee struct atp867x_priv {
115d15d6e6cSJohn(Jung-Ik) Lee 	void __iomem *dma_mode;
116d15d6e6cSJohn(Jung-Ik) Lee 	void __iomem *mstr_piospd;
117d15d6e6cSJohn(Jung-Ik) Lee 	void __iomem *slave_piospd;
118d15d6e6cSJohn(Jung-Ik) Lee 	void __iomem *eightb_piospd;
119d15d6e6cSJohn(Jung-Ik) Lee 	int		pci66mhz;
120d15d6e6cSJohn(Jung-Ik) Lee };
121d15d6e6cSJohn(Jung-Ik) Lee 
122d15d6e6cSJohn(Jung-Ik) Lee static void atp867x_set_dmamode(struct ata_port *ap, struct ata_device *adev)
123d15d6e6cSJohn(Jung-Ik) Lee {
124d15d6e6cSJohn(Jung-Ik) Lee 	struct pci_dev *pdev	= to_pci_dev(ap->host->dev);
125d15d6e6cSJohn(Jung-Ik) Lee 	struct atp867x_priv *dp = ap->private_data;
126d15d6e6cSJohn(Jung-Ik) Lee 	u8 speed = adev->dma_mode;
127d15d6e6cSJohn(Jung-Ik) Lee 	u8 b;
128566b54c8SBartlomiej Zolnierkiewicz 	u8 mode = speed - XFER_UDMA_0 + 1;
129d15d6e6cSJohn(Jung-Ik) Lee 
130d15d6e6cSJohn(Jung-Ik) Lee 	/*
131d15d6e6cSJohn(Jung-Ik) Lee 	 * Doc 6.6.9: decrease the udma mode value by 1 for safer UDMA speed
132d15d6e6cSJohn(Jung-Ik) Lee 	 * on 66MHz bus
133d15d6e6cSJohn(Jung-Ik) Lee 	 *   rev-A: UDMA_1~4 (5, 6 no change)
134d15d6e6cSJohn(Jung-Ik) Lee 	 *   rev-B: all UDMA modes
135d15d6e6cSJohn(Jung-Ik) Lee 	 *   UDMA_0 stays not to disable UDMA
136d15d6e6cSJohn(Jung-Ik) Lee 	 */
137d15d6e6cSJohn(Jung-Ik) Lee 	if (dp->pci66mhz && mode > ATP867X_IO_DMAMODE_UDMA_0  &&
138d15d6e6cSJohn(Jung-Ik) Lee 	   (pdev->device == PCI_DEVICE_ID_ARTOP_ATP867B ||
139d15d6e6cSJohn(Jung-Ik) Lee 	    mode < ATP867X_IO_DMAMODE_UDMA_5))
140d15d6e6cSJohn(Jung-Ik) Lee 		mode--;
141d15d6e6cSJohn(Jung-Ik) Lee 
142d15d6e6cSJohn(Jung-Ik) Lee 	b = ioread8(dp->dma_mode);
143d15d6e6cSJohn(Jung-Ik) Lee 	if (adev->devno & 1) {
144d15d6e6cSJohn(Jung-Ik) Lee 		b = (b & ~ATP867X_IO_DMAMODE_SLAVE_MASK) |
145d15d6e6cSJohn(Jung-Ik) Lee 			(mode << ATP867X_IO_DMAMODE_SLAVE_SHIFT);
146d15d6e6cSJohn(Jung-Ik) Lee 	} else {
147d15d6e6cSJohn(Jung-Ik) Lee 		b = (b & ~ATP867X_IO_DMAMODE_MSTR_MASK) |
148d15d6e6cSJohn(Jung-Ik) Lee 			(mode << ATP867X_IO_DMAMODE_MSTR_SHIFT);
149d15d6e6cSJohn(Jung-Ik) Lee 	}
150d15d6e6cSJohn(Jung-Ik) Lee 	iowrite8(b, dp->dma_mode);
151d15d6e6cSJohn(Jung-Ik) Lee }
152d15d6e6cSJohn(Jung-Ik) Lee 
15364207f59SJohn(Jung-Ik) Lee static int atp867x_get_active_clocks_shifted(struct ata_port *ap,
15464207f59SJohn(Jung-Ik) Lee 	unsigned int clk)
155d15d6e6cSJohn(Jung-Ik) Lee {
15664207f59SJohn(Jung-Ik) Lee 	struct atp867x_priv *dp = ap->private_data;
157d15d6e6cSJohn(Jung-Ik) Lee 	unsigned char clocks = clk;
158d15d6e6cSJohn(Jung-Ik) Lee 
15964207f59SJohn(Jung-Ik) Lee 	/*
16064207f59SJohn(Jung-Ik) Lee 	 * Doc 6.6.9: increase the clock value by 1 for safer PIO speed
16164207f59SJohn(Jung-Ik) Lee 	 * on 66MHz bus
16264207f59SJohn(Jung-Ik) Lee 	 */
163c59bcc37SBartlomiej Zolnierkiewicz 	if (dp->pci66mhz)
16464207f59SJohn(Jung-Ik) Lee 		clocks++;
16564207f59SJohn(Jung-Ik) Lee 
166c59bcc37SBartlomiej Zolnierkiewicz 	switch (clocks) {
167c59bcc37SBartlomiej Zolnierkiewicz 	case 0:
168c59bcc37SBartlomiej Zolnierkiewicz 		clocks = 1;
169c59bcc37SBartlomiej Zolnierkiewicz 		break;
170c59bcc37SBartlomiej Zolnierkiewicz 	case 1 ... 6:
171c59bcc37SBartlomiej Zolnierkiewicz 		break;
172c59bcc37SBartlomiej Zolnierkiewicz 	default:
173c59bcc37SBartlomiej Zolnierkiewicz 		printk(KERN_WARNING "ATP867X: active %dclk is invalid. "
174c59bcc37SBartlomiej Zolnierkiewicz 			"Using 12clk.\n", clk);
175c59bcc37SBartlomiej Zolnierkiewicz 	case 9 ... 12:
176c59bcc37SBartlomiej Zolnierkiewicz 		clocks = 7;	/* 12 clk */
177c59bcc37SBartlomiej Zolnierkiewicz 		break;
178c59bcc37SBartlomiej Zolnierkiewicz 	case 7:
179c59bcc37SBartlomiej Zolnierkiewicz 	case 8:	/* default 8 clk */
180c59bcc37SBartlomiej Zolnierkiewicz 		clocks = 0;
181c59bcc37SBartlomiej Zolnierkiewicz 		goto active_clock_shift_done;
182c59bcc37SBartlomiej Zolnierkiewicz 	}
183c59bcc37SBartlomiej Zolnierkiewicz 
18464207f59SJohn(Jung-Ik) Lee active_clock_shift_done:
185d15d6e6cSJohn(Jung-Ik) Lee 	return clocks << ATP867X_IO_PIOSPD_ACTIVE_SHIFT;
186d15d6e6cSJohn(Jung-Ik) Lee }
187d15d6e6cSJohn(Jung-Ik) Lee 
188d15d6e6cSJohn(Jung-Ik) Lee static int atp867x_get_recover_clocks_shifted(unsigned int clk)
189d15d6e6cSJohn(Jung-Ik) Lee {
190d15d6e6cSJohn(Jung-Ik) Lee 	unsigned char clocks = clk;
191d15d6e6cSJohn(Jung-Ik) Lee 
192d15d6e6cSJohn(Jung-Ik) Lee 	switch (clocks) {
193d15d6e6cSJohn(Jung-Ik) Lee 	case 0:
194d15d6e6cSJohn(Jung-Ik) Lee 		clocks = 1;
195d15d6e6cSJohn(Jung-Ik) Lee 		break;
196d15d6e6cSJohn(Jung-Ik) Lee 	case 1 ... 11:
197d15d6e6cSJohn(Jung-Ik) Lee 		break;
198c59bcc37SBartlomiej Zolnierkiewicz 	case 13:
199c59bcc37SBartlomiej Zolnierkiewicz 	case 14:
20064207f59SJohn(Jung-Ik) Lee 		--clocks;	/* by the spec */
201d15d6e6cSJohn(Jung-Ik) Lee 		break;
202d15d6e6cSJohn(Jung-Ik) Lee 	case 15:
203d15d6e6cSJohn(Jung-Ik) Lee 		break;
204d15d6e6cSJohn(Jung-Ik) Lee 	default:
205d15d6e6cSJohn(Jung-Ik) Lee 		printk(KERN_WARNING "ATP867X: recover %dclk is invalid. "
20664207f59SJohn(Jung-Ik) Lee 			"Using default 12clk.\n", clk);
20764207f59SJohn(Jung-Ik) Lee 	case 12:	/* default 12 clk */
20864207f59SJohn(Jung-Ik) Lee 		clocks = 0;
209d15d6e6cSJohn(Jung-Ik) Lee 		break;
210d15d6e6cSJohn(Jung-Ik) Lee 	}
21164207f59SJohn(Jung-Ik) Lee 
212d15d6e6cSJohn(Jung-Ik) Lee 	return clocks << ATP867X_IO_PIOSPD_RECOVER_SHIFT;
213d15d6e6cSJohn(Jung-Ik) Lee }
214d15d6e6cSJohn(Jung-Ik) Lee 
215d15d6e6cSJohn(Jung-Ik) Lee static void atp867x_set_piomode(struct ata_port *ap, struct ata_device *adev)
216d15d6e6cSJohn(Jung-Ik) Lee {
217d15d6e6cSJohn(Jung-Ik) Lee 	struct ata_device *peer = ata_dev_pair(adev);
218d15d6e6cSJohn(Jung-Ik) Lee 	struct atp867x_priv *dp = ap->private_data;
219d15d6e6cSJohn(Jung-Ik) Lee 	u8 speed = adev->pio_mode;
220d15d6e6cSJohn(Jung-Ik) Lee 	struct ata_timing t, p;
221d15d6e6cSJohn(Jung-Ik) Lee 	int T, UT;
222d15d6e6cSJohn(Jung-Ik) Lee 	u8 b;
223d15d6e6cSJohn(Jung-Ik) Lee 
224d15d6e6cSJohn(Jung-Ik) Lee 	T = 1000000000 / 33333;
225d15d6e6cSJohn(Jung-Ik) Lee 	UT = T / 4;
226d15d6e6cSJohn(Jung-Ik) Lee 
227d15d6e6cSJohn(Jung-Ik) Lee 	ata_timing_compute(adev, speed, &t, T, UT);
228d15d6e6cSJohn(Jung-Ik) Lee 	if (peer && peer->pio_mode) {
229d15d6e6cSJohn(Jung-Ik) Lee 		ata_timing_compute(peer, peer->pio_mode, &p, T, UT);
230d15d6e6cSJohn(Jung-Ik) Lee 		ata_timing_merge(&p, &t, &t, ATA_TIMING_8BIT);
231d15d6e6cSJohn(Jung-Ik) Lee 	}
232d15d6e6cSJohn(Jung-Ik) Lee 
233d15d6e6cSJohn(Jung-Ik) Lee 	b = ioread8(dp->dma_mode);
234d15d6e6cSJohn(Jung-Ik) Lee 	if (adev->devno & 1)
235d15d6e6cSJohn(Jung-Ik) Lee 		b = (b & ~ATP867X_IO_DMAMODE_SLAVE_MASK);
236d15d6e6cSJohn(Jung-Ik) Lee 	else
237d15d6e6cSJohn(Jung-Ik) Lee 		b = (b & ~ATP867X_IO_DMAMODE_MSTR_MASK);
238d15d6e6cSJohn(Jung-Ik) Lee 	iowrite8(b, dp->dma_mode);
239d15d6e6cSJohn(Jung-Ik) Lee 
24064207f59SJohn(Jung-Ik) Lee 	b = atp867x_get_active_clocks_shifted(ap, t.active) |
241d15d6e6cSJohn(Jung-Ik) Lee 	    atp867x_get_recover_clocks_shifted(t.recover);
242d15d6e6cSJohn(Jung-Ik) Lee 
243d15d6e6cSJohn(Jung-Ik) Lee 	if (adev->devno & 1)
244d15d6e6cSJohn(Jung-Ik) Lee 		iowrite8(b, dp->slave_piospd);
245d15d6e6cSJohn(Jung-Ik) Lee 	else
246d15d6e6cSJohn(Jung-Ik) Lee 		iowrite8(b, dp->mstr_piospd);
247d15d6e6cSJohn(Jung-Ik) Lee 
248c59bcc37SBartlomiej Zolnierkiewicz 	b = atp867x_get_active_clocks_shifted(ap, t.act8b) |
249c59bcc37SBartlomiej Zolnierkiewicz 	    atp867x_get_recover_clocks_shifted(t.rec8b);
250c59bcc37SBartlomiej Zolnierkiewicz 
251d15d6e6cSJohn(Jung-Ik) Lee 	iowrite8(b, dp->eightb_piospd);
252d15d6e6cSJohn(Jung-Ik) Lee }
253d15d6e6cSJohn(Jung-Ik) Lee 
25464207f59SJohn(Jung-Ik) Lee static int atp867x_cable_override(struct pci_dev *pdev)
25564207f59SJohn(Jung-Ik) Lee {
25664207f59SJohn(Jung-Ik) Lee 	if (pdev->subsystem_vendor == PCI_VENDOR_ID_ARTOP &&
25764207f59SJohn(Jung-Ik) Lee 		(pdev->subsystem_device == PCI_DEVICE_ID_ARTOP_ATP867A ||
25864207f59SJohn(Jung-Ik) Lee 		 pdev->subsystem_device == PCI_DEVICE_ID_ARTOP_ATP867B)) {
25964207f59SJohn(Jung-Ik) Lee 		return 1;
26064207f59SJohn(Jung-Ik) Lee 	}
26164207f59SJohn(Jung-Ik) Lee 	return 0;
26264207f59SJohn(Jung-Ik) Lee }
26364207f59SJohn(Jung-Ik) Lee 
264d15d6e6cSJohn(Jung-Ik) Lee static int atp867x_cable_detect(struct ata_port *ap)
265d15d6e6cSJohn(Jung-Ik) Lee {
26664207f59SJohn(Jung-Ik) Lee 	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
26764207f59SJohn(Jung-Ik) Lee 
26864207f59SJohn(Jung-Ik) Lee 	if (atp867x_cable_override(pdev))
269d15d6e6cSJohn(Jung-Ik) Lee 		return ATA_CBL_PATA40_SHORT;
27064207f59SJohn(Jung-Ik) Lee 
27164207f59SJohn(Jung-Ik) Lee 	return ATA_CBL_PATA_UNK;
272d15d6e6cSJohn(Jung-Ik) Lee }
273d15d6e6cSJohn(Jung-Ik) Lee 
274d15d6e6cSJohn(Jung-Ik) Lee static struct scsi_host_template atp867x_sht = {
275d15d6e6cSJohn(Jung-Ik) Lee 	ATA_BMDMA_SHT(DRV_NAME),
276d15d6e6cSJohn(Jung-Ik) Lee };
277d15d6e6cSJohn(Jung-Ik) Lee 
278d15d6e6cSJohn(Jung-Ik) Lee static struct ata_port_operations atp867x_ops = {
279d15d6e6cSJohn(Jung-Ik) Lee 	.inherits		= &ata_bmdma_port_ops,
280d15d6e6cSJohn(Jung-Ik) Lee 	.cable_detect		= atp867x_cable_detect,
281d15d6e6cSJohn(Jung-Ik) Lee 	.set_piomode		= atp867x_set_piomode,
282d15d6e6cSJohn(Jung-Ik) Lee 	.set_dmamode		= atp867x_set_dmamode,
283d15d6e6cSJohn(Jung-Ik) Lee };
284d15d6e6cSJohn(Jung-Ik) Lee 
285d15d6e6cSJohn(Jung-Ik) Lee 
286d15d6e6cSJohn(Jung-Ik) Lee #ifdef	ATP867X_DEBUG
287d15d6e6cSJohn(Jung-Ik) Lee static void atp867x_check_res(struct pci_dev *pdev)
288d15d6e6cSJohn(Jung-Ik) Lee {
289d15d6e6cSJohn(Jung-Ik) Lee 	int i;
290d15d6e6cSJohn(Jung-Ik) Lee 	unsigned long start, len;
291d15d6e6cSJohn(Jung-Ik) Lee 
292d15d6e6cSJohn(Jung-Ik) Lee 	/* Check the PCI resources for this channel are enabled */
293d15d6e6cSJohn(Jung-Ik) Lee 	for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
294d15d6e6cSJohn(Jung-Ik) Lee 		start = pci_resource_start(pdev, i);
295d15d6e6cSJohn(Jung-Ik) Lee 		len   = pci_resource_len(pdev, i);
296d15d6e6cSJohn(Jung-Ik) Lee 		printk(KERN_DEBUG "ATP867X: resource start:len=%lx:%lx\n",
297d15d6e6cSJohn(Jung-Ik) Lee 			start, len);
298d15d6e6cSJohn(Jung-Ik) Lee 	}
299d15d6e6cSJohn(Jung-Ik) Lee }
300d15d6e6cSJohn(Jung-Ik) Lee 
301d15d6e6cSJohn(Jung-Ik) Lee static void atp867x_check_ports(struct ata_port *ap, int port)
302d15d6e6cSJohn(Jung-Ik) Lee {
303d15d6e6cSJohn(Jung-Ik) Lee 	struct ata_ioports *ioaddr = &ap->ioaddr;
304d15d6e6cSJohn(Jung-Ik) Lee 	struct atp867x_priv *dp = ap->private_data;
305d15d6e6cSJohn(Jung-Ik) Lee 
306d15d6e6cSJohn(Jung-Ik) Lee 	printk(KERN_DEBUG "ATP867X: port[%d] addresses\n"
307d15d6e6cSJohn(Jung-Ik) Lee 		"  cmd_addr	=0x%llx, 0x%llx\n"
308d15d6e6cSJohn(Jung-Ik) Lee 		"  ctl_addr	=0x%llx, 0x%llx\n"
309d15d6e6cSJohn(Jung-Ik) Lee 		"  bmdma_addr	=0x%llx, 0x%llx\n"
310d15d6e6cSJohn(Jung-Ik) Lee 		"  data_addr	=0x%llx\n"
311d15d6e6cSJohn(Jung-Ik) Lee 		"  error_addr	=0x%llx\n"
312d15d6e6cSJohn(Jung-Ik) Lee 		"  feature_addr	=0x%llx\n"
313d15d6e6cSJohn(Jung-Ik) Lee 		"  nsect_addr	=0x%llx\n"
314d15d6e6cSJohn(Jung-Ik) Lee 		"  lbal_addr	=0x%llx\n"
315d15d6e6cSJohn(Jung-Ik) Lee 		"  lbam_addr	=0x%llx\n"
316d15d6e6cSJohn(Jung-Ik) Lee 		"  lbah_addr	=0x%llx\n"
317d15d6e6cSJohn(Jung-Ik) Lee 		"  device_addr	=0x%llx\n"
318d15d6e6cSJohn(Jung-Ik) Lee 		"  status_addr	=0x%llx\n"
319d15d6e6cSJohn(Jung-Ik) Lee 		"  command_addr	=0x%llx\n"
320d15d6e6cSJohn(Jung-Ik) Lee 		"  dp->dma_mode	=0x%llx\n"
321d15d6e6cSJohn(Jung-Ik) Lee 		"  dp->mstr_piospd	=0x%llx\n"
322d15d6e6cSJohn(Jung-Ik) Lee 		"  dp->slave_piospd	=0x%llx\n"
323d15d6e6cSJohn(Jung-Ik) Lee 		"  dp->eightb_piospd	=0x%llx\n"
324d15d6e6cSJohn(Jung-Ik) Lee 		"  dp->pci66mhz		=0x%lx\n",
325d15d6e6cSJohn(Jung-Ik) Lee 		port,
326d15d6e6cSJohn(Jung-Ik) Lee 		(unsigned long long)ioaddr->cmd_addr,
327d15d6e6cSJohn(Jung-Ik) Lee 		(unsigned long long)ATP867X_IO_PORTBASE(ap, port),
328d15d6e6cSJohn(Jung-Ik) Lee 		(unsigned long long)ioaddr->ctl_addr,
329d15d6e6cSJohn(Jung-Ik) Lee 		(unsigned long long)ATP867X_IO_ALTSTATUS(ap, port),
330d15d6e6cSJohn(Jung-Ik) Lee 		(unsigned long long)ioaddr->bmdma_addr,
331d15d6e6cSJohn(Jung-Ik) Lee 		(unsigned long long)ATP867X_IO_DMABASE(ap, port),
332d15d6e6cSJohn(Jung-Ik) Lee 		(unsigned long long)ioaddr->data_addr,
333d15d6e6cSJohn(Jung-Ik) Lee 		(unsigned long long)ioaddr->error_addr,
334d15d6e6cSJohn(Jung-Ik) Lee 		(unsigned long long)ioaddr->feature_addr,
335d15d6e6cSJohn(Jung-Ik) Lee 		(unsigned long long)ioaddr->nsect_addr,
336d15d6e6cSJohn(Jung-Ik) Lee 		(unsigned long long)ioaddr->lbal_addr,
337d15d6e6cSJohn(Jung-Ik) Lee 		(unsigned long long)ioaddr->lbam_addr,
338d15d6e6cSJohn(Jung-Ik) Lee 		(unsigned long long)ioaddr->lbah_addr,
339d15d6e6cSJohn(Jung-Ik) Lee 		(unsigned long long)ioaddr->device_addr,
340d15d6e6cSJohn(Jung-Ik) Lee 		(unsigned long long)ioaddr->status_addr,
341d15d6e6cSJohn(Jung-Ik) Lee 		(unsigned long long)ioaddr->command_addr,
342d15d6e6cSJohn(Jung-Ik) Lee 		(unsigned long long)dp->dma_mode,
343d15d6e6cSJohn(Jung-Ik) Lee 		(unsigned long long)dp->mstr_piospd,
344d15d6e6cSJohn(Jung-Ik) Lee 		(unsigned long long)dp->slave_piospd,
345d15d6e6cSJohn(Jung-Ik) Lee 		(unsigned long long)dp->eightb_piospd,
346d15d6e6cSJohn(Jung-Ik) Lee 		(unsigned long)dp->pci66mhz);
347d15d6e6cSJohn(Jung-Ik) Lee }
348d15d6e6cSJohn(Jung-Ik) Lee #endif
349d15d6e6cSJohn(Jung-Ik) Lee 
350d15d6e6cSJohn(Jung-Ik) Lee static int atp867x_set_priv(struct ata_port *ap)
351d15d6e6cSJohn(Jung-Ik) Lee {
352d15d6e6cSJohn(Jung-Ik) Lee 	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
353d15d6e6cSJohn(Jung-Ik) Lee 	struct atp867x_priv *dp;
354d15d6e6cSJohn(Jung-Ik) Lee 	int port = ap->port_no;
355d15d6e6cSJohn(Jung-Ik) Lee 
356d15d6e6cSJohn(Jung-Ik) Lee 	dp = ap->private_data =
357d15d6e6cSJohn(Jung-Ik) Lee 		devm_kzalloc(&pdev->dev, sizeof(*dp), GFP_KERNEL);
358d15d6e6cSJohn(Jung-Ik) Lee 	if (dp == NULL)
359d15d6e6cSJohn(Jung-Ik) Lee 		return -ENOMEM;
360d15d6e6cSJohn(Jung-Ik) Lee 
361d15d6e6cSJohn(Jung-Ik) Lee 	dp->dma_mode	 = ATP867X_IO_DMAMODE(ap, port);
362d15d6e6cSJohn(Jung-Ik) Lee 	dp->mstr_piospd	 = ATP867X_IO_MSTRPIOSPD(ap, port);
363d15d6e6cSJohn(Jung-Ik) Lee 	dp->slave_piospd = ATP867X_IO_SLAVPIOSPD(ap, port);
364d15d6e6cSJohn(Jung-Ik) Lee 	dp->eightb_piospd = ATP867X_IO_8BPIOSPD(ap, port);
365d15d6e6cSJohn(Jung-Ik) Lee 
366d15d6e6cSJohn(Jung-Ik) Lee 	dp->pci66mhz =
367d15d6e6cSJohn(Jung-Ik) Lee 		ioread8(ATP867X_SYS_INFO(ap)) & ATP867X_IO_SYS_INFO_66MHZ;
368d15d6e6cSJohn(Jung-Ik) Lee 
369d15d6e6cSJohn(Jung-Ik) Lee 	return 0;
370d15d6e6cSJohn(Jung-Ik) Lee }
371d15d6e6cSJohn(Jung-Ik) Lee 
372d15d6e6cSJohn(Jung-Ik) Lee static void atp867x_fixup(struct ata_host *host)
373d15d6e6cSJohn(Jung-Ik) Lee {
374d15d6e6cSJohn(Jung-Ik) Lee 	struct pci_dev *pdev = to_pci_dev(host->dev);
375d15d6e6cSJohn(Jung-Ik) Lee 	struct ata_port *ap = host->ports[0];
376d15d6e6cSJohn(Jung-Ik) Lee 	int i;
377d15d6e6cSJohn(Jung-Ik) Lee 	u8 v;
378d15d6e6cSJohn(Jung-Ik) Lee 
379d15d6e6cSJohn(Jung-Ik) Lee 	/*
380d15d6e6cSJohn(Jung-Ik) Lee 	 * Broken BIOS might not set latency high enough
381d15d6e6cSJohn(Jung-Ik) Lee 	 */
382d15d6e6cSJohn(Jung-Ik) Lee 	pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &v);
383d15d6e6cSJohn(Jung-Ik) Lee 	if (v < 0x80) {
384d15d6e6cSJohn(Jung-Ik) Lee 		v = 0x80;
385d15d6e6cSJohn(Jung-Ik) Lee 		pci_write_config_byte(pdev, PCI_LATENCY_TIMER, v);
386d15d6e6cSJohn(Jung-Ik) Lee 		printk(KERN_DEBUG "ATP867X: set latency timer of device %s"
387d15d6e6cSJohn(Jung-Ik) Lee 			" to %d\n", pci_name(pdev), v);
388d15d6e6cSJohn(Jung-Ik) Lee 	}
389d15d6e6cSJohn(Jung-Ik) Lee 
390d15d6e6cSJohn(Jung-Ik) Lee 	/*
391d15d6e6cSJohn(Jung-Ik) Lee 	 * init 8bit io ports speed(0aaarrrr) to 43h and
392d15d6e6cSJohn(Jung-Ik) Lee 	 * init udma modes of master/slave to 0/0(11h)
393d15d6e6cSJohn(Jung-Ik) Lee 	 */
394d15d6e6cSJohn(Jung-Ik) Lee 	for (i = 0; i < ATP867X_NUM_PORTS; i++)
395d15d6e6cSJohn(Jung-Ik) Lee 		iowrite16(ATP867X_IO_PORTSPD_VAL, ATP867X_IO_PORTSPD(ap, i));
396d15d6e6cSJohn(Jung-Ik) Lee 
397d15d6e6cSJohn(Jung-Ik) Lee 	/*
398d15d6e6cSJohn(Jung-Ik) Lee 	 * init PreREAD counts
399d15d6e6cSJohn(Jung-Ik) Lee 	 */
400d15d6e6cSJohn(Jung-Ik) Lee 	for (i = 0; i < ATP867X_NUM_PORTS; i++)
401d15d6e6cSJohn(Jung-Ik) Lee 		iowrite16(ATP867X_PREREAD_VAL, ATP867X_IO_PREREAD(ap, i));
402d15d6e6cSJohn(Jung-Ik) Lee 
403d15d6e6cSJohn(Jung-Ik) Lee 	v = ioread8(ATP867X_IOBASE(ap) + 0x28);
404d15d6e6cSJohn(Jung-Ik) Lee 	v &= 0xcf;	/* Enable INTA#: bit4=0 means enable */
405d15d6e6cSJohn(Jung-Ik) Lee 	v |= 0xc0;	/* Enable PCI burst, MRM & not immediate interrupts */
406d15d6e6cSJohn(Jung-Ik) Lee 	iowrite8(v, ATP867X_IOBASE(ap) + 0x28);
407d15d6e6cSJohn(Jung-Ik) Lee 
408d15d6e6cSJohn(Jung-Ik) Lee 	/*
409d15d6e6cSJohn(Jung-Ik) Lee 	 * Turn off the over clocked udma5 mode, only for Rev-B
410d15d6e6cSJohn(Jung-Ik) Lee 	 */
411d15d6e6cSJohn(Jung-Ik) Lee 	v = ioread8(ATP867X_SYS_INFO(ap));
412d15d6e6cSJohn(Jung-Ik) Lee 	v &= ATP867X_IO_SYS_MASK_RESERVED;
413d15d6e6cSJohn(Jung-Ik) Lee 	if (pdev->device == PCI_DEVICE_ID_ARTOP_ATP867B)
414d15d6e6cSJohn(Jung-Ik) Lee 		v |= ATP867X_IO_SYS_INFO_SLOW_UDMA5;
415d15d6e6cSJohn(Jung-Ik) Lee 	iowrite8(v, ATP867X_SYS_INFO(ap));
416d15d6e6cSJohn(Jung-Ik) Lee }
417d15d6e6cSJohn(Jung-Ik) Lee 
418d15d6e6cSJohn(Jung-Ik) Lee static int atp867x_ata_pci_sff_init_host(struct ata_host *host)
419d15d6e6cSJohn(Jung-Ik) Lee {
420d15d6e6cSJohn(Jung-Ik) Lee 	struct device *gdev = host->dev;
421d15d6e6cSJohn(Jung-Ik) Lee 	struct pci_dev *pdev = to_pci_dev(gdev);
422d15d6e6cSJohn(Jung-Ik) Lee 	unsigned int mask = 0;
423d15d6e6cSJohn(Jung-Ik) Lee 	int i, rc;
424d15d6e6cSJohn(Jung-Ik) Lee 
425d15d6e6cSJohn(Jung-Ik) Lee 	/*
426d15d6e6cSJohn(Jung-Ik) Lee 	 * do not map rombase
427d15d6e6cSJohn(Jung-Ik) Lee 	 */
428d15d6e6cSJohn(Jung-Ik) Lee 	rc = pcim_iomap_regions(pdev, 1 << ATP867X_BAR_IOBASE, DRV_NAME);
429d15d6e6cSJohn(Jung-Ik) Lee 	if (rc == -EBUSY)
430d15d6e6cSJohn(Jung-Ik) Lee 		pcim_pin_device(pdev);
431d15d6e6cSJohn(Jung-Ik) Lee 	if (rc)
432d15d6e6cSJohn(Jung-Ik) Lee 		return rc;
433d15d6e6cSJohn(Jung-Ik) Lee 	host->iomap = pcim_iomap_table(pdev);
434d15d6e6cSJohn(Jung-Ik) Lee 
435d15d6e6cSJohn(Jung-Ik) Lee #ifdef	ATP867X_DEBUG
436d15d6e6cSJohn(Jung-Ik) Lee 	atp867x_check_res(pdev);
437d15d6e6cSJohn(Jung-Ik) Lee 
438d15d6e6cSJohn(Jung-Ik) Lee 	for (i = 0; i < PCI_ROM_RESOURCE; i++)
439d15d6e6cSJohn(Jung-Ik) Lee 		printk(KERN_DEBUG "ATP867X: iomap[%d]=0x%llx\n", i,
440d15d6e6cSJohn(Jung-Ik) Lee 			(unsigned long long)(host->iomap[i]));
441d15d6e6cSJohn(Jung-Ik) Lee #endif
442d15d6e6cSJohn(Jung-Ik) Lee 
443d15d6e6cSJohn(Jung-Ik) Lee 	/*
444d15d6e6cSJohn(Jung-Ik) Lee 	 * request, iomap BARs and init port addresses accordingly
445d15d6e6cSJohn(Jung-Ik) Lee 	 */
446d15d6e6cSJohn(Jung-Ik) Lee 	for (i = 0; i < host->n_ports; i++) {
447d15d6e6cSJohn(Jung-Ik) Lee 		struct ata_port *ap = host->ports[i];
448d15d6e6cSJohn(Jung-Ik) Lee 		struct ata_ioports *ioaddr = &ap->ioaddr;
449d15d6e6cSJohn(Jung-Ik) Lee 
450d15d6e6cSJohn(Jung-Ik) Lee 		ioaddr->cmd_addr = ATP867X_IO_PORTBASE(ap, i);
451d15d6e6cSJohn(Jung-Ik) Lee 		ioaddr->ctl_addr = ioaddr->altstatus_addr
452d15d6e6cSJohn(Jung-Ik) Lee 				 = ATP867X_IO_ALTSTATUS(ap, i);
453d15d6e6cSJohn(Jung-Ik) Lee 		ioaddr->bmdma_addr = ATP867X_IO_DMABASE(ap, i);
454d15d6e6cSJohn(Jung-Ik) Lee 
455d15d6e6cSJohn(Jung-Ik) Lee 		ata_sff_std_ports(ioaddr);
456d15d6e6cSJohn(Jung-Ik) Lee 		rc = atp867x_set_priv(ap);
457d15d6e6cSJohn(Jung-Ik) Lee 		if (rc)
458d15d6e6cSJohn(Jung-Ik) Lee 			return rc;
459d15d6e6cSJohn(Jung-Ik) Lee 
460d15d6e6cSJohn(Jung-Ik) Lee #ifdef	ATP867X_DEBUG
461d15d6e6cSJohn(Jung-Ik) Lee 		atp867x_check_ports(ap, i);
462d15d6e6cSJohn(Jung-Ik) Lee #endif
463d15d6e6cSJohn(Jung-Ik) Lee 		ata_port_desc(ap, "cmd 0x%lx ctl 0x%lx",
464d15d6e6cSJohn(Jung-Ik) Lee 			(unsigned long)ioaddr->cmd_addr,
465d15d6e6cSJohn(Jung-Ik) Lee 			(unsigned long)ioaddr->ctl_addr);
466d15d6e6cSJohn(Jung-Ik) Lee 		ata_port_desc(ap, "bmdma 0x%lx",
467d15d6e6cSJohn(Jung-Ik) Lee 			(unsigned long)ioaddr->bmdma_addr);
468d15d6e6cSJohn(Jung-Ik) Lee 
469d15d6e6cSJohn(Jung-Ik) Lee 		mask |= 1 << i;
470d15d6e6cSJohn(Jung-Ik) Lee 	}
471d15d6e6cSJohn(Jung-Ik) Lee 
472d15d6e6cSJohn(Jung-Ik) Lee 	if (!mask) {
473a44fec1fSJoe Perches 		dev_err(gdev, "no available native port\n");
474d15d6e6cSJohn(Jung-Ik) Lee 		return -ENODEV;
475d15d6e6cSJohn(Jung-Ik) Lee 	}
476d15d6e6cSJohn(Jung-Ik) Lee 
477d15d6e6cSJohn(Jung-Ik) Lee 	atp867x_fixup(host);
478d15d6e6cSJohn(Jung-Ik) Lee 
479d15d6e6cSJohn(Jung-Ik) Lee 	rc = pci_set_dma_mask(pdev, ATA_DMA_MASK);
480d15d6e6cSJohn(Jung-Ik) Lee 	if (rc)
481d15d6e6cSJohn(Jung-Ik) Lee 		return rc;
482d15d6e6cSJohn(Jung-Ik) Lee 
483d15d6e6cSJohn(Jung-Ik) Lee 	rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK);
484d15d6e6cSJohn(Jung-Ik) Lee 	return rc;
485d15d6e6cSJohn(Jung-Ik) Lee }
486d15d6e6cSJohn(Jung-Ik) Lee 
487d15d6e6cSJohn(Jung-Ik) Lee static int atp867x_init_one(struct pci_dev *pdev,
488d15d6e6cSJohn(Jung-Ik) Lee 	const struct pci_device_id *id)
489d15d6e6cSJohn(Jung-Ik) Lee {
490d15d6e6cSJohn(Jung-Ik) Lee 	static int printed_version;
491d15d6e6cSJohn(Jung-Ik) Lee 	static const struct ata_port_info info_867x = {
492d15d6e6cSJohn(Jung-Ik) Lee 		.flags		= ATA_FLAG_SLAVE_POSS,
493d15d6e6cSJohn(Jung-Ik) Lee 		.pio_mask	= ATA_PIO4,
494d15d6e6cSJohn(Jung-Ik) Lee 		.udma_mask 	= ATA_UDMA6,
495d15d6e6cSJohn(Jung-Ik) Lee 		.port_ops	= &atp867x_ops,
496d15d6e6cSJohn(Jung-Ik) Lee 	};
497d15d6e6cSJohn(Jung-Ik) Lee 
498d15d6e6cSJohn(Jung-Ik) Lee 	struct ata_host *host;
499d15d6e6cSJohn(Jung-Ik) Lee 	const struct ata_port_info *ppi[] = { &info_867x, NULL };
500d15d6e6cSJohn(Jung-Ik) Lee 	int rc;
501d15d6e6cSJohn(Jung-Ik) Lee 
502d15d6e6cSJohn(Jung-Ik) Lee 	if (!printed_version++)
503a44fec1fSJoe Perches 		dev_info(&pdev->dev, "version " DRV_VERSION "\n");
504d15d6e6cSJohn(Jung-Ik) Lee 
505d15d6e6cSJohn(Jung-Ik) Lee 	rc = pcim_enable_device(pdev);
506d15d6e6cSJohn(Jung-Ik) Lee 	if (rc)
507d15d6e6cSJohn(Jung-Ik) Lee 		return rc;
508d15d6e6cSJohn(Jung-Ik) Lee 
509d15d6e6cSJohn(Jung-Ik) Lee 	printk(KERN_INFO "ATP867X: ATP867 ATA UDMA133 controller (rev %02X)",
510d15d6e6cSJohn(Jung-Ik) Lee 		pdev->device);
511d15d6e6cSJohn(Jung-Ik) Lee 
512d15d6e6cSJohn(Jung-Ik) Lee 	host = ata_host_alloc_pinfo(&pdev->dev, ppi, ATP867X_NUM_PORTS);
513d15d6e6cSJohn(Jung-Ik) Lee 	if (!host) {
514a44fec1fSJoe Perches 		dev_err(&pdev->dev, "failed to allocate ATA host\n");
515d15d6e6cSJohn(Jung-Ik) Lee 		rc = -ENOMEM;
516d15d6e6cSJohn(Jung-Ik) Lee 		goto err_out;
517d15d6e6cSJohn(Jung-Ik) Lee 	}
518d15d6e6cSJohn(Jung-Ik) Lee 
519d15d6e6cSJohn(Jung-Ik) Lee 	rc = atp867x_ata_pci_sff_init_host(host);
520d15d6e6cSJohn(Jung-Ik) Lee 	if (rc) {
521a44fec1fSJoe Perches 		dev_err(&pdev->dev, "failed to init host\n");
522d15d6e6cSJohn(Jung-Ik) Lee 		goto err_out;
523d15d6e6cSJohn(Jung-Ik) Lee 	}
524d15d6e6cSJohn(Jung-Ik) Lee 
525d15d6e6cSJohn(Jung-Ik) Lee 	pci_set_master(pdev);
526d15d6e6cSJohn(Jung-Ik) Lee 
527c3b28894STejun Heo 	rc = ata_host_activate(host, pdev->irq, ata_bmdma_interrupt,
528d15d6e6cSJohn(Jung-Ik) Lee 				IRQF_SHARED, &atp867x_sht);
529d15d6e6cSJohn(Jung-Ik) Lee 	if (rc)
530a44fec1fSJoe Perches 		dev_err(&pdev->dev, "failed to activate host\n");
531d15d6e6cSJohn(Jung-Ik) Lee 
532d15d6e6cSJohn(Jung-Ik) Lee err_out:
533d15d6e6cSJohn(Jung-Ik) Lee 	return rc;
534d15d6e6cSJohn(Jung-Ik) Lee }
535d15d6e6cSJohn(Jung-Ik) Lee 
5367affb32aSBartlomiej Zolnierkiewicz #ifdef CONFIG_PM
5377affb32aSBartlomiej Zolnierkiewicz static int atp867x_reinit_one(struct pci_dev *pdev)
5387affb32aSBartlomiej Zolnierkiewicz {
5397affb32aSBartlomiej Zolnierkiewicz 	struct ata_host *host = dev_get_drvdata(&pdev->dev);
5407affb32aSBartlomiej Zolnierkiewicz 	int rc;
5417affb32aSBartlomiej Zolnierkiewicz 
5427affb32aSBartlomiej Zolnierkiewicz 	rc = ata_pci_device_do_resume(pdev);
5437affb32aSBartlomiej Zolnierkiewicz 	if (rc)
5447affb32aSBartlomiej Zolnierkiewicz 		return rc;
5457affb32aSBartlomiej Zolnierkiewicz 
5467affb32aSBartlomiej Zolnierkiewicz 	atp867x_fixup(host);
5477affb32aSBartlomiej Zolnierkiewicz 
5487affb32aSBartlomiej Zolnierkiewicz 	ata_host_resume(host);
5497affb32aSBartlomiej Zolnierkiewicz 	return 0;
5507affb32aSBartlomiej Zolnierkiewicz }
5517affb32aSBartlomiej Zolnierkiewicz #endif
5527affb32aSBartlomiej Zolnierkiewicz 
553d15d6e6cSJohn(Jung-Ik) Lee static struct pci_device_id atp867x_pci_tbl[] = {
554d15d6e6cSJohn(Jung-Ik) Lee 	{ PCI_VDEVICE(ARTOP, PCI_DEVICE_ID_ARTOP_ATP867A),	0 },
555d15d6e6cSJohn(Jung-Ik) Lee 	{ PCI_VDEVICE(ARTOP, PCI_DEVICE_ID_ARTOP_ATP867B),	0 },
556d15d6e6cSJohn(Jung-Ik) Lee 	{ },
557d15d6e6cSJohn(Jung-Ik) Lee };
558d15d6e6cSJohn(Jung-Ik) Lee 
559d15d6e6cSJohn(Jung-Ik) Lee static struct pci_driver atp867x_driver = {
560d15d6e6cSJohn(Jung-Ik) Lee 	.name 		= DRV_NAME,
561d15d6e6cSJohn(Jung-Ik) Lee 	.id_table 	= atp867x_pci_tbl,
562d15d6e6cSJohn(Jung-Ik) Lee 	.probe 		= atp867x_init_one,
563d15d6e6cSJohn(Jung-Ik) Lee 	.remove		= ata_pci_remove_one,
5647affb32aSBartlomiej Zolnierkiewicz #ifdef CONFIG_PM
5657affb32aSBartlomiej Zolnierkiewicz 	.suspend	= ata_pci_device_suspend,
5667affb32aSBartlomiej Zolnierkiewicz 	.resume		= atp867x_reinit_one,
5677affb32aSBartlomiej Zolnierkiewicz #endif
568d15d6e6cSJohn(Jung-Ik) Lee };
569d15d6e6cSJohn(Jung-Ik) Lee 
570d15d6e6cSJohn(Jung-Ik) Lee static int __init atp867x_init(void)
571d15d6e6cSJohn(Jung-Ik) Lee {
572d15d6e6cSJohn(Jung-Ik) Lee 	return pci_register_driver(&atp867x_driver);
573d15d6e6cSJohn(Jung-Ik) Lee }
574d15d6e6cSJohn(Jung-Ik) Lee 
575d15d6e6cSJohn(Jung-Ik) Lee static void __exit atp867x_exit(void)
576d15d6e6cSJohn(Jung-Ik) Lee {
577d15d6e6cSJohn(Jung-Ik) Lee 	pci_unregister_driver(&atp867x_driver);
578d15d6e6cSJohn(Jung-Ik) Lee }
579d15d6e6cSJohn(Jung-Ik) Lee 
580d15d6e6cSJohn(Jung-Ik) Lee MODULE_AUTHOR("John(Jung-Ik) Lee, Google Inc.");
581d15d6e6cSJohn(Jung-Ik) Lee MODULE_DESCRIPTION("low level driver for Artop/Acard 867x ATA controller");
582d15d6e6cSJohn(Jung-Ik) Lee MODULE_LICENSE("GPL");
583d15d6e6cSJohn(Jung-Ik) Lee MODULE_DEVICE_TABLE(pci, atp867x_pci_tbl);
584d15d6e6cSJohn(Jung-Ik) Lee MODULE_VERSION(DRV_VERSION);
585d15d6e6cSJohn(Jung-Ik) Lee 
586d15d6e6cSJohn(Jung-Ik) Lee module_init(atp867x_init);
587d15d6e6cSJohn(Jung-Ik) Lee module_exit(atp867x_exit);
588