xref: /OK3568_Linux_fs/u-boot/drivers/ata/sata_sil3114.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * Copyright (C) Excito Elektronik i Skåne AB, All rights reserved.
3*4882a593Smuzhiyun  * Author: Tor Krill <tor@excito.com>
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * SPDX-License-Identifier:	GPL-2.0+
6*4882a593Smuzhiyun  *
7*4882a593Smuzhiyun  * This is a driver for Silicon Image sil3114 sata chip modelled on
8*4882a593Smuzhiyun  * the ata_piix driver
9*4882a593Smuzhiyun  */
10*4882a593Smuzhiyun 
11*4882a593Smuzhiyun #include <common.h>
12*4882a593Smuzhiyun #include <pci.h>
13*4882a593Smuzhiyun #include <command.h>
14*4882a593Smuzhiyun #include <config.h>
15*4882a593Smuzhiyun #include <asm/byteorder.h>
16*4882a593Smuzhiyun #include <asm/io.h>
17*4882a593Smuzhiyun #include <ide.h>
18*4882a593Smuzhiyun #include <sata.h>
19*4882a593Smuzhiyun #include <libata.h>
20*4882a593Smuzhiyun #include "sata_sil3114.h"
21*4882a593Smuzhiyun 
22*4882a593Smuzhiyun /* Convert sectorsize to wordsize */
23*4882a593Smuzhiyun #define ATA_SECTOR_WORDS (ATA_SECT_SIZE/2)
24*4882a593Smuzhiyun 
25*4882a593Smuzhiyun /* Forwards */
26*4882a593Smuzhiyun u8 sil3114_spin_up (int num);
27*4882a593Smuzhiyun u8 sil3114_spin_down (int num);
28*4882a593Smuzhiyun static int sata_bus_softreset (int num);
29*4882a593Smuzhiyun static void sata_identify (int num, int dev);
30*4882a593Smuzhiyun static u8 check_power_mode (int num);
31*4882a593Smuzhiyun static void sata_port (struct sata_ioports *ioport);
32*4882a593Smuzhiyun static void set_Feature_cmd (int num, int dev);
33*4882a593Smuzhiyun static u8 sata_busy_wait (struct sata_ioports *ioaddr, int bits,
34*4882a593Smuzhiyun 			  unsigned int max, u8 usealtstatus);
35*4882a593Smuzhiyun static u8 sata_chk_status (struct sata_ioports *ioaddr, u8 usealtstatus);
36*4882a593Smuzhiyun static void msleep (int count);
37*4882a593Smuzhiyun 
38*4882a593Smuzhiyun static u32 iobase[6] = { 0, 0, 0, 0, 0, 0};	/* PCI BAR registers for device */
39*4882a593Smuzhiyun 
40*4882a593Smuzhiyun static struct sata_port port[CONFIG_SYS_SATA_MAX_DEVICE];
41*4882a593Smuzhiyun 
output_data(struct sata_ioports * ioaddr,u16 * sect_buf,int words)42*4882a593Smuzhiyun static void output_data (struct sata_ioports *ioaddr, u16 * sect_buf, int words)
43*4882a593Smuzhiyun {
44*4882a593Smuzhiyun 	while (words--) {
45*4882a593Smuzhiyun 		__raw_writew (*sect_buf++, (void *)ioaddr->data_addr);
46*4882a593Smuzhiyun 	}
47*4882a593Smuzhiyun }
48*4882a593Smuzhiyun 
input_data(struct sata_ioports * ioaddr,u16 * sect_buf,int words)49*4882a593Smuzhiyun static int input_data (struct sata_ioports *ioaddr, u16 * sect_buf, int words)
50*4882a593Smuzhiyun {
51*4882a593Smuzhiyun 	while (words--) {
52*4882a593Smuzhiyun 		*sect_buf++ = __raw_readw ((void *)ioaddr->data_addr);
53*4882a593Smuzhiyun 	}
54*4882a593Smuzhiyun 	return 0;
55*4882a593Smuzhiyun }
56*4882a593Smuzhiyun 
sata_bus_softreset(int num)57*4882a593Smuzhiyun static int sata_bus_softreset (int num)
58*4882a593Smuzhiyun {
59*4882a593Smuzhiyun 	u8 status = 0;
60*4882a593Smuzhiyun 
61*4882a593Smuzhiyun 	port[num].dev_mask = 1;
62*4882a593Smuzhiyun 
63*4882a593Smuzhiyun 	port[num].ctl_reg = 0x08;	/*Default value of control reg */
64*4882a593Smuzhiyun 	writeb (port[num].ctl_reg, port[num].ioaddr.ctl_addr);
65*4882a593Smuzhiyun 	udelay (10);
66*4882a593Smuzhiyun 	writeb (port[num].ctl_reg | ATA_SRST, port[num].ioaddr.ctl_addr);
67*4882a593Smuzhiyun 	udelay (10);
68*4882a593Smuzhiyun 	writeb (port[num].ctl_reg, port[num].ioaddr.ctl_addr);
69*4882a593Smuzhiyun 
70*4882a593Smuzhiyun 	/* spec mandates ">= 2ms" before checking status.
71*4882a593Smuzhiyun 	 * We wait 150ms, because that was the magic delay used for
72*4882a593Smuzhiyun 	 * ATAPI devices in Hale Landis's ATADRVR, for the period of time
73*4882a593Smuzhiyun 	 * between when the ATA command register is written, and then
74*4882a593Smuzhiyun 	 * status is checked.  Because waiting for "a while" before
75*4882a593Smuzhiyun 	 * checking status is fine, post SRST, we perform this magic
76*4882a593Smuzhiyun 	 * delay here as well.
77*4882a593Smuzhiyun 	 */
78*4882a593Smuzhiyun 	msleep (150);
79*4882a593Smuzhiyun 	status = sata_busy_wait (&port[num].ioaddr, ATA_BUSY, 300, 0);
80*4882a593Smuzhiyun 	while ((status & ATA_BUSY)) {
81*4882a593Smuzhiyun 		msleep (100);
82*4882a593Smuzhiyun 		status = sata_busy_wait (&port[num].ioaddr, ATA_BUSY, 3, 0);
83*4882a593Smuzhiyun 	}
84*4882a593Smuzhiyun 
85*4882a593Smuzhiyun 	if (status & ATA_BUSY) {
86*4882a593Smuzhiyun 		printf ("ata%u is slow to respond,plz be patient\n", num);
87*4882a593Smuzhiyun 	}
88*4882a593Smuzhiyun 
89*4882a593Smuzhiyun 	while ((status & ATA_BUSY)) {
90*4882a593Smuzhiyun 		msleep (100);
91*4882a593Smuzhiyun 		status = sata_chk_status (&port[num].ioaddr, 0);
92*4882a593Smuzhiyun 	}
93*4882a593Smuzhiyun 
94*4882a593Smuzhiyun 	if (status & ATA_BUSY) {
95*4882a593Smuzhiyun 		printf ("ata%u failed to respond : ", num);
96*4882a593Smuzhiyun 		printf ("bus reset failed\n");
97*4882a593Smuzhiyun 		port[num].dev_mask = 0;
98*4882a593Smuzhiyun 		return 1;
99*4882a593Smuzhiyun 	}
100*4882a593Smuzhiyun 	return 0;
101*4882a593Smuzhiyun }
102*4882a593Smuzhiyun 
sata_identify(int num,int dev)103*4882a593Smuzhiyun static void sata_identify (int num, int dev)
104*4882a593Smuzhiyun {
105*4882a593Smuzhiyun 	u8 cmd = 0, status = 0, devno = num;
106*4882a593Smuzhiyun 	u16 iobuf[ATA_SECTOR_WORDS];
107*4882a593Smuzhiyun 	u64 n_sectors = 0;
108*4882a593Smuzhiyun 
109*4882a593Smuzhiyun 	memset (iobuf, 0, sizeof (iobuf));
110*4882a593Smuzhiyun 
111*4882a593Smuzhiyun 	if (!(port[num].dev_mask & 0x01)) {
112*4882a593Smuzhiyun 		printf ("dev%d is not present on port#%d\n", dev, num);
113*4882a593Smuzhiyun 		return;
114*4882a593Smuzhiyun 	}
115*4882a593Smuzhiyun 
116*4882a593Smuzhiyun 	debug ("port=%d dev=%d\n", num, dev);
117*4882a593Smuzhiyun 
118*4882a593Smuzhiyun 	status = 0;
119*4882a593Smuzhiyun 	cmd = ATA_CMD_ID_ATA;	/*Device Identify Command */
120*4882a593Smuzhiyun 	writeb (cmd, port[num].ioaddr.command_addr);
121*4882a593Smuzhiyun 	readb (port[num].ioaddr.altstatus_addr);
122*4882a593Smuzhiyun 	udelay (10);
123*4882a593Smuzhiyun 
124*4882a593Smuzhiyun 	status = sata_busy_wait (&port[num].ioaddr, ATA_BUSY, 1000, 0);
125*4882a593Smuzhiyun 	if (status & ATA_ERR) {
126*4882a593Smuzhiyun 		printf ("\ndevice not responding\n");
127*4882a593Smuzhiyun 		port[num].dev_mask &= ~0x01;
128*4882a593Smuzhiyun 		return;
129*4882a593Smuzhiyun 	}
130*4882a593Smuzhiyun 
131*4882a593Smuzhiyun 	input_data (&port[num].ioaddr, iobuf, ATA_SECTOR_WORDS);
132*4882a593Smuzhiyun 
133*4882a593Smuzhiyun 	ata_swap_buf_le16 (iobuf, ATA_SECTOR_WORDS);
134*4882a593Smuzhiyun 
135*4882a593Smuzhiyun 	debug ("Specific config: %x\n", iobuf[2]);
136*4882a593Smuzhiyun 
137*4882a593Smuzhiyun 	/* we require LBA and DMA support (bits 8 & 9 of word 49) */
138*4882a593Smuzhiyun 	if (!ata_id_has_dma (iobuf) || !ata_id_has_lba (iobuf)) {
139*4882a593Smuzhiyun 		debug ("ata%u: no dma/lba\n", num);
140*4882a593Smuzhiyun 	}
141*4882a593Smuzhiyun #ifdef DEBUG
142*4882a593Smuzhiyun 	ata_dump_id (iobuf);
143*4882a593Smuzhiyun #endif
144*4882a593Smuzhiyun 	n_sectors = ata_id_n_sectors (iobuf);
145*4882a593Smuzhiyun 
146*4882a593Smuzhiyun 	if (n_sectors == 0) {
147*4882a593Smuzhiyun 		port[num].dev_mask &= ~0x01;
148*4882a593Smuzhiyun 		return;
149*4882a593Smuzhiyun 	}
150*4882a593Smuzhiyun 	ata_id_c_string (iobuf, (unsigned char *)sata_dev_desc[devno].revision,
151*4882a593Smuzhiyun 			 ATA_ID_FW_REV, sizeof (sata_dev_desc[devno].revision));
152*4882a593Smuzhiyun 	ata_id_c_string (iobuf, (unsigned char *)sata_dev_desc[devno].vendor,
153*4882a593Smuzhiyun 			 ATA_ID_PROD, sizeof (sata_dev_desc[devno].vendor));
154*4882a593Smuzhiyun 	ata_id_c_string (iobuf, (unsigned char *)sata_dev_desc[devno].product,
155*4882a593Smuzhiyun 			 ATA_ID_SERNO, sizeof (sata_dev_desc[devno].product));
156*4882a593Smuzhiyun 
157*4882a593Smuzhiyun 	/* TODO - atm we asume harddisk ie not removable */
158*4882a593Smuzhiyun 	sata_dev_desc[devno].removable = 0;
159*4882a593Smuzhiyun 
160*4882a593Smuzhiyun 	sata_dev_desc[devno].lba = (u32) n_sectors;
161*4882a593Smuzhiyun 	debug("lba=0x%lx\n", sata_dev_desc[devno].lba);
162*4882a593Smuzhiyun 
163*4882a593Smuzhiyun #ifdef CONFIG_LBA48
164*4882a593Smuzhiyun 	if (iobuf[83] & (1 << 10)) {
165*4882a593Smuzhiyun 		sata_dev_desc[devno].lba48 = 1;
166*4882a593Smuzhiyun 	} else {
167*4882a593Smuzhiyun 		sata_dev_desc[devno].lba48 = 0;
168*4882a593Smuzhiyun 	}
169*4882a593Smuzhiyun #endif
170*4882a593Smuzhiyun 
171*4882a593Smuzhiyun 	/* assuming HD */
172*4882a593Smuzhiyun 	sata_dev_desc[devno].type = DEV_TYPE_HARDDISK;
173*4882a593Smuzhiyun 	sata_dev_desc[devno].blksz = ATA_SECT_SIZE;
174*4882a593Smuzhiyun 	sata_dev_desc[devno].lun = 0;	/* just to fill something in... */
175*4882a593Smuzhiyun }
176*4882a593Smuzhiyun 
set_Feature_cmd(int num,int dev)177*4882a593Smuzhiyun static void set_Feature_cmd (int num, int dev)
178*4882a593Smuzhiyun {
179*4882a593Smuzhiyun 	u8 status = 0;
180*4882a593Smuzhiyun 
181*4882a593Smuzhiyun 	if (!(port[num].dev_mask & 0x01)) {
182*4882a593Smuzhiyun 		debug ("dev%d is not present on port#%d\n", dev, num);
183*4882a593Smuzhiyun 		return;
184*4882a593Smuzhiyun 	}
185*4882a593Smuzhiyun 
186*4882a593Smuzhiyun 	writeb (SETFEATURES_XFER, port[num].ioaddr.feature_addr);
187*4882a593Smuzhiyun 	writeb (XFER_PIO_4, port[num].ioaddr.nsect_addr);
188*4882a593Smuzhiyun 	writeb (0, port[num].ioaddr.lbal_addr);
189*4882a593Smuzhiyun 	writeb (0, port[num].ioaddr.lbam_addr);
190*4882a593Smuzhiyun 	writeb (0, port[num].ioaddr.lbah_addr);
191*4882a593Smuzhiyun 
192*4882a593Smuzhiyun 	writeb (ATA_DEVICE_OBS, port[num].ioaddr.device_addr);
193*4882a593Smuzhiyun 	writeb (ATA_CMD_SET_FEATURES, port[num].ioaddr.command_addr);
194*4882a593Smuzhiyun 
195*4882a593Smuzhiyun 	udelay (50);
196*4882a593Smuzhiyun 	msleep (150);
197*4882a593Smuzhiyun 
198*4882a593Smuzhiyun 	status = sata_busy_wait (&port[num].ioaddr, ATA_BUSY, 5000, 0);
199*4882a593Smuzhiyun 	if ((status & (ATA_BUSY | ATA_ERR))) {
200*4882a593Smuzhiyun 		printf ("Error  : status 0x%02x\n", status);
201*4882a593Smuzhiyun 		port[num].dev_mask &= ~0x01;
202*4882a593Smuzhiyun 	}
203*4882a593Smuzhiyun }
204*4882a593Smuzhiyun 
sil3114_spin_down(int num)205*4882a593Smuzhiyun u8 sil3114_spin_down (int num)
206*4882a593Smuzhiyun {
207*4882a593Smuzhiyun 	u8 status = 0;
208*4882a593Smuzhiyun 
209*4882a593Smuzhiyun 	debug ("Spin down disk\n");
210*4882a593Smuzhiyun 
211*4882a593Smuzhiyun 	if (!(port[num].dev_mask & 0x01)) {
212*4882a593Smuzhiyun 		debug ("Device ata%d is not present\n", num);
213*4882a593Smuzhiyun 		return 1;
214*4882a593Smuzhiyun 	}
215*4882a593Smuzhiyun 
216*4882a593Smuzhiyun 	if ((status = check_power_mode (num)) == 0x00) {
217*4882a593Smuzhiyun 		debug ("Already in standby\n");
218*4882a593Smuzhiyun 		return 0;
219*4882a593Smuzhiyun 	}
220*4882a593Smuzhiyun 
221*4882a593Smuzhiyun 	if (status == 0x01) {
222*4882a593Smuzhiyun 		printf ("Failed to check power mode on ata%d\n", num);
223*4882a593Smuzhiyun 		return 1;
224*4882a593Smuzhiyun 	}
225*4882a593Smuzhiyun 
226*4882a593Smuzhiyun 	if (!((status = sata_chk_status (&port[num].ioaddr, 0)) & ATA_DRDY)) {
227*4882a593Smuzhiyun 		printf ("Device ata%d not ready\n", num);
228*4882a593Smuzhiyun 		return 1;
229*4882a593Smuzhiyun 	}
230*4882a593Smuzhiyun 
231*4882a593Smuzhiyun 	writeb (0x00, port[num].ioaddr.feature_addr);
232*4882a593Smuzhiyun 
233*4882a593Smuzhiyun 	writeb (0x00, port[num].ioaddr.nsect_addr);
234*4882a593Smuzhiyun 	writeb (0x00, port[num].ioaddr.lbal_addr);
235*4882a593Smuzhiyun 	writeb (0x00, port[num].ioaddr.lbam_addr);
236*4882a593Smuzhiyun 	writeb (0x00, port[num].ioaddr.lbah_addr);
237*4882a593Smuzhiyun 
238*4882a593Smuzhiyun 	writeb (ATA_DEVICE_OBS, port[num].ioaddr.device_addr);
239*4882a593Smuzhiyun 	writeb (ATA_CMD_STANDBY, port[num].ioaddr.command_addr);
240*4882a593Smuzhiyun 
241*4882a593Smuzhiyun 	status = sata_busy_wait (&port[num].ioaddr, ATA_BUSY, 30000, 0);
242*4882a593Smuzhiyun 	if ((status & (ATA_BUSY | ATA_ERR))) {
243*4882a593Smuzhiyun 		printf ("Error waiting for disk spin down: status 0x%02x\n",
244*4882a593Smuzhiyun 			status);
245*4882a593Smuzhiyun 		port[num].dev_mask &= ~0x01;
246*4882a593Smuzhiyun 		return 1;
247*4882a593Smuzhiyun 	}
248*4882a593Smuzhiyun 	return 0;
249*4882a593Smuzhiyun }
250*4882a593Smuzhiyun 
sil3114_spin_up(int num)251*4882a593Smuzhiyun u8 sil3114_spin_up (int num)
252*4882a593Smuzhiyun {
253*4882a593Smuzhiyun 	u8 status = 0;
254*4882a593Smuzhiyun 
255*4882a593Smuzhiyun 	debug ("Spin up disk\n");
256*4882a593Smuzhiyun 
257*4882a593Smuzhiyun 	if (!(port[num].dev_mask & 0x01)) {
258*4882a593Smuzhiyun 		debug ("Device ata%d is not present\n", num);
259*4882a593Smuzhiyun 		return 1;
260*4882a593Smuzhiyun 	}
261*4882a593Smuzhiyun 
262*4882a593Smuzhiyun 	if ((status = check_power_mode (num)) != 0x00) {
263*4882a593Smuzhiyun 		if (status == 0x01) {
264*4882a593Smuzhiyun 			printf ("Failed to check power mode on ata%d\n", num);
265*4882a593Smuzhiyun 			return 1;
266*4882a593Smuzhiyun 		} else {
267*4882a593Smuzhiyun 			/* should be up and running already */
268*4882a593Smuzhiyun 			return 0;
269*4882a593Smuzhiyun 		}
270*4882a593Smuzhiyun 	}
271*4882a593Smuzhiyun 
272*4882a593Smuzhiyun 	if (!((status = sata_chk_status (&port[num].ioaddr, 0)) & ATA_DRDY)) {
273*4882a593Smuzhiyun 		printf ("Device ata%d not ready\n", num);
274*4882a593Smuzhiyun 		return 1;
275*4882a593Smuzhiyun 	}
276*4882a593Smuzhiyun 
277*4882a593Smuzhiyun 	debug ("Stautus of device check: %d\n", status);
278*4882a593Smuzhiyun 
279*4882a593Smuzhiyun 	writeb (0x00, port[num].ioaddr.feature_addr);
280*4882a593Smuzhiyun 
281*4882a593Smuzhiyun 	writeb (0x00, port[num].ioaddr.nsect_addr);
282*4882a593Smuzhiyun 	writeb (0x00, port[num].ioaddr.lbal_addr);
283*4882a593Smuzhiyun 	writeb (0x00, port[num].ioaddr.lbam_addr);
284*4882a593Smuzhiyun 	writeb (0x00, port[num].ioaddr.lbah_addr);
285*4882a593Smuzhiyun 
286*4882a593Smuzhiyun 	writeb (ATA_DEVICE_OBS, port[num].ioaddr.device_addr);
287*4882a593Smuzhiyun 	writeb (ATA_CMD_IDLE, port[num].ioaddr.command_addr);
288*4882a593Smuzhiyun 
289*4882a593Smuzhiyun 	status = sata_busy_wait (&port[num].ioaddr, ATA_BUSY, 30000, 0);
290*4882a593Smuzhiyun 	if ((status & (ATA_BUSY | ATA_ERR))) {
291*4882a593Smuzhiyun 		printf ("Error waiting for disk spin up: status 0x%02x\n",
292*4882a593Smuzhiyun 			status);
293*4882a593Smuzhiyun 		port[num].dev_mask &= ~0x01;
294*4882a593Smuzhiyun 		return 1;
295*4882a593Smuzhiyun 	}
296*4882a593Smuzhiyun 
297*4882a593Smuzhiyun 	/* Wait for disk to enter Active state */
298*4882a593Smuzhiyun 	do {
299*4882a593Smuzhiyun 		msleep (10);
300*4882a593Smuzhiyun 		status = check_power_mode (num);
301*4882a593Smuzhiyun 	} while ((status == 0x00) || (status == 0x80));
302*4882a593Smuzhiyun 
303*4882a593Smuzhiyun 	if (status == 0x01) {
304*4882a593Smuzhiyun 		printf ("Falied waiting for disk to spin up\n");
305*4882a593Smuzhiyun 		return 1;
306*4882a593Smuzhiyun 	}
307*4882a593Smuzhiyun 
308*4882a593Smuzhiyun 	return 0;
309*4882a593Smuzhiyun }
310*4882a593Smuzhiyun 
311*4882a593Smuzhiyun /* Return value is not the usual here
312*4882a593Smuzhiyun  * 0x00 - Device stand by
313*4882a593Smuzhiyun  * 0x01 - Operation failed
314*4882a593Smuzhiyun  * 0x80 - Device idle
315*4882a593Smuzhiyun  * 0xff - Device active
316*4882a593Smuzhiyun */
check_power_mode(int num)317*4882a593Smuzhiyun static u8 check_power_mode (int num)
318*4882a593Smuzhiyun {
319*4882a593Smuzhiyun 	u8 status = 0;
320*4882a593Smuzhiyun 	u8 res = 0;
321*4882a593Smuzhiyun 	if (!(port[num].dev_mask & 0x01)) {
322*4882a593Smuzhiyun 		debug ("Device ata%d is not present\n", num);
323*4882a593Smuzhiyun 		return 1;
324*4882a593Smuzhiyun 	}
325*4882a593Smuzhiyun 
326*4882a593Smuzhiyun 	if (!(sata_chk_status (&port[num].ioaddr, 0) & ATA_DRDY)) {
327*4882a593Smuzhiyun 		printf ("Device ata%d not ready\n", num);
328*4882a593Smuzhiyun 		return 1;
329*4882a593Smuzhiyun 	}
330*4882a593Smuzhiyun 
331*4882a593Smuzhiyun 	writeb (0, port[num].ioaddr.feature_addr);
332*4882a593Smuzhiyun 	writeb (0, port[num].ioaddr.nsect_addr);
333*4882a593Smuzhiyun 	writeb (0, port[num].ioaddr.lbal_addr);
334*4882a593Smuzhiyun 	writeb (0, port[num].ioaddr.lbam_addr);
335*4882a593Smuzhiyun 	writeb (0, port[num].ioaddr.lbah_addr);
336*4882a593Smuzhiyun 
337*4882a593Smuzhiyun 	writeb (ATA_DEVICE_OBS, port[num].ioaddr.device_addr);
338*4882a593Smuzhiyun 	writeb (ATA_CMD_CHK_POWER, port[num].ioaddr.command_addr);
339*4882a593Smuzhiyun 
340*4882a593Smuzhiyun 	status = sata_busy_wait (&port[num].ioaddr, ATA_BUSY, 5000, 0);
341*4882a593Smuzhiyun 	if ((status & (ATA_BUSY | ATA_ERR))) {
342*4882a593Smuzhiyun 		printf
343*4882a593Smuzhiyun 		    ("Error waiting for check power mode complete  : status 0x%02x\n",
344*4882a593Smuzhiyun 		     status);
345*4882a593Smuzhiyun 		port[num].dev_mask &= ~0x01;
346*4882a593Smuzhiyun 		return 1;
347*4882a593Smuzhiyun 	}
348*4882a593Smuzhiyun 	res = readb (port[num].ioaddr.nsect_addr);
349*4882a593Smuzhiyun 	debug ("Check powermode: %d\n", res);
350*4882a593Smuzhiyun 	return res;
351*4882a593Smuzhiyun 
352*4882a593Smuzhiyun }
353*4882a593Smuzhiyun 
sata_port(struct sata_ioports * ioport)354*4882a593Smuzhiyun static void sata_port (struct sata_ioports *ioport)
355*4882a593Smuzhiyun {
356*4882a593Smuzhiyun 	ioport->data_addr = ioport->cmd_addr + ATA_REG_DATA;
357*4882a593Smuzhiyun 	ioport->error_addr = ioport->cmd_addr + ATA_REG_ERR;
358*4882a593Smuzhiyun 	ioport->feature_addr = ioport->cmd_addr + ATA_REG_FEATURE;
359*4882a593Smuzhiyun 	ioport->nsect_addr = ioport->cmd_addr + ATA_REG_NSECT;
360*4882a593Smuzhiyun 	ioport->lbal_addr = ioport->cmd_addr + ATA_REG_LBAL;
361*4882a593Smuzhiyun 	ioport->lbam_addr = ioport->cmd_addr + ATA_REG_LBAM;
362*4882a593Smuzhiyun 	ioport->lbah_addr = ioport->cmd_addr + ATA_REG_LBAH;
363*4882a593Smuzhiyun 	ioport->device_addr = ioport->cmd_addr + ATA_REG_DEVICE;
364*4882a593Smuzhiyun 	ioport->status_addr = ioport->cmd_addr + ATA_REG_STATUS;
365*4882a593Smuzhiyun 	ioport->command_addr = ioport->cmd_addr + ATA_REG_CMD;
366*4882a593Smuzhiyun }
367*4882a593Smuzhiyun 
wait_for_irq(int num,unsigned int max)368*4882a593Smuzhiyun static u8 wait_for_irq (int num, unsigned int max)
369*4882a593Smuzhiyun {
370*4882a593Smuzhiyun 
371*4882a593Smuzhiyun 	u32 port = iobase[5];
372*4882a593Smuzhiyun 	switch (num) {
373*4882a593Smuzhiyun 	case 0:
374*4882a593Smuzhiyun 		port += VND_TF_CNST_CH0;
375*4882a593Smuzhiyun 		break;
376*4882a593Smuzhiyun 	case 1:
377*4882a593Smuzhiyun 		port += VND_TF_CNST_CH1;
378*4882a593Smuzhiyun 		break;
379*4882a593Smuzhiyun 	case 2:
380*4882a593Smuzhiyun 		port += VND_TF_CNST_CH2;
381*4882a593Smuzhiyun 		break;
382*4882a593Smuzhiyun 	case 3:
383*4882a593Smuzhiyun 		port += VND_TF_CNST_CH3;
384*4882a593Smuzhiyun 		break;
385*4882a593Smuzhiyun 	default:
386*4882a593Smuzhiyun 		return 1;
387*4882a593Smuzhiyun 	}
388*4882a593Smuzhiyun 
389*4882a593Smuzhiyun 	do {
390*4882a593Smuzhiyun 		if (readl (port) & VND_TF_CNST_INTST) {
391*4882a593Smuzhiyun 			break;
392*4882a593Smuzhiyun 		}
393*4882a593Smuzhiyun 		udelay (1000);
394*4882a593Smuzhiyun 		max--;
395*4882a593Smuzhiyun 	} while ((max > 0));
396*4882a593Smuzhiyun 
397*4882a593Smuzhiyun 	return (max == 0);
398*4882a593Smuzhiyun }
399*4882a593Smuzhiyun 
sata_busy_wait(struct sata_ioports * ioaddr,int bits,unsigned int max,u8 usealtstatus)400*4882a593Smuzhiyun static u8 sata_busy_wait (struct sata_ioports *ioaddr, int bits,
401*4882a593Smuzhiyun 			  unsigned int max, u8 usealtstatus)
402*4882a593Smuzhiyun {
403*4882a593Smuzhiyun 	u8 status;
404*4882a593Smuzhiyun 
405*4882a593Smuzhiyun 	do {
406*4882a593Smuzhiyun 		if (!((status = sata_chk_status (ioaddr, usealtstatus)) & bits)) {
407*4882a593Smuzhiyun 			break;
408*4882a593Smuzhiyun 		}
409*4882a593Smuzhiyun 		udelay (1000);
410*4882a593Smuzhiyun 		max--;
411*4882a593Smuzhiyun 	} while ((status & bits) && (max > 0));
412*4882a593Smuzhiyun 
413*4882a593Smuzhiyun 	return status;
414*4882a593Smuzhiyun }
415*4882a593Smuzhiyun 
sata_chk_status(struct sata_ioports * ioaddr,u8 usealtstatus)416*4882a593Smuzhiyun static u8 sata_chk_status (struct sata_ioports *ioaddr, u8 usealtstatus)
417*4882a593Smuzhiyun {
418*4882a593Smuzhiyun 	if (!usealtstatus) {
419*4882a593Smuzhiyun 		return readb (ioaddr->status_addr);
420*4882a593Smuzhiyun 	} else {
421*4882a593Smuzhiyun 		return readb (ioaddr->altstatus_addr);
422*4882a593Smuzhiyun 	}
423*4882a593Smuzhiyun }
424*4882a593Smuzhiyun 
msleep(int count)425*4882a593Smuzhiyun static void msleep (int count)
426*4882a593Smuzhiyun {
427*4882a593Smuzhiyun 	int i;
428*4882a593Smuzhiyun 
429*4882a593Smuzhiyun 	for (i = 0; i < count; i++)
430*4882a593Smuzhiyun 		udelay (1000);
431*4882a593Smuzhiyun }
432*4882a593Smuzhiyun 
433*4882a593Smuzhiyun /* Read up to 255 sectors
434*4882a593Smuzhiyun  *
435*4882a593Smuzhiyun  * Returns sectors read
436*4882a593Smuzhiyun */
do_one_read(int device,ulong block,u8 blkcnt,u16 * buff,uchar lba48)437*4882a593Smuzhiyun static u8 do_one_read (int device, ulong block, u8 blkcnt, u16 * buff,
438*4882a593Smuzhiyun 		       uchar lba48)
439*4882a593Smuzhiyun {
440*4882a593Smuzhiyun 
441*4882a593Smuzhiyun 	u8 sr = 0;
442*4882a593Smuzhiyun 	u8 status;
443*4882a593Smuzhiyun 	u64 blknr = (u64) block;
444*4882a593Smuzhiyun 
445*4882a593Smuzhiyun 	if (!(sata_chk_status (&port[device].ioaddr, 0) & ATA_DRDY)) {
446*4882a593Smuzhiyun 		printf ("Device ata%d not ready\n", device);
447*4882a593Smuzhiyun 		return 0;
448*4882a593Smuzhiyun 	}
449*4882a593Smuzhiyun 
450*4882a593Smuzhiyun 	/* Set up transfer */
451*4882a593Smuzhiyun #ifdef CONFIG_LBA48
452*4882a593Smuzhiyun 	if (lba48) {
453*4882a593Smuzhiyun 		/* write high bits */
454*4882a593Smuzhiyun 		writeb (0, port[device].ioaddr.nsect_addr);
455*4882a593Smuzhiyun 		writeb ((blknr >> 24) & 0xFF, port[device].ioaddr.lbal_addr);
456*4882a593Smuzhiyun 		writeb ((blknr >> 32) & 0xFF, port[device].ioaddr.lbam_addr);
457*4882a593Smuzhiyun 		writeb ((blknr >> 40) & 0xFF, port[device].ioaddr.lbah_addr);
458*4882a593Smuzhiyun 	}
459*4882a593Smuzhiyun #endif
460*4882a593Smuzhiyun 	writeb (blkcnt, port[device].ioaddr.nsect_addr);
461*4882a593Smuzhiyun 	writeb (((blknr) >> 0) & 0xFF, port[device].ioaddr.lbal_addr);
462*4882a593Smuzhiyun 	writeb ((blknr >> 8) & 0xFF, port[device].ioaddr.lbam_addr);
463*4882a593Smuzhiyun 	writeb ((blknr >> 16) & 0xFF, port[device].ioaddr.lbah_addr);
464*4882a593Smuzhiyun 
465*4882a593Smuzhiyun #ifdef CONFIG_LBA48
466*4882a593Smuzhiyun 	if (lba48) {
467*4882a593Smuzhiyun 		writeb (ATA_LBA, port[device].ioaddr.device_addr);
468*4882a593Smuzhiyun 		writeb (ATA_CMD_PIO_READ_EXT, port[device].ioaddr.command_addr);
469*4882a593Smuzhiyun 	} else
470*4882a593Smuzhiyun #endif
471*4882a593Smuzhiyun 	{
472*4882a593Smuzhiyun 		writeb (ATA_LBA | ((blknr >> 24) & 0xF),
473*4882a593Smuzhiyun 			port[device].ioaddr.device_addr);
474*4882a593Smuzhiyun 		writeb (ATA_CMD_PIO_READ, port[device].ioaddr.command_addr);
475*4882a593Smuzhiyun 	}
476*4882a593Smuzhiyun 
477*4882a593Smuzhiyun 	status = sata_busy_wait (&port[device].ioaddr, ATA_BUSY, 10000, 1);
478*4882a593Smuzhiyun 
479*4882a593Smuzhiyun 	if (status & ATA_BUSY) {
480*4882a593Smuzhiyun 		u8 err = 0;
481*4882a593Smuzhiyun 
482*4882a593Smuzhiyun 		printf ("Device %d not responding status %d\n", device, status);
483*4882a593Smuzhiyun 		err = readb (port[device].ioaddr.error_addr);
484*4882a593Smuzhiyun 		printf ("Error reg = 0x%x\n", err);
485*4882a593Smuzhiyun 
486*4882a593Smuzhiyun 		return (sr);
487*4882a593Smuzhiyun 	}
488*4882a593Smuzhiyun 	while (blkcnt--) {
489*4882a593Smuzhiyun 
490*4882a593Smuzhiyun 		if (wait_for_irq (device, 500)) {
491*4882a593Smuzhiyun 			printf ("ata%u irq failed\n", device);
492*4882a593Smuzhiyun 			return sr;
493*4882a593Smuzhiyun 		}
494*4882a593Smuzhiyun 
495*4882a593Smuzhiyun 		status = sata_chk_status (&port[device].ioaddr, 0);
496*4882a593Smuzhiyun 		if (status & ATA_ERR) {
497*4882a593Smuzhiyun 			printf ("ata%u error %d\n", device,
498*4882a593Smuzhiyun 				readb (port[device].ioaddr.error_addr));
499*4882a593Smuzhiyun 			return sr;
500*4882a593Smuzhiyun 		}
501*4882a593Smuzhiyun 		/* Read one sector */
502*4882a593Smuzhiyun 		input_data (&port[device].ioaddr, buff, ATA_SECTOR_WORDS);
503*4882a593Smuzhiyun 		buff += ATA_SECTOR_WORDS;
504*4882a593Smuzhiyun 		sr++;
505*4882a593Smuzhiyun 
506*4882a593Smuzhiyun 	}
507*4882a593Smuzhiyun 	return sr;
508*4882a593Smuzhiyun }
509*4882a593Smuzhiyun 
sata_read(int device,ulong block,lbaint_t blkcnt,void * buff)510*4882a593Smuzhiyun ulong sata_read (int device, ulong block, lbaint_t blkcnt, void *buff)
511*4882a593Smuzhiyun {
512*4882a593Smuzhiyun 	ulong n = 0, sread;
513*4882a593Smuzhiyun 	u16 *buffer = (u16 *) buff;
514*4882a593Smuzhiyun 	u8 status = 0;
515*4882a593Smuzhiyun 	u64 blknr = (u64) block;
516*4882a593Smuzhiyun 	unsigned char lba48 = 0;
517*4882a593Smuzhiyun 
518*4882a593Smuzhiyun #ifdef CONFIG_LBA48
519*4882a593Smuzhiyun 	if (blknr > 0xfffffff) {
520*4882a593Smuzhiyun 		if (!sata_dev_desc[device].lba48) {
521*4882a593Smuzhiyun 			printf ("Drive doesn't support 48-bit addressing\n");
522*4882a593Smuzhiyun 			return 0;
523*4882a593Smuzhiyun 		}
524*4882a593Smuzhiyun 		/* more than 28 bits used, use 48bit mode */
525*4882a593Smuzhiyun 		lba48 = 1;
526*4882a593Smuzhiyun 	}
527*4882a593Smuzhiyun #endif
528*4882a593Smuzhiyun 
529*4882a593Smuzhiyun 	while (blkcnt > 0) {
530*4882a593Smuzhiyun 
531*4882a593Smuzhiyun 		if (blkcnt > 255) {
532*4882a593Smuzhiyun 			sread = 255;
533*4882a593Smuzhiyun 		} else {
534*4882a593Smuzhiyun 			sread = blkcnt;
535*4882a593Smuzhiyun 		}
536*4882a593Smuzhiyun 
537*4882a593Smuzhiyun 		status = do_one_read (device, blknr, sread, buffer, lba48);
538*4882a593Smuzhiyun 		if (status != sread) {
539*4882a593Smuzhiyun 			printf ("Read failed\n");
540*4882a593Smuzhiyun 			return n;
541*4882a593Smuzhiyun 		}
542*4882a593Smuzhiyun 
543*4882a593Smuzhiyun 		blkcnt -= sread;
544*4882a593Smuzhiyun 		blknr += sread;
545*4882a593Smuzhiyun 		n += sread;
546*4882a593Smuzhiyun 		buffer += sread * ATA_SECTOR_WORDS;
547*4882a593Smuzhiyun 	}
548*4882a593Smuzhiyun 	return n;
549*4882a593Smuzhiyun }
550*4882a593Smuzhiyun 
sata_write(int device,ulong block,lbaint_t blkcnt,const void * buff)551*4882a593Smuzhiyun ulong sata_write (int device, ulong block, lbaint_t blkcnt, const void *buff)
552*4882a593Smuzhiyun {
553*4882a593Smuzhiyun 	ulong n = 0;
554*4882a593Smuzhiyun 	u16 *buffer = (u16 *) buff;
555*4882a593Smuzhiyun 	unsigned char status = 0, num = 0;
556*4882a593Smuzhiyun 	u64 blknr = (u64) block;
557*4882a593Smuzhiyun #ifdef CONFIG_LBA48
558*4882a593Smuzhiyun 	unsigned char lba48 = 0;
559*4882a593Smuzhiyun 
560*4882a593Smuzhiyun 	if (blknr > 0xfffffff) {
561*4882a593Smuzhiyun 		if (!sata_dev_desc[device].lba48) {
562*4882a593Smuzhiyun 			printf ("Drive doesn't support 48-bit addressing\n");
563*4882a593Smuzhiyun 			return 0;
564*4882a593Smuzhiyun 		}
565*4882a593Smuzhiyun 		/* more than 28 bits used, use 48bit mode */
566*4882a593Smuzhiyun 		lba48 = 1;
567*4882a593Smuzhiyun 	}
568*4882a593Smuzhiyun #endif
569*4882a593Smuzhiyun 	/*Port Number */
570*4882a593Smuzhiyun 	num = device;
571*4882a593Smuzhiyun 
572*4882a593Smuzhiyun 	while (blkcnt-- > 0) {
573*4882a593Smuzhiyun 		status = sata_busy_wait (&port[num].ioaddr, ATA_BUSY, 500, 0);
574*4882a593Smuzhiyun 		if (status & ATA_BUSY) {
575*4882a593Smuzhiyun 			printf ("ata%u failed to respond\n", port[num].port_no);
576*4882a593Smuzhiyun 			return n;
577*4882a593Smuzhiyun 		}
578*4882a593Smuzhiyun #ifdef CONFIG_LBA48
579*4882a593Smuzhiyun 		if (lba48) {
580*4882a593Smuzhiyun 			/* write high bits */
581*4882a593Smuzhiyun 			writeb (0, port[num].ioaddr.nsect_addr);
582*4882a593Smuzhiyun 			writeb ((blknr >> 24) & 0xFF,
583*4882a593Smuzhiyun 				port[num].ioaddr.lbal_addr);
584*4882a593Smuzhiyun 			writeb ((blknr >> 32) & 0xFF,
585*4882a593Smuzhiyun 				port[num].ioaddr.lbam_addr);
586*4882a593Smuzhiyun 			writeb ((blknr >> 40) & 0xFF,
587*4882a593Smuzhiyun 				port[num].ioaddr.lbah_addr);
588*4882a593Smuzhiyun 		}
589*4882a593Smuzhiyun #endif
590*4882a593Smuzhiyun 		writeb (1, port[num].ioaddr.nsect_addr);
591*4882a593Smuzhiyun 		writeb ((blknr >> 0) & 0xFF, port[num].ioaddr.lbal_addr);
592*4882a593Smuzhiyun 		writeb ((blknr >> 8) & 0xFF, port[num].ioaddr.lbam_addr);
593*4882a593Smuzhiyun 		writeb ((blknr >> 16) & 0xFF, port[num].ioaddr.lbah_addr);
594*4882a593Smuzhiyun #ifdef CONFIG_LBA48
595*4882a593Smuzhiyun 		if (lba48) {
596*4882a593Smuzhiyun 			writeb (ATA_LBA, port[num].ioaddr.device_addr);
597*4882a593Smuzhiyun 			writeb (ATA_CMD_PIO_WRITE_EXT, port[num].ioaddr.command_addr);
598*4882a593Smuzhiyun 		} else
599*4882a593Smuzhiyun #endif
600*4882a593Smuzhiyun 		{
601*4882a593Smuzhiyun 			writeb (ATA_LBA | ((blknr >> 24) & 0xF),
602*4882a593Smuzhiyun 				port[num].ioaddr.device_addr);
603*4882a593Smuzhiyun 			writeb (ATA_CMD_PIO_WRITE, port[num].ioaddr.command_addr);
604*4882a593Smuzhiyun 		}
605*4882a593Smuzhiyun 
606*4882a593Smuzhiyun 		msleep (50);
607*4882a593Smuzhiyun 		/*may take up to 4 sec */
608*4882a593Smuzhiyun 		status = sata_busy_wait (&port[num].ioaddr, ATA_BUSY, 4000, 0);
609*4882a593Smuzhiyun 		if ((status & (ATA_DRQ | ATA_BUSY | ATA_ERR)) != ATA_DRQ) {
610*4882a593Smuzhiyun 			printf ("Error no DRQ dev %d blk %ld: sts 0x%02x\n",
611*4882a593Smuzhiyun 				device, (ulong) blknr, status);
612*4882a593Smuzhiyun 			return (n);
613*4882a593Smuzhiyun 		}
614*4882a593Smuzhiyun 
615*4882a593Smuzhiyun 		output_data (&port[num].ioaddr, buffer, ATA_SECTOR_WORDS);
616*4882a593Smuzhiyun 		readb (port[num].ioaddr.altstatus_addr);
617*4882a593Smuzhiyun 		udelay (50);
618*4882a593Smuzhiyun 
619*4882a593Smuzhiyun 		++n;
620*4882a593Smuzhiyun 		++blknr;
621*4882a593Smuzhiyun 		buffer += ATA_SECTOR_WORDS;
622*4882a593Smuzhiyun 	}
623*4882a593Smuzhiyun 	return n;
624*4882a593Smuzhiyun }
625*4882a593Smuzhiyun 
626*4882a593Smuzhiyun /* Driver implementation */
sil_get_device_cache_line(pci_dev_t pdev)627*4882a593Smuzhiyun static u8 sil_get_device_cache_line (pci_dev_t pdev)
628*4882a593Smuzhiyun {
629*4882a593Smuzhiyun 	u8 cache_line = 0;
630*4882a593Smuzhiyun 	pci_read_config_byte (pdev, PCI_CACHE_LINE_SIZE, &cache_line);
631*4882a593Smuzhiyun 	return cache_line;
632*4882a593Smuzhiyun }
633*4882a593Smuzhiyun 
init_sata(int dev)634*4882a593Smuzhiyun int init_sata (int dev)
635*4882a593Smuzhiyun {
636*4882a593Smuzhiyun 	static u8 init_done = 0;
637*4882a593Smuzhiyun 	static int res = 1;
638*4882a593Smuzhiyun 	pci_dev_t devno;
639*4882a593Smuzhiyun 	u8 cls = 0;
640*4882a593Smuzhiyun 	u16 cmd = 0;
641*4882a593Smuzhiyun 	u32 sconf = 0;
642*4882a593Smuzhiyun 
643*4882a593Smuzhiyun 	if (init_done) {
644*4882a593Smuzhiyun 		return res;
645*4882a593Smuzhiyun 	}
646*4882a593Smuzhiyun 
647*4882a593Smuzhiyun 	init_done = 1;
648*4882a593Smuzhiyun 
649*4882a593Smuzhiyun 	if ((devno = pci_find_device (SIL_VEND_ID, SIL3114_DEVICE_ID, 0)) == -1) {
650*4882a593Smuzhiyun 		res = 1;
651*4882a593Smuzhiyun 		return res;
652*4882a593Smuzhiyun 	}
653*4882a593Smuzhiyun 
654*4882a593Smuzhiyun 	/* Read out all BARs, even though we only use MMIO from BAR5 */
655*4882a593Smuzhiyun 	pci_read_config_dword (devno, PCI_BASE_ADDRESS_0, &iobase[0]);
656*4882a593Smuzhiyun 	pci_read_config_dword (devno, PCI_BASE_ADDRESS_1, &iobase[1]);
657*4882a593Smuzhiyun 	pci_read_config_dword (devno, PCI_BASE_ADDRESS_2, &iobase[2]);
658*4882a593Smuzhiyun 	pci_read_config_dword (devno, PCI_BASE_ADDRESS_3, &iobase[3]);
659*4882a593Smuzhiyun 	pci_read_config_dword (devno, PCI_BASE_ADDRESS_4, &iobase[4]);
660*4882a593Smuzhiyun 	pci_read_config_dword (devno, PCI_BASE_ADDRESS_5, &iobase[5]);
661*4882a593Smuzhiyun 
662*4882a593Smuzhiyun 	if ((iobase[0] == 0xFFFFFFFF) || (iobase[1] == 0xFFFFFFFF) ||
663*4882a593Smuzhiyun 	    (iobase[2] == 0xFFFFFFFF) || (iobase[3] == 0xFFFFFFFF) ||
664*4882a593Smuzhiyun 	    (iobase[4] == 0xFFFFFFFF) || (iobase[5] == 0xFFFFFFFF)) {
665*4882a593Smuzhiyun 		printf ("Error no base addr for SATA controller\n");
666*4882a593Smuzhiyun 		res = 1;
667*4882a593Smuzhiyun 		return res;
668*4882a593Smuzhiyun 	}
669*4882a593Smuzhiyun 
670*4882a593Smuzhiyun 	/* mask off unused bits */
671*4882a593Smuzhiyun 	iobase[0] &= 0xfffffffc;
672*4882a593Smuzhiyun 	iobase[1] &= 0xfffffff8;
673*4882a593Smuzhiyun 	iobase[2] &= 0xfffffffc;
674*4882a593Smuzhiyun 	iobase[3] &= 0xfffffff8;
675*4882a593Smuzhiyun 	iobase[4] &= 0xfffffff0;
676*4882a593Smuzhiyun 	iobase[5] &= 0xfffffc00;
677*4882a593Smuzhiyun 
678*4882a593Smuzhiyun 	/* from sata_sil in Linux kernel */
679*4882a593Smuzhiyun 	cls = sil_get_device_cache_line (devno);
680*4882a593Smuzhiyun 	if (cls) {
681*4882a593Smuzhiyun 		cls >>= 3;
682*4882a593Smuzhiyun 		cls++;		/* cls = (line_size/8)+1 */
683*4882a593Smuzhiyun 		writel (cls << 8 | cls, iobase[5] + VND_FIFOCFG_CH0);
684*4882a593Smuzhiyun 		writel (cls << 8 | cls, iobase[5] + VND_FIFOCFG_CH1);
685*4882a593Smuzhiyun 		writel (cls << 8 | cls, iobase[5] + VND_FIFOCFG_CH2);
686*4882a593Smuzhiyun 		writel (cls << 8 | cls, iobase[5] + VND_FIFOCFG_CH3);
687*4882a593Smuzhiyun 	} else {
688*4882a593Smuzhiyun 		printf ("Cache line not set. Driver may not function\n");
689*4882a593Smuzhiyun 	}
690*4882a593Smuzhiyun 
691*4882a593Smuzhiyun 	/* Enable operation */
692*4882a593Smuzhiyun 	pci_read_config_word (devno, PCI_COMMAND, &cmd);
693*4882a593Smuzhiyun 	cmd |= PCI_COMMAND_MASTER | PCI_COMMAND_IO | PCI_COMMAND_MEMORY;
694*4882a593Smuzhiyun 	pci_write_config_word (devno, PCI_COMMAND, cmd);
695*4882a593Smuzhiyun 
696*4882a593Smuzhiyun 	/* Disable interrupt usage */
697*4882a593Smuzhiyun 	pci_read_config_dword (devno, VND_SYSCONFSTAT, &sconf);
698*4882a593Smuzhiyun 	sconf |= (VND_SYSCONFSTAT_CHN_0_INTBLOCK | VND_SYSCONFSTAT_CHN_1_INTBLOCK);
699*4882a593Smuzhiyun 	pci_write_config_dword (devno, VND_SYSCONFSTAT, sconf);
700*4882a593Smuzhiyun 
701*4882a593Smuzhiyun 	res = 0;
702*4882a593Smuzhiyun 	return res;
703*4882a593Smuzhiyun }
704*4882a593Smuzhiyun 
reset_sata(int dev)705*4882a593Smuzhiyun int reset_sata(int dev)
706*4882a593Smuzhiyun {
707*4882a593Smuzhiyun 	return 0;
708*4882a593Smuzhiyun }
709*4882a593Smuzhiyun 
710*4882a593Smuzhiyun /* Check if device is connected to port */
sata_bus_probe(int portno)711*4882a593Smuzhiyun int sata_bus_probe (int portno)
712*4882a593Smuzhiyun {
713*4882a593Smuzhiyun 	u32 port = iobase[5];
714*4882a593Smuzhiyun 	u32 val;
715*4882a593Smuzhiyun 	switch (portno) {
716*4882a593Smuzhiyun 	case 0:
717*4882a593Smuzhiyun 		port += VND_SSTATUS_CH0;
718*4882a593Smuzhiyun 		break;
719*4882a593Smuzhiyun 	case 1:
720*4882a593Smuzhiyun 		port += VND_SSTATUS_CH1;
721*4882a593Smuzhiyun 		break;
722*4882a593Smuzhiyun 	case 2:
723*4882a593Smuzhiyun 		port += VND_SSTATUS_CH2;
724*4882a593Smuzhiyun 		break;
725*4882a593Smuzhiyun 	case 3:
726*4882a593Smuzhiyun 		port += VND_SSTATUS_CH3;
727*4882a593Smuzhiyun 		break;
728*4882a593Smuzhiyun 	default:
729*4882a593Smuzhiyun 		return 0;
730*4882a593Smuzhiyun 	}
731*4882a593Smuzhiyun 	val = readl (port);
732*4882a593Smuzhiyun 	if ((val & SATA_DET_PRES) == SATA_DET_PRES) {
733*4882a593Smuzhiyun 		return 1;
734*4882a593Smuzhiyun 	} else {
735*4882a593Smuzhiyun 		return 0;
736*4882a593Smuzhiyun 	}
737*4882a593Smuzhiyun }
738*4882a593Smuzhiyun 
sata_phy_reset(int portno)739*4882a593Smuzhiyun int sata_phy_reset (int portno)
740*4882a593Smuzhiyun {
741*4882a593Smuzhiyun 	u32 port = iobase[5];
742*4882a593Smuzhiyun 	u32 val;
743*4882a593Smuzhiyun 	switch (portno) {
744*4882a593Smuzhiyun 	case 0:
745*4882a593Smuzhiyun 		port += VND_SCONTROL_CH0;
746*4882a593Smuzhiyun 		break;
747*4882a593Smuzhiyun 	case 1:
748*4882a593Smuzhiyun 		port += VND_SCONTROL_CH1;
749*4882a593Smuzhiyun 		break;
750*4882a593Smuzhiyun 	case 2:
751*4882a593Smuzhiyun 		port += VND_SCONTROL_CH2;
752*4882a593Smuzhiyun 		break;
753*4882a593Smuzhiyun 	case 3:
754*4882a593Smuzhiyun 		port += VND_SCONTROL_CH3;
755*4882a593Smuzhiyun 		break;
756*4882a593Smuzhiyun 	default:
757*4882a593Smuzhiyun 		return 0;
758*4882a593Smuzhiyun 	}
759*4882a593Smuzhiyun 	val = readl (port);
760*4882a593Smuzhiyun 	writel (val | SATA_SC_DET_RST, port);
761*4882a593Smuzhiyun 	msleep (150);
762*4882a593Smuzhiyun 	writel (val & ~SATA_SC_DET_RST, port);
763*4882a593Smuzhiyun 	return 0;
764*4882a593Smuzhiyun }
765*4882a593Smuzhiyun 
scan_sata(int dev)766*4882a593Smuzhiyun int scan_sata (int dev)
767*4882a593Smuzhiyun {
768*4882a593Smuzhiyun 	/* A bit brain dead, but the code has a legacy */
769*4882a593Smuzhiyun 	switch (dev) {
770*4882a593Smuzhiyun 	case 0:
771*4882a593Smuzhiyun 		port[0].port_no = 0;
772*4882a593Smuzhiyun 		port[0].ioaddr.cmd_addr = iobase[5] + VND_TF0_CH0;
773*4882a593Smuzhiyun 		port[0].ioaddr.altstatus_addr = port[0].ioaddr.ctl_addr =
774*4882a593Smuzhiyun 		    (iobase[5] + VND_TF2_CH0) | ATA_PCI_CTL_OFS;
775*4882a593Smuzhiyun 		port[0].ioaddr.bmdma_addr = iobase[5] + VND_BMDMA_CH0;
776*4882a593Smuzhiyun 		break;
777*4882a593Smuzhiyun #if (CONFIG_SYS_SATA_MAX_DEVICE >= 1)
778*4882a593Smuzhiyun 	case 1:
779*4882a593Smuzhiyun 		port[1].port_no = 0;
780*4882a593Smuzhiyun 		port[1].ioaddr.cmd_addr = iobase[5] + VND_TF0_CH1;
781*4882a593Smuzhiyun 		port[1].ioaddr.altstatus_addr = port[1].ioaddr.ctl_addr =
782*4882a593Smuzhiyun 		    (iobase[5] + VND_TF2_CH1) | ATA_PCI_CTL_OFS;
783*4882a593Smuzhiyun 		port[1].ioaddr.bmdma_addr = iobase[5] + VND_BMDMA_CH1;
784*4882a593Smuzhiyun 		break;
785*4882a593Smuzhiyun #elif (CONFIG_SYS_SATA_MAX_DEVICE >= 2)
786*4882a593Smuzhiyun 	case 2:
787*4882a593Smuzhiyun 		port[2].port_no = 0;
788*4882a593Smuzhiyun 		port[2].ioaddr.cmd_addr = iobase[5] + VND_TF0_CH2;
789*4882a593Smuzhiyun 		port[2].ioaddr.altstatus_addr = port[2].ioaddr.ctl_addr =
790*4882a593Smuzhiyun 		    (iobase[5] + VND_TF2_CH2) | ATA_PCI_CTL_OFS;
791*4882a593Smuzhiyun 		port[2].ioaddr.bmdma_addr = iobase[5] + VND_BMDMA_CH2;
792*4882a593Smuzhiyun 		break;
793*4882a593Smuzhiyun #elif (CONFIG_SYS_SATA_MAX_DEVICE >= 3)
794*4882a593Smuzhiyun 	case 3:
795*4882a593Smuzhiyun 		port[3].port_no = 0;
796*4882a593Smuzhiyun 		port[3].ioaddr.cmd_addr = iobase[5] + VND_TF0_CH3;
797*4882a593Smuzhiyun 		port[3].ioaddr.altstatus_addr = port[3].ioaddr.ctl_addr =
798*4882a593Smuzhiyun 		    (iobase[5] + VND_TF2_CH3) | ATA_PCI_CTL_OFS;
799*4882a593Smuzhiyun 		port[3].ioaddr.bmdma_addr = iobase[5] + VND_BMDMA_CH3;
800*4882a593Smuzhiyun 		break;
801*4882a593Smuzhiyun #endif
802*4882a593Smuzhiyun 	default:
803*4882a593Smuzhiyun 		printf ("Tried to scan unknown port: ata%d\n", dev);
804*4882a593Smuzhiyun 		return 1;
805*4882a593Smuzhiyun 	}
806*4882a593Smuzhiyun 
807*4882a593Smuzhiyun 	/* Initialize other registers */
808*4882a593Smuzhiyun 	sata_port (&port[dev].ioaddr);
809*4882a593Smuzhiyun 
810*4882a593Smuzhiyun 	/* Check for attached device */
811*4882a593Smuzhiyun 	if (!sata_bus_probe (dev)) {
812*4882a593Smuzhiyun 		port[dev].port_state = 0;
813*4882a593Smuzhiyun 		debug ("SATA#%d port is not present\n", dev);
814*4882a593Smuzhiyun 	} else {
815*4882a593Smuzhiyun 		debug ("SATA#%d port is present\n", dev);
816*4882a593Smuzhiyun 		if (sata_bus_softreset (dev)) {
817*4882a593Smuzhiyun 			/* soft reset failed, try a hard one */
818*4882a593Smuzhiyun 			sata_phy_reset (dev);
819*4882a593Smuzhiyun 			if (sata_bus_softreset (dev)) {
820*4882a593Smuzhiyun 				port[dev].port_state = 0;
821*4882a593Smuzhiyun 			} else {
822*4882a593Smuzhiyun 				port[dev].port_state = 1;
823*4882a593Smuzhiyun 			}
824*4882a593Smuzhiyun 		} else {
825*4882a593Smuzhiyun 			port[dev].port_state = 1;
826*4882a593Smuzhiyun 		}
827*4882a593Smuzhiyun 	}
828*4882a593Smuzhiyun 	if (port[dev].port_state == 1) {
829*4882a593Smuzhiyun 		/* Probe device and set xfer mode */
830*4882a593Smuzhiyun 		sata_identify (dev, 0);
831*4882a593Smuzhiyun 		set_Feature_cmd (dev, 0);
832*4882a593Smuzhiyun 	}
833*4882a593Smuzhiyun 
834*4882a593Smuzhiyun 	return 0;
835*4882a593Smuzhiyun }
836