Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  1/*
  2 * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
  3 *
  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.
  7 *
  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
 11 * more details.
 12 *
 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/>.
 15 */
 16
 17#include <linux/clkdev.h>
 18#include <linux/clk.h>
 19#include <linux/clk-provider.h>
 20#include <linux/of.h>
 21#include <linux/clk/tegra.h>
 22#include <linux/reset-controller.h>
 23
 24#include <soc/tegra/fuse.h>
 25
 26#include "clk.h"
 27
 28#define CLK_OUT_ENB_L			0x010
 29#define CLK_OUT_ENB_H			0x014
 30#define CLK_OUT_ENB_U			0x018
 31#define CLK_OUT_ENB_V			0x360
 32#define CLK_OUT_ENB_W			0x364
 33#define CLK_OUT_ENB_X			0x280
 34#define CLK_OUT_ENB_Y			0x298
 35#define CLK_OUT_ENB_SET_L		0x320
 36#define CLK_OUT_ENB_CLR_L		0x324
 37#define CLK_OUT_ENB_SET_H		0x328
 38#define CLK_OUT_ENB_CLR_H		0x32c
 39#define CLK_OUT_ENB_SET_U		0x330
 40#define CLK_OUT_ENB_CLR_U		0x334
 41#define CLK_OUT_ENB_SET_V		0x440
 42#define CLK_OUT_ENB_CLR_V		0x444
 43#define CLK_OUT_ENB_SET_W		0x448
 44#define CLK_OUT_ENB_CLR_W		0x44c
 45#define CLK_OUT_ENB_SET_X		0x284
 46#define CLK_OUT_ENB_CLR_X		0x288
 47#define CLK_OUT_ENB_SET_Y		0x29c
 48#define CLK_OUT_ENB_CLR_Y		0x2a0
 49
 50#define RST_DEVICES_L			0x004
 51#define RST_DEVICES_H			0x008
 52#define RST_DEVICES_U			0x00C
 53#define RST_DEVICES_V			0x358
 54#define RST_DEVICES_W			0x35C
 55#define RST_DEVICES_X			0x28C
 56#define RST_DEVICES_Y			0x2a4
 57#define RST_DEVICES_SET_L		0x300
 58#define RST_DEVICES_CLR_L		0x304
 59#define RST_DEVICES_SET_H		0x308
 60#define RST_DEVICES_CLR_H		0x30c
 61#define RST_DEVICES_SET_U		0x310
 62#define RST_DEVICES_CLR_U		0x314
 63#define RST_DEVICES_SET_V		0x430
 64#define RST_DEVICES_CLR_V		0x434
 65#define RST_DEVICES_SET_W		0x438
 66#define RST_DEVICES_CLR_W		0x43c
 67#define RST_DEVICES_SET_X		0x290
 68#define RST_DEVICES_CLR_X		0x294
 69#define RST_DEVICES_SET_Y		0x2a8
 70#define RST_DEVICES_CLR_Y		0x2ac
 71
 72/* Global data of Tegra CPU CAR ops */
 73static struct tegra_cpu_car_ops dummy_car_ops;
 74struct tegra_cpu_car_ops *tegra_cpu_car_ops = &dummy_car_ops;
 75
 76int *periph_clk_enb_refcnt;
 77static int periph_banks;
 78static struct clk **clks;
 79static int clk_num;
 80static struct clk_onecell_data clk_data;
 81
 82/* Handlers for SoC-specific reset lines */
 83static int (*special_reset_assert)(unsigned long);
 84static int (*special_reset_deassert)(unsigned long);
 85static unsigned int num_special_reset;
 86
 87static struct tegra_clk_periph_regs periph_regs[] = {
 88	[0] = {
 89		.enb_reg = CLK_OUT_ENB_L,
 90		.enb_set_reg = CLK_OUT_ENB_SET_L,
 91		.enb_clr_reg = CLK_OUT_ENB_CLR_L,
 92		.rst_reg = RST_DEVICES_L,
 93		.rst_set_reg = RST_DEVICES_SET_L,
 94		.rst_clr_reg = RST_DEVICES_CLR_L,
 95	},
 96	[1] = {
 97		.enb_reg = CLK_OUT_ENB_H,
 98		.enb_set_reg = CLK_OUT_ENB_SET_H,
 99		.enb_clr_reg = CLK_OUT_ENB_CLR_H,
100		.rst_reg = RST_DEVICES_H,
101		.rst_set_reg = RST_DEVICES_SET_H,
102		.rst_clr_reg = RST_DEVICES_CLR_H,
103	},
104	[2] = {
105		.enb_reg = CLK_OUT_ENB_U,
106		.enb_set_reg = CLK_OUT_ENB_SET_U,
107		.enb_clr_reg = CLK_OUT_ENB_CLR_U,
108		.rst_reg = RST_DEVICES_U,
109		.rst_set_reg = RST_DEVICES_SET_U,
110		.rst_clr_reg = RST_DEVICES_CLR_U,
111	},
112	[3] = {
113		.enb_reg = CLK_OUT_ENB_V,
114		.enb_set_reg = CLK_OUT_ENB_SET_V,
115		.enb_clr_reg = CLK_OUT_ENB_CLR_V,
116		.rst_reg = RST_DEVICES_V,
117		.rst_set_reg = RST_DEVICES_SET_V,
118		.rst_clr_reg = RST_DEVICES_CLR_V,
119	},
120	[4] = {
121		.enb_reg = CLK_OUT_ENB_W,
122		.enb_set_reg = CLK_OUT_ENB_SET_W,
123		.enb_clr_reg = CLK_OUT_ENB_CLR_W,
124		.rst_reg = RST_DEVICES_W,
125		.rst_set_reg = RST_DEVICES_SET_W,
126		.rst_clr_reg = RST_DEVICES_CLR_W,
127	},
128	[5] = {
129		.enb_reg = CLK_OUT_ENB_X,
130		.enb_set_reg = CLK_OUT_ENB_SET_X,
131		.enb_clr_reg = CLK_OUT_ENB_CLR_X,
132		.rst_reg = RST_DEVICES_X,
133		.rst_set_reg = RST_DEVICES_SET_X,
134		.rst_clr_reg = RST_DEVICES_CLR_X,
135	},
136	[6] = {
137		.enb_reg = CLK_OUT_ENB_Y,
138		.enb_set_reg = CLK_OUT_ENB_SET_Y,
139		.enb_clr_reg = CLK_OUT_ENB_CLR_Y,
140		.rst_reg = RST_DEVICES_Y,
141		.rst_set_reg = RST_DEVICES_SET_Y,
142		.rst_clr_reg = RST_DEVICES_CLR_Y,
143	},
144};
145
146static void __iomem *clk_base;
147
148static int tegra_clk_rst_assert(struct reset_controller_dev *rcdev,
149		unsigned long id)
150{
151	/*
152	 * If peripheral is on the APB bus then we must read the APB bus to
153	 * flush the write operation in apb bus. This will avoid peripheral
154	 * access after disabling clock. Since the reset driver has no
155	 * knowledge of which reset IDs represent which devices, simply do
156	 * this all the time.
157	 */
158	tegra_read_chipid();
159
160	if (id < periph_banks * 32) {
161		writel_relaxed(BIT(id % 32),
162			       clk_base + periph_regs[id / 32].rst_set_reg);
163		return 0;
164	} else if (id < periph_banks * 32 + num_special_reset) {
165		return special_reset_assert(id);
166	}
167
168	return -EINVAL;
169}
170
171static int tegra_clk_rst_deassert(struct reset_controller_dev *rcdev,
172		unsigned long id)
173{
174	if (id < periph_banks * 32) {
175		writel_relaxed(BIT(id % 32),
176			       clk_base + periph_regs[id / 32].rst_clr_reg);
177		return 0;
178	} else if (id < periph_banks * 32 + num_special_reset) {
179		return special_reset_deassert(id);
180	}
181
182	return -EINVAL;
183}
184
185struct tegra_clk_periph_regs *get_reg_bank(int clkid)
186{
187	int reg_bank = clkid / 32;
188
189	if (reg_bank < periph_banks)
190		return &periph_regs[reg_bank];
191	else {
192		WARN_ON(1);
193		return NULL;
194	}
195}
196
197struct clk ** __init tegra_clk_init(void __iomem *regs, int num, int banks)
198{
199	clk_base = regs;
200
201	if (WARN_ON(banks > ARRAY_SIZE(periph_regs)))
202		return NULL;
203
204	periph_clk_enb_refcnt = kzalloc(32 * banks *
205				sizeof(*periph_clk_enb_refcnt), GFP_KERNEL);
206	if (!periph_clk_enb_refcnt)
207		return NULL;
208
209	periph_banks = banks;
210
211	clks = kzalloc(num * sizeof(struct clk *), GFP_KERNEL);
212	if (!clks)
213		kfree(periph_clk_enb_refcnt);
214
215	clk_num = num;
216
217	return clks;
218}
219
220void __init tegra_init_dup_clks(struct tegra_clk_duplicate *dup_list,
221				struct clk *clks[], int clk_max)
222{
223	struct clk *clk;
224
225	for (; dup_list->clk_id < clk_max; dup_list++) {
226		clk = clks[dup_list->clk_id];
227		dup_list->lookup.clk = clk;
228		clkdev_add(&dup_list->lookup);
229	}
230}
231
232void __init tegra_init_from_table(struct tegra_clk_init_table *tbl,
233				  struct clk *clks[], int clk_max)
234{
235	struct clk *clk;
236
237	for (; tbl->clk_id < clk_max; tbl++) {
238		clk = clks[tbl->clk_id];
239		if (IS_ERR_OR_NULL(clk)) {
240			pr_err("%s: invalid entry %ld in clks array for id %d\n",
241			       __func__, PTR_ERR(clk), tbl->clk_id);
242			WARN_ON(1);
243
244			continue;
245		}
246
247		if (tbl->parent_id < clk_max) {
248			struct clk *parent = clks[tbl->parent_id];
249			if (clk_set_parent(clk, parent)) {
250				pr_err("%s: Failed to set parent %s of %s\n",
251				       __func__, __clk_get_name(parent),
252				       __clk_get_name(clk));
253				WARN_ON(1);
254			}
255		}
256
257		if (tbl->rate)
258			if (clk_set_rate(clk, tbl->rate)) {
259				pr_err("%s: Failed to set rate %lu of %s\n",
260				       __func__, tbl->rate,
261				       __clk_get_name(clk));
262				WARN_ON(1);
263			}
264
265		if (tbl->state)
266			if (clk_prepare_enable(clk)) {
267				pr_err("%s: Failed to enable %s\n", __func__,
268				       __clk_get_name(clk));
269				WARN_ON(1);
270			}
271	}
272}
273
274static const struct reset_control_ops rst_ops = {
275	.assert = tegra_clk_rst_assert,
276	.deassert = tegra_clk_rst_deassert,
277};
278
279static struct reset_controller_dev rst_ctlr = {
280	.ops = &rst_ops,
281	.owner = THIS_MODULE,
282	.of_reset_n_cells = 1,
283};
284
285void __init tegra_add_of_provider(struct device_node *np)
286{
287	int i;
288
289	for (i = 0; i < clk_num; i++) {
290		if (IS_ERR(clks[i])) {
291			pr_err
292			    ("Tegra clk %d: register failed with %ld\n",
293			     i, PTR_ERR(clks[i]));
294		}
295		if (!clks[i])
296			clks[i] = ERR_PTR(-EINVAL);
297	}
298
299	clk_data.clks = clks;
300	clk_data.clk_num = clk_num;
301	of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
302
303	rst_ctlr.of_node = np;
304	rst_ctlr.nr_resets = periph_banks * 32 + num_special_reset;
305	reset_controller_register(&rst_ctlr);
306}
307
308void __init tegra_init_special_resets(unsigned int num,
309				      int (*assert)(unsigned long),
310				      int (*deassert)(unsigned long))
311{
312	num_special_reset = num;
313	special_reset_assert = assert;
314	special_reset_deassert = deassert;
315}
316
317void __init tegra_register_devclks(struct tegra_devclk *dev_clks, int num)
318{
319	int i;
320
321	for (i = 0; i < num; i++, dev_clks++)
322		clk_register_clkdev(clks[dev_clks->dt_id], dev_clks->con_id,
323				dev_clks->dev_id);
324
325	for (i = 0; i < clk_num; i++) {
326		if (!IS_ERR_OR_NULL(clks[i]))
327			clk_register_clkdev(clks[i], __clk_get_name(clks[i]),
328				"tegra-clk-debug");
329	}
330}
331
332struct clk ** __init tegra_lookup_dt_id(int clk_id,
333					struct tegra_clk *tegra_clk)
334{
335	if (tegra_clk[clk_id].present)
336		return &clks[tegra_clk[clk_id].dt_id];
337	else
338		return NULL;
339}
340
341tegra_clk_apply_init_table_func tegra_clk_apply_init_table;
342
343static int __init tegra_clocks_apply_init_table(void)
344{
345	if (!tegra_clk_apply_init_table)
346		return 0;
347
348	tegra_clk_apply_init_table();
349
350	return 0;
351}
352arch_initcall(tegra_clocks_apply_init_table);