drivers/clk/qcom/gdsc.c

Source file repositories/reference/linux-study-clean/drivers/clk/qcom/gdsc.c

File Facts

System
Linux kernel
Corpus path
drivers/clk/qcom/gdsc.c
Extension
.c
Size
16441 bytes
Lines
678
Domain
Driver Families
Bucket
drivers/clk
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

switch (status) {
		case GDSC_ON:
			return !!(val & GDSC_POWER_UP_COMPLETE);
		case GDSC_OFF:
			return !!(val & GDSC_POWER_DOWN_COMPLETE);
		}
	}

	switch (status) {
	case GDSC_ON:
		return !!(val & PWR_ON_MASK);
	case GDSC_OFF:
		return !(val & PWR_ON_MASK);
	}

	return -EINVAL;
}

static int gdsc_hwctrl(struct gdsc *sc, bool en)
{
	u32 val = en ? HW_CONTROL_MASK : 0;

	return regmap_update_bits(sc->regmap, sc->gdscr, HW_CONTROL_MASK, val);
}

static int gdsc_poll_status(struct gdsc *sc, enum gdsc_status status)
{
	ktime_t start;

	start = ktime_get();
	do {
		if (gdsc_check_status(sc, status))
			return 0;
	} while (ktime_us_delta(ktime_get(), start) < STATUS_POLL_TIMEOUT_US);

	if (gdsc_check_status(sc, status))
		return 0;

	return -ETIMEDOUT;
}

static int gdsc_update_collapse_bit(struct gdsc *sc, bool val)
{
	u32 reg, mask;
	int ret;

	if (sc->collapse_mask) {
		reg = sc->collapse_ctrl;
		mask = sc->collapse_mask;
	} else {
		reg = sc->gdscr;
		mask = SW_COLLAPSE_MASK;
	}

	ret = regmap_update_bits(sc->regmap, reg, mask, val ? mask : 0);
	if (ret)
		return ret;

	return 0;
}

static int gdsc_toggle_logic(struct gdsc *sc, enum gdsc_status status,
		bool wait)
{
	int ret;

	if (status == GDSC_ON && sc->rsupply) {
		ret = regulator_enable(sc->rsupply);
		if (ret < 0)
			return ret;
	}

	ret = gdsc_update_collapse_bit(sc, status == GDSC_OFF);

	/* If disabling votable gdscs, don't poll on status */
	if ((sc->flags & VOTABLE) && status == GDSC_OFF && !wait) {
		/*
		 * Add a short delay here to ensure that an enable
		 * right after it was disabled does not put it in an
		 * unknown state
		 */
		udelay(TIMEOUT_US);
		return 0;
	}

	if (sc->gds_hw_ctrl) {
		/*
		 * The gds hw controller asserts/de-asserts the status bit soon
		 * after it receives a power on/off request from a master.
		 * The controller then takes around 8 xo cycles to start its

Annotation

Implementation Notes