]>
Commit | Line | Data |
---|---|---|
fd0b1fe3 | 1 | /* |
f54fe87a | 2 | * Copyright (C) 2008,2010 Freescale Semiconductor, Inc. |
fd0b1fe3 DL |
3 | * Dave Liu <daveliu@freescale.com> |
4 | * | |
5 | * This program is free software; you can redistribute it and/or | |
6 | * modify it under the terms of the GNU General Public License as | |
7 | * published by the Free Software Foundation; either version 2 of | |
8 | * the License, or (at your option) any later version. | |
9 | * | |
10 | * This program is distributed in the hope that it will be useful, | |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 | * GNU General Public License for more details. | |
14 | * | |
15 | * You should have received a copy of the GNU General Public License | |
16 | * along with this program; if not, write to the Free Software | |
17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, | |
18 | * MA 02111-1307 USA | |
19 | */ | |
20 | ||
21 | #include <common.h> | |
22 | #include <command.h> | |
23 | #include <asm/io.h> | |
e4773deb | 24 | #include <asm/processor.h> |
f54fe87a | 25 | #include <asm/fsl_serdes.h> |
fd0b1fe3 DL |
26 | #include <malloc.h> |
27 | #include <libata.h> | |
28 | #include <fis.h> | |
29 | #include "fsl_sata.h" | |
30 | ||
6d0f6bcf | 31 | extern block_dev_desc_t sata_dev_desc[CONFIG_SYS_SATA_MAX_DEVICE]; |
fd0b1fe3 | 32 | |
6d0f6bcf JCPV |
33 | #ifndef CONFIG_SYS_SATA1_FLAGS |
34 | #define CONFIG_SYS_SATA1_FLAGS FLAGS_DMA | |
fd0b1fe3 | 35 | #endif |
6d0f6bcf JCPV |
36 | #ifndef CONFIG_SYS_SATA2_FLAGS |
37 | #define CONFIG_SYS_SATA2_FLAGS FLAGS_DMA | |
fd0b1fe3 DL |
38 | #endif |
39 | ||
40 | static struct fsl_sata_info fsl_sata_info[] = { | |
41 | #ifdef CONFIG_SATA1 | |
6d0f6bcf | 42 | {CONFIG_SYS_SATA1, CONFIG_SYS_SATA1_FLAGS}, |
fd0b1fe3 DL |
43 | #else |
44 | {0, 0}, | |
45 | #endif | |
46 | #ifdef CONFIG_SATA2 | |
6d0f6bcf | 47 | {CONFIG_SYS_SATA2, CONFIG_SYS_SATA2_FLAGS}, |
fd0b1fe3 DL |
48 | #else |
49 | {0, 0}, | |
50 | #endif | |
51 | }; | |
52 | ||
53 | static inline void mdelay(unsigned long msec) | |
54 | { | |
55 | unsigned long i; | |
56 | for (i = 0; i < msec; i++) | |
57 | udelay(1000); | |
58 | } | |
59 | ||
60 | static inline void sdelay(unsigned long sec) | |
61 | { | |
62 | unsigned long i; | |
63 | for (i = 0; i < sec; i++) | |
64 | mdelay(1000); | |
65 | } | |
66 | ||
67 | void dprint_buffer(unsigned char *buf, int len) | |
68 | { | |
69 | int i, j; | |
70 | ||
71 | i = 0; | |
72 | j = 0; | |
73 | printf("\n\r"); | |
74 | ||
75 | for (i = 0; i < len; i++) { | |
76 | printf("%02x ", *buf++); | |
77 | j++; | |
78 | if (j == 16) { | |
79 | printf("\n\r"); | |
80 | j = 0; | |
81 | } | |
82 | } | |
83 | printf("\n\r"); | |
84 | } | |
85 | ||
f14d8105 | 86 | static void fsl_sata_dump_sfis(struct sata_fis_d2h *s) |
fd0b1fe3 DL |
87 | { |
88 | printf("Status FIS dump:\n\r"); | |
89 | printf("fis_type: %02x\n\r", s->fis_type); | |
90 | printf("pm_port_i: %02x\n\r", s->pm_port_i); | |
91 | printf("status: %02x\n\r", s->status); | |
92 | printf("error: %02x\n\r", s->error); | |
93 | printf("lba_low: %02x\n\r", s->lba_low); | |
94 | printf("lba_mid: %02x\n\r", s->lba_mid); | |
95 | printf("lba_high: %02x\n\r", s->lba_high); | |
96 | printf("device: %02x\n\r", s->device); | |
97 | printf("lba_low_exp: %02x\n\r", s->lba_low_exp); | |
98 | printf("lba_mid_exp: %02x\n\r", s->lba_mid_exp); | |
99 | printf("lba_high_exp: %02x\n\r", s->lba_high_exp); | |
100 | printf("res1: %02x\n\r", s->res1); | |
101 | printf("sector_count: %02x\n\r", s->sector_count); | |
102 | printf("sector_count_exp: %02x\n\r", s->sector_count_exp); | |
103 | } | |
104 | ||
105 | static int ata_wait_register(volatile unsigned *addr, u32 mask, | |
106 | u32 val, u32 timeout_msec) | |
107 | { | |
108 | int i; | |
109 | u32 temp; | |
110 | ||
111 | for (i = 0; (((temp = in_le32(addr)) & mask) != val) | |
112 | && i < timeout_msec; i++) | |
113 | mdelay(1); | |
114 | return (i < timeout_msec) ? 0 : -1; | |
115 | } | |
116 | ||
117 | int init_sata(int dev) | |
118 | { | |
119 | u32 length, align; | |
120 | cmd_hdr_tbl_t *cmd_hdr; | |
121 | u32 cda; | |
122 | u32 val32; | |
123 | fsl_sata_reg_t *reg; | |
124 | u32 sig; | |
125 | int i; | |
126 | fsl_sata_t *sata; | |
127 | ||
6d0f6bcf | 128 | if (dev < 0 || dev > (CONFIG_SYS_SATA_MAX_DEVICE - 1)) { |
fd0b1fe3 DL |
129 | printf("the sata index %d is out of ranges\n\r", dev); |
130 | return -1; | |
131 | } | |
132 | ||
f54fe87a KG |
133 | #ifdef CONFIG_MPC85xx |
134 | if ((dev == 0) && (!is_serdes_configured(SATA1))) { | |
135 | printf("SATA%d [dev = %d] is not enabled\n", dev+1, dev); | |
136 | return -1; | |
137 | } | |
138 | if ((dev == 1) && (!is_serdes_configured(SATA2))) { | |
139 | printf("SATA%d [dev = %d] is not enabled\n", dev+1, dev); | |
140 | return -1; | |
141 | } | |
142 | #endif | |
143 | ||
fd0b1fe3 DL |
144 | /* Allocate SATA device driver struct */ |
145 | sata = (fsl_sata_t *)malloc(sizeof(fsl_sata_t)); | |
146 | if (!sata) { | |
147 | printf("alloc the sata device struct failed\n\r"); | |
148 | return -1; | |
149 | } | |
150 | /* Zero all of the device driver struct */ | |
151 | memset((void *)sata, 0, sizeof(fsl_sata_t)); | |
152 | ||
153 | /* Save the private struct to block device struct */ | |
154 | sata_dev_desc[dev].priv = (void *)sata; | |
155 | ||
156 | sprintf(sata->name, "SATA%d", dev); | |
157 | ||
158 | /* Set the controller register base address to device struct */ | |
159 | reg = (fsl_sata_reg_t *)(fsl_sata_info[dev].sata_reg_base); | |
160 | sata->reg_base = reg; | |
161 | ||
162 | /* Allocate the command header table, 4 bytes aligned */ | |
163 | length = sizeof(struct cmd_hdr_tbl); | |
164 | align = SATA_HC_CMD_HDR_TBL_ALIGN; | |
165 | sata->cmd_hdr_tbl_offset = (void *)malloc(length + align); | |
166 | if (!sata) { | |
167 | printf("alloc the command header failed\n\r"); | |
168 | return -1; | |
169 | } | |
170 | ||
171 | cmd_hdr = (cmd_hdr_tbl_t *)(((u32)sata->cmd_hdr_tbl_offset + align) | |
172 | & ~(align - 1)); | |
173 | sata->cmd_hdr = cmd_hdr; | |
174 | ||
175 | /* Zero all of the command header table */ | |
176 | memset((void *)sata->cmd_hdr_tbl_offset, 0, length + align); | |
177 | ||
178 | /* Allocate command descriptor for all command */ | |
179 | length = sizeof(struct cmd_desc) * SATA_HC_MAX_CMD; | |
180 | align = SATA_HC_CMD_DESC_ALIGN; | |
181 | sata->cmd_desc_offset = (void *)malloc(length + align); | |
182 | if (!sata->cmd_desc_offset) { | |
183 | printf("alloc the command descriptor failed\n\r"); | |
184 | return -1; | |
185 | } | |
186 | sata->cmd_desc = (cmd_desc_t *)(((u32)sata->cmd_desc_offset + align) | |
187 | & ~(align - 1)); | |
188 | /* Zero all of command descriptor */ | |
189 | memset((void *)sata->cmd_desc_offset, 0, length + align); | |
190 | ||
191 | /* Link the command descriptor to command header */ | |
192 | for (i = 0; i < SATA_HC_MAX_CMD; i++) { | |
193 | cda = ((u32)sata->cmd_desc + SATA_HC_CMD_DESC_SIZE * i) | |
194 | & ~(CMD_HDR_CDA_ALIGN - 1); | |
195 | cmd_hdr->cmd_slot[i].cda = cpu_to_le32(cda); | |
196 | } | |
197 | ||
198 | /* To have safe state, force the controller offline */ | |
199 | val32 = in_le32(®->hcontrol); | |
200 | val32 &= ~HCONTROL_ONOFF; | |
201 | val32 |= HCONTROL_FORCE_OFFLINE; | |
202 | out_le32(®->hcontrol, val32); | |
203 | ||
204 | /* Wait the controller offline */ | |
205 | ata_wait_register(®->hstatus, HSTATUS_ONOFF, 0, 1000); | |
206 | ||
e4773deb DL |
207 | #if defined(CONFIG_FSL_SATA_V2) && defined(CONFIG_FSL_SATA_ERRATUM_A001) |
208 | /* | |
209 | * For P1022/1013 Rev1.0 silicon, after power on SATA host | |
210 | * controller is configured in legacy mode instead of the | |
211 | * expected enterprise mode. software needs to clear bit[28] | |
212 | * of HControl register to change to enterprise mode from | |
213 | * legacy mode. | |
214 | */ | |
215 | { | |
216 | u32 svr = get_svr(); | |
217 | if (IS_SVR_REV(svr, 1, 0) && | |
218 | ((SVR_SOC_VER(svr) == SVR_P1022) || | |
219 | (SVR_SOC_VER(svr) == SVR_P1022_E) || | |
220 | (SVR_SOC_VER(svr) == SVR_P1013) || | |
221 | (SVR_SOC_VER(svr) == SVR_P1013_E))) { | |
222 | out_le32(®->hstatus, 0x20000000); | |
223 | out_le32(®->hcontrol, 0x00000100); | |
224 | } | |
225 | } | |
226 | #endif | |
227 | ||
fd0b1fe3 DL |
228 | /* Set the command header base address to CHBA register to tell DMA */ |
229 | out_le32(®->chba, (u32)cmd_hdr & ~0x3); | |
230 | ||
231 | /* Snoop for the command header */ | |
232 | val32 = in_le32(®->hcontrol); | |
233 | val32 |= HCONTROL_HDR_SNOOP; | |
234 | out_le32(®->hcontrol, val32); | |
235 | ||
236 | /* Disable all of interrupts */ | |
237 | val32 = in_le32(®->hcontrol); | |
238 | val32 &= ~HCONTROL_INT_EN_ALL; | |
239 | out_le32(®->hcontrol, val32); | |
240 | ||
241 | /* Clear all of interrupts */ | |
242 | val32 = in_le32(®->hstatus); | |
243 | out_le32(®->hstatus, val32); | |
244 | ||
245 | /* Set the ICC, no interrupt coalescing */ | |
246 | out_le32(®->icc, 0x01000000); | |
247 | ||
248 | /* No PM attatched, the SATA device direct connect */ | |
249 | out_le32(®->cqpmp, 0); | |
250 | ||
251 | /* Clear SError register */ | |
252 | val32 = in_le32(®->serror); | |
253 | out_le32(®->serror, val32); | |
254 | ||
255 | /* Clear CER register */ | |
256 | val32 = in_le32(®->cer); | |
257 | out_le32(®->cer, val32); | |
258 | ||
259 | /* Clear DER register */ | |
260 | val32 = in_le32(®->der); | |
261 | out_le32(®->der, val32); | |
262 | ||
263 | /* No device detection or initialization action requested */ | |
264 | out_le32(®->scontrol, 0x00000300); | |
265 | ||
266 | /* Configure the transport layer, default value */ | |
267 | out_le32(®->transcfg, 0x08000016); | |
268 | ||
269 | /* Configure the link layer, default value */ | |
270 | out_le32(®->linkcfg, 0x0000ff34); | |
271 | ||
272 | /* Bring the controller online */ | |
273 | val32 = in_le32(®->hcontrol); | |
274 | val32 |= HCONTROL_ONOFF; | |
275 | out_le32(®->hcontrol, val32); | |
276 | ||
277 | mdelay(100); | |
278 | ||
279 | /* print sata device name */ | |
280 | if (!dev) | |
281 | printf("%s ", sata->name); | |
282 | else | |
283 | printf(" %s ", sata->name); | |
284 | ||
9810263a DL |
285 | /* Wait PHY RDY signal changed for 500ms */ |
286 | ata_wait_register(®->hstatus, HSTATUS_PHY_RDY, | |
287 | HSTATUS_PHY_RDY, 500); | |
288 | ||
fd0b1fe3 DL |
289 | /* Check PHYRDY */ |
290 | val32 = in_le32(®->hstatus); | |
291 | if (val32 & HSTATUS_PHY_RDY) { | |
292 | sata->link = 1; | |
293 | } else { | |
294 | sata->link = 0; | |
295 | printf("(No RDY)\n\r"); | |
296 | return -1; | |
297 | } | |
298 | ||
9810263a DL |
299 | /* Wait for signature updated, which is 1st D2H */ |
300 | ata_wait_register(®->hstatus, HSTATUS_SIGNATURE, | |
301 | HSTATUS_SIGNATURE, 10000); | |
302 | ||
fd0b1fe3 DL |
303 | if (val32 & HSTATUS_SIGNATURE) { |
304 | sig = in_le32(®->sig); | |
305 | debug("Signature updated, the sig =%08x\n\r", sig); | |
306 | sata->ata_device_type = ata_dev_classify(sig); | |
307 | } | |
308 | ||
309 | /* Check the speed */ | |
310 | val32 = in_le32(®->sstatus); | |
311 | if ((val32 & SSTATUS_SPD_MASK) == SSTATUS_SPD_GEN1) | |
312 | printf("(1.5 Gbps)\n\r"); | |
313 | else if ((val32 & SSTATUS_SPD_MASK) == SSTATUS_SPD_GEN2) | |
314 | printf("(3 Gbps)\n\r"); | |
315 | ||
316 | return 0; | |
317 | } | |
318 | ||
319 | /* Hardware reset, like Power-on and COMRESET */ | |
320 | void fsl_sata_hardware_reset(u32 reg_base) | |
321 | { | |
322 | fsl_sata_reg_t *reg = (fsl_sata_reg_t *)reg_base; | |
323 | u32 scontrol; | |
324 | ||
325 | /* Disable the SATA interface and put PHY offline */ | |
326 | scontrol = in_le32(®->scontrol); | |
327 | scontrol = (scontrol & 0x0f0) | 0x304; | |
328 | out_le32(®->scontrol, scontrol); | |
329 | ||
330 | /* No speed strict */ | |
331 | scontrol = in_le32(®->scontrol); | |
332 | scontrol = scontrol & ~0x0f0; | |
333 | out_le32(®->scontrol, scontrol); | |
334 | ||
335 | /* Issue PHY wake/reset, Hardware_reset_asserted */ | |
336 | scontrol = in_le32(®->scontrol); | |
337 | scontrol = (scontrol & 0x0f0) | 0x301; | |
338 | out_le32(®->scontrol, scontrol); | |
339 | ||
340 | mdelay(100); | |
341 | ||
342 | /* Resume PHY, COMRESET negated, the device initialize hardware | |
343 | * and execute diagnostics, send good status-signature to host, | |
344 | * which is D2H register FIS, and then the device enter idle state. | |
345 | */ | |
346 | scontrol = in_le32(®->scontrol); | |
347 | scontrol = (scontrol & 0x0f0) | 0x300; | |
348 | out_le32(®->scontrol, scontrol); | |
349 | ||
350 | mdelay(100); | |
351 | return; | |
352 | } | |
353 | ||
354 | static void fsl_sata_dump_regs(fsl_sata_reg_t *reg) | |
355 | { | |
356 | printf("\n\rSATA: %08x\n\r", (u32)reg); | |
357 | printf("CQR: %08x\n\r", in_le32(®->cqr)); | |
358 | printf("CAR: %08x\n\r", in_le32(®->car)); | |
359 | printf("CCR: %08x\n\r", in_le32(®->ccr)); | |
360 | printf("CER: %08x\n\r", in_le32(®->cer)); | |
361 | printf("CQR: %08x\n\r", in_le32(®->cqr)); | |
362 | printf("DER: %08x\n\r", in_le32(®->der)); | |
363 | printf("CHBA: %08x\n\r", in_le32(®->chba)); | |
364 | printf("HStatus: %08x\n\r", in_le32(®->hstatus)); | |
365 | printf("HControl: %08x\n\r", in_le32(®->hcontrol)); | |
366 | printf("CQPMP: %08x\n\r", in_le32(®->cqpmp)); | |
367 | printf("SIG: %08x\n\r", in_le32(®->sig)); | |
368 | printf("ICC: %08x\n\r", in_le32(®->icc)); | |
369 | printf("SStatus: %08x\n\r", in_le32(®->sstatus)); | |
370 | printf("SError: %08x\n\r", in_le32(®->serror)); | |
371 | printf("SControl: %08x\n\r", in_le32(®->scontrol)); | |
372 | printf("SNotification: %08x\n\r", in_le32(®->snotification)); | |
373 | printf("TransCfg: %08x\n\r", in_le32(®->transcfg)); | |
374 | printf("TransStatus: %08x\n\r", in_le32(®->transstatus)); | |
375 | printf("LinkCfg: %08x\n\r", in_le32(®->linkcfg)); | |
376 | printf("LinkCfg1: %08x\n\r", in_le32(®->linkcfg1)); | |
377 | printf("LinkCfg2: %08x\n\r", in_le32(®->linkcfg2)); | |
378 | printf("LinkStatus: %08x\n\r", in_le32(®->linkstatus)); | |
379 | printf("LinkStatus1: %08x\n\r", in_le32(®->linkstatus1)); | |
380 | printf("PhyCtrlCfg: %08x\n\r", in_le32(®->phyctrlcfg)); | |
381 | printf("SYSPR: %08x\n\r", in_be32(®->syspr)); | |
382 | } | |
383 | ||
f14d8105 | 384 | static int fsl_ata_exec_ata_cmd(struct fsl_sata *sata, struct sata_fis_h2d *cfis, |
fd0b1fe3 DL |
385 | int is_ncq, int tag, u8 *buffer, u32 len) |
386 | { | |
387 | cmd_hdr_entry_t *cmd_hdr; | |
388 | cmd_desc_t *cmd_desc; | |
389 | sata_fis_h2d_t *h2d; | |
390 | prd_entry_t *prde; | |
391 | u32 ext_c_ddc; | |
392 | u32 prde_count; | |
393 | u32 val32; | |
394 | u32 ttl; | |
395 | fsl_sata_reg_t *reg = sata->reg_base; | |
396 | int i; | |
397 | ||
398 | /* Check xfer length */ | |
399 | if (len > SATA_HC_MAX_XFER_LEN) { | |
400 | printf("max transfer length is 64MB\n\r"); | |
401 | return 0; | |
402 | } | |
403 | ||
404 | /* Setup the command descriptor */ | |
405 | cmd_desc = sata->cmd_desc + tag; | |
406 | ||
407 | /* Get the pointer cfis of command descriptor */ | |
408 | h2d = (sata_fis_h2d_t *)cmd_desc->cfis; | |
409 | ||
410 | /* Zero the cfis of command descriptor */ | |
411 | memset((void *)h2d, 0, SATA_HC_CMD_DESC_CFIS_SIZE); | |
412 | ||
413 | /* Copy the cfis from user to command descriptor */ | |
414 | h2d->fis_type = cfis->fis_type; | |
415 | h2d->pm_port_c = cfis->pm_port_c; | |
416 | h2d->command = cfis->command; | |
417 | ||
418 | h2d->features = cfis->features; | |
419 | h2d->features_exp = cfis->features_exp; | |
420 | ||
421 | h2d->lba_low = cfis->lba_low; | |
422 | h2d->lba_mid = cfis->lba_mid; | |
423 | h2d->lba_high = cfis->lba_high; | |
424 | h2d->lba_low_exp = cfis->lba_low_exp; | |
425 | h2d->lba_mid_exp = cfis->lba_mid_exp; | |
426 | h2d->lba_high_exp = cfis->lba_high_exp; | |
427 | ||
428 | if (!is_ncq) { | |
429 | h2d->sector_count = cfis->sector_count; | |
430 | h2d->sector_count_exp = cfis->sector_count_exp; | |
431 | } else { /* NCQ */ | |
432 | h2d->sector_count = (u8)(tag << 3); | |
433 | } | |
434 | ||
435 | h2d->device = cfis->device; | |
436 | h2d->control = cfis->control; | |
437 | ||
438 | /* Setup the PRD table */ | |
439 | prde = (prd_entry_t *)cmd_desc->prdt; | |
440 | memset((void *)prde, 0, sizeof(struct prdt)); | |
441 | ||
442 | prde_count = 0; | |
443 | ttl = len; | |
444 | for (i = 0; i < SATA_HC_MAX_PRD_DIRECT; i++) { | |
445 | if (!len) | |
446 | break; | |
447 | prde->dba = cpu_to_le32((u32)buffer & ~0x3); | |
448 | debug("dba = %08x\n\r", (u32)buffer); | |
449 | ||
450 | if (len < PRD_ENTRY_MAX_XFER_SZ) { | |
451 | ext_c_ddc = PRD_ENTRY_DATA_SNOOP | len; | |
452 | debug("ext_c_ddc1 = %08x, len = %08x\n\r", ext_c_ddc, len); | |
453 | prde->ext_c_ddc = cpu_to_le32(ext_c_ddc); | |
454 | prde_count++; | |
455 | prde++; | |
456 | break; | |
457 | } else { | |
458 | ext_c_ddc = PRD_ENTRY_DATA_SNOOP; /* 4M bytes */ | |
459 | debug("ext_c_ddc2 = %08x, len = %08x\n\r", ext_c_ddc, len); | |
460 | prde->ext_c_ddc = cpu_to_le32(ext_c_ddc); | |
461 | buffer += PRD_ENTRY_MAX_XFER_SZ; | |
462 | len -= PRD_ENTRY_MAX_XFER_SZ; | |
463 | prde_count++; | |
464 | prde++; | |
465 | } | |
466 | } | |
467 | ||
468 | /* Setup the command slot of cmd hdr */ | |
469 | cmd_hdr = (cmd_hdr_entry_t *)&sata->cmd_hdr->cmd_slot[tag]; | |
470 | ||
471 | cmd_hdr->cda = cpu_to_le32((u32)cmd_desc & ~0x3); | |
472 | ||
473 | val32 = prde_count << CMD_HDR_PRD_ENTRY_SHIFT; | |
474 | val32 |= sizeof(sata_fis_h2d_t); | |
475 | cmd_hdr->prde_fis_len = cpu_to_le32(val32); | |
476 | ||
477 | cmd_hdr->ttl = cpu_to_le32(ttl); | |
478 | ||
479 | if (!is_ncq) { | |
480 | val32 = CMD_HDR_ATTR_RES | CMD_HDR_ATTR_SNOOP; | |
481 | } else { | |
482 | val32 = CMD_HDR_ATTR_RES | CMD_HDR_ATTR_SNOOP | CMD_HDR_ATTR_FPDMA; | |
483 | } | |
484 | ||
485 | tag &= CMD_HDR_ATTR_TAG; | |
486 | val32 |= tag; | |
487 | ||
488 | debug("attribute = %08x\n\r", val32); | |
489 | cmd_hdr->attribute = cpu_to_le32(val32); | |
490 | ||
491 | /* Make sure cmd desc and cmd slot valid before commmand issue */ | |
492 | sync(); | |
493 | ||
494 | /* PMP*/ | |
495 | val32 = (u32)(h2d->pm_port_c & 0x0f); | |
496 | out_le32(®->cqpmp, val32); | |
497 | ||
498 | /* Wait no active */ | |
499 | if (ata_wait_register(®->car, (1 << tag), 0, 10000)) | |
500 | printf("Wait no active time out\n\r"); | |
501 | ||
502 | /* Issue command */ | |
503 | if (!(in_le32(®->cqr) & (1 << tag))) { | |
504 | val32 = 1 << tag; | |
505 | out_le32(®->cqr, val32); | |
506 | } | |
507 | ||
508 | /* Wait command completed for 10s */ | |
509 | if (ata_wait_register(®->ccr, (1 << tag), (1 << tag), 10000)) { | |
510 | if (!is_ncq) | |
511 | printf("Non-NCQ command time out\n\r"); | |
512 | else | |
513 | printf("NCQ command time out\n\r"); | |
514 | } | |
515 | ||
516 | val32 = in_le32(®->cer); | |
517 | ||
518 | if (val32) { | |
519 | u32 der; | |
f14d8105 | 520 | fsl_sata_dump_sfis((struct sata_fis_d2h *)cmd_desc->sfis); |
fd0b1fe3 DL |
521 | printf("CE at device\n\r"); |
522 | fsl_sata_dump_regs(reg); | |
523 | der = in_le32(®->der); | |
524 | out_le32(®->cer, val32); | |
525 | out_le32(®->der, der); | |
526 | } | |
527 | ||
528 | /* Clear complete flags */ | |
529 | val32 = in_le32(®->ccr); | |
530 | out_le32(®->ccr, val32); | |
531 | ||
532 | return len; | |
533 | } | |
534 | ||
f14d8105 | 535 | static int fsl_ata_exec_reset_cmd(struct fsl_sata *sata, struct sata_fis_h2d *cfis, |
fd0b1fe3 DL |
536 | int tag, u8 *buffer, u32 len) |
537 | { | |
538 | return 0; | |
539 | } | |
540 | ||
f14d8105 | 541 | static int fsl_sata_exec_cmd(struct fsl_sata *sata, struct sata_fis_h2d *cfis, |
fd0b1fe3 DL |
542 | enum cmd_type command_type, int tag, u8 *buffer, u32 len) |
543 | { | |
544 | int rc; | |
545 | ||
546 | if (tag > SATA_HC_MAX_CMD || tag < 0) { | |
4109df6f | 547 | printf("tag is out of range, tag=%d\n\r", tag); |
fd0b1fe3 DL |
548 | return -1; |
549 | } | |
550 | ||
551 | switch (command_type) { | |
552 | case CMD_ATA: | |
553 | rc = fsl_ata_exec_ata_cmd(sata, cfis, 0, tag, buffer, len); | |
554 | return rc; | |
555 | case CMD_RESET: | |
556 | rc = fsl_ata_exec_reset_cmd(sata, cfis, tag, buffer, len); | |
557 | return rc; | |
558 | case CMD_NCQ: | |
559 | rc = fsl_ata_exec_ata_cmd(sata, cfis, 1, tag, buffer, len); | |
560 | return rc; | |
561 | case CMD_ATAPI: | |
562 | case CMD_VENDOR_BIST: | |
563 | case CMD_BIST: | |
564 | printf("not support now\n\r"); | |
565 | return -1; | |
566 | default: | |
567 | break; | |
568 | } | |
569 | ||
570 | return -1; | |
571 | } | |
572 | ||
573 | static void fsl_sata_identify(int dev, u16 *id) | |
574 | { | |
575 | fsl_sata_t *sata = (fsl_sata_t *)sata_dev_desc[dev].priv; | |
f14d8105 | 576 | struct sata_fis_h2d h2d, *cfis = &h2d; |
fd0b1fe3 | 577 | |
f14d8105 | 578 | memset(cfis, 0, sizeof(struct sata_fis_h2d)); |
fd0b1fe3 DL |
579 | |
580 | cfis->fis_type = SATA_FIS_TYPE_REGISTER_H2D; | |
581 | cfis->pm_port_c = 0x80; /* is command */ | |
582 | cfis->command = ATA_CMD_ID_ATA; | |
583 | ||
584 | fsl_sata_exec_cmd(sata, cfis, CMD_ATA, 0, (u8 *)id, ATA_ID_WORDS * 2); | |
585 | ata_swap_buf_le16(id, ATA_ID_WORDS); | |
586 | } | |
587 | ||
588 | static void fsl_sata_xfer_mode(int dev, u16 *id) | |
589 | { | |
590 | fsl_sata_t *sata = (fsl_sata_t *)sata_dev_desc[dev].priv; | |
591 | ||
592 | sata->pio = id[ATA_ID_PIO_MODES]; | |
593 | sata->mwdma = id[ATA_ID_MWDMA_MODES]; | |
594 | sata->udma = id[ATA_ID_UDMA_MODES]; | |
595 | debug("pio %04x, mwdma %04x, udma %04x\n\r", sata->pio, sata->mwdma, sata->udma); | |
596 | } | |
597 | ||
598 | static void fsl_sata_set_features(int dev) | |
599 | { | |
600 | fsl_sata_t *sata = (fsl_sata_t *)sata_dev_desc[dev].priv; | |
f14d8105 | 601 | struct sata_fis_h2d h2d, *cfis = &h2d; |
fd0b1fe3 DL |
602 | u8 udma_cap; |
603 | ||
f14d8105 | 604 | memset(cfis, 0, sizeof(struct sata_fis_h2d)); |
fd0b1fe3 DL |
605 | |
606 | cfis->fis_type = SATA_FIS_TYPE_REGISTER_H2D; | |
607 | cfis->pm_port_c = 0x80; /* is command */ | |
608 | cfis->command = ATA_CMD_SET_FEATURES; | |
609 | cfis->features = SETFEATURES_XFER; | |
610 | ||
611 | /* First check the device capablity */ | |
612 | udma_cap = (u8)(sata->udma & 0xff); | |
613 | debug("udma_cap %02x\n\r", udma_cap); | |
614 | ||
615 | if (udma_cap == ATA_UDMA6) | |
616 | cfis->sector_count = XFER_UDMA_6; | |
617 | if (udma_cap == ATA_UDMA5) | |
618 | cfis->sector_count = XFER_UDMA_5; | |
619 | if (udma_cap == ATA_UDMA4) | |
620 | cfis->sector_count = XFER_UDMA_4; | |
621 | if (udma_cap == ATA_UDMA3) | |
622 | cfis->sector_count = XFER_UDMA_3; | |
623 | ||
624 | fsl_sata_exec_cmd(sata, cfis, CMD_ATA, 0, NULL, 0); | |
625 | } | |
626 | ||
627 | static u32 fsl_sata_rw_cmd(int dev, u32 start, u32 blkcnt, u8 *buffer, int is_write) | |
628 | { | |
629 | fsl_sata_t *sata = (fsl_sata_t *)sata_dev_desc[dev].priv; | |
f14d8105 | 630 | struct sata_fis_h2d h2d, *cfis = &h2d; |
fd0b1fe3 DL |
631 | u32 block; |
632 | ||
633 | block = start; | |
fd0b1fe3 | 634 | |
f14d8105 | 635 | memset(cfis, 0, sizeof(struct sata_fis_h2d)); |
fd0b1fe3 DL |
636 | |
637 | cfis->fis_type = SATA_FIS_TYPE_REGISTER_H2D; | |
638 | cfis->pm_port_c = 0x80; /* is command */ | |
24b44844 | 639 | cfis->command = (is_write) ? ATA_CMD_WRITE : ATA_CMD_READ; |
fd0b1fe3 DL |
640 | cfis->device = ATA_LBA; |
641 | ||
642 | cfis->device |= (block >> 24) & 0xf; | |
643 | cfis->lba_high = (block >> 16) & 0xff; | |
644 | cfis->lba_mid = (block >> 8) & 0xff; | |
645 | cfis->lba_low = block & 0xff; | |
646 | cfis->sector_count = (u8)(blkcnt & 0xff); | |
647 | ||
648 | fsl_sata_exec_cmd(sata, cfis, CMD_ATA, 0, buffer, ATA_SECT_SIZE * blkcnt); | |
649 | return blkcnt; | |
650 | } | |
651 | ||
652 | void fsl_sata_flush_cache(int dev) | |
653 | { | |
654 | fsl_sata_t *sata = (fsl_sata_t *)sata_dev_desc[dev].priv; | |
f14d8105 | 655 | struct sata_fis_h2d h2d, *cfis = &h2d; |
fd0b1fe3 | 656 | |
f14d8105 | 657 | memset(cfis, 0, sizeof(struct sata_fis_h2d)); |
fd0b1fe3 DL |
658 | |
659 | cfis->fis_type = SATA_FIS_TYPE_REGISTER_H2D; | |
660 | cfis->pm_port_c = 0x80; /* is command */ | |
24b44844 | 661 | cfis->command = ATA_CMD_FLUSH; |
fd0b1fe3 DL |
662 | |
663 | fsl_sata_exec_cmd(sata, cfis, CMD_ATA, 0, NULL, 0); | |
664 | } | |
665 | ||
666 | static u32 fsl_sata_rw_cmd_ext(int dev, u32 start, u32 blkcnt, u8 *buffer, int is_write) | |
667 | { | |
668 | fsl_sata_t *sata = (fsl_sata_t *)sata_dev_desc[dev].priv; | |
f14d8105 | 669 | struct sata_fis_h2d h2d, *cfis = &h2d; |
fd0b1fe3 DL |
670 | u64 block; |
671 | ||
672 | block = (u64)start; | |
fd0b1fe3 | 673 | |
f14d8105 | 674 | memset(cfis, 0, sizeof(struct sata_fis_h2d)); |
fd0b1fe3 DL |
675 | |
676 | cfis->fis_type = SATA_FIS_TYPE_REGISTER_H2D; | |
677 | cfis->pm_port_c = 0x80; /* is command */ | |
678 | ||
24b44844 DL |
679 | cfis->command = (is_write) ? ATA_CMD_WRITE_EXT |
680 | : ATA_CMD_READ_EXT; | |
fd0b1fe3 DL |
681 | |
682 | cfis->lba_high_exp = (block >> 40) & 0xff; | |
683 | cfis->lba_mid_exp = (block >> 32) & 0xff; | |
684 | cfis->lba_low_exp = (block >> 24) & 0xff; | |
685 | cfis->lba_high = (block >> 16) & 0xff; | |
686 | cfis->lba_mid = (block >> 8) & 0xff; | |
687 | cfis->lba_low = block & 0xff; | |
688 | cfis->device = ATA_LBA; | |
689 | cfis->sector_count_exp = (blkcnt >> 8) & 0xff; | |
690 | cfis->sector_count = blkcnt & 0xff; | |
691 | ||
692 | fsl_sata_exec_cmd(sata, cfis, CMD_ATA, 0, buffer, ATA_SECT_SIZE * blkcnt); | |
693 | return blkcnt; | |
694 | } | |
695 | ||
696 | u32 fsl_sata_rw_ncq_cmd(int dev, u32 start, u32 blkcnt, u8 *buffer, int is_write) | |
697 | { | |
698 | fsl_sata_t *sata = (fsl_sata_t *)sata_dev_desc[dev].priv; | |
f14d8105 | 699 | struct sata_fis_h2d h2d, *cfis = &h2d; |
fd0b1fe3 DL |
700 | int ncq_channel; |
701 | u64 block; | |
702 | ||
703 | if (sata_dev_desc[dev].lba48 != 1) { | |
704 | printf("execute FPDMA command on non-LBA48 hard disk\n\r"); | |
705 | return -1; | |
706 | } | |
707 | ||
708 | block = (u64)start; | |
fd0b1fe3 | 709 | |
f14d8105 | 710 | memset(cfis, 0, sizeof(struct sata_fis_h2d)); |
fd0b1fe3 DL |
711 | |
712 | cfis->fis_type = SATA_FIS_TYPE_REGISTER_H2D; | |
713 | cfis->pm_port_c = 0x80; /* is command */ | |
714 | ||
24b44844 DL |
715 | cfis->command = (is_write) ? ATA_CMD_FPDMA_WRITE |
716 | : ATA_CMD_FPDMA_READ; | |
fd0b1fe3 DL |
717 | |
718 | cfis->lba_high_exp = (block >> 40) & 0xff; | |
719 | cfis->lba_mid_exp = (block >> 32) & 0xff; | |
720 | cfis->lba_low_exp = (block >> 24) & 0xff; | |
721 | cfis->lba_high = (block >> 16) & 0xff; | |
722 | cfis->lba_mid = (block >> 8) & 0xff; | |
723 | cfis->lba_low = block & 0xff; | |
724 | ||
725 | cfis->device = ATA_LBA; | |
726 | cfis->features_exp = (blkcnt >> 8) & 0xff; | |
727 | cfis->features = blkcnt & 0xff; | |
728 | ||
729 | if (sata->queue_depth >= SATA_HC_MAX_CMD) | |
730 | ncq_channel = SATA_HC_MAX_CMD - 1; | |
731 | else | |
732 | ncq_channel = sata->queue_depth - 1; | |
733 | ||
734 | /* Use the latest queue */ | |
735 | fsl_sata_exec_cmd(sata, cfis, CMD_NCQ, ncq_channel, buffer, ATA_SECT_SIZE * blkcnt); | |
736 | return blkcnt; | |
737 | } | |
738 | ||
739 | void fsl_sata_flush_cache_ext(int dev) | |
740 | { | |
741 | fsl_sata_t *sata = (fsl_sata_t *)sata_dev_desc[dev].priv; | |
f14d8105 | 742 | struct sata_fis_h2d h2d, *cfis = &h2d; |
fd0b1fe3 | 743 | |
f14d8105 | 744 | memset(cfis, 0, sizeof(struct sata_fis_h2d)); |
fd0b1fe3 DL |
745 | |
746 | cfis->fis_type = SATA_FIS_TYPE_REGISTER_H2D; | |
747 | cfis->pm_port_c = 0x80; /* is command */ | |
24b44844 | 748 | cfis->command = ATA_CMD_FLUSH_EXT; |
fd0b1fe3 DL |
749 | |
750 | fsl_sata_exec_cmd(sata, cfis, CMD_ATA, 0, NULL, 0); | |
751 | } | |
752 | ||
753 | /* Software reset, set SRST of the Device Control register */ | |
754 | void fsl_sata_software_reset(int dev) | |
755 | { | |
756 | return; | |
757 | } | |
758 | ||
759 | static void fsl_sata_init_wcache(int dev, u16 *id) | |
760 | { | |
761 | fsl_sata_t *sata = (fsl_sata_t *)sata_dev_desc[dev].priv; | |
762 | ||
763 | if (ata_id_has_wcache(id) && ata_id_wcache_enabled(id)) | |
764 | sata->wcache = 1; | |
765 | if (ata_id_has_flush(id)) | |
766 | sata->flush = 1; | |
767 | if (ata_id_has_flush_ext(id)) | |
768 | sata->flush_ext = 1; | |
769 | } | |
770 | ||
771 | static int fsl_sata_get_wcache(int dev) | |
772 | { | |
773 | fsl_sata_t *sata = (fsl_sata_t *)sata_dev_desc[dev].priv; | |
774 | return sata->wcache; | |
775 | } | |
776 | ||
777 | static int fsl_sata_get_flush(int dev) | |
778 | { | |
779 | fsl_sata_t *sata = (fsl_sata_t *)sata_dev_desc[dev].priv; | |
780 | return sata->flush; | |
781 | } | |
782 | ||
783 | static int fsl_sata_get_flush_ext(int dev) | |
784 | { | |
785 | fsl_sata_t *sata = (fsl_sata_t *)sata_dev_desc[dev].priv; | |
786 | return sata->flush_ext; | |
787 | } | |
788 | ||
789 | u32 ata_low_level_rw_lba48(int dev, u32 blknr, u32 blkcnt, void *buffer, int is_write) | |
790 | { | |
791 | u32 start, blks; | |
792 | u8 *addr; | |
793 | int max_blks; | |
794 | ||
795 | start = blknr; | |
796 | blks = blkcnt; | |
797 | addr = (u8 *)buffer; | |
798 | ||
799 | max_blks = ATA_MAX_SECTORS_LBA48; | |
800 | do { | |
801 | if (blks > max_blks) { | |
802 | if (fsl_sata_info[dev].flags != FLAGS_FPDMA) | |
803 | fsl_sata_rw_cmd_ext(dev, start, max_blks, addr, is_write); | |
804 | else | |
805 | fsl_sata_rw_ncq_cmd(dev, start, max_blks, addr, is_write); | |
806 | start += max_blks; | |
807 | blks -= max_blks; | |
808 | addr += ATA_SECT_SIZE * max_blks; | |
809 | } else { | |
810 | if (fsl_sata_info[dev].flags != FLAGS_FPDMA) | |
811 | fsl_sata_rw_cmd_ext(dev, start, blks, addr, is_write); | |
812 | else | |
813 | fsl_sata_rw_ncq_cmd(dev, start, blks, addr, is_write); | |
814 | start += blks; | |
815 | blks = 0; | |
816 | addr += ATA_SECT_SIZE * blks; | |
817 | } | |
818 | } while (blks != 0); | |
819 | ||
820 | return blkcnt; | |
821 | } | |
822 | ||
823 | u32 ata_low_level_rw_lba28(int dev, u32 blknr, u32 blkcnt, void *buffer, int is_write) | |
824 | { | |
825 | u32 start, blks; | |
826 | u8 *addr; | |
827 | int max_blks; | |
828 | ||
829 | start = blknr; | |
830 | blks = blkcnt; | |
831 | addr = (u8 *)buffer; | |
832 | ||
833 | max_blks = ATA_MAX_SECTORS; | |
834 | do { | |
835 | if (blks > max_blks) { | |
836 | fsl_sata_rw_cmd(dev, start, max_blks, addr, is_write); | |
837 | start += max_blks; | |
838 | blks -= max_blks; | |
839 | addr += ATA_SECT_SIZE * max_blks; | |
840 | } else { | |
841 | fsl_sata_rw_cmd(dev, start, blks, addr, is_write); | |
842 | start += blks; | |
843 | blks = 0; | |
844 | addr += ATA_SECT_SIZE * blks; | |
845 | } | |
846 | } while (blks != 0); | |
847 | ||
848 | return blkcnt; | |
849 | } | |
850 | ||
851 | /* | |
852 | * SATA interface between low level driver and command layer | |
853 | */ | |
854 | ulong sata_read(int dev, u32 blknr, u32 blkcnt, void *buffer) | |
855 | { | |
856 | u32 rc; | |
857 | ||
858 | if (sata_dev_desc[dev].lba48) | |
859 | rc = ata_low_level_rw_lba48(dev, blknr, blkcnt, buffer, READ_CMD); | |
860 | else | |
861 | rc = ata_low_level_rw_lba28(dev, blknr, blkcnt, buffer, READ_CMD); | |
862 | return rc; | |
863 | } | |
864 | ||
865 | ulong sata_write(int dev, u32 blknr, u32 blkcnt, void *buffer) | |
866 | { | |
867 | u32 rc; | |
868 | ||
869 | if (sata_dev_desc[dev].lba48) { | |
870 | rc = ata_low_level_rw_lba48(dev, blknr, blkcnt, buffer, WRITE_CMD); | |
871 | if (fsl_sata_get_wcache(dev) && fsl_sata_get_flush_ext(dev)) | |
872 | fsl_sata_flush_cache_ext(dev); | |
873 | } else { | |
874 | rc = ata_low_level_rw_lba28(dev, blknr, blkcnt, buffer, WRITE_CMD); | |
875 | if (fsl_sata_get_wcache(dev) && fsl_sata_get_flush(dev)) | |
876 | fsl_sata_flush_cache(dev); | |
877 | } | |
878 | return rc; | |
879 | } | |
880 | ||
881 | int scan_sata(int dev) | |
882 | { | |
883 | fsl_sata_t *sata = (fsl_sata_t *)sata_dev_desc[dev].priv; | |
884 | unsigned char serial[ATA_ID_SERNO_LEN + 1]; | |
885 | unsigned char firmware[ATA_ID_FW_REV_LEN + 1]; | |
886 | unsigned char product[ATA_ID_PROD_LEN + 1]; | |
887 | u16 *id; | |
888 | u64 n_sectors; | |
889 | ||
890 | /* if no detected link */ | |
891 | if (!sata->link) | |
892 | return -1; | |
893 | ||
894 | id = (u16 *)malloc(ATA_ID_WORDS * 2); | |
895 | if (!id) { | |
896 | printf("id malloc failed\n\r"); | |
897 | return -1; | |
898 | } | |
899 | ||
900 | /* Identify device to get information */ | |
901 | fsl_sata_identify(dev, id); | |
902 | ||
903 | /* Serial number */ | |
904 | ata_id_c_string(id, serial, ATA_ID_SERNO, sizeof(serial)); | |
905 | memcpy(sata_dev_desc[dev].product, serial, sizeof(serial)); | |
906 | ||
907 | /* Firmware version */ | |
908 | ata_id_c_string(id, firmware, ATA_ID_FW_REV, sizeof(firmware)); | |
909 | memcpy(sata_dev_desc[dev].revision, firmware, sizeof(firmware)); | |
910 | ||
911 | /* Product model */ | |
912 | ata_id_c_string(id, product, ATA_ID_PROD, sizeof(product)); | |
913 | memcpy(sata_dev_desc[dev].vendor, product, sizeof(product)); | |
914 | ||
915 | /* Totoal sectors */ | |
916 | n_sectors = ata_id_n_sectors(id); | |
917 | sata_dev_desc[dev].lba = (u32)n_sectors; | |
918 | ||
919 | /* Check if support LBA48 */ | |
920 | if (ata_id_has_lba48(id)) { | |
921 | sata_dev_desc[dev].lba48 = 1; | |
922 | debug("Device support LBA48\n\r"); | |
923 | } | |
924 | ||
925 | /* Get the NCQ queue depth from device */ | |
926 | sata->queue_depth = ata_id_queue_depth(id); | |
927 | ||
928 | /* Get the xfer mode from device */ | |
929 | fsl_sata_xfer_mode(dev, id); | |
930 | ||
931 | /* Get the write cache status from device */ | |
932 | fsl_sata_init_wcache(dev, id); | |
933 | ||
934 | /* Set the xfer mode to highest speed */ | |
935 | fsl_sata_set_features(dev); | |
936 | #ifdef DEBUG | |
937 | fsl_sata_identify(dev, id); | |
938 | ata_dump_id(id); | |
939 | #endif | |
940 | free((void *)id); | |
941 | return 0; | |
942 | } |