diff options
-rw-r--r-- | drivers/clk/Kconfig | 15 | ||||
-rw-r--r-- | drivers/clk/Makefile | 2 | ||||
-rw-r--r-- | drivers/clk/clk-max-gen.c | 194 | ||||
-rw-r--r-- | drivers/clk/clk-max-gen.h | 32 | ||||
-rw-r--r-- | drivers/clk/clk-max77686.c | 244 | ||||
-rw-r--r-- | drivers/clk/clk-max77802.c | 96 |
6 files changed, 234 insertions, 349 deletions
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index e2d9bd760c84..d7d2993a889c 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig | |||
@@ -31,22 +31,11 @@ config COMMON_CLK_WM831X | |||
31 | 31 | ||
32 | source "drivers/clk/versatile/Kconfig" | 32 | source "drivers/clk/versatile/Kconfig" |
33 | 33 | ||
34 | config COMMON_CLK_MAX_GEN | ||
35 | bool | ||
36 | |||
37 | config COMMON_CLK_MAX77686 | 34 | config COMMON_CLK_MAX77686 |
38 | tristate "Clock driver for Maxim 77686 MFD" | 35 | tristate "Clock driver for Maxim 77686/77802 MFD" |
39 | depends on MFD_MAX77686 | ||
40 | select COMMON_CLK_MAX_GEN | ||
41 | ---help--- | ||
42 | This driver supports Maxim 77686 crystal oscillator clock. | ||
43 | |||
44 | config COMMON_CLK_MAX77802 | ||
45 | tristate "Clock driver for Maxim 77802 PMIC" | ||
46 | depends on MFD_MAX77686 | 36 | depends on MFD_MAX77686 |
47 | select COMMON_CLK_MAX_GEN | ||
48 | ---help--- | 37 | ---help--- |
49 | This driver supports Maxim 77802 crystal oscillator clock. | 38 | This driver supports Maxim 77686/77802 crystal oscillator clock. |
50 | 39 | ||
51 | config COMMON_CLK_RK808 | 40 | config COMMON_CLK_RK808 |
52 | tristate "Clock driver for RK808/RK818" | 41 | tristate "Clock driver for RK808/RK818" |
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index 3b6f9cf3464a..e775a836247c 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile | |||
@@ -27,9 +27,7 @@ obj-$(CONFIG_COMMON_CLK_CS2000_CP) += clk-cs2000-cp.o | |||
27 | obj-$(CONFIG_ARCH_EFM32) += clk-efm32gg.o | 27 | obj-$(CONFIG_ARCH_EFM32) += clk-efm32gg.o |
28 | obj-$(CONFIG_ARCH_HIGHBANK) += clk-highbank.o | 28 | obj-$(CONFIG_ARCH_HIGHBANK) += clk-highbank.o |
29 | obj-$(CONFIG_MACH_LOONGSON32) += clk-ls1x.o | 29 | obj-$(CONFIG_MACH_LOONGSON32) += clk-ls1x.o |
30 | obj-$(CONFIG_COMMON_CLK_MAX_GEN) += clk-max-gen.o | ||
31 | obj-$(CONFIG_COMMON_CLK_MAX77686) += clk-max77686.o | 30 | obj-$(CONFIG_COMMON_CLK_MAX77686) += clk-max77686.o |
32 | obj-$(CONFIG_COMMON_CLK_MAX77802) += clk-max77802.o | ||
33 | obj-$(CONFIG_ARCH_MB86S7X) += clk-mb86s7x.o | 31 | obj-$(CONFIG_ARCH_MB86S7X) += clk-mb86s7x.o |
34 | obj-$(CONFIG_ARCH_MOXART) += clk-moxart.o | 32 | obj-$(CONFIG_ARCH_MOXART) += clk-moxart.o |
35 | obj-$(CONFIG_ARCH_NOMADIK) += clk-nomadik.o | 33 | obj-$(CONFIG_ARCH_NOMADIK) += clk-nomadik.o |
diff --git a/drivers/clk/clk-max-gen.c b/drivers/clk/clk-max-gen.c deleted file mode 100644 index 35af9cb6da4f..000000000000 --- a/drivers/clk/clk-max-gen.c +++ /dev/null | |||
@@ -1,194 +0,0 @@ | |||
1 | /* | ||
2 | * clk-max-gen.c - Generic clock driver for Maxim PMICs clocks | ||
3 | * | ||
4 | * Copyright (C) 2014 Google, Inc | ||
5 | * | ||
6 | * Copyright (C) 2012 Samsung Electornics | ||
7 | * Jonghwa Lee <jonghwa3.lee@samsung.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify it | ||
10 | * under the terms of the GNU General Public License as published by the | ||
11 | * Free Software Foundation; either version 2 of the License, or (at your | ||
12 | * option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * This driver is based on clk-max77686.c | ||
20 | * | ||
21 | */ | ||
22 | |||
23 | #include <linux/kernel.h> | ||
24 | #include <linux/slab.h> | ||
25 | #include <linux/err.h> | ||
26 | #include <linux/regmap.h> | ||
27 | #include <linux/platform_device.h> | ||
28 | #include <linux/clk-provider.h> | ||
29 | #include <linux/mutex.h> | ||
30 | #include <linux/clkdev.h> | ||
31 | #include <linux/of.h> | ||
32 | #include <linux/export.h> | ||
33 | |||
34 | #include "clk-max-gen.h" | ||
35 | |||
36 | struct max_gen_clk { | ||
37 | struct regmap *regmap; | ||
38 | u32 mask; | ||
39 | u32 reg; | ||
40 | struct clk_hw hw; | ||
41 | }; | ||
42 | |||
43 | static struct max_gen_clk *to_max_gen_clk(struct clk_hw *hw) | ||
44 | { | ||
45 | return container_of(hw, struct max_gen_clk, hw); | ||
46 | } | ||
47 | |||
48 | static int max_gen_clk_prepare(struct clk_hw *hw) | ||
49 | { | ||
50 | struct max_gen_clk *max_gen = to_max_gen_clk(hw); | ||
51 | |||
52 | return regmap_update_bits(max_gen->regmap, max_gen->reg, | ||
53 | max_gen->mask, max_gen->mask); | ||
54 | } | ||
55 | |||
56 | static void max_gen_clk_unprepare(struct clk_hw *hw) | ||
57 | { | ||
58 | struct max_gen_clk *max_gen = to_max_gen_clk(hw); | ||
59 | |||
60 | regmap_update_bits(max_gen->regmap, max_gen->reg, | ||
61 | max_gen->mask, ~max_gen->mask); | ||
62 | } | ||
63 | |||
64 | static int max_gen_clk_is_prepared(struct clk_hw *hw) | ||
65 | { | ||
66 | struct max_gen_clk *max_gen = to_max_gen_clk(hw); | ||
67 | int ret; | ||
68 | u32 val; | ||
69 | |||
70 | ret = regmap_read(max_gen->regmap, max_gen->reg, &val); | ||
71 | |||
72 | if (ret < 0) | ||
73 | return -EINVAL; | ||
74 | |||
75 | return val & max_gen->mask; | ||
76 | } | ||
77 | |||
78 | static unsigned long max_gen_recalc_rate(struct clk_hw *hw, | ||
79 | unsigned long parent_rate) | ||
80 | { | ||
81 | return 32768; | ||
82 | } | ||
83 | |||
84 | struct clk_ops max_gen_clk_ops = { | ||
85 | .prepare = max_gen_clk_prepare, | ||
86 | .unprepare = max_gen_clk_unprepare, | ||
87 | .is_prepared = max_gen_clk_is_prepared, | ||
88 | .recalc_rate = max_gen_recalc_rate, | ||
89 | }; | ||
90 | EXPORT_SYMBOL_GPL(max_gen_clk_ops); | ||
91 | |||
92 | static struct clk *max_gen_clk_register(struct device *dev, | ||
93 | struct max_gen_clk *max_gen) | ||
94 | { | ||
95 | struct clk *clk; | ||
96 | struct clk_hw *hw = &max_gen->hw; | ||
97 | int ret; | ||
98 | |||
99 | clk = devm_clk_register(dev, hw); | ||
100 | if (IS_ERR(clk)) | ||
101 | return clk; | ||
102 | |||
103 | ret = clk_register_clkdev(clk, hw->init->name, NULL); | ||
104 | |||
105 | if (ret) | ||
106 | return ERR_PTR(ret); | ||
107 | |||
108 | return clk; | ||
109 | } | ||
110 | |||
111 | int max_gen_clk_probe(struct platform_device *pdev, struct regmap *regmap, | ||
112 | u32 reg, struct clk_init_data *clks_init, int num_init) | ||
113 | { | ||
114 | int i, ret; | ||
115 | struct max_gen_clk *max_gen_clks; | ||
116 | struct clk **clocks; | ||
117 | struct device *dev = pdev->dev.parent; | ||
118 | const char *clk_name; | ||
119 | struct clk_init_data *init; | ||
120 | |||
121 | clocks = devm_kzalloc(dev, sizeof(struct clk *) * num_init, GFP_KERNEL); | ||
122 | if (!clocks) | ||
123 | return -ENOMEM; | ||
124 | |||
125 | max_gen_clks = devm_kzalloc(dev, sizeof(struct max_gen_clk) | ||
126 | * num_init, GFP_KERNEL); | ||
127 | if (!max_gen_clks) | ||
128 | return -ENOMEM; | ||
129 | |||
130 | for (i = 0; i < num_init; i++) { | ||
131 | max_gen_clks[i].regmap = regmap; | ||
132 | max_gen_clks[i].mask = 1 << i; | ||
133 | max_gen_clks[i].reg = reg; | ||
134 | |||
135 | init = devm_kzalloc(dev, sizeof(*init), GFP_KERNEL); | ||
136 | if (!init) | ||
137 | return -ENOMEM; | ||
138 | |||
139 | if (dev->of_node && | ||
140 | !of_property_read_string_index(dev->of_node, | ||
141 | "clock-output-names", | ||
142 | i, &clk_name)) | ||
143 | init->name = clk_name; | ||
144 | else | ||
145 | init->name = clks_init[i].name; | ||
146 | |||
147 | init->ops = clks_init[i].ops; | ||
148 | init->flags = clks_init[i].flags; | ||
149 | |||
150 | max_gen_clks[i].hw.init = init; | ||
151 | |||
152 | clocks[i] = max_gen_clk_register(dev, &max_gen_clks[i]); | ||
153 | if (IS_ERR(clocks[i])) { | ||
154 | ret = PTR_ERR(clocks[i]); | ||
155 | dev_err(dev, "failed to register %s\n", | ||
156 | max_gen_clks[i].hw.init->name); | ||
157 | return ret; | ||
158 | } | ||
159 | } | ||
160 | |||
161 | platform_set_drvdata(pdev, clocks); | ||
162 | |||
163 | if (dev->of_node) { | ||
164 | struct clk_onecell_data *of_data; | ||
165 | |||
166 | of_data = devm_kzalloc(dev, sizeof(*of_data), GFP_KERNEL); | ||
167 | if (!of_data) | ||
168 | return -ENOMEM; | ||
169 | |||
170 | of_data->clks = clocks; | ||
171 | of_data->clk_num = num_init; | ||
172 | ret = of_clk_add_provider(dev->of_node, of_clk_src_onecell_get, | ||
173 | of_data); | ||
174 | |||
175 | if (ret) { | ||
176 | dev_err(dev, "failed to register OF clock provider\n"); | ||
177 | return ret; | ||
178 | } | ||
179 | } | ||
180 | |||
181 | return 0; | ||
182 | } | ||
183 | EXPORT_SYMBOL_GPL(max_gen_clk_probe); | ||
184 | |||
185 | int max_gen_clk_remove(struct platform_device *pdev, int num_init) | ||
186 | { | ||
187 | struct device *dev = pdev->dev.parent; | ||
188 | |||
189 | if (dev->of_node) | ||
190 | of_clk_del_provider(dev->of_node); | ||
191 | |||
192 | return 0; | ||
193 | } | ||
194 | EXPORT_SYMBOL_GPL(max_gen_clk_remove); | ||
diff --git a/drivers/clk/clk-max-gen.h b/drivers/clk/clk-max-gen.h deleted file mode 100644 index 997e86fc3f4d..000000000000 --- a/drivers/clk/clk-max-gen.h +++ /dev/null | |||
@@ -1,32 +0,0 @@ | |||
1 | /* | ||
2 | * clk-max-gen.h - Generic clock driver for Maxim PMICs clocks | ||
3 | * | ||
4 | * Copyright (C) 2014 Google, Inc | ||
5 | * | ||
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 | ||
8 | * Free Software Foundation; either version 2 of the License, or (at your | ||
9 | * option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | */ | ||
17 | |||
18 | #ifndef __CLK_MAX_GEN_H__ | ||
19 | #define __CLK_MAX_GEN_H__ | ||
20 | |||
21 | #include <linux/types.h> | ||
22 | #include <linux/device.h> | ||
23 | #include <linux/clkdev.h> | ||
24 | #include <linux/regmap.h> | ||
25 | #include <linux/platform_device.h> | ||
26 | |||
27 | int max_gen_clk_probe(struct platform_device *pdev, struct regmap *regmap, | ||
28 | u32 reg, struct clk_init_data *clks_init, int num_init); | ||
29 | int max_gen_clk_remove(struct platform_device *pdev, int num_init); | ||
30 | extern struct clk_ops max_gen_clk_ops; | ||
31 | |||
32 | #endif /* __CLK_MAX_GEN_H__ */ | ||
diff --git a/drivers/clk/clk-max77686.c b/drivers/clk/clk-max77686.c index 9b6f2772e948..9aba3a8245e1 100644 --- a/drivers/clk/clk-max77686.c +++ b/drivers/clk/clk-max77686.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * clk-max77686.c - Clock driver for Maxim 77686 | 2 | * clk-max77686.c - Clock driver for Maxim 77686/MAX77802 |
3 | * | 3 | * |
4 | * Copyright (C) 2012 Samsung Electornics | 4 | * Copyright (C) 2012 Samsung Electornics |
5 | * Jonghwa Lee <jonghwa3.lee@samsung.com> | 5 | * Jonghwa Lee <jonghwa3.lee@samsung.com> |
@@ -30,41 +30,261 @@ | |||
30 | #include <linux/clk-provider.h> | 30 | #include <linux/clk-provider.h> |
31 | #include <linux/mutex.h> | 31 | #include <linux/mutex.h> |
32 | #include <linux/clkdev.h> | 32 | #include <linux/clkdev.h> |
33 | #include <linux/of.h> | ||
34 | #include <linux/regmap.h> | ||
33 | 35 | ||
34 | #include <dt-bindings/clock/maxim,max77686.h> | 36 | #include <dt-bindings/clock/maxim,max77686.h> |
35 | #include "clk-max-gen.h" | 37 | #include <dt-bindings/clock/maxim,max77802.h> |
36 | 38 | ||
37 | static struct clk_init_data max77686_clks_init[MAX77686_CLKS_NUM] = { | 39 | #define MAX77802_CLOCK_LOW_JITTER_SHIFT 0x3 |
40 | |||
41 | enum max77686_chip_name { | ||
42 | CHIP_MAX77686, | ||
43 | CHIP_MAX77802, | ||
44 | }; | ||
45 | |||
46 | struct max77686_hw_clk_info { | ||
47 | const char *name; | ||
48 | u32 clk_reg; | ||
49 | u32 clk_enable_mask; | ||
50 | u32 flags; | ||
51 | }; | ||
52 | |||
53 | struct max77686_clk_init_data { | ||
54 | struct regmap *regmap; | ||
55 | struct clk_hw hw; | ||
56 | struct clk_init_data clk_idata; | ||
57 | const struct max77686_hw_clk_info *clk_info; | ||
58 | }; | ||
59 | |||
60 | struct max77686_clk_driver_data { | ||
61 | enum max77686_chip_name chip; | ||
62 | struct clk **clks; | ||
63 | struct max77686_clk_init_data *max_clk_data; | ||
64 | struct clk_onecell_data of_data; | ||
65 | }; | ||
66 | |||
67 | static const struct | ||
68 | max77686_hw_clk_info max77686_hw_clks_info[MAX77686_CLKS_NUM] = { | ||
38 | [MAX77686_CLK_AP] = { | 69 | [MAX77686_CLK_AP] = { |
39 | .name = "32khz_ap", | 70 | .name = "32khz_ap", |
40 | .ops = &max_gen_clk_ops, | 71 | .clk_reg = MAX77686_REG_32KHZ, |
72 | .clk_enable_mask = BIT(MAX77686_CLK_AP), | ||
41 | }, | 73 | }, |
42 | [MAX77686_CLK_CP] = { | 74 | [MAX77686_CLK_CP] = { |
43 | .name = "32khz_cp", | 75 | .name = "32khz_cp", |
44 | .ops = &max_gen_clk_ops, | 76 | .clk_reg = MAX77686_REG_32KHZ, |
77 | .clk_enable_mask = BIT(MAX77686_CLK_CP), | ||
45 | }, | 78 | }, |
46 | [MAX77686_CLK_PMIC] = { | 79 | [MAX77686_CLK_PMIC] = { |
47 | .name = "32khz_pmic", | 80 | .name = "32khz_pmic", |
48 | .ops = &max_gen_clk_ops, | 81 | .clk_reg = MAX77686_REG_32KHZ, |
82 | .clk_enable_mask = BIT(MAX77686_CLK_PMIC), | ||
83 | }, | ||
84 | }; | ||
85 | |||
86 | static const struct | ||
87 | max77686_hw_clk_info max77802_hw_clks_info[MAX77802_CLKS_NUM] = { | ||
88 | [MAX77802_CLK_32K_AP] = { | ||
89 | .name = "32khz_ap", | ||
90 | .clk_reg = MAX77802_REG_32KHZ, | ||
91 | .clk_enable_mask = BIT(MAX77802_CLK_32K_AP), | ||
92 | }, | ||
93 | [MAX77802_CLK_32K_CP] = { | ||
94 | .name = "32khz_cp", | ||
95 | .clk_reg = MAX77802_REG_32KHZ, | ||
96 | .clk_enable_mask = BIT(MAX77802_CLK_32K_CP), | ||
49 | }, | 97 | }, |
50 | }; | 98 | }; |
51 | 99 | ||
100 | static struct max77686_clk_init_data *to_max77686_clk_init_data( | ||
101 | struct clk_hw *hw) | ||
102 | { | ||
103 | return container_of(hw, struct max77686_clk_init_data, hw); | ||
104 | } | ||
105 | |||
106 | static int max77686_clk_prepare(struct clk_hw *hw) | ||
107 | { | ||
108 | struct max77686_clk_init_data *max77686 = to_max77686_clk_init_data(hw); | ||
109 | |||
110 | return regmap_update_bits(max77686->regmap, max77686->clk_info->clk_reg, | ||
111 | max77686->clk_info->clk_enable_mask, | ||
112 | max77686->clk_info->clk_enable_mask); | ||
113 | } | ||
114 | |||
115 | static void max77686_clk_unprepare(struct clk_hw *hw) | ||
116 | { | ||
117 | struct max77686_clk_init_data *max77686 = to_max77686_clk_init_data(hw); | ||
118 | |||
119 | regmap_update_bits(max77686->regmap, max77686->clk_info->clk_reg, | ||
120 | max77686->clk_info->clk_enable_mask, | ||
121 | ~max77686->clk_info->clk_enable_mask); | ||
122 | } | ||
123 | |||
124 | static int max77686_clk_is_prepared(struct clk_hw *hw) | ||
125 | { | ||
126 | struct max77686_clk_init_data *max77686 = to_max77686_clk_init_data(hw); | ||
127 | int ret; | ||
128 | u32 val; | ||
129 | |||
130 | ret = regmap_read(max77686->regmap, max77686->clk_info->clk_reg, &val); | ||
131 | |||
132 | if (ret < 0) | ||
133 | return -EINVAL; | ||
134 | |||
135 | return val & max77686->clk_info->clk_enable_mask; | ||
136 | } | ||
137 | |||
138 | static unsigned long max77686_recalc_rate(struct clk_hw *hw, | ||
139 | unsigned long parent_rate) | ||
140 | { | ||
141 | return 32768; | ||
142 | } | ||
143 | |||
144 | static struct clk_ops max77686_clk_ops = { | ||
145 | .prepare = max77686_clk_prepare, | ||
146 | .unprepare = max77686_clk_unprepare, | ||
147 | .is_prepared = max77686_clk_is_prepared, | ||
148 | .recalc_rate = max77686_recalc_rate, | ||
149 | }; | ||
150 | |||
52 | static int max77686_clk_probe(struct platform_device *pdev) | 151 | static int max77686_clk_probe(struct platform_device *pdev) |
53 | { | 152 | { |
54 | struct max77686_dev *iodev = dev_get_drvdata(pdev->dev.parent); | 153 | struct device *dev = &pdev->dev; |
154 | struct device *parent = dev->parent; | ||
155 | const struct platform_device_id *id = platform_get_device_id(pdev); | ||
156 | struct max77686_clk_driver_data *drv_data; | ||
157 | const struct max77686_hw_clk_info *hw_clks; | ||
158 | struct regmap *regmap; | ||
159 | int i, ret, num_clks; | ||
160 | |||
161 | drv_data = devm_kzalloc(dev, sizeof(*drv_data), GFP_KERNEL); | ||
162 | if (!drv_data) | ||
163 | return -ENOMEM; | ||
164 | |||
165 | regmap = dev_get_regmap(parent, NULL); | ||
166 | if (!regmap) { | ||
167 | dev_err(dev, "Failed to get rtc regmap\n"); | ||
168 | return -ENODEV; | ||
169 | } | ||
170 | |||
171 | drv_data->chip = id->driver_data; | ||
172 | |||
173 | switch (drv_data->chip) { | ||
174 | case CHIP_MAX77686: | ||
175 | num_clks = MAX77686_CLKS_NUM; | ||
176 | hw_clks = max77686_hw_clks_info; | ||
177 | break; | ||
178 | |||
179 | case CHIP_MAX77802: | ||
180 | num_clks = MAX77802_CLKS_NUM; | ||
181 | hw_clks = max77802_hw_clks_info; | ||
182 | break; | ||
183 | |||
184 | default: | ||
185 | dev_err(dev, "Unknown Chip ID\n"); | ||
186 | return -EINVAL; | ||
187 | } | ||
188 | |||
189 | drv_data->max_clk_data = devm_kcalloc(dev, num_clks, | ||
190 | sizeof(*drv_data->max_clk_data), | ||
191 | GFP_KERNEL); | ||
192 | if (!drv_data->max_clk_data) | ||
193 | return -ENOMEM; | ||
194 | |||
195 | drv_data->clks = devm_kcalloc(dev, num_clks, | ||
196 | sizeof(*drv_data->clks), GFP_KERNEL); | ||
197 | if (!drv_data->clks) | ||
198 | return -ENOMEM; | ||
55 | 199 | ||
56 | return max_gen_clk_probe(pdev, iodev->regmap, MAX77686_REG_32KHZ, | 200 | for (i = 0; i < num_clks; i++) { |
57 | max77686_clks_init, MAX77686_CLKS_NUM); | 201 | struct max77686_clk_init_data *max_clk_data; |
202 | struct clk *clk; | ||
203 | const char *clk_name; | ||
204 | |||
205 | max_clk_data = &drv_data->max_clk_data[i]; | ||
206 | |||
207 | max_clk_data->regmap = regmap; | ||
208 | max_clk_data->clk_info = &hw_clks[i]; | ||
209 | max_clk_data->clk_idata.flags = hw_clks[i].flags; | ||
210 | max_clk_data->clk_idata.ops = &max77686_clk_ops; | ||
211 | |||
212 | if (parent->of_node && | ||
213 | !of_property_read_string_index(parent->of_node, | ||
214 | "clock-output-names", | ||
215 | i, &clk_name)) | ||
216 | max_clk_data->clk_idata.name = clk_name; | ||
217 | else | ||
218 | max_clk_data->clk_idata.name = hw_clks[i].name; | ||
219 | |||
220 | max_clk_data->hw.init = &max_clk_data->clk_idata; | ||
221 | |||
222 | clk = devm_clk_register(dev, &max_clk_data->hw); | ||
223 | if (IS_ERR(clk)) { | ||
224 | ret = PTR_ERR(clk); | ||
225 | dev_err(dev, "Failed to clock register: %d\n", ret); | ||
226 | return ret; | ||
227 | } | ||
228 | |||
229 | ret = clk_register_clkdev(clk, max_clk_data->clk_idata.name, | ||
230 | NULL); | ||
231 | if (ret < 0) { | ||
232 | dev_err(dev, "Failed to clkdev register: %d\n", ret); | ||
233 | return ret; | ||
234 | } | ||
235 | drv_data->clks[i] = clk; | ||
236 | } | ||
237 | |||
238 | platform_set_drvdata(pdev, drv_data); | ||
239 | |||
240 | if (parent->of_node) { | ||
241 | drv_data->of_data.clks = drv_data->clks; | ||
242 | drv_data->of_data.clk_num = num_clks; | ||
243 | ret = of_clk_add_provider(parent->of_node, | ||
244 | of_clk_src_onecell_get, | ||
245 | &drv_data->of_data); | ||
246 | |||
247 | if (ret < 0) { | ||
248 | dev_err(dev, "Failed to register OF clock provider: %d\n", | ||
249 | ret); | ||
250 | return ret; | ||
251 | } | ||
252 | } | ||
253 | |||
254 | /* MAX77802: Enable low-jitter mode on the 32khz clocks. */ | ||
255 | if (drv_data->chip == CHIP_MAX77802) { | ||
256 | ret = regmap_update_bits(regmap, MAX77802_REG_32KHZ, | ||
257 | 1 << MAX77802_CLOCK_LOW_JITTER_SHIFT, | ||
258 | 1 << MAX77802_CLOCK_LOW_JITTER_SHIFT); | ||
259 | if (ret < 0) { | ||
260 | dev_err(dev, "Failed to config low-jitter: %d\n", ret); | ||
261 | goto remove_of_clk_provider; | ||
262 | } | ||
263 | } | ||
264 | |||
265 | return 0; | ||
266 | |||
267 | remove_of_clk_provider: | ||
268 | if (parent->of_node) | ||
269 | of_clk_del_provider(parent->of_node); | ||
270 | |||
271 | return ret; | ||
58 | } | 272 | } |
59 | 273 | ||
60 | static int max77686_clk_remove(struct platform_device *pdev) | 274 | static int max77686_clk_remove(struct platform_device *pdev) |
61 | { | 275 | { |
62 | return max_gen_clk_remove(pdev, MAX77686_CLKS_NUM); | 276 | struct device *parent = pdev->dev.parent; |
277 | |||
278 | if (parent->of_node) | ||
279 | of_clk_del_provider(parent->of_node); | ||
280 | |||
281 | return 0; | ||
63 | } | 282 | } |
64 | 283 | ||
65 | static const struct platform_device_id max77686_clk_id[] = { | 284 | static const struct platform_device_id max77686_clk_id[] = { |
66 | { "max77686-clk", 0}, | 285 | { "max77686-clk", .driver_data = CHIP_MAX77686, }, |
67 | { }, | 286 | { "max77802-clk", .driver_data = CHIP_MAX77802, }, |
287 | {}, | ||
68 | }; | 288 | }; |
69 | MODULE_DEVICE_TABLE(platform, max77686_clk_id); | 289 | MODULE_DEVICE_TABLE(platform, max77686_clk_id); |
70 | 290 | ||
diff --git a/drivers/clk/clk-max77802.c b/drivers/clk/clk-max77802.c deleted file mode 100644 index 355dd2e522c3..000000000000 --- a/drivers/clk/clk-max77802.c +++ /dev/null | |||
@@ -1,96 +0,0 @@ | |||
1 | /* | ||
2 | * clk-max77802.c - Clock driver for Maxim 77802 | ||
3 | * | ||
4 | * Copyright (C) 2014 Google, Inc | ||
5 | * | ||
6 | * Copyright (C) 2012 Samsung Electornics | ||
7 | * Jonghwa Lee <jonghwa3.lee@samsung.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify it | ||
10 | * under the terms of the GNU General Public License as published by the | ||
11 | * Free Software Foundation; either version 2 of the License, or (at your | ||
12 | * option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * This driver is based on clk-max77686.c | ||
20 | */ | ||
21 | |||
22 | #include <linux/kernel.h> | ||
23 | #include <linux/slab.h> | ||
24 | #include <linux/err.h> | ||
25 | #include <linux/module.h> | ||
26 | #include <linux/platform_device.h> | ||
27 | #include <linux/mfd/max77686-private.h> | ||
28 | #include <linux/clk-provider.h> | ||
29 | #include <linux/mutex.h> | ||
30 | #include <linux/clkdev.h> | ||
31 | |||
32 | #include <dt-bindings/clock/maxim,max77802.h> | ||
33 | #include "clk-max-gen.h" | ||
34 | |||
35 | #define MAX77802_CLOCK_OPMODE_MASK 0x1 | ||
36 | #define MAX77802_CLOCK_LOW_JITTER_SHIFT 0x3 | ||
37 | |||
38 | static struct clk_init_data max77802_clks_init[MAX77802_CLKS_NUM] = { | ||
39 | [MAX77802_CLK_32K_AP] = { | ||
40 | .name = "32khz_ap", | ||
41 | .ops = &max_gen_clk_ops, | ||
42 | }, | ||
43 | [MAX77802_CLK_32K_CP] = { | ||
44 | .name = "32khz_cp", | ||
45 | .ops = &max_gen_clk_ops, | ||
46 | }, | ||
47 | }; | ||
48 | |||
49 | static int max77802_clk_probe(struct platform_device *pdev) | ||
50 | { | ||
51 | struct max77686_dev *iodev = dev_get_drvdata(pdev->dev.parent); | ||
52 | int ret; | ||
53 | |||
54 | ret = max_gen_clk_probe(pdev, iodev->regmap, MAX77802_REG_32KHZ, | ||
55 | max77802_clks_init, MAX77802_CLKS_NUM); | ||
56 | |||
57 | if (ret) { | ||
58 | dev_err(&pdev->dev, "generic probe failed %d\n", ret); | ||
59 | return ret; | ||
60 | } | ||
61 | |||
62 | /* Enable low-jitter mode on the 32khz clocks. */ | ||
63 | ret = regmap_update_bits(iodev->regmap, MAX77802_REG_32KHZ, | ||
64 | 1 << MAX77802_CLOCK_LOW_JITTER_SHIFT, | ||
65 | 1 << MAX77802_CLOCK_LOW_JITTER_SHIFT); | ||
66 | if (ret < 0) | ||
67 | dev_err(&pdev->dev, "failed to enable low-jitter mode\n"); | ||
68 | |||
69 | return ret; | ||
70 | } | ||
71 | |||
72 | static int max77802_clk_remove(struct platform_device *pdev) | ||
73 | { | ||
74 | return max_gen_clk_remove(pdev, MAX77802_CLKS_NUM); | ||
75 | } | ||
76 | |||
77 | static const struct platform_device_id max77802_clk_id[] = { | ||
78 | { "max77802-clk", 0}, | ||
79 | { }, | ||
80 | }; | ||
81 | MODULE_DEVICE_TABLE(platform, max77802_clk_id); | ||
82 | |||
83 | static struct platform_driver max77802_clk_driver = { | ||
84 | .driver = { | ||
85 | .name = "max77802-clk", | ||
86 | }, | ||
87 | .probe = max77802_clk_probe, | ||
88 | .remove = max77802_clk_remove, | ||
89 | .id_table = max77802_clk_id, | ||
90 | }; | ||
91 | |||
92 | module_platform_driver(max77802_clk_driver); | ||
93 | |||
94 | MODULE_DESCRIPTION("MAXIM 77802 Clock Driver"); | ||
95 | MODULE_AUTHOR("Javier Martinez Canillas <javier@osg.samsung.com"); | ||
96 | MODULE_LICENSE("GPL"); | ||