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