Commit MetaInfo

Revisionb395094abff6bbc2c0616177c6231aeaa1367786 (tree)
Time2016-01-16 19:22:55
AuthorYoshinori Sato <ysato@user...>
CommiterYoshinori Sato

Log Message

clk: h8300: Add module stop driver

Signed-off-by: Yoshinori Sato <ysato@users.sourceforge.jp>

Change Summary

Incremental Difference

--- a/drivers/clk/h8300/Makefile
+++ b/drivers/clk/h8300/Makefile
@@ -1,2 +1,2 @@
1-obj-y += clk-div.o
1+obj-y += clk-div.o clk-mstp.o
22 obj-$(CONFIG_H8S2678) += clk-h8s2678.o
--- /dev/null
+++ b/drivers/clk/h8300/clk-mstp.c
@@ -0,0 +1,157 @@
1+/*
2+ * H8/300 gated clock driver
3+ *
4+ * Copyright (C) 2016 Yoshinoi Sato <ysato@users.sourceforge.jp>
5+ *
6+ * This program is free software; you can redistribute it and/or modify
7+ * it under the terms of the GNU General Public License version 2 as
8+ * published by the Free Software Foundation.
9+ *
10+ */
11+
12+#include <linux/clk-provider.h>
13+#include <linux/err.h>
14+#include <linux/device.h>
15+#include <linux/of.h>
16+#include <linux/of_address.h>
17+#include <linux/slab.h>
18+
19+#define MAX_CLOCK 16
20+
21+struct mstp_data {
22+ struct clk_onecell_data data;
23+ void __iomem *mstcr;
24+};
25+
26+struct mstp_clock {
27+ struct clk_hw hw;
28+ u32 bit_index;
29+ struct mstp_data *data;
30+};
31+
32+static inline struct mstp_clock *to_mstp_clock(struct clk_hw *clk_hw)
33+{
34+ return container_of(clk_hw, struct mstp_clock, hw);
35+}
36+
37+static int cpg_mstp_clock_enable(struct clk_hw *hw)
38+{
39+ struct mstp_clock *clock = to_mstp_clock(hw);
40+ u16 value;
41+
42+ value = ioread16be(clock->data->mstcr);
43+ value &= ~BIT(clock->bit_index);
44+ iowrite16be(value, clock->data->mstcr);
45+ return 0;
46+}
47+
48+static void cpg_mstp_clock_disable(struct clk_hw *hw)
49+{
50+ struct mstp_clock *clock = to_mstp_clock(hw);
51+ u16 value;
52+
53+ value = ioread16be(clock->data->mstcr);
54+ value |= BIT(clock->bit_index);
55+ iowrite16be(value, clock->data->mstcr);
56+}
57+
58+static int cpg_mstp_clock_is_enabled(struct clk_hw *hw)
59+{
60+ struct mstp_clock *clock = to_mstp_clock(hw);
61+ u16 value;
62+
63+ value = ioread16be(clock->data->mstcr);
64+ return !(value & BIT(clock->bit_index));
65+}
66+
67+static const struct clk_ops cpg_mstp_clock_ops = {
68+ .enable = cpg_mstp_clock_enable,
69+ .disable = cpg_mstp_clock_disable,
70+ .is_enabled = cpg_mstp_clock_is_enabled,
71+};
72+
73+static struct clk * __init
74+cpg_mstp_clock_register(const char *name, const char *parent_name,
75+ unsigned int index, struct mstp_data *data)
76+{
77+ struct clk_init_data init;
78+ struct mstp_clock *clock;
79+ struct clk *clk;
80+
81+ clock = kzalloc(sizeof(*clock), GFP_KERNEL);
82+ if (!clock) {
83+ pr_err("%s: failed to allocate MSTP clock.\n", __func__);
84+ return ERR_PTR(-ENOMEM);
85+ }
86+
87+ init.name = name;
88+ init.ops = &cpg_mstp_clock_ops;
89+ init.flags = CLK_IS_BASIC | CLK_SET_RATE_PARENT;
90+ init.parent_names = &parent_name;
91+ init.num_parents = 1;
92+
93+ clock->bit_index = index;
94+ clock->data = data;
95+ clock->hw.init = &init;
96+
97+ clk = clk_register(NULL, &clock->hw);
98+
99+ if (IS_ERR(clk))
100+ kfree(clock);
101+
102+ return clk;
103+}
104+
105+static void __init mstp_clk_setup(struct device_node *node)
106+{
107+ const char *pclk;
108+ int i;
109+ void __iomem *mstcr;
110+ struct clk **clks;
111+ struct mstp_data *data;
112+
113+ if (!(pclk = of_clk_get_parent_name(node, 0))) {
114+ pr_err("%s: parent clock not found\n", __func__);
115+ return;
116+ }
117+ mstcr = of_iomap(node, 0);
118+ if (!mstcr) {
119+ pr_err("%s: MSTP regieter map failed\n", __func__);
120+ return;
121+ }
122+
123+ data = kzalloc(sizeof(*data), GFP_KERNEL);
124+ if (!data) {
125+ pr_err("%s: malloc failed\n", __func__);
126+ return;
127+ }
128+ clks = kmalloc(MAX_CLOCKS * sizeof(*clks), GFP_KERNEL);
129+ if (!clks) {
130+ pr_err("%s: malloc failed\n", __func__);
131+ goto free_data;
132+ }
133+
134+ for (i = 0; i < MAX_CLOCKS; i++) {
135+ const char *name;
136+ int ret;
137+
138+ clks[i] = ERR_PTR(-ENOENT);
139+ ret = of_property_read_string_index(node, "clock-output-names",
140+ i, &name);
141+ if (ret < 0 || strlen(name) == 0)
142+ continue;
143+ clks[i] = cpg_mstp_clock_register(name, pclk, i, data);
144+ if (IS_ERR(clks[i]))
145+ pr_err("%s: failed to register %s %s clock (%ld)\n",
146+ __func__, node->name, name, PTR_ERR(clks[i]));
147+ }
148+ data->data.clk_num = MAX_CLOCKS;
149+ data->data.clks = clks;
150+ data->mstcr = mstcr;
151+ of_clk_add_provider(node, of_clk_src_onecell_get, data);
152+ return;
153+free_data:
154+ kfree(data);
155+}
156+
157+CLK_OF_DECLARE(renesas_h8_mstp_clk, "renesas,h8300-mstp-clock", mstp_clk_setup);
Show on old repository browser