diff options
author | Colin Cross <ccross@android.com> | 2010-10-20 22:19:58 -0400 |
---|---|---|
committer | Colin Cross <ccross@android.com> | 2011-02-22 14:22:24 -0500 |
commit | 78f379b574dcbe656fa21ea72e95f8dff232e233 (patch) | |
tree | f76ccb9312f911d51c9c4d168f6ce706fd2df148 /arch | |
parent | 9c7dc562cd78784f54261b9bedb44e8b0056f729 (diff) |
ARM: tegra: clock: Refcount periph clock enables
Some peripheral clocks share enable bits. Refcount the enables so
that calling clk_disable on one clock will not turn off another
clock.
Signed-off-by: Colin Cross <ccross@android.com>
Acked-by: Olof Johansson <olof@lixom.net>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/mach-tegra/tegra2_clocks.c | 37 |
1 files changed, 31 insertions, 6 deletions
diff --git a/arch/arm/mach-tegra/tegra2_clocks.c b/arch/arm/mach-tegra/tegra2_clocks.c index 59e77ba9580..2ca8b74ec07 100644 --- a/arch/arm/mach-tegra/tegra2_clocks.c +++ b/arch/arm/mach-tegra/tegra2_clocks.c | |||
@@ -159,6 +159,12 @@ static void __iomem *reg_pmc_base = IO_ADDRESS(TEGRA_PMC_BASE); | |||
159 | */ | 159 | */ |
160 | static DEFINE_SPINLOCK(clock_register_lock); | 160 | static DEFINE_SPINLOCK(clock_register_lock); |
161 | 161 | ||
162 | /* | ||
163 | * Some peripheral clocks share an enable bit, so refcount the enable bits | ||
164 | * in registers CLK_ENABLE_L, CLK_ENABLE_H, and CLK_ENABLE_U | ||
165 | */ | ||
166 | static int tegra_periph_clk_enable_refcount[3 * 32]; | ||
167 | |||
162 | #define clk_writel(value, reg) \ | 168 | #define clk_writel(value, reg) \ |
163 | __raw_writel(value, (u32)reg_clk_base + (reg)) | 169 | __raw_writel(value, (u32)reg_clk_base + (reg)) |
164 | #define clk_readl(reg) \ | 170 | #define clk_readl(reg) \ |
@@ -952,8 +958,17 @@ static void tegra2_periph_clk_init(struct clk *c) | |||
952 | static int tegra2_periph_clk_enable(struct clk *c) | 958 | static int tegra2_periph_clk_enable(struct clk *c) |
953 | { | 959 | { |
954 | u32 val; | 960 | u32 val; |
961 | unsigned long flags; | ||
962 | int refcount; | ||
955 | pr_debug("%s on clock %s\n", __func__, c->name); | 963 | pr_debug("%s on clock %s\n", __func__, c->name); |
956 | 964 | ||
965 | spin_lock_irqsave(&clock_register_lock, flags); | ||
966 | |||
967 | refcount = tegra_periph_clk_enable_refcount[c->u.periph.clk_num]++; | ||
968 | |||
969 | if (refcount > 1) | ||
970 | goto out; | ||
971 | |||
957 | clk_writel(PERIPH_CLK_TO_ENB_BIT(c), | 972 | clk_writel(PERIPH_CLK_TO_ENB_BIT(c), |
958 | CLK_OUT_ENB_SET + PERIPH_CLK_TO_ENB_SET_REG(c)); | 973 | CLK_OUT_ENB_SET + PERIPH_CLK_TO_ENB_SET_REG(c)); |
959 | if (!(c->flags & PERIPH_NO_RESET) && !(c->flags & PERIPH_MANUAL_RESET)) | 974 | if (!(c->flags & PERIPH_NO_RESET) && !(c->flags & PERIPH_MANUAL_RESET)) |
@@ -966,15 +981,29 @@ static int tegra2_periph_clk_enable(struct clk *c) | |||
966 | val |= 0x3 << 24; | 981 | val |= 0x3 << 24; |
967 | clk_writel(val, c->reg); | 982 | clk_writel(val, c->reg); |
968 | } | 983 | } |
984 | |||
985 | out: | ||
986 | spin_unlock_irqrestore(&clock_register_lock, flags); | ||
987 | |||
969 | return 0; | 988 | return 0; |
970 | } | 989 | } |
971 | 990 | ||
972 | static void tegra2_periph_clk_disable(struct clk *c) | 991 | static void tegra2_periph_clk_disable(struct clk *c) |
973 | { | 992 | { |
993 | unsigned long flags; | ||
994 | |||
974 | pr_debug("%s on clock %s\n", __func__, c->name); | 995 | pr_debug("%s on clock %s\n", __func__, c->name); |
975 | 996 | ||
976 | clk_writel(PERIPH_CLK_TO_ENB_BIT(c), | 997 | spin_lock_irqsave(&clock_register_lock, flags); |
977 | CLK_OUT_ENB_CLR + PERIPH_CLK_TO_ENB_SET_REG(c)); | 998 | |
999 | if (c->refcnt) | ||
1000 | tegra_periph_clk_enable_refcount[c->u.periph.clk_num]--; | ||
1001 | |||
1002 | if (tegra_periph_clk_enable_refcount[c->u.periph.clk_num] == 0) | ||
1003 | clk_writel(PERIPH_CLK_TO_ENB_BIT(c), | ||
1004 | CLK_OUT_ENB_CLR + PERIPH_CLK_TO_ENB_SET_REG(c)); | ||
1005 | |||
1006 | spin_unlock_irqrestore(&clock_register_lock, flags); | ||
978 | } | 1007 | } |
979 | 1008 | ||
980 | static void tegra2_periph_clk_reset(struct clk *c, bool assert) | 1009 | static void tegra2_periph_clk_reset(struct clk *c, bool assert) |
@@ -2076,7 +2105,6 @@ struct clk tegra_list_clks[] = { | |||
2076 | PERIPH_CLK("timer", "timer", NULL, 5, 0, 26000000, mux_clk_m, 0), | 2105 | PERIPH_CLK("timer", "timer", NULL, 5, 0, 26000000, mux_clk_m, 0), |
2077 | PERIPH_CLK("i2s1", "i2s.0", NULL, 11, 0x100, 26000000, mux_pllaout0_audio2x_pllp_clkm, MUX | DIV_U71), | 2106 | PERIPH_CLK("i2s1", "i2s.0", NULL, 11, 0x100, 26000000, mux_pllaout0_audio2x_pllp_clkm, MUX | DIV_U71), |
2078 | PERIPH_CLK("i2s2", "i2s.1", NULL, 18, 0x104, 26000000, mux_pllaout0_audio2x_pllp_clkm, MUX | DIV_U71), | 2107 | PERIPH_CLK("i2s2", "i2s.1", NULL, 18, 0x104, 26000000, mux_pllaout0_audio2x_pllp_clkm, MUX | DIV_U71), |
2079 | /* FIXME: spdif has 2 clocks but 1 enable */ | ||
2080 | PERIPH_CLK("spdif_out", "spdif_out", NULL, 10, 0x108, 100000000, mux_pllaout0_audio2x_pllp_clkm, MUX | DIV_U71), | 2108 | PERIPH_CLK("spdif_out", "spdif_out", NULL, 10, 0x108, 100000000, mux_pllaout0_audio2x_pllp_clkm, MUX | DIV_U71), |
2081 | PERIPH_CLK("spdif_in", "spdif_in", NULL, 10, 0x10c, 100000000, mux_pllp_pllc_pllm, MUX | DIV_U71), | 2109 | PERIPH_CLK("spdif_in", "spdif_in", NULL, 10, 0x10c, 100000000, mux_pllp_pllc_pllm, MUX | DIV_U71), |
2082 | PERIPH_CLK("pwm", "pwm", NULL, 17, 0x110, 432000000, mux_pllp_pllc_audio_clkm_clk32, MUX | DIV_U71), | 2110 | PERIPH_CLK("pwm", "pwm", NULL, 17, 0x110, 432000000, mux_pllp_pllc_audio_clkm_clk32, MUX | DIV_U71), |
@@ -2089,7 +2117,6 @@ struct clk tegra_list_clks[] = { | |||
2089 | PERIPH_CLK("sbc4", "spi_tegra.3", NULL, 68, 0x1b4, 160000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), | 2117 | PERIPH_CLK("sbc4", "spi_tegra.3", NULL, 68, 0x1b4, 160000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), |
2090 | PERIPH_CLK("ide", "ide", NULL, 25, 0x144, 100000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), /* requires min voltage */ | 2118 | PERIPH_CLK("ide", "ide", NULL, 25, 0x144, 100000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), /* requires min voltage */ |
2091 | PERIPH_CLK("ndflash", "tegra_nand", NULL, 13, 0x160, 164000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), /* scales with voltage */ | 2119 | PERIPH_CLK("ndflash", "tegra_nand", NULL, 13, 0x160, 164000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), /* scales with voltage */ |
2092 | /* FIXME: vfir shares an enable with uartb */ | ||
2093 | PERIPH_CLK("vfir", "vfir", NULL, 7, 0x168, 72000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), | 2120 | PERIPH_CLK("vfir", "vfir", NULL, 7, 0x168, 72000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), |
2094 | PERIPH_CLK("sdmmc1", "sdhci-tegra.0", NULL, 14, 0x150, 52000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), /* scales with voltage */ | 2121 | PERIPH_CLK("sdmmc1", "sdhci-tegra.0", NULL, 14, 0x150, 52000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), /* scales with voltage */ |
2095 | PERIPH_CLK("sdmmc2", "sdhci-tegra.1", NULL, 9, 0x154, 52000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), /* scales with voltage */ | 2122 | PERIPH_CLK("sdmmc2", "sdhci-tegra.1", NULL, 9, 0x154, 52000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), /* scales with voltage */ |
@@ -2120,13 +2147,11 @@ struct clk tegra_list_clks[] = { | |||
2120 | PERIPH_CLK("uarte", "uart.4", NULL, 66, 0x1c4, 600000000, mux_pllp_pllc_pllm_clkm, MUX), | 2147 | PERIPH_CLK("uarte", "uart.4", NULL, 66, 0x1c4, 600000000, mux_pllp_pllc_pllm_clkm, MUX), |
2121 | PERIPH_CLK("3d", "3d", NULL, 24, 0x158, 300000000, mux_pllm_pllc_pllp_plla, MUX | DIV_U71 | PERIPH_MANUAL_RESET), /* scales with voltage and process_id */ | 2148 | PERIPH_CLK("3d", "3d", NULL, 24, 0x158, 300000000, mux_pllm_pllc_pllp_plla, MUX | DIV_U71 | PERIPH_MANUAL_RESET), /* scales with voltage and process_id */ |
2122 | PERIPH_CLK("2d", "2d", NULL, 21, 0x15c, 300000000, mux_pllm_pllc_pllp_plla, MUX | DIV_U71), /* scales with voltage and process_id */ | 2149 | PERIPH_CLK("2d", "2d", NULL, 21, 0x15c, 300000000, mux_pllm_pllc_pllp_plla, MUX | DIV_U71), /* scales with voltage and process_id */ |
2123 | /* FIXME: vi and vi_sensor share an enable */ | ||
2124 | PERIPH_CLK("vi", "tegra_camera", "vi", 20, 0x148, 150000000, mux_pllm_pllc_pllp_plla, MUX | DIV_U71), /* scales with voltage and process_id */ | 2150 | PERIPH_CLK("vi", "tegra_camera", "vi", 20, 0x148, 150000000, mux_pllm_pllc_pllp_plla, MUX | DIV_U71), /* scales with voltage and process_id */ |
2125 | PERIPH_CLK("vi_sensor", "tegra_camera", "vi_sensor", 20, 0x1a8, 150000000, mux_pllm_pllc_pllp_plla, MUX | DIV_U71 | PERIPH_NO_RESET), /* scales with voltage and process_id */ | 2151 | PERIPH_CLK("vi_sensor", "tegra_camera", "vi_sensor", 20, 0x1a8, 150000000, mux_pllm_pllc_pllp_plla, MUX | DIV_U71 | PERIPH_NO_RESET), /* scales with voltage and process_id */ |
2126 | PERIPH_CLK("epp", "epp", NULL, 19, 0x16c, 300000000, mux_pllm_pllc_pllp_plla, MUX | DIV_U71), /* scales with voltage and process_id */ | 2152 | PERIPH_CLK("epp", "epp", NULL, 19, 0x16c, 300000000, mux_pllm_pllc_pllp_plla, MUX | DIV_U71), /* scales with voltage and process_id */ |
2127 | PERIPH_CLK("mpe", "mpe", NULL, 60, 0x170, 250000000, mux_pllm_pllc_pllp_plla, MUX | DIV_U71), /* scales with voltage and process_id */ | 2153 | PERIPH_CLK("mpe", "mpe", NULL, 60, 0x170, 250000000, mux_pllm_pllc_pllp_plla, MUX | DIV_U71), /* scales with voltage and process_id */ |
2128 | PERIPH_CLK("host1x", "host1x", NULL, 28, 0x180, 166000000, mux_pllm_pllc_pllp_plla, MUX | DIV_U71), /* scales with voltage and process_id */ | 2154 | PERIPH_CLK("host1x", "host1x", NULL, 28, 0x180, 166000000, mux_pllm_pllc_pllp_plla, MUX | DIV_U71), /* scales with voltage and process_id */ |
2129 | /* FIXME: cve and tvo share an enable */ | ||
2130 | PERIPH_CLK("cve", "cve", NULL, 49, 0x140, 250000000, mux_pllp_plld_pllc_clkm, MUX | DIV_U71), /* requires min voltage */ | 2155 | PERIPH_CLK("cve", "cve", NULL, 49, 0x140, 250000000, mux_pllp_plld_pllc_clkm, MUX | DIV_U71), /* requires min voltage */ |
2131 | PERIPH_CLK("tvo", "tvo", NULL, 49, 0x188, 250000000, mux_pllp_plld_pllc_clkm, MUX | DIV_U71), /* requires min voltage */ | 2156 | PERIPH_CLK("tvo", "tvo", NULL, 49, 0x188, 250000000, mux_pllp_plld_pllc_clkm, MUX | DIV_U71), /* requires min voltage */ |
2132 | PERIPH_CLK("hdmi", "hdmi", NULL, 51, 0x18c, 600000000, mux_pllp_plld_pllc_clkm, MUX | DIV_U71), /* requires min voltage */ | 2157 | PERIPH_CLK("hdmi", "hdmi", NULL, 51, 0x18c, 600000000, mux_pllp_plld_pllc_clkm, MUX | DIV_U71), /* requires min voltage */ |