blob: 19c5f137f84bafbfd54feda470f7cfa8535c0e0a [file] [log] [blame]
Jin Zhengxiong4782ac82006-08-23 19:10:44 +08001/*
Kumar Gala4c2e3da2009-07-28 21:49:52 -05002 * Copyright (C) Freescale Semiconductor, Inc. 2006.
Jin Zhengxiong4782ac82006-08-23 19:10:44 +08003 * Author: Jason Jin<Jason.jin@freescale.com>
4 * Zhang Wei<wei.zhang@freescale.com>
5 *
6 * See file CREDITS for list of people who contributed to this
7 * project.
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation; either version 2 of
12 * the License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
22 * MA 02111-1307 USA
23 *
24 * with the reference on libata and ahci drvier in kernel
25 *
26 */
27#include <common.h>
28
Jin Zhengxiong4782ac82006-08-23 19:10:44 +080029#include <command.h>
30#include <pci.h>
31#include <asm/processor.h>
32#include <asm/errno.h>
33#include <asm/io.h>
34#include <malloc.h>
35#include <scsi.h>
36#include <ata.h>
37#include <linux/ctype.h>
38#include <ahci.h>
39
40struct ahci_probe_ent *probe_ent = NULL;
41hd_driveid_t *ataid[AHCI_MAX_PORTS];
42
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -050043#define writel_with_flush(a,b) do { writel(a,b); readl(b); } while (0)
44
Vadim Bendebury284231e2012-10-29 05:23:44 +000045/*
Hung-Te Linb7a21b72012-10-29 05:23:53 +000046 * Some controllers limit number of blocks they can read/write at once.
47 * Contemporary SSD devices work much faster if the read/write size is aligned
48 * to a power of 2. Let's set default to 128 and allowing to be overwritten if
49 * needed.
Vadim Bendebury284231e2012-10-29 05:23:44 +000050 */
Hung-Te Linb7a21b72012-10-29 05:23:53 +000051#ifndef MAX_SATA_BLOCKS_READ_WRITE
52#define MAX_SATA_BLOCKS_READ_WRITE 0x80
Vadim Bendebury284231e2012-10-29 05:23:44 +000053#endif
Jin Zhengxiong4782ac82006-08-23 19:10:44 +080054
Walter Murphy57847662012-10-29 05:24:00 +000055/* Maximum timeouts for each event */
Marc Jones2a0c61d2012-10-29 05:24:01 +000056#define WAIT_MS_SPINUP 10000
Walter Murphy57847662012-10-29 05:24:00 +000057#define WAIT_MS_DATAIO 5000
58#define WAIT_MS_LINKUP 4
59
Jin Zhengxiong4782ac82006-08-23 19:10:44 +080060static inline u32 ahci_port_base(u32 base, u32 port)
61{
62 return base + 0x100 + (port * 0x80);
63}
64
65
66static void ahci_setup_port(struct ahci_ioports *port, unsigned long base,
67 unsigned int port_idx)
68{
69 base = ahci_port_base(base, port_idx);
70
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -050071 port->cmd_addr = base;
72 port->scr_addr = base + PORT_SCR;
Jin Zhengxiong4782ac82006-08-23 19:10:44 +080073}
74
75
76#define msleep(a) udelay(a * 1000)
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -050077
Taylor Hutt90b276f2012-10-29 05:23:59 +000078static void ahci_dcache_flush_range(unsigned begin, unsigned len)
79{
80 const unsigned long start = begin;
81 const unsigned long end = start + len;
82
83 debug("%s: flush dcache: [%#lx, %#lx)\n", __func__, start, end);
84 flush_dcache_range(start, end);
85}
86
87/*
88 * SATA controller DMAs to physical RAM. Ensure data from the
89 * controller is invalidated from dcache; next access comes from
90 * physical RAM.
91 */
92static void ahci_dcache_invalidate_range(unsigned begin, unsigned len)
93{
94 const unsigned long start = begin;
95 const unsigned long end = start + len;
96
97 debug("%s: invalidate dcache: [%#lx, %#lx)\n", __func__, start, end);
98 invalidate_dcache_range(start, end);
99}
100
101/*
102 * Ensure data for SATA controller is flushed out of dcache and
103 * written to physical memory.
104 */
105static void ahci_dcache_flush_sata_cmd(struct ahci_ioports *pp)
106{
107 ahci_dcache_flush_range((unsigned long)pp->cmd_slot,
108 AHCI_PORT_PRIV_DMA_SZ);
109}
110
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500111static int waiting_for_cmd_completed(volatile u8 *offset,
112 int timeout_msec,
113 u32 sign)
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800114{
115 int i;
116 u32 status;
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500117
118 for (i = 0; ((status = readl(offset)) & sign) && i < timeout_msec; i++)
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800119 msleep(1);
120
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500121 return (i < timeout_msec) ? 0 : -1;
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800122}
123
124
125static int ahci_host_init(struct ahci_probe_ent *probe_ent)
126{
Rob Herring942e3142011-07-06 16:13:36 +0000127#ifndef CONFIG_SCSI_AHCI_PLAT
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800128 pci_dev_t pdev = probe_ent->dev;
Rob Herring942e3142011-07-06 16:13:36 +0000129 u16 tmp16;
130 unsigned short vendor;
131#endif
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800132 volatile u8 *mmio = (volatile u8 *)probe_ent->mmio_base;
Marc Jones2a0c61d2012-10-29 05:24:01 +0000133 u32 tmp, cap_save, cmd;
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800134 int i, j;
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500135 volatile u8 *port_mmio;
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800136
Vadim Bendebury284231e2012-10-29 05:23:44 +0000137 debug("ahci_host_init: start\n");
138
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800139 cap_save = readl(mmio + HOST_CAP);
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500140 cap_save &= ((1 << 28) | (1 << 17));
Marc Jones2a0c61d2012-10-29 05:24:01 +0000141 cap_save |= (1 << 27); /* Staggered Spin-up. Not needed. */
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800142
143 /* global controller reset */
144 tmp = readl(mmio + HOST_CTL);
145 if ((tmp & HOST_RESET) == 0)
146 writel_with_flush(tmp | HOST_RESET, mmio + HOST_CTL);
147
148 /* reset must complete within 1 second, or
149 * the hardware should be considered fried.
150 */
Stefan Reinauer9a65b872012-10-29 05:23:49 +0000151 i = 1000;
152 do {
153 udelay(1000);
154 tmp = readl(mmio + HOST_CTL);
155 if (!i--) {
156 debug("controller reset failed (0x%x)\n", tmp);
157 return -1;
158 }
159 } while (tmp & HOST_RESET);
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800160
161 writel_with_flush(HOST_AHCI_EN, mmio + HOST_CTL);
162 writel(cap_save, mmio + HOST_CAP);
163 writel_with_flush(0xf, mmio + HOST_PORTS_IMPL);
164
Rob Herring942e3142011-07-06 16:13:36 +0000165#ifndef CONFIG_SCSI_AHCI_PLAT
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800166 pci_read_config_word(pdev, PCI_VENDOR_ID, &vendor);
167
168 if (vendor == PCI_VENDOR_ID_INTEL) {
169 u16 tmp16;
170 pci_read_config_word(pdev, 0x92, &tmp16);
171 tmp16 |= 0xf;
172 pci_write_config_word(pdev, 0x92, tmp16);
173 }
Rob Herring942e3142011-07-06 16:13:36 +0000174#endif
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800175 probe_ent->cap = readl(mmio + HOST_CAP);
176 probe_ent->port_map = readl(mmio + HOST_PORTS_IMPL);
177 probe_ent->n_ports = (probe_ent->cap & 0x1f) + 1;
178
179 debug("cap 0x%x port_map 0x%x n_ports %d\n",
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500180 probe_ent->cap, probe_ent->port_map, probe_ent->n_ports);
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800181
Vadim Bendebury284231e2012-10-29 05:23:44 +0000182 if (probe_ent->n_ports > CONFIG_SYS_SCSI_MAX_SCSI_ID)
183 probe_ent->n_ports = CONFIG_SYS_SCSI_MAX_SCSI_ID;
184
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800185 for (i = 0; i < probe_ent->n_ports; i++) {
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500186 probe_ent->port[i].port_mmio = ahci_port_base((u32) mmio, i);
187 port_mmio = (u8 *) probe_ent->port[i].port_mmio;
188 ahci_setup_port(&probe_ent->port[i], (unsigned long)mmio, i);
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800189
190 /* make sure port is not active */
191 tmp = readl(port_mmio + PORT_CMD);
192 if (tmp & (PORT_CMD_LIST_ON | PORT_CMD_FIS_ON |
193 PORT_CMD_FIS_RX | PORT_CMD_START)) {
Stefan Reinauer7ba79172012-10-29 05:23:50 +0000194 debug("Port %d is active. Deactivating.\n", i);
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800195 tmp &= ~(PORT_CMD_LIST_ON | PORT_CMD_FIS_ON |
196 PORT_CMD_FIS_RX | PORT_CMD_START);
197 writel_with_flush(tmp, port_mmio + PORT_CMD);
198
199 /* spec says 500 msecs for each bit, so
200 * this is slightly incorrect.
201 */
202 msleep(500);
203 }
204
Marc Jones2a0c61d2012-10-29 05:24:01 +0000205 /* Add the spinup command to whatever mode bits may
206 * already be on in the command register.
207 */
208 cmd = readl(port_mmio + PORT_CMD);
209 cmd |= PORT_CMD_FIS_RX;
210 cmd |= PORT_CMD_SPIN_UP;
211 writel_with_flush(cmd, port_mmio + PORT_CMD);
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800212
Marc Jones2a0c61d2012-10-29 05:24:01 +0000213 /* Bring up SATA link.
214 * SATA link bringup time is usually less than 1 ms; only very
215 * rarely has it taken between 1-2 ms. Never seen it above 2 ms.
216 */
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800217 j = 0;
Walter Murphy57847662012-10-29 05:24:00 +0000218 while (j < WAIT_MS_LINKUP) {
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800219 tmp = readl(port_mmio + PORT_SCR_STAT);
220 if ((tmp & 0xf) == 0x3)
221 break;
Stefan Reinauer9a65b872012-10-29 05:23:49 +0000222 udelay(1000);
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800223 j++;
224 }
Marc Jones2a0c61d2012-10-29 05:24:01 +0000225 if (j == WAIT_MS_LINKUP) {
226 printf("SATA link %d timeout.\n", i);
227 continue;
228 } else {
229 debug("SATA link ok.\n");
230 }
231
232 /* Clear error status */
233 tmp = readl(port_mmio + PORT_SCR_ERR);
234 if (tmp)
235 writel(tmp, port_mmio + PORT_SCR_ERR);
236
237 debug("Spinning up device on SATA port %d... ", i);
238
239 j = 0;
240 while (j < WAIT_MS_SPINUP) {
241 tmp = readl(port_mmio + PORT_TFDATA);
242 if (!(tmp & (ATA_STAT_BUSY | ATA_STAT_DRQ)))
243 break;
244 udelay(1000);
245 j++;
246 }
247 printf("Target spinup took %d ms.\n", j);
248 if (j == WAIT_MS_SPINUP)
Stefan Reinauer9a65b872012-10-29 05:23:49 +0000249 debug("timeout.\n");
250 else
251 debug("ok.\n");
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800252
253 tmp = readl(port_mmio + PORT_SCR_ERR);
254 debug("PORT_SCR_ERR 0x%x\n", tmp);
255 writel(tmp, port_mmio + PORT_SCR_ERR);
256
257 /* ack any pending irq events for this port */
258 tmp = readl(port_mmio + PORT_IRQ_STAT);
259 debug("PORT_IRQ_STAT 0x%x\n", tmp);
260 if (tmp)
261 writel(tmp, port_mmio + PORT_IRQ_STAT);
262
263 writel(1 << i, mmio + HOST_IRQ_STAT);
264
265 /* set irq mask (enables interrupts) */
266 writel(DEF_PORT_IRQ, port_mmio + PORT_IRQ_MASK);
267
Stefan Reinauer4e422bc2012-10-29 05:23:51 +0000268 /* register linkup ports */
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800269 tmp = readl(port_mmio + PORT_SCR_STAT);
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500270 debug("Port %d status: 0x%x\n", i, tmp);
271 if ((tmp & 0xf) == 0x03)
272 probe_ent->link_port_map |= (0x01 << i);
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800273 }
274
275 tmp = readl(mmio + HOST_CTL);
276 debug("HOST_CTL 0x%x\n", tmp);
277 writel(tmp | HOST_IRQ_EN, mmio + HOST_CTL);
278 tmp = readl(mmio + HOST_CTL);
279 debug("HOST_CTL 0x%x\n", tmp);
Rob Herring942e3142011-07-06 16:13:36 +0000280#ifndef CONFIG_SCSI_AHCI_PLAT
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800281 pci_read_config_word(pdev, PCI_COMMAND, &tmp16);
282 tmp |= PCI_COMMAND_MASTER;
283 pci_write_config_word(pdev, PCI_COMMAND, tmp16);
Rob Herring942e3142011-07-06 16:13:36 +0000284#endif
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800285 return 0;
286}
287
288
289static void ahci_print_info(struct ahci_probe_ent *probe_ent)
290{
Rob Herring942e3142011-07-06 16:13:36 +0000291#ifndef CONFIG_SCSI_AHCI_PLAT
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800292 pci_dev_t pdev = probe_ent->dev;
Rob Herring942e3142011-07-06 16:13:36 +0000293 u16 cc;
294#endif
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500295 volatile u8 *mmio = (volatile u8 *)probe_ent->mmio_base;
Stefan Reinauer4e422bc2012-10-29 05:23:51 +0000296 u32 vers, cap, cap2, impl, speed;
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800297 const char *speed_s;
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800298 const char *scc_s;
299
300 vers = readl(mmio + HOST_VERSION);
301 cap = probe_ent->cap;
Stefan Reinauer4e422bc2012-10-29 05:23:51 +0000302 cap2 = readl(mmio + HOST_CAP2);
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800303 impl = probe_ent->port_map;
304
305 speed = (cap >> 20) & 0xf;
306 if (speed == 1)
307 speed_s = "1.5";
308 else if (speed == 2)
309 speed_s = "3";
Stefan Reinauer4e422bc2012-10-29 05:23:51 +0000310 else if (speed == 3)
311 speed_s = "6";
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800312 else
313 speed_s = "?";
314
Rob Herring942e3142011-07-06 16:13:36 +0000315#ifdef CONFIG_SCSI_AHCI_PLAT
316 scc_s = "SATA";
317#else
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800318 pci_read_config_word(pdev, 0x0a, &cc);
319 if (cc == 0x0101)
320 scc_s = "IDE";
321 else if (cc == 0x0106)
322 scc_s = "SATA";
323 else if (cc == 0x0104)
324 scc_s = "RAID";
325 else
326 scc_s = "unknown";
Rob Herring942e3142011-07-06 16:13:36 +0000327#endif
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500328 printf("AHCI %02x%02x.%02x%02x "
329 "%u slots %u ports %s Gbps 0x%x impl %s mode\n",
330 (vers >> 24) & 0xff,
331 (vers >> 16) & 0xff,
332 (vers >> 8) & 0xff,
333 vers & 0xff,
334 ((cap >> 8) & 0x1f) + 1, (cap & 0x1f) + 1, speed_s, impl, scc_s);
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800335
336 printf("flags: "
Stefan Reinauer4e422bc2012-10-29 05:23:51 +0000337 "%s%s%s%s%s%s%s"
338 "%s%s%s%s%s%s%s"
339 "%s%s%s%s%s%s\n",
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500340 cap & (1 << 31) ? "64bit " : "",
341 cap & (1 << 30) ? "ncq " : "",
342 cap & (1 << 28) ? "ilck " : "",
343 cap & (1 << 27) ? "stag " : "",
344 cap & (1 << 26) ? "pm " : "",
345 cap & (1 << 25) ? "led " : "",
346 cap & (1 << 24) ? "clo " : "",
347 cap & (1 << 19) ? "nz " : "",
348 cap & (1 << 18) ? "only " : "",
349 cap & (1 << 17) ? "pmp " : "",
Stefan Reinauer4e422bc2012-10-29 05:23:51 +0000350 cap & (1 << 16) ? "fbss " : "",
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500351 cap & (1 << 15) ? "pio " : "",
352 cap & (1 << 14) ? "slum " : "",
Stefan Reinauer4e422bc2012-10-29 05:23:51 +0000353 cap & (1 << 13) ? "part " : "",
354 cap & (1 << 7) ? "ccc " : "",
355 cap & (1 << 6) ? "ems " : "",
356 cap & (1 << 5) ? "sxs " : "",
357 cap2 & (1 << 2) ? "apst " : "",
358 cap2 & (1 << 1) ? "nvmp " : "",
359 cap2 & (1 << 0) ? "boh " : "");
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800360}
361
Rob Herring942e3142011-07-06 16:13:36 +0000362#ifndef CONFIG_SCSI_AHCI_PLAT
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500363static int ahci_init_one(pci_dev_t pdev)
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800364{
Ed Swarthout63cec582007-08-02 14:09:49 -0500365 u16 vendor;
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800366 int rc;
367
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500368 memset((void *)ataid, 0, sizeof(hd_driveid_t *) * AHCI_MAX_PORTS);
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800369
Ed Swarthout594e7982007-08-14 14:06:45 -0500370 probe_ent = malloc(sizeof(struct ahci_probe_ent));
371 memset(probe_ent, 0, sizeof(struct ahci_probe_ent));
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800372 probe_ent->dev = pdev;
373
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500374 probe_ent->host_flags = ATA_FLAG_SATA
375 | ATA_FLAG_NO_LEGACY
376 | ATA_FLAG_MMIO
377 | ATA_FLAG_PIO_DMA
378 | ATA_FLAG_NO_ATAPI;
379 probe_ent->pio_mask = 0x1f;
380 probe_ent->udma_mask = 0x7f; /*Fixme,assume to support UDMA6 */
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800381
Vadim Bendebury284231e2012-10-29 05:23:44 +0000382 pci_read_config_dword(pdev, PCI_BASE_ADDRESS_5, &probe_ent->mmio_base);
383 debug("ahci mmio_base=0x%08x\n", probe_ent->mmio_base);
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800384
385 /* Take from kernel:
386 * JMicron-specific fixup:
387 * make sure we're in AHCI mode
388 */
389 pci_read_config_word(pdev, PCI_VENDOR_ID, &vendor);
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500390 if (vendor == 0x197b)
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800391 pci_write_config_byte(pdev, 0x41, 0xa1);
392
393 /* initialize adapter */
394 rc = ahci_host_init(probe_ent);
395 if (rc)
396 goto err_out;
397
398 ahci_print_info(probe_ent);
399
400 return 0;
401
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500402 err_out:
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800403 return rc;
404}
Rob Herring942e3142011-07-06 16:13:36 +0000405#endif
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800406
407#define MAX_DATA_BYTE_COUNT (4*1024*1024)
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500408
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800409static int ahci_fill_sg(u8 port, unsigned char *buf, int buf_len)
410{
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800411 struct ahci_ioports *pp = &(probe_ent->port[port]);
412 struct ahci_sg *ahci_sg = pp->cmd_tbl_sg;
413 u32 sg_count;
414 int i;
415
416 sg_count = ((buf_len - 1) / MAX_DATA_BYTE_COUNT) + 1;
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500417 if (sg_count > AHCI_MAX_SG) {
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800418 printf("Error:Too much sg!\n");
419 return -1;
420 }
421
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500422 for (i = 0; i < sg_count; i++) {
423 ahci_sg->addr =
424 cpu_to_le32((u32) buf + i * MAX_DATA_BYTE_COUNT);
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800425 ahci_sg->addr_hi = 0;
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500426 ahci_sg->flags_size = cpu_to_le32(0x3fffff &
427 (buf_len < MAX_DATA_BYTE_COUNT
428 ? (buf_len - 1)
429 : (MAX_DATA_BYTE_COUNT - 1)));
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800430 ahci_sg++;
431 buf_len -= MAX_DATA_BYTE_COUNT;
432 }
433
434 return sg_count;
435}
436
437
438static void ahci_fill_cmd_slot(struct ahci_ioports *pp, u32 opts)
439{
440 pp->cmd_slot->opts = cpu_to_le32(opts);
441 pp->cmd_slot->status = 0;
442 pp->cmd_slot->tbl_addr = cpu_to_le32(pp->cmd_tbl & 0xffffffff);
443 pp->cmd_slot->tbl_addr_hi = 0;
444}
445
446
Gabe Blacke81058c2012-10-29 05:23:52 +0000447#ifdef CONFIG_AHCI_SETFEATURES_XFER
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800448static void ahci_set_feature(u8 port)
449{
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800450 struct ahci_ioports *pp = &(probe_ent->port[port]);
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500451 volatile u8 *port_mmio = (volatile u8 *)pp->port_mmio;
452 u32 cmd_fis_len = 5; /* five dwords */
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800453 u8 fis[20];
454
Stefan Reinauer4e422bc2012-10-29 05:23:51 +0000455 /* set feature */
Taylor Huttc8731112012-10-29 05:23:55 +0000456 memset(fis, 0, sizeof(fis));
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800457 fis[0] = 0x27;
458 fis[1] = 1 << 7;
459 fis[2] = ATA_CMD_SETF;
460 fis[3] = SETFEATURES_XFER;
461 fis[12] = __ilog2(probe_ent->udma_mask + 1) + 0x40 - 0x01;
462
Taylor Huttc8731112012-10-29 05:23:55 +0000463 memcpy((unsigned char *)pp->cmd_tbl, fis, sizeof(fis));
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800464 ahci_fill_cmd_slot(pp, cmd_fis_len);
Taylor Hutt90b276f2012-10-29 05:23:59 +0000465 ahci_dcache_flush_sata_cmd(pp);
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800466 writel(1, port_mmio + PORT_CMD_ISSUE);
467 readl(port_mmio + PORT_CMD_ISSUE);
468
Walter Murphy57847662012-10-29 05:24:00 +0000469 if (waiting_for_cmd_completed(port_mmio + PORT_CMD_ISSUE,
470 WAIT_MS_DATAIO, 0x1)) {
Stefan Reinauer4e422bc2012-10-29 05:23:51 +0000471 printf("set feature error on port %d!\n", port);
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800472 }
473}
Gabe Blacke81058c2012-10-29 05:23:52 +0000474#endif
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800475
476
477static int ahci_port_start(u8 port)
478{
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800479 struct ahci_ioports *pp = &(probe_ent->port[port]);
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500480 volatile u8 *port_mmio = (volatile u8 *)pp->port_mmio;
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800481 u32 port_status;
482 u32 mem;
483
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500484 debug("Enter start port: %d\n", port);
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800485 port_status = readl(port_mmio + PORT_SCR_STAT);
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500486 debug("Port %d status: %x\n", port, port_status);
487 if ((port_status & 0xf) != 0x03) {
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800488 printf("No Link on this port!\n");
489 return -1;
490 }
491
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500492 mem = (u32) malloc(AHCI_PORT_PRIV_DMA_SZ + 2048);
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800493 if (!mem) {
494 free(pp);
495 printf("No mem for table!\n");
496 return -ENOMEM;
497 }
498
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500499 mem = (mem + 0x800) & (~0x7ff); /* Aligned to 2048-bytes */
500 memset((u8 *) mem, 0, AHCI_PORT_PRIV_DMA_SZ);
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800501
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800502 /*
503 * First item in chunk of DMA memory: 32-slot command table,
504 * 32 bytes each in size
505 */
Taylor Hutt64738e82012-10-29 05:23:58 +0000506 pp->cmd_slot =
507 (struct ahci_cmd_hdr *)(uintptr_t)virt_to_phys((void *)mem);
Vadim Bendebury284231e2012-10-29 05:23:44 +0000508 debug("cmd_slot = 0x%x\n", (unsigned)pp->cmd_slot);
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800509 mem += (AHCI_CMD_SLOT_SZ + 224);
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500510
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800511 /*
512 * Second item: Received-FIS area
513 */
Taylor Hutt64738e82012-10-29 05:23:58 +0000514 pp->rx_fis = virt_to_phys((void *)mem);
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800515 mem += AHCI_RX_FIS_SZ;
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500516
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800517 /*
518 * Third item: data area for storing a single command
519 * and its scatter-gather table
520 */
Taylor Hutt64738e82012-10-29 05:23:58 +0000521 pp->cmd_tbl = virt_to_phys((void *)mem);
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500522 debug("cmd_tbl_dma = 0x%x\n", pp->cmd_tbl);
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800523
524 mem += AHCI_CMD_TBL_HDR;
Taylor Hutt64738e82012-10-29 05:23:58 +0000525 pp->cmd_tbl_sg =
526 (struct ahci_sg *)(uintptr_t)virt_to_phys((void *)mem);
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800527
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500528 writel_with_flush((u32) pp->cmd_slot, port_mmio + PORT_LST_ADDR);
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800529
530 writel_with_flush(pp->rx_fis, port_mmio + PORT_FIS_ADDR);
531
532 writel_with_flush(PORT_CMD_ICC_ACTIVE | PORT_CMD_FIS_RX |
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500533 PORT_CMD_POWER_ON | PORT_CMD_SPIN_UP |
534 PORT_CMD_START, port_mmio + PORT_CMD);
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800535
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500536 debug("Exit start port %d\n", port);
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800537
538 return 0;
539}
540
541
Hung-Te Linb7a21b72012-10-29 05:23:53 +0000542static int ahci_device_data_io(u8 port, u8 *fis, int fis_len, u8 *buf,
543 int buf_len, u8 is_write)
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800544{
545
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500546 struct ahci_ioports *pp = &(probe_ent->port[port]);
547 volatile u8 *port_mmio = (volatile u8 *)pp->port_mmio;
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800548 u32 opts;
549 u32 port_status;
550 int sg_count;
551
Hung-Te Linb7a21b72012-10-29 05:23:53 +0000552 debug("Enter %s: for port %d\n", __func__, port);
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800553
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500554 if (port > probe_ent->n_ports) {
Taylor Hutt5a2b77f2012-10-29 05:23:56 +0000555 printf("Invalid port number %d\n", port);
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800556 return -1;
557 }
558
559 port_status = readl(port_mmio + PORT_SCR_STAT);
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500560 if ((port_status & 0xf) != 0x03) {
561 debug("No Link on port %d!\n", port);
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800562 return -1;
563 }
564
565 memcpy((unsigned char *)pp->cmd_tbl, fis, fis_len);
566
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500567 sg_count = ahci_fill_sg(port, buf, buf_len);
Hung-Te Linb7a21b72012-10-29 05:23:53 +0000568 opts = (fis_len >> 2) | (sg_count << 16) | (is_write << 6);
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800569 ahci_fill_cmd_slot(pp, opts);
570
Taylor Hutt90b276f2012-10-29 05:23:59 +0000571 ahci_dcache_flush_sata_cmd(pp);
572 ahci_dcache_flush_range((unsigned)buf, (unsigned)buf_len);
573
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800574 writel_with_flush(1, port_mmio + PORT_CMD_ISSUE);
575
Walter Murphy57847662012-10-29 05:24:00 +0000576 if (waiting_for_cmd_completed(port_mmio + PORT_CMD_ISSUE,
577 WAIT_MS_DATAIO, 0x1)) {
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800578 printf("timeout exit!\n");
579 return -1;
580 }
Taylor Hutt90b276f2012-10-29 05:23:59 +0000581
582 ahci_dcache_invalidate_range((unsigned)buf, (unsigned)buf_len);
Hung-Te Linb7a21b72012-10-29 05:23:53 +0000583 debug("%s: %d byte transferred.\n", __func__, pp->cmd_slot->status);
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800584
585 return 0;
586}
587
588
589static char *ata_id_strcpy(u16 *target, u16 *src, int len)
590{
591 int i;
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500592 for (i = 0; i < len / 2; i++)
Rob Herringe5a6c792011-06-01 09:10:26 +0000593 target[i] = swab16(src[i]);
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800594 return (char *)target;
595}
596
597
598static void dump_ataid(hd_driveid_t *ataid)
599{
600 debug("(49)ataid->capability = 0x%x\n", ataid->capability);
601 debug("(53)ataid->field_valid =0x%x\n", ataid->field_valid);
602 debug("(63)ataid->dma_mword = 0x%x\n", ataid->dma_mword);
603 debug("(64)ataid->eide_pio_modes = 0x%x\n", ataid->eide_pio_modes);
604 debug("(75)ataid->queue_depth = 0x%x\n", ataid->queue_depth);
605 debug("(80)ataid->major_rev_num = 0x%x\n", ataid->major_rev_num);
606 debug("(81)ataid->minor_rev_num = 0x%x\n", ataid->minor_rev_num);
607 debug("(82)ataid->command_set_1 = 0x%x\n", ataid->command_set_1);
608 debug("(83)ataid->command_set_2 = 0x%x\n", ataid->command_set_2);
609 debug("(84)ataid->cfsse = 0x%x\n", ataid->cfsse);
610 debug("(85)ataid->cfs_enable_1 = 0x%x\n", ataid->cfs_enable_1);
611 debug("(86)ataid->cfs_enable_2 = 0x%x\n", ataid->cfs_enable_2);
612 debug("(87)ataid->csf_default = 0x%x\n", ataid->csf_default);
613 debug("(88)ataid->dma_ultra = 0x%x\n", ataid->dma_ultra);
614 debug("(93)ataid->hw_config = 0x%x\n", ataid->hw_config);
615}
616
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500617
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800618/*
619 * SCSI INQUIRY command operation.
620 */
621static int ata_scsiop_inquiry(ccb *pccb)
622{
623 u8 hdr[] = {
624 0,
625 0,
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500626 0x5, /* claim SPC-3 version compatibility */
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800627 2,
628 95 - 4,
629 };
630 u8 fis[20];
631 u8 *tmpid;
632 u8 port;
633
634 /* Clean ccb data buffer */
635 memset(pccb->pdata, 0, pccb->datalen);
636
637 memcpy(pccb->pdata, hdr, sizeof(hdr));
638
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500639 if (pccb->datalen <= 35)
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800640 return 0;
641
Taylor Huttc8731112012-10-29 05:23:55 +0000642 memset(fis, 0, sizeof(fis));
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800643 /* Construct the FIS */
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500644 fis[0] = 0x27; /* Host to device FIS. */
645 fis[1] = 1 << 7; /* Command FIS. */
646 fis[2] = ATA_CMD_IDENT; /* Command byte. */
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800647
648 /* Read id from sata */
649 port = pccb->target;
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500650 if (!(tmpid = malloc(sizeof(hd_driveid_t))))
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800651 return -ENOMEM;
652
Taylor Huttc8731112012-10-29 05:23:55 +0000653 if (ahci_device_data_io(port, (u8 *) &fis, sizeof(fis), tmpid,
Hung-Te Linb7a21b72012-10-29 05:23:53 +0000654 sizeof(hd_driveid_t), 0)) {
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800655 debug("scsi_ahci: SCSI inquiry command failure.\n");
656 return -EIO;
657 }
658
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500659 if (ataid[port])
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800660 free(ataid[port]);
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500661 ataid[port] = (hd_driveid_t *) tmpid;
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800662
663 memcpy(&pccb->pdata[8], "ATA ", 8);
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500664 ata_id_strcpy((u16 *) &pccb->pdata[16], (u16 *)ataid[port]->model, 16);
665 ata_id_strcpy((u16 *) &pccb->pdata[32], (u16 *)ataid[port]->fw_rev, 4);
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800666
667 dump_ataid(ataid[port]);
668 return 0;
669}
670
671
672/*
Hung-Te Linb7a21b72012-10-29 05:23:53 +0000673 * SCSI READ10/WRITE10 command operation.
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800674 */
Hung-Te Linb7a21b72012-10-29 05:23:53 +0000675static int ata_scsiop_read_write(ccb *pccb, u8 is_write)
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800676{
Vadim Bendebury284231e2012-10-29 05:23:44 +0000677 u32 lba = 0;
678 u16 blocks = 0;
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800679 u8 fis[20];
Vadim Bendebury284231e2012-10-29 05:23:44 +0000680 u8 *user_buffer = pccb->pdata;
681 u32 user_buffer_size = pccb->datalen;
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800682
Vadim Bendebury284231e2012-10-29 05:23:44 +0000683 /* Retrieve the base LBA number from the ccb structure. */
684 memcpy(&lba, pccb->cmd + 2, sizeof(lba));
685 lba = be32_to_cpu(lba);
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800686
Vadim Bendebury284231e2012-10-29 05:23:44 +0000687 /*
688 * And the number of blocks.
689 *
690 * For 10-byte and 16-byte SCSI R/W commands, transfer
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800691 * length 0 means transfer 0 block of data.
692 * However, for ATA R/W commands, sector count 0 means
693 * 256 or 65536 sectors, not 0 sectors as in SCSI.
694 *
695 * WARNING: one or two older ATA drives treat 0 as 0...
696 */
Vadim Bendebury284231e2012-10-29 05:23:44 +0000697 blocks = (((u16)pccb->cmd[7]) << 8) | ((u16) pccb->cmd[8]);
698
Hung-Te Linb7a21b72012-10-29 05:23:53 +0000699 debug("scsi_ahci: %s %d blocks starting from lba 0x%x\n",
700 is_write ? "write" : "read", (unsigned)lba, blocks);
Vadim Bendebury284231e2012-10-29 05:23:44 +0000701
702 /* Preset the FIS */
Taylor Huttc8731112012-10-29 05:23:55 +0000703 memset(fis, 0, sizeof(fis));
Vadim Bendebury284231e2012-10-29 05:23:44 +0000704 fis[0] = 0x27; /* Host to device FIS. */
705 fis[1] = 1 << 7; /* Command FIS. */
Hung-Te Linb7a21b72012-10-29 05:23:53 +0000706 /* Command byte (read/write). */
707 fis[2] = is_write ? ATA_CMD_WR_DMA : ATA_CMD_RD_DMA;
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800708
Vadim Bendebury284231e2012-10-29 05:23:44 +0000709 while (blocks) {
710 u16 now_blocks; /* number of blocks per iteration */
711 u32 transfer_size; /* number of bytes per iteration */
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800712
Hung-Te Linb7a21b72012-10-29 05:23:53 +0000713 now_blocks = min(MAX_SATA_BLOCKS_READ_WRITE, blocks);
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800714
Vadim Bendebury284231e2012-10-29 05:23:44 +0000715 transfer_size = ATA_BLOCKSIZE * now_blocks;
716 if (transfer_size > user_buffer_size) {
717 printf("scsi_ahci: Error: buffer too small.\n");
718 return -EIO;
719 }
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800720
Vadim Bendebury284231e2012-10-29 05:23:44 +0000721 /* LBA address, only support LBA28 in this driver */
722 fis[4] = (lba >> 0) & 0xff;
723 fis[5] = (lba >> 8) & 0xff;
724 fis[6] = (lba >> 16) & 0xff;
725 fis[7] = ((lba >> 24) & 0xf) | 0xe0;
726
727 /* Block (sector) count */
728 fis[12] = (now_blocks >> 0) & 0xff;
729 fis[13] = (now_blocks >> 8) & 0xff;
730
Hung-Te Linb7a21b72012-10-29 05:23:53 +0000731 /* Read/Write from ahci */
732 if (ahci_device_data_io(pccb->target, (u8 *) &fis, sizeof(fis),
733 user_buffer, user_buffer_size,
734 is_write)) {
735 debug("scsi_ahci: SCSI %s10 command failure.\n",
736 is_write ? "WRITE" : "READ");
Vadim Bendebury284231e2012-10-29 05:23:44 +0000737 return -EIO;
738 }
739 user_buffer += transfer_size;
740 user_buffer_size -= transfer_size;
741 blocks -= now_blocks;
742 lba += now_blocks;
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800743 }
744
745 return 0;
746}
747
748
749/*
750 * SCSI READ CAPACITY10 command operation.
751 */
752static int ata_scsiop_read_capacity10(ccb *pccb)
753{
Kumar Galacb6d0b72009-07-13 09:24:00 -0500754 u32 cap;
Gabe Black19d1d412012-10-29 05:23:54 +0000755 u32 block_size;
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800756
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500757 if (!ataid[pccb->target]) {
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800758 printf("scsi_ahci: SCSI READ CAPACITY10 command failure. "
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500759 "\tNo ATA info!\n"
760 "\tPlease run SCSI commmand INQUIRY firstly!\n");
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800761 return -EPERM;
762 }
763
Gabe Black19d1d412012-10-29 05:23:54 +0000764 cap = le32_to_cpu(ataid[pccb->target]->lba_capacity);
765 if (cap == 0xfffffff) {
766 unsigned short *cap48 = ataid[pccb->target]->lba48_capacity;
767 if (cap48[2] || cap48[3]) {
768 cap = 0xffffffff;
769 } else {
770 cap = (le16_to_cpu(cap48[1]) << 16) |
771 (le16_to_cpu(cap48[0]));
772 }
773 }
774
775 cap = cpu_to_be32(cap);
Kumar Galacb6d0b72009-07-13 09:24:00 -0500776 memcpy(pccb->pdata, &cap, sizeof(cap));
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800777
Gabe Black19d1d412012-10-29 05:23:54 +0000778 block_size = cpu_to_be32((u32)512);
779 memcpy(&pccb->pdata[4], &block_size, 4);
780
781 return 0;
782}
783
784
785/*
786 * SCSI READ CAPACITY16 command operation.
787 */
788static int ata_scsiop_read_capacity16(ccb *pccb)
789{
790 u64 cap;
791 u64 block_size;
792
793 if (!ataid[pccb->target]) {
794 printf("scsi_ahci: SCSI READ CAPACITY16 command failure. "
795 "\tNo ATA info!\n"
796 "\tPlease run SCSI commmand INQUIRY firstly!\n");
797 return -EPERM;
798 }
799
800 cap = le32_to_cpu(ataid[pccb->target]->lba_capacity);
801 if (cap == 0xfffffff) {
802 memcpy(&cap, ataid[pccb->target]->lba48_capacity, sizeof(cap));
803 cap = le64_to_cpu(cap);
804 }
805
806 cap = cpu_to_be64(cap);
807 memcpy(pccb->pdata, &cap, sizeof(cap));
808
809 block_size = cpu_to_be64((u64)512);
810 memcpy(&pccb->pdata[8], &block_size, 8);
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800811
812 return 0;
813}
814
815
816/*
817 * SCSI TEST UNIT READY command operation.
818 */
819static int ata_scsiop_test_unit_ready(ccb *pccb)
820{
821 return (ataid[pccb->target]) ? 0 : -EPERM;
822}
823
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500824
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800825int scsi_exec(ccb *pccb)
826{
827 int ret;
828
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500829 switch (pccb->cmd[0]) {
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800830 case SCSI_READ10:
Hung-Te Linb7a21b72012-10-29 05:23:53 +0000831 ret = ata_scsiop_read_write(pccb, 0);
832 break;
833 case SCSI_WRITE10:
834 ret = ata_scsiop_read_write(pccb, 1);
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800835 break;
Gabe Black19d1d412012-10-29 05:23:54 +0000836 case SCSI_RD_CAPAC10:
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800837 ret = ata_scsiop_read_capacity10(pccb);
838 break;
Gabe Black19d1d412012-10-29 05:23:54 +0000839 case SCSI_RD_CAPAC16:
840 ret = ata_scsiop_read_capacity16(pccb);
841 break;
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800842 case SCSI_TST_U_RDY:
843 ret = ata_scsiop_test_unit_ready(pccb);
844 break;
845 case SCSI_INQUIRY:
846 ret = ata_scsiop_inquiry(pccb);
847 break;
848 default:
849 printf("Unsupport SCSI command 0x%02x\n", pccb->cmd[0]);
850 return FALSE;
851 }
852
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500853 if (ret) {
854 debug("SCSI command 0x%02x ret errno %d\n", pccb->cmd[0], ret);
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800855 return FALSE;
856 }
857 return TRUE;
858
859}
860
861
862void scsi_low_level_init(int busdevfunc)
863{
864 int i;
865 u32 linkmap;
866
Rob Herring942e3142011-07-06 16:13:36 +0000867#ifndef CONFIG_SCSI_AHCI_PLAT
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800868 ahci_init_one(busdevfunc);
Rob Herring942e3142011-07-06 16:13:36 +0000869#endif
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800870
871 linkmap = probe_ent->link_port_map;
872
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200873 for (i = 0; i < CONFIG_SYS_SCSI_MAX_SCSI_ID; i++) {
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500874 if (((linkmap >> i) & 0x01)) {
875 if (ahci_port_start((u8) i)) {
876 printf("Can not start port %d\n", i);
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800877 continue;
878 }
Gabe Blacke81058c2012-10-29 05:23:52 +0000879#ifdef CONFIG_AHCI_SETFEATURES_XFER
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500880 ahci_set_feature((u8) i);
Gabe Blacke81058c2012-10-29 05:23:52 +0000881#endif
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800882 }
883 }
884}
885
Rob Herring942e3142011-07-06 16:13:36 +0000886#ifdef CONFIG_SCSI_AHCI_PLAT
887int ahci_init(u32 base)
888{
889 int i, rc = 0;
890 u32 linkmap;
891
892 memset(ataid, 0, sizeof(ataid));
893
894 probe_ent = malloc(sizeof(struct ahci_probe_ent));
895 memset(probe_ent, 0, sizeof(struct ahci_probe_ent));
896
897 probe_ent->host_flags = ATA_FLAG_SATA
898 | ATA_FLAG_NO_LEGACY
899 | ATA_FLAG_MMIO
900 | ATA_FLAG_PIO_DMA
901 | ATA_FLAG_NO_ATAPI;
902 probe_ent->pio_mask = 0x1f;
903 probe_ent->udma_mask = 0x7f; /*Fixme,assume to support UDMA6 */
904
905 probe_ent->mmio_base = base;
906
907 /* initialize adapter */
908 rc = ahci_host_init(probe_ent);
909 if (rc)
910 goto err_out;
911
912 ahci_print_info(probe_ent);
913
914 linkmap = probe_ent->link_port_map;
915
916 for (i = 0; i < CONFIG_SYS_SCSI_MAX_SCSI_ID; i++) {
917 if (((linkmap >> i) & 0x01)) {
918 if (ahci_port_start((u8) i)) {
919 printf("Can not start port %d\n", i);
920 continue;
921 }
Gabe Blacke81058c2012-10-29 05:23:52 +0000922#ifdef CONFIG_AHCI_SETFEATURES_XFER
Rob Herring942e3142011-07-06 16:13:36 +0000923 ahci_set_feature((u8) i);
Gabe Blacke81058c2012-10-29 05:23:52 +0000924#endif
Rob Herring942e3142011-07-06 16:13:36 +0000925 }
926 }
927err_out:
928 return rc;
929}
930#endif
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800931
932void scsi_bus_reset(void)
933{
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500934 /*Not implement*/
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800935}
936
937
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500938void scsi_print_error(ccb * pccb)
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800939{
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500940 /*The ahci error info can be read in the ahci driver*/
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800941}