aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLaurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>2013-10-17 17:54:07 -0400
committerMike Turquette <mturquette@linaro.org>2013-12-12 22:23:59 -0500
commitf94859c215b6d977794108a1a9a101239e393c09 (patch)
tree8de13d7d3cd0d6a27219207e388037fd3407f16c
parentabe844aa5bb50444ac3e02aed89b431823d6ad56 (diff)
clk: shmobile: Add MSTP clock support
MSTP clocks are gate clocks controlled through a register that handles up to 32 clocks. The register is often sparsely populated. Those clocks are found on Renesas ARM SoCs. Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> Signed-off-by: Mike Turquette <mturquette@linaro.org>
-rw-r--r--Documentation/devicetree/bindings/clock/renesas,cpg-mstp-clocks.txt51
-rw-r--r--drivers/clk/shmobile/Makefile1
-rw-r--r--drivers/clk/shmobile/clk-mstp.c229
3 files changed, 281 insertions, 0 deletions
diff --git a/Documentation/devicetree/bindings/clock/renesas,cpg-mstp-clocks.txt b/Documentation/devicetree/bindings/clock/renesas,cpg-mstp-clocks.txt
new file mode 100644
index 000000000000..a6a352c2771e
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/renesas,cpg-mstp-clocks.txt
@@ -0,0 +1,51 @@
1* Renesas CPG Module Stop (MSTP) Clocks
2
3The CPG can gate SoC device clocks. The gates are organized in groups of up to
432 gates.
5
6This device tree binding describes a single 32 gate clocks group per node.
7Clocks are referenced by user nodes by the MSTP node phandle and the clock
8index in the group, from 0 to 31.
9
10Required Properties:
11
12 - compatible: Must be one of the following
13 - "renesas,r8a7790-mstp-clocks" for R8A7790 (R-Car H2) MSTP gate clocks
14 - "renesas,r8a7791-mstp-clocks" for R8A7791 (R-Car M2) MSTP gate clocks
15 - "renesas,cpg-mstp-clock" for generic MSTP gate clocks
16 - reg: Base address and length of the I/O mapped registers used by the MSTP
17 clocks. The first register is the clock control register and is mandatory.
18 The second register is the clock status register and is optional when not
19 implemented in hardware.
20 - clocks: Reference to the parent clocks, one per output clock. The parents
21 must appear in the same order as the output clocks.
22 - #clock-cells: Must be 1
23 - clock-output-names: The name of the clocks as free-form strings
24 - renesas,indices: Indices of the gate clocks into the group (0 to 31)
25
26The clocks, clock-output-names and renesas,indices properties contain one
27entry per gate clock. The MSTP groups are sparsely populated. Unimplemented
28gate clocks must not be declared.
29
30
31Example
32-------
33
34 #include <dt-bindings/clock/r8a7790-clock.h>
35
36 mstp3_clks: mstp3_clks@e615013c {
37 compatible = "renesas,r8a7790-mstp-clocks", "renesas,cpg-mstp-clocks";
38 reg = <0 0xe615013c 0 4>, <0 0xe6150048 0 4>;
39 clocks = <&cp_clk>, <&mmc1_clk>, <&sd3_clk>, <&sd2_clk>,
40 <&cpg_clocks R8A7790_CLK_SD1>, <&cpg_clocks R8A7790_CLK_SD0>,
41 <&mmc0_clk>;
42 #clock-cells = <1>;
43 clock-output-names =
44 "tpu0", "mmcif1", "sdhi3", "sdhi2",
45 "sdhi1", "sdhi0", "mmcif0";
46 renesas,clock-indices = <
47 R8A7790_CLK_TPU0 R8A7790_CLK_MMCIF1 R8A7790_CLK_SDHI3
48 R8A7790_CLK_SDHI2 R8A7790_CLK_SDHI1 R8A7790_CLK_SDHI0
49 R8A7790_CLK_MMCIF0
50 >;
51 };
diff --git a/drivers/clk/shmobile/Makefile b/drivers/clk/shmobile/Makefile
index 2e4a1197aa0a..706adc6ae70c 100644
--- a/drivers/clk/shmobile/Makefile
+++ b/drivers/clk/shmobile/Makefile
@@ -1,6 +1,7 @@
1obj-$(CONFIG_ARCH_R8A7790) += clk-rcar-gen2.o 1obj-$(CONFIG_ARCH_R8A7790) += clk-rcar-gen2.o
2obj-$(CONFIG_ARCH_R8A7791) += clk-rcar-gen2.o 2obj-$(CONFIG_ARCH_R8A7791) += clk-rcar-gen2.o
3obj-$(CONFIG_ARCH_SHMOBILE_MULTI) += clk-div6.o 3obj-$(CONFIG_ARCH_SHMOBILE_MULTI) += clk-div6.o
4obj-$(CONFIG_ARCH_SHMOBILE_MULTI) += clk-mstp.o
4 5
5# for emply built-in.o 6# for emply built-in.o
6obj-n := dummy 7obj-n := dummy
diff --git a/drivers/clk/shmobile/clk-mstp.c b/drivers/clk/shmobile/clk-mstp.c
new file mode 100644
index 000000000000..e576b60de20e
--- /dev/null
+++ b/drivers/clk/shmobile/clk-mstp.c
@@ -0,0 +1,229 @@
1/*
2 * R-Car MSTP clocks
3 *
4 * Copyright (C) 2013 Ideas On Board SPRL
5 *
6 * Contact: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; version 2 of the License.
11 */
12
13#include <linux/clk-provider.h>
14#include <linux/clkdev.h>
15#include <linux/io.h>
16#include <linux/of.h>
17#include <linux/of_address.h>
18#include <linux/spinlock.h>
19
20/*
21 * MSTP clocks. We can't use standard gate clocks as we need to poll on the
22 * status register when enabling the clock.
23 */
24
25#define MSTP_MAX_CLOCKS 32
26
27/**
28 * struct mstp_clock_group - MSTP gating clocks group
29 *
30 * @data: clocks in this group
31 * @smstpcr: module stop control register
32 * @mstpsr: module stop status register (optional)
33 * @lock: protects writes to SMSTPCR
34 */
35struct mstp_clock_group {
36 struct clk_onecell_data data;
37 void __iomem *smstpcr;
38 void __iomem *mstpsr;
39 spinlock_t lock;
40};
41
42/**
43 * struct mstp_clock - MSTP gating clock
44 * @hw: handle between common and hardware-specific interfaces
45 * @bit_index: control bit index
46 * @group: MSTP clocks group
47 */
48struct mstp_clock {
49 struct clk_hw hw;
50 u32 bit_index;
51 struct mstp_clock_group *group;
52};
53
54#define to_mstp_clock(_hw) container_of(_hw, struct mstp_clock, hw)
55
56static int cpg_mstp_clock_endisable(struct clk_hw *hw, bool enable)
57{
58 struct mstp_clock *clock = to_mstp_clock(hw);
59 struct mstp_clock_group *group = clock->group;
60 u32 bitmask = BIT(clock->bit_index);
61 unsigned long flags;
62 unsigned int i;
63 u32 value;
64
65 spin_lock_irqsave(&group->lock, flags);
66
67 value = clk_readl(group->smstpcr);
68 if (enable)
69 value &= ~bitmask;
70 else
71 value |= bitmask;
72 clk_writel(value, group->smstpcr);
73
74 spin_unlock_irqrestore(&group->lock, flags);
75
76 if (!enable || !group->mstpsr)
77 return 0;
78
79 for (i = 1000; i > 0; --i) {
80 if (!(clk_readl(group->mstpsr) & bitmask))
81 break;
82 cpu_relax();
83 }
84
85 if (!i) {
86 pr_err("%s: failed to enable %p[%d]\n", __func__,
87 group->smstpcr, clock->bit_index);
88 return -ETIMEDOUT;
89 }
90
91 return 0;
92}
93
94static int cpg_mstp_clock_enable(struct clk_hw *hw)
95{
96 return cpg_mstp_clock_endisable(hw, true);
97}
98
99static void cpg_mstp_clock_disable(struct clk_hw *hw)
100{
101 cpg_mstp_clock_endisable(hw, false);
102}
103
104static int cpg_mstp_clock_is_enabled(struct clk_hw *hw)
105{
106 struct mstp_clock *clock = to_mstp_clock(hw);
107 struct mstp_clock_group *group = clock->group;
108 u32 value;
109
110 if (group->mstpsr)
111 value = clk_readl(group->mstpsr);
112 else
113 value = clk_readl(group->smstpcr);
114
115 return !!(value & BIT(clock->bit_index));
116}
117
118static const struct clk_ops cpg_mstp_clock_ops = {
119 .enable = cpg_mstp_clock_enable,
120 .disable = cpg_mstp_clock_disable,
121 .is_enabled = cpg_mstp_clock_is_enabled,
122};
123
124static struct clk * __init
125cpg_mstp_clock_register(const char *name, const char *parent_name,
126 unsigned int index, struct mstp_clock_group *group)
127{
128 struct clk_init_data init;
129 struct mstp_clock *clock;
130 struct clk *clk;
131
132 clock = kzalloc(sizeof(*clock), GFP_KERNEL);
133 if (!clock) {
134 pr_err("%s: failed to allocate MSTP clock.\n", __func__);
135 return ERR_PTR(-ENOMEM);
136 }
137
138 init.name = name;
139 init.ops = &cpg_mstp_clock_ops;
140 init.flags = CLK_IS_BASIC;
141 init.parent_names = &parent_name;
142 init.num_parents = 1;
143
144 clock->bit_index = index;
145 clock->group = group;
146 clock->hw.init = &init;
147
148 clk = clk_register(NULL, &clock->hw);
149
150 if (IS_ERR(clk))
151 kfree(clock);
152
153 return clk;
154}
155
156static void __init cpg_mstp_clocks_init(struct device_node *np)
157{
158 struct mstp_clock_group *group;
159 struct clk **clks;
160 unsigned int i;
161
162 group = kzalloc(sizeof(*group), GFP_KERNEL);
163 clks = kzalloc(MSTP_MAX_CLOCKS * sizeof(*clks), GFP_KERNEL);
164 if (group == NULL || clks == NULL) {
165 kfree(group);
166 kfree(clks);
167 pr_err("%s: failed to allocate group\n", __func__);
168 return;
169 }
170
171 spin_lock_init(&group->lock);
172 group->data.clks = clks;
173
174 group->smstpcr = of_iomap(np, 0);
175 group->mstpsr = of_iomap(np, 1);
176
177 if (group->smstpcr == NULL) {
178 pr_err("%s: failed to remap SMSTPCR\n", __func__);
179 kfree(group);
180 kfree(clks);
181 return;
182 }
183
184 for (i = 0; i < MSTP_MAX_CLOCKS; ++i) {
185 const char *parent_name;
186 const char *name;
187 u32 clkidx;
188 int ret;
189
190 /* Skip clocks with no name. */
191 ret = of_property_read_string_index(np, "clock-output-names",
192 i, &name);
193 if (ret < 0 || strlen(name) == 0)
194 continue;
195
196 parent_name = of_clk_get_parent_name(np, i);
197 ret = of_property_read_u32_index(np, "renesas,clock-indices", i,
198 &clkidx);
199 if (parent_name == NULL || ret < 0)
200 break;
201
202 if (clkidx >= MSTP_MAX_CLOCKS) {
203 pr_err("%s: invalid clock %s %s index %u)\n",
204 __func__, np->name, name, clkidx);
205 continue;
206 }
207
208 clks[clkidx] = cpg_mstp_clock_register(name, parent_name, i,
209 group);
210 if (!IS_ERR(clks[clkidx])) {
211 group->data.clk_num = max(group->data.clk_num, clkidx);
212 /*
213 * Register a clkdev to let board code retrieve the
214 * clock by name and register aliases for non-DT
215 * devices.
216 *
217 * FIXME: Remove this when all devices that require a
218 * clock will be instantiated from DT.
219 */
220 clk_register_clkdev(clks[clkidx], name, NULL);
221 } else {
222 pr_err("%s: failed to register %s %s clock (%ld)\n",
223 __func__, np->name, name, PTR_ERR(clks[clkidx]));
224 }
225 }
226
227 of_clk_add_provider(np, of_clk_src_onecell_get, &group->data);
228}
229CLK_OF_DECLARE(cpg_mstp_clks, "renesas,cpg-mstp-clocks", cpg_mstp_clocks_init);