diff options
-rw-r--r-- | arch/arm/mach-tegra/clock.h | 1 | ||||
-rw-r--r-- | arch/arm/mach-tegra/tegra2_clocks.c | 83 |
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 */ |