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