drivers/clk/versatile/clk-impd1.c

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

File Facts

System
Linux kernel
Corpus path
drivers/clk/versatile/clk-impd1.c
Extension
.c
Size
3233 bytes
Lines
136
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-only
/*
 * Clock driver for the ARM Integrator/IM-PD1 board
 * Copyright (C) 2012-2013 Linus Walleij
 */
#include <linux/clk-provider.h>
#include <linux/clkdev.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/platform_device.h>
#include <linux/module.h>
#include <linux/mfd/syscon.h>
#include <linux/regmap.h>

#include "icst.h"
#include "clk-icst.h"

#define IMPD1_OSC1	0x00
#define IMPD1_OSC2	0x04
#define IMPD1_LOCK	0x08

/*
 * There are two VCO's on the IM-PD1
 */

static const struct icst_params impd1_vco1_params = {
	.ref		= 24000000,	/* 24 MHz */
	.vco_max	= ICST525_VCO_MAX_3V,
	.vco_min	= ICST525_VCO_MIN,
	.vd_min		= 12,
	.vd_max		= 519,
	.rd_min		= 3,
	.rd_max		= 120,
	.s2div		= icst525_s2div,
	.idx2s		= icst525_idx2s,
};

static const struct clk_icst_desc impd1_icst1_desc = {
	.params = &impd1_vco1_params,
	.vco_offset = IMPD1_OSC1,
	.lock_offset = IMPD1_LOCK,
};

static const struct icst_params impd1_vco2_params = {
	.ref		= 24000000,	/* 24 MHz */
	.vco_max	= ICST525_VCO_MAX_3V,
	.vco_min	= ICST525_VCO_MIN,
	.vd_min		= 12,
	.vd_max		= 519,
	.rd_min		= 3,
	.rd_max		= 120,
	.s2div		= icst525_s2div,
	.idx2s		= icst525_idx2s,
};

static const struct clk_icst_desc impd1_icst2_desc = {
	.params = &impd1_vco2_params,
	.vco_offset = IMPD1_OSC2,
	.lock_offset = IMPD1_LOCK,
};

static int integrator_impd1_clk_spawn(struct device *dev,
				      struct device_node *parent,
				      struct device_node *np)
{
	struct regmap *map;
	struct clk *clk = ERR_PTR(-EINVAL);
	const char *name = np->name;
	const char *parent_name;
	const struct clk_icst_desc *desc;
	int ret;

	map = syscon_node_to_regmap(parent);
	if (IS_ERR(map)) {
		pr_err("no regmap for syscon IM-PD1 ICST clock parent\n");
		return PTR_ERR(map);
	}

	if (of_device_is_compatible(np, "arm,impd1-vco1")) {
		desc = &impd1_icst1_desc;
	} else if (of_device_is_compatible(np, "arm,impd1-vco2")) {
		desc = &impd1_icst2_desc;
	} else {
		dev_err(dev, "not a clock node %s\n", name);
		return -ENODEV;
	}

	of_property_read_string(np, "clock-output-names", &name);
	parent_name = of_clk_get_parent_name(np, 0);
	clk = icst_clk_setup(NULL, desc, name, parent_name, map,

Annotation

Implementation Notes