| /* |
| * arch/arm/mach-tegra/include/mach/clock.h |
| * |
| * Copyright (C) 2010 Google, Inc. |
| * |
| * Author: |
| * Colin Cross <ccross@google.com> |
| * |
| * Copyright (C) 2010-2012, NVIDIA Corporation. |
| * |
| * 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 |
| |
| #ifdef CONFIG_ARCH_TEGRA_2x_SOC |
| #define USE_PLL_LOCK_BITS 0 /* Never use lock bits on Tegra2 */ |
| #else |
| #define USE_PLL_LOCK_BITS 1 /* Use lock bits for PLL stabiliation */ |
| #define USE_PLLE_SS 1 /* Use spread spectrum coefficients for PLLE */ |
| #define PLL_POST_LOCK_DELAY 50 /* Safety delay after lock is detected */ |
| #endif |
| |
| #define DIV_BUS (1 << 0) |
| #define DIV_U71 (1 << 1) |
| #define DIV_U71_FIXED (1 << 2) |
| #define DIV_2 (1 << 3) |
| #define DIV_U16 (1 << 4) |
| #define PLL_FIXED (1 << 5) |
| #define PLL_HAS_CPCON (1 << 6) |
| #define MUX (1 << 7) |
| #define PLLD (1 << 8) |
| #define PERIPH_NO_RESET (1 << 9) |
| #define PERIPH_NO_ENB (1 << 10) |
| #define PERIPH_EMC_ENB (1 << 11) |
| #define PERIPH_MANUAL_RESET (1 << 12) |
| #define PLL_ALT_MISC_REG (1 << 13) |
| #define PLLU (1 << 14) |
| #define PLLX (1 << 15) |
| #define MUX_PWM (1 << 16) |
| #define MUX8 (1 << 17) |
| #define DIV_U151_UART (1 << 18) |
| #define MUX_CLK_OUT (1 << 19) |
| #define PLLM (1 << 20) |
| #define DIV_U71_INT (1 << 21) |
| #define DIV_U71_IDLE (1 << 22) |
| #define DIV_U151 (1 << 23) |
| #define ENABLE_ON_INIT (1 << 28) |
| #define PERIPH_ON_APB (1 << 29) |
| #define PERIPH_ON_CBUS (1 << 30) |
| |
| #ifndef __ASSEMBLY__ |
| |
| #include <linux/clkdev.h> |
| #include <linux/list.h> |
| #include <linux/mutex.h> |
| #include <linux/spinlock.h> |
| #include <asm/cputime.h> |
| |
| #include <mach/clk.h> |
| #define MAX_SAME_LIMIT_SKU_IDS 16 |
| |
| struct clk; |
| |
| struct clk_mux_sel { |
| struct clk *input; |
| u32 value; |
| }; |
| |
| struct clk_pll_freq_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 *); |
| int (*set_parent)(struct clk *, struct clk *); |
| int (*set_rate)(struct clk *, unsigned long); |
| long (*round_rate)(struct clk *, unsigned long); |
| int (*clk_cfg_ex)(struct clk *, enum tegra_clk_ex_param, u32); |
| void (*reset)(struct clk *, bool); |
| int (*shared_bus_update)(struct clk *); |
| }; |
| |
| struct clk_stats { |
| cputime64_t time_on; |
| u64 last_update; |
| }; |
| |
| enum cpu_mode { |
| MODE_G = 0, |
| MODE_LP, |
| }; |
| |
| enum shared_bus_users_mode { |
| SHARED_FLOOR = 0, |
| SHARED_BW, |
| SHARED_CEILING, |
| SHARED_AUTO, |
| }; |
| |
| enum clk_state { |
| UNINITIALIZED = 0, |
| ON, |
| OFF, |
| }; |
| |
| struct clk { |
| /* node for master clocks list */ |
| struct list_head node; /* node for list of all clocks */ |
| struct dvfs *dvfs; |
| struct clk_lookup lookup; |
| |
| #ifdef CONFIG_DEBUG_FS |
| struct dentry *dent; |
| #endif |
| bool set; |
| struct clk_ops *ops; |
| unsigned long dvfs_rate; |
| unsigned long rate; |
| unsigned long max_rate; |
| unsigned long min_rate; |
| bool auto_dvfs; |
| bool cansleep; |
| u32 flags; |
| const char *name; |
| |
| u32 refcnt; |
| enum clk_state state; |
| struct clk *parent; |
| u32 div; |
| u32 mul; |
| struct clk_stats stats; |
| |
| const struct clk_mux_sel *inputs; |
| u32 reg; |
| u32 reg_shift; |
| |
| struct list_head shared_bus_list; |
| struct clk_mux_sel shared_bus_backup; |
| |
| union { |
| struct { |
| unsigned int clk_num; |
| } periph; |
| struct { |
| unsigned long input_min; |
| unsigned long input_max; |
| unsigned long cf_min; |
| unsigned long cf_max; |
| unsigned long vco_min; |
| unsigned long vco_max; |
| const struct clk_pll_freq_table *freq_table; |
| int lock_delay; |
| unsigned long fixed_rate; |
| } pll; |
| struct { |
| unsigned long default_rate; |
| } pll_div; |
| struct { |
| u32 sel; |
| u32 reg_mask; |
| } mux; |
| struct { |
| struct clk *main; |
| struct clk *backup; |
| unsigned long backup_rate; |
| enum cpu_mode mode; |
| } cpu; |
| struct { |
| u32 div71; |
| } cclk; |
| struct { |
| struct clk *pclk; |
| struct clk *hclk; |
| struct clk *sclk_low; |
| struct clk *sclk_high; |
| unsigned long threshold; |
| } system; |
| struct { |
| struct list_head node; |
| bool enabled; |
| unsigned long rate; |
| const char *client_id; |
| struct clk *client; |
| u32 client_div; |
| enum shared_bus_users_mode mode; |
| } shared_bus_user; |
| } u; |
| |
| struct raw_notifier_head *rate_change_nh; |
| |
| struct mutex mutex; |
| spinlock_t spinlock; |
| }; |
| |
| 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; |
| }; |
| |
| struct tegra_sku_rate_limit { |
| const char *clk_name; |
| unsigned long max_rate; |
| int sku_ids[MAX_SAME_LIMIT_SKU_IDS]; |
| }; |
| |
| void tegra_soc_init_clocks(void); |
| void tegra_init_max_rate(struct clk *c, unsigned long max_rate); |
| void clk_init(struct clk *clk); |
| struct clk *tegra_get_clock_by_name(const char *name); |
| unsigned long tegra_clk_measure_input_freq(void); |
| int clk_reparent(struct clk *c, struct clk *parent); |
| void tegra_clk_init_from_table(struct tegra_clk_init_table *table); |
| void clk_set_cansleep(struct clk *c); |
| unsigned long clk_get_max_rate(struct clk *c); |
| unsigned long clk_get_min_rate(struct clk *c); |
| unsigned long clk_get_rate_locked(struct clk *c); |
| int clk_set_rate_locked(struct clk *c, unsigned long rate); |
| int clk_set_parent_locked(struct clk *c, struct clk *parent); |
| int tegra_clk_shared_bus_update(struct clk *c); |
| void tegra2_sdmmc_tap_delay(struct clk *c, int delay); |
| void tegra3_set_cpu_skipper_delay(int delay); |
| int tegra_emc_set_rate(unsigned long rate); |
| long tegra_emc_round_rate(unsigned long rate); |
| struct clk *tegra_emc_predict_parent(unsigned long rate, u32 *div_value); |
| void tegra_emc_timing_invalidate(void); |
| #ifdef CONFIG_ARCH_TEGRA_2x_SOC |
| static inline bool tegra_clk_is_parent_allowed(struct clk *c, struct clk *p) |
| { return true; } |
| #else |
| bool tegra_clk_is_parent_allowed(struct clk *c, struct clk *p); |
| #endif |
| |
| static inline bool clk_is_auto_dvfs(struct clk *c) |
| { |
| return c->auto_dvfs; |
| } |
| |
| static inline bool clk_is_dvfs(struct clk *c) |
| { |
| return (c->dvfs != NULL); |
| } |
| |
| static inline bool clk_cansleep(struct clk *c) |
| { |
| return c->cansleep; |
| } |
| |
| static inline void clk_lock_save(struct clk *c, unsigned long *flags) |
| { |
| if (clk_cansleep(c)) { |
| *flags = 0; |
| mutex_lock(&c->mutex); |
| } else { |
| spin_lock_irqsave(&c->spinlock, *flags); |
| } |
| } |
| |
| static inline void clk_unlock_restore(struct clk *c, unsigned long *flags) |
| { |
| if (clk_cansleep(c)) |
| mutex_unlock(&c->mutex); |
| else |
| spin_unlock_irqrestore(&c->spinlock, *flags); |
| } |
| |
| static inline void clk_lock_init(struct clk *c) |
| { |
| mutex_init(&c->mutex); |
| spin_lock_init(&c->spinlock); |
| } |
| |
| #ifdef CONFIG_CPU_FREQ |
| struct cpufreq_frequency_table; |
| |
| struct tegra_cpufreq_table_data { |
| struct cpufreq_frequency_table *freq_table; |
| int throttle_lowest_index; |
| int throttle_highest_index; |
| int suspend_index; |
| }; |
| struct tegra_cpufreq_table_data *tegra_cpufreq_table_get(void); |
| unsigned long tegra_emc_to_cpu_ratio(unsigned long cpu_rate); |
| #ifdef CONFIG_ARCH_TEGRA_2x_SOC |
| static inline int tegra_update_mselect_rate(unsigned long cpu_rate) |
| { return 0; } |
| #else |
| int tegra_update_mselect_rate(unsigned long cpu_rate); |
| #endif |
| #endif |
| |
| #endif |
| #endif |