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(®->hcontrol); 161*f2105c61SSimon Glass val32 &= ~HCONTROL_ONOFF; 162*f2105c61SSimon Glass val32 |= HCONTROL_FORCE_OFFLINE; 163*f2105c61SSimon Glass out_le32(®->hcontrol, val32); 164*f2105c61SSimon Glass 165*f2105c61SSimon Glass /* Wait the controller offline */ 166*f2105c61SSimon Glass ata_wait_register(®->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(®->chba, (u32)cmd_hdr & ~0x3); 170*f2105c61SSimon Glass 171*f2105c61SSimon Glass /* Snoop for the command header */ 172*f2105c61SSimon Glass val32 = in_le32(®->hcontrol); 173*f2105c61SSimon Glass val32 |= HCONTROL_HDR_SNOOP; 174*f2105c61SSimon Glass out_le32(®->hcontrol, val32); 175*f2105c61SSimon Glass 176*f2105c61SSimon Glass /* Disable all of interrupts */ 177*f2105c61SSimon Glass val32 = in_le32(®->hcontrol); 178*f2105c61SSimon Glass val32 &= ~HCONTROL_INT_EN_ALL; 179*f2105c61SSimon Glass out_le32(®->hcontrol, val32); 180*f2105c61SSimon Glass 181*f2105c61SSimon Glass /* Clear all of interrupts */ 182*f2105c61SSimon Glass val32 = in_le32(®->hstatus); 183*f2105c61SSimon Glass out_le32(®->hstatus, val32); 184*f2105c61SSimon Glass 185*f2105c61SSimon Glass /* Set the ICC, no interrupt coalescing */ 186*f2105c61SSimon Glass out_le32(®->icc, 0x01000000); 187*f2105c61SSimon Glass 188*f2105c61SSimon Glass /* No PM attatched, the SATA device direct connect */ 189*f2105c61SSimon Glass out_le32(®->cqpmp, 0); 190*f2105c61SSimon Glass 191*f2105c61SSimon Glass /* Clear SError register */ 192*f2105c61SSimon Glass val32 = in_le32(®->serror); 193*f2105c61SSimon Glass out_le32(®->serror, val32); 194*f2105c61SSimon Glass 195*f2105c61SSimon Glass /* Clear CER register */ 196*f2105c61SSimon Glass val32 = in_le32(®->cer); 197*f2105c61SSimon Glass out_le32(®->cer, val32); 198*f2105c61SSimon Glass 199*f2105c61SSimon Glass /* Clear DER register */ 200*f2105c61SSimon Glass val32 = in_le32(®->der); 201*f2105c61SSimon Glass out_le32(®->der, val32); 202*f2105c61SSimon Glass 203*f2105c61SSimon Glass /* No device detection or initialization action requested */ 204*f2105c61SSimon Glass out_le32(®->scontrol, 0x00000300); 205*f2105c61SSimon Glass 206*f2105c61SSimon Glass /* Configure the transport layer, default value */ 207*f2105c61SSimon Glass out_le32(®->transcfg, 0x08000016); 208*f2105c61SSimon Glass 209*f2105c61SSimon Glass /* Configure the link layer, default value */ 210*f2105c61SSimon Glass out_le32(®->linkcfg, 0x0000ff34); 211*f2105c61SSimon Glass 212*f2105c61SSimon Glass /* Bring the controller online */ 213*f2105c61SSimon Glass val32 = in_le32(®->hcontrol); 214*f2105c61SSimon Glass val32 |= HCONTROL_ONOFF; 215*f2105c61SSimon Glass out_le32(®->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(®->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(®->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(®->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(®->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(®->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(®->cqr)); 268*f2105c61SSimon Glass printf("CAR: %08x\n\r", in_le32(®->car)); 269*f2105c61SSimon Glass printf("CCR: %08x\n\r", in_le32(®->ccr)); 270*f2105c61SSimon Glass printf("CER: %08x\n\r", in_le32(®->cer)); 271*f2105c61SSimon Glass printf("CQR: %08x\n\r", in_le32(®->cqr)); 272*f2105c61SSimon Glass printf("DER: %08x\n\r", in_le32(®->der)); 273*f2105c61SSimon Glass printf("CHBA: %08x\n\r", in_le32(®->chba)); 274*f2105c61SSimon Glass printf("HStatus: %08x\n\r", in_le32(®->hstatus)); 275*f2105c61SSimon Glass printf("HControl: %08x\n\r", in_le32(®->hcontrol)); 276*f2105c61SSimon Glass printf("CQPMP: %08x\n\r", in_le32(®->cqpmp)); 277*f2105c61SSimon Glass printf("SIG: %08x\n\r", in_le32(®->sig)); 278*f2105c61SSimon Glass printf("ICC: %08x\n\r", in_le32(®->icc)); 279*f2105c61SSimon Glass printf("SStatus: %08x\n\r", in_le32(®->sstatus)); 280*f2105c61SSimon Glass printf("SError: %08x\n\r", in_le32(®->serror)); 281*f2105c61SSimon Glass printf("SControl: %08x\n\r", in_le32(®->scontrol)); 282*f2105c61SSimon Glass printf("SNotification: %08x\n\r", in_le32(®->snotification)); 283*f2105c61SSimon Glass printf("TransCfg: %08x\n\r", in_le32(®->transcfg)); 284*f2105c61SSimon Glass printf("TransStatus: %08x\n\r", in_le32(®->transstatus)); 285*f2105c61SSimon Glass printf("LinkCfg: %08x\n\r", in_le32(®->linkcfg)); 286*f2105c61SSimon Glass printf("LinkCfg1: %08x\n\r", in_le32(®->linkcfg1)); 287*f2105c61SSimon Glass printf("LinkCfg2: %08x\n\r", in_le32(®->linkcfg2)); 288*f2105c61SSimon Glass printf("LinkStatus: %08x\n\r", in_le32(®->linkstatus)); 289*f2105c61SSimon Glass printf("LinkStatus1: %08x\n\r", in_le32(®->linkstatus1)); 290*f2105c61SSimon Glass printf("PhyCtrlCfg: %08x\n\r", in_le32(®->phyctrlcfg)); 291*f2105c61SSimon Glass printf("SYSPR: %08x\n\r", in_be32(®->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(®->cqpmp, val32); 407*f2105c61SSimon Glass 408*f2105c61SSimon Glass /* Wait no active */ 409*f2105c61SSimon Glass if (ata_wait_register(®->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(®->cqr) & (1 << tag))) { 414*f2105c61SSimon Glass val32 = 1 << tag; 415*f2105c61SSimon Glass out_le32(®->cqr, val32); 416*f2105c61SSimon Glass } 417*f2105c61SSimon Glass 418*f2105c61SSimon Glass /* Wait command completed for 10s */ 419*f2105c61SSimon Glass if (ata_wait_register(®->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(®->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(®->der); 434*f2105c61SSimon Glass out_le32(®->cer, val32); 435*f2105c61SSimon Glass out_le32(®->der, der); 436*f2105c61SSimon Glass } 437*f2105c61SSimon Glass 438*f2105c61SSimon Glass /* Clear complete flags */ 439*f2105c61SSimon Glass val32 = in_le32(®->ccr); 440*f2105c61SSimon Glass out_le32(®->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