2 * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
4 * This software is licensed under the terms of the GNU General Public
5 * License version 2, as published by the Free Software Foundation, and
6 * may be copied, distributed, and modified under those terms.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
14 #include <linux/export.h>
15 #include <linux/module.h>
16 #include <linux/regmap.h>
17 #include <linux/platform_device.h>
18 #include <linux/clk-provider.h>
19 #include <linux/reset-controller.h>
23 #include "clk-regmap.h"
28 struct qcom_reset_controller reset
;
29 struct clk_onecell_data data
;
34 struct freq_tbl
*qcom_find_freq(const struct freq_tbl
*f
, unsigned long rate
)
43 /* Default to our fastest rate */
46 EXPORT_SYMBOL_GPL(qcom_find_freq
);
48 int qcom_find_src_index(struct clk_hw
*hw
, const struct parent_map
*map
, u8 src
)
50 int i
, num_parents
= clk_hw_get_num_parents(hw
);
52 for (i
= 0; i
< num_parents
; i
++)
53 if (src
== map
[i
].src
)
58 EXPORT_SYMBOL_GPL(qcom_find_src_index
);
61 qcom_cc_map(struct platform_device
*pdev
, const struct qcom_cc_desc
*desc
)
65 struct device
*dev
= &pdev
->dev
;
67 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
68 base
= devm_ioremap_resource(dev
, res
);
70 return ERR_CAST(base
);
72 return devm_regmap_init_mmio(dev
, base
, desc
->config
);
74 EXPORT_SYMBOL_GPL(qcom_cc_map
);
76 static void qcom_cc_del_clk_provider(void *data
)
78 of_clk_del_provider(data
);
81 static void qcom_cc_reset_unregister(void *data
)
83 reset_controller_unregister(data
);
86 static void qcom_cc_gdsc_unregister(void *data
)
88 gdsc_unregister(data
);
91 int qcom_cc_really_probe(struct platform_device
*pdev
,
92 const struct qcom_cc_desc
*desc
, struct regmap
*regmap
)
95 struct device
*dev
= &pdev
->dev
;
97 struct clk_onecell_data
*data
;
99 struct qcom_reset_controller
*reset
;
101 size_t num_clks
= desc
->num_clks
;
102 struct clk_regmap
**rclks
= desc
->clks
;
104 cc
= devm_kzalloc(dev
, sizeof(*cc
) + sizeof(*clks
) * num_clks
,
112 data
->clk_num
= num_clks
;
114 for (i
= 0; i
< num_clks
; i
++) {
116 clks
[i
] = ERR_PTR(-ENOENT
);
119 clk
= devm_clk_register_regmap(dev
, rclks
[i
]);
125 ret
= of_clk_add_provider(dev
->of_node
, of_clk_src_onecell_get
, data
);
129 devm_add_action(dev
, qcom_cc_del_clk_provider
, pdev
->dev
.of_node
);
132 reset
->rcdev
.of_node
= dev
->of_node
;
133 reset
->rcdev
.ops
= &qcom_reset_ops
;
134 reset
->rcdev
.owner
= dev
->driver
->owner
;
135 reset
->rcdev
.nr_resets
= desc
->num_resets
;
136 reset
->regmap
= regmap
;
137 reset
->reset_map
= desc
->resets
;
139 ret
= reset_controller_register(&reset
->rcdev
);
143 devm_add_action(dev
, qcom_cc_reset_unregister
, &reset
->rcdev
);
145 if (desc
->gdscs
&& desc
->num_gdscs
) {
146 ret
= gdsc_register(dev
, desc
->gdscs
, desc
->num_gdscs
,
147 &reset
->rcdev
, regmap
);
152 devm_add_action(dev
, qcom_cc_gdsc_unregister
, dev
);
157 EXPORT_SYMBOL_GPL(qcom_cc_really_probe
);
159 int qcom_cc_probe(struct platform_device
*pdev
, const struct qcom_cc_desc
*desc
)
161 struct regmap
*regmap
;
163 regmap
= qcom_cc_map(pdev
, desc
);
165 return PTR_ERR(regmap
);
167 return qcom_cc_really_probe(pdev
, desc
, regmap
);
169 EXPORT_SYMBOL_GPL(qcom_cc_probe
);
171 MODULE_LICENSE("GPL v2");