Skip to content
Snippets Groups Projects
Commit 7689696a authored by Leo Yan's avatar Leo Yan Committed by Erik Schilling
Browse files

clk: virt: Add virtual CPU clock driver


Signed-off-by: default avatarLeo Yan <leo.yan@linaro.org>
parent 3265d393
No related branches found
No related tags found
No related merge requests found
......@@ -138,3 +138,5 @@ endif
obj-y += xilinx/
obj-$(CONFIG_ARCH_ZYNQ) += zynq/
obj-$(CONFIG_COMMON_CLK_ZYNQMP) += zynqmp/
obj-y += clk-virt-2.8-cpu.o
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Linaro virt clock driver
*
* Copyright (c) 2021 Linaro Limited.
*
* Author: Leo Yan <leo.yan@linaro.org>
*/
#include <linux/clk-provider.h>
#include <linux/device.h>
#include <linux/err.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/mailbox_client.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#define DEFINE_VIRT_CLK(_id, _name, _rate) \
{ \
.id = (_id), \
.hw.init = &(struct clk_init_data) { \
.name = #_name, \
.ops = &virt_clk_ops, \
.num_parents = 0, \
.flags = CLK_GET_RATE_NOCACHE, \
}, \
.rate = (_rate), \
},
#define to_virt_clk(_hw) container_of(_hw, struct virt_clk, hw)
struct virt_clk {
unsigned int id;
struct clk_hw hw;
unsigned int rate;
};
static unsigned long virt_clk_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct virt_clk *virt_clk = to_virt_clk(hw);
return virt_clk->rate;
}
static long virt_clk_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
{
/*
* LPM3 handles rate rounding so just return whatever
* rate is requested.
*/
return rate;
}
static int virt_clk_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
struct virt_clk *virt_clk = to_virt_clk(hw);
virt_clk->rate = rate;
return 0;
}
static const struct clk_ops virt_clk_ops = {
.recalc_rate = virt_clk_recalc_rate,
.round_rate = virt_clk_round_rate,
.set_rate = virt_clk_set_rate,
};
static struct virt_clk virt_clks[2] = {
DEFINE_VIRT_CLK(0, "cpu-cluster.0", 533000000)
DEFINE_VIRT_CLK(1, "cpu-cluster.1", 533000000)
};
static struct clk_hw *virt_clk_hw_get(struct of_phandle_args *clkspec,
void *data)
{
unsigned int idx = clkspec->args[0];
if (idx >= 2) {
pr_err("%s: invalid index %u\n", __func__, idx);
return ERR_PTR(-EINVAL);
}
return &virt_clks[idx].hw;
}
static int virt_clk_probe(struct platform_device *pdev)
{
unsigned int i;
int ret;
for (i = 0; i < 2; i++) {
ret = devm_clk_hw_register(&pdev->dev, &virt_clks[i].hw);
if (ret)
return ret;
}
return devm_of_clk_add_hw_provider(&pdev->dev, virt_clk_hw_get,
virt_clks);
}
static const struct of_device_id virt_clk_of_match[] = {
{ .compatible = "linaro,virt-2.8-cpu-clk", },
{}
};
static struct platform_driver virt_clk_driver = {
.probe = virt_clk_probe,
.driver = {
.name = "virt-2.8-cpu-clk",
.of_match_table = virt_clk_of_match,
},
};
static int __init virt_clk_init(void)
{
return platform_driver_register(&virt_clk_driver);
}
subsys_initcall(virt_clk_init);
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment