Esempio n. 1
0
static int wait_dma_completion(int port, int index, u32 timeout_msec)
{
	u32 tmp, res;

	tmp = port == 0 ? SATAHC_ICR_PORT0 : SATAHC_ICR_PORT1;
	res = ata_wait_register((u32 *)(SATAHC_BASE + SATAHC_ICR), tmp,
				tmp, timeout_msec);
	if (res)
		printf("Failed to wait for completion on port %d\n", port);

	return res;
}
Esempio n. 2
0
static int mv_ata_exec_ata_cmd_nondma(int port,
				      struct sata_fis_h2d *cfis, u8 *buffer,
				      u32 len, u32 iswrite)
{
	struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv;
	int i;
	u16 *tp;

	debug("%s\n", __func__);

	out_le32(priv->regbase + PIO_SECTOR_COUNT, cfis->sector_count);
	out_le32(priv->regbase + PIO_LBA_HI, cfis->lba_high);
	out_le32(priv->regbase + PIO_LBA_MID, cfis->lba_mid);
	out_le32(priv->regbase + PIO_LBA_LOW, cfis->lba_low);
	out_le32(priv->regbase + PIO_ERR_FEATURES, cfis->features);
	out_le32(priv->regbase + PIO_DEVICE, cfis->device);
	out_le32(priv->regbase + PIO_CMD_STATUS, cfis->command);

	if (ata_wait_register((u32 *)(priv->regbase + PIO_CMD_STATUS),
			      ATA_BUSY, 0x0, 10000)) {
		debug("Failed to wait for completion\n");
		return -1;
	}

	if (len > 0) {
		tp = (u16 *)buffer;
		for (i = 0; i < len / 2; i++) {
			if (iswrite)
				out_le16(priv->regbase + PIO_DATA, *tp++);
			else
				*tp++ = in_le16(priv->regbase + PIO_DATA);
		}
	}

	return len;
}
Esempio n. 3
0
static int fsl_ata_exec_ata_cmd(struct fsl_sata *sata, struct cfis *cfis,
				int is_ncq, int tag, u8 *buffer, u32 len)
{
	cmd_hdr_entry_t *cmd_hdr;
	cmd_desc_t *cmd_desc;
	sata_fis_h2d_t *h2d;
	prd_entry_t *prde;
	u32 ext_c_ddc;
	u32 prde_count;
	u32 val32;
	u32 ttl;
	fsl_sata_reg_t *reg = sata->reg_base;
	int i;

	/* Check xfer length */
	if (len > SATA_HC_MAX_XFER_LEN) {
		printf("max transfer length is 64MB\n\r");
		return 0;
	}

	/* Setup the command descriptor */
	cmd_desc = sata->cmd_desc + tag;

	/* Get the pointer cfis of command descriptor */
	h2d = (sata_fis_h2d_t *)cmd_desc->cfis;

	/* Zero the cfis of command descriptor */
	memset((void *)h2d, 0, SATA_HC_CMD_DESC_CFIS_SIZE);

	/* Copy the cfis from user to command descriptor */
	h2d->fis_type = cfis->fis_type;
	h2d->pm_port_c = cfis->pm_port_c;
	h2d->command = cfis->command;

	h2d->features = cfis->features;
	h2d->features_exp = cfis->features_exp;

	h2d->lba_low = cfis->lba_low;
	h2d->lba_mid = cfis->lba_mid;
	h2d->lba_high = cfis->lba_high;
	h2d->lba_low_exp = cfis->lba_low_exp;
	h2d->lba_mid_exp = cfis->lba_mid_exp;
	h2d->lba_high_exp = cfis->lba_high_exp;

	if (!is_ncq) {
		h2d->sector_count = cfis->sector_count;
		h2d->sector_count_exp = cfis->sector_count_exp;
	} else { /* NCQ */
		h2d->sector_count = (u8)(tag << 3);
	}

	h2d->device = cfis->device;
	h2d->control = cfis->control;

	/* Setup the PRD table */
	prde = (prd_entry_t *)cmd_desc->prdt;
	memset((void *)prde, 0, sizeof(struct prdt));

	prde_count = 0;
	ttl = len;
	for (i = 0; i < SATA_HC_MAX_PRD_DIRECT; i++) {
		if (!len)
			break;
		prde->dba = cpu_to_le32((u32)buffer & ~0x3);
		debug("dba = %08x\n\r", (u32)buffer);

		if (len < PRD_ENTRY_MAX_XFER_SZ) {
			ext_c_ddc = PRD_ENTRY_DATA_SNOOP | len;
			debug("ext_c_ddc1 = %08x, len = %08x\n\r", ext_c_ddc, len);
			prde->ext_c_ddc = cpu_to_le32(ext_c_ddc);
			prde_count++;
			prde++;
			break;
		} else {
			ext_c_ddc = PRD_ENTRY_DATA_SNOOP; /* 4M bytes */
			debug("ext_c_ddc2 = %08x, len = %08x\n\r", ext_c_ddc, len);
			prde->ext_c_ddc = cpu_to_le32(ext_c_ddc);
			buffer += PRD_ENTRY_MAX_XFER_SZ;
			len -= PRD_ENTRY_MAX_XFER_SZ;
			prde_count++;
			prde++;
		}
	}

	/* Setup the command slot of cmd hdr */
	cmd_hdr = (cmd_hdr_entry_t *)&sata->cmd_hdr->cmd_slot[tag];

	cmd_hdr->cda = cpu_to_le32((u32)cmd_desc & ~0x3);

	val32 = prde_count << CMD_HDR_PRD_ENTRY_SHIFT;
	val32 |= sizeof(sata_fis_h2d_t);
	cmd_hdr->prde_fis_len = cpu_to_le32(val32);

	cmd_hdr->ttl = cpu_to_le32(ttl);

	if (!is_ncq) {
		val32 = CMD_HDR_ATTR_RES | CMD_HDR_ATTR_SNOOP;
	} else {
		val32 = CMD_HDR_ATTR_RES | CMD_HDR_ATTR_SNOOP | CMD_HDR_ATTR_FPDMA;
	}

	tag &= CMD_HDR_ATTR_TAG;
	val32 |= tag;

	debug("attribute = %08x\n\r", val32);
	cmd_hdr->attribute = cpu_to_le32(val32);

	/* Make sure cmd desc and cmd slot valid before commmand issue */
	sync();

	/* PMP*/
	val32 = (u32)(h2d->pm_port_c & 0x0f);
	out_le32(&reg->cqpmp, val32);

	/* Wait no active */
	if (ata_wait_register(&reg->car, (1 << tag), 0, 10000))
		printf("Wait no active time out\n\r");

	/* Issue command */
	if (!(in_le32(&reg->cqr) & (1 << tag))) {
		val32 = 1 << tag;
		out_le32(&reg->cqr, val32);
	}

	/* Wait command completed for 10s */
	if (ata_wait_register(&reg->ccr, (1 << tag), (1 << tag), 10000)) {
		if (!is_ncq)
			printf("Non-NCQ command time out\n\r");
		else
			printf("NCQ command time out\n\r");
	}

	val32 = in_le32(&reg->cer);

	if (val32) {
		u32 der;
		fsl_sata_dump_sfis((struct sfis *)cmd_desc->sfis);
		printf("CE at device\n\r");
		fsl_sata_dump_regs(reg);
		der = in_le32(&reg->der);
		out_le32(&reg->cer, val32);
		out_le32(&reg->der, der);
	}

	/* Clear complete flags */
	val32 = in_le32(&reg->ccr);
	out_le32(&reg->ccr, val32);

	return len;
}
Esempio n. 4
0
int init_sata(int dev)
{
	u32 length, align;
	cmd_hdr_tbl_t *cmd_hdr;
	u32 cda;
	u32 val32;
	fsl_sata_reg_t *reg;
	u32 sig;
	int i;
	fsl_sata_t *sata;

	if (dev < 0 || dev > (CFG_SATA_MAX_DEVICE - 1)) {
		printf("the sata index %d is out of ranges\n\r", dev);
		return -1;
	}

	/* Allocate SATA device driver struct */
	sata = (fsl_sata_t *)malloc(sizeof(fsl_sata_t));
	if (!sata) {
		printf("alloc the sata device struct failed\n\r");
		return -1;
	}
	/* Zero all of the device driver struct */
	memset((void *)sata, 0, sizeof(fsl_sata_t));

	/* Save the private struct to block device struct */
	sata_dev_desc[dev].priv = (void *)sata;

	sprintf(sata->name, "SATA%d", dev);

	/* Set the controller register base address to device struct */
	reg = (fsl_sata_reg_t *)(fsl_sata_info[dev].sata_reg_base);
	sata->reg_base = reg;

	/* Allocate the command header table, 4 bytes aligned */
	length = sizeof(struct cmd_hdr_tbl);
	align = SATA_HC_CMD_HDR_TBL_ALIGN;
	sata->cmd_hdr_tbl_offset = (void *)malloc(length + align);
	if (!sata) {
		printf("alloc the command header failed\n\r");
		return -1;
	}

	cmd_hdr = (cmd_hdr_tbl_t *)(((u32)sata->cmd_hdr_tbl_offset + align)
						& ~(align - 1));
	sata->cmd_hdr = cmd_hdr;

	/* Zero all of the command header table */
	memset((void *)sata->cmd_hdr_tbl_offset, 0, length + align);

	/* Allocate command descriptor for all command */
	length = sizeof(struct cmd_desc) * SATA_HC_MAX_CMD;
	align = SATA_HC_CMD_DESC_ALIGN;
	sata->cmd_desc_offset = (void *)malloc(length + align);
	if (!sata->cmd_desc_offset) {
		printf("alloc the command descriptor failed\n\r");
		return -1;
	}
	sata->cmd_desc = (cmd_desc_t *)(((u32)sata->cmd_desc_offset + align)
						& ~(align - 1));
	/* Zero all of command descriptor */
	memset((void *)sata->cmd_desc_offset, 0, length + align);

	/* Link the command descriptor to command header */
	for (i = 0; i < SATA_HC_MAX_CMD; i++) {
		cda = ((u32)sata->cmd_desc + SATA_HC_CMD_DESC_SIZE * i)
					 & ~(CMD_HDR_CDA_ALIGN - 1);
		cmd_hdr->cmd_slot[i].cda = cpu_to_le32(cda);
	}

	/* To have safe state, force the controller offline */
	val32 = in_le32(&reg->hcontrol);
	val32 &= ~HCONTROL_ONOFF;
	val32 |= HCONTROL_FORCE_OFFLINE;
	out_le32(&reg->hcontrol, val32);

	/* Wait the controller offline */
	ata_wait_register(&reg->hstatus, HSTATUS_ONOFF, 0, 1000);

	/* Set the command header base address to CHBA register to tell DMA */
	out_le32(&reg->chba, (u32)cmd_hdr & ~0x3);

	/* Snoop for the command header */
	val32 = in_le32(&reg->hcontrol);
	val32 |= HCONTROL_HDR_SNOOP;
	out_le32(&reg->hcontrol, val32);

	/* Disable all of interrupts */
	val32 = in_le32(&reg->hcontrol);
	val32 &= ~HCONTROL_INT_EN_ALL;
	out_le32(&reg->hcontrol, val32);

	/* Clear all of interrupts */
	val32 = in_le32(&reg->hstatus);
	out_le32(&reg->hstatus, val32);

	/* Set the ICC, no interrupt coalescing */
	out_le32(&reg->icc, 0x01000000);

	/* No PM attatched, the SATA device direct connect */
	out_le32(&reg->cqpmp, 0);

	/* Clear SError register */
	val32 = in_le32(&reg->serror);
	out_le32(&reg->serror, val32);

	/* Clear CER register */
	val32 = in_le32(&reg->cer);
	out_le32(&reg->cer, val32);

	/* Clear DER register */
	val32 = in_le32(&reg->der);
	out_le32(&reg->der, val32);

	/* No device detection or initialization action requested */
	out_le32(&reg->scontrol, 0x00000300);

	/* Configure the transport layer, default value */
	out_le32(&reg->transcfg, 0x08000016);

	/* Configure the link layer, default value */
	out_le32(&reg->linkcfg, 0x0000ff34);

	/* Bring the controller online */
	val32 = in_le32(&reg->hcontrol);
	val32 |= HCONTROL_ONOFF;
	out_le32(&reg->hcontrol, val32);

	mdelay(100);

	/* print sata device name */
	if (!dev)
		printf("%s ", sata->name);
	else
		printf("       %s ", sata->name);

	/* Wait PHY RDY signal changed for 500ms */
	ata_wait_register(&reg->hstatus, HSTATUS_PHY_RDY,
			  HSTATUS_PHY_RDY, 500);

	/* Check PHYRDY */
	val32 = in_le32(&reg->hstatus);
	if (val32 & HSTATUS_PHY_RDY) {
		sata->link = 1;
	} else {
		sata->link = 0;
		printf("(No RDY)\n\r");
		return -1;
	}

	/* Wait for signature updated, which is 1st D2H */
	ata_wait_register(&reg->hstatus, HSTATUS_SIGNATURE,
			  HSTATUS_SIGNATURE, 10000);

	if (val32 & HSTATUS_SIGNATURE) {
		sig = in_le32(&reg->sig);
		debug("Signature updated, the sig =%08x\n\r", sig);
		sata->ata_device_type = ata_dev_classify(sig);
	}

	/* Check the speed */
	val32 = in_le32(&reg->sstatus);
	if ((val32 & SSTATUS_SPD_MASK) == SSTATUS_SPD_GEN1)
		printf("(1.5 Gbps)\n\r");
	else if ((val32 & SSTATUS_SPD_MASK) == SSTATUS_SPD_GEN2)
		printf("(3 Gbps)\n\r");

	return 0;
}