drivers/clk/renesas/clk-mstp.c

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

File Facts

System
Linux kernel
Corpus path
drivers/clk/renesas/clk-mstp.c
Extension
.c
Size
8162 bytes
Lines
347
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

struct mstp_clock_group {
	struct clk_onecell_data data;
	void __iomem *smstpcr;
	void __iomem *mstpsr;
	spinlock_t lock;
	bool width_8bit;
	struct clk *clks[];
};

/**
 * struct mstp_clock - MSTP gating clock
 * @hw: handle between common and hardware-specific interfaces
 * @bit_index: control bit index
 * @group: MSTP clocks group
 */
struct mstp_clock {
	struct clk_hw hw;
	u32 bit_index;
	struct mstp_clock_group *group;
};

#define to_mstp_clock(_hw) container_of(_hw, struct mstp_clock, hw)

static inline u32 cpg_mstp_read(struct mstp_clock_group *group,
				u32 __iomem *reg)
{
	return group->width_8bit ? readb(reg) : readl(reg);
}

static inline void cpg_mstp_write(struct mstp_clock_group *group, u32 val,
				  u32 __iomem *reg)
{
	group->width_8bit ? writeb(val, reg) : writel(val, reg);
}

static int cpg_mstp_clock_endisable(struct clk_hw *hw, bool enable)
{
	struct mstp_clock *clock = to_mstp_clock(hw);
	struct mstp_clock_group *group = clock->group;
	u32 bitmask = BIT(clock->bit_index);
	unsigned long flags;
	u32 value;
	int ret;

	spin_lock_irqsave(&group->lock, flags);

	value = cpg_mstp_read(group, group->smstpcr);
	if (enable)
		value &= ~bitmask;
	else
		value |= bitmask;
	cpg_mstp_write(group, value, group->smstpcr);

	if (!group->mstpsr) {
		/* dummy read to ensure write has completed */
		cpg_mstp_read(group, group->smstpcr);
		barrier_data(group->smstpcr);
	}

	spin_unlock_irqrestore(&group->lock, flags);

	if (!enable || !group->mstpsr)
		return 0;

	/* group->width_8bit is always false if group->mstpsr is present */
	ret = readl_poll_timeout_atomic(group->mstpsr, value,
					!(value & bitmask), 0, 10);
	if (ret)
		pr_err("%s: failed to enable %p[%d]\n", __func__,
		       group->smstpcr, clock->bit_index);

	return ret;
}

static int cpg_mstp_clock_enable(struct clk_hw *hw)
{
	return cpg_mstp_clock_endisable(hw, true);
}

static void cpg_mstp_clock_disable(struct clk_hw *hw)
{
	cpg_mstp_clock_endisable(hw, false);
}

static int cpg_mstp_clock_is_enabled(struct clk_hw *hw)
{
	struct mstp_clock *clock = to_mstp_clock(hw);
	struct mstp_clock_group *group = clock->group;
	u32 value;

Annotation

Implementation Notes