aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/clk/clk-s2mps11.c
diff options
context:
space:
mode:
authorKrzysztof Kozlowski <k.kozlowski@samsung.com>2014-05-21 07:23:01 -0400
committerMike Turquette <mturquette@linaro.org>2014-05-23 18:44:03 -0400
commite8b60a45a54738243d13aeba230af20a68619b1b (patch)
treed67f2df3cc56f82f93e448e4f461f8c6153676f6 /drivers/clk/clk-s2mps11.c
parent7002483c7b28a808d2bd4366b00c48911688c768 (diff)
clk: s2mps11: Add support for S2MPS14 clocks
This patch adds support for S2MPS14 PMIC clocks (BT and AP) to the s2mps11 clock driver. Signed-off-by: Krzysztof Kozlowski <k.kozlowski@samsung.com> Cc: Kyungmin Park <kyungmin.park@samsung.com> Reviewed-by: Yadwinder Singh Brar <yadi.brar@samsung.com> Reviewed-by: Tomasz Figa <t.figa@samsung.com> Acked-by: Mike Turquette <mturquette@linaro.org> Signed-off-by: Mike Turquette <mturquette@linaro.org>
Diffstat (limited to 'drivers/clk/clk-s2mps11.c')
-rw-r--r--drivers/clk/clk-s2mps11.c64
1 files changed, 48 insertions, 16 deletions
diff --git a/drivers/clk/clk-s2mps11.c b/drivers/clk/clk-s2mps11.c
index 23ffd89c4023..9b7b5859a420 100644
--- a/drivers/clk/clk-s2mps11.c
+++ b/drivers/clk/clk-s2mps11.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * clk-s2mps11.c - Clock driver for S2MPS11. 2 * clk-s2mps11.c - Clock driver for S2MPS11.
3 * 3 *
4 * Copyright (C) 2013 Samsung Electornics 4 * Copyright (C) 2013,2014 Samsung Electornics
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify it 6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the 7 * under the terms of the GNU General Public License as published by the
@@ -13,10 +13,6 @@
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details. 14 * GNU General Public License for more details.
15 * 15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */ 16 */
21 17
22#include <linux/module.h> 18#include <linux/module.h>
@@ -27,6 +23,7 @@
27#include <linux/clk-provider.h> 23#include <linux/clk-provider.h>
28#include <linux/platform_device.h> 24#include <linux/platform_device.h>
29#include <linux/mfd/samsung/s2mps11.h> 25#include <linux/mfd/samsung/s2mps11.h>
26#include <linux/mfd/samsung/s2mps14.h>
30#include <linux/mfd/samsung/s5m8767.h> 27#include <linux/mfd/samsung/s5m8767.h>
31#include <linux/mfd/samsung/core.h> 28#include <linux/mfd/samsung/core.h>
32 29
@@ -126,7 +123,21 @@ static struct clk_init_data s2mps11_clks_init[S2MPS11_CLKS_NUM] = {
126 }, 123 },
127}; 124};
128 125
129static struct device_node *s2mps11_clk_parse_dt(struct platform_device *pdev) 126static struct clk_init_data s2mps14_clks_init[S2MPS11_CLKS_NUM] = {
127 [S2MPS11_CLK_AP] = {
128 .name = "s2mps14_ap",
129 .ops = &s2mps11_clk_ops,
130 .flags = CLK_IS_ROOT,
131 },
132 [S2MPS11_CLK_BT] = {
133 .name = "s2mps14_bt",
134 .ops = &s2mps11_clk_ops,
135 .flags = CLK_IS_ROOT,
136 },
137};
138
139static struct device_node *s2mps11_clk_parse_dt(struct platform_device *pdev,
140 struct clk_init_data *clks_init)
130{ 141{
131 struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent); 142 struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent);
132 struct device_node *clk_np; 143 struct device_node *clk_np;
@@ -141,9 +152,12 @@ static struct device_node *s2mps11_clk_parse_dt(struct platform_device *pdev)
141 return ERR_PTR(-EINVAL); 152 return ERR_PTR(-EINVAL);
142 } 153 }
143 154
144 for (i = 0; i < S2MPS11_CLKS_NUM; i++) 155 for (i = 0; i < S2MPS11_CLKS_NUM; i++) {
156 if (!clks_init[i].name)
157 continue; /* Skip clocks not present in some devices */
145 of_property_read_string_index(clk_np, "clock-output-names", i, 158 of_property_read_string_index(clk_np, "clock-output-names", i,
146 &s2mps11_clks_init[i].name); 159 &clks_init[i].name);
160 }
147 161
148 return clk_np; 162 return clk_np;
149} 163}
@@ -153,6 +167,7 @@ static int s2mps11_clk_probe(struct platform_device *pdev)
153 struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent); 167 struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent);
154 struct s2mps11_clk *s2mps11_clks, *s2mps11_clk; 168 struct s2mps11_clk *s2mps11_clks, *s2mps11_clk;
155 unsigned int s2mps11_reg; 169 unsigned int s2mps11_reg;
170 struct clk_init_data *clks_init;
156 int i, ret = 0; 171 int i, ret = 0;
157 u32 val; 172 u32 val;
158 173
@@ -168,26 +183,34 @@ static int s2mps11_clk_probe(struct platform_device *pdev)
168 if (!clk_table) 183 if (!clk_table)
169 return -ENOMEM; 184 return -ENOMEM;
170 185
171 /* Store clocks of_node in first element of s2mps11_clks array */
172 s2mps11_clks->clk_np = s2mps11_clk_parse_dt(pdev);
173 if (IS_ERR(s2mps11_clks->clk_np))
174 return PTR_ERR(s2mps11_clks->clk_np);
175
176 switch(platform_get_device_id(pdev)->driver_data) { 186 switch(platform_get_device_id(pdev)->driver_data) {
177 case S2MPS11X: 187 case S2MPS11X:
178 s2mps11_reg = S2MPS11_REG_RTC_CTRL; 188 s2mps11_reg = S2MPS11_REG_RTC_CTRL;
189 clks_init = s2mps11_clks_init;
190 break;
191 case S2MPS14X:
192 s2mps11_reg = S2MPS14_REG_RTCCTRL;
193 clks_init = s2mps14_clks_init;
179 break; 194 break;
180 case S5M8767X: 195 case S5M8767X:
181 s2mps11_reg = S5M8767_REG_CTRL1; 196 s2mps11_reg = S5M8767_REG_CTRL1;
197 clks_init = s2mps11_clks_init;
182 break; 198 break;
183 default: 199 default:
184 dev_err(&pdev->dev, "Invalid device type\n"); 200 dev_err(&pdev->dev, "Invalid device type\n");
185 return -EINVAL; 201 return -EINVAL;
186 }; 202 };
187 203
204 /* Store clocks of_node in first element of s2mps11_clks array */
205 s2mps11_clks->clk_np = s2mps11_clk_parse_dt(pdev, clks_init);
206 if (IS_ERR(s2mps11_clks->clk_np))
207 return PTR_ERR(s2mps11_clks->clk_np);
208
188 for (i = 0; i < S2MPS11_CLKS_NUM; i++, s2mps11_clk++) { 209 for (i = 0; i < S2MPS11_CLKS_NUM; i++, s2mps11_clk++) {
210 if (!clks_init[i].name)
211 continue; /* Skip clocks not present in some devices */
189 s2mps11_clk->iodev = iodev; 212 s2mps11_clk->iodev = iodev;
190 s2mps11_clk->hw.init = &s2mps11_clks_init[i]; 213 s2mps11_clk->hw.init = &clks_init[i];
191 s2mps11_clk->mask = 1 << i; 214 s2mps11_clk->mask = 1 << i;
192 s2mps11_clk->reg = s2mps11_reg; 215 s2mps11_clk->reg = s2mps11_reg;
193 216
@@ -220,8 +243,12 @@ static int s2mps11_clk_probe(struct platform_device *pdev)
220 clkdev_add(s2mps11_clk->lookup); 243 clkdev_add(s2mps11_clk->lookup);
221 } 244 }
222 245
223 for (i = 0; i < S2MPS11_CLKS_NUM; i++) 246 for (i = 0; i < S2MPS11_CLKS_NUM; i++) {
247 /* Skip clocks not present on S2MPS14 */
248 if (!clks_init[i].name)
249 continue;
224 clk_table[i] = s2mps11_clks[i].clk; 250 clk_table[i] = s2mps11_clks[i].clk;
251 }
225 252
226 clk_data.clks = clk_table; 253 clk_data.clks = clk_table;
227 clk_data.clk_num = S2MPS11_CLKS_NUM; 254 clk_data.clk_num = S2MPS11_CLKS_NUM;
@@ -254,14 +281,19 @@ static int s2mps11_clk_remove(struct platform_device *pdev)
254 /* Drop the reference obtained in s2mps11_clk_parse_dt */ 281 /* Drop the reference obtained in s2mps11_clk_parse_dt */
255 of_node_put(s2mps11_clks[0].clk_np); 282 of_node_put(s2mps11_clks[0].clk_np);
256 283
257 for (i = 0; i < S2MPS11_CLKS_NUM; i++) 284 for (i = 0; i < S2MPS11_CLKS_NUM; i++) {
285 /* Skip clocks not present on S2MPS14 */
286 if (!s2mps11_clks[i].lookup)
287 continue;
258 clkdev_drop(s2mps11_clks[i].lookup); 288 clkdev_drop(s2mps11_clks[i].lookup);
289 }
259 290
260 return 0; 291 return 0;
261} 292}
262 293
263static const struct platform_device_id s2mps11_clk_id[] = { 294static const struct platform_device_id s2mps11_clk_id[] = {
264 { "s2mps11-clk", S2MPS11X}, 295 { "s2mps11-clk", S2MPS11X},
296 { "s2mps14-clk", S2MPS14X},
265 { "s5m8767-clk", S5M8767X}, 297 { "s5m8767-clk", S5M8767X},
266 { }, 298 { },
267}; 299};