blob: 3261c10f91dea5bee4faaca36bacf6e435ffe91e [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Dave Liu6f1a8a22008-03-26 22:55:32 +08002/*
Kumar Galaeb453df2010-04-20 10:21:25 -05003 * Copyright (C) 2008,2010 Freescale Semiconductor, Inc.
Peng Ma64a6ec32019-11-19 06:17:36 +00004 * Copyright 2019 NXP
5 * Author: Dave Liu <daveliu@freescale.com>
Dave Liu6f1a8a22008-03-26 22:55:32 +08006 */
7
8#include <common.h>
9#include <command.h>
Simon Glassa73bda42015-11-08 23:47:45 -070010#include <console.h>
Dave Liu6f1a8a22008-03-26 22:55:32 +080011#include <asm/io.h>
Dave Liub9674d02010-04-12 14:23:25 +080012#include <asm/processor.h>
Kumar Galaeb453df2010-04-20 10:21:25 -050013#include <asm/fsl_serdes.h>
Dave Liu6f1a8a22008-03-26 22:55:32 +080014#include <malloc.h>
15#include <libata.h>
16#include <fis.h>
Pavel Herrmann9e9f6282012-09-27 23:18:04 +000017#include <sata.h>
Dave Liu6f1a8a22008-03-26 22:55:32 +080018#include "fsl_sata.h"
19
Peng Ma64a6ec32019-11-19 06:17:36 +000020#if CONFIG_IS_ENABLED(BLK)
21#include <dm.h>
22#include <ahci.h>
23#include <blk.h>
24#else
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +020025#ifndef CONFIG_SYS_SATA1_FLAGS
26 #define CONFIG_SYS_SATA1_FLAGS FLAGS_DMA
Dave Liu6f1a8a22008-03-26 22:55:32 +080027#endif
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +020028#ifndef CONFIG_SYS_SATA2_FLAGS
29 #define CONFIG_SYS_SATA2_FLAGS FLAGS_DMA
Dave Liu6f1a8a22008-03-26 22:55:32 +080030#endif
31
32static struct fsl_sata_info fsl_sata_info[] = {
33#ifdef CONFIG_SATA1
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +020034 {CONFIG_SYS_SATA1, CONFIG_SYS_SATA1_FLAGS},
Dave Liu6f1a8a22008-03-26 22:55:32 +080035#else
36 {0, 0},
37#endif
38#ifdef CONFIG_SATA2
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +020039 {CONFIG_SYS_SATA2, CONFIG_SYS_SATA2_FLAGS},
Dave Liu6f1a8a22008-03-26 22:55:32 +080040#else
41 {0, 0},
42#endif
43};
Peng Ma64a6ec32019-11-19 06:17:36 +000044#endif
Dave Liu6f1a8a22008-03-26 22:55:32 +080045
Dave Liu6f1a8a22008-03-26 22:55:32 +080046static inline void sdelay(unsigned long sec)
47{
48 unsigned long i;
49 for (i = 0; i < sec; i++)
50 mdelay(1000);
51}
52
galak18cf84a2009-07-07 15:53:21 -050053static void fsl_sata_dump_sfis(struct sata_fis_d2h *s)
Dave Liu6f1a8a22008-03-26 22:55:32 +080054{
55 printf("Status FIS dump:\n\r");
56 printf("fis_type: %02x\n\r", s->fis_type);
57 printf("pm_port_i: %02x\n\r", s->pm_port_i);
58 printf("status: %02x\n\r", s->status);
59 printf("error: %02x\n\r", s->error);
60 printf("lba_low: %02x\n\r", s->lba_low);
61 printf("lba_mid: %02x\n\r", s->lba_mid);
62 printf("lba_high: %02x\n\r", s->lba_high);
63 printf("device: %02x\n\r", s->device);
64 printf("lba_low_exp: %02x\n\r", s->lba_low_exp);
65 printf("lba_mid_exp: %02x\n\r", s->lba_mid_exp);
66 printf("lba_high_exp: %02x\n\r", s->lba_high_exp);
67 printf("res1: %02x\n\r", s->res1);
68 printf("sector_count: %02x\n\r", s->sector_count);
69 printf("sector_count_exp: %02x\n\r", s->sector_count_exp);
70}
71
Kim Phillips03487482012-10-29 13:34:40 +000072static int ata_wait_register(unsigned __iomem *addr, u32 mask,
Dave Liu6f1a8a22008-03-26 22:55:32 +080073 u32 val, u32 timeout_msec)
74{
75 int i;
76 u32 temp;
77
78 for (i = 0; (((temp = in_le32(addr)) & mask) != val)
79 && i < timeout_msec; i++)
80 mdelay(1);
81 return (i < timeout_msec) ? 0 : -1;
82}
83
Peng Ma64a6ec32019-11-19 06:17:36 +000084#if !CONFIG_IS_ENABLED(BLK)
Dave Liu6f1a8a22008-03-26 22:55:32 +080085int init_sata(int dev)
Peng Ma64a6ec32019-11-19 06:17:36 +000086#else
87static int init_sata(struct fsl_ata_priv *priv, int dev)
88#endif
Dave Liu6f1a8a22008-03-26 22:55:32 +080089{
90 u32 length, align;
91 cmd_hdr_tbl_t *cmd_hdr;
92 u32 cda;
93 u32 val32;
Kim Phillips03487482012-10-29 13:34:40 +000094 fsl_sata_reg_t __iomem *reg;
Dave Liu6f1a8a22008-03-26 22:55:32 +080095 u32 sig;
96 int i;
97 fsl_sata_t *sata;
98
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +020099 if (dev < 0 || dev > (CONFIG_SYS_SATA_MAX_DEVICE - 1)) {
Dave Liu6f1a8a22008-03-26 22:55:32 +0800100 printf("the sata index %d is out of ranges\n\r", dev);
101 return -1;
102 }
103
Kumar Galaeb453df2010-04-20 10:21:25 -0500104#ifdef CONFIG_MPC85xx
105 if ((dev == 0) && (!is_serdes_configured(SATA1))) {
106 printf("SATA%d [dev = %d] is not enabled\n", dev+1, dev);
107 return -1;
108 }
109 if ((dev == 1) && (!is_serdes_configured(SATA2))) {
110 printf("SATA%d [dev = %d] is not enabled\n", dev+1, dev);
111 return -1;
112 }
113#endif
114
Dave Liu6f1a8a22008-03-26 22:55:32 +0800115 /* Allocate SATA device driver struct */
116 sata = (fsl_sata_t *)malloc(sizeof(fsl_sata_t));
117 if (!sata) {
118 printf("alloc the sata device struct failed\n\r");
119 return -1;
120 }
121 /* Zero all of the device driver struct */
122 memset((void *)sata, 0, sizeof(fsl_sata_t));
123
Peng Ma64a6ec32019-11-19 06:17:36 +0000124 snprintf(sata->name, 12, "SATA%d:\n", dev);
Dave Liu6f1a8a22008-03-26 22:55:32 +0800125
126 /* Set the controller register base address to device struct */
Peng Ma64a6ec32019-11-19 06:17:36 +0000127#if !CONFIG_IS_ENABLED(BLK)
128 sata_dev_desc[dev].priv = (void *)sata;
Dave Liu6f1a8a22008-03-26 22:55:32 +0800129 reg = (fsl_sata_reg_t *)(fsl_sata_info[dev].sata_reg_base);
Peng Ma64a6ec32019-11-19 06:17:36 +0000130 sata->dma_flag = fsl_sata_info[dev].flags;
131#else
132 reg = (fsl_sata_reg_t *)(priv->base + priv->offset * dev);
133 sata->dma_flag = priv->flag;
134 priv->fsl_sata = sata;
135#endif
Dave Liu6f1a8a22008-03-26 22:55:32 +0800136 sata->reg_base = reg;
137
138 /* Allocate the command header table, 4 bytes aligned */
139 length = sizeof(struct cmd_hdr_tbl);
140 align = SATA_HC_CMD_HDR_TBL_ALIGN;
141 sata->cmd_hdr_tbl_offset = (void *)malloc(length + align);
xypron.glpk@gmx.de222d2422017-04-15 15:31:53 +0200142 if (!sata->cmd_hdr_tbl_offset) {
Dave Liu6f1a8a22008-03-26 22:55:32 +0800143 printf("alloc the command header failed\n\r");
144 return -1;
145 }
146
147 cmd_hdr = (cmd_hdr_tbl_t *)(((u32)sata->cmd_hdr_tbl_offset + align)
148 & ~(align - 1));
149 sata->cmd_hdr = cmd_hdr;
150
151 /* Zero all of the command header table */
152 memset((void *)sata->cmd_hdr_tbl_offset, 0, length + align);
153
154 /* Allocate command descriptor for all command */
155 length = sizeof(struct cmd_desc) * SATA_HC_MAX_CMD;
156 align = SATA_HC_CMD_DESC_ALIGN;
157 sata->cmd_desc_offset = (void *)malloc(length + align);
158 if (!sata->cmd_desc_offset) {
159 printf("alloc the command descriptor failed\n\r");
160 return -1;
161 }
162 sata->cmd_desc = (cmd_desc_t *)(((u32)sata->cmd_desc_offset + align)
163 & ~(align - 1));
164 /* Zero all of command descriptor */
165 memset((void *)sata->cmd_desc_offset, 0, length + align);
166
167 /* Link the command descriptor to command header */
168 for (i = 0; i < SATA_HC_MAX_CMD; i++) {
169 cda = ((u32)sata->cmd_desc + SATA_HC_CMD_DESC_SIZE * i)
170 & ~(CMD_HDR_CDA_ALIGN - 1);
171 cmd_hdr->cmd_slot[i].cda = cpu_to_le32(cda);
172 }
173
174 /* To have safe state, force the controller offline */
175 val32 = in_le32(&reg->hcontrol);
176 val32 &= ~HCONTROL_ONOFF;
177 val32 |= HCONTROL_FORCE_OFFLINE;
178 out_le32(&reg->hcontrol, val32);
179
180 /* Wait the controller offline */
181 ata_wait_register(&reg->hstatus, HSTATUS_ONOFF, 0, 1000);
182
183 /* Set the command header base address to CHBA register to tell DMA */
184 out_le32(&reg->chba, (u32)cmd_hdr & ~0x3);
185
186 /* Snoop for the command header */
187 val32 = in_le32(&reg->hcontrol);
188 val32 |= HCONTROL_HDR_SNOOP;
189 out_le32(&reg->hcontrol, val32);
190
191 /* Disable all of interrupts */
192 val32 = in_le32(&reg->hcontrol);
193 val32 &= ~HCONTROL_INT_EN_ALL;
194 out_le32(&reg->hcontrol, val32);
195
196 /* Clear all of interrupts */
197 val32 = in_le32(&reg->hstatus);
198 out_le32(&reg->hstatus, val32);
199
200 /* Set the ICC, no interrupt coalescing */
201 out_le32(&reg->icc, 0x01000000);
202
203 /* No PM attatched, the SATA device direct connect */
204 out_le32(&reg->cqpmp, 0);
205
206 /* Clear SError register */
207 val32 = in_le32(&reg->serror);
208 out_le32(&reg->serror, val32);
209
210 /* Clear CER register */
211 val32 = in_le32(&reg->cer);
212 out_le32(&reg->cer, val32);
213
214 /* Clear DER register */
215 val32 = in_le32(&reg->der);
216 out_le32(&reg->der, val32);
217
218 /* No device detection or initialization action requested */
219 out_le32(&reg->scontrol, 0x00000300);
220
221 /* Configure the transport layer, default value */
222 out_le32(&reg->transcfg, 0x08000016);
223
224 /* Configure the link layer, default value */
225 out_le32(&reg->linkcfg, 0x0000ff34);
226
227 /* Bring the controller online */
228 val32 = in_le32(&reg->hcontrol);
229 val32 |= HCONTROL_ONOFF;
230 out_le32(&reg->hcontrol, val32);
231
232 mdelay(100);
233
234 /* print sata device name */
235 if (!dev)
236 printf("%s ", sata->name);
237 else
238 printf(" %s ", sata->name);
239
Dave Liu4d9c1882008-06-03 17:38:19 +0800240 /* Wait PHY RDY signal changed for 500ms */
241 ata_wait_register(&reg->hstatus, HSTATUS_PHY_RDY,
242 HSTATUS_PHY_RDY, 500);
243
Dave Liu6f1a8a22008-03-26 22:55:32 +0800244 /* Check PHYRDY */
245 val32 = in_le32(&reg->hstatus);
246 if (val32 & HSTATUS_PHY_RDY) {
247 sata->link = 1;
248 } else {
249 sata->link = 0;
250 printf("(No RDY)\n\r");
251 return -1;
252 }
253
Dave Liu4d9c1882008-06-03 17:38:19 +0800254 /* Wait for signature updated, which is 1st D2H */
255 ata_wait_register(&reg->hstatus, HSTATUS_SIGNATURE,
256 HSTATUS_SIGNATURE, 10000);
257
Dave Liu6f1a8a22008-03-26 22:55:32 +0800258 if (val32 & HSTATUS_SIGNATURE) {
259 sig = in_le32(&reg->sig);
260 debug("Signature updated, the sig =%08x\n\r", sig);
261 sata->ata_device_type = ata_dev_classify(sig);
262 }
263
264 /* Check the speed */
265 val32 = in_le32(&reg->sstatus);
266 if ((val32 & SSTATUS_SPD_MASK) == SSTATUS_SPD_GEN1)
267 printf("(1.5 Gbps)\n\r");
268 else if ((val32 & SSTATUS_SPD_MASK) == SSTATUS_SPD_GEN2)
269 printf("(3 Gbps)\n\r");
270
271 return 0;
272}
273
Nikita Kiryanovb9666d62014-11-21 12:47:23 +0200274int reset_sata(int dev)
275{
276 return 0;
277}
278
Kim Phillips03487482012-10-29 13:34:40 +0000279static void fsl_sata_dump_regs(fsl_sata_reg_t __iomem *reg)
Dave Liu6f1a8a22008-03-26 22:55:32 +0800280{
281 printf("\n\rSATA: %08x\n\r", (u32)reg);
282 printf("CQR: %08x\n\r", in_le32(&reg->cqr));
283 printf("CAR: %08x\n\r", in_le32(&reg->car));
284 printf("CCR: %08x\n\r", in_le32(&reg->ccr));
285 printf("CER: %08x\n\r", in_le32(&reg->cer));
286 printf("CQR: %08x\n\r", in_le32(&reg->cqr));
287 printf("DER: %08x\n\r", in_le32(&reg->der));
288 printf("CHBA: %08x\n\r", in_le32(&reg->chba));
289 printf("HStatus: %08x\n\r", in_le32(&reg->hstatus));
290 printf("HControl: %08x\n\r", in_le32(&reg->hcontrol));
291 printf("CQPMP: %08x\n\r", in_le32(&reg->cqpmp));
292 printf("SIG: %08x\n\r", in_le32(&reg->sig));
293 printf("ICC: %08x\n\r", in_le32(&reg->icc));
294 printf("SStatus: %08x\n\r", in_le32(&reg->sstatus));
295 printf("SError: %08x\n\r", in_le32(&reg->serror));
296 printf("SControl: %08x\n\r", in_le32(&reg->scontrol));
297 printf("SNotification: %08x\n\r", in_le32(&reg->snotification));
298 printf("TransCfg: %08x\n\r", in_le32(&reg->transcfg));
299 printf("TransStatus: %08x\n\r", in_le32(&reg->transstatus));
300 printf("LinkCfg: %08x\n\r", in_le32(&reg->linkcfg));
301 printf("LinkCfg1: %08x\n\r", in_le32(&reg->linkcfg1));
302 printf("LinkCfg2: %08x\n\r", in_le32(&reg->linkcfg2));
303 printf("LinkStatus: %08x\n\r", in_le32(&reg->linkstatus));
304 printf("LinkStatus1: %08x\n\r", in_le32(&reg->linkstatus1));
305 printf("PhyCtrlCfg: %08x\n\r", in_le32(&reg->phyctrlcfg));
306 printf("SYSPR: %08x\n\r", in_be32(&reg->syspr));
307}
308
galak18cf84a2009-07-07 15:53:21 -0500309static int fsl_ata_exec_ata_cmd(struct fsl_sata *sata, struct sata_fis_h2d *cfis,
Dave Liu6f1a8a22008-03-26 22:55:32 +0800310 int is_ncq, int tag, u8 *buffer, u32 len)
311{
312 cmd_hdr_entry_t *cmd_hdr;
313 cmd_desc_t *cmd_desc;
314 sata_fis_h2d_t *h2d;
315 prd_entry_t *prde;
316 u32 ext_c_ddc;
317 u32 prde_count;
318 u32 val32;
319 u32 ttl;
Kim Phillips03487482012-10-29 13:34:40 +0000320 fsl_sata_reg_t __iomem *reg = sata->reg_base;
Dave Liu6f1a8a22008-03-26 22:55:32 +0800321 int i;
322
323 /* Check xfer length */
324 if (len > SATA_HC_MAX_XFER_LEN) {
325 printf("max transfer length is 64MB\n\r");
326 return 0;
327 }
328
329 /* Setup the command descriptor */
330 cmd_desc = sata->cmd_desc + tag;
331
332 /* Get the pointer cfis of command descriptor */
333 h2d = (sata_fis_h2d_t *)cmd_desc->cfis;
334
335 /* Zero the cfis of command descriptor */
336 memset((void *)h2d, 0, SATA_HC_CMD_DESC_CFIS_SIZE);
337
338 /* Copy the cfis from user to command descriptor */
339 h2d->fis_type = cfis->fis_type;
340 h2d->pm_port_c = cfis->pm_port_c;
341 h2d->command = cfis->command;
342
343 h2d->features = cfis->features;
344 h2d->features_exp = cfis->features_exp;
345
346 h2d->lba_low = cfis->lba_low;
347 h2d->lba_mid = cfis->lba_mid;
348 h2d->lba_high = cfis->lba_high;
349 h2d->lba_low_exp = cfis->lba_low_exp;
350 h2d->lba_mid_exp = cfis->lba_mid_exp;
351 h2d->lba_high_exp = cfis->lba_high_exp;
352
353 if (!is_ncq) {
354 h2d->sector_count = cfis->sector_count;
355 h2d->sector_count_exp = cfis->sector_count_exp;
356 } else { /* NCQ */
357 h2d->sector_count = (u8)(tag << 3);
358 }
359
360 h2d->device = cfis->device;
361 h2d->control = cfis->control;
362
363 /* Setup the PRD table */
364 prde = (prd_entry_t *)cmd_desc->prdt;
365 memset((void *)prde, 0, sizeof(struct prdt));
366
367 prde_count = 0;
368 ttl = len;
369 for (i = 0; i < SATA_HC_MAX_PRD_DIRECT; i++) {
370 if (!len)
371 break;
372 prde->dba = cpu_to_le32((u32)buffer & ~0x3);
373 debug("dba = %08x\n\r", (u32)buffer);
374
375 if (len < PRD_ENTRY_MAX_XFER_SZ) {
376 ext_c_ddc = PRD_ENTRY_DATA_SNOOP | len;
377 debug("ext_c_ddc1 = %08x, len = %08x\n\r", ext_c_ddc, len);
378 prde->ext_c_ddc = cpu_to_le32(ext_c_ddc);
379 prde_count++;
380 prde++;
381 break;
382 } else {
383 ext_c_ddc = PRD_ENTRY_DATA_SNOOP; /* 4M bytes */
384 debug("ext_c_ddc2 = %08x, len = %08x\n\r", ext_c_ddc, len);
385 prde->ext_c_ddc = cpu_to_le32(ext_c_ddc);
386 buffer += PRD_ENTRY_MAX_XFER_SZ;
387 len -= PRD_ENTRY_MAX_XFER_SZ;
388 prde_count++;
389 prde++;
390 }
391 }
392
393 /* Setup the command slot of cmd hdr */
394 cmd_hdr = (cmd_hdr_entry_t *)&sata->cmd_hdr->cmd_slot[tag];
395
396 cmd_hdr->cda = cpu_to_le32((u32)cmd_desc & ~0x3);
397
398 val32 = prde_count << CMD_HDR_PRD_ENTRY_SHIFT;
399 val32 |= sizeof(sata_fis_h2d_t);
400 cmd_hdr->prde_fis_len = cpu_to_le32(val32);
401
402 cmd_hdr->ttl = cpu_to_le32(ttl);
403
404 if (!is_ncq) {
405 val32 = CMD_HDR_ATTR_RES | CMD_HDR_ATTR_SNOOP;
406 } else {
407 val32 = CMD_HDR_ATTR_RES | CMD_HDR_ATTR_SNOOP | CMD_HDR_ATTR_FPDMA;
408 }
409
410 tag &= CMD_HDR_ATTR_TAG;
411 val32 |= tag;
412
413 debug("attribute = %08x\n\r", val32);
414 cmd_hdr->attribute = cpu_to_le32(val32);
415
Vagrant Cascadiand65d6842015-11-24 14:45:02 -0800416 /* Make sure cmd desc and cmd slot valid before command issue */
Dave Liu6f1a8a22008-03-26 22:55:32 +0800417 sync();
418
419 /* PMP*/
420 val32 = (u32)(h2d->pm_port_c & 0x0f);
421 out_le32(&reg->cqpmp, val32);
422
423 /* Wait no active */
424 if (ata_wait_register(&reg->car, (1 << tag), 0, 10000))
425 printf("Wait no active time out\n\r");
426
427 /* Issue command */
428 if (!(in_le32(&reg->cqr) & (1 << tag))) {
429 val32 = 1 << tag;
430 out_le32(&reg->cqr, val32);
431 }
432
433 /* Wait command completed for 10s */
434 if (ata_wait_register(&reg->ccr, (1 << tag), (1 << tag), 10000)) {
435 if (!is_ncq)
436 printf("Non-NCQ command time out\n\r");
437 else
438 printf("NCQ command time out\n\r");
439 }
440
441 val32 = in_le32(&reg->cer);
442
443 if (val32) {
444 u32 der;
galak18cf84a2009-07-07 15:53:21 -0500445 fsl_sata_dump_sfis((struct sata_fis_d2h *)cmd_desc->sfis);
Dave Liu6f1a8a22008-03-26 22:55:32 +0800446 printf("CE at device\n\r");
447 fsl_sata_dump_regs(reg);
448 der = in_le32(&reg->der);
449 out_le32(&reg->cer, val32);
450 out_le32(&reg->der, der);
451 }
452
453 /* Clear complete flags */
454 val32 = in_le32(&reg->ccr);
455 out_le32(&reg->ccr, val32);
456
457 return len;
458}
459
galak18cf84a2009-07-07 15:53:21 -0500460static int fsl_ata_exec_reset_cmd(struct fsl_sata *sata, struct sata_fis_h2d *cfis,
Dave Liu6f1a8a22008-03-26 22:55:32 +0800461 int tag, u8 *buffer, u32 len)
462{
463 return 0;
464}
465
galak18cf84a2009-07-07 15:53:21 -0500466static int fsl_sata_exec_cmd(struct fsl_sata *sata, struct sata_fis_h2d *cfis,
Dave Liu6f1a8a22008-03-26 22:55:32 +0800467 enum cmd_type command_type, int tag, u8 *buffer, u32 len)
468{
469 int rc;
470
471 if (tag > SATA_HC_MAX_CMD || tag < 0) {
Kim Phillipsf91aa8d2008-07-10 14:00:15 -0500472 printf("tag is out of range, tag=%d\n\r", tag);
Dave Liu6f1a8a22008-03-26 22:55:32 +0800473 return -1;
474 }
475
476 switch (command_type) {
477 case CMD_ATA:
478 rc = fsl_ata_exec_ata_cmd(sata, cfis, 0, tag, buffer, len);
479 return rc;
480 case CMD_RESET:
481 rc = fsl_ata_exec_reset_cmd(sata, cfis, tag, buffer, len);
482 return rc;
483 case CMD_NCQ:
484 rc = fsl_ata_exec_ata_cmd(sata, cfis, 1, tag, buffer, len);
485 return rc;
486 case CMD_ATAPI:
487 case CMD_VENDOR_BIST:
488 case CMD_BIST:
489 printf("not support now\n\r");
490 return -1;
491 default:
492 break;
493 }
494
495 return -1;
496}
497
Peng Ma64a6ec32019-11-19 06:17:36 +0000498static void fsl_sata_xfer_mode(fsl_sata_t *sata, u16 *id)
Dave Liu6f1a8a22008-03-26 22:55:32 +0800499{
Dave Liu6f1a8a22008-03-26 22:55:32 +0800500 sata->pio = id[ATA_ID_PIO_MODES];
501 sata->mwdma = id[ATA_ID_MWDMA_MODES];
502 sata->udma = id[ATA_ID_UDMA_MODES];
503 debug("pio %04x, mwdma %04x, udma %04x\n\r", sata->pio, sata->mwdma, sata->udma);
504}
505
Peng Ma64a6ec32019-11-19 06:17:36 +0000506static void fsl_sata_set_features(fsl_sata_t *sata)
Dave Liu6f1a8a22008-03-26 22:55:32 +0800507{
galak18cf84a2009-07-07 15:53:21 -0500508 struct sata_fis_h2d h2d, *cfis = &h2d;
Dave Liu6f1a8a22008-03-26 22:55:32 +0800509 u8 udma_cap;
510
galak18cf84a2009-07-07 15:53:21 -0500511 memset(cfis, 0, sizeof(struct sata_fis_h2d));
Dave Liu6f1a8a22008-03-26 22:55:32 +0800512
513 cfis->fis_type = SATA_FIS_TYPE_REGISTER_H2D;
514 cfis->pm_port_c = 0x80; /* is command */
515 cfis->command = ATA_CMD_SET_FEATURES;
516 cfis->features = SETFEATURES_XFER;
517
518 /* First check the device capablity */
519 udma_cap = (u8)(sata->udma & 0xff);
520 debug("udma_cap %02x\n\r", udma_cap);
521
522 if (udma_cap == ATA_UDMA6)
523 cfis->sector_count = XFER_UDMA_6;
524 if (udma_cap == ATA_UDMA5)
525 cfis->sector_count = XFER_UDMA_5;
526 if (udma_cap == ATA_UDMA4)
527 cfis->sector_count = XFER_UDMA_4;
528 if (udma_cap == ATA_UDMA3)
529 cfis->sector_count = XFER_UDMA_3;
530
531 fsl_sata_exec_cmd(sata, cfis, CMD_ATA, 0, NULL, 0);
532}
533
Peng Ma64a6ec32019-11-19 06:17:36 +0000534static u32 fsl_sata_rw_cmd(fsl_sata_t *sata, u32 start, u32 blkcnt, u8 *buffer,
535 int is_write)
Dave Liu6f1a8a22008-03-26 22:55:32 +0800536{
galak18cf84a2009-07-07 15:53:21 -0500537 struct sata_fis_h2d h2d, *cfis = &h2d;
Dave Liu6f1a8a22008-03-26 22:55:32 +0800538 u32 block;
539
540 block = start;
Dave Liu6f1a8a22008-03-26 22:55:32 +0800541
galak18cf84a2009-07-07 15:53:21 -0500542 memset(cfis, 0, sizeof(struct sata_fis_h2d));
Dave Liu6f1a8a22008-03-26 22:55:32 +0800543
544 cfis->fis_type = SATA_FIS_TYPE_REGISTER_H2D;
545 cfis->pm_port_c = 0x80; /* is command */
Dave Liub9342a02008-04-01 15:22:11 +0800546 cfis->command = (is_write) ? ATA_CMD_WRITE : ATA_CMD_READ;
Dave Liu6f1a8a22008-03-26 22:55:32 +0800547 cfis->device = ATA_LBA;
548
549 cfis->device |= (block >> 24) & 0xf;
550 cfis->lba_high = (block >> 16) & 0xff;
551 cfis->lba_mid = (block >> 8) & 0xff;
552 cfis->lba_low = block & 0xff;
553 cfis->sector_count = (u8)(blkcnt & 0xff);
554
555 fsl_sata_exec_cmd(sata, cfis, CMD_ATA, 0, buffer, ATA_SECT_SIZE * blkcnt);
556 return blkcnt;
557}
558
Peng Ma64a6ec32019-11-19 06:17:36 +0000559static void fsl_sata_flush_cache(fsl_sata_t *sata)
Dave Liu6f1a8a22008-03-26 22:55:32 +0800560{
galak18cf84a2009-07-07 15:53:21 -0500561 struct sata_fis_h2d h2d, *cfis = &h2d;
Dave Liu6f1a8a22008-03-26 22:55:32 +0800562
galak18cf84a2009-07-07 15:53:21 -0500563 memset(cfis, 0, sizeof(struct sata_fis_h2d));
Dave Liu6f1a8a22008-03-26 22:55:32 +0800564
565 cfis->fis_type = SATA_FIS_TYPE_REGISTER_H2D;
566 cfis->pm_port_c = 0x80; /* is command */
Dave Liub9342a02008-04-01 15:22:11 +0800567 cfis->command = ATA_CMD_FLUSH;
Dave Liu6f1a8a22008-03-26 22:55:32 +0800568
569 fsl_sata_exec_cmd(sata, cfis, CMD_ATA, 0, NULL, 0);
570}
571
Peng Ma64a6ec32019-11-19 06:17:36 +0000572static u32 fsl_sata_rw_cmd_ext(fsl_sata_t *sata, u32 start, u32 blkcnt,
573 u8 *buffer, int is_write)
Dave Liu6f1a8a22008-03-26 22:55:32 +0800574{
galak18cf84a2009-07-07 15:53:21 -0500575 struct sata_fis_h2d h2d, *cfis = &h2d;
Dave Liu6f1a8a22008-03-26 22:55:32 +0800576 u64 block;
577
578 block = (u64)start;
Dave Liu6f1a8a22008-03-26 22:55:32 +0800579
galak18cf84a2009-07-07 15:53:21 -0500580 memset(cfis, 0, sizeof(struct sata_fis_h2d));
Dave Liu6f1a8a22008-03-26 22:55:32 +0800581
582 cfis->fis_type = SATA_FIS_TYPE_REGISTER_H2D;
583 cfis->pm_port_c = 0x80; /* is command */
584
Dave Liub9342a02008-04-01 15:22:11 +0800585 cfis->command = (is_write) ? ATA_CMD_WRITE_EXT
586 : ATA_CMD_READ_EXT;
Dave Liu6f1a8a22008-03-26 22:55:32 +0800587
588 cfis->lba_high_exp = (block >> 40) & 0xff;
589 cfis->lba_mid_exp = (block >> 32) & 0xff;
590 cfis->lba_low_exp = (block >> 24) & 0xff;
591 cfis->lba_high = (block >> 16) & 0xff;
592 cfis->lba_mid = (block >> 8) & 0xff;
593 cfis->lba_low = block & 0xff;
594 cfis->device = ATA_LBA;
595 cfis->sector_count_exp = (blkcnt >> 8) & 0xff;
596 cfis->sector_count = blkcnt & 0xff;
597
598 fsl_sata_exec_cmd(sata, cfis, CMD_ATA, 0, buffer, ATA_SECT_SIZE * blkcnt);
599 return blkcnt;
600}
601
Peng Ma64a6ec32019-11-19 06:17:36 +0000602static u32 fsl_sata_rw_ncq_cmd(fsl_sata_t *sata, u32 start, u32 blkcnt,
603 u8 *buffer, int is_write)
Dave Liu6f1a8a22008-03-26 22:55:32 +0800604{
galak18cf84a2009-07-07 15:53:21 -0500605 struct sata_fis_h2d h2d, *cfis = &h2d;
Dave Liu6f1a8a22008-03-26 22:55:32 +0800606 int ncq_channel;
607 u64 block;
608
Tang Yuantiana89db422011-10-03 12:18:41 -0700609 if (sata->lba48 != 1) {
Dave Liu6f1a8a22008-03-26 22:55:32 +0800610 printf("execute FPDMA command on non-LBA48 hard disk\n\r");
611 return -1;
612 }
613
614 block = (u64)start;
Dave Liu6f1a8a22008-03-26 22:55:32 +0800615
galak18cf84a2009-07-07 15:53:21 -0500616 memset(cfis, 0, sizeof(struct sata_fis_h2d));
Dave Liu6f1a8a22008-03-26 22:55:32 +0800617
618 cfis->fis_type = SATA_FIS_TYPE_REGISTER_H2D;
619 cfis->pm_port_c = 0x80; /* is command */
620
Dave Liub9342a02008-04-01 15:22:11 +0800621 cfis->command = (is_write) ? ATA_CMD_FPDMA_WRITE
622 : ATA_CMD_FPDMA_READ;
Dave Liu6f1a8a22008-03-26 22:55:32 +0800623
624 cfis->lba_high_exp = (block >> 40) & 0xff;
625 cfis->lba_mid_exp = (block >> 32) & 0xff;
626 cfis->lba_low_exp = (block >> 24) & 0xff;
627 cfis->lba_high = (block >> 16) & 0xff;
628 cfis->lba_mid = (block >> 8) & 0xff;
629 cfis->lba_low = block & 0xff;
630
631 cfis->device = ATA_LBA;
632 cfis->features_exp = (blkcnt >> 8) & 0xff;
633 cfis->features = blkcnt & 0xff;
634
635 if (sata->queue_depth >= SATA_HC_MAX_CMD)
636 ncq_channel = SATA_HC_MAX_CMD - 1;
637 else
638 ncq_channel = sata->queue_depth - 1;
639
640 /* Use the latest queue */
641 fsl_sata_exec_cmd(sata, cfis, CMD_NCQ, ncq_channel, buffer, ATA_SECT_SIZE * blkcnt);
642 return blkcnt;
643}
644
Peng Ma64a6ec32019-11-19 06:17:36 +0000645static void fsl_sata_flush_cache_ext(fsl_sata_t *sata)
Dave Liu6f1a8a22008-03-26 22:55:32 +0800646{
galak18cf84a2009-07-07 15:53:21 -0500647 struct sata_fis_h2d h2d, *cfis = &h2d;
Dave Liu6f1a8a22008-03-26 22:55:32 +0800648
galak18cf84a2009-07-07 15:53:21 -0500649 memset(cfis, 0, sizeof(struct sata_fis_h2d));
Dave Liu6f1a8a22008-03-26 22:55:32 +0800650
651 cfis->fis_type = SATA_FIS_TYPE_REGISTER_H2D;
652 cfis->pm_port_c = 0x80; /* is command */
Dave Liub9342a02008-04-01 15:22:11 +0800653 cfis->command = ATA_CMD_FLUSH_EXT;
Dave Liu6f1a8a22008-03-26 22:55:32 +0800654
655 fsl_sata_exec_cmd(sata, cfis, CMD_ATA, 0, NULL, 0);
656}
657
Peng Ma64a6ec32019-11-19 06:17:36 +0000658static void fsl_sata_init_wcache(fsl_sata_t *sata, u16 *id)
Dave Liu6f1a8a22008-03-26 22:55:32 +0800659{
Dave Liu6f1a8a22008-03-26 22:55:32 +0800660 if (ata_id_has_wcache(id) && ata_id_wcache_enabled(id))
661 sata->wcache = 1;
662 if (ata_id_has_flush(id))
663 sata->flush = 1;
664 if (ata_id_has_flush_ext(id))
665 sata->flush_ext = 1;
666}
667
Peng Ma64a6ec32019-11-19 06:17:36 +0000668static u32 ata_low_level_rw_lba48(fsl_sata_t *sata, u32 blknr, lbaint_t blkcnt,
669 const void *buffer, int is_write)
Dave Liu6f1a8a22008-03-26 22:55:32 +0800670{
671 u32 start, blks;
672 u8 *addr;
673 int max_blks;
674
675 start = blknr;
676 blks = blkcnt;
677 addr = (u8 *)buffer;
678
679 max_blks = ATA_MAX_SECTORS_LBA48;
680 do {
681 if (blks > max_blks) {
Peng Ma64a6ec32019-11-19 06:17:36 +0000682 if (sata->dma_flag != FLAGS_FPDMA)
683 fsl_sata_rw_cmd_ext(sata, start, max_blks, addr,
684 is_write);
Dave Liu6f1a8a22008-03-26 22:55:32 +0800685 else
Peng Ma64a6ec32019-11-19 06:17:36 +0000686 fsl_sata_rw_ncq_cmd(sata, start, max_blks, addr,
687 is_write);
Dave Liu6f1a8a22008-03-26 22:55:32 +0800688 start += max_blks;
689 blks -= max_blks;
690 addr += ATA_SECT_SIZE * max_blks;
691 } else {
Peng Ma64a6ec32019-11-19 06:17:36 +0000692 if (sata->dma_flag != FLAGS_FPDMA)
693 fsl_sata_rw_cmd_ext(sata, start, blks, addr,
694 is_write);
Dave Liu6f1a8a22008-03-26 22:55:32 +0800695 else
Peng Ma64a6ec32019-11-19 06:17:36 +0000696 fsl_sata_rw_ncq_cmd(sata, start, blks, addr,
697 is_write);
Dave Liu6f1a8a22008-03-26 22:55:32 +0800698 start += blks;
699 blks = 0;
700 addr += ATA_SECT_SIZE * blks;
701 }
702 } while (blks != 0);
703
704 return blkcnt;
705}
706
Peng Ma64a6ec32019-11-19 06:17:36 +0000707static u32 ata_low_level_rw_lba28(fsl_sata_t *sata, u32 blknr, u32 blkcnt,
Kim Phillips03487482012-10-29 13:34:40 +0000708 const void *buffer, int is_write)
Dave Liu6f1a8a22008-03-26 22:55:32 +0800709{
710 u32 start, blks;
711 u8 *addr;
712 int max_blks;
713
714 start = blknr;
715 blks = blkcnt;
716 addr = (u8 *)buffer;
717
718 max_blks = ATA_MAX_SECTORS;
719 do {
720 if (blks > max_blks) {
Peng Ma64a6ec32019-11-19 06:17:36 +0000721 fsl_sata_rw_cmd(sata, start, max_blks, addr, is_write);
Dave Liu6f1a8a22008-03-26 22:55:32 +0800722 start += max_blks;
723 blks -= max_blks;
724 addr += ATA_SECT_SIZE * max_blks;
725 } else {
Peng Ma64a6ec32019-11-19 06:17:36 +0000726 fsl_sata_rw_cmd(sata, start, blks, addr, is_write);
Dave Liu6f1a8a22008-03-26 22:55:32 +0800727 start += blks;
728 blks = 0;
729 addr += ATA_SECT_SIZE * blks;
730 }
731 } while (blks != 0);
732
733 return blkcnt;
734}
735
736/*
737 * SATA interface between low level driver and command layer
738 */
Peng Ma64a6ec32019-11-19 06:17:36 +0000739#if !CONFIG_IS_ENABLED(BLK)
Tom Rini47e68fb2012-09-29 07:55:11 -0700740ulong sata_read(int dev, ulong blknr, lbaint_t blkcnt, void *buffer)
Dave Liu6f1a8a22008-03-26 22:55:32 +0800741{
Tang Yuantiana89db422011-10-03 12:18:41 -0700742 fsl_sata_t *sata = (fsl_sata_t *)sata_dev_desc[dev].priv;
Peng Ma64a6ec32019-11-19 06:17:36 +0000743#else
744static ulong sata_read(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt,
745 void *buffer)
746{
747 struct fsl_ata_priv *priv = dev_get_platdata(dev);
748 fsl_sata_t *sata = priv->fsl_sata;
749#endif
750 u32 rc;
Dave Liu6f1a8a22008-03-26 22:55:32 +0800751
Tang Yuantiana89db422011-10-03 12:18:41 -0700752 if (sata->lba48)
Peng Ma64a6ec32019-11-19 06:17:36 +0000753 rc = ata_low_level_rw_lba48(sata, blknr, blkcnt, buffer,
754 READ_CMD);
Dave Liu6f1a8a22008-03-26 22:55:32 +0800755 else
Peng Ma64a6ec32019-11-19 06:17:36 +0000756 rc = ata_low_level_rw_lba28(sata, blknr, blkcnt, buffer,
757 READ_CMD);
Dave Liu6f1a8a22008-03-26 22:55:32 +0800758 return rc;
759}
760
Peng Ma64a6ec32019-11-19 06:17:36 +0000761#if !CONFIG_IS_ENABLED(BLK)
Tom Rini47e68fb2012-09-29 07:55:11 -0700762ulong sata_write(int dev, ulong blknr, lbaint_t blkcnt, const void *buffer)
Dave Liu6f1a8a22008-03-26 22:55:32 +0800763{
Tang Yuantiana89db422011-10-03 12:18:41 -0700764 fsl_sata_t *sata = (fsl_sata_t *)sata_dev_desc[dev].priv;
Peng Ma64a6ec32019-11-19 06:17:36 +0000765#else
766static ulong sata_write(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt,
767 const void *buffer)
768{
769 struct fsl_ata_priv *priv = dev_get_platdata(dev);
770 fsl_sata_t *sata = priv->fsl_sata;
771#endif
772 u32 rc;
Dave Liu6f1a8a22008-03-26 22:55:32 +0800773
Tang Yuantiana89db422011-10-03 12:18:41 -0700774 if (sata->lba48) {
Peng Ma64a6ec32019-11-19 06:17:36 +0000775 rc = ata_low_level_rw_lba48(sata, blknr, blkcnt, buffer,
776 WRITE_CMD);
777 if (sata->wcache && sata->flush_ext)
778 fsl_sata_flush_cache_ext(sata);
Dave Liu6f1a8a22008-03-26 22:55:32 +0800779 } else {
Peng Ma64a6ec32019-11-19 06:17:36 +0000780 rc = ata_low_level_rw_lba28(sata, blknr, blkcnt, buffer,
781 WRITE_CMD);
782 if (sata->wcache && sata->flush)
783 fsl_sata_flush_cache(sata);
Dave Liu6f1a8a22008-03-26 22:55:32 +0800784 }
785 return rc;
786}
787
Peng Ma64a6ec32019-11-19 06:17:36 +0000788static void fsl_sata_identify(fsl_sata_t *sata, u16 *id)
789{
790 struct sata_fis_h2d h2d, *cfis = &h2d;
791
792 memset(cfis, 0, sizeof(struct sata_fis_h2d));
793
794 cfis->fis_type = SATA_FIS_TYPE_REGISTER_H2D;
795 cfis->pm_port_c = 0x80; /* is command */
796 cfis->command = ATA_CMD_ID_ATA;
797
798 fsl_sata_exec_cmd(sata, cfis, CMD_ATA, 0, (u8 *)id, ATA_ID_WORDS * 2);
799 ata_swap_buf_le16(id, ATA_ID_WORDS);
800}
801
802#if !CONFIG_IS_ENABLED(BLK)
Dave Liu6f1a8a22008-03-26 22:55:32 +0800803int scan_sata(int dev)
804{
805 fsl_sata_t *sata = (fsl_sata_t *)sata_dev_desc[dev].priv;
Peng Ma64a6ec32019-11-19 06:17:36 +0000806#else
807static int scan_sata(struct udevice *dev)
808{
809 struct blk_desc *desc = dev_get_uclass_platdata(dev);
810 struct fsl_ata_priv *priv = dev_get_platdata(dev);
811 fsl_sata_t *sata = priv->fsl_sata;
812#endif
813
Dave Liu6f1a8a22008-03-26 22:55:32 +0800814 unsigned char serial[ATA_ID_SERNO_LEN + 1];
815 unsigned char firmware[ATA_ID_FW_REV_LEN + 1];
816 unsigned char product[ATA_ID_PROD_LEN + 1];
817 u16 *id;
818 u64 n_sectors;
819
820 /* if no detected link */
821 if (!sata->link)
822 return -1;
823
824 id = (u16 *)malloc(ATA_ID_WORDS * 2);
825 if (!id) {
826 printf("id malloc failed\n\r");
827 return -1;
828 }
829
830 /* Identify device to get information */
Peng Ma64a6ec32019-11-19 06:17:36 +0000831 fsl_sata_identify(sata, id);
Dave Liu6f1a8a22008-03-26 22:55:32 +0800832
833 /* Serial number */
834 ata_id_c_string(id, serial, ATA_ID_SERNO, sizeof(serial));
Dave Liu6f1a8a22008-03-26 22:55:32 +0800835
836 /* Firmware version */
837 ata_id_c_string(id, firmware, ATA_ID_FW_REV, sizeof(firmware));
Dave Liu6f1a8a22008-03-26 22:55:32 +0800838
839 /* Product model */
840 ata_id_c_string(id, product, ATA_ID_PROD, sizeof(product));
Dave Liu6f1a8a22008-03-26 22:55:32 +0800841
842 /* Totoal sectors */
843 n_sectors = ata_id_n_sectors(id);
Dave Liu6f1a8a22008-03-26 22:55:32 +0800844
Tang Yuantiana89db422011-10-03 12:18:41 -0700845#ifdef CONFIG_LBA48
Dave Liu6f1a8a22008-03-26 22:55:32 +0800846 /* Check if support LBA48 */
847 if (ata_id_has_lba48(id)) {
Tang Yuantiana89db422011-10-03 12:18:41 -0700848 sata->lba48 = 1;
Dave Liu6f1a8a22008-03-26 22:55:32 +0800849 debug("Device support LBA48\n\r");
Tang Yuantiana89db422011-10-03 12:18:41 -0700850 } else
851 debug("Device supports LBA28\n\r");
852#endif
Dave Liu6f1a8a22008-03-26 22:55:32 +0800853
Peng Ma64a6ec32019-11-19 06:17:36 +0000854#if !CONFIG_IS_ENABLED(BLK)
855 memcpy(sata_dev_desc[dev].product, serial, sizeof(serial));
856 memcpy(sata_dev_desc[dev].revision, firmware, sizeof(firmware));
857 memcpy(sata_dev_desc[dev].vendor, product, sizeof(product));
858 sata_dev_desc[dev].lba = (u32)n_sectors;
859#ifdef CONFIG_LBA48
860 sata_dev_desc[dev].lba48 = sata->lba48;
861#endif
862#else
863 memcpy(desc->product, serial, sizeof(serial));
864 memcpy(desc->revision, firmware, sizeof(firmware));
865 memcpy(desc->vendor, product, sizeof(product));
866 desc->lba = n_sectors;
867#ifdef CONFIG_LBA48
868 desc->lba48 = sata->lba48;
869#endif
870#endif
871
Dave Liu6f1a8a22008-03-26 22:55:32 +0800872 /* Get the NCQ queue depth from device */
873 sata->queue_depth = ata_id_queue_depth(id);
874
875 /* Get the xfer mode from device */
Peng Ma64a6ec32019-11-19 06:17:36 +0000876 fsl_sata_xfer_mode(sata, id);
Dave Liu6f1a8a22008-03-26 22:55:32 +0800877
878 /* Get the write cache status from device */
Peng Ma64a6ec32019-11-19 06:17:36 +0000879 fsl_sata_init_wcache(sata, id);
Dave Liu6f1a8a22008-03-26 22:55:32 +0800880
881 /* Set the xfer mode to highest speed */
Peng Ma64a6ec32019-11-19 06:17:36 +0000882 fsl_sata_set_features(sata);
883
Dave Liu6f1a8a22008-03-26 22:55:32 +0800884#ifdef DEBUG
Dave Liu6f1a8a22008-03-26 22:55:32 +0800885 ata_dump_id(id);
886#endif
887 free((void *)id);
888 return 0;
889}
Peng Ma64a6ec32019-11-19 06:17:36 +0000890
891#if CONFIG_IS_ENABLED(BLK)
892static const struct blk_ops sata_fsl_blk_ops = {
893 .read = sata_read,
894 .write = sata_write,
895};
896
897U_BOOT_DRIVER(sata_fsl_driver) = {
898 .name = "sata_fsl_blk",
899 .id = UCLASS_BLK,
900 .ops = &sata_fsl_blk_ops,
901 .platdata_auto_alloc_size = sizeof(struct fsl_ata_priv),
902};
903
904static int fsl_ata_ofdata_to_platdata(struct udevice *dev)
905{
906 struct fsl_ata_priv *priv = dev_get_priv(dev);
907
908 priv->number = dev_read_u32_default(dev, "sata-number", -1);
909 priv->flag = dev_read_u32_default(dev, "sata-fpdma", -1);
910 priv->offset = dev_read_u32_default(dev, "sata-offset", -1);
911
912 priv->base = dev_read_addr(dev);
913 if (priv->base == FDT_ADDR_T_NONE)
914 return -EINVAL;
915
916 return 0;
917}
918
919static int fsl_ata_probe(struct udevice *dev)
920{
921 struct fsl_ata_priv *blk_priv, *priv;
922 struct udevice *blk;
923 char sata_name[10];
924 int nr_ports;
925 int ret;
926 int i;
927
928 priv = dev_get_priv(dev);
929 nr_ports = priv->number;
930 nr_ports = min(nr_ports, CONFIG_SYS_SATA_MAX_DEVICE);
931
932 for (i = 0; i < nr_ports; i++) {
933 snprintf(sata_name, sizeof(sata_name), "fsl_sata%d", i);
934 ret = blk_create_devicef(dev, "sata_fsl_blk", sata_name,
935 IF_TYPE_SATA, -1, 512, 0, &blk);
936 if (ret) {
937 debug("Can't create device\n");
938 return ret;
939 }
940
941 /* Init SATA port */
942 ret = init_sata(priv, i);
943 if (ret) {
944 debug("%s: Failed to init sata\n", __func__);
945 return ret;
946 }
947
948 blk_priv = dev_get_platdata(blk);
949 blk_priv->fsl_sata = priv->fsl_sata;
950 /* Scan SATA port */
951 ret = scan_sata(blk);
952 if (ret) {
953 debug("%s: Failed to scan bus\n", __func__);
954 return ret;
955 }
956 }
957
958 return 0;
959}
960
961static int sata_fsl_scan(struct udevice *dev)
962{
963 /* Nothing to do here */
964
965 return 0;
966}
967
968struct ahci_ops sata_fsl_ahci_ops = {
969 .scan = sata_fsl_scan,
970};
971
972static const struct udevice_id fsl_ata_ids[] = {
973 { .compatible = "fsl,pq-sata-v2" },
974 { }
975};
976
977U_BOOT_DRIVER(fsl_ahci) = {
978 .name = "fsl_ahci",
979 .id = UCLASS_AHCI,
980 .of_match = fsl_ata_ids,
981 .ops = &sata_fsl_ahci_ops,
982 .ofdata_to_platdata = fsl_ata_ofdata_to_platdata,
983 .probe = fsl_ata_probe,
984 .priv_auto_alloc_size = sizeof(struct fsl_ata_priv),
985};
986#endif