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>
24 #include "clk-regmap.h"
29 struct qcom_reset_controller reset
;
30 struct clk_regmap
**rclks
;
35 struct freq_tbl
*qcom_find_freq(const struct freq_tbl
*f
, unsigned long rate
)
44 /* Default to our fastest rate */
47 EXPORT_SYMBOL_GPL(qcom_find_freq
);
49 int qcom_find_src_index(struct clk_hw
*hw
, const struct parent_map
*map
, u8 src
)
51 int i
, num_parents
= clk_hw_get_num_parents(hw
);
53 for (i
= 0; i
< num_parents
; i
++)
54 if (src
== map
[i
].src
)
59 EXPORT_SYMBOL_GPL(qcom_find_src_index
);
62 qcom_cc_map(struct platform_device
*pdev
, const struct qcom_cc_desc
*desc
)
66 struct device
*dev
= &pdev
->dev
;
68 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
69 base
= devm_ioremap_resource(dev
, res
);
71 return ERR_CAST(base
);
73 return devm_regmap_init_mmio(dev
, base
, desc
->config
);
75 EXPORT_SYMBOL_GPL(qcom_cc_map
);
77 static void qcom_cc_del_clk_provider(void *data
)
79 of_clk_del_provider(data
);
82 static void qcom_cc_reset_unregister(void *data
)
84 reset_controller_unregister(data
);
87 static void qcom_cc_gdsc_unregister(void *data
)
89 gdsc_unregister(data
);
93 * Backwards compatibility with old DTs. Register a pass-through factor 1/1
94 * clock to translate 'path' clk into 'name' clk and regsiter the 'path'
95 * clk as a fixed rate clock if it isn't present.
97 static int _qcom_cc_register_board_clk(struct device
*dev
, const char *path
,
98 const char *name
, unsigned long rate
,
101 struct device_node
*node
= NULL
;
102 struct device_node
*clocks_node
;
103 struct clk_fixed_factor
*factor
;
104 struct clk_fixed_rate
*fixed
;
105 struct clk_init_data init_data
= { };
108 clocks_node
= of_find_node_by_path("/clocks");
110 node
= of_find_node_by_name(clocks_node
, path
);
111 of_node_put(clocks_node
);
114 fixed
= devm_kzalloc(dev
, sizeof(*fixed
), GFP_KERNEL
);
118 fixed
->fixed_rate
= rate
;
119 fixed
->hw
.init
= &init_data
;
121 init_data
.name
= path
;
122 init_data
.ops
= &clk_fixed_rate_ops
;
124 ret
= devm_clk_hw_register(dev
, &fixed
->hw
);
131 factor
= devm_kzalloc(dev
, sizeof(*factor
), GFP_KERNEL
);
135 factor
->mult
= factor
->div
= 1;
136 factor
->hw
.init
= &init_data
;
138 init_data
.name
= name
;
139 init_data
.parent_names
= &path
;
140 init_data
.num_parents
= 1;
142 init_data
.ops
= &clk_fixed_factor_ops
;
144 ret
= devm_clk_hw_register(dev
, &factor
->hw
);
152 int qcom_cc_register_board_clk(struct device
*dev
, const char *path
,
153 const char *name
, unsigned long rate
)
155 bool add_factor
= true;
156 struct device_node
*node
;
158 /* The RPM clock driver will add the factor clock if present */
159 if (IS_ENABLED(CONFIG_QCOM_RPMCC
)) {
160 node
= of_find_compatible_node(NULL
, NULL
, "qcom,rpmcc");
161 if (of_device_is_available(node
))
166 return _qcom_cc_register_board_clk(dev
, path
, name
, rate
, add_factor
);
168 EXPORT_SYMBOL_GPL(qcom_cc_register_board_clk
);
170 int qcom_cc_register_sleep_clk(struct device
*dev
)
172 return _qcom_cc_register_board_clk(dev
, "sleep_clk", "sleep_clk_src",
175 EXPORT_SYMBOL_GPL(qcom_cc_register_sleep_clk
);
177 static struct clk_hw
*qcom_cc_clk_hw_get(struct of_phandle_args
*clkspec
,
180 struct qcom_cc
*cc
= data
;
181 unsigned int idx
= clkspec
->args
[0];
183 if (idx
>= cc
->num_rclks
) {
184 pr_err("%s: invalid index %u\n", __func__
, idx
);
185 return ERR_PTR(-EINVAL
);
188 return cc
->rclks
[idx
] ? &cc
->rclks
[idx
]->hw
: ERR_PTR(-ENOENT
);
191 int qcom_cc_really_probe(struct platform_device
*pdev
,
192 const struct qcom_cc_desc
*desc
, struct regmap
*regmap
)
195 struct device
*dev
= &pdev
->dev
;
196 struct qcom_reset_controller
*reset
;
198 struct gdsc_desc
*scd
;
199 size_t num_clks
= desc
->num_clks
;
200 struct clk_regmap
**rclks
= desc
->clks
;
202 cc
= devm_kzalloc(dev
, sizeof(*cc
), GFP_KERNEL
);
207 cc
->num_rclks
= num_clks
;
209 for (i
= 0; i
< num_clks
; i
++) {
213 ret
= devm_clk_register_regmap(dev
, rclks
[i
]);
218 ret
= of_clk_add_hw_provider(dev
->of_node
, qcom_cc_clk_hw_get
, cc
);
222 ret
= devm_add_action_or_reset(dev
, qcom_cc_del_clk_provider
,
229 reset
->rcdev
.of_node
= dev
->of_node
;
230 reset
->rcdev
.ops
= &qcom_reset_ops
;
231 reset
->rcdev
.owner
= dev
->driver
->owner
;
232 reset
->rcdev
.nr_resets
= desc
->num_resets
;
233 reset
->regmap
= regmap
;
234 reset
->reset_map
= desc
->resets
;
236 ret
= reset_controller_register(&reset
->rcdev
);
240 ret
= devm_add_action_or_reset(dev
, qcom_cc_reset_unregister
,
246 if (desc
->gdscs
&& desc
->num_gdscs
) {
247 scd
= devm_kzalloc(dev
, sizeof(*scd
), GFP_KERNEL
);
251 scd
->scs
= desc
->gdscs
;
252 scd
->num
= desc
->num_gdscs
;
253 ret
= gdsc_register(scd
, &reset
->rcdev
, regmap
);
256 ret
= devm_add_action_or_reset(dev
, qcom_cc_gdsc_unregister
,
264 EXPORT_SYMBOL_GPL(qcom_cc_really_probe
);
266 int qcom_cc_probe(struct platform_device
*pdev
, const struct qcom_cc_desc
*desc
)
268 struct regmap
*regmap
;
270 regmap
= qcom_cc_map(pdev
, desc
);
272 return PTR_ERR(regmap
);
274 return qcom_cc_really_probe(pdev
, desc
, regmap
);
276 EXPORT_SYMBOL_GPL(qcom_cc_probe
);
278 MODULE_LICENSE("GPL v2");