drivers/clk/meson/clk-regmap.c

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

File Facts

System
Linux kernel
Corpus path
drivers/clk/meson/clk-regmap.c
Extension
.c
Size
6456 bytes
Lines
237
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

// SPDX-License-Identifier: GPL-2.0
/*
 * Copyright (c) 2018 BayLibre, SAS.
 * Author: Jerome Brunet <jbrunet@baylibre.com>
 */

#include <linux/device.h>
#include <linux/module.h>
#include <linux/mfd/syscon.h>
#include "clk-regmap.h"

int clk_regmap_init(struct clk_hw *hw)
{
	struct clk_regmap *clk = to_clk_regmap(hw);
	struct device_node *np, *parent_np;
	struct device *dev;

	/* Allow regmap to be preset as it was historically done */
	if (clk->map)
		return 0;

	/*
	 * FIXME: what follows couples the controller implementation
	 * and clk_regmap clock type. This situation is not desirable
	 * but temporary, until the controller is able to register
	 * a hook to initialize a clock type
	 */

	/* Check the usual dev enabled controller with an basic IO regmap */
	dev = clk_hw_get_dev(hw);
	if (dev) {
		clk->map = dev_get_regmap(dev, NULL);
		if (clk->map)
			return 0;
	}

	/* Move on to early and syscon based controllers */
	np = clk_hw_get_of_node(hw);
	if (np) {
		parent_np = of_get_parent(np);
		clk->map = syscon_node_to_regmap(parent_np);
		of_node_put(parent_np);

		if (!IS_ERR_OR_NULL(clk->map))
			return 0;
	}

	/* Bail out if regmap can't be found */
	return -EINVAL;
}
EXPORT_SYMBOL_NS_GPL(clk_regmap_init, "CLK_MESON");

static int clk_regmap_gate_endisable(struct clk_hw *hw, int enable)
{
	struct clk_regmap *clk = to_clk_regmap(hw);
	struct clk_regmap_gate_data *gate = clk_get_regmap_gate_data(clk);
	int set = gate->flags & CLK_GATE_SET_TO_DISABLE ? 1 : 0;

	set ^= enable;

	return regmap_update_bits(clk->map, gate->offset, BIT(gate->bit_idx),
				  set ? BIT(gate->bit_idx) : 0);
}

static int clk_regmap_gate_enable(struct clk_hw *hw)
{
	return clk_regmap_gate_endisable(hw, 1);
}

static void clk_regmap_gate_disable(struct clk_hw *hw)
{
	clk_regmap_gate_endisable(hw, 0);
}

static int clk_regmap_gate_is_enabled(struct clk_hw *hw)
{
	struct clk_regmap *clk = to_clk_regmap(hw);
	struct clk_regmap_gate_data *gate = clk_get_regmap_gate_data(clk);
	unsigned int val;

	regmap_read(clk->map, gate->offset, &val);
	if (gate->flags & CLK_GATE_SET_TO_DISABLE)
		val ^= BIT(gate->bit_idx);

	val &= BIT(gate->bit_idx);

	return val ? 1 : 0;
}

const struct clk_ops clk_regmap_gate_ops = {

Annotation

Implementation Notes