summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlok Chauhan <alokc@nvidia.com>2011-08-09 10:49:11 +0530
committerManish Tuteja <mtuteja@nvidia.com>2011-08-11 03:36:38 -0700
commit437596050c805c77783e17e6b70cf169f8cb223f (patch)
tree97165875a7ed7185b192f4c5f4ab3e4ebb7b0802
parent9f46cc5ba4d6f8bcace3bec46a874750740795a8 (diff)
arm: tegra: clock: Reading APB bus before disabling clocktegra-11.2.13
It may be possible that write operation on apb bus does not get complete before disabling clock if the clock is disabled just after the write on apb bus. To have proper sequence of operation, it is require to read back the apb bus to make sure the write operation is completed. bug 833341 This is cherry pick of change http://git-master/r/#change,32556 in main but hand-merged. Change-Id: Ifdabd7507d2bd738da3880cff6756a9a7b489e4b Reviewed-on: http://git-master/r/45981 Reviewed-by: Alok Chauhan <alokc@nvidia.com> Tested-by: Alok Chauhan <alokc@nvidia.com> Reviewed-by: Bharat Nihalani <bnihalani@nvidia.com>
-rw-r--r--arch/arm/mach-tegra/clock.h1
-rw-r--r--arch/arm/mach-tegra/tegra2_clocks.c83
2 files changed, 53 insertions, 31 deletions
diff --git a/arch/arm/mach-tegra/clock.h b/arch/arm/mach-tegra/clock.h
index 21531895867d..8192fa8197a2 100644
--- a/arch/arm/mach-tegra/clock.h
+++ b/arch/arm/mach-tegra/clock.h
@@ -41,6 +41,7 @@
#define PLL_ALT_MISC_REG (1 << 13)
#define PLLU (1 << 14)
#define ENABLE_ON_INIT (1 << 28)
+#define PERIPH_ON_APB (1 << 29)
#define MAX_SAME_LIMIT_SKU_IDS 16
diff --git a/arch/arm/mach-tegra/tegra2_clocks.c b/arch/arm/mach-tegra/tegra2_clocks.c
index 53af5140c2a8..6292414f48db 100644
--- a/arch/arm/mach-tegra/tegra2_clocks.c
+++ b/arch/arm/mach-tegra/tegra2_clocks.c
@@ -153,6 +153,9 @@
static void __iomem *reg_clk_base = IO_ADDRESS(TEGRA_CLK_RESET_BASE);
static void __iomem *reg_pmc_base = IO_ADDRESS(TEGRA_PMC_BASE);
+static void __iomem *misc_gp_hidrev_base = IO_ADDRESS(TEGRA_APB_MISC_BASE);
+
+#define MISC_GP_HIDREV 0x804
/*
* Some peripheral clocks share an enable bit, so refcount the enable bits
@@ -168,6 +171,8 @@ static int tegra_periph_clk_enable_refcount[3 * 32];
__raw_writel(value, (u32)reg_pmc_base + (reg))
#define pmc_readl(reg) \
__raw_readl((u32)reg_pmc_base + (reg))
+#define chipid_readl() \
+ __raw_readl((u32)misc_gp_hidrev_base + MISC_GP_HIDREV)
unsigned long clk_measure_input_freq(void)
{
@@ -975,25 +980,41 @@ static int tegra2_periph_clk_enable(struct clk *c)
static void tegra2_periph_clk_disable(struct clk *c)
{
+ unsigned long val;
pr_debug("%s on clock %s\n", __func__, c->name);
if (c->refcnt)
tegra_periph_clk_enable_refcount[c->u.periph.clk_num]--;
- if (tegra_periph_clk_enable_refcount[c->u.periph.clk_num] == 0)
+ if (tegra_periph_clk_enable_refcount[c->u.periph.clk_num] == 0) {
+ /* If peripheral is in the APB bus then read the APB bus to
+ * flush the write operation in apb bus. This will avoid the
+ * peripheral access after disabling clock*/
+ if (c->flags & PERIPH_ON_APB)
+ val = chipid_readl();
+
clk_writel(PERIPH_CLK_TO_ENB_BIT(c),
CLK_OUT_ENB_CLR + PERIPH_CLK_TO_ENB_SET_REG(c));
+ }
}
static void tegra2_periph_clk_reset(struct clk *c, bool assert)
{
unsigned long base = assert ? RST_DEVICES_SET : RST_DEVICES_CLR;
+ unsigned long val;
pr_debug("%s %s on clock %s\n", __func__,
assert ? "assert" : "deassert", c->name);
- if (!(c->flags & PERIPH_NO_RESET))
+ if (!(c->flags & PERIPH_NO_RESET)) {
+ /* If peripheral is in the APB bus then read the APB bus to
+ * flush the write operation in apb bus. This will avoid the
+ * peripheral access after disabling clock*/
+ if (c->flags & PERIPH_ON_APB)
+ val = chipid_readl();
+
clk_writel(PERIPH_CLK_TO_ENB_BIT(c),
base + PERIPH_CLK_TO_ENB_SET_REG(c));
+ }
}
static int tegra2_periph_clk_set_parent(struct clk *c, struct clk *p)
@@ -2114,27 +2135,27 @@ static struct clk tegra_clk_emc = {
}
struct clk tegra_list_periph_clks[] = {
- PERIPH_CLK("rtc", "rtc-tegra", NULL, 4, 0, 0x31E, 32768, mux_clk_32k, PERIPH_NO_RESET),
- PERIPH_CLK("kbc", "tegra-kbc", NULL, 36, 0, 0x31E, 32768, mux_clk_32k, PERIPH_NO_RESET),
+ PERIPH_CLK("rtc", "rtc-tegra", NULL, 4, 0, 0x31E, 32768, mux_clk_32k, PERIPH_NO_RESET | PERIPH_ON_APB),
+ PERIPH_CLK("kbc", "tegra-kbc", NULL, 36, 0, 0x31E, 32768, mux_clk_32k, PERIPH_NO_RESET | PERIPH_ON_APB),
PERIPH_CLK("timer", "timer", NULL, 5, 0, 0x31E, 26000000, mux_clk_m, 0),
PERIPH_CLK("kfuse", "kfuse-tegra", NULL, 40, 0, 0x31E, 26000000, mux_clk_m, 0),
PERIPH_CLK("fuse", "fuse-tegra", "fuse", 39, 0, 0x31E, 26000000, mux_clk_m, 0),
PERIPH_CLK("fuse_burn", "fuse-tegra", "fuse_burn", 39, 0, 0x31E, 26000000, mux_clk_m, 0),
- PERIPH_CLK("i2s1", "i2s.0", NULL, 11, 0x100, 0x31E, 26000000, mux_pllaout0_audio2x_pllp_clkm, MUX | DIV_U71),
- PERIPH_CLK("i2s2", "i2s.1", NULL, 18, 0x104, 0x31E, 26000000, mux_pllaout0_audio2x_pllp_clkm, MUX | DIV_U71),
- PERIPH_CLK("spdif_out", "spdif_out", NULL, 10, 0x108, 0x31E, 100000000, mux_pllaout0_audio2x_pllp_clkm, MUX | DIV_U71),
- PERIPH_CLK("spdif_in", "spdif_in", NULL, 10, 0x10c, 0x31E, 100000000, mux_pllp_pllc_pllm, MUX | DIV_U71),
- PERIPH_CLK("pwm", "pwm", NULL, 17, 0x110, 0x71C, 432000000, mux_pllp_pllc_audio_clkm_clk32, MUX | DIV_U71),
- PERIPH_CLK("spi", "spi", NULL, 43, 0x114, 0x31E, 40000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71),
+ PERIPH_CLK("i2s1", "i2s.0", NULL, 11, 0x100, 0x31E, 26000000, mux_pllaout0_audio2x_pllp_clkm, MUX | DIV_U71 | PERIPH_ON_APB),
+ PERIPH_CLK("i2s2", "i2s.1", NULL, 18, 0x104, 0x31E, 26000000, mux_pllaout0_audio2x_pllp_clkm, MUX | DIV_U71 | PERIPH_ON_APB),
+ PERIPH_CLK("spdif_out", "spdif_out", NULL, 10, 0x108, 0x31E, 100000000, mux_pllaout0_audio2x_pllp_clkm, MUX | DIV_U71 | PERIPH_ON_APB),
+ PERIPH_CLK("spdif_in", "spdif_in", NULL, 10, 0x10c, 0x31E, 100000000, mux_pllp_pllc_pllm, MUX | DIV_U71 | PERIPH_ON_APB),
+ PERIPH_CLK("pwm", "pwm", NULL, 17, 0x110, 0x71C, 432000000, mux_pllp_pllc_audio_clkm_clk32, MUX | DIV_U71 | PERIPH_ON_APB),
+ PERIPH_CLK("spi", "spi", NULL, 43, 0x114, 0x31E, 40000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71 | PERIPH_ON_APB),
PERIPH_CLK("xio", "xio", NULL, 45, 0x120, 0x31E, 150000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71),
- PERIPH_CLK("twc", "twc", NULL, 16, 0x12c, 0x31E, 150000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71),
- PERIPH_CLK("sbc1", "spi_tegra.0", NULL, 41, 0x134, 0x31E, 160000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71),
- PERIPH_CLK("sbc2", "spi_tegra.1", NULL, 44, 0x118, 0x31E, 160000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71),
- PERIPH_CLK("sbc3", "spi_tegra.2", NULL, 46, 0x11c, 0x31E, 160000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71),
- PERIPH_CLK("sbc4", "spi_tegra.3", NULL, 68, 0x1b4, 0x31E, 160000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71),
+ PERIPH_CLK("twc", "twc", NULL, 16, 0x12c, 0x31E, 150000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71 | PERIPH_ON_APB),
+ PERIPH_CLK("sbc1", "spi_tegra.0", NULL, 41, 0x134, 0x31E, 160000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71 | PERIPH_ON_APB),
+ PERIPH_CLK("sbc2", "spi_tegra.1", NULL, 44, 0x118, 0x31E, 160000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71 | PERIPH_ON_APB),
+ PERIPH_CLK("sbc3", "spi_tegra.2", NULL, 46, 0x11c, 0x31E, 160000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71 | PERIPH_ON_APB),
+ PERIPH_CLK("sbc4", "spi_tegra.3", NULL, 68, 0x1b4, 0x31E, 160000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71 | PERIPH_ON_APB),
PERIPH_CLK("ide", "ide", NULL, 25, 0x144, 0x31E, 100000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), /* requires min voltage */
PERIPH_CLK("ndflash", "tegra_nand", NULL, 13, 0x160, 0x31E, 164000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), /* scales with voltage */
- PERIPH_CLK("vfir", "vfir", NULL, 7, 0x168, 0x31E, 72000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71),
+ PERIPH_CLK("vfir", "vfir", NULL, 7, 0x168, 0x31E, 72000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71 | PERIPH_ON_APB),
PERIPH_CLK("sdmmc1", "sdhci-tegra.0", NULL, 14, 0x150, 0x31E, 52000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), /* scales with voltage */
PERIPH_CLK("sdmmc2", "sdhci-tegra.1", NULL, 9, 0x154, 0x31E, 52000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), /* scales with voltage */
PERIPH_CLK("sdmmc3", "sdhci-tegra.2", NULL, 69, 0x1bc, 0x31E, 52000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), /* scales with voltage */
@@ -2146,22 +2167,22 @@ struct clk tegra_list_periph_clks[] = {
PERIPH_CLK("csite", "csite", NULL, 73, 0x1d4, 0x31E, 144000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), /* max rate ??? */
/* FIXME: what is la? */
PERIPH_CLK("la", "la", NULL, 76, 0x1f8, 0x31E, 26000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71),
- PERIPH_CLK("owr", "tegra_w1", NULL, 71, 0x1cc, 0x31E, 26000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71),
+ PERIPH_CLK("owr", "tegra_w1", NULL, 71, 0x1cc, 0x31E, 26000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71 | PERIPH_ON_APB),
PERIPH_CLK("nor", "nor", NULL, 42, 0x1d0, 0x31E, 92000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), /* requires min voltage */
- PERIPH_CLK("mipi", "mipi", NULL, 50, 0x174, 0x31E, 60000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), /* scales with voltage */
- PERIPH_CLK("i2c1", "tegra-i2c.0", NULL, 12, 0x124, 0x31E, 26000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U16),
- PERIPH_CLK("i2c2", "tegra-i2c.1", NULL, 54, 0x198, 0x31E, 26000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U16),
- PERIPH_CLK("i2c3", "tegra-i2c.2", NULL, 67, 0x1b8, 0x31E, 26000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U16),
- PERIPH_CLK("dvc", "tegra-i2c.3", NULL, 47, 0x128, 0x31E, 26000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U16),
- PERIPH_CLK("i2c1_i2c", "tegra-i2c.0", "i2c", 0, 0, 0x31E, 72000000, mux_pllp_out3, 0),
- PERIPH_CLK("i2c2_i2c", "tegra-i2c.1", "i2c", 0, 0, 0x31E, 72000000, mux_pllp_out3, 0),
- PERIPH_CLK("i2c3_i2c", "tegra-i2c.2", "i2c", 0, 0, 0x31E, 72000000, mux_pllp_out3, 0),
- PERIPH_CLK("dvc_i2c", "tegra-i2c.3", "i2c", 0, 0, 0x31E, 72000000, mux_pllp_out3, 0),
- PERIPH_CLK("uarta", "uart.0", NULL, 6, 0x178, 0x31E, 600000000, mux_pllp_pllc_pllm_clkm, MUX),
- PERIPH_CLK("uartb", "uart.1", NULL, 7, 0x17c, 0x31E, 600000000, mux_pllp_pllc_pllm_clkm, MUX),
- PERIPH_CLK("uartc", "uart.2", NULL, 55, 0x1a0, 0x31E, 600000000, mux_pllp_pllc_pllm_clkm, MUX),
- PERIPH_CLK("uartd", "uart.3", NULL, 65, 0x1c0, 0x31E, 600000000, mux_pllp_pllc_pllm_clkm, MUX),
- PERIPH_CLK("uarte", "uart.4", NULL, 66, 0x1c4, 0x31E, 600000000, mux_pllp_pllc_pllm_clkm, MUX),
+ PERIPH_CLK("mipi", "mipi", NULL, 50, 0x174, 0x31E, 60000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71 | PERIPH_ON_APB), /* scales with voltage */
+ PERIPH_CLK("i2c1", "tegra-i2c.0", NULL, 12, 0x124, 0x31E, 26000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U16 | PERIPH_ON_APB),
+ PERIPH_CLK("i2c2", "tegra-i2c.1", NULL, 54, 0x198, 0x31E, 26000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U16 | PERIPH_ON_APB),
+ PERIPH_CLK("i2c3", "tegra-i2c.2", NULL, 67, 0x1b8, 0x31E, 26000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U16 | PERIPH_ON_APB),
+ PERIPH_CLK("dvc", "tegra-i2c.3", NULL, 47, 0x128, 0x31E, 26000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U16 | PERIPH_ON_APB),
+ PERIPH_CLK("i2c1_i2c", "tegra-i2c.0", "i2c", 0, 0, 0x31E, 72000000, mux_pllp_out3, PERIPH_ON_APB),
+ PERIPH_CLK("i2c2_i2c", "tegra-i2c.1", "i2c", 0, 0, 0x31E, 72000000, mux_pllp_out3, PERIPH_ON_APB),
+ PERIPH_CLK("i2c3_i2c", "tegra-i2c.2", "i2c", 0, 0, 0x31E, 72000000, mux_pllp_out3, PERIPH_ON_APB),
+ PERIPH_CLK("dvc_i2c", "tegra-i2c.3", "i2c", 0, 0, 0x31E, 72000000, mux_pllp_out3, PERIPH_ON_APB),
+ PERIPH_CLK("uarta", "uart.0", NULL, 6, 0x178, 0x31E, 600000000, mux_pllp_pllc_pllm_clkm, MUX | PERIPH_ON_APB),
+ PERIPH_CLK("uartb", "uart.1", NULL, 7, 0x17c, 0x31E, 600000000, mux_pllp_pllc_pllm_clkm, MUX | PERIPH_ON_APB),
+ PERIPH_CLK("uartc", "uart.2", NULL, 55, 0x1a0, 0x31E, 600000000, mux_pllp_pllc_pllm_clkm, MUX | PERIPH_ON_APB),
+ PERIPH_CLK("uartd", "uart.3", NULL, 65, 0x1c0, 0x31E, 600000000, mux_pllp_pllc_pllm_clkm, MUX | PERIPH_ON_APB),
+ PERIPH_CLK("uarte", "uart.4", NULL, 66, 0x1c4, 0x31E, 600000000, mux_pllp_pllc_pllm_clkm, MUX | PERIPH_ON_APB),
PERIPH_CLK("3d", "3d", NULL, 24, 0x158, 0x31E, 300000000, mux_pllm_pllc_pllp_plla, MUX | DIV_U71 | PERIPH_MANUAL_RESET), /* scales with voltage and process_id */
PERIPH_CLK("2d", "2d", NULL, 21, 0x15c, 0x31E, 300000000, mux_pllm_pllc_pllp_plla, MUX | DIV_U71), /* scales with voltage and process_id */
PERIPH_CLK("vi", "tegra_camera", "vi", 20, 0x148, 0x31E, 150000000, mux_pllm_pllc_pllp_plla, MUX | DIV_U71), /* scales with voltage and process_id */