drivers/crypto/intel/keembay/keembay-ocs-ecc.c

Source file repositories/reference/linux-study-clean/drivers/crypto/intel/keembay/keembay-ocs-ecc.c

File Facts

System
Linux kernel
Corpus path
drivers/crypto/intel/keembay/keembay-ocs-ecc.c
Extension
.c
Size
26768 bytes
Lines
999
Domain
Driver Families
Bucket
drivers/crypto
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

struct ocs_ecc_dev {
	struct list_head list;
	struct device *dev;
	void __iomem *base_reg;
	struct crypto_engine *engine;
	struct completion irq_done;
	int irq;
};

/**
 * struct ocs_ecc_ctx - Transformation context.
 * @ecc_dev:	 The ECC driver associated with this context.
 * @curve:	 The elliptic curve used by this transformation.
 * @private_key: The private key.
 */
struct ocs_ecc_ctx {
	struct ocs_ecc_dev *ecc_dev;
	const struct ecc_curve *curve;
	u64 private_key[KMB_ECC_VLI_MAX_DIGITS];
};

/* Driver data. */
struct ocs_ecc_drv {
	struct list_head dev_list;
	spinlock_t lock;	/* Protects dev_list. */
};

/* Global variable holding the list of OCS ECC devices (only one expected). */
static struct ocs_ecc_drv ocs_ecc = {
	.dev_list = LIST_HEAD_INIT(ocs_ecc.dev_list),
	.lock = __SPIN_LOCK_UNLOCKED(ocs_ecc.lock),
};

/* Get OCS ECC tfm context from kpp_request. */
static inline struct ocs_ecc_ctx *kmb_ocs_ecc_tctx(struct kpp_request *req)
{
	return kpp_tfm_ctx(crypto_kpp_reqtfm(req));
}

/* Converts number of digits to number of bytes. */
static inline unsigned int digits_to_bytes(unsigned int n)
{
	return n << ECC_DIGITS_TO_BYTES_SHIFT;
}

/*
 * Wait for ECC idle i.e when an operation (other than write operations)
 * is done.
 */
static inline int ocs_ecc_wait_idle(struct ocs_ecc_dev *dev)
{
	u32 value;

	return readl_poll_timeout((dev->base_reg + HW_OFFS_OCS_ECC_STATUS),
				  value,
				  !(value & HW_OCS_ECC_ISR_INT_STATUS_DONE),
				  POLL_USEC, TIMEOUT_USEC);
}

static void ocs_ecc_cmd_start(struct ocs_ecc_dev *ecc_dev, u32 op_size)
{
	iowrite32(op_size | HW_OCS_ECC_COMMAND_START_VAL,
		  ecc_dev->base_reg + HW_OFFS_OCS_ECC_COMMAND);
}

/* Direct write of u32 buffer to ECC engine with associated instruction. */
static void ocs_ecc_write_cmd_and_data(struct ocs_ecc_dev *dev,
				       u32 op_size,
				       u32 inst,
				       const void *data_in,
				       size_t data_size)
{
	iowrite32(op_size | inst, dev->base_reg + HW_OFFS_OCS_ECC_COMMAND);

	/* MMIO Write src uint32 to dst. */
	memcpy_toio(dev->base_reg + HW_OFFS_OCS_ECC_DATA_IN, data_in,
		    data_size);
}

/* Start OCS ECC operation and wait for its completion. */
static int ocs_ecc_trigger_op(struct ocs_ecc_dev *ecc_dev, u32 op_size,
			      u32 inst)
{
	reinit_completion(&ecc_dev->irq_done);

	iowrite32(ECC_ENABLE_INTR, ecc_dev->base_reg + HW_OFFS_OCS_ECC_IER);
	iowrite32(op_size | inst, ecc_dev->base_reg + HW_OFFS_OCS_ECC_COMMAND);

	return wait_for_completion_interruptible(&ecc_dev->irq_done);
}

Annotation

Implementation Notes