2 * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation.
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 #include <linux/clk.h>
18 #include <linux/clk-provider.h>
20 #include <linux/clk/tegra.h>
24 #define CLK_OUT_ENB_L 0x010
25 #define CLK_OUT_ENB_H 0x014
26 #define CLK_OUT_ENB_U 0x018
27 #define CLK_OUT_ENB_V 0x360
28 #define CLK_OUT_ENB_W 0x364
29 #define CLK_OUT_ENB_X 0x280
30 #define CLK_OUT_ENB_SET_L 0x320
31 #define CLK_OUT_ENB_CLR_L 0x324
32 #define CLK_OUT_ENB_SET_H 0x328
33 #define CLK_OUT_ENB_CLR_H 0x32c
34 #define CLK_OUT_ENB_SET_U 0x330
35 #define CLK_OUT_ENB_CLR_U 0x334
36 #define CLK_OUT_ENB_SET_V 0x440
37 #define CLK_OUT_ENB_CLR_V 0x444
38 #define CLK_OUT_ENB_SET_W 0x448
39 #define CLK_OUT_ENB_CLR_W 0x44c
40 #define CLK_OUT_ENB_SET_X 0x284
41 #define CLK_OUT_ENB_CLR_X 0x288
43 #define RST_DEVICES_L 0x004
44 #define RST_DEVICES_H 0x008
45 #define RST_DEVICES_U 0x00C
46 #define RST_DFLL_DVCO 0x2F4
47 #define RST_DEVICES_V 0x358
48 #define RST_DEVICES_W 0x35C
49 #define RST_DEVICES_X 0x28C
50 #define RST_DEVICES_SET_L 0x300
51 #define RST_DEVICES_CLR_L 0x304
52 #define RST_DEVICES_SET_H 0x308
53 #define RST_DEVICES_CLR_H 0x30c
54 #define RST_DEVICES_SET_U 0x310
55 #define RST_DEVICES_CLR_U 0x314
56 #define RST_DEVICES_SET_V 0x430
57 #define RST_DEVICES_CLR_V 0x434
58 #define RST_DEVICES_SET_W 0x438
59 #define RST_DEVICES_CLR_W 0x43c
61 /* Global data of Tegra CPU CAR ops */
62 static struct tegra_cpu_car_ops dummy_car_ops
;
63 struct tegra_cpu_car_ops
*tegra_cpu_car_ops
= &dummy_car_ops
;
65 int *periph_clk_enb_refcnt
;
66 static int periph_banks
;
67 static struct clk
**clks
;
69 static struct clk_onecell_data clk_data
;
71 static struct tegra_clk_periph_regs periph_regs
[] = {
73 .enb_reg
= CLK_OUT_ENB_L
,
74 .enb_set_reg
= CLK_OUT_ENB_SET_L
,
75 .enb_clr_reg
= CLK_OUT_ENB_CLR_L
,
76 .rst_reg
= RST_DEVICES_L
,
77 .rst_set_reg
= RST_DEVICES_SET_L
,
78 .rst_clr_reg
= RST_DEVICES_CLR_L
,
81 .enb_reg
= CLK_OUT_ENB_H
,
82 .enb_set_reg
= CLK_OUT_ENB_SET_H
,
83 .enb_clr_reg
= CLK_OUT_ENB_CLR_H
,
84 .rst_reg
= RST_DEVICES_H
,
85 .rst_set_reg
= RST_DEVICES_SET_H
,
86 .rst_clr_reg
= RST_DEVICES_CLR_H
,
89 .enb_reg
= CLK_OUT_ENB_U
,
90 .enb_set_reg
= CLK_OUT_ENB_SET_U
,
91 .enb_clr_reg
= CLK_OUT_ENB_CLR_U
,
92 .rst_reg
= RST_DEVICES_U
,
93 .rst_set_reg
= RST_DEVICES_SET_U
,
94 .rst_clr_reg
= RST_DEVICES_CLR_U
,
97 .enb_reg
= CLK_OUT_ENB_V
,
98 .enb_set_reg
= CLK_OUT_ENB_SET_V
,
99 .enb_clr_reg
= CLK_OUT_ENB_CLR_V
,
100 .rst_reg
= RST_DEVICES_V
,
101 .rst_set_reg
= RST_DEVICES_SET_V
,
102 .rst_clr_reg
= RST_DEVICES_CLR_V
,
105 .enb_reg
= CLK_OUT_ENB_W
,
106 .enb_set_reg
= CLK_OUT_ENB_SET_W
,
107 .enb_clr_reg
= CLK_OUT_ENB_CLR_W
,
108 .rst_reg
= RST_DEVICES_W
,
109 .rst_set_reg
= RST_DEVICES_SET_W
,
110 .rst_clr_reg
= RST_DEVICES_CLR_W
,
114 struct tegra_clk_periph_regs
*get_reg_bank(int clkid
)
116 int reg_bank
= clkid
/ 32;
118 if (reg_bank
< periph_banks
)
119 return &periph_regs
[reg_bank
];
126 struct clk
** __init
tegra_clk_init(int num
, int banks
)
128 if (WARN_ON(banks
> ARRAY_SIZE(periph_regs
)))
131 periph_clk_enb_refcnt
= kzalloc(32 * banks
*
132 sizeof(*periph_clk_enb_refcnt
), GFP_KERNEL
);
133 if (!periph_clk_enb_refcnt
)
136 periph_banks
= banks
;
138 clks
= kzalloc(num
* sizeof(struct clk
*), GFP_KERNEL
);
140 kfree(periph_clk_enb_refcnt
);
147 void __init
tegra_init_dup_clks(struct tegra_clk_duplicate
*dup_list
,
148 struct clk
*clks
[], int clk_max
)
152 for (; dup_list
->clk_id
< clk_max
; dup_list
++) {
153 clk
= clks
[dup_list
->clk_id
];
154 dup_list
->lookup
.clk
= clk
;
155 clkdev_add(&dup_list
->lookup
);
159 void __init
tegra_init_from_table(struct tegra_clk_init_table
*tbl
,
160 struct clk
*clks
[], int clk_max
)
164 for (; tbl
->clk_id
< clk_max
; tbl
++) {
165 clk
= clks
[tbl
->clk_id
];
166 if (IS_ERR_OR_NULL(clk
))
169 if (tbl
->parent_id
< clk_max
) {
170 struct clk
*parent
= clks
[tbl
->parent_id
];
171 if (clk_set_parent(clk
, parent
)) {
172 pr_err("%s: Failed to set parent %s of %s\n",
173 __func__
, __clk_get_name(parent
),
174 __clk_get_name(clk
));
180 if (clk_set_rate(clk
, tbl
->rate
)) {
181 pr_err("%s: Failed to set rate %lu of %s\n",
183 __clk_get_name(clk
));
188 if (clk_prepare_enable(clk
)) {
189 pr_err("%s: Failed to enable %s\n", __func__
,
190 __clk_get_name(clk
));
196 void __init
tegra_add_of_provider(struct device_node
*np
)
200 for (i
= 0; i
< clk_num
; i
++) {
201 if (IS_ERR(clks
[i
])) {
203 ("Tegra clk %d: register failed with %ld\n",
204 i
, PTR_ERR(clks
[i
]));
207 clks
[i
] = ERR_PTR(-EINVAL
);
210 clk_data
.clks
= clks
;
211 clk_data
.clk_num
= clk_num
;
212 of_clk_add_provider(np
, of_clk_src_onecell_get
, &clk_data
);
215 tegra_clk_apply_init_table_func tegra_clk_apply_init_table
;
217 void __init
tegra_clocks_apply_init_table(void)
219 if (!tegra_clk_apply_init_table
)
222 tegra_clk_apply_init_table();