Merge tag 'clk-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux
[linux-2.6-microblaze.git] / drivers / clk / zynqmp / clkc.c
index 5eed5ce..db8d0d7 100644 (file)
@@ -84,6 +84,7 @@ struct name_resp {
 
 struct topology_resp {
 #define CLK_TOPOLOGY_TYPE              GENMASK(3, 0)
+#define CLK_TOPOLOGY_CUSTOM_TYPE_FLAGS GENMASK(7, 4)
 #define CLK_TOPOLOGY_FLAGS             GENMASK(23, 8)
 #define CLK_TOPOLOGY_TYPE_FLAGS                GENMASK(31, 24)
        u32 topology[CLK_GET_TOPOLOGY_RESP_WORDS];
@@ -395,6 +396,9 @@ static int __zynqmp_clock_get_topology(struct clock_topology *topology,
                topology[*nnodes].type_flag =
                                FIELD_GET(CLK_TOPOLOGY_TYPE_FLAGS,
                                          response->topology[i]);
+               topology[*nnodes].custom_type_flag =
+                       FIELD_GET(CLK_TOPOLOGY_CUSTOM_TYPE_FLAGS,
+                                 response->topology[i]);
                (*nnodes)++;
        }
 
@@ -557,7 +561,7 @@ static struct clk_hw *zynqmp_register_clk_topology(int clk_id, char *clk_name,
 {
        int j;
        u32 num_nodes, clk_dev_id;
-       char *clk_out = NULL;
+       char *clk_out[MAX_NODES];
        struct clock_topology *nodes;
        struct clk_hw *hw = NULL;
 
@@ -571,16 +575,16 @@ static struct clk_hw *zynqmp_register_clk_topology(int clk_id, char *clk_name,
                 * Intermediate clock names are postfixed with type of clock.
                 */
                if (j != (num_nodes - 1)) {
-                       clk_out = kasprintf(GFP_KERNEL, "%s%s", clk_name,
+                       clk_out[j] = kasprintf(GFP_KERNEL, "%s%s", clk_name,
                                            clk_type_postfix[nodes[j].type]);
                } else {
-                       clk_out = kasprintf(GFP_KERNEL, "%s", clk_name);
+                       clk_out[j] = kasprintf(GFP_KERNEL, "%s", clk_name);
                }
 
                if (!clk_topology[nodes[j].type])
                        continue;
 
-               hw = (*clk_topology[nodes[j].type])(clk_out, clk_dev_id,
+               hw = (*clk_topology[nodes[j].type])(clk_out[j], clk_dev_id,
                                                    parent_names,
                                                    num_parents,
                                                    &nodes[j]);
@@ -589,9 +593,12 @@ static struct clk_hw *zynqmp_register_clk_topology(int clk_id, char *clk_name,
                                     __func__,  clk_dev_id, clk_name,
                                     PTR_ERR(hw));
 
-               parent_names[0] = clk_out;
+               parent_names[0] = clk_out[j];
        }
-       kfree(clk_out);
+
+       for (j = 0; j < num_nodes; j++)
+               kfree(clk_out[j]);
+
        return hw;
 }
 
@@ -662,6 +669,11 @@ static void zynqmp_get_clock_info(void)
                        continue;
 
                clock[i].valid = FIELD_GET(CLK_ATTR_VALID, attr.attr[0]);
+               /* skip query for Invalid clock */
+               ret = zynqmp_is_valid_clock(i);
+               if (ret != CLK_ATTR_VALID)
+                       continue;
+
                clock[i].type = FIELD_GET(CLK_ATTR_TYPE, attr.attr[0]) ?
                        CLK_TYPE_EXTERNAL : CLK_TYPE_OUTPUT;