Re: [U-Boot] [PATCH v3 3/9] tegra: Enhance clock support to handle 16-bit clock divisors

2012-02-10 Thread Tom Warren
Simon,

 -Original Message-
 From: Simon Glass [mailto:s...@chromium.org]
 Sent: Friday, February 03, 2012 6:14 PM
 To: U-Boot Mailing List
 Cc: Tom Warren; Stephen Warren; linux-te...@vger.kernel.org; Simon Glass
 Subject: [PATCH v3 3/9] tegra: Enhance clock support to handle 16-bit clock
 divisors
 
 I2C ports have a 16-bit clock divisor. Add code to handle this special case
 so that I2C speeds below 150KHz are supported.
 
 Signed-off-by: Simon Glass s...@chromium.org
 ---
 Changes in v3:
 - Add new patch to support 16-bit clock divisors required by I2C
 
  arch/arm/cpu/armv7/tegra2/clock.c  |   63 ++---
 ---
  arch/arm/include/asm/arch-tegra2/clk_rst.h |   10 -
  2 files changed, 49 insertions(+), 24 deletions(-)
 
 diff --git a/arch/arm/cpu/armv7/tegra2/clock.c
 b/arch/arm/cpu/armv7/tegra2/clock.c
 index 11d2346..e58cb3b 100644
 --- a/arch/arm/cpu/armv7/tegra2/clock.c
 +++ b/arch/arm/cpu/armv7/tegra2/clock.c
 @@ -67,6 +67,7 @@ enum clock_type_id {
   CLOCK_TYPE_MCPT,
   CLOCK_TYPE_PCM,
   CLOCK_TYPE_PCMT,
 + CLOCK_TYPE_PCMT16,  /* CLOCK_TYPE_PCMT with 16-bit divider */
   CLOCK_TYPE_PCXTS,
   CLOCK_TYPE_PDCT,
 
 @@ -98,6 +99,7 @@ static enum clock_id
 clock_source[CLOCK_TYPE_COUNT][CLOCK_MAX_MUX] = {
   { CLK(MEMORY),  CLK(CGENERAL),  CLK(PERIPH),CLK(OSC)},
   { CLK(PERIPH),  CLK(CGENERAL),  CLK(MEMORY),CLK(NONE)   },
   { CLK(PERIPH),  CLK(CGENERAL),  CLK(MEMORY),CLK(OSC)},
 + { CLK(PERIPH),  CLK(CGENERAL),  CLK(MEMORY),CLK(OSC)},
   { CLK(PERIPH),  CLK(CGENERAL),  CLK(XCPU),  CLK(OSC)},
   { CLK(PERIPH),  CLK(DISPLAY),   CLK(CGENERAL),  CLK(OSC)
   },
  };
 @@ -211,8 +213,8 @@ static enum clock_type_id
 clock_periph_type[PERIPHC_COUNT] = {
 
   /* 0x08 */
   TYPE(PERIPHC_XIO,   CLOCK_TYPE_PCMT),
 - TYPE(PERIPHC_I2C1,  CLOCK_TYPE_PCMT),
 - TYPE(PERIPHC_DVC_I2C,   CLOCK_TYPE_PCMT),
 + TYPE(PERIPHC_I2C1,  CLOCK_TYPE_PCMT16),
 + TYPE(PERIPHC_DVC_I2C,   CLOCK_TYPE_PCMT16),
   TYPE(PERIPHC_TWC,   CLOCK_TYPE_PCMT),
   TYPE(PERIPHC_NONE,  CLOCK_TYPE_NONE),
   TYPE(PERIPHC_SPI1,  CLOCK_TYPE_PCMT),
 @@ -246,7 +248,7 @@ static enum clock_type_id
 clock_periph_type[PERIPHC_COUNT] = {
   TYPE(PERIPHC_HDMI,  CLOCK_TYPE_PDCT),
   TYPE(PERIPHC_NONE,  CLOCK_TYPE_NONE),
   TYPE(PERIPHC_TVDAC, CLOCK_TYPE_PDCT),
 - TYPE(PERIPHC_I2C2,  CLOCK_TYPE_PCMT),
 + TYPE(PERIPHC_I2C2,  CLOCK_TYPE_PCMT16),
   TYPE(PERIPHC_EMC,   CLOCK_TYPE_MCPT),
 
   /* 0x28 */
 @@ -256,7 +258,7 @@ static enum clock_type_id
 clock_periph_type[PERIPHC_COUNT] = {
   TYPE(PERIPHC_NONE,  CLOCK_TYPE_NONE),
   TYPE(PERIPHC_NONE,  CLOCK_TYPE_NONE),
   TYPE(PERIPHC_SPI4,  CLOCK_TYPE_PCMT),
 - TYPE(PERIPHC_I2C3,  CLOCK_TYPE_PCMT),
 + TYPE(PERIPHC_I2C3,  CLOCK_TYPE_PCMT16),
   TYPE(PERIPHC_SDMMC3,CLOCK_TYPE_PCMT),
 
   /* 0x30 */
 @@ -518,14 +520,16 @@ void clock_ll_set_source(enum periph_id periph_id,
 unsigned source)
   * Given the parent's rate and the required rate for the children, this
 works
   * out the peripheral clock divider to use, in 7.1 binary format.
   *
 + * @param divider_bits   number of divider bits (8 or 16)
   * @param parent_rateclock rate of parent clock in Hz
   * @param rate   required clock rate for this clock
   * @return divider which should be used
   */
 -static int clk_div7_1_get_divider(unsigned long parent_rate,
 -   unsigned long rate)
 +static int clk_get_divider(unsigned divider_bits, unsigned long
 parent_rate,
 +unsigned long rate)
  {
   u64 divider = parent_rate * 2;
 + unsigned max_divider = 1  divider_bits;
 
   divider += rate - 1;
   do_div(divider, rate);
 @@ -533,7 +537,7 @@ static int clk_div7_1_get_divider(unsigned long
 parent_rate,
   if ((s64)divider - 2  0)
   return 0;
 
 - if ((s64)divider - 2  255)
 + if ((s64)divider - 2 = max_divider)
   return -1;
 
   return divider - 2;
 @@ -571,6 +575,7 @@ unsigned long clock_get_periph_rate(enum periph_id
 periph_id,
   * required child clock rate. This function assumes that a second-stage
   * divisor is available which can divide by powers of 2 from 1 to 256.
   *
 + * @param divider_bits   number of divider bits (8 or 16)
   * @param parent_rateclock rate of parent clock in Hz
   * @param rate   required clock rate for this clock
   * @param extra_div  value for the second-stage divisor (not set if
 this
 @@ -578,8 +583,8 @@ unsigned long clock_get_periph_rate(enum periph_id
 periph_id,
   * @return divider which should be used, or -1 if nothing is valid
   *
   */
 -static int find_best_divider(unsigned long parent_rate, unsigned long rate,
 - int *extra_div)
 +static int 

[U-Boot] [PATCH v3 3/9] tegra: Enhance clock support to handle 16-bit clock divisors

2012-02-03 Thread Simon Glass
I2C ports have a 16-bit clock divisor. Add code to handle this special
case so that I2C speeds below 150KHz are supported.

Signed-off-by: Simon Glass s...@chromium.org
---
Changes in v3:
- Add new patch to support 16-bit clock divisors required by I2C

 arch/arm/cpu/armv7/tegra2/clock.c  |   63 ++--
 arch/arm/include/asm/arch-tegra2/clk_rst.h |   10 -
 2 files changed, 49 insertions(+), 24 deletions(-)

diff --git a/arch/arm/cpu/armv7/tegra2/clock.c 
b/arch/arm/cpu/armv7/tegra2/clock.c
index 11d2346..e58cb3b 100644
--- a/arch/arm/cpu/armv7/tegra2/clock.c
+++ b/arch/arm/cpu/armv7/tegra2/clock.c
@@ -67,6 +67,7 @@ enum clock_type_id {
CLOCK_TYPE_MCPT,
CLOCK_TYPE_PCM,
CLOCK_TYPE_PCMT,
+   CLOCK_TYPE_PCMT16,  /* CLOCK_TYPE_PCMT with 16-bit divider */
CLOCK_TYPE_PCXTS,
CLOCK_TYPE_PDCT,
 
@@ -98,6 +99,7 @@ static enum clock_id 
clock_source[CLOCK_TYPE_COUNT][CLOCK_MAX_MUX] = {
{ CLK(MEMORY),  CLK(CGENERAL),  CLK(PERIPH),CLK(OSC)},
{ CLK(PERIPH),  CLK(CGENERAL),  CLK(MEMORY),CLK(NONE)   },
{ CLK(PERIPH),  CLK(CGENERAL),  CLK(MEMORY),CLK(OSC)},
+   { CLK(PERIPH),  CLK(CGENERAL),  CLK(MEMORY),CLK(OSC)},
{ CLK(PERIPH),  CLK(CGENERAL),  CLK(XCPU),  CLK(OSC)},
{ CLK(PERIPH),  CLK(DISPLAY),   CLK(CGENERAL),  CLK(OSC)},
 };
@@ -211,8 +213,8 @@ static enum clock_type_id clock_periph_type[PERIPHC_COUNT] 
= {
 
/* 0x08 */
TYPE(PERIPHC_XIO,   CLOCK_TYPE_PCMT),
-   TYPE(PERIPHC_I2C1,  CLOCK_TYPE_PCMT),
-   TYPE(PERIPHC_DVC_I2C,   CLOCK_TYPE_PCMT),
+   TYPE(PERIPHC_I2C1,  CLOCK_TYPE_PCMT16),
+   TYPE(PERIPHC_DVC_I2C,   CLOCK_TYPE_PCMT16),
TYPE(PERIPHC_TWC,   CLOCK_TYPE_PCMT),
TYPE(PERIPHC_NONE,  CLOCK_TYPE_NONE),
TYPE(PERIPHC_SPI1,  CLOCK_TYPE_PCMT),
@@ -246,7 +248,7 @@ static enum clock_type_id clock_periph_type[PERIPHC_COUNT] 
= {
TYPE(PERIPHC_HDMI,  CLOCK_TYPE_PDCT),
TYPE(PERIPHC_NONE,  CLOCK_TYPE_NONE),
TYPE(PERIPHC_TVDAC, CLOCK_TYPE_PDCT),
-   TYPE(PERIPHC_I2C2,  CLOCK_TYPE_PCMT),
+   TYPE(PERIPHC_I2C2,  CLOCK_TYPE_PCMT16),
TYPE(PERIPHC_EMC,   CLOCK_TYPE_MCPT),
 
/* 0x28 */
@@ -256,7 +258,7 @@ static enum clock_type_id clock_periph_type[PERIPHC_COUNT] 
= {
TYPE(PERIPHC_NONE,  CLOCK_TYPE_NONE),
TYPE(PERIPHC_NONE,  CLOCK_TYPE_NONE),
TYPE(PERIPHC_SPI4,  CLOCK_TYPE_PCMT),
-   TYPE(PERIPHC_I2C3,  CLOCK_TYPE_PCMT),
+   TYPE(PERIPHC_I2C3,  CLOCK_TYPE_PCMT16),
TYPE(PERIPHC_SDMMC3,CLOCK_TYPE_PCMT),
 
/* 0x30 */
@@ -518,14 +520,16 @@ void clock_ll_set_source(enum periph_id periph_id, 
unsigned source)
  * Given the parent's rate and the required rate for the children, this works
  * out the peripheral clock divider to use, in 7.1 binary format.
  *
+ * @param divider_bits number of divider bits (8 or 16)
  * @param parent_rate  clock rate of parent clock in Hz
  * @param rate required clock rate for this clock
  * @return divider which should be used
  */
-static int clk_div7_1_get_divider(unsigned long parent_rate,
- unsigned long rate)
+static int clk_get_divider(unsigned divider_bits, unsigned long parent_rate,
+  unsigned long rate)
 {
u64 divider = parent_rate * 2;
+   unsigned max_divider = 1  divider_bits;
 
divider += rate - 1;
do_div(divider, rate);
@@ -533,7 +537,7 @@ static int clk_div7_1_get_divider(unsigned long parent_rate,
if ((s64)divider - 2  0)
return 0;
 
-   if ((s64)divider - 2  255)
+   if ((s64)divider - 2 = max_divider)
return -1;
 
return divider - 2;
@@ -571,6 +575,7 @@ unsigned long clock_get_periph_rate(enum periph_id 
periph_id,
  * required child clock rate. This function assumes that a second-stage
  * divisor is available which can divide by powers of 2 from 1 to 256.
  *
+ * @param divider_bits number of divider bits (8 or 16)
  * @param parent_rate  clock rate of parent clock in Hz
  * @param rate required clock rate for this clock
  * @param extra_divvalue for the second-stage divisor (not set if this
@@ -578,8 +583,8 @@ unsigned long clock_get_periph_rate(enum periph_id 
periph_id,
  * @return divider which should be used, or -1 if nothing is valid
  *
  */
-static int find_best_divider(unsigned long parent_rate, unsigned long rate,
-   int *extra_div)
+static int find_best_divider(unsigned divider_bits, unsigned long parent_rate,
+unsigned long rate, int *extra_div)
 {
int shift;
int best_divider = -1;
@@ -588,7 +593,8 @@ static int find_best_divider(unsigned long parent_rate, 
unsigned long rate,
/* try dividers from 1 to 256 and find closest match */
for