Patchwork [1/4] ARM: tegra30: Add support for Uart clock source divider as 15.1

login
register
mail settings
Submitter Laxman Dewangan
Date Dec. 17, 2012, 12:08 p.m.
Message ID <1355746101-15291-2-git-send-email-ldewangan@nvidia.com>
Download mbox | patch
Permalink /patch/206846/
State Superseded, archived
Headers show

Comments

Laxman Dewangan - Dec. 17, 2012, 12:08 p.m.
Tegra20 uart clock source have the 15.1 clock divider in place of
7.1. Add support for 15.1 clock divider and change the uart clock divider
flag to DIV_U151.

Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com>
---
 arch/arm/mach-tegra/clock.h               |    3 +-
 arch/arm/mach-tegra/tegra30_clocks.c      |   70 ++++++++++++++++++++++------
 arch/arm/mach-tegra/tegra30_clocks_data.c |   10 ++--
 3 files changed, 62 insertions(+), 21 deletions(-)
Stephen Warren - Dec. 17, 2012, 9:43 p.m.
On 12/17/2012 05:08 AM, Laxman Dewangan wrote:
> Tegra20 uart clock source have the 15.1 clock divider in place of

That says Tegra20, but ...

> 7.1. Add support for 15.1 clock divider and change the uart clock divider
> flag to DIV_U151.

>  arch/arm/mach-tegra/clock.h               |    3 +-
>  arch/arm/mach-tegra/tegra30_clocks.c      |   70 ++++++++++++++++++++++------
>  arch/arm/mach-tegra/tegra30_clocks_data.c |   10 ++--

... the patch only modifies Tegra30. Do both Tegra20 and Tegra30 have
this feature; should both clock drivers be updated?

BTW, Prashant is reworking the Tegra clock support to be modular, rather
than having a single monolithic "Tegra clock" type, and also moving the
code to drivers/clk. This patch will conflict signifcantly with that.
Please work with him to integrate this patch into his rework series,
either before or after his changes, and have him include the patch when
he posts his series. You'll also need to think about whether/how your
and his series depend on each-other.

... but: Is this a pure bug-fix? If so, I guess this patch should be
applied before Prashant's patches, and this patch also Cc: stable?
--
To unsubscribe from this list: send the line "unsubscribe linux-tegra" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Prashant Gaikwad - Dec. 18, 2012, 6:14 a.m.
On Tuesday 18 December 2012 03:13 AM, Stephen Warren wrote:
> On 12/17/2012 05:08 AM, Laxman Dewangan wrote:
>> Tegra20 uart clock source have the 15.1 clock divider in place of
> That says Tegra20, but ...
>
>> 7.1. Add support for 15.1 clock divider and change the uart clock divider
>> flag to DIV_U151.
>>   arch/arm/mach-tegra/clock.h               |    3 +-
>>   arch/arm/mach-tegra/tegra30_clocks.c      |   70 ++++++++++++++++++++++------
>>   arch/arm/mach-tegra/tegra30_clocks_data.c |   10 ++--
> ... the patch only modifies Tegra30. Do both Tegra20 and Tegra30 have
> this feature; should both clock drivers be updated?
>
> BTW, Prashant is reworking the Tegra clock support to be modular, rather
> than having a single monolithic "Tegra clock" type, and also moving the
> code to drivers/clk. This patch will conflict signifcantly with that.
> Please work with him to integrate this patch into his rework series,
> either before or after his changes, and have him include the patch when
> he posts his series. You'll also need to think about whether/how your
> and his series depend on each-other.
>
> ... but: Is this a pure bug-fix? If so, I guess this patch should be
> applied before Prashant's patches, and this patch also Cc: stable?

My clock driver rework includes this fix. Divider supports both DIVU71 
and DIVU151.
UART divider is set to DIVU151.


--
To unsubscribe from this list: send the line "unsubscribe linux-tegra" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Laxman Dewangan - Dec. 18, 2012, 6:24 a.m.
On Tuesday 18 December 2012 11:44 AM, Prashant Gaikwad wrote:
> On Tuesday 18 December 2012 03:13 AM, Stephen Warren wrote:
>> On 12/17/2012 05:08 AM, Laxman Dewangan wrote:
>>> Tegra20 uart clock source have the 15.1 clock divider in place of
>> That says Tegra20, but ...
>>
>>> 7.1. Add support for 15.1 clock divider and change the uart clock divider
>>> flag to DIV_U151.
>>>    arch/arm/mach-tegra/clock.h               |    3 +-
>>>    arch/arm/mach-tegra/tegra30_clocks.c      |   70 ++++++++++++++++++++++------
>>>    arch/arm/mach-tegra/tegra30_clocks_data.c |   10 ++--
>> ... the patch only modifies Tegra30. Do both Tegra20 and Tegra30 have
>> this feature; should both clock drivers be updated?
>>
>> BTW, Prashant is reworking the Tegra clock support to be modular, rather
>> than having a single monolithic "Tegra clock" type, and also moving the
>> code to drivers/clk. This patch will conflict signifcantly with that.
>> Please work with him to integrate this patch into his rework series,
>> either before or after his changes, and have him include the patch when
>> he posts his series. You'll also need to think about whether/how your
>> and his series depend on each-other.
>>
>> ... but: Is this a pure bug-fix? If so, I guess this patch should be
>> applied before Prashant's patches, and this patch also Cc: stable?
> My clock driver rework includes this fix. Divider supports both DIVU71
> and DIVU151.
> UART divider is set to DIVU151.

Prashant,
I like to go this patch as first patch towards bug fixes rather than 
after moving the clock. The reason is that we will pull this change in 
our downstream and will be available in our K3.7 code.



--
To unsubscribe from this list: send the line "unsubscribe linux-tegra" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Prashant Gaikwad - Dec. 18, 2012, 7:07 a.m.
On Tuesday 18 December 2012 11:54 AM, Laxman Dewangan wrote:
> On Tuesday 18 December 2012 11:44 AM, Prashant Gaikwad wrote:
>> On Tuesday 18 December 2012 03:13 AM, Stephen Warren wrote:
>>> On 12/17/2012 05:08 AM, Laxman Dewangan wrote:
>>>> Tegra20 uart clock source have the 15.1 clock divider in place of
>>> That says Tegra20, but ...
>>>
>>>> 7.1. Add support for 15.1 clock divider and change the uart clock divider
>>>> flag to DIV_U151.
>>>>     arch/arm/mach-tegra/clock.h               |    3 +-
>>>>     arch/arm/mach-tegra/tegra30_clocks.c      |   70 ++++++++++++++++++++++------
>>>>     arch/arm/mach-tegra/tegra30_clocks_data.c |   10 ++--
>>> ... the patch only modifies Tegra30. Do both Tegra20 and Tegra30 have
>>> this feature; should both clock drivers be updated?
>>>
>>> BTW, Prashant is reworking the Tegra clock support to be modular, rather
>>> than having a single monolithic "Tegra clock" type, and also moving the
>>> code to drivers/clk. This patch will conflict signifcantly with that.
>>> Please work with him to integrate this patch into his rework series,
>>> either before or after his changes, and have him include the patch when
>>> he posts his series. You'll also need to think about whether/how your
>>> and his series depend on each-other.
>>>
>>> ... but: Is this a pure bug-fix? If so, I guess this patch should be
>>> applied before Prashant's patches, and this patch also Cc: stable?
>> My clock driver rework includes this fix. Divider supports both DIVU71
>> and DIVU151.
>> UART divider is set to DIVU151.
> Prashant,
> I like to go this patch as first patch towards bug fixes rather than
> after moving the clock. The reason is that we will pull this change in
> our downstream and will be available in our K3.7 code.

Laxman,

We are not going to use ccf in our downstream kernel port to K3.7. How 
does that help pushing in upstream?

>
>

--
To unsubscribe from this list: send the line "unsubscribe linux-tegra" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Laxman Dewangan - Dec. 18, 2012, 1:05 p.m.
On Tuesday 18 December 2012 12:37 PM, Prashant Gaikwad wrote:
> On Tuesday 18 December 2012 11:54 AM, Laxman Dewangan wrote:
>> On Tuesday 18 December 2012 11:44 AM, Prashant Gaikwad wrote:
>>>
>>> My clock driver rework includes this fix. Divider supports both DIVU71
>>> and DIVU151.
>>> UART divider is set to DIVU151.
>> Prashant,
>> I like to go this patch as first patch towards bug fixes rather than
>> after moving the clock. The reason is that we will pull this change in
>> our downstream and will be available in our K3.7 code.
> Laxman,
>
> We are not going to use ccf in our downstream kernel port to K3.7. How
> does that help pushing in upstream?

Ok, as per our internal discussion, I am going to drop first three 
patches. I will relookinto these patches once your series get applied 
and will work if there is any missing items.


Stephen,
I will respin the 4th patch based on how the discussion on serial driver 
goes. I will send the new patch for 4th change.


--
To unsubscribe from this list: send the line "unsubscribe linux-tegra" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Patch

diff --git a/arch/arm/mach-tegra/clock.h b/arch/arm/mach-tegra/clock.h
index 2aa37f5..26e9253 100644
--- a/arch/arm/mach-tegra/clock.h
+++ b/arch/arm/mach-tegra/clock.h
@@ -45,11 +45,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)
 
diff --git a/arch/arm/mach-tegra/tegra30_clocks.c b/arch/arm/mach-tegra/tegra30_clocks.c
index d714777..795ea87 100644
--- a/arch/arm/mach-tegra/tegra30_clocks.c
+++ b/arch/arm/mach-tegra/tegra30_clocks.c
@@ -466,28 +466,45 @@  static 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)
@@ -1936,7 +1953,19 @@  static int tegra30_periph_clk_set_rate(struct clk_hw *hw, 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
@@ -1983,6 +2012,13 @@  static long tegra30_periph_clk_round_rate(struct clk_hw *hw, unsigned long rate,
 			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)
@@ -2001,10 +2037,6 @@  static unsigned long tegra30_periph_clk_recalc_rate(struct clk_hw *hw,
 
 	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);
@@ -2014,6 +2046,14 @@  static unsigned long tegra30_periph_clk_recalc_rate(struct clk_hw *hw,
 		}
 		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;
diff --git a/arch/arm/mach-tegra/tegra30_clocks_data.c b/arch/arm/mach-tegra/tegra30_clocks_data.c
index 6942c7a..e2e6022 100644
--- a/arch/arm/mach-tegra/tegra30_clocks_data.c
+++ b/arch/arm/mach-tegra/tegra30_clocks_data.c
@@ -1120,11 +1120,11 @@  PERIPH_CLK(i2c2,	"tegra-i2c.1",		"div-clk", 54,	0x198,	26000000,  mux_pllp_clkm,
 PERIPH_CLK(i2c3,	"tegra-i2c.2",		"div-clk", 67,	0x1b8,	26000000,  mux_pllp_clkm,		MUX | DIV_U16 | PERIPH_ON_APB);
 PERIPH_CLK(i2c4,	"tegra-i2c.3",		"div-clk", 103,	0x3c4,	26000000,  mux_pllp_clkm,		MUX | DIV_U16 | PERIPH_ON_APB);
 PERIPH_CLK(i2c5,	"tegra-i2c.4",		"div-clk", 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,	"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(vi,		"tegra_camera",		"vi",	20,	0x148,	425000000, mux_pllm_pllc_pllp_plla,	MUX | DIV_U71 | DIV_U71_INT);
 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);