blob: 719574f220b93067184741a5bf1a130591af27f7 [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 */
56#define WAIT_MS_DATAIO 5000
57#define WAIT_MS_LINKUP 4
58
Jin Zhengxiong4782ac82006-08-23 19:10:44 +080059static inline u32 ahci_port_base(u32 base, u32 port)
60{
61 return base + 0x100 + (port * 0x80);
62}
63
64
65static void ahci_setup_port(struct ahci_ioports *port, unsigned long base,
66 unsigned int port_idx)
67{
68 base = ahci_port_base(base, port_idx);
69
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -050070 port->cmd_addr = base;
71 port->scr_addr = base + PORT_SCR;
Jin Zhengxiong4782ac82006-08-23 19:10:44 +080072}
73
74
75#define msleep(a) udelay(a * 1000)
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -050076
Taylor Hutt90b276f2012-10-29 05:23:59 +000077static void ahci_dcache_flush_range(unsigned begin, unsigned len)
78{
79 const unsigned long start = begin;
80 const unsigned long end = start + len;
81
82 debug("%s: flush dcache: [%#lx, %#lx)\n", __func__, start, end);
83 flush_dcache_range(start, end);
84}
85
86/*
87 * SATA controller DMAs to physical RAM. Ensure data from the
88 * controller is invalidated from dcache; next access comes from
89 * physical RAM.
90 */
91static void ahci_dcache_invalidate_range(unsigned begin, unsigned len)
92{
93 const unsigned long start = begin;
94 const unsigned long end = start + len;
95
96 debug("%s: invalidate dcache: [%#lx, %#lx)\n", __func__, start, end);
97 invalidate_dcache_range(start, end);
98}
99
100/*
101 * Ensure data for SATA controller is flushed out of dcache and
102 * written to physical memory.
103 */
104static void ahci_dcache_flush_sata_cmd(struct ahci_ioports *pp)
105{
106 ahci_dcache_flush_range((unsigned long)pp->cmd_slot,
107 AHCI_PORT_PRIV_DMA_SZ);
108}
109
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500110static int waiting_for_cmd_completed(volatile u8 *offset,
111 int timeout_msec,
112 u32 sign)
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800113{
114 int i;
115 u32 status;
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500116
117 for (i = 0; ((status = readl(offset)) & sign) && i < timeout_msec; i++)
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800118 msleep(1);
119
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500120 return (i < timeout_msec) ? 0 : -1;
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800121}
122
123
124static int ahci_host_init(struct ahci_probe_ent *probe_ent)
125{
Rob Herring942e3142011-07-06 16:13:36 +0000126#ifndef CONFIG_SCSI_AHCI_PLAT
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800127 pci_dev_t pdev = probe_ent->dev;
Rob Herring942e3142011-07-06 16:13:36 +0000128 u16 tmp16;
129 unsigned short vendor;
130#endif
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800131 volatile u8 *mmio = (volatile u8 *)probe_ent->mmio_base;
132 u32 tmp, cap_save;
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800133 int i, j;
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500134 volatile u8 *port_mmio;
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800135
Vadim Bendebury284231e2012-10-29 05:23:44 +0000136 debug("ahci_host_init: start\n");
137
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800138 cap_save = readl(mmio + HOST_CAP);
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500139 cap_save &= ((1 << 28) | (1 << 17));
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800140 cap_save |= (1 << 27);
141
142 /* global controller reset */
143 tmp = readl(mmio + HOST_CTL);
144 if ((tmp & HOST_RESET) == 0)
145 writel_with_flush(tmp | HOST_RESET, mmio + HOST_CTL);
146
147 /* reset must complete within 1 second, or
148 * the hardware should be considered fried.
149 */
Stefan Reinauer9a65b872012-10-29 05:23:49 +0000150 i = 1000;
151 do {
152 udelay(1000);
153 tmp = readl(mmio + HOST_CTL);
154 if (!i--) {
155 debug("controller reset failed (0x%x)\n", tmp);
156 return -1;
157 }
158 } while (tmp & HOST_RESET);
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800159
160 writel_with_flush(HOST_AHCI_EN, mmio + HOST_CTL);
161 writel(cap_save, mmio + HOST_CAP);
162 writel_with_flush(0xf, mmio + HOST_PORTS_IMPL);
163
Rob Herring942e3142011-07-06 16:13:36 +0000164#ifndef CONFIG_SCSI_AHCI_PLAT
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800165 pci_read_config_word(pdev, PCI_VENDOR_ID, &vendor);
166
167 if (vendor == PCI_VENDOR_ID_INTEL) {
168 u16 tmp16;
169 pci_read_config_word(pdev, 0x92, &tmp16);
170 tmp16 |= 0xf;
171 pci_write_config_word(pdev, 0x92, tmp16);
172 }
Rob Herring942e3142011-07-06 16:13:36 +0000173#endif
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800174 probe_ent->cap = readl(mmio + HOST_CAP);
175 probe_ent->port_map = readl(mmio + HOST_PORTS_IMPL);
176 probe_ent->n_ports = (probe_ent->cap & 0x1f) + 1;
177
178 debug("cap 0x%x port_map 0x%x n_ports %d\n",
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500179 probe_ent->cap, probe_ent->port_map, probe_ent->n_ports);
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800180
Vadim Bendebury284231e2012-10-29 05:23:44 +0000181 if (probe_ent->n_ports > CONFIG_SYS_SCSI_MAX_SCSI_ID)
182 probe_ent->n_ports = CONFIG_SYS_SCSI_MAX_SCSI_ID;
183
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800184 for (i = 0; i < probe_ent->n_ports; i++) {
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500185 probe_ent->port[i].port_mmio = ahci_port_base((u32) mmio, i);
186 port_mmio = (u8 *) probe_ent->port[i].port_mmio;
187 ahci_setup_port(&probe_ent->port[i], (unsigned long)mmio, i);
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800188
189 /* make sure port is not active */
190 tmp = readl(port_mmio + PORT_CMD);
191 if (tmp & (PORT_CMD_LIST_ON | PORT_CMD_FIS_ON |
192 PORT_CMD_FIS_RX | PORT_CMD_START)) {
Stefan Reinauer7ba79172012-10-29 05:23:50 +0000193 debug("Port %d is active. Deactivating.\n", i);
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800194 tmp &= ~(PORT_CMD_LIST_ON | PORT_CMD_FIS_ON |
195 PORT_CMD_FIS_RX | PORT_CMD_START);
196 writel_with_flush(tmp, port_mmio + PORT_CMD);
197
198 /* spec says 500 msecs for each bit, so
199 * this is slightly incorrect.
200 */
201 msleep(500);
202 }
203
Stefan Reinauer7ba79172012-10-29 05:23:50 +0000204 debug("Spinning up port %d... ", i);
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800205 writel(PORT_CMD_SPIN_UP, port_mmio + PORT_CMD);
206
207 j = 0;
Walter Murphy57847662012-10-29 05:24:00 +0000208 while (j < WAIT_MS_LINKUP) {
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800209 tmp = readl(port_mmio + PORT_SCR_STAT);
210 if ((tmp & 0xf) == 0x3)
211 break;
Stefan Reinauer9a65b872012-10-29 05:23:49 +0000212 udelay(1000);
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800213 j++;
214 }
Walter Murphy57847662012-10-29 05:24:00 +0000215 if (j == WAIT_MS_LINKUP)
Stefan Reinauer9a65b872012-10-29 05:23:49 +0000216 debug("timeout.\n");
217 else
218 debug("ok.\n");
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800219
220 tmp = readl(port_mmio + PORT_SCR_ERR);
221 debug("PORT_SCR_ERR 0x%x\n", tmp);
222 writel(tmp, port_mmio + PORT_SCR_ERR);
223
224 /* ack any pending irq events for this port */
225 tmp = readl(port_mmio + PORT_IRQ_STAT);
226 debug("PORT_IRQ_STAT 0x%x\n", tmp);
227 if (tmp)
228 writel(tmp, port_mmio + PORT_IRQ_STAT);
229
230 writel(1 << i, mmio + HOST_IRQ_STAT);
231
232 /* set irq mask (enables interrupts) */
233 writel(DEF_PORT_IRQ, port_mmio + PORT_IRQ_MASK);
234
Stefan Reinauer4e422bc2012-10-29 05:23:51 +0000235 /* register linkup ports */
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800236 tmp = readl(port_mmio + PORT_SCR_STAT);
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500237 debug("Port %d status: 0x%x\n", i, tmp);
238 if ((tmp & 0xf) == 0x03)
239 probe_ent->link_port_map |= (0x01 << i);
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800240 }
241
242 tmp = readl(mmio + HOST_CTL);
243 debug("HOST_CTL 0x%x\n", tmp);
244 writel(tmp | HOST_IRQ_EN, mmio + HOST_CTL);
245 tmp = readl(mmio + HOST_CTL);
246 debug("HOST_CTL 0x%x\n", tmp);
Rob Herring942e3142011-07-06 16:13:36 +0000247#ifndef CONFIG_SCSI_AHCI_PLAT
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800248 pci_read_config_word(pdev, PCI_COMMAND, &tmp16);
249 tmp |= PCI_COMMAND_MASTER;
250 pci_write_config_word(pdev, PCI_COMMAND, tmp16);
Rob Herring942e3142011-07-06 16:13:36 +0000251#endif
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800252 return 0;
253}
254
255
256static void ahci_print_info(struct ahci_probe_ent *probe_ent)
257{
Rob Herring942e3142011-07-06 16:13:36 +0000258#ifndef CONFIG_SCSI_AHCI_PLAT
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800259 pci_dev_t pdev = probe_ent->dev;
Rob Herring942e3142011-07-06 16:13:36 +0000260 u16 cc;
261#endif
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500262 volatile u8 *mmio = (volatile u8 *)probe_ent->mmio_base;
Stefan Reinauer4e422bc2012-10-29 05:23:51 +0000263 u32 vers, cap, cap2, impl, speed;
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800264 const char *speed_s;
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800265 const char *scc_s;
266
267 vers = readl(mmio + HOST_VERSION);
268 cap = probe_ent->cap;
Stefan Reinauer4e422bc2012-10-29 05:23:51 +0000269 cap2 = readl(mmio + HOST_CAP2);
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800270 impl = probe_ent->port_map;
271
272 speed = (cap >> 20) & 0xf;
273 if (speed == 1)
274 speed_s = "1.5";
275 else if (speed == 2)
276 speed_s = "3";
Stefan Reinauer4e422bc2012-10-29 05:23:51 +0000277 else if (speed == 3)
278 speed_s = "6";
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800279 else
280 speed_s = "?";
281
Rob Herring942e3142011-07-06 16:13:36 +0000282#ifdef CONFIG_SCSI_AHCI_PLAT
283 scc_s = "SATA";
284#else
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800285 pci_read_config_word(pdev, 0x0a, &cc);
286 if (cc == 0x0101)
287 scc_s = "IDE";
288 else if (cc == 0x0106)
289 scc_s = "SATA";
290 else if (cc == 0x0104)
291 scc_s = "RAID";
292 else
293 scc_s = "unknown";
Rob Herring942e3142011-07-06 16:13:36 +0000294#endif
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500295 printf("AHCI %02x%02x.%02x%02x "
296 "%u slots %u ports %s Gbps 0x%x impl %s mode\n",
297 (vers >> 24) & 0xff,
298 (vers >> 16) & 0xff,
299 (vers >> 8) & 0xff,
300 vers & 0xff,
301 ((cap >> 8) & 0x1f) + 1, (cap & 0x1f) + 1, speed_s, impl, scc_s);
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800302
303 printf("flags: "
Stefan Reinauer4e422bc2012-10-29 05:23:51 +0000304 "%s%s%s%s%s%s%s"
305 "%s%s%s%s%s%s%s"
306 "%s%s%s%s%s%s\n",
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500307 cap & (1 << 31) ? "64bit " : "",
308 cap & (1 << 30) ? "ncq " : "",
309 cap & (1 << 28) ? "ilck " : "",
310 cap & (1 << 27) ? "stag " : "",
311 cap & (1 << 26) ? "pm " : "",
312 cap & (1 << 25) ? "led " : "",
313 cap & (1 << 24) ? "clo " : "",
314 cap & (1 << 19) ? "nz " : "",
315 cap & (1 << 18) ? "only " : "",
316 cap & (1 << 17) ? "pmp " : "",
Stefan Reinauer4e422bc2012-10-29 05:23:51 +0000317 cap & (1 << 16) ? "fbss " : "",
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500318 cap & (1 << 15) ? "pio " : "",
319 cap & (1 << 14) ? "slum " : "",
Stefan Reinauer4e422bc2012-10-29 05:23:51 +0000320 cap & (1 << 13) ? "part " : "",
321 cap & (1 << 7) ? "ccc " : "",
322 cap & (1 << 6) ? "ems " : "",
323 cap & (1 << 5) ? "sxs " : "",
324 cap2 & (1 << 2) ? "apst " : "",
325 cap2 & (1 << 1) ? "nvmp " : "",
326 cap2 & (1 << 0) ? "boh " : "");
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800327}
328
Rob Herring942e3142011-07-06 16:13:36 +0000329#ifndef CONFIG_SCSI_AHCI_PLAT
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500330static int ahci_init_one(pci_dev_t pdev)
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800331{
Ed Swarthout63cec582007-08-02 14:09:49 -0500332 u16 vendor;
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800333 int rc;
334
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500335 memset((void *)ataid, 0, sizeof(hd_driveid_t *) * AHCI_MAX_PORTS);
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800336
Ed Swarthout594e7982007-08-14 14:06:45 -0500337 probe_ent = malloc(sizeof(struct ahci_probe_ent));
338 memset(probe_ent, 0, sizeof(struct ahci_probe_ent));
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800339 probe_ent->dev = pdev;
340
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500341 probe_ent->host_flags = ATA_FLAG_SATA
342 | ATA_FLAG_NO_LEGACY
343 | ATA_FLAG_MMIO
344 | ATA_FLAG_PIO_DMA
345 | ATA_FLAG_NO_ATAPI;
346 probe_ent->pio_mask = 0x1f;
347 probe_ent->udma_mask = 0x7f; /*Fixme,assume to support UDMA6 */
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800348
Vadim Bendebury284231e2012-10-29 05:23:44 +0000349 pci_read_config_dword(pdev, PCI_BASE_ADDRESS_5, &probe_ent->mmio_base);
350 debug("ahci mmio_base=0x%08x\n", probe_ent->mmio_base);
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800351
352 /* Take from kernel:
353 * JMicron-specific fixup:
354 * make sure we're in AHCI mode
355 */
356 pci_read_config_word(pdev, PCI_VENDOR_ID, &vendor);
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500357 if (vendor == 0x197b)
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800358 pci_write_config_byte(pdev, 0x41, 0xa1);
359
360 /* initialize adapter */
361 rc = ahci_host_init(probe_ent);
362 if (rc)
363 goto err_out;
364
365 ahci_print_info(probe_ent);
366
367 return 0;
368
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500369 err_out:
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800370 return rc;
371}
Rob Herring942e3142011-07-06 16:13:36 +0000372#endif
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800373
374#define MAX_DATA_BYTE_COUNT (4*1024*1024)
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500375
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800376static int ahci_fill_sg(u8 port, unsigned char *buf, int buf_len)
377{
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800378 struct ahci_ioports *pp = &(probe_ent->port[port]);
379 struct ahci_sg *ahci_sg = pp->cmd_tbl_sg;
380 u32 sg_count;
381 int i;
382
383 sg_count = ((buf_len - 1) / MAX_DATA_BYTE_COUNT) + 1;
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500384 if (sg_count > AHCI_MAX_SG) {
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800385 printf("Error:Too much sg!\n");
386 return -1;
387 }
388
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500389 for (i = 0; i < sg_count; i++) {
390 ahci_sg->addr =
391 cpu_to_le32((u32) buf + i * MAX_DATA_BYTE_COUNT);
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800392 ahci_sg->addr_hi = 0;
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500393 ahci_sg->flags_size = cpu_to_le32(0x3fffff &
394 (buf_len < MAX_DATA_BYTE_COUNT
395 ? (buf_len - 1)
396 : (MAX_DATA_BYTE_COUNT - 1)));
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800397 ahci_sg++;
398 buf_len -= MAX_DATA_BYTE_COUNT;
399 }
400
401 return sg_count;
402}
403
404
405static void ahci_fill_cmd_slot(struct ahci_ioports *pp, u32 opts)
406{
407 pp->cmd_slot->opts = cpu_to_le32(opts);
408 pp->cmd_slot->status = 0;
409 pp->cmd_slot->tbl_addr = cpu_to_le32(pp->cmd_tbl & 0xffffffff);
410 pp->cmd_slot->tbl_addr_hi = 0;
411}
412
413
Gabe Blacke81058c2012-10-29 05:23:52 +0000414#ifdef CONFIG_AHCI_SETFEATURES_XFER
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800415static void ahci_set_feature(u8 port)
416{
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800417 struct ahci_ioports *pp = &(probe_ent->port[port]);
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500418 volatile u8 *port_mmio = (volatile u8 *)pp->port_mmio;
419 u32 cmd_fis_len = 5; /* five dwords */
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800420 u8 fis[20];
421
Stefan Reinauer4e422bc2012-10-29 05:23:51 +0000422 /* set feature */
Taylor Huttc8731112012-10-29 05:23:55 +0000423 memset(fis, 0, sizeof(fis));
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800424 fis[0] = 0x27;
425 fis[1] = 1 << 7;
426 fis[2] = ATA_CMD_SETF;
427 fis[3] = SETFEATURES_XFER;
428 fis[12] = __ilog2(probe_ent->udma_mask + 1) + 0x40 - 0x01;
429
Taylor Huttc8731112012-10-29 05:23:55 +0000430 memcpy((unsigned char *)pp->cmd_tbl, fis, sizeof(fis));
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800431 ahci_fill_cmd_slot(pp, cmd_fis_len);
Taylor Hutt90b276f2012-10-29 05:23:59 +0000432 ahci_dcache_flush_sata_cmd(pp);
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800433 writel(1, port_mmio + PORT_CMD_ISSUE);
434 readl(port_mmio + PORT_CMD_ISSUE);
435
Walter Murphy57847662012-10-29 05:24:00 +0000436 if (waiting_for_cmd_completed(port_mmio + PORT_CMD_ISSUE,
437 WAIT_MS_DATAIO, 0x1)) {
Stefan Reinauer4e422bc2012-10-29 05:23:51 +0000438 printf("set feature error on port %d!\n", port);
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800439 }
440}
Gabe Blacke81058c2012-10-29 05:23:52 +0000441#endif
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800442
443
444static int ahci_port_start(u8 port)
445{
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800446 struct ahci_ioports *pp = &(probe_ent->port[port]);
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500447 volatile u8 *port_mmio = (volatile u8 *)pp->port_mmio;
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800448 u32 port_status;
449 u32 mem;
450
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500451 debug("Enter start port: %d\n", port);
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800452 port_status = readl(port_mmio + PORT_SCR_STAT);
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500453 debug("Port %d status: %x\n", port, port_status);
454 if ((port_status & 0xf) != 0x03) {
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800455 printf("No Link on this port!\n");
456 return -1;
457 }
458
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500459 mem = (u32) malloc(AHCI_PORT_PRIV_DMA_SZ + 2048);
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800460 if (!mem) {
461 free(pp);
462 printf("No mem for table!\n");
463 return -ENOMEM;
464 }
465
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500466 mem = (mem + 0x800) & (~0x7ff); /* Aligned to 2048-bytes */
467 memset((u8 *) mem, 0, AHCI_PORT_PRIV_DMA_SZ);
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800468
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800469 /*
470 * First item in chunk of DMA memory: 32-slot command table,
471 * 32 bytes each in size
472 */
Taylor Hutt64738e82012-10-29 05:23:58 +0000473 pp->cmd_slot =
474 (struct ahci_cmd_hdr *)(uintptr_t)virt_to_phys((void *)mem);
Vadim Bendebury284231e2012-10-29 05:23:44 +0000475 debug("cmd_slot = 0x%x\n", (unsigned)pp->cmd_slot);
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800476 mem += (AHCI_CMD_SLOT_SZ + 224);
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500477
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800478 /*
479 * Second item: Received-FIS area
480 */
Taylor Hutt64738e82012-10-29 05:23:58 +0000481 pp->rx_fis = virt_to_phys((void *)mem);
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800482 mem += AHCI_RX_FIS_SZ;
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500483
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800484 /*
485 * Third item: data area for storing a single command
486 * and its scatter-gather table
487 */
Taylor Hutt64738e82012-10-29 05:23:58 +0000488 pp->cmd_tbl = virt_to_phys((void *)mem);
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500489 debug("cmd_tbl_dma = 0x%x\n", pp->cmd_tbl);
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800490
491 mem += AHCI_CMD_TBL_HDR;
Taylor Hutt64738e82012-10-29 05:23:58 +0000492 pp->cmd_tbl_sg =
493 (struct ahci_sg *)(uintptr_t)virt_to_phys((void *)mem);
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800494
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500495 writel_with_flush((u32) pp->cmd_slot, port_mmio + PORT_LST_ADDR);
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800496
497 writel_with_flush(pp->rx_fis, port_mmio + PORT_FIS_ADDR);
498
499 writel_with_flush(PORT_CMD_ICC_ACTIVE | PORT_CMD_FIS_RX |
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500500 PORT_CMD_POWER_ON | PORT_CMD_SPIN_UP |
501 PORT_CMD_START, port_mmio + PORT_CMD);
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800502
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500503 debug("Exit start port %d\n", port);
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800504
505 return 0;
506}
507
508
Hung-Te Linb7a21b72012-10-29 05:23:53 +0000509static int ahci_device_data_io(u8 port, u8 *fis, int fis_len, u8 *buf,
510 int buf_len, u8 is_write)
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800511{
512
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500513 struct ahci_ioports *pp = &(probe_ent->port[port]);
514 volatile u8 *port_mmio = (volatile u8 *)pp->port_mmio;
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800515 u32 opts;
516 u32 port_status;
517 int sg_count;
518
Hung-Te Linb7a21b72012-10-29 05:23:53 +0000519 debug("Enter %s: for port %d\n", __func__, port);
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800520
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500521 if (port > probe_ent->n_ports) {
Taylor Hutt5a2b77f2012-10-29 05:23:56 +0000522 printf("Invalid port number %d\n", port);
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800523 return -1;
524 }
525
526 port_status = readl(port_mmio + PORT_SCR_STAT);
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500527 if ((port_status & 0xf) != 0x03) {
528 debug("No Link on port %d!\n", port);
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800529 return -1;
530 }
531
532 memcpy((unsigned char *)pp->cmd_tbl, fis, fis_len);
533
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500534 sg_count = ahci_fill_sg(port, buf, buf_len);
Hung-Te Linb7a21b72012-10-29 05:23:53 +0000535 opts = (fis_len >> 2) | (sg_count << 16) | (is_write << 6);
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800536 ahci_fill_cmd_slot(pp, opts);
537
Taylor Hutt90b276f2012-10-29 05:23:59 +0000538 ahci_dcache_flush_sata_cmd(pp);
539 ahci_dcache_flush_range((unsigned)buf, (unsigned)buf_len);
540
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800541 writel_with_flush(1, port_mmio + PORT_CMD_ISSUE);
542
Walter Murphy57847662012-10-29 05:24:00 +0000543 if (waiting_for_cmd_completed(port_mmio + PORT_CMD_ISSUE,
544 WAIT_MS_DATAIO, 0x1)) {
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800545 printf("timeout exit!\n");
546 return -1;
547 }
Taylor Hutt90b276f2012-10-29 05:23:59 +0000548
549 ahci_dcache_invalidate_range((unsigned)buf, (unsigned)buf_len);
Hung-Te Linb7a21b72012-10-29 05:23:53 +0000550 debug("%s: %d byte transferred.\n", __func__, pp->cmd_slot->status);
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800551
552 return 0;
553}
554
555
556static char *ata_id_strcpy(u16 *target, u16 *src, int len)
557{
558 int i;
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500559 for (i = 0; i < len / 2; i++)
Rob Herringe5a6c792011-06-01 09:10:26 +0000560 target[i] = swab16(src[i]);
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800561 return (char *)target;
562}
563
564
565static void dump_ataid(hd_driveid_t *ataid)
566{
567 debug("(49)ataid->capability = 0x%x\n", ataid->capability);
568 debug("(53)ataid->field_valid =0x%x\n", ataid->field_valid);
569 debug("(63)ataid->dma_mword = 0x%x\n", ataid->dma_mword);
570 debug("(64)ataid->eide_pio_modes = 0x%x\n", ataid->eide_pio_modes);
571 debug("(75)ataid->queue_depth = 0x%x\n", ataid->queue_depth);
572 debug("(80)ataid->major_rev_num = 0x%x\n", ataid->major_rev_num);
573 debug("(81)ataid->minor_rev_num = 0x%x\n", ataid->minor_rev_num);
574 debug("(82)ataid->command_set_1 = 0x%x\n", ataid->command_set_1);
575 debug("(83)ataid->command_set_2 = 0x%x\n", ataid->command_set_2);
576 debug("(84)ataid->cfsse = 0x%x\n", ataid->cfsse);
577 debug("(85)ataid->cfs_enable_1 = 0x%x\n", ataid->cfs_enable_1);
578 debug("(86)ataid->cfs_enable_2 = 0x%x\n", ataid->cfs_enable_2);
579 debug("(87)ataid->csf_default = 0x%x\n", ataid->csf_default);
580 debug("(88)ataid->dma_ultra = 0x%x\n", ataid->dma_ultra);
581 debug("(93)ataid->hw_config = 0x%x\n", ataid->hw_config);
582}
583
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500584
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800585/*
586 * SCSI INQUIRY command operation.
587 */
588static int ata_scsiop_inquiry(ccb *pccb)
589{
590 u8 hdr[] = {
591 0,
592 0,
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500593 0x5, /* claim SPC-3 version compatibility */
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800594 2,
595 95 - 4,
596 };
597 u8 fis[20];
598 u8 *tmpid;
599 u8 port;
600
601 /* Clean ccb data buffer */
602 memset(pccb->pdata, 0, pccb->datalen);
603
604 memcpy(pccb->pdata, hdr, sizeof(hdr));
605
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500606 if (pccb->datalen <= 35)
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800607 return 0;
608
Taylor Huttc8731112012-10-29 05:23:55 +0000609 memset(fis, 0, sizeof(fis));
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800610 /* Construct the FIS */
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500611 fis[0] = 0x27; /* Host to device FIS. */
612 fis[1] = 1 << 7; /* Command FIS. */
613 fis[2] = ATA_CMD_IDENT; /* Command byte. */
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800614
615 /* Read id from sata */
616 port = pccb->target;
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500617 if (!(tmpid = malloc(sizeof(hd_driveid_t))))
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800618 return -ENOMEM;
619
Taylor Huttc8731112012-10-29 05:23:55 +0000620 if (ahci_device_data_io(port, (u8 *) &fis, sizeof(fis), tmpid,
Hung-Te Linb7a21b72012-10-29 05:23:53 +0000621 sizeof(hd_driveid_t), 0)) {
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800622 debug("scsi_ahci: SCSI inquiry command failure.\n");
623 return -EIO;
624 }
625
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500626 if (ataid[port])
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800627 free(ataid[port]);
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500628 ataid[port] = (hd_driveid_t *) tmpid;
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800629
630 memcpy(&pccb->pdata[8], "ATA ", 8);
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500631 ata_id_strcpy((u16 *) &pccb->pdata[16], (u16 *)ataid[port]->model, 16);
632 ata_id_strcpy((u16 *) &pccb->pdata[32], (u16 *)ataid[port]->fw_rev, 4);
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800633
634 dump_ataid(ataid[port]);
635 return 0;
636}
637
638
639/*
Hung-Te Linb7a21b72012-10-29 05:23:53 +0000640 * SCSI READ10/WRITE10 command operation.
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800641 */
Hung-Te Linb7a21b72012-10-29 05:23:53 +0000642static int ata_scsiop_read_write(ccb *pccb, u8 is_write)
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800643{
Vadim Bendebury284231e2012-10-29 05:23:44 +0000644 u32 lba = 0;
645 u16 blocks = 0;
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800646 u8 fis[20];
Vadim Bendebury284231e2012-10-29 05:23:44 +0000647 u8 *user_buffer = pccb->pdata;
648 u32 user_buffer_size = pccb->datalen;
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800649
Vadim Bendebury284231e2012-10-29 05:23:44 +0000650 /* Retrieve the base LBA number from the ccb structure. */
651 memcpy(&lba, pccb->cmd + 2, sizeof(lba));
652 lba = be32_to_cpu(lba);
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800653
Vadim Bendebury284231e2012-10-29 05:23:44 +0000654 /*
655 * And the number of blocks.
656 *
657 * For 10-byte and 16-byte SCSI R/W commands, transfer
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800658 * length 0 means transfer 0 block of data.
659 * However, for ATA R/W commands, sector count 0 means
660 * 256 or 65536 sectors, not 0 sectors as in SCSI.
661 *
662 * WARNING: one or two older ATA drives treat 0 as 0...
663 */
Vadim Bendebury284231e2012-10-29 05:23:44 +0000664 blocks = (((u16)pccb->cmd[7]) << 8) | ((u16) pccb->cmd[8]);
665
Hung-Te Linb7a21b72012-10-29 05:23:53 +0000666 debug("scsi_ahci: %s %d blocks starting from lba 0x%x\n",
667 is_write ? "write" : "read", (unsigned)lba, blocks);
Vadim Bendebury284231e2012-10-29 05:23:44 +0000668
669 /* Preset the FIS */
Taylor Huttc8731112012-10-29 05:23:55 +0000670 memset(fis, 0, sizeof(fis));
Vadim Bendebury284231e2012-10-29 05:23:44 +0000671 fis[0] = 0x27; /* Host to device FIS. */
672 fis[1] = 1 << 7; /* Command FIS. */
Hung-Te Linb7a21b72012-10-29 05:23:53 +0000673 /* Command byte (read/write). */
674 fis[2] = is_write ? ATA_CMD_WR_DMA : ATA_CMD_RD_DMA;
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800675
Vadim Bendebury284231e2012-10-29 05:23:44 +0000676 while (blocks) {
677 u16 now_blocks; /* number of blocks per iteration */
678 u32 transfer_size; /* number of bytes per iteration */
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800679
Hung-Te Linb7a21b72012-10-29 05:23:53 +0000680 now_blocks = min(MAX_SATA_BLOCKS_READ_WRITE, blocks);
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800681
Vadim Bendebury284231e2012-10-29 05:23:44 +0000682 transfer_size = ATA_BLOCKSIZE * now_blocks;
683 if (transfer_size > user_buffer_size) {
684 printf("scsi_ahci: Error: buffer too small.\n");
685 return -EIO;
686 }
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800687
Vadim Bendebury284231e2012-10-29 05:23:44 +0000688 /* LBA address, only support LBA28 in this driver */
689 fis[4] = (lba >> 0) & 0xff;
690 fis[5] = (lba >> 8) & 0xff;
691 fis[6] = (lba >> 16) & 0xff;
692 fis[7] = ((lba >> 24) & 0xf) | 0xe0;
693
694 /* Block (sector) count */
695 fis[12] = (now_blocks >> 0) & 0xff;
696 fis[13] = (now_blocks >> 8) & 0xff;
697
Hung-Te Linb7a21b72012-10-29 05:23:53 +0000698 /* Read/Write from ahci */
699 if (ahci_device_data_io(pccb->target, (u8 *) &fis, sizeof(fis),
700 user_buffer, user_buffer_size,
701 is_write)) {
702 debug("scsi_ahci: SCSI %s10 command failure.\n",
703 is_write ? "WRITE" : "READ");
Vadim Bendebury284231e2012-10-29 05:23:44 +0000704 return -EIO;
705 }
706 user_buffer += transfer_size;
707 user_buffer_size -= transfer_size;
708 blocks -= now_blocks;
709 lba += now_blocks;
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800710 }
711
712 return 0;
713}
714
715
716/*
717 * SCSI READ CAPACITY10 command operation.
718 */
719static int ata_scsiop_read_capacity10(ccb *pccb)
720{
Kumar Galacb6d0b72009-07-13 09:24:00 -0500721 u32 cap;
Gabe Black19d1d412012-10-29 05:23:54 +0000722 u32 block_size;
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800723
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500724 if (!ataid[pccb->target]) {
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800725 printf("scsi_ahci: SCSI READ CAPACITY10 command failure. "
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500726 "\tNo ATA info!\n"
727 "\tPlease run SCSI commmand INQUIRY firstly!\n");
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800728 return -EPERM;
729 }
730
Gabe Black19d1d412012-10-29 05:23:54 +0000731 cap = le32_to_cpu(ataid[pccb->target]->lba_capacity);
732 if (cap == 0xfffffff) {
733 unsigned short *cap48 = ataid[pccb->target]->lba48_capacity;
734 if (cap48[2] || cap48[3]) {
735 cap = 0xffffffff;
736 } else {
737 cap = (le16_to_cpu(cap48[1]) << 16) |
738 (le16_to_cpu(cap48[0]));
739 }
740 }
741
742 cap = cpu_to_be32(cap);
Kumar Galacb6d0b72009-07-13 09:24:00 -0500743 memcpy(pccb->pdata, &cap, sizeof(cap));
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800744
Gabe Black19d1d412012-10-29 05:23:54 +0000745 block_size = cpu_to_be32((u32)512);
746 memcpy(&pccb->pdata[4], &block_size, 4);
747
748 return 0;
749}
750
751
752/*
753 * SCSI READ CAPACITY16 command operation.
754 */
755static int ata_scsiop_read_capacity16(ccb *pccb)
756{
757 u64 cap;
758 u64 block_size;
759
760 if (!ataid[pccb->target]) {
761 printf("scsi_ahci: SCSI READ CAPACITY16 command failure. "
762 "\tNo ATA info!\n"
763 "\tPlease run SCSI commmand INQUIRY firstly!\n");
764 return -EPERM;
765 }
766
767 cap = le32_to_cpu(ataid[pccb->target]->lba_capacity);
768 if (cap == 0xfffffff) {
769 memcpy(&cap, ataid[pccb->target]->lba48_capacity, sizeof(cap));
770 cap = le64_to_cpu(cap);
771 }
772
773 cap = cpu_to_be64(cap);
774 memcpy(pccb->pdata, &cap, sizeof(cap));
775
776 block_size = cpu_to_be64((u64)512);
777 memcpy(&pccb->pdata[8], &block_size, 8);
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800778
779 return 0;
780}
781
782
783/*
784 * SCSI TEST UNIT READY command operation.
785 */
786static int ata_scsiop_test_unit_ready(ccb *pccb)
787{
788 return (ataid[pccb->target]) ? 0 : -EPERM;
789}
790
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500791
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800792int scsi_exec(ccb *pccb)
793{
794 int ret;
795
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500796 switch (pccb->cmd[0]) {
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800797 case SCSI_READ10:
Hung-Te Linb7a21b72012-10-29 05:23:53 +0000798 ret = ata_scsiop_read_write(pccb, 0);
799 break;
800 case SCSI_WRITE10:
801 ret = ata_scsiop_read_write(pccb, 1);
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800802 break;
Gabe Black19d1d412012-10-29 05:23:54 +0000803 case SCSI_RD_CAPAC10:
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800804 ret = ata_scsiop_read_capacity10(pccb);
805 break;
Gabe Black19d1d412012-10-29 05:23:54 +0000806 case SCSI_RD_CAPAC16:
807 ret = ata_scsiop_read_capacity16(pccb);
808 break;
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800809 case SCSI_TST_U_RDY:
810 ret = ata_scsiop_test_unit_ready(pccb);
811 break;
812 case SCSI_INQUIRY:
813 ret = ata_scsiop_inquiry(pccb);
814 break;
815 default:
816 printf("Unsupport SCSI command 0x%02x\n", pccb->cmd[0]);
817 return FALSE;
818 }
819
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500820 if (ret) {
821 debug("SCSI command 0x%02x ret errno %d\n", pccb->cmd[0], ret);
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800822 return FALSE;
823 }
824 return TRUE;
825
826}
827
828
829void scsi_low_level_init(int busdevfunc)
830{
831 int i;
832 u32 linkmap;
833
Rob Herring942e3142011-07-06 16:13:36 +0000834#ifndef CONFIG_SCSI_AHCI_PLAT
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800835 ahci_init_one(busdevfunc);
Rob Herring942e3142011-07-06 16:13:36 +0000836#endif
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800837
838 linkmap = probe_ent->link_port_map;
839
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200840 for (i = 0; i < CONFIG_SYS_SCSI_MAX_SCSI_ID; i++) {
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500841 if (((linkmap >> i) & 0x01)) {
842 if (ahci_port_start((u8) i)) {
843 printf("Can not start port %d\n", i);
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800844 continue;
845 }
Gabe Blacke81058c2012-10-29 05:23:52 +0000846#ifdef CONFIG_AHCI_SETFEATURES_XFER
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500847 ahci_set_feature((u8) i);
Gabe Blacke81058c2012-10-29 05:23:52 +0000848#endif
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800849 }
850 }
851}
852
Rob Herring942e3142011-07-06 16:13:36 +0000853#ifdef CONFIG_SCSI_AHCI_PLAT
854int ahci_init(u32 base)
855{
856 int i, rc = 0;
857 u32 linkmap;
858
859 memset(ataid, 0, sizeof(ataid));
860
861 probe_ent = malloc(sizeof(struct ahci_probe_ent));
862 memset(probe_ent, 0, sizeof(struct ahci_probe_ent));
863
864 probe_ent->host_flags = ATA_FLAG_SATA
865 | ATA_FLAG_NO_LEGACY
866 | ATA_FLAG_MMIO
867 | ATA_FLAG_PIO_DMA
868 | ATA_FLAG_NO_ATAPI;
869 probe_ent->pio_mask = 0x1f;
870 probe_ent->udma_mask = 0x7f; /*Fixme,assume to support UDMA6 */
871
872 probe_ent->mmio_base = base;
873
874 /* initialize adapter */
875 rc = ahci_host_init(probe_ent);
876 if (rc)
877 goto err_out;
878
879 ahci_print_info(probe_ent);
880
881 linkmap = probe_ent->link_port_map;
882
883 for (i = 0; i < CONFIG_SYS_SCSI_MAX_SCSI_ID; i++) {
884 if (((linkmap >> i) & 0x01)) {
885 if (ahci_port_start((u8) i)) {
886 printf("Can not start port %d\n", i);
887 continue;
888 }
Gabe Blacke81058c2012-10-29 05:23:52 +0000889#ifdef CONFIG_AHCI_SETFEATURES_XFER
Rob Herring942e3142011-07-06 16:13:36 +0000890 ahci_set_feature((u8) i);
Gabe Blacke81058c2012-10-29 05:23:52 +0000891#endif
Rob Herring942e3142011-07-06 16:13:36 +0000892 }
893 }
894err_out:
895 return rc;
896}
897#endif
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800898
899void scsi_bus_reset(void)
900{
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500901 /*Not implement*/
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800902}
903
904
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500905void scsi_print_error(ccb * pccb)
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800906{
Jon Loeliger4a7cc0f2006-08-23 11:04:43 -0500907 /*The ahci error info can be read in the ahci driver*/
Jin Zhengxiong4782ac82006-08-23 19:10:44 +0800908}