drivers/mfd/arizona-core.c

Source file repositories/reference/linux-study-clean/drivers/mfd/arizona-core.c

File Facts

System
Linux kernel
Corpus path
drivers/mfd/arizona-core.c
Extension
.c
Size
34315 bytes
Lines
1434
Domain
Driver Families
Bucket
drivers/mfd
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 arizona_sysclk_state {
	unsigned int fll;
	unsigned int sysclk;
};

static int arizona_enable_freerun_sysclk(struct arizona *arizona,
					 struct arizona_sysclk_state *state)
{
	int ret, err;

	/* Cache existing FLL and SYSCLK settings */
	ret = regmap_read(arizona->regmap, ARIZONA_FLL1_CONTROL_1, &state->fll);
	if (ret) {
		dev_err(arizona->dev, "Failed to cache FLL settings: %d\n",
			ret);
		return ret;
	}
	ret = regmap_read(arizona->regmap, ARIZONA_SYSTEM_CLOCK_1,
			  &state->sysclk);
	if (ret) {
		dev_err(arizona->dev, "Failed to cache SYSCLK settings: %d\n",
			ret);
		return ret;
	}

	/* Start up SYSCLK using the FLL in free running mode */
	ret = regmap_write(arizona->regmap, ARIZONA_FLL1_CONTROL_1,
			ARIZONA_FLL1_ENA | ARIZONA_FLL1_FREERUN);
	if (ret) {
		dev_err(arizona->dev,
			"Failed to start FLL in freerunning mode: %d\n",
			ret);
		return ret;
	}
	ret = arizona_poll_reg(arizona, 180, ARIZONA_INTERRUPT_RAW_STATUS_5,
			       ARIZONA_FLL1_CLOCK_OK_STS,
			       ARIZONA_FLL1_CLOCK_OK_STS);
	if (ret)
		goto err_fll;

	ret = regmap_write(arizona->regmap, ARIZONA_SYSTEM_CLOCK_1, 0x0144);
	if (ret) {
		dev_err(arizona->dev, "Failed to start SYSCLK: %d\n", ret);
		goto err_fll;
	}

	return 0;

err_fll:
	err = regmap_write(arizona->regmap, ARIZONA_FLL1_CONTROL_1, state->fll);
	if (err)
		dev_err(arizona->dev,
			"Failed to re-apply old FLL settings: %d\n", err);

	return ret;
}

static int arizona_disable_freerun_sysclk(struct arizona *arizona,
					  struct arizona_sysclk_state *state)
{
	int ret;

	ret = regmap_write(arizona->regmap, ARIZONA_SYSTEM_CLOCK_1,
			   state->sysclk);
	if (ret) {
		dev_err(arizona->dev,
			"Failed to re-apply old SYSCLK settings: %d\n", ret);
		return ret;
	}

	ret = regmap_write(arizona->regmap, ARIZONA_FLL1_CONTROL_1, state->fll);
	if (ret) {
		dev_err(arizona->dev,
			"Failed to re-apply old FLL settings: %d\n", ret);
		return ret;
	}

	return 0;
}

static int wm5102_apply_hardware_patch(struct arizona *arizona)
{
	struct arizona_sysclk_state state;
	int err, ret;

	ret = arizona_enable_freerun_sysclk(arizona, &state);
	if (ret)
		return ret;

	/* Start the write sequencer and wait for it to finish */

Annotation

Implementation Notes