drivers/clk/clk-vt8500.c

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

File Facts

System
Linux kernel
Corpus path
drivers/clk/clk-vt8500.c
Extension
.c
Size
18383 bytes
Lines
756
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_device {
	struct clk_hw	hw;
	void __iomem	*div_reg;
	unsigned int	div_mask;
	void __iomem	*en_reg;
	int		en_bit;
	spinlock_t	*lock;
};

/*
 * Add new PLL_TYPE_x definitions here as required. Use the first known model
 * to support the new type as the name.
 * Add case statements to vtwm_pll_recalc_rate(), vtwm_pll_round_round() and
 * vtwm_pll_set_rate() to handle the new PLL_TYPE_x
 */

#define PLL_TYPE_VT8500		0
#define PLL_TYPE_WM8650		1
#define PLL_TYPE_WM8750		2
#define PLL_TYPE_WM8850		3

struct clk_pll {
	struct clk_hw	hw;
	void __iomem	*reg;
	spinlock_t	*lock;
	int		type;
};

static void __iomem *pmc_base;

static __init void vtwm_set_pmc_base(void)
{
	struct device_node *np =
		of_find_compatible_node(NULL, NULL, "via,vt8500-pmc");

	if (np)
		pmc_base = of_iomap(np, 0);
	else
		pmc_base = ioremap(LEGACY_PMC_BASE, 0x1000);
	of_node_put(np);

	if (!pmc_base)
		pr_err("%s:of_iomap(pmc) failed\n", __func__);
}

#define to_clk_device(_hw) container_of(_hw, struct clk_device, hw)

#define VT8500_PMC_BUSY_MASK		0x18

static void vt8500_pmc_wait_busy(void)
{
	while (readl(pmc_base) & VT8500_PMC_BUSY_MASK)
		cpu_relax();
}

static int vt8500_dclk_enable(struct clk_hw *hw)
{
	struct clk_device *cdev = to_clk_device(hw);
	u32 en_val;
	unsigned long flags = 0;

	spin_lock_irqsave(cdev->lock, flags);

	en_val = readl(cdev->en_reg);
	en_val |= BIT(cdev->en_bit);
	writel(en_val, cdev->en_reg);

	spin_unlock_irqrestore(cdev->lock, flags);
	return 0;
}

static void vt8500_dclk_disable(struct clk_hw *hw)
{
	struct clk_device *cdev = to_clk_device(hw);
	u32 en_val;
	unsigned long flags = 0;

	spin_lock_irqsave(cdev->lock, flags);

	en_val = readl(cdev->en_reg);
	en_val &= ~BIT(cdev->en_bit);
	writel(en_val, cdev->en_reg);

	spin_unlock_irqrestore(cdev->lock, flags);
}

static int vt8500_dclk_is_enabled(struct clk_hw *hw)
{
	struct clk_device *cdev = to_clk_device(hw);
	u32 en_val = (readl(cdev->en_reg) & BIT(cdev->en_bit));

Annotation

Implementation Notes