2 * Copyright (c) 2014 MediaTek Inc.
3 * Author: James Liao <jamesjj.liao@mediatek.com>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
16 #include <linux/of_address.h>
17 #include <linux/err.h>
19 #include <linux/slab.h>
20 #include <linux/delay.h>
21 #include <linux/clkdev.h>
22 #include <linux/mfd/syscon.h>
27 struct clk_onecell_data
*mtk_alloc_clk_data(unsigned int clk_num
)
30 struct clk_onecell_data
*clk_data
;
32 clk_data
= kzalloc(sizeof(*clk_data
), GFP_KERNEL
);
36 clk_data
->clks
= kcalloc(clk_num
, sizeof(*clk_data
->clks
), GFP_KERNEL
);
40 clk_data
->clk_num
= clk_num
;
42 for (i
= 0; i
< clk_num
; i
++)
43 clk_data
->clks
[i
] = ERR_PTR(-ENOENT
);
52 void mtk_clk_register_fixed_clks(const struct mtk_fixed_clk
*clks
,
53 int num
, struct clk_onecell_data
*clk_data
)
58 for (i
= 0; i
< num
; i
++) {
59 const struct mtk_fixed_clk
*rc
= &clks
[i
];
61 clk
= clk_register_fixed_rate(NULL
, rc
->name
, rc
->parent
, 0,
65 pr_err("Failed to register clk %s: %ld\n",
66 rc
->name
, PTR_ERR(clk
));
71 clk_data
->clks
[rc
->id
] = clk
;
75 void mtk_clk_register_factors(const struct mtk_fixed_factor
*clks
,
76 int num
, struct clk_onecell_data
*clk_data
)
81 for (i
= 0; i
< num
; i
++) {
82 const struct mtk_fixed_factor
*ff
= &clks
[i
];
84 clk
= clk_register_fixed_factor(NULL
, ff
->name
, ff
->parent_name
,
85 CLK_SET_RATE_PARENT
, ff
->mult
, ff
->div
);
88 pr_err("Failed to register clk %s: %ld\n",
89 ff
->name
, PTR_ERR(clk
));
94 clk_data
->clks
[ff
->id
] = clk
;
98 int mtk_clk_register_gates(struct device_node
*node
,
99 const struct mtk_gate
*clks
,
100 int num
, struct clk_onecell_data
*clk_data
)
104 struct regmap
*regmap
;
109 regmap
= syscon_node_to_regmap(node
);
110 if (IS_ERR(regmap
)) {
111 pr_err("Cannot find regmap for %s: %ld\n", node
->full_name
,
113 return PTR_ERR(regmap
);
116 for (i
= 0; i
< num
; i
++) {
117 const struct mtk_gate
*gate
= &clks
[i
];
119 clk
= mtk_clk_register_gate(gate
->name
, gate
->parent_name
,
124 gate
->shift
, gate
->ops
);
127 pr_err("Failed to register clk %s: %ld\n",
128 gate
->name
, PTR_ERR(clk
));
132 clk_data
->clks
[gate
->id
] = clk
;
138 struct clk
*mtk_clk_register_composite(const struct mtk_composite
*mc
,
139 void __iomem
*base
, spinlock_t
*lock
)
142 struct clk_mux
*mux
= NULL
;
143 struct clk_gate
*gate
= NULL
;
144 struct clk_divider
*div
= NULL
;
145 struct clk_hw
*mux_hw
= NULL
, *gate_hw
= NULL
, *div_hw
= NULL
;
146 const struct clk_ops
*mux_ops
= NULL
, *gate_ops
= NULL
, *div_ops
= NULL
;
147 const char * const *parent_names
;
152 if (mc
->mux_shift
>= 0) {
153 mux
= kzalloc(sizeof(*mux
), GFP_KERNEL
);
155 return ERR_PTR(-ENOMEM
);
157 mux
->reg
= base
+ mc
->mux_reg
;
158 mux
->mask
= BIT(mc
->mux_width
) - 1;
159 mux
->shift
= mc
->mux_shift
;
163 mux_ops
= &clk_mux_ops
;
165 parent_names
= mc
->parent_names
;
166 num_parents
= mc
->num_parents
;
169 parent_names
= &parent
;
173 if (mc
->gate_shift
>= 0) {
174 gate
= kzalloc(sizeof(*gate
), GFP_KERNEL
);
180 gate
->reg
= base
+ mc
->gate_reg
;
181 gate
->bit_idx
= mc
->gate_shift
;
182 gate
->flags
= CLK_GATE_SET_TO_DISABLE
;
186 gate_ops
= &clk_gate_ops
;
189 if (mc
->divider_shift
>= 0) {
190 div
= kzalloc(sizeof(*div
), GFP_KERNEL
);
196 div
->reg
= base
+ mc
->divider_reg
;
197 div
->shift
= mc
->divider_shift
;
198 div
->width
= mc
->divider_width
;
202 div_ops
= &clk_divider_ops
;
205 clk
= clk_register_composite(NULL
, mc
->name
, parent_names
, num_parents
,
225 void mtk_clk_register_composites(const struct mtk_composite
*mcs
,
226 int num
, void __iomem
*base
, spinlock_t
*lock
,
227 struct clk_onecell_data
*clk_data
)
232 for (i
= 0; i
< num
; i
++) {
233 const struct mtk_composite
*mc
= &mcs
[i
];
235 clk
= mtk_clk_register_composite(mc
, base
, lock
);
238 pr_err("Failed to register clk %s: %ld\n",
239 mc
->name
, PTR_ERR(clk
));
244 clk_data
->clks
[mc
->id
] = clk
;