drivers/clk/sifive/sifive-prci.c

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

File Facts

System
Linux kernel
Corpus path
drivers/clk/sifive/sifive-prci.c
Extension
.c
Size
16644 bytes
Lines
621
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

if (r) {
			dev_warn(dev, "Failed to register clock %s: %d\n",
				 init.name, r);
			return r;
		}

		pd->hw_clks.hws[i] = &pic->hw;
	}

	pd->hw_clks.num = i;

	r = devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get,
					&pd->hw_clks);
	if (r) {
		dev_err(dev, "could not add hw_provider: %d\n", r);
		return r;
	}

	return 0;
}

/**
 * sifive_prci_probe() - initialize prci data and check parent count
 * @pdev: platform device pointer for the prci
 *
 * Return: 0 upon success or a negative error code upon failure.
 */
static int sifive_prci_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	struct __prci_data *pd;
	const struct prci_clk_desc *desc;
	int r;

	desc = of_device_get_match_data(&pdev->dev);

	pd = devm_kzalloc(dev, struct_size(pd, hw_clks.hws, desc->num_clks), GFP_KERNEL);
	if (!pd)
		return -ENOMEM;

	pd->va = devm_platform_ioremap_resource(pdev, 0);
	if (IS_ERR(pd->va))
		return PTR_ERR(pd->va);

	pd->reset.rcdev.owner = THIS_MODULE;
	pd->reset.rcdev.nr_resets = PRCI_RST_NR;
	pd->reset.rcdev.ops = &reset_simple_ops;
	pd->reset.rcdev.of_node = pdev->dev.of_node;
	pd->reset.active_low = true;
	pd->reset.membase = pd->va + PRCI_DEVICESRESETREG_OFFSET;
	spin_lock_init(&pd->reset.lock);

	r = devm_reset_controller_register(&pdev->dev, &pd->reset.rcdev);
	if (r) {
		dev_err(dev, "could not register reset controller: %d\n", r);
		return r;
	}
	r = __prci_register_clocks(dev, pd, desc);
	if (r) {
		dev_err(dev, "could not register clocks: %d\n", r);
		return r;
	}

	dev_dbg(dev, "SiFive PRCI probed\n");

	return 0;
}

static const struct of_device_id sifive_prci_of_match[] = {
	{.compatible = "sifive,fu540-c000-prci", .data = &prci_clk_fu540},
	{.compatible = "sifive,fu740-c000-prci", .data = &prci_clk_fu740},
	{}
};
MODULE_DEVICE_TABLE(of, sifive_prci_of_match);

static struct platform_driver sifive_prci_driver = {
	.driver = {
		.name = "sifive-clk-prci",
		.of_match_table = sifive_prci_of_match,
	},
	.probe = sifive_prci_probe,
};
module_platform_driver(sifive_prci_driver);

MODULE_AUTHOR("Paul Walmsley <paul.walmsley@sifive.com>");
MODULE_DESCRIPTION("SiFive Power Reset Clock Interface (PRCI) driver");
MODULE_LICENSE("GPL");

Annotation

Implementation Notes