drivers/reset/reset-eyeq.c

Source file repositories/reference/linux-study-clean/drivers/reset/reset-eyeq.c

File Facts

System
Linux kernel
Corpus path
drivers/reset/reset-eyeq.c
Extension
.c
Size
16411 bytes
Lines
593
Domain
Driver Families
Bucket
drivers/reset
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 eqr_busy_wait_timings {
	unsigned long sleep_us;
	unsigned long timeout_us;
};

static const struct eqr_busy_wait_timings eqr_timings[] = {
	[EQR_EYEQ5_SARCR]	= {1, 10},
	[EQR_EYEQ5_ACRP]	= {1, 40 * USEC_PER_MSEC}, /* LBIST implies long timeout. */
	/* EQR_EYEQ5_PCIE does no busy waiting. */
	[EQR_EYEQ6H_SARCR]	= {1, 400},
};

#define EQR_MAX_DOMAIN_COUNT 3

struct eqr_domain_descriptor {
	enum eqr_domain_type	type;
	u32			valid_mask;
	unsigned int		offset;
};

struct eqr_match_data {
	unsigned int				domain_count;
	const struct eqr_domain_descriptor	*domains;
};

struct eqr_private {
	/*
	 * One mutex per domain for read-modify-write operations on registers.
	 * Some domains can be involved in LBIST which implies long critical
	 * sections; we wouldn't want other domains to be impacted by that.
	 */
	struct mutex			mutexes[EQR_MAX_DOMAIN_COUNT];
	void __iomem			*base;
	const struct eqr_match_data	*data;
	struct reset_controller_dev	rcdev;
};

static inline struct eqr_private *eqr_rcdev_to_priv(struct reset_controller_dev *x)
{
	return container_of(x, struct eqr_private, rcdev);
}

static u32 eqr_double_readl(void __iomem *addr_a, void __iomem *addr_b,
			    u32 *dest_a, u32 *dest_b)
{
	*dest_a = readl(addr_a);
	*dest_b = readl(addr_b);
	return 0; /* read_poll_timeout() op argument must return something. */
}

static int eqr_busy_wait_locked(struct eqr_private *priv, struct device *dev,
				u32 domain, u32 offset, bool assert)
{
	void __iomem *base = priv->base + priv->data->domains[domain].offset;
	enum eqr_domain_type domain_type = priv->data->domains[domain].type;
	unsigned long timeout_us = eqr_timings[domain_type].timeout_us;
	unsigned long sleep_us = eqr_timings[domain_type].sleep_us;
	u32 val, mask, rst_status, clk_status;
	void __iomem *reg;
	int ret;

	lockdep_assert_held(&priv->mutexes[domain]);

	switch (domain_type) {
	case EQR_EYEQ5_SARCR:
		reg = base + EQR_EYEQ5_SARCR_STATUS;
		mask = BIT(offset);

		ret = readl_poll_timeout(reg, val, !(val & mask) == assert,
					 sleep_us, timeout_us);
		break;

	case EQR_EYEQ5_ACRP:
		reg = base + 4 * offset;
		if (assert)
			mask = EQR_EYEQ5_ACRP_ST_POWER_DOWN;
		else
			mask = EQR_EYEQ5_ACRP_ST_ACTIVE;

		ret = readl_poll_timeout(reg, val, !!(val & mask),
					 sleep_us, timeout_us);
		break;

	case EQR_EYEQ5_PCIE:
		ret = 0; /* No busy waiting. */
		break;

	case EQR_EYEQ6H_SARCR:
		/*
		 * Wait until both bits change:

Annotation

Implementation Notes