drivers/soc/qcom/ice.c

Source file repositories/reference/linux-study-clean/drivers/soc/qcom/ice.c

File Facts

System
Linux kernel
Corpus path
drivers/soc/qcom/ice.c
Extension
.c
Size
24131 bytes
Lines
791
Domain
Driver Families
Bucket
drivers/soc
Inferred role
Driver Families: exported/initcall integration point
Status
integration 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

struct qcom_ice {
	struct device *dev;
	void __iomem *base;

	struct clk *core_clk;
	struct clk *iface_clk;
	bool use_hwkm;
	bool hwkm_init_complete;
	u8 hwkm_version;
};

static DEFINE_XARRAY(ice_handles);
static DEFINE_MUTEX(ice_mutex);

static bool qcom_ice_check_supported(struct qcom_ice *ice)
{
	u32 regval = qcom_ice_readl(ice, QCOM_ICE_REG_VERSION);
	struct device *dev = ice->dev;
	int major = FIELD_GET(GENMASK(31, 24), regval);
	int minor = FIELD_GET(GENMASK(23, 16), regval);
	int step = FIELD_GET(GENMASK(15, 0), regval);

	/* For now this driver only supports ICE version 3 and 4. */
	if (major != 3 && major != 4) {
		dev_warn(dev, "Unsupported ICE version: v%d.%d.%d\n",
			 major, minor, step);
		return false;
	}

	/* HWKM version v2 is present from ICE 3.2.1 onwards while version v1
	 * is present only in ICE 3.2.0. Earlier ICE version don't have HWKM.
	 */
	if (major > 3 ||
	   (major == 3 && (minor >= 3 || (minor == 2 && step >= 1))))
		ice->hwkm_version = QCOM_ICE_HWKM_V2;
	else if ((major == 3) && (minor == 2))
		ice->hwkm_version = QCOM_ICE_HWKM_V1;
	else
		ice->hwkm_version = 0;

	dev_info(dev, "Found QC Inline Crypto Engine (ICE) v%d.%d.%d\n",
		 major, minor, step);

	if (ice->hwkm_version)
		dev_info(dev, "QC Hardware Key Manager (HWKM) version v%d\n",
			 ice->hwkm_version);

	/* If fuses are blown, ICE might not work in the standard way. */
	regval = qcom_ice_readl(ice, QCOM_ICE_REG_FUSE_SETTING);
	if (regval & (QCOM_ICE_FUSE_SETTING_MASK |
		      QCOM_ICE_FORCE_HW_KEY0_SETTING_MASK |
		      QCOM_ICE_FORCE_HW_KEY1_SETTING_MASK)) {
		dev_warn(dev, "Fuses are blown; ICE is unusable!\n");
		return false;
	}

	/*
	 * Check for HWKM support and decide whether to use it or not.  ICE
	 * v3.2.1 and later have HWKM v2.  ICE v3.2.0 has HWKM v1.  Earlier ICE
	 * versions don't have HWKM at all.  However, for HWKM to be fully
	 * usable by Linux, the TrustZone software also needs to support certain
	 * SCM calls including the ones to generate and prepare keys. Support
	 * for these SCM calls is present for SoCs with HWKM v2 and is being
	 * added for SoCs with HWKM v1 as well but not every SoC with HWKM v1
	 * currently supports this. So, this driver checks for the SCM call
	 * support before it decides to use HWKM.
	 *
	 * Also, since HWKM and legacy mode are mutually exclusive, and
	 * ICE-capable storage driver(s) need to know early on whether to
	 * advertise support for raw keys or wrapped keys, HWKM cannot be used
	 * unconditionally.  A module parameter is used to opt into using it.
	 */
	if (ice->hwkm_version && qcom_scm_has_wrapped_key_support()) {
		if (qcom_ice_use_wrapped_keys) {
			dev_info(dev, "Using HWKM. Supporting wrapped keys only.\n");
			ice->use_hwkm = true;
		} else {
			dev_info(dev, "Not using HWKM. Supporting raw keys only.\n");
		}
	} else if (qcom_ice_use_wrapped_keys) {
		dev_warn(dev, "A supported HWKM is not present. Ignoring qcom_ice.use_wrapped_keys=1.\n");
	} else {
		dev_info(dev, "A supported HWKM is not present. Supporting raw keys only.\n");
	}
	return true;
}

static void qcom_ice_low_power_mode_enable(struct qcom_ice *ice)
{
	u32 regval;

Annotation

Implementation Notes