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