drivers/clk/ti/clk.c

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

File Facts

System
Linux kernel
Corpus path
drivers/clk/ti/clk.c
Extension
.c
Size
16717 bytes
Lines
691
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_iomap {
	struct regmap *regmap;
	void __iomem *mem;
};

static struct clk_iomap *clk_memmaps[CLK_MAX_MEMMAPS];

static void clk_memmap_writel(u32 val, const struct clk_omap_reg *reg)
{
	struct clk_iomap *io = clk_memmaps[reg->index];

	if (reg->ptr)
		writel_relaxed(val, reg->ptr);
	else if (io->regmap)
		regmap_write(io->regmap, reg->offset, val);
	else
		writel_relaxed(val, io->mem + reg->offset);
}

static void _clk_rmw(u32 val, u32 mask, void __iomem *ptr)
{
	u32 v;

	v = readl_relaxed(ptr);
	v &= ~mask;
	v |= val;
	writel_relaxed(v, ptr);
}

static void clk_memmap_rmw(u32 val, u32 mask, const struct clk_omap_reg *reg)
{
	struct clk_iomap *io = clk_memmaps[reg->index];

	if (reg->ptr) {
		_clk_rmw(val, mask, reg->ptr);
	} else if (io->regmap) {
		regmap_update_bits(io->regmap, reg->offset, mask, val);
	} else {
		_clk_rmw(val, mask, io->mem + reg->offset);
	}
}

static u32 clk_memmap_readl(const struct clk_omap_reg *reg)
{
	u32 val;
	struct clk_iomap *io = clk_memmaps[reg->index];

	if (reg->ptr)
		val = readl_relaxed(reg->ptr);
	else if (io->regmap)
		regmap_read(io->regmap, reg->offset, &val);
	else
		val = readl_relaxed(io->mem + reg->offset);

	return val;
}

/**
 * ti_clk_setup_ll_ops - setup low level clock operations
 * @ops: low level clock ops descriptor
 *
 * Sets up low level clock operations for TI clock driver. This is used
 * to provide various callbacks for the clock driver towards platform
 * specific code. Returns 0 on success, -EBUSY if ll_ops have been
 * registered already.
 */
int ti_clk_setup_ll_ops(struct ti_clk_ll_ops *ops)
{
	if (ti_clk_ll_ops) {
		pr_err("Attempt to register ll_ops multiple times.\n");
		return -EBUSY;
	}

	ti_clk_ll_ops = ops;
	ops->clk_readl = clk_memmap_readl;
	ops->clk_writel = clk_memmap_writel;
	ops->clk_rmw = clk_memmap_rmw;

	return 0;
}

/*
 * Eventually we could standardize to using '_' for clk-*.c files to follow the
 * TRM naming.
 */
static struct device_node *ti_find_clock_provider(const char *name)
{
	char *tmp __free(kfree) = NULL;
	struct device_node *np;
	char *p;

Annotation

Implementation Notes