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