diff options
author | Sang-Hun Lee <sanlee@nvidia.com> | 2012-06-20 16:16:57 -0700 |
---|---|---|
committer | Varun Wadekar <vwadekar@nvidia.com> | 2012-07-12 10:12:16 +0530 |
commit | a6f1c5312b99deb8b69f7878129f4993f44bd04f (patch) | |
tree | 8e3f1eea362ff25a6b7795e742cdafd04aabd702 /arch/arm | |
parent | d4556687b3b5518924e17324c8dd3f2496ec1fd4 (diff) |
ARM: tegra: emc: add reference counting to early ack disablement
Bug 995950
Signed-off-by: Sang-Hun Lee <sanlee@nvidia.com>
Reviewed-on: http://git-master/r/110190
(cherry picked from commit cbfc31fb126cd651157125d1785135eced6587dd)
Change-Id: I44eb889235db82b0efda238b87be5612425afb9d
Reviewed-on: http://git-master/r/110978
Reviewed-by: Simone Willett <swillett@nvidia.com>
Tested-by: Simone Willett <swillett@nvidia.com>
Diffstat (limited to 'arch/arm')
-rw-r--r-- | arch/arm/mach-tegra/include/mach/clk.h | 18 | ||||
-rw-r--r-- | arch/arm/mach-tegra/tegra3_emc.c | 39 | ||||
-rw-r--r-- | arch/arm/mach-tegra/tegra3_emc.h | 3 |
3 files changed, 51 insertions, 9 deletions
diff --git a/arch/arm/mach-tegra/include/mach/clk.h b/arch/arm/mach-tegra/include/mach/clk.h index 6792962e2eca..d5846c548350 100644 --- a/arch/arm/mach-tegra/include/mach/clk.h +++ b/arch/arm/mach-tegra/include/mach/clk.h @@ -6,7 +6,7 @@ * Author: * Erik Gilling <konkers@google.com> * - * Copyright (C) 2010-2011 NVIDIA Corporation + * 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 @@ -41,7 +41,23 @@ void tegra_periph_reset_assert(struct clk *c); int tegra_dvfs_set_rate(struct clk *c, unsigned long rate); unsigned long clk_get_rate_all_locked(struct clk *c); +#ifdef CONFIG_ARCH_TEGRA_2x_SOC void tegra2_sdmmc_tap_delay(struct clk *c, int delay); + +static inline int tegra_emc_enable_eack(void) { + return 0; +} + +static inline int tegra_emc_disable_eack(void) { + return 0; +} +#else +static inline void tegra2_sdmmc_tap_delay(struct clk *c, int delay) +{ +} +int tegra_emc_enable_eack(void); +int tegra_emc_disable_eack(void); +#endif int tegra_dvfs_rail_disable_by_name(const char *reg_id); int tegra_clk_cfg_ex(struct clk *c, enum tegra_clk_ex_param p, u32 setting); int tegra_register_clk_rate_notifier(struct clk *c, struct notifier_block *nb); diff --git a/arch/arm/mach-tegra/tegra3_emc.c b/arch/arm/mach-tegra/tegra3_emc.c index c8bbafe368f9..cfe7e9d8ed34 100644 --- a/arch/arm/mach-tegra/tegra3_emc.c +++ b/arch/arm/mach-tegra/tegra3_emc.c @@ -1,7 +1,7 @@ /* * arch/arm/mach-tegra/tegra3_emc.c * - * Copyright (C) 2011 NVIDIA Corporation + * Copyright (C) 2012 NVIDIA Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -1172,24 +1172,51 @@ int tegra_emc_set_over_temp_state(unsigned long state) return 0; } -int tegra_emc_set_eack_state(unsigned long state) +/* non-zero state value will reduce eack_disable_refcnt */ +static int tegra_emc_set_eack_state(unsigned long state) { unsigned long flags; u32 mc_override; + static int eack_disable_refcnt = 0; spin_lock_irqsave(&emc_access_lock, flags); - mc_override = mc_readl(MC_EMEM_ARB_OVERRIDE); - - if (state) + /* + * refcnt > 0 implies there is at least one client requiring eack + * disabled. refcnt of 0 implies eack is enabled + */ + if (eack_disable_refcnt == 1 && state) { + mc_override = mc_readl(MC_EMEM_ARB_OVERRIDE); enable_early_ack(mc_override); - else + } else if (eack_disable_refcnt == 0 && !state) { + mc_override = mc_readl(MC_EMEM_ARB_OVERRIDE); disable_early_ack(mc_override); + } + + if (state) { + if (likely(eack_disable_refcnt > 0)) { + --eack_disable_refcnt; + } else { + pr_err("%s: Ignored a request to underflow eack " + "disable reference counter\n",__func__); + dump_stack(); + } + } else { + ++eack_disable_refcnt; + } spin_unlock_irqrestore(&emc_access_lock, flags); return 0; } +int tegra_emc_enable_eack(void) { + return tegra_emc_set_eack_state(1); +} + +int tegra_emc_disable_eack(void) { + return tegra_emc_set_eack_state(0); +} + #ifdef CONFIG_DEBUG_FS static struct dentry *emc_debugfs_root; diff --git a/arch/arm/mach-tegra/tegra3_emc.h b/arch/arm/mach-tegra/tegra3_emc.h index 185d77762da2..f59654295ba4 100644 --- a/arch/arm/mach-tegra/tegra3_emc.h +++ b/arch/arm/mach-tegra/tegra3_emc.h @@ -1,7 +1,7 @@ /* * arch/arm/mach-tegra/tegra3_emc.h * - * Copyright (C) 2011 NVIDIA Corporation + * Copyright (C) 2012 NVIDIA Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -61,7 +61,6 @@ void tegra_emc_dram_type_init(struct clk *c); int tegra_emc_get_dram_type(void); int tegra_emc_get_dram_temperature(void); int tegra_emc_set_over_temp_state(unsigned long state); -int tegra_emc_set_eack_state(unsigned long state); #ifdef CONFIG_PM_SLEEP void tegra_mc_timing_restore(void); |