aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/clk/samsung/clk-exynos-audss.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/clk/samsung/clk-exynos-audss.c')
-rw-r--r--drivers/clk/samsung/clk-exynos-audss.c104
1 files changed, 88 insertions, 16 deletions
diff --git a/drivers/clk/samsung/clk-exynos-audss.c b/drivers/clk/samsung/clk-exynos-audss.c
index 68e515d093d8..1d8f6770ccfe 100644
--- a/drivers/clk/samsung/clk-exynos-audss.c
+++ b/drivers/clk/samsung/clk-exynos-audss.c
@@ -14,6 +14,8 @@
14#include <linux/clk-provider.h> 14#include <linux/clk-provider.h>
15#include <linux/of_address.h> 15#include <linux/of_address.h>
16#include <linux/syscore_ops.h> 16#include <linux/syscore_ops.h>
17#include <linux/module.h>
18#include <linux/platform_device.h>
17 19
18#include <dt-bindings/clk/exynos-audss-clk.h> 20#include <dt-bindings/clk/exynos-audss-clk.h>
19 21
@@ -62,24 +64,26 @@ static struct syscore_ops exynos_audss_clk_syscore_ops = {
62#endif /* CONFIG_PM_SLEEP */ 64#endif /* CONFIG_PM_SLEEP */
63 65
64/* register exynos_audss clocks */ 66/* register exynos_audss clocks */
65static void __init exynos_audss_clk_init(struct device_node *np) 67static int exynos_audss_clk_probe(struct platform_device *pdev)
66{ 68{
67 reg_base = of_iomap(np, 0); 69 int i, ret = 0;
68 if (!reg_base) { 70 struct resource *res;
69 pr_err("%s: failed to map audss registers\n", __func__); 71
70 return; 72 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
73 reg_base = devm_ioremap_resource(&pdev->dev, res);
74 if (IS_ERR(reg_base)) {
75 dev_err(&pdev->dev, "failed to map audss registers\n");
76 return PTR_ERR(reg_base);
71 } 77 }
72 78
73 clk_table = kzalloc(sizeof(struct clk *) * EXYNOS_AUDSS_MAX_CLKS, 79 clk_table = devm_kzalloc(&pdev->dev,
80 sizeof(struct clk *) * EXYNOS_AUDSS_MAX_CLKS,
74 GFP_KERNEL); 81 GFP_KERNEL);
75 if (!clk_table) { 82 if (!clk_table)
76 pr_err("%s: could not allocate clk lookup table\n", __func__); 83 return -ENOMEM;
77 return;
78 }
79 84
80 clk_data.clks = clk_table; 85 clk_data.clks = clk_table;
81 clk_data.clk_num = EXYNOS_AUDSS_MAX_CLKS; 86 clk_data.clk_num = EXYNOS_AUDSS_MAX_CLKS;
82 of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
83 87
84 clk_table[EXYNOS_MOUT_AUDSS] = clk_register_mux(NULL, "mout_audss", 88 clk_table[EXYNOS_MOUT_AUDSS] = clk_register_mux(NULL, "mout_audss",
85 mout_audss_p, ARRAY_SIZE(mout_audss_p), 89 mout_audss_p, ARRAY_SIZE(mout_audss_p),
@@ -123,13 +127,81 @@ static void __init exynos_audss_clk_init(struct device_node *np)
123 "div_pcm0", CLK_SET_RATE_PARENT, 127 "div_pcm0", CLK_SET_RATE_PARENT,
124 reg_base + ASS_CLK_GATE, 5, 0, &lock); 128 reg_base + ASS_CLK_GATE, 5, 0, &lock);
125 129
130 for (i = 0; i < clk_data.clk_num; i++) {
131 if (IS_ERR(clk_table[i])) {
132 dev_err(&pdev->dev, "failed to register clock %d\n", i);
133 ret = PTR_ERR(clk_table[i]);
134 goto unregister;
135 }
136 }
137
138 ret = of_clk_add_provider(pdev->dev.of_node, of_clk_src_onecell_get,
139 &clk_data);
140 if (ret) {
141 dev_err(&pdev->dev, "failed to add clock provider\n");
142 goto unregister;
143 }
144
126#ifdef CONFIG_PM_SLEEP 145#ifdef CONFIG_PM_SLEEP
127 register_syscore_ops(&exynos_audss_clk_syscore_ops); 146 register_syscore_ops(&exynos_audss_clk_syscore_ops);
128#endif 147#endif
129 148
130 pr_info("Exynos: Audss: clock setup completed\n"); 149 dev_info(&pdev->dev, "setup completed\n");
150
151 return 0;
152
153unregister:
154 for (i = 0; i < clk_data.clk_num; i++) {
155 if (!IS_ERR(clk_table[i]))
156 clk_unregister(clk_table[i]);
157 }
158
159 return ret;
160}
161
162static int exynos_audss_clk_remove(struct platform_device *pdev)
163{
164 int i;
165
166 of_clk_del_provider(pdev->dev.of_node);
167
168 for (i = 0; i < clk_data.clk_num; i++) {
169 if (!IS_ERR(clk_table[i]))
170 clk_unregister(clk_table[i]);
171 }
172
173 return 0;
131} 174}
132CLK_OF_DECLARE(exynos4210_audss_clk, "samsung,exynos4210-audss-clock", 175
133 exynos_audss_clk_init); 176static const struct of_device_id exynos_audss_clk_of_match[] = {
134CLK_OF_DECLARE(exynos5250_audss_clk, "samsung,exynos5250-audss-clock", 177 { .compatible = "samsung,exynos4210-audss-clock", },
135 exynos_audss_clk_init); 178 { .compatible = "samsung,exynos5250-audss-clock", },
179 {},
180};
181
182static struct platform_driver exynos_audss_clk_driver = {
183 .driver = {
184 .name = "exynos-audss-clk",
185 .owner = THIS_MODULE,
186 .of_match_table = exynos_audss_clk_of_match,
187 },
188 .probe = exynos_audss_clk_probe,
189 .remove = exynos_audss_clk_remove,
190};
191
192static int __init exynos_audss_clk_init(void)
193{
194 return platform_driver_register(&exynos_audss_clk_driver);
195}
196core_initcall(exynos_audss_clk_init);
197
198static void __exit exynos_audss_clk_exit(void)
199{
200 platform_driver_unregister(&exynos_audss_clk_driver);
201}
202module_exit(exynos_audss_clk_exit);
203
204MODULE_AUTHOR("Padmavathi Venna <padma.v@samsung.com>");
205MODULE_DESCRIPTION("Exynos Audio Subsystem Clock Controller");
206MODULE_LICENSE("GPL v2");
207MODULE_ALIAS("platform:exynos-audss-clk");