summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorLaxman Dewangan <ldewangan@nvidia.com>2011-12-28 14:21:16 +0530
committerVarun Wadekar <vwadekar@nvidia.com>2012-01-04 11:44:57 +0530
commitf24c4131ebf2a59e7d6c81fb338a856b36432691 (patch)
tree4e2cdf6363549fa0c47b384927adf01ed82a1d9f /arch
parentf37e8ecb37b05ec0794d17bb1e7f461135d387f6 (diff)
tegra3: clock: Support for divisor 15.1
Uart clock source has divisor of 16 bits where LSB is 0.5. Adding support for divisor 15.1 and configuring uart for use the 15.1 type divisor. Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com> Change-Id: Ifdd77041e7abb43026bbfb273f6e12923d64d607 Reviewed-on: http://git-master/r/70324 Reviewed-by: Laxman Dewangan <ldewangan@nvidia.com> Tested-by: Laxman Dewangan <ldewangan@nvidia.com> Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Bitan Biswas <bbiswas@nvidia.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/mach-tegra/clock.h3
-rw-r--r--arch/arm/mach-tegra/tegra3_clocks.c89
2 files changed, 66 insertions, 26 deletions
diff --git a/arch/arm/mach-tegra/clock.h b/arch/arm/mach-tegra/clock.h
index 3f159ced1103..25ba88bc4893 100644
--- a/arch/arm/mach-tegra/clock.h
+++ b/arch/arm/mach-tegra/clock.h
@@ -48,11 +48,12 @@
#define PLLX (1 << 15)
#define MUX_PWM (1 << 16)
#define MUX8 (1 << 17)
-#define DIV_U71_UART (1 << 18)
+#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)
diff --git a/arch/arm/mach-tegra/tegra3_clocks.c b/arch/arm/mach-tegra/tegra3_clocks.c
index 743e8eeeabc4..39a1712c7225 100644
--- a/arch/arm/mach-tegra/tegra3_clocks.c
+++ b/arch/arm/mach-tegra/tegra3_clocks.c
@@ -414,28 +414,44 @@ unsigned long clk_measure_input_freq(void)
}
}
-static int clk_div71_get_divider(unsigned long parent_rate, unsigned long rate,
- u32 flags, u32 round_mode)
+static int clk_div_x1_get_divider(unsigned long parent_rate, unsigned long rate,
+ u32 max_x, u32 flags, u32 round_mode)
{
- s64 divider_u71 = parent_rate;
+ s64 divider_ux1 = parent_rate;
if (!rate)
return -EINVAL;
if (!(flags & DIV_U71_INT))
- divider_u71 *= 2;
+ divider_ux1 *= 2;
+
if (round_mode == ROUND_DIVIDER_UP)
- divider_u71 += rate - 1;
- do_div(divider_u71, rate);
+ divider_ux1 += rate - 1;
+ do_div(divider_ux1, rate);
+
if (flags & DIV_U71_INT)
- divider_u71 *= 2;
+ divider_ux1 *= 2;
- if (divider_u71 - 2 < 0)
+ if (divider_ux1 - 2 < 0)
return 0;
- if (divider_u71 - 2 > 255)
+ if (divider_ux1 - 2 > max_x)
return -EINVAL;
- return divider_u71 - 2;
+ return divider_ux1 - 2;
+}
+
+static int clk_div71_get_divider(unsigned long parent_rate, unsigned long rate,
+ u32 flags, u32 round_mode)
+{
+ return clk_div_x1_get_divider(parent_rate, rate, 0xFF,
+ flags, round_mode);
+}
+
+static int clk_div151_get_divider(unsigned long parent_rate, unsigned long rate,
+ u32 flags, u32 round_mode)
+{
+ return clk_div_x1_get_divider(parent_rate, rate, 0xFFFF,
+ flags, round_mode);
}
static int clk_div16_get_divider(unsigned long parent_rate, unsigned long rate)
@@ -1947,10 +1963,6 @@ static void tegra3_periph_clk_init(struct clk *c)
if (c->flags & DIV_U71) {
u32 divu71 = val & PERIPH_CLK_SOURCE_DIVU71_MASK;
- if ((c->flags & DIV_U71_UART) &&
- (!(val & PERIPH_CLK_UART_DIV_ENB))) {
- divu71 = 0;
- }
if (c->flags & DIV_U71_IDLE) {
val &= ~(PERIPH_CLK_SOURCE_DIVU71_MASK <<
PERIPH_CLK_SOURCE_DIVIDLE_SHIFT);
@@ -1960,6 +1972,14 @@ static void tegra3_periph_clk_init(struct clk *c)
}
c->div = divu71 + 2;
c->mul = 2;
+ } else if (c->flags & DIV_U151) {
+ u32 divu151 = val & PERIPH_CLK_SOURCE_DIVU16_MASK;
+ if ((c->flags & DIV_U151_UART) &&
+ (!(val & PERIPH_CLK_UART_DIV_ENB))) {
+ divu151 = 0;
+ }
+ c->div = divu151 + 2;
+ c->mul = 2;
} else if (c->flags & DIV_U16) {
u32 divu16 = val & PERIPH_CLK_SOURCE_DIVU16_MASK;
c->div = divu16 + 1;
@@ -2085,7 +2105,19 @@ static int tegra3_periph_clk_set_rate(struct clk *c, unsigned long rate)
val = clk_readl(c->reg);
val &= ~PERIPH_CLK_SOURCE_DIVU71_MASK;
val |= divider;
- if (c->flags & DIV_U71_UART) {
+ clk_writel_delay(val, c->reg);
+ c->div = divider + 2;
+ c->mul = 2;
+ return 0;
+ }
+ } else if (c->flags & DIV_U151) {
+ divider = clk_div151_get_divider(
+ parent_rate, rate, c->flags, ROUND_DIVIDER_UP);
+ if (divider >= 0) {
+ val = clk_readl(c->reg);
+ val &= ~PERIPH_CLK_SOURCE_DIVU16_MASK;
+ val |= divider;
+ if (c->flags & DIV_U151_UART) {
if (divider)
val |= PERIPH_CLK_UART_DIV_ENB;
else
@@ -2129,6 +2161,13 @@ static long tegra3_periph_clk_round_rate(struct clk *c,
return divider;
return DIV_ROUND_UP(parent_rate * 2, divider + 2);
+ } else if (c->flags & DIV_U151) {
+ divider = clk_div151_get_divider(
+ parent_rate, rate, c->flags, ROUND_DIVIDER_UP);
+ if (divider < 0)
+ return divider;
+
+ return DIV_ROUND_UP(parent_rate * 2, divider + 2);
} else if (c->flags & DIV_U16) {
divider = clk_div16_get_divider(parent_rate, rate);
if (divider < 0)
@@ -4046,16 +4085,16 @@ struct clk tegra_list_clks[] = {
PERIPH_CLK("i2c3", "tegra-i2c.2", NULL, 67, 0x1b8, 26000000, mux_pllp_clkm, MUX | DIV_U16 | PERIPH_ON_APB),
PERIPH_CLK("i2c4", "tegra-i2c.3", NULL, 103, 0x3c4, 26000000, mux_pllp_clkm, MUX | DIV_U16 | PERIPH_ON_APB),
PERIPH_CLK("i2c5", "tegra-i2c.4", NULL, 47, 0x128, 26000000, mux_pllp_clkm, MUX | DIV_U16 | PERIPH_ON_APB),
- PERIPH_CLK("uarta", "tegra_uart.0", NULL, 6, 0x178, 800000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71 | DIV_U71_UART | PERIPH_ON_APB),
- PERIPH_CLK("uartb", "tegra_uart.1", NULL, 7, 0x17c, 800000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71 | DIV_U71_UART | PERIPH_ON_APB),
- PERIPH_CLK("uartc", "tegra_uart.2", NULL, 55, 0x1a0, 800000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71 | DIV_U71_UART | PERIPH_ON_APB),
- PERIPH_CLK("uartd", "tegra_uart.3", NULL, 65, 0x1c0, 800000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71 | DIV_U71_UART | PERIPH_ON_APB),
- PERIPH_CLK("uarte", "tegra_uart.4", NULL, 66, 0x1c4, 800000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71 | DIV_U71_UART | PERIPH_ON_APB),
- PERIPH_CLK("uarta_dbg", "serial8250.0", "uarta",6, 0x178, 800000000, mux_pllp_clkm, MUX | DIV_U71 | DIV_U71_UART | PERIPH_ON_APB),
- PERIPH_CLK("uartb_dbg", "serial8250.0", "uartb",7, 0x17c, 800000000, mux_pllp_clkm, MUX | DIV_U71 | DIV_U71_UART | PERIPH_ON_APB),
- PERIPH_CLK("uartc_dbg", "serial8250.0", "uartc",55, 0x1a0, 800000000, mux_pllp_clkm, MUX | DIV_U71 | DIV_U71_UART | PERIPH_ON_APB),
- PERIPH_CLK("uartd_dbg", "serial8250.0", "uartd",65, 0x1c0, 800000000, mux_pllp_clkm, MUX | DIV_U71 | DIV_U71_UART | PERIPH_ON_APB),
- PERIPH_CLK("uarte_dbg", "serial8250.0", "uarte",66, 0x1c4, 800000000, mux_pllp_clkm, MUX | DIV_U71 | DIV_U71_UART | PERIPH_ON_APB),
+ PERIPH_CLK("uarta", "tegra_uart.0", NULL, 6, 0x178, 800000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U151 | DIV_U151_UART | PERIPH_ON_APB),
+ PERIPH_CLK("uartb", "tegra_uart.1", NULL, 7, 0x17c, 800000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U151 | DIV_U151_UART | PERIPH_ON_APB),
+ PERIPH_CLK("uartc", "tegra_uart.2", NULL, 55, 0x1a0, 800000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U151 | DIV_U151_UART | PERIPH_ON_APB),
+ PERIPH_CLK("uartd", "tegra_uart.3", NULL, 65, 0x1c0, 800000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U151 | DIV_U151_UART | PERIPH_ON_APB),
+ PERIPH_CLK("uarte", "tegra_uart.4", NULL, 66, 0x1c4, 800000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U151 | DIV_U151_UART | PERIPH_ON_APB),
+ PERIPH_CLK("uarta_dbg", "serial8250.0", "uarta",6, 0x178, 800000000, mux_pllp_clkm, MUX | DIV_U151 | DIV_U151_UART | PERIPH_ON_APB),
+ PERIPH_CLK("uartb_dbg", "serial8250.0", "uartb",7, 0x17c, 800000000, mux_pllp_clkm, MUX | DIV_U151 | DIV_U151_UART | PERIPH_ON_APB),
+ PERIPH_CLK("uartc_dbg", "serial8250.0", "uartc",55, 0x1a0, 800000000, mux_pllp_clkm, MUX | DIV_U151 | DIV_U151_UART | PERIPH_ON_APB),
+ PERIPH_CLK("uartd_dbg", "serial8250.0", "uartd",65, 0x1c0, 800000000, mux_pllp_clkm, MUX | DIV_U151 | DIV_U151_UART | PERIPH_ON_APB),
+ PERIPH_CLK("uarte_dbg", "serial8250.0", "uarte",66, 0x1c4, 800000000, mux_pllp_clkm, MUX | DIV_U151 | DIV_U151_UART | PERIPH_ON_APB),
PERIPH_CLK_EX("vi", "tegra_camera", "vi", 20, 0x148, 425000000, mux_pllm_pllc_pllp_plla, MUX | DIV_U71 | DIV_U71_INT, &tegra_vi_clk_ops),
PERIPH_CLK("3d", "3d", NULL, 24, 0x158, 520000000, mux_pllm_pllc_pllp_plla, MUX | DIV_U71 | DIV_U71_INT | DIV_U71_IDLE | PERIPH_MANUAL_RESET),
PERIPH_CLK("3d2", "3d2", NULL, 98, 0x3b0, 520000000, mux_pllm_pllc_pllp_plla, MUX | DIV_U71 | DIV_U71_INT | DIV_U71_IDLE | PERIPH_MANUAL_RESET),