static bool inject_fatal_err_tm(struct ufs_hba *hba, u8 ocs_err)
{
	int tag;

	tag = find_first_bit(&hba->outstanding_tasks, hba->nutmrs);
	if (tag == hba->nutmrs)
		return 0;

	ufshcd_writel(hba, ~(1 << tag), REG_UTP_TASK_REQ_LIST_CLEAR);
	(&hba->utmrdl_base_addr[tag])->header.dword_2 =
						cpu_to_be32(ocs_err);

	/* fatal error injected */
	return 1;
}
static bool inject_fatal_err_tr(struct ufs_hba *hba, u8 ocs_err)
{
	int tag;

	tag = find_first_bit(&hba->outstanding_reqs, hba->nutrs);
	if (tag == hba->nutrs)
		return 0;

	ufshcd_writel(hba, ~(1 << tag), REG_UTP_TRANSFER_REQ_LIST_CLEAR);
	(&hba->lrb[tag])->utr_descriptor_ptr->header.dword_2 =
							cpu_to_be32(ocs_err);

	/* fatal error injected */
	return 1;
}
Example #3
0
/**
 * ufshcd_dwc_program_clk_div()
 * This function programs the clk divider value. This value is needed to
 * provide 1 microsecond tick to unipro layer.
 * @hba: Private Structure pointer
 * @divider_val: clock divider value to be programmed
 *
 */
static void ufshcd_dwc_program_clk_div(struct ufs_hba *hba, u32 divider_val)
{
	ufshcd_writel(hba, divider_val, DWC_UFS_REG_HCLKDIV);
}
Example #4
0
/**
 * ufs_qcom_ice_cfg() - configures UFS's ICE registers for an ICE transaction
 * @qcom_host:	Pointer to a UFS QCom internal host structure.
 *		qcom_host, qcom_host->hba and qcom_host->hba->dev should all
 *		be valid pointers.
 * @cmd:	Pointer to a valid scsi command. cmd->request should also be
 *              a valid pointer.
 *
 * Return: -EINVAL in-case of an error
 *         0 otherwise
 */
int ufs_qcom_ice_cfg(struct ufs_qcom_host *qcom_host, struct scsi_cmnd *cmd)
{
	struct device *dev = qcom_host->hba->dev;
	int err = 0;
	struct ice_data_setting ice_set;
	unsigned int slot = 0;
	sector_t lba = 0;
	unsigned int ctrl_info_2_val = 0;
	unsigned int bypass = 0;
	struct request *req;
	char cmd_op;

	if (!qcom_host->ice.pdev || !qcom_host->ice.vops) {
		dev_dbg(dev, "%s: ice device is not enabled\n", __func__);
		goto out;
	}

	if (qcom_host->ice.state != UFS_QCOM_ICE_STATE_ACTIVE) {
		dev_err(dev, "%s: ice state (%d) is not active\n",
			__func__, qcom_host->ice.state);
		return -EINVAL;
	}

	req = cmd->request;
	if (req->bio)
		lba = req->bio->bi_sector;

	slot = req->tag;
	if (slot < 0 || slot > qcom_host->hba->nutrs) {
		dev_err(dev, "%s: slot (%d) is out of boundaries (0...%d)\n",
			__func__, slot, qcom_host->hba->nutrs);
		return -EINVAL;
	}

	memset(&ice_set, 0, sizeof(ice_set));
	if (qcom_host->ice.vops->config) {
		err = qcom_host->ice.vops->config(qcom_host->ice.pdev,
							req, &ice_set);

		if (err) {
			dev_err(dev, "%s: error in ice_vops->config %d\n",
				__func__, err);
			goto out;
		}
	}

	cmd_op = cmd->cmnd[0];

#define UFS_QCOM_DIR_WRITE	true
#define UFS_QCOM_DIR_READ	false
	/* if non data command, bypass shall be enabled */
	if (!ufs_qcom_is_data_cmd(cmd_op, UFS_QCOM_DIR_WRITE) &&
	    !ufs_qcom_is_data_cmd(cmd_op, UFS_QCOM_DIR_READ))
		bypass = UFS_QCOM_ICE_ENABLE_BYPASS;
	/* if writing data command */
	else if (ufs_qcom_is_data_cmd(cmd_op, UFS_QCOM_DIR_WRITE))
		bypass = ice_set.encr_bypass ? UFS_QCOM_ICE_ENABLE_BYPASS :
						UFS_QCOM_ICE_DISABLE_BYPASS;
	/* if reading data command */
	else if (ufs_qcom_is_data_cmd(cmd_op, UFS_QCOM_DIR_READ))
		bypass = ice_set.decr_bypass ? UFS_QCOM_ICE_ENABLE_BYPASS :
						UFS_QCOM_ICE_DISABLE_BYPASS;

	/* Configure ICE index */
	ctrl_info_2_val =
		(ice_set.crypto_data.key_index &
		 MASK_UFS_QCOM_ICE_CTRL_INFO_2_KEY_INDEX)
		 << OFFSET_UFS_QCOM_ICE_CTRL_INFO_2_KEY_INDEX;

	/* Configure data unit size of transfer request */
	ctrl_info_2_val |=
		(UFS_QCOM_ICE_TR_DATA_UNIT_4_KB &
		 MASK_UFS_QCOM_ICE_CTRL_INFO_2_CDU)
		 << OFFSET_UFS_QCOM_ICE_CTRL_INFO_2_CDU;

	/* Configure ICE bypass mode */
	ctrl_info_2_val |=
		(bypass & MASK_UFS_QCOM_ICE_CTRL_INFO_2_BYPASS)
		 << OFFSET_UFS_QCOM_ICE_CTRL_INFO_2_BYPASS;

	ufshcd_writel(qcom_host->hba, lba,
		     (REG_UFS_QCOM_ICE_CTRL_INFO_1_n + 8 * slot));

	ufshcd_writel(qcom_host->hba, ctrl_info_2_val,
		     (REG_UFS_QCOM_ICE_CTRL_INFO_2_n + 8 * slot));

	/*
	 * Ensure UFS-ICE registers are being configured
	 * before next operation, otherwise UFS Host Controller might
	 * set get errors
	 */
	mb();
out:
	return err;
}