summaryrefslogtreecommitdiff
path: root/drivers/clk/zynqmp
diff options
context:
space:
mode:
authorRajan Vaja <rajan.vaja@xilinx.com>2019-03-04 15:19:10 -0800
committerStephen Boyd <sboyd@kernel.org>2019-04-11 11:31:44 -0700
commitd3e4ebc18753c429e64cf92cd70616f51fa6f543 (patch)
tree0021b334c9b6f23833f83ff3cc1fc7f05aea77bc /drivers/clk/zynqmp
parent60d74e011c8e7450846563739a8530f823e5d77a (diff)
downloadlwn-d3e4ebc18753c429e64cf92cd70616f51fa6f543.tar.gz
lwn-d3e4ebc18753c429e64cf92cd70616f51fa6f543.zip
drivers: clk: Update clock driver to handle clock attribute
Versal EEMI APIs uses clock device ID which is combination of class, subclass, type and clock index (e.g. 0x8104006 in which 0-13 bits are for index(6 in given example), 14-19 bits are for clock type (i.e pll, out or ref, 1 in given example), 20-25 bits are for subclass which is nothing but clock type only), 26-32 bits are for device class, which is clock(0x2) for all clocks) while zynqmp firmware uses clock ID which is index only (e.g 0, 1, to n, where n is max_clock id). To use zynqmp clock driver for versal platform also, extend use of QueryAttribute API to fetch device class, subclass and clock type to create clock device ID. In case of zynqmp this attributes would be 0 only, so there won't be any effect on clock id as it would use clock index only. Signed-off-by: Tejas Patel <tejas.patel@xilinx.com> Signed-off-by: Rajan Vaja <rajan.vaja@xilinx.com> Signed-off-by: Michal Simek <michal.simek@xilinx.com> Signed-off-by: Jolly Shah <jollys@xilinx.com> Signed-off-by: Stephen Boyd <sboyd@kernel.org>
Diffstat (limited to 'drivers/clk/zynqmp')
-rw-r--r--drivers/clk/zynqmp/clkc.c42
1 files changed, 29 insertions, 13 deletions
diff --git a/drivers/clk/zynqmp/clkc.c b/drivers/clk/zynqmp/clkc.c
index b0908ec62f73..112ae7d157e1 100644
--- a/drivers/clk/zynqmp/clkc.c
+++ b/drivers/clk/zynqmp/clkc.c
@@ -53,6 +53,10 @@
#define RESERVED_CLK_NAME ""
#define CLK_VALID_MASK 0x1
+#define NODE_CLASS_SHIFT 26U
+#define NODE_SUBCLASS_SHIFT 20U
+#define NODE_TYPE_SHIFT 14U
+#define NODE_INDEX_SHIFT 0U
enum clk_type {
CLK_TYPE_OUTPUT,
@@ -80,6 +84,7 @@ struct clock_parent {
* @num_nodes: Number of nodes present in topology
* @parent: Parent of clock
* @num_parents: Number of parents of clock
+ * @clk_id: Clock id
*/
struct zynqmp_clock {
char clk_name[MAX_NAME_LEN];
@@ -89,6 +94,7 @@ struct zynqmp_clock {
u32 num_nodes;
struct clock_parent parent[MAX_PARENT];
u32 num_parents;
+ u32 clk_id;
};
static const char clk_type_postfix[][10] = {
@@ -396,7 +402,8 @@ static int zynqmp_clock_get_topology(u32 clk_id,
*num_nodes = 0;
for (j = 0; j <= MAX_NODES; j += 3) {
- ret = zynqmp_pm_clock_get_topology(clk_id, j, pm_resp);
+ ret = zynqmp_pm_clock_get_topology(clock[clk_id].clk_id, j,
+ pm_resp);
if (ret)
return ret;
ret = __zynqmp_clock_get_topology(topology, pm_resp, num_nodes);
@@ -459,7 +466,8 @@ static int zynqmp_clock_get_parents(u32 clk_id, struct clock_parent *parents,
*num_parents = 0;
do {
/* Get parents from firmware */
- ret = zynqmp_pm_clock_get_parents(clk_id, j, pm_resp);
+ ret = zynqmp_pm_clock_get_parents(clock[clk_id].clk_id, j,
+ pm_resp);
if (ret)
return ret;
@@ -528,13 +536,14 @@ static struct clk_hw *zynqmp_register_clk_topology(int clk_id, char *clk_name,
const char **parent_names)
{
int j;
- u32 num_nodes;
+ u32 num_nodes, clk_dev_id;
char *clk_out = NULL;
struct clock_topology *nodes;
struct clk_hw *hw = NULL;
nodes = clock[clk_id].node;
num_nodes = clock[clk_id].num_nodes;
+ clk_dev_id = clock[clk_id].clk_id;
for (j = 0; j < num_nodes; j++) {
/*
@@ -551,13 +560,14 @@ static struct clk_hw *zynqmp_register_clk_topology(int clk_id, char *clk_name,
if (!clk_topology[nodes[j].type])
continue;
- hw = (*clk_topology[nodes[j].type])(clk_out, clk_id,
+ hw = (*clk_topology[nodes[j].type])(clk_out, clk_dev_id,
parent_names,
num_parents,
&nodes[j]);
if (IS_ERR(hw))
- pr_warn_once("%s() %s register fail with %ld\n",
- __func__, clk_name, PTR_ERR(hw));
+ pr_warn_once("%s() 0x%x: %s register fail with %ld\n",
+ __func__, clk_dev_id, clk_name,
+ PTR_ERR(hw));
parent_names[0] = clk_out;
}
@@ -621,20 +631,26 @@ static int zynqmp_register_clocks(struct device_node *np)
static void zynqmp_get_clock_info(void)
{
int i, ret;
- u32 attr, type = 0;
+ u32 attr, type = 0, nodetype, subclass, class;
for (i = 0; i < clock_max_idx; i++) {
- zynqmp_pm_clock_get_name(i, clock[i].clk_name);
- if (!strcmp(clock[i].clk_name, RESERVED_CLK_NAME))
- continue;
-
ret = zynqmp_pm_clock_get_attributes(i, &attr);
if (ret)
continue;
clock[i].valid = attr & CLK_VALID_MASK;
- clock[i].type = attr >> CLK_TYPE_SHIFT ? CLK_TYPE_EXTERNAL :
- CLK_TYPE_OUTPUT;
+ clock[i].type = ((attr >> CLK_TYPE_SHIFT) & 0x1) ?
+ CLK_TYPE_EXTERNAL : CLK_TYPE_OUTPUT;
+ nodetype = (attr >> NODE_TYPE_SHIFT) & 0x3F;
+ subclass = (attr >> NODE_SUBCLASS_SHIFT) & 0x3F;
+ class = (attr >> NODE_CLASS_SHIFT) & 0x3F;
+
+ clock[i].clk_id = (class << NODE_CLASS_SHIFT) |
+ (subclass << NODE_SUBCLASS_SHIFT) |
+ (nodetype << NODE_TYPE_SHIFT) |
+ (i << NODE_INDEX_SHIFT);
+
+ zynqmp_pm_clock_get_name(clock[i].clk_id, clock[i].clk_name);
}
/* Get topology of all clock */