aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSoren Brinkmann <soren.brinkmann@xilinx.com>2013-11-27 15:16:23 -0500
committerMichal Simek <michal.simek@xilinx.com>2013-12-20 07:23:55 -0500
commitba52f8a986089e263ea28e231b6a405769ae1235 (patch)
treeb2f86681050be4395efc4d5edb51c386d21196cb
parent24c039f6acacd63e739b39a030197d5a2945e0d2 (diff)
clk/zynq/clkc: Add 'fclk-enable' feature
In some use cases Zynq's FPGA clocks are used as static clock generators for IP in the FPGA part of the SOC for which no Linux driver exists and would control those clocks. To avoid automatic gating of these clocks in such cases a new property - fclk-enable - is added to the clock controller's DT description to accomodate such use cases. It's value is a bitmask, where a set bit results in enabling the corresponding FCLK through the clkc. FPGA clocks are handled following the rules below: If an FCLK is not enabled by bootloaders, that FCLK will be disabled in Linux. Drivers can enable and control it through the CCF as usual. If an FCLK is enabled by bootloaders AND the corresponding bit in the 'fclk-enable' DT property is set, that FCLK will be enabled by the clkc, resulting in an off by one reference count for that clock. Ensuring it will always be running. Signed-off-by: Soren Brinkmann <soren.brinkmann@xilinx.com> Acked-by: Michal Simek <michal.simek@xilinx.com> Signed-off-by: Michal Simek <michal.simek@xilinx.com>
-rw-r--r--Documentation/devicetree/bindings/clock/zynq-7000.txt4
-rw-r--r--drivers/clk/zynq/clkc.c18
2 files changed, 19 insertions, 3 deletions
diff --git a/Documentation/devicetree/bindings/clock/zynq-7000.txt b/Documentation/devicetree/bindings/clock/zynq-7000.txt
index d99af878f5d7..17b4a94916d6 100644
--- a/Documentation/devicetree/bindings/clock/zynq-7000.txt
+++ b/Documentation/devicetree/bindings/clock/zynq-7000.txt
@@ -22,6 +22,10 @@ Required properties:
22Optional properties: 22Optional properties:
23 - clocks : as described in the clock bindings 23 - clocks : as described in the clock bindings
24 - clock-names : as described in the clock bindings 24 - clock-names : as described in the clock bindings
25 - fclk-enable : Bit mask to enable FCLKs statically at boot time.
26 Bit [0..3] correspond to FCLK0..FCLK3. The corresponding
27 FCLK will only be enabled if it is actually running at
28 boot time.
25 29
26Clock inputs: 30Clock inputs:
27The following strings are optional parameters to the 'clock-names' property in 31The following strings are optional parameters to the 'clock-names' property in
diff --git a/drivers/clk/zynq/clkc.c b/drivers/clk/zynq/clkc.c
index 10772aa72e4e..09dd0173ea0a 100644
--- a/drivers/clk/zynq/clkc.c
+++ b/drivers/clk/zynq/clkc.c
@@ -102,9 +102,10 @@ static const char *swdt_ext_clk_input_names[] __initdata = {"swdt_ext_clk"};
102 102
103static void __init zynq_clk_register_fclk(enum zynq_clk fclk, 103static void __init zynq_clk_register_fclk(enum zynq_clk fclk,
104 const char *clk_name, void __iomem *fclk_ctrl_reg, 104 const char *clk_name, void __iomem *fclk_ctrl_reg,
105 const char **parents) 105 const char **parents, int enable)
106{ 106{
107 struct clk *clk; 107 struct clk *clk;
108 u32 enable_reg;
108 char *mux_name; 109 char *mux_name;
109 char *div0_name; 110 char *div0_name;
110 char *div1_name; 111 char *div1_name;
@@ -147,6 +148,12 @@ static void __init zynq_clk_register_fclk(enum zynq_clk fclk,
147 clks[fclk] = clk_register_gate(NULL, clk_name, 148 clks[fclk] = clk_register_gate(NULL, clk_name,
148 div1_name, CLK_SET_RATE_PARENT, fclk_gate_reg, 149 div1_name, CLK_SET_RATE_PARENT, fclk_gate_reg,
149 0, CLK_GATE_SET_TO_DISABLE, fclk_gate_lock); 150 0, CLK_GATE_SET_TO_DISABLE, fclk_gate_lock);
151 enable_reg = readl(fclk_gate_reg) & 1;
152 if (enable && !enable_reg) {
153 if (clk_prepare_enable(clks[fclk]))
154 pr_warn("%s: FCLK%u enable failed\n", __func__,
155 fclk - fclk0);
156 }
150 kfree(mux_name); 157 kfree(mux_name);
151 kfree(div0_name); 158 kfree(div0_name);
152 kfree(div1_name); 159 kfree(div1_name);
@@ -213,6 +220,7 @@ static void __init zynq_clk_setup(struct device_node *np)
213 int ret; 220 int ret;
214 struct clk *clk; 221 struct clk *clk;
215 char *clk_name; 222 char *clk_name;
223 unsigned int fclk_enable = 0;
216 const char *clk_output_name[clk_max]; 224 const char *clk_output_name[clk_max];
217 const char *cpu_parents[4]; 225 const char *cpu_parents[4];
218 const char *periph_parents[4]; 226 const char *periph_parents[4];
@@ -238,6 +246,8 @@ static void __init zynq_clk_setup(struct device_node *np)
238 periph_parents[2] = clk_output_name[armpll]; 246 periph_parents[2] = clk_output_name[armpll];
239 periph_parents[3] = clk_output_name[ddrpll]; 247 periph_parents[3] = clk_output_name[ddrpll];
240 248
249 of_property_read_u32(np, "fclk-enable", &fclk_enable);
250
241 /* ps_clk */ 251 /* ps_clk */
242 ret = of_property_read_u32(np, "ps-clk-frequency", &tmp); 252 ret = of_property_read_u32(np, "ps-clk-frequency", &tmp);
243 if (ret) { 253 if (ret) {
@@ -340,10 +350,12 @@ static void __init zynq_clk_setup(struct device_node *np)
340 clk_prepare_enable(clks[dci]); 350 clk_prepare_enable(clks[dci]);
341 351
342 /* Peripheral clocks */ 352 /* Peripheral clocks */
343 for (i = fclk0; i <= fclk3; i++) 353 for (i = fclk0; i <= fclk3; i++) {
354 int enable = !!(fclk_enable & BIT(i - fclk0));
344 zynq_clk_register_fclk(i, clk_output_name[i], 355 zynq_clk_register_fclk(i, clk_output_name[i],
345 SLCR_FPGA0_CLK_CTRL + 0x10 * (i - fclk0), 356 SLCR_FPGA0_CLK_CTRL + 0x10 * (i - fclk0),
346 periph_parents); 357 periph_parents, enable);
358 }
347 359
348 zynq_clk_register_periph_clk(lqspi, 0, clk_output_name[lqspi], NULL, 360 zynq_clk_register_periph_clk(lqspi, 0, clk_output_name[lqspi], NULL,
349 SLCR_LQSPI_CLK_CTRL, periph_parents, 0); 361 SLCR_LQSPI_CLK_CTRL, periph_parents, 0);