drivers/clk/nxp/clk-lpc18xx-creg.c

Source file repositories/reference/linux-study-clean/drivers/clk/nxp/clk-lpc18xx-creg.c

File Facts

System
Linux kernel
Corpus path
drivers/clk/nxp/clk-lpc18xx-creg.c
Extension
.c
Size
5588 bytes
Lines
226
Domain
Driver Families
Bucket
drivers/clk
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 clk_creg_data {
	struct clk_hw hw;
	const char *name;
	struct regmap *reg;
	unsigned int en_mask;
	const struct clk_ops *ops;
};

#define CREG_CLK(_name, _emask, _ops)		\
{						\
	.name = _name,				\
	.en_mask = LPC18XX_CREG_CREG0_##_emask,	\
	.ops = &_ops,				\
}

static int clk_creg_32k_prepare(struct clk_hw *hw)
{
	struct clk_creg_data *creg = to_clk_creg(hw);
	int ret;

	ret = regmap_update_bits(creg->reg, LPC18XX_CREG_CREG0,
				 LPC18XX_CREG_CREG0_PD32KHZ |
				 LPC18XX_CREG_CREG0_RESET32KHZ, 0);

	/*
	 * Powering up the 32k oscillator takes a long while
	 * and sadly there aren't any status bit to poll.
	 */
	msleep(2500);

	return ret;
}

static void clk_creg_32k_unprepare(struct clk_hw *hw)
{
	struct clk_creg_data *creg = to_clk_creg(hw);

	regmap_update_bits(creg->reg, LPC18XX_CREG_CREG0,
			   LPC18XX_CREG_CREG0_PD32KHZ,
			   LPC18XX_CREG_CREG0_PD32KHZ);
}

static int clk_creg_32k_is_prepared(struct clk_hw *hw)
{
	struct clk_creg_data *creg = to_clk_creg(hw);
	u32 reg;

	regmap_read(creg->reg, LPC18XX_CREG_CREG0, &reg);

	return !(reg & LPC18XX_CREG_CREG0_PD32KHZ) &&
	       !(reg & LPC18XX_CREG_CREG0_RESET32KHZ);
}

static unsigned long clk_creg_1k_recalc_rate(struct clk_hw *hw,
					     unsigned long parent_rate)
{
	return parent_rate / 32;
}

static int clk_creg_enable(struct clk_hw *hw)
{
	struct clk_creg_data *creg = to_clk_creg(hw);

	return regmap_update_bits(creg->reg, LPC18XX_CREG_CREG0,
				  creg->en_mask, creg->en_mask);
}

static void clk_creg_disable(struct clk_hw *hw)
{
	struct clk_creg_data *creg = to_clk_creg(hw);

	regmap_update_bits(creg->reg, LPC18XX_CREG_CREG0,
			   creg->en_mask, 0);
}

static int clk_creg_is_enabled(struct clk_hw *hw)
{
	struct clk_creg_data *creg = to_clk_creg(hw);
	u32 reg;

	regmap_read(creg->reg, LPC18XX_CREG_CREG0, &reg);

	return !!(reg & creg->en_mask);
}

static const struct clk_ops clk_creg_32k = {
	.enable		= clk_creg_enable,
	.disable	= clk_creg_disable,
	.is_enabled	= clk_creg_is_enabled,
	.prepare	= clk_creg_32k_prepare,

Annotation

Implementation Notes