drivers/clk/sunxi/clk-a10-pll2.c

Source file repositories/reference/linux-study-clean/drivers/clk/sunxi/clk-a10-pll2.c

File Facts

System
Linux kernel
Corpus path
drivers/clk/sunxi/clk-a10-pll2.c
Extension
.c
Size
5217 bytes
Lines
196
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

// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * Copyright 2013 Emilio López
 * Emilio López <emilio@elopez.com.ar>
 *
 * Copyright 2015 Maxime Ripard
 * Maxime Ripard <maxime.ripard@free-electrons.com>
 */

#include <linux/clk-provider.h>
#include <linux/io.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/slab.h>

#include <dt-bindings/clock/sun4i-a10-pll2.h>

#define SUN4I_PLL2_ENABLE		31

#define SUN4I_PLL2_PRE_DIV_SHIFT	0
#define SUN4I_PLL2_PRE_DIV_WIDTH	5
#define SUN4I_PLL2_PRE_DIV_MASK		GENMASK(SUN4I_PLL2_PRE_DIV_WIDTH - 1, 0)

#define SUN4I_PLL2_N_SHIFT		8
#define SUN4I_PLL2_N_WIDTH		7
#define SUN4I_PLL2_N_MASK		GENMASK(SUN4I_PLL2_N_WIDTH - 1, 0)

#define SUN4I_PLL2_POST_DIV_SHIFT	26
#define SUN4I_PLL2_POST_DIV_WIDTH	4
#define SUN4I_PLL2_POST_DIV_MASK	GENMASK(SUN4I_PLL2_POST_DIV_WIDTH - 1, 0)

#define SUN4I_PLL2_POST_DIV_VALUE	4

#define SUN4I_PLL2_OUTPUTS		4

static DEFINE_SPINLOCK(sun4i_a10_pll2_lock);

static void __init sun4i_pll2_setup(struct device_node *node,
				    int post_div_offset)
{
	const char *clk_name = node->name, *parent;
	struct clk **clks, *base_clk, *prediv_clk;
	struct clk_onecell_data *clk_data;
	struct clk_multiplier *mult;
	struct clk_gate *gate;
	void __iomem *reg;
	u32 val;

	reg = of_io_request_and_map(node, 0, of_node_full_name(node));
	if (IS_ERR(reg))
		return;

	clk_data = kzalloc_obj(*clk_data);
	if (!clk_data)
		goto err_unmap;

	clks = kzalloc_objs(struct clk *, SUN4I_PLL2_OUTPUTS);
	if (!clks)
		goto err_free_data;

	parent = of_clk_get_parent_name(node, 0);
	prediv_clk = clk_register_divider(NULL, "pll2-prediv",
					  parent, 0, reg,
					  SUN4I_PLL2_PRE_DIV_SHIFT,
					  SUN4I_PLL2_PRE_DIV_WIDTH,
					  CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO,
					  &sun4i_a10_pll2_lock);
	if (IS_ERR(prediv_clk)) {
		pr_err("Couldn't register the prediv clock\n");
		goto err_free_array;
	}

	/* Setup the gate part of the PLL2 */
	gate = kzalloc_obj(struct clk_gate);
	if (!gate)
		goto err_unregister_prediv;

	gate->reg = reg;
	gate->bit_idx = SUN4I_PLL2_ENABLE;
	gate->lock = &sun4i_a10_pll2_lock;

	/* Setup the multiplier part of the PLL2 */
	mult = kzalloc_obj(struct clk_multiplier);
	if (!mult)
		goto err_free_gate;

	mult->reg = reg;
	mult->shift = SUN4I_PLL2_N_SHIFT;
	mult->width = 7;
	mult->flags = CLK_MULTIPLIER_ZERO_BYPASS |

Annotation

Implementation Notes