0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #include <linux/kernel.h>
0013 #include <linux/clkdev.h>
0014 #include <linux/clk-provider.h>
0015 #include <linux/delay.h>
0016 #include <linux/io.h>
0017 #include <linux/of.h>
0018 #include <linux/of_address.h>
0019 #include <linux/of_device.h>
0020 #include <linux/slab.h>
0021
0022 #include "clk.h"
0023
0024 static DEFINE_SPINLOCK(hisi_clk_lock);
0025
0026 struct hisi_clock_data *hisi_clk_alloc(struct platform_device *pdev,
0027 int nr_clks)
0028 {
0029 struct hisi_clock_data *clk_data;
0030 struct resource *res;
0031 struct clk **clk_table;
0032
0033 clk_data = devm_kmalloc(&pdev->dev, sizeof(*clk_data), GFP_KERNEL);
0034 if (!clk_data)
0035 return NULL;
0036
0037 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
0038 if (!res)
0039 return NULL;
0040 clk_data->base = devm_ioremap(&pdev->dev,
0041 res->start, resource_size(res));
0042 if (!clk_data->base)
0043 return NULL;
0044
0045 clk_table = devm_kmalloc_array(&pdev->dev, nr_clks,
0046 sizeof(*clk_table),
0047 GFP_KERNEL);
0048 if (!clk_table)
0049 return NULL;
0050
0051 clk_data->clk_data.clks = clk_table;
0052 clk_data->clk_data.clk_num = nr_clks;
0053
0054 return clk_data;
0055 }
0056 EXPORT_SYMBOL_GPL(hisi_clk_alloc);
0057
0058 struct hisi_clock_data *hisi_clk_init(struct device_node *np,
0059 int nr_clks)
0060 {
0061 struct hisi_clock_data *clk_data;
0062 struct clk **clk_table;
0063 void __iomem *base;
0064
0065 base = of_iomap(np, 0);
0066 if (!base) {
0067 pr_err("%s: failed to map clock registers\n", __func__);
0068 goto err;
0069 }
0070
0071 clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
0072 if (!clk_data)
0073 goto err;
0074
0075 clk_data->base = base;
0076 clk_table = kcalloc(nr_clks, sizeof(*clk_table), GFP_KERNEL);
0077 if (!clk_table)
0078 goto err_data;
0079
0080 clk_data->clk_data.clks = clk_table;
0081 clk_data->clk_data.clk_num = nr_clks;
0082 of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data->clk_data);
0083 return clk_data;
0084 err_data:
0085 kfree(clk_data);
0086 err:
0087 return NULL;
0088 }
0089 EXPORT_SYMBOL_GPL(hisi_clk_init);
0090
0091 int hisi_clk_register_fixed_rate(const struct hisi_fixed_rate_clock *clks,
0092 int nums, struct hisi_clock_data *data)
0093 {
0094 struct clk *clk;
0095 int i;
0096
0097 for (i = 0; i < nums; i++) {
0098 clk = clk_register_fixed_rate(NULL, clks[i].name,
0099 clks[i].parent_name,
0100 clks[i].flags,
0101 clks[i].fixed_rate);
0102 if (IS_ERR(clk)) {
0103 pr_err("%s: failed to register clock %s\n",
0104 __func__, clks[i].name);
0105 goto err;
0106 }
0107 data->clk_data.clks[clks[i].id] = clk;
0108 }
0109
0110 return 0;
0111
0112 err:
0113 while (i--)
0114 clk_unregister_fixed_rate(data->clk_data.clks[clks[i].id]);
0115
0116 return PTR_ERR(clk);
0117 }
0118 EXPORT_SYMBOL_GPL(hisi_clk_register_fixed_rate);
0119
0120 int hisi_clk_register_fixed_factor(const struct hisi_fixed_factor_clock *clks,
0121 int nums,
0122 struct hisi_clock_data *data)
0123 {
0124 struct clk *clk;
0125 int i;
0126
0127 for (i = 0; i < nums; i++) {
0128 clk = clk_register_fixed_factor(NULL, clks[i].name,
0129 clks[i].parent_name,
0130 clks[i].flags, clks[i].mult,
0131 clks[i].div);
0132 if (IS_ERR(clk)) {
0133 pr_err("%s: failed to register clock %s\n",
0134 __func__, clks[i].name);
0135 goto err;
0136 }
0137 data->clk_data.clks[clks[i].id] = clk;
0138 }
0139
0140 return 0;
0141
0142 err:
0143 while (i--)
0144 clk_unregister_fixed_factor(data->clk_data.clks[clks[i].id]);
0145
0146 return PTR_ERR(clk);
0147 }
0148 EXPORT_SYMBOL_GPL(hisi_clk_register_fixed_factor);
0149
0150 int hisi_clk_register_mux(const struct hisi_mux_clock *clks,
0151 int nums, struct hisi_clock_data *data)
0152 {
0153 struct clk *clk;
0154 void __iomem *base = data->base;
0155 int i;
0156
0157 for (i = 0; i < nums; i++) {
0158 u32 mask = BIT(clks[i].width) - 1;
0159
0160 clk = clk_register_mux_table(NULL, clks[i].name,
0161 clks[i].parent_names,
0162 clks[i].num_parents, clks[i].flags,
0163 base + clks[i].offset, clks[i].shift,
0164 mask, clks[i].mux_flags,
0165 clks[i].table, &hisi_clk_lock);
0166 if (IS_ERR(clk)) {
0167 pr_err("%s: failed to register clock %s\n",
0168 __func__, clks[i].name);
0169 goto err;
0170 }
0171
0172 if (clks[i].alias)
0173 clk_register_clkdev(clk, clks[i].alias, NULL);
0174
0175 data->clk_data.clks[clks[i].id] = clk;
0176 }
0177
0178 return 0;
0179
0180 err:
0181 while (i--)
0182 clk_unregister_mux(data->clk_data.clks[clks[i].id]);
0183
0184 return PTR_ERR(clk);
0185 }
0186 EXPORT_SYMBOL_GPL(hisi_clk_register_mux);
0187
0188 int hisi_clk_register_phase(struct device *dev,
0189 const struct hisi_phase_clock *clks,
0190 int nums, struct hisi_clock_data *data)
0191 {
0192 void __iomem *base = data->base;
0193 struct clk *clk;
0194 int i;
0195
0196 for (i = 0; i < nums; i++) {
0197 clk = clk_register_hisi_phase(dev, &clks[i], base,
0198 &hisi_clk_lock);
0199 if (IS_ERR(clk)) {
0200 pr_err("%s: failed to register clock %s\n", __func__,
0201 clks[i].name);
0202 return PTR_ERR(clk);
0203 }
0204
0205 data->clk_data.clks[clks[i].id] = clk;
0206 }
0207
0208 return 0;
0209 }
0210 EXPORT_SYMBOL_GPL(hisi_clk_register_phase);
0211
0212 int hisi_clk_register_divider(const struct hisi_divider_clock *clks,
0213 int nums, struct hisi_clock_data *data)
0214 {
0215 struct clk *clk;
0216 void __iomem *base = data->base;
0217 int i;
0218
0219 for (i = 0; i < nums; i++) {
0220 clk = clk_register_divider_table(NULL, clks[i].name,
0221 clks[i].parent_name,
0222 clks[i].flags,
0223 base + clks[i].offset,
0224 clks[i].shift, clks[i].width,
0225 clks[i].div_flags,
0226 clks[i].table,
0227 &hisi_clk_lock);
0228 if (IS_ERR(clk)) {
0229 pr_err("%s: failed to register clock %s\n",
0230 __func__, clks[i].name);
0231 goto err;
0232 }
0233
0234 if (clks[i].alias)
0235 clk_register_clkdev(clk, clks[i].alias, NULL);
0236
0237 data->clk_data.clks[clks[i].id] = clk;
0238 }
0239
0240 return 0;
0241
0242 err:
0243 while (i--)
0244 clk_unregister_divider(data->clk_data.clks[clks[i].id]);
0245
0246 return PTR_ERR(clk);
0247 }
0248 EXPORT_SYMBOL_GPL(hisi_clk_register_divider);
0249
0250 int hisi_clk_register_gate(const struct hisi_gate_clock *clks,
0251 int nums, struct hisi_clock_data *data)
0252 {
0253 struct clk *clk;
0254 void __iomem *base = data->base;
0255 int i;
0256
0257 for (i = 0; i < nums; i++) {
0258 clk = clk_register_gate(NULL, clks[i].name,
0259 clks[i].parent_name,
0260 clks[i].flags,
0261 base + clks[i].offset,
0262 clks[i].bit_idx,
0263 clks[i].gate_flags,
0264 &hisi_clk_lock);
0265 if (IS_ERR(clk)) {
0266 pr_err("%s: failed to register clock %s\n",
0267 __func__, clks[i].name);
0268 goto err;
0269 }
0270
0271 if (clks[i].alias)
0272 clk_register_clkdev(clk, clks[i].alias, NULL);
0273
0274 data->clk_data.clks[clks[i].id] = clk;
0275 }
0276
0277 return 0;
0278
0279 err:
0280 while (i--)
0281 clk_unregister_gate(data->clk_data.clks[clks[i].id]);
0282
0283 return PTR_ERR(clk);
0284 }
0285 EXPORT_SYMBOL_GPL(hisi_clk_register_gate);
0286
0287 void hisi_clk_register_gate_sep(const struct hisi_gate_clock *clks,
0288 int nums, struct hisi_clock_data *data)
0289 {
0290 struct clk *clk;
0291 void __iomem *base = data->base;
0292 int i;
0293
0294 for (i = 0; i < nums; i++) {
0295 clk = hisi_register_clkgate_sep(NULL, clks[i].name,
0296 clks[i].parent_name,
0297 clks[i].flags,
0298 base + clks[i].offset,
0299 clks[i].bit_idx,
0300 clks[i].gate_flags,
0301 &hisi_clk_lock);
0302 if (IS_ERR(clk)) {
0303 pr_err("%s: failed to register clock %s\n",
0304 __func__, clks[i].name);
0305 continue;
0306 }
0307
0308 if (clks[i].alias)
0309 clk_register_clkdev(clk, clks[i].alias, NULL);
0310
0311 data->clk_data.clks[clks[i].id] = clk;
0312 }
0313 }
0314 EXPORT_SYMBOL_GPL(hisi_clk_register_gate_sep);
0315
0316 void __init hi6220_clk_register_divider(const struct hi6220_divider_clock *clks,
0317 int nums, struct hisi_clock_data *data)
0318 {
0319 struct clk *clk;
0320 void __iomem *base = data->base;
0321 int i;
0322
0323 for (i = 0; i < nums; i++) {
0324 clk = hi6220_register_clkdiv(NULL, clks[i].name,
0325 clks[i].parent_name,
0326 clks[i].flags,
0327 base + clks[i].offset,
0328 clks[i].shift,
0329 clks[i].width,
0330 clks[i].mask_bit,
0331 &hisi_clk_lock);
0332 if (IS_ERR(clk)) {
0333 pr_err("%s: failed to register clock %s\n",
0334 __func__, clks[i].name);
0335 continue;
0336 }
0337
0338 if (clks[i].alias)
0339 clk_register_clkdev(clk, clks[i].alias, NULL);
0340
0341 data->clk_data.clks[clks[i].id] = clk;
0342 }
0343 }