drivers/ufs/host/ufs-sprd.c

Source file repositories/reference/linux-study-clean/drivers/ufs/host/ufs-sprd.c

File Facts

System
Linux kernel
Corpus path
drivers/ufs/host/ufs-sprd.c
Extension
.c
Size
11566 bytes
Lines
451
Domain
Driver Families
Bucket
drivers/ufs
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

if (ufshcd_is_auto_hibern8_supported(hba)) {
			spin_lock_irqsave(hba->host->host_lock, flags);
			ufshcd_writel(hba, 0, REG_AUTO_HIBERNATE_IDLE_TIMER);
			spin_unlock_irqrestore(hba->host->host_lock, flags);
		}
	}

	return 0;
}

static void ufs_sprd_n6_host_reset(struct ufs_hba *hba)
{
	struct ufs_sprd_priv *priv = ufs_sprd_get_priv_data(hba);

	dev_info(hba->dev, "ufs host reset!\n");

	reset_control_assert(priv->rci[SPRD_UFSHCI_SOFT_RST].rc);
	usleep_range(1000, 1100);
	reset_control_deassert(priv->rci[SPRD_UFSHCI_SOFT_RST].rc);
}

static int ufs_sprd_n6_device_reset(struct ufs_hba *hba)
{
	struct ufs_sprd_priv *priv = ufs_sprd_get_priv_data(hba);

	dev_info(hba->dev, "ufs device reset!\n");

	reset_control_assert(priv->rci[SPRD_UFS_DEV_RST].rc);
	usleep_range(1000, 1100);
	reset_control_deassert(priv->rci[SPRD_UFS_DEV_RST].rc);

	return 0;
}

static void ufs_sprd_n6_key_acc_enable(struct ufs_hba *hba)
{
	u32 val;
	u32 retry = 10;
	struct arm_smccc_res res;

check_hce:
	/* Key access only can be enabled under HCE enable */
	val = ufshcd_readl(hba, REG_CONTROLLER_ENABLE);
	if (!(val & CONTROLLER_ENABLE)) {
		ufs_sprd_n6_host_reset(hba);
		val |= CONTROLLER_ENABLE;
		ufshcd_writel(hba, val, REG_CONTROLLER_ENABLE);
		usleep_range(1000, 1100);
		if (retry) {
			retry--;
			goto check_hce;
		}
		goto disable_crypto;
	}

	arm_smccc_smc(SPRD_SIP_SVC_STORAGE_UFS_CRYPTO_ENABLE,
		      0, 0, 0, 0, 0, 0, 0, &res);
	if (!res.a0)
		return;

disable_crypto:
	dev_err(hba->dev, "key reg access enable fail, disable crypto\n");
	hba->caps &= ~UFSHCD_CAP_CRYPTO;
}

static int ufs_sprd_n6_init(struct ufs_hba *hba)
{
	struct ufs_sprd_priv *priv;
	int ret = 0;

	ret = ufs_sprd_common_init(hba);
	if (ret != 0)
		return ret;

	priv = ufs_sprd_get_priv_data(hba);

	ret = regulator_enable(priv->vregi[SPRD_UFS_VDD_MPHY].vreg);
	if (ret)
		return -ENODEV;

	if (hba->caps & UFSHCD_CAP_CRYPTO)
		ufs_sprd_n6_key_acc_enable(hba);

	return 0;
}

static int ufs_sprd_n6_phy_init(struct ufs_hba *hba)
{
	int ret = 0;
	uint32_t val = 0;

Annotation

Implementation Notes