Commit d8611961 authored by Colin Cross's avatar Colin Cross Committed by Erik Gilling

[ARM] tegra: Add clock support

v2: fixes from Russell King:
	- include linux/io.h instead of asm/io.h
	- fix whitespace in Kconfig
	- Use spin_lock_init to initialize lock
	- Return -ENOSYS instead of BUG for unimplemented clock ops
	- Use proper return values in tegra2 clock ops
    additional changes:
	- Rename some clocks to match dev_ids
	- add rate propagation
	- add debugfs entries
	- add support for clock listed in clk_lookup under multiple dev_ids
v3:
	- Replace per-clock locking with global clock lock
	- Autodetect clock state on init
	- Let clock dividers pick next lower possible frequency
	- Add support for clock init tables
	- Minor bug fixes
	- Fix checkpatch issues
Signed-off-by: default avatarColin Cross <ccross@android.com>
parent 5ad36c5f
...@@ -568,6 +568,7 @@ config ARCH_TEGRA ...@@ -568,6 +568,7 @@ config ARCH_TEGRA
select GENERIC_CLOCKEVENTS select GENERIC_CLOCKEVENTS
select GENERIC_GPIO select GENERIC_GPIO
select HAVE_CLK select HAVE_CLK
select COMMON_CLKDEV
select ARCH_HAS_BARRIERS if CACHE_L2X0 select ARCH_HAS_BARRIERS if CACHE_L2X0
help help
This enables support for NVIDIA Tegra based systems (Tegra APX, This enables support for NVIDIA Tegra based systems (Tegra APX,
......
obj-y += common.o obj-y += common.o
obj-y += io.o obj-y += io.o
obj-y += irq.o obj-y += irq.o
obj-y += clock.o
obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra2_clocks.o
This diff is collapsed.
/*
* arch/arm/mach-tegra/include/mach/clock.h
*
* Copyright (C) 2010 Google, Inc.
*
* Author:
* Colin Cross <ccross@google.com>
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#ifndef __MACH_TEGRA_CLOCK_H
#define __MACH_TEGRA_CLOCK_H
#include <linux/list.h>
#include <asm/clkdev.h>
#define DIV_BUS (1 << 0)
#define DIV_U71 (1 << 1)
#define DIV_U71_FIXED (1 << 2)
#define DIV_2 (1 << 3)
#define PLL_FIXED (1 << 4)
#define PLL_HAS_CPCON (1 << 5)
#define MUX (1 << 6)
#define PLLD (1 << 7)
#define PERIPH_NO_RESET (1 << 8)
#define PERIPH_NO_ENB (1 << 9)
#define PERIPH_EMC_ENB (1 << 10)
#define PERIPH_MANUAL_RESET (1 << 11)
#define PLL_ALT_MISC_REG (1 << 12)
#define ENABLE_ON_INIT (1 << 28)
struct clk;
struct clk_mux_sel {
struct clk *input;
u32 value;
};
struct clk_pll_table {
unsigned long input_rate;
unsigned long output_rate;
u16 n;
u16 m;
u8 p;
u8 cpcon;
};
struct clk_ops {
void (*init)(struct clk *);
int (*enable)(struct clk *);
void (*disable)(struct clk *);
void (*recalc)(struct clk *);
int (*set_parent)(struct clk *, struct clk *);
int (*set_rate)(struct clk *, unsigned long);
unsigned long (*get_rate)(struct clk *);
long (*round_rate)(struct clk *, unsigned long);
unsigned long (*recalculate_rate)(struct clk *);
};
enum clk_state {
UNINITIALIZED = 0,
ON,
OFF,
};
struct clk {
/* node for master clocks list */
struct list_head node;
struct list_head children; /* list of children */
struct list_head sibling; /* node for children */
#ifdef CONFIG_DEBUG_FS
struct dentry *dent;
struct dentry *parent_dent;
#endif
struct clk_ops *ops;
struct clk *parent;
struct clk_lookup lookup;
unsigned long rate;
u32 flags;
u32 refcnt;
const char *name;
u32 reg;
u32 reg_shift;
unsigned int clk_num;
enum clk_state state;
#ifdef CONFIG_DEBUG_FS
bool set;
#endif
/* PLL */
unsigned long input_min;
unsigned long input_max;
unsigned long cf_min;
unsigned long cf_max;
unsigned long vco_min;
unsigned long vco_max;
u32 m;
u32 n;
u32 p;
u32 cpcon;
const struct clk_pll_table *pll_table;
/* DIV */
u32 div;
u32 mul;
/* MUX */
const struct clk_mux_sel *inputs;
u32 sel;
u32 reg_mask;
};
struct clk_duplicate {
const char *name;
struct clk_lookup lookup;
};
struct tegra_clk_init_table {
const char *name;
const char *parent;
unsigned long rate;
bool enabled;
};
void tegra2_init_clocks(void);
void tegra2_periph_reset_deassert(struct clk *c);
void tegra2_periph_reset_assert(struct clk *c);
void clk_init(struct clk *clk);
struct clk *tegra_get_clock_by_name(const char *name);
unsigned long clk_measure_input_freq(void);
void clk_disable_locked(struct clk *c);
int clk_enable_locked(struct clk *c);
int clk_set_parent_locked(struct clk *c, struct clk *parent);
int clk_reparent(struct clk *c, struct clk *parent);
void tegra_clk_init_from_table(struct tegra_clk_init_table *table);
#endif
...@@ -25,6 +25,21 @@ ...@@ -25,6 +25,21 @@
#include <mach/iomap.h> #include <mach/iomap.h>
#include "board.h" #include "board.h"
#include "clock.h"
static __initdata struct tegra_clk_init_table common_clk_init_table[] = {
/* name parent rate enabled */
{ "clk_m", NULL, 0, true },
{ "pll_p", "clk_m", 216000000, true },
{ "pll_p_out1", "pll_p", 28800000, true },
{ "pll_p_out2", "pll_p", 48000000, true },
{ "pll_p_out3", "pll_p", 72000000, true },
{ "pll_p_out4", "pll_p", 108000000, true },
{ "sys", "pll_p_out4", 108000000, true },
{ "hclk", "sys", 108000000, true },
{ "pclk", "hclk", 54000000, true },
{ NULL, NULL, 0, 0},
};
void __init tegra_init_cache(void) void __init tegra_init_cache(void)
{ {
...@@ -40,5 +55,7 @@ void __init tegra_init_cache(void) ...@@ -40,5 +55,7 @@ void __init tegra_init_cache(void)
void __init tegra_common_init(void) void __init tegra_common_init(void)
{ {
tegra_init_clock();
tegra_clk_init_from_table(common_clk_init_table);
tegra_init_cache(); tegra_init_cache();
} }
/*
* arch/arm/mach-tegra/include/mach/clk.h
*
* Copyright (C) 2010 Google, Inc.
*
* Author:
* Erik Gilling <konkers@google.com>
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#ifndef __MACH_CLK_H
#define __MACH_CLK_H
void tegra_periph_reset_deassert(struct clk *c);
void tegra_periph_reset_assert(struct clk *c);
#endif
/*
* arch/arm/mach-tegra/include/mach/clkdev.h
*
* Copyright (C) 2010 Google, Inc.
*
* Author:
* Colin Cross <ccross@google.com>
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#ifndef __MACH_CLKDEV_H
#define __MACH_CLKDEV_H
static inline int __clk_get(struct clk *clk)
{
return 1;
}
static inline void __clk_put(struct clk *clk)
{
}
#endif
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment