diff mbox

[U-Boot,v3,3/6] Exynos542x: Add and enable get_periph_rate support

Message ID 1421387300-13502-4-git-send-email-akshay.s@samsung.com
State Changes Requested
Delegated to: Minkyu Kang
Headers show

Commit Message

Akshay Saraswat Jan. 16, 2015, 5:48 a.m. UTC
We planned to fetch peripheral rate through one generic API per
peripheral. These generic peripheral functions are in turn
expected to fetch apt values from a function refactored as
per SoC versions. This patch adds support for fetching peripheral
rates for Exynos5420 and Exynos5800.

Signed-off-by: Akshay Saraswat <akshay.s@samsung.com>
---
Changes since v2:
	- Fixed enum and exynos542x_get_periph_rate switch.
	- Added checks for negative values in exynos542x_get_periph_rate.

Changes since v1:
	- Changes suuport -> support in commit message.
	- Removed position change of exynos5420_get_pll_clk.
	- Removed #ifdef.

 arch/arm/cpu/armv7/exynos/clock.c      | 151 +++++++++++++++++++++++++++++++--
 arch/arm/include/asm/arch-exynos/clk.h |   3 +
 2 files changed, 147 insertions(+), 7 deletions(-)

Comments

Joonyoung Shim Jan. 16, 2015, 6:09 a.m. UTC | #1
Hi,

On 01/16/2015 02:48 PM, Akshay Saraswat wrote:
> We planned to fetch peripheral rate through one generic API per
> peripheral. These generic peripheral functions are in turn
> expected to fetch apt values from a function refactored as
> per SoC versions. This patch adds support for fetching peripheral
> rates for Exynos5420 and Exynos5800.
> 
> Signed-off-by: Akshay Saraswat <akshay.s@samsung.com>
> ---
> Changes since v2:
> 	- Fixed enum and exynos542x_get_periph_rate switch.
> 	- Added checks for negative values in exynos542x_get_periph_rate.
> 
> Changes since v1:
> 	- Changes suuport -> support in commit message.
> 	- Removed position change of exynos5420_get_pll_clk.
> 	- Removed #ifdef.
> 
>  arch/arm/cpu/armv7/exynos/clock.c      | 151 +++++++++++++++++++++++++++++++--
>  arch/arm/include/asm/arch-exynos/clk.h |   3 +
>  2 files changed, 147 insertions(+), 7 deletions(-)
> 
> diff --git a/arch/arm/cpu/armv7/exynos/clock.c b/arch/arm/cpu/armv7/exynos/clock.c
> index 5dc9ed2..ee6c13b 100644
> --- a/arch/arm/cpu/armv7/exynos/clock.c
> +++ b/arch/arm/cpu/armv7/exynos/clock.c
> @@ -27,7 +27,7 @@ struct clk_bit_info {
>  };
>  
>  /* periph_id src_bit div_bit prediv_bit */
> -static struct clk_bit_info clk_bit_info[] = {
> +static struct clk_bit_info exynos5_bit_info[] = {
>  	{PERIPH_ID_UART0,	0,	0,	-1},
>  	{PERIPH_ID_UART1,	4,	4,	-1},
>  	{PERIPH_ID_UART2,	8,	8,	-1},
> @@ -61,6 +61,42 @@ static struct clk_bit_info clk_bit_info[] = {
>  	{PERIPH_ID_NONE,	-1,	-1,	-1},
>  };
>  
> +static struct clk_bit_info exynos542x_bit_info[] = {
> +	{PERIPH_ID_UART0,	4,	8,	-1},
> +	{PERIPH_ID_UART1,	8,	12,	-1},
> +	{PERIPH_ID_UART2,	12,	16,	-1},
> +	{PERIPH_ID_UART3,	16,	20,	-1},
> +	{PERIPH_ID_I2C0,	-1,	8,	-1},
> +	{PERIPH_ID_I2C1,	-1,	8,	-1},
> +	{PERIPH_ID_I2C2,	-1,	8,	-1},
> +	{PERIPH_ID_I2C3,	-1,	8,	-1},
> +	{PERIPH_ID_I2C4,	-1,	8,	-1},
> +	{PERIPH_ID_I2C5,	-1,	8,	-1},
> +	{PERIPH_ID_I2C6,	-1,	8,	-1},
> +	{PERIPH_ID_I2C7,	-1,	8,	-1},
> +	{PERIPH_ID_SPI0,	20,	20,	8},
> +	{PERIPH_ID_SPI1,	24,	24,	16},
> +	{PERIPH_ID_SPI2,	28,	28,	24},
> +	{PERIPH_ID_SDMMC0,	0,	0,	-1},
> +	{PERIPH_ID_SDMMC1,	4,	10,	-1},
> +	{PERIPH_ID_SDMMC2,	8,	20,	-1},
> +	{PERIPH_ID_I2C8,	-1,	8,	-1},
> +	{PERIPH_ID_I2C9,	-1,	8,	-1},
> +	{PERIPH_ID_I2S0,	0,	0,	4},
> +	{PERIPH_ID_I2S1,	4,	12,	16},
> +	{PERIPH_ID_SPI3,	12,	16,	0},
> +	{PERIPH_ID_SPI4,	16,	20,	8},
> +	{PERIPH_ID_SDMMC4,	16,	0,	8},
> +	{PERIPH_ID_PWM0,	24,	28,	-1},
> +	{PERIPH_ID_PWM1,	24,	28,	-1},
> +	{PERIPH_ID_PWM2,	24,	28,	-1},
> +	{PERIPH_ID_PWM3,	24,	28,	-1},
> +	{PERIPH_ID_PWM4,	24,	28,	-1},
> +	{PERIPH_ID_I2C10,	-1,	8,	-1},
> +
> +	{PERIPH_ID_NONE,	-1,	-1,	-1},
> +};
> +
>  /* Epll Clock division values to achive different frequency output */
>  static struct set_epll_con_val exynos5_epll_div[] = {
>  	{ 192000000, 0, 48, 3, 1, 0 },
> @@ -306,16 +342,22 @@ static unsigned long exynos542x_get_pll_clk(int pllreg)
>  static struct clk_bit_info *get_clk_bit_info(int peripheral)
>  {
>  	int i;
> +	struct clk_bit_info *info;
>  
> -	for (i = 0; clk_bit_info[i].id != PERIPH_ID_NONE; i++) {
> -		if (clk_bit_info[i].id == peripheral)
> +	if (proid_is_exynos5420() || proid_is_exynos5800())
> +		info = exynos542x_bit_info;
> +	else
> +		info = exynos5_bit_info;
> +
> +	for (i = 0; info[i].id != PERIPH_ID_NONE; i++) {
> +		if (info[i].id == peripheral)
>  			break;
>  	}
>  
> -	if (clk_bit_info[i].id == PERIPH_ID_NONE)
> +	if (info[i].id == PERIPH_ID_NONE)
>  		debug("ERROR: Peripheral ID %d not found\n", peripheral);
>  
> -	return &clk_bit_info[i];
> +	return &info[i];
>  }
>  
>  static unsigned long exynos5_get_periph_rate(int peripheral)
> @@ -414,12 +456,107 @@ static unsigned long exynos5_get_periph_rate(int peripheral)
>  	return sub_clk;
>  }
>  
> +static unsigned long exynos542x_get_periph_rate(int peripheral)
> +{
> +	struct clk_bit_info *bit_info = get_clk_bit_info(peripheral);
> +	unsigned long sclk, sub_clk = 0;
> +	unsigned int src, div, sub_div = 0;
> +	struct exynos5420_clock *clk =
> +			(struct exynos5420_clock *)samsung_get_base_clock();
> +
> +	switch (peripheral) {
> +	case PERIPH_ID_UART0:
> +	case PERIPH_ID_UART1:
> +	case PERIPH_ID_UART2:
> +	case PERIPH_ID_UART3:
> +	case PERIPH_ID_PWM0:
> +	case PERIPH_ID_PWM1:
> +	case PERIPH_ID_PWM2:
> +	case PERIPH_ID_PWM3:
> +	case PERIPH_ID_PWM4:
> +		src = readl(&clk->src_peric0);
> +		div = readl(&clk->div_peric0);
> +		break;
> +	case PERIPH_ID_SPI0:
> +	case PERIPH_ID_SPI1:
> +	case PERIPH_ID_SPI2:
> +		src = readl(&clk->src_peric1);
> +		div = readl(&clk->div_peric1);
> +		sub_div = readl(&clk->div_peric4);
> +		break;
> +	case PERIPH_ID_SPI3:
> +	case PERIPH_ID_SPI4:
> +		src = readl(&clk->src_isp);
> +		div = readl(&clk->div_isp1);
> +		sub_div = readl(&clk->div_isp1);
> +		break;
> +	case PERIPH_ID_SDMMC0:
> +	case PERIPH_ID_SDMMC1:
> +	case PERIPH_ID_SDMMC2:
> +	case PERIPH_ID_SDMMC3:
> +		src = readl(&clk->src_fsys);
> +		div = readl(&clk->div_fsys1);
> +		break;
> +	case PERIPH_ID_I2C0:
> +	case PERIPH_ID_I2C1:
> +	case PERIPH_ID_I2C2:
> +	case PERIPH_ID_I2C3:
> +	case PERIPH_ID_I2C4:
> +	case PERIPH_ID_I2C5:
> +	case PERIPH_ID_I2C6:
> +	case PERIPH_ID_I2C7:
> +	case PERIPH_ID_I2C8:
> +	case PERIPH_ID_I2C9:
> +	case PERIPH_ID_I2C10:
> +		sclk = exynos542x_get_pll_clk(MPLL);
> +		sub_div = ((readl(&clk->div_top1) >> bit_info->div_bit)
> +								& 0x7) + 1;
> +		return sclk / sub_div;
> +	default:
> +		debug("%s: invalid peripheral %d", __func__, peripheral);
> +		return -1;
> +	};
> +
> +	if (bit_info->src_bit >= 0)
> +		src = (src >> bit_info->src_bit) & 0xf;
> +
> +	switch (src) {
> +	case EXYNOS542x_SRC_MPLL:
> +		sclk = exynos542x_get_pll_clk(MPLL);
> +		break;
> +	case EXYNOS542x_SRC_EPLL:
> +		sclk = exynos542x_get_pll_clk(EPLL);
> +		break;
> +	case EXYNOS542x_SRC_RPLL:
> +		sclk = exynos542x_get_pll_clk(RPLL);
> +		break;
> +	default:
> +		return 0;
> +	}
> +

Odroid xu3 board uses SPLL as source clock for SDMMCx, please SPLL case.

> +	/* Ratio clock division for this peripheral */
> +	if (bit_info->div_bit >= 0) {
> +		div = (div >> bit_info->div_bit) & 0xf;

Hmm, mask bits are different each peripheral, e.g. SDMMCx needs 0x3ff
mask bits.

> +		sub_clk = sclk / (div + 1);
> +	}
> +
> +	if (bit_info->prediv_bit >= 0) {
> +		sub_div = (sub_div >> bit_info->prediv_bit) & 0xff;
> +		return sub_clk / (sub_div + 1);
> +	}
> +
> +	return sub_clk;
> +}
> +
>  unsigned long clock_get_periph_rate(int peripheral)
>  {
> -	if (cpu_is_exynos5())
> +	if (cpu_is_exynos5()) {
> +		if (proid_is_exynos5420() || proid_is_exynos5800())
> +			return exynos542x_get_periph_rate(peripheral);
>  		return exynos5_get_periph_rate(peripheral);
> -	else
> +	} else {
>  		return 0;
> +	}
>  }
>  
>  /* exynos4: return ARM clock frequency */
> diff --git a/arch/arm/include/asm/arch-exynos/clk.h b/arch/arm/include/asm/arch-exynos/clk.h
> index db24dc0..da9bfcd 100644
> --- a/arch/arm/include/asm/arch-exynos/clk.h
> +++ b/arch/arm/include/asm/arch-exynos/clk.h
> @@ -26,6 +26,9 @@ enum pll_src_bit {
>  	EXYNOS_SRC_MPLL = 6,
>  	EXYNOS_SRC_EPLL,
>  	EXYNOS_SRC_VPLL,
> +	EXYNOS542x_SRC_MPLL = 3,
> +	EXYNOS542x_SRC_EPLL = 6,
> +	EXYNOS542x_SRC_RPLL,

Sorry, i want to use EXYNOS542X instead of EXYNOS542x.

Thanks.
Simon Glass Jan. 28, 2015, 4:09 a.m. UTC | #2
Hi,

On 15 January 2015 at 23:09, Joonyoung Shim <jy0922.shim@samsung.com> wrote:
> Hi,
>
> On 01/16/2015 02:48 PM, Akshay Saraswat wrote:
>> We planned to fetch peripheral rate through one generic API per
>> peripheral. These generic peripheral functions are in turn
>> expected to fetch apt values from a function refactored as
>> per SoC versions. This patch adds support for fetching peripheral
>> rates for Exynos5420 and Exynos5800.
>>
>> Signed-off-by: Akshay Saraswat <akshay.s@samsung.com>
>> ---
>> Changes since v2:
>>       - Fixed enum and exynos542x_get_periph_rate switch.
>>       - Added checks for negative values in exynos542x_get_periph_rate.
>>
>> Changes since v1:
>>       - Changes suuport -> support in commit message.
>>       - Removed position change of exynos5420_get_pll_clk.
>>       - Removed #ifdef.
>>
>>  arch/arm/cpu/armv7/exynos/clock.c      | 151 +++++++++++++++++++++++++++++++--
>>  arch/arm/include/asm/arch-exynos/clk.h |   3 +
>>  2 files changed, 147 insertions(+), 7 deletions(-)

What else needs to be done to get this applied, please?

>>
>> diff --git a/arch/arm/cpu/armv7/exynos/clock.c b/arch/arm/cpu/armv7/exynos/clock.c
>> index 5dc9ed2..ee6c13b 100644
>> --- a/arch/arm/cpu/armv7/exynos/clock.c
>> +++ b/arch/arm/cpu/armv7/exynos/clock.c
>> @@ -27,7 +27,7 @@ struct clk_bit_info {
>>  };
>>
>>  /* periph_id src_bit div_bit prediv_bit */
>> -static struct clk_bit_info clk_bit_info[] = {
>> +static struct clk_bit_info exynos5_bit_info[] = {
>>       {PERIPH_ID_UART0,       0,      0,      -1},
>>       {PERIPH_ID_UART1,       4,      4,      -1},
>>       {PERIPH_ID_UART2,       8,      8,      -1},
>> @@ -61,6 +61,42 @@ static struct clk_bit_info clk_bit_info[] = {
>>       {PERIPH_ID_NONE,        -1,     -1,     -1},
>>  };
>>
>> +static struct clk_bit_info exynos542x_bit_info[] = {
>> +     {PERIPH_ID_UART0,       4,      8,      -1},
>> +     {PERIPH_ID_UART1,       8,      12,     -1},
>> +     {PERIPH_ID_UART2,       12,     16,     -1},
>> +     {PERIPH_ID_UART3,       16,     20,     -1},
>> +     {PERIPH_ID_I2C0,        -1,     8,      -1},
>> +     {PERIPH_ID_I2C1,        -1,     8,      -1},
>> +     {PERIPH_ID_I2C2,        -1,     8,      -1},
>> +     {PERIPH_ID_I2C3,        -1,     8,      -1},
>> +     {PERIPH_ID_I2C4,        -1,     8,      -1},
>> +     {PERIPH_ID_I2C5,        -1,     8,      -1},
>> +     {PERIPH_ID_I2C6,        -1,     8,      -1},
>> +     {PERIPH_ID_I2C7,        -1,     8,      -1},
>> +     {PERIPH_ID_SPI0,        20,     20,     8},
>> +     {PERIPH_ID_SPI1,        24,     24,     16},
>> +     {PERIPH_ID_SPI2,        28,     28,     24},
>> +     {PERIPH_ID_SDMMC0,      0,      0,      -1},
>> +     {PERIPH_ID_SDMMC1,      4,      10,     -1},
>> +     {PERIPH_ID_SDMMC2,      8,      20,     -1},
>> +     {PERIPH_ID_I2C8,        -1,     8,      -1},
>> +     {PERIPH_ID_I2C9,        -1,     8,      -1},
>> +     {PERIPH_ID_I2S0,        0,      0,      4},
>> +     {PERIPH_ID_I2S1,        4,      12,     16},
>> +     {PERIPH_ID_SPI3,        12,     16,     0},
>> +     {PERIPH_ID_SPI4,        16,     20,     8},
>> +     {PERIPH_ID_SDMMC4,      16,     0,      8},
>> +     {PERIPH_ID_PWM0,        24,     28,     -1},
>> +     {PERIPH_ID_PWM1,        24,     28,     -1},
>> +     {PERIPH_ID_PWM2,        24,     28,     -1},
>> +     {PERIPH_ID_PWM3,        24,     28,     -1},
>> +     {PERIPH_ID_PWM4,        24,     28,     -1},
>> +     {PERIPH_ID_I2C10,       -1,     8,      -1},
>> +
>> +     {PERIPH_ID_NONE,        -1,     -1,     -1},
>> +};
>> +
>>  /* Epll Clock division values to achive different frequency output */
>>  static struct set_epll_con_val exynos5_epll_div[] = {
>>       { 192000000, 0, 48, 3, 1, 0 },
>> @@ -306,16 +342,22 @@ static unsigned long exynos542x_get_pll_clk(int pllreg)
>>  static struct clk_bit_info *get_clk_bit_info(int peripheral)
>>  {
>>       int i;
>> +     struct clk_bit_info *info;
>>
>> -     for (i = 0; clk_bit_info[i].id != PERIPH_ID_NONE; i++) {
>> -             if (clk_bit_info[i].id == peripheral)
>> +     if (proid_is_exynos5420() || proid_is_exynos5800())
>> +             info = exynos542x_bit_info;
>> +     else
>> +             info = exynos5_bit_info;
>> +
>> +     for (i = 0; info[i].id != PERIPH_ID_NONE; i++) {
>> +             if (info[i].id == peripheral)
>>                       break;
>>       }
>>
>> -     if (clk_bit_info[i].id == PERIPH_ID_NONE)
>> +     if (info[i].id == PERIPH_ID_NONE)
>>               debug("ERROR: Peripheral ID %d not found\n", peripheral);
>>
>> -     return &clk_bit_info[i];
>> +     return &info[i];
>>  }
>>
>>  static unsigned long exynos5_get_periph_rate(int peripheral)
>> @@ -414,12 +456,107 @@ static unsigned long exynos5_get_periph_rate(int peripheral)
>>       return sub_clk;
>>  }
>>
>> +static unsigned long exynos542x_get_periph_rate(int peripheral)
>> +{
>> +     struct clk_bit_info *bit_info = get_clk_bit_info(peripheral);
>> +     unsigned long sclk, sub_clk = 0;
>> +     unsigned int src, div, sub_div = 0;
>> +     struct exynos5420_clock *clk =
>> +                     (struct exynos5420_clock *)samsung_get_base_clock();
>> +
>> +     switch (peripheral) {
>> +     case PERIPH_ID_UART0:
>> +     case PERIPH_ID_UART1:
>> +     case PERIPH_ID_UART2:
>> +     case PERIPH_ID_UART3:
>> +     case PERIPH_ID_PWM0:
>> +     case PERIPH_ID_PWM1:
>> +     case PERIPH_ID_PWM2:
>> +     case PERIPH_ID_PWM3:
>> +     case PERIPH_ID_PWM4:
>> +             src = readl(&clk->src_peric0);
>> +             div = readl(&clk->div_peric0);
>> +             break;
>> +     case PERIPH_ID_SPI0:
>> +     case PERIPH_ID_SPI1:
>> +     case PERIPH_ID_SPI2:
>> +             src = readl(&clk->src_peric1);
>> +             div = readl(&clk->div_peric1);
>> +             sub_div = readl(&clk->div_peric4);
>> +             break;
>> +     case PERIPH_ID_SPI3:
>> +     case PERIPH_ID_SPI4:
>> +             src = readl(&clk->src_isp);
>> +             div = readl(&clk->div_isp1);
>> +             sub_div = readl(&clk->div_isp1);
>> +             break;
>> +     case PERIPH_ID_SDMMC0:
>> +     case PERIPH_ID_SDMMC1:
>> +     case PERIPH_ID_SDMMC2:
>> +     case PERIPH_ID_SDMMC3:
>> +             src = readl(&clk->src_fsys);
>> +             div = readl(&clk->div_fsys1);
>> +             break;
>> +     case PERIPH_ID_I2C0:
>> +     case PERIPH_ID_I2C1:
>> +     case PERIPH_ID_I2C2:
>> +     case PERIPH_ID_I2C3:
>> +     case PERIPH_ID_I2C4:
>> +     case PERIPH_ID_I2C5:
>> +     case PERIPH_ID_I2C6:
>> +     case PERIPH_ID_I2C7:
>> +     case PERIPH_ID_I2C8:
>> +     case PERIPH_ID_I2C9:
>> +     case PERIPH_ID_I2C10:
>> +             sclk = exynos542x_get_pll_clk(MPLL);
>> +             sub_div = ((readl(&clk->div_top1) >> bit_info->div_bit)
>> +                                                             & 0x7) + 1;
>> +             return sclk / sub_div;
>> +     default:
>> +             debug("%s: invalid peripheral %d", __func__, peripheral);
>> +             return -1;
>> +     };
>> +
>> +     if (bit_info->src_bit >= 0)
>> +             src = (src >> bit_info->src_bit) & 0xf;
>> +
>> +     switch (src) {
>> +     case EXYNOS542x_SRC_MPLL:
>> +             sclk = exynos542x_get_pll_clk(MPLL);
>> +             break;
>> +     case EXYNOS542x_SRC_EPLL:
>> +             sclk = exynos542x_get_pll_clk(EPLL);
>> +             break;
>> +     case EXYNOS542x_SRC_RPLL:
>> +             sclk = exynos542x_get_pll_clk(RPLL);
>> +             break;
>> +     default:
>> +             return 0;
>> +     }
>> +
>
> Odroid xu3 board uses SPLL as source clock for SDMMCx, please SPLL case.

Perhaps this can be sorted out by the maintainer of that board? I'm
not sure how we can deal with this other than a special case.
Certainly Akshay is not going to know what to do here.

>
>> +     /* Ratio clock division for this peripheral */
>> +     if (bit_info->div_bit >= 0) {
>> +             div = (div >> bit_info->div_bit) & 0xf;
>
> Hmm, mask bits are different each peripheral, e.g. SDMMCx needs 0x3ff
> mask bits.
>
>> +             sub_clk = sclk / (div + 1);
>> +     }
>> +
>> +     if (bit_info->prediv_bit >= 0) {
>> +             sub_div = (sub_div >> bit_info->prediv_bit) & 0xff;
>> +             return sub_clk / (sub_div + 1);
>> +     }
>> +
>> +     return sub_clk;
>> +}
>> +
>>  unsigned long clock_get_periph_rate(int peripheral)
>>  {
>> -     if (cpu_is_exynos5())
>> +     if (cpu_is_exynos5()) {
>> +             if (proid_is_exynos5420() || proid_is_exynos5800())
>> +                     return exynos542x_get_periph_rate(peripheral);
>>               return exynos5_get_periph_rate(peripheral);
>> -     else
>> +     } else {
>>               return 0;
>> +     }
>>  }
>>
>>  /* exynos4: return ARM clock frequency */
>> diff --git a/arch/arm/include/asm/arch-exynos/clk.h b/arch/arm/include/asm/arch-exynos/clk.h
>> index db24dc0..da9bfcd 100644
>> --- a/arch/arm/include/asm/arch-exynos/clk.h
>> +++ b/arch/arm/include/asm/arch-exynos/clk.h
>> @@ -26,6 +26,9 @@ enum pll_src_bit {
>>       EXYNOS_SRC_MPLL = 6,
>>       EXYNOS_SRC_EPLL,
>>       EXYNOS_SRC_VPLL,
>> +     EXYNOS542x_SRC_MPLL = 3,
>> +     EXYNOS542x_SRC_EPLL = 6,
>> +     EXYNOS542x_SRC_RPLL,
>
> Sorry, i want to use EXYNOS542X instead of EXYNOS542x.

Agreed, we should use capitals for #defines.
>
> Thanks.

Regards,
Simon
Joonyoung Shim Jan. 28, 2015, 4:46 a.m. UTC | #3
Hi Simon,

On 01/28/2015 01:09 PM, Simon Glass wrote:
> Hi,
> 
> On 15 January 2015 at 23:09, Joonyoung Shim <jy0922.shim@samsung.com> wrote:
>> Hi,
>>
>> On 01/16/2015 02:48 PM, Akshay Saraswat wrote:
>>> We planned to fetch peripheral rate through one generic API per
>>> peripheral. These generic peripheral functions are in turn
>>> expected to fetch apt values from a function refactored as
>>> per SoC versions. This patch adds support for fetching peripheral
>>> rates for Exynos5420 and Exynos5800.
>>>
>>> Signed-off-by: Akshay Saraswat <akshay.s@samsung.com>
>>> ---
>>> Changes since v2:
>>>       - Fixed enum and exynos542x_get_periph_rate switch.
>>>       - Added checks for negative values in exynos542x_get_periph_rate.
>>>
>>> Changes since v1:
>>>       - Changes suuport -> support in commit message.
>>>       - Removed position change of exynos5420_get_pll_clk.
>>>       - Removed #ifdef.
>>>
>>>  arch/arm/cpu/armv7/exynos/clock.c      | 151 +++++++++++++++++++++++++++++++--
>>>  arch/arm/include/asm/arch-exynos/clk.h |   3 +
>>>  2 files changed, 147 insertions(+), 7 deletions(-)
> 
> What else needs to be done to get this applied, please?
> 

As i said, current this patch has some problem like mask bits, so eMMC
doesn't work normally.

>>>
>>> diff --git a/arch/arm/cpu/armv7/exynos/clock.c b/arch/arm/cpu/armv7/exynos/clock.c
>>> index 5dc9ed2..ee6c13b 100644
>>> --- a/arch/arm/cpu/armv7/exynos/clock.c
>>> +++ b/arch/arm/cpu/armv7/exynos/clock.c
>>> @@ -27,7 +27,7 @@ struct clk_bit_info {
>>>  };
>>>
>>>  /* periph_id src_bit div_bit prediv_bit */
>>> -static struct clk_bit_info clk_bit_info[] = {
>>> +static struct clk_bit_info exynos5_bit_info[] = {
>>>       {PERIPH_ID_UART0,       0,      0,      -1},
>>>       {PERIPH_ID_UART1,       4,      4,      -1},
>>>       {PERIPH_ID_UART2,       8,      8,      -1},
>>> @@ -61,6 +61,42 @@ static struct clk_bit_info clk_bit_info[] = {
>>>       {PERIPH_ID_NONE,        -1,     -1,     -1},
>>>  };
>>>
>>> +static struct clk_bit_info exynos542x_bit_info[] = {
>>> +     {PERIPH_ID_UART0,       4,      8,      -1},
>>> +     {PERIPH_ID_UART1,       8,      12,     -1},
>>> +     {PERIPH_ID_UART2,       12,     16,     -1},
>>> +     {PERIPH_ID_UART3,       16,     20,     -1},
>>> +     {PERIPH_ID_I2C0,        -1,     8,      -1},
>>> +     {PERIPH_ID_I2C1,        -1,     8,      -1},
>>> +     {PERIPH_ID_I2C2,        -1,     8,      -1},
>>> +     {PERIPH_ID_I2C3,        -1,     8,      -1},
>>> +     {PERIPH_ID_I2C4,        -1,     8,      -1},
>>> +     {PERIPH_ID_I2C5,        -1,     8,      -1},
>>> +     {PERIPH_ID_I2C6,        -1,     8,      -1},
>>> +     {PERIPH_ID_I2C7,        -1,     8,      -1},
>>> +     {PERIPH_ID_SPI0,        20,     20,     8},
>>> +     {PERIPH_ID_SPI1,        24,     24,     16},
>>> +     {PERIPH_ID_SPI2,        28,     28,     24},
>>> +     {PERIPH_ID_SDMMC0,      0,      0,      -1},
>>> +     {PERIPH_ID_SDMMC1,      4,      10,     -1},
>>> +     {PERIPH_ID_SDMMC2,      8,      20,     -1},
>>> +     {PERIPH_ID_I2C8,        -1,     8,      -1},
>>> +     {PERIPH_ID_I2C9,        -1,     8,      -1},
>>> +     {PERIPH_ID_I2S0,        0,      0,      4},
>>> +     {PERIPH_ID_I2S1,        4,      12,     16},
>>> +     {PERIPH_ID_SPI3,        12,     16,     0},
>>> +     {PERIPH_ID_SPI4,        16,     20,     8},
>>> +     {PERIPH_ID_SDMMC4,      16,     0,      8},
>>> +     {PERIPH_ID_PWM0,        24,     28,     -1},
>>> +     {PERIPH_ID_PWM1,        24,     28,     -1},
>>> +     {PERIPH_ID_PWM2,        24,     28,     -1},
>>> +     {PERIPH_ID_PWM3,        24,     28,     -1},
>>> +     {PERIPH_ID_PWM4,        24,     28,     -1},
>>> +     {PERIPH_ID_I2C10,       -1,     8,      -1},
>>> +
>>> +     {PERIPH_ID_NONE,        -1,     -1,     -1},
>>> +};
>>> +
>>>  /* Epll Clock division values to achive different frequency output */
>>>  static struct set_epll_con_val exynos5_epll_div[] = {
>>>       { 192000000, 0, 48, 3, 1, 0 },
>>> @@ -306,16 +342,22 @@ static unsigned long exynos542x_get_pll_clk(int pllreg)
>>>  static struct clk_bit_info *get_clk_bit_info(int peripheral)
>>>  {
>>>       int i;
>>> +     struct clk_bit_info *info;
>>>
>>> -     for (i = 0; clk_bit_info[i].id != PERIPH_ID_NONE; i++) {
>>> -             if (clk_bit_info[i].id == peripheral)
>>> +     if (proid_is_exynos5420() || proid_is_exynos5800())
>>> +             info = exynos542x_bit_info;
>>> +     else
>>> +             info = exynos5_bit_info;
>>> +
>>> +     for (i = 0; info[i].id != PERIPH_ID_NONE; i++) {
>>> +             if (info[i].id == peripheral)
>>>                       break;
>>>       }
>>>
>>> -     if (clk_bit_info[i].id == PERIPH_ID_NONE)
>>> +     if (info[i].id == PERIPH_ID_NONE)
>>>               debug("ERROR: Peripheral ID %d not found\n", peripheral);
>>>
>>> -     return &clk_bit_info[i];
>>> +     return &info[i];
>>>  }
>>>
>>>  static unsigned long exynos5_get_periph_rate(int peripheral)
>>> @@ -414,12 +456,107 @@ static unsigned long exynos5_get_periph_rate(int peripheral)
>>>       return sub_clk;
>>>  }
>>>
>>> +static unsigned long exynos542x_get_periph_rate(int peripheral)
>>> +{
>>> +     struct clk_bit_info *bit_info = get_clk_bit_info(peripheral);
>>> +     unsigned long sclk, sub_clk = 0;
>>> +     unsigned int src, div, sub_div = 0;
>>> +     struct exynos5420_clock *clk =
>>> +                     (struct exynos5420_clock *)samsung_get_base_clock();
>>> +
>>> +     switch (peripheral) {
>>> +     case PERIPH_ID_UART0:
>>> +     case PERIPH_ID_UART1:
>>> +     case PERIPH_ID_UART2:
>>> +     case PERIPH_ID_UART3:
>>> +     case PERIPH_ID_PWM0:
>>> +     case PERIPH_ID_PWM1:
>>> +     case PERIPH_ID_PWM2:
>>> +     case PERIPH_ID_PWM3:
>>> +     case PERIPH_ID_PWM4:
>>> +             src = readl(&clk->src_peric0);
>>> +             div = readl(&clk->div_peric0);
>>> +             break;
>>> +     case PERIPH_ID_SPI0:
>>> +     case PERIPH_ID_SPI1:
>>> +     case PERIPH_ID_SPI2:
>>> +             src = readl(&clk->src_peric1);
>>> +             div = readl(&clk->div_peric1);
>>> +             sub_div = readl(&clk->div_peric4);
>>> +             break;
>>> +     case PERIPH_ID_SPI3:
>>> +     case PERIPH_ID_SPI4:
>>> +             src = readl(&clk->src_isp);
>>> +             div = readl(&clk->div_isp1);
>>> +             sub_div = readl(&clk->div_isp1);
>>> +             break;
>>> +     case PERIPH_ID_SDMMC0:
>>> +     case PERIPH_ID_SDMMC1:
>>> +     case PERIPH_ID_SDMMC2:
>>> +     case PERIPH_ID_SDMMC3:
>>> +             src = readl(&clk->src_fsys);
>>> +             div = readl(&clk->div_fsys1);
>>> +             break;
>>> +     case PERIPH_ID_I2C0:
>>> +     case PERIPH_ID_I2C1:
>>> +     case PERIPH_ID_I2C2:
>>> +     case PERIPH_ID_I2C3:
>>> +     case PERIPH_ID_I2C4:
>>> +     case PERIPH_ID_I2C5:
>>> +     case PERIPH_ID_I2C6:
>>> +     case PERIPH_ID_I2C7:
>>> +     case PERIPH_ID_I2C8:
>>> +     case PERIPH_ID_I2C9:
>>> +     case PERIPH_ID_I2C10:
>>> +             sclk = exynos542x_get_pll_clk(MPLL);
>>> +             sub_div = ((readl(&clk->div_top1) >> bit_info->div_bit)
>>> +                                                             & 0x7) + 1;
>>> +             return sclk / sub_div;
>>> +     default:
>>> +             debug("%s: invalid peripheral %d", __func__, peripheral);
>>> +             return -1;
>>> +     };
>>> +
>>> +     if (bit_info->src_bit >= 0)
>>> +             src = (src >> bit_info->src_bit) & 0xf;
>>> +
>>> +     switch (src) {
>>> +     case EXYNOS542x_SRC_MPLL:
>>> +             sclk = exynos542x_get_pll_clk(MPLL);
>>> +             break;
>>> +     case EXYNOS542x_SRC_EPLL:
>>> +             sclk = exynos542x_get_pll_clk(EPLL);
>>> +             break;
>>> +     case EXYNOS542x_SRC_RPLL:
>>> +             sclk = exynos542x_get_pll_clk(RPLL);
>>> +             break;
>>> +     default:
>>> +             return 0;
>>> +     }
>>> +
>>
>> Odroid xu3 board uses SPLL as source clock for SDMMCx, please SPLL case.
> 
> Perhaps this can be sorted out by the maintainer of that board? I'm
> not sure how we can deal with this other than a special case.
> Certainly Akshay is not going to know what to do here.
> 

I don't think this is special case, SPLL also can be used as source
clock like MPLL, EPLL and RPLL.

>>
>>> +     /* Ratio clock division for this peripheral */
>>> +     if (bit_info->div_bit >= 0) {
>>> +             div = (div >> bit_info->div_bit) & 0xf;
>>
>> Hmm, mask bits are different each peripheral, e.g. SDMMCx needs 0x3ff
>> mask bits.
>>

Akshay, could you follow up this?

Thanks.
Simon Glass Jan. 28, 2015, 5:01 a.m. UTC | #4
Hi Joonyoung,

On 27 January 2015 at 21:46, Joonyoung Shim <jy0922.shim@samsung.com> wrote:
> Hi Simon,
>
> On 01/28/2015 01:09 PM, Simon Glass wrote:
>> Hi,
>>
>> On 15 January 2015 at 23:09, Joonyoung Shim <jy0922.shim@samsung.com> wrote:
>>> Hi,
>>>
>>> On 01/16/2015 02:48 PM, Akshay Saraswat wrote:
>>>> We planned to fetch peripheral rate through one generic API per
>>>> peripheral. These generic peripheral functions are in turn
>>>> expected to fetch apt values from a function refactored as
>>>> per SoC versions. This patch adds support for fetching peripheral
>>>> rates for Exynos5420 and Exynos5800.
>>>>
>>>> Signed-off-by: Akshay Saraswat <akshay.s@samsung.com>
>>>> ---
>>>> Changes since v2:
>>>>       - Fixed enum and exynos542x_get_periph_rate switch.
>>>>       - Added checks for negative values in exynos542x_get_periph_rate.
>>>>
>>>> Changes since v1:
>>>>       - Changes suuport -> support in commit message.
>>>>       - Removed position change of exynos5420_get_pll_clk.
>>>>       - Removed #ifdef.
>>>>
>>>>  arch/arm/cpu/armv7/exynos/clock.c      | 151 +++++++++++++++++++++++++++++++--
>>>>  arch/arm/include/asm/arch-exynos/clk.h |   3 +
>>>>  2 files changed, 147 insertions(+), 7 deletions(-)
>>
>> What else needs to be done to get this applied, please?
>>
>
> As i said, current this patch has some problem like mask bits, so eMMC
> doesn't work normally.
>
>>>>
>>>> diff --git a/arch/arm/cpu/armv7/exynos/clock.c b/arch/arm/cpu/armv7/exynos/clock.c
>>>> index 5dc9ed2..ee6c13b 100644
>>>> --- a/arch/arm/cpu/armv7/exynos/clock.c
>>>> +++ b/arch/arm/cpu/armv7/exynos/clock.c
>>>> @@ -27,7 +27,7 @@ struct clk_bit_info {
>>>>  };
>>>>
>>>>  /* periph_id src_bit div_bit prediv_bit */
>>>> -static struct clk_bit_info clk_bit_info[] = {
>>>> +static struct clk_bit_info exynos5_bit_info[] = {
>>>>       {PERIPH_ID_UART0,       0,      0,      -1},
>>>>       {PERIPH_ID_UART1,       4,      4,      -1},
>>>>       {PERIPH_ID_UART2,       8,      8,      -1},
>>>> @@ -61,6 +61,42 @@ static struct clk_bit_info clk_bit_info[] = {
>>>>       {PERIPH_ID_NONE,        -1,     -1,     -1},
>>>>  };
>>>>
>>>> +static struct clk_bit_info exynos542x_bit_info[] = {
>>>> +     {PERIPH_ID_UART0,       4,      8,      -1},
>>>> +     {PERIPH_ID_UART1,       8,      12,     -1},
>>>> +     {PERIPH_ID_UART2,       12,     16,     -1},
>>>> +     {PERIPH_ID_UART3,       16,     20,     -1},
>>>> +     {PERIPH_ID_I2C0,        -1,     8,      -1},
>>>> +     {PERIPH_ID_I2C1,        -1,     8,      -1},
>>>> +     {PERIPH_ID_I2C2,        -1,     8,      -1},
>>>> +     {PERIPH_ID_I2C3,        -1,     8,      -1},
>>>> +     {PERIPH_ID_I2C4,        -1,     8,      -1},
>>>> +     {PERIPH_ID_I2C5,        -1,     8,      -1},
>>>> +     {PERIPH_ID_I2C6,        -1,     8,      -1},
>>>> +     {PERIPH_ID_I2C7,        -1,     8,      -1},
>>>> +     {PERIPH_ID_SPI0,        20,     20,     8},
>>>> +     {PERIPH_ID_SPI1,        24,     24,     16},
>>>> +     {PERIPH_ID_SPI2,        28,     28,     24},
>>>> +     {PERIPH_ID_SDMMC0,      0,      0,      -1},
>>>> +     {PERIPH_ID_SDMMC1,      4,      10,     -1},
>>>> +     {PERIPH_ID_SDMMC2,      8,      20,     -1},
>>>> +     {PERIPH_ID_I2C8,        -1,     8,      -1},
>>>> +     {PERIPH_ID_I2C9,        -1,     8,      -1},
>>>> +     {PERIPH_ID_I2S0,        0,      0,      4},
>>>> +     {PERIPH_ID_I2S1,        4,      12,     16},
>>>> +     {PERIPH_ID_SPI3,        12,     16,     0},
>>>> +     {PERIPH_ID_SPI4,        16,     20,     8},
>>>> +     {PERIPH_ID_SDMMC4,      16,     0,      8},
>>>> +     {PERIPH_ID_PWM0,        24,     28,     -1},
>>>> +     {PERIPH_ID_PWM1,        24,     28,     -1},
>>>> +     {PERIPH_ID_PWM2,        24,     28,     -1},
>>>> +     {PERIPH_ID_PWM3,        24,     28,     -1},
>>>> +     {PERIPH_ID_PWM4,        24,     28,     -1},
>>>> +     {PERIPH_ID_I2C10,       -1,     8,      -1},
>>>> +
>>>> +     {PERIPH_ID_NONE,        -1,     -1,     -1},
>>>> +};
>>>> +
>>>>  /* Epll Clock division values to achive different frequency output */
>>>>  static struct set_epll_con_val exynos5_epll_div[] = {
>>>>       { 192000000, 0, 48, 3, 1, 0 },
>>>> @@ -306,16 +342,22 @@ static unsigned long exynos542x_get_pll_clk(int pllreg)
>>>>  static struct clk_bit_info *get_clk_bit_info(int peripheral)
>>>>  {
>>>>       int i;
>>>> +     struct clk_bit_info *info;
>>>>
>>>> -     for (i = 0; clk_bit_info[i].id != PERIPH_ID_NONE; i++) {
>>>> -             if (clk_bit_info[i].id == peripheral)
>>>> +     if (proid_is_exynos5420() || proid_is_exynos5800())
>>>> +             info = exynos542x_bit_info;
>>>> +     else
>>>> +             info = exynos5_bit_info;
>>>> +
>>>> +     for (i = 0; info[i].id != PERIPH_ID_NONE; i++) {
>>>> +             if (info[i].id == peripheral)
>>>>                       break;
>>>>       }
>>>>
>>>> -     if (clk_bit_info[i].id == PERIPH_ID_NONE)
>>>> +     if (info[i].id == PERIPH_ID_NONE)
>>>>               debug("ERROR: Peripheral ID %d not found\n", peripheral);
>>>>
>>>> -     return &clk_bit_info[i];
>>>> +     return &info[i];
>>>>  }
>>>>
>>>>  static unsigned long exynos5_get_periph_rate(int peripheral)
>>>> @@ -414,12 +456,107 @@ static unsigned long exynos5_get_periph_rate(int peripheral)
>>>>       return sub_clk;
>>>>  }
>>>>
>>>> +static unsigned long exynos542x_get_periph_rate(int peripheral)
>>>> +{
>>>> +     struct clk_bit_info *bit_info = get_clk_bit_info(peripheral);
>>>> +     unsigned long sclk, sub_clk = 0;
>>>> +     unsigned int src, div, sub_div = 0;
>>>> +     struct exynos5420_clock *clk =
>>>> +                     (struct exynos5420_clock *)samsung_get_base_clock();
>>>> +
>>>> +     switch (peripheral) {
>>>> +     case PERIPH_ID_UART0:
>>>> +     case PERIPH_ID_UART1:
>>>> +     case PERIPH_ID_UART2:
>>>> +     case PERIPH_ID_UART3:
>>>> +     case PERIPH_ID_PWM0:
>>>> +     case PERIPH_ID_PWM1:
>>>> +     case PERIPH_ID_PWM2:
>>>> +     case PERIPH_ID_PWM3:
>>>> +     case PERIPH_ID_PWM4:
>>>> +             src = readl(&clk->src_peric0);
>>>> +             div = readl(&clk->div_peric0);
>>>> +             break;
>>>> +     case PERIPH_ID_SPI0:
>>>> +     case PERIPH_ID_SPI1:
>>>> +     case PERIPH_ID_SPI2:
>>>> +             src = readl(&clk->src_peric1);
>>>> +             div = readl(&clk->div_peric1);
>>>> +             sub_div = readl(&clk->div_peric4);
>>>> +             break;
>>>> +     case PERIPH_ID_SPI3:
>>>> +     case PERIPH_ID_SPI4:
>>>> +             src = readl(&clk->src_isp);
>>>> +             div = readl(&clk->div_isp1);
>>>> +             sub_div = readl(&clk->div_isp1);
>>>> +             break;
>>>> +     case PERIPH_ID_SDMMC0:
>>>> +     case PERIPH_ID_SDMMC1:
>>>> +     case PERIPH_ID_SDMMC2:
>>>> +     case PERIPH_ID_SDMMC3:
>>>> +             src = readl(&clk->src_fsys);
>>>> +             div = readl(&clk->div_fsys1);
>>>> +             break;
>>>> +     case PERIPH_ID_I2C0:
>>>> +     case PERIPH_ID_I2C1:
>>>> +     case PERIPH_ID_I2C2:
>>>> +     case PERIPH_ID_I2C3:
>>>> +     case PERIPH_ID_I2C4:
>>>> +     case PERIPH_ID_I2C5:
>>>> +     case PERIPH_ID_I2C6:
>>>> +     case PERIPH_ID_I2C7:
>>>> +     case PERIPH_ID_I2C8:
>>>> +     case PERIPH_ID_I2C9:
>>>> +     case PERIPH_ID_I2C10:
>>>> +             sclk = exynos542x_get_pll_clk(MPLL);
>>>> +             sub_div = ((readl(&clk->div_top1) >> bit_info->div_bit)
>>>> +                                                             & 0x7) + 1;
>>>> +             return sclk / sub_div;
>>>> +     default:
>>>> +             debug("%s: invalid peripheral %d", __func__, peripheral);
>>>> +             return -1;
>>>> +     };
>>>> +
>>>> +     if (bit_info->src_bit >= 0)
>>>> +             src = (src >> bit_info->src_bit) & 0xf;
>>>> +
>>>> +     switch (src) {
>>>> +     case EXYNOS542x_SRC_MPLL:
>>>> +             sclk = exynos542x_get_pll_clk(MPLL);
>>>> +             break;
>>>> +     case EXYNOS542x_SRC_EPLL:
>>>> +             sclk = exynos542x_get_pll_clk(EPLL);
>>>> +             break;
>>>> +     case EXYNOS542x_SRC_RPLL:
>>>> +             sclk = exynos542x_get_pll_clk(RPLL);
>>>> +             break;
>>>> +     default:
>>>> +             return 0;
>>>> +     }
>>>> +
>>>
>>> Odroid xu3 board uses SPLL as source clock for SDMMCx, please SPLL case.
>>
>> Perhaps this can be sorted out by the maintainer of that board? I'm
>> not sure how we can deal with this other than a special case.
>> Certainly Akshay is not going to know what to do here.
>>
>
> I don't think this is special case, SPLL also can be used as source
> clock like MPLL, EPLL and RPLL.
>
>>>
>>>> +     /* Ratio clock division for this peripheral */
>>>> +     if (bit_info->div_bit >= 0) {
>>>> +             div = (div >> bit_info->div_bit) & 0xf;
>>>
>>> Hmm, mask bits are different each peripheral, e.g. SDMMCx needs 0x3ff
>>> mask bits.
>>>
>
> Akshay, could you follow up this?

Can you please issue a Reviewed-by/Tested-by for those patches you are
happy with?

I saw a flurry of comments but I'm not sure if you are now happy with
them or not.

Regards,
Simon
Joonyoung Shim Jan. 28, 2015, 5:12 a.m. UTC | #5
Hi Simon,

On 01/28/2015 02:01 PM, Simon Glass wrote:
> Hi Joonyoung,
> 
> On 27 January 2015 at 21:46, Joonyoung Shim <jy0922.shim@samsung.com> wrote:
>> Hi Simon,
>>
>> On 01/28/2015 01:09 PM, Simon Glass wrote:
>>> Hi,
>>>
>>> On 15 January 2015 at 23:09, Joonyoung Shim <jy0922.shim@samsung.com> wrote:
>>>> Hi,
>>>>
>>>> On 01/16/2015 02:48 PM, Akshay Saraswat wrote:
>>>>> We planned to fetch peripheral rate through one generic API per
>>>>> peripheral. These generic peripheral functions are in turn
>>>>> expected to fetch apt values from a function refactored as
>>>>> per SoC versions. This patch adds support for fetching peripheral
>>>>> rates for Exynos5420 and Exynos5800.
>>>>>
>>>>> Signed-off-by: Akshay Saraswat <akshay.s@samsung.com>
>>>>> ---
>>>>> Changes since v2:
>>>>>       - Fixed enum and exynos542x_get_periph_rate switch.
>>>>>       - Added checks for negative values in exynos542x_get_periph_rate.
>>>>>
>>>>> Changes since v1:
>>>>>       - Changes suuport -> support in commit message.
>>>>>       - Removed position change of exynos5420_get_pll_clk.
>>>>>       - Removed #ifdef.
>>>>>
>>>>>  arch/arm/cpu/armv7/exynos/clock.c      | 151 +++++++++++++++++++++++++++++++--
>>>>>  arch/arm/include/asm/arch-exynos/clk.h |   3 +
>>>>>  2 files changed, 147 insertions(+), 7 deletions(-)
>>>
>>> What else needs to be done to get this applied, please?
>>>
>>
>> As i said, current this patch has some problem like mask bits, so eMMC
>> doesn't work normally.
>>
>>>>>
>>>>> diff --git a/arch/arm/cpu/armv7/exynos/clock.c b/arch/arm/cpu/armv7/exynos/clock.c
>>>>> index 5dc9ed2..ee6c13b 100644
>>>>> --- a/arch/arm/cpu/armv7/exynos/clock.c
>>>>> +++ b/arch/arm/cpu/armv7/exynos/clock.c
>>>>> @@ -27,7 +27,7 @@ struct clk_bit_info {
>>>>>  };
>>>>>
>>>>>  /* periph_id src_bit div_bit prediv_bit */
>>>>> -static struct clk_bit_info clk_bit_info[] = {
>>>>> +static struct clk_bit_info exynos5_bit_info[] = {
>>>>>       {PERIPH_ID_UART0,       0,      0,      -1},
>>>>>       {PERIPH_ID_UART1,       4,      4,      -1},
>>>>>       {PERIPH_ID_UART2,       8,      8,      -1},
>>>>> @@ -61,6 +61,42 @@ static struct clk_bit_info clk_bit_info[] = {
>>>>>       {PERIPH_ID_NONE,        -1,     -1,     -1},
>>>>>  };
>>>>>
>>>>> +static struct clk_bit_info exynos542x_bit_info[] = {
>>>>> +     {PERIPH_ID_UART0,       4,      8,      -1},
>>>>> +     {PERIPH_ID_UART1,       8,      12,     -1},
>>>>> +     {PERIPH_ID_UART2,       12,     16,     -1},
>>>>> +     {PERIPH_ID_UART3,       16,     20,     -1},
>>>>> +     {PERIPH_ID_I2C0,        -1,     8,      -1},
>>>>> +     {PERIPH_ID_I2C1,        -1,     8,      -1},
>>>>> +     {PERIPH_ID_I2C2,        -1,     8,      -1},
>>>>> +     {PERIPH_ID_I2C3,        -1,     8,      -1},
>>>>> +     {PERIPH_ID_I2C4,        -1,     8,      -1},
>>>>> +     {PERIPH_ID_I2C5,        -1,     8,      -1},
>>>>> +     {PERIPH_ID_I2C6,        -1,     8,      -1},
>>>>> +     {PERIPH_ID_I2C7,        -1,     8,      -1},
>>>>> +     {PERIPH_ID_SPI0,        20,     20,     8},
>>>>> +     {PERIPH_ID_SPI1,        24,     24,     16},
>>>>> +     {PERIPH_ID_SPI2,        28,     28,     24},
>>>>> +     {PERIPH_ID_SDMMC0,      0,      0,      -1},
>>>>> +     {PERIPH_ID_SDMMC1,      4,      10,     -1},
>>>>> +     {PERIPH_ID_SDMMC2,      8,      20,     -1},
>>>>> +     {PERIPH_ID_I2C8,        -1,     8,      -1},
>>>>> +     {PERIPH_ID_I2C9,        -1,     8,      -1},
>>>>> +     {PERIPH_ID_I2S0,        0,      0,      4},
>>>>> +     {PERIPH_ID_I2S1,        4,      12,     16},
>>>>> +     {PERIPH_ID_SPI3,        12,     16,     0},
>>>>> +     {PERIPH_ID_SPI4,        16,     20,     8},
>>>>> +     {PERIPH_ID_SDMMC4,      16,     0,      8},
>>>>> +     {PERIPH_ID_PWM0,        24,     28,     -1},
>>>>> +     {PERIPH_ID_PWM1,        24,     28,     -1},
>>>>> +     {PERIPH_ID_PWM2,        24,     28,     -1},
>>>>> +     {PERIPH_ID_PWM3,        24,     28,     -1},
>>>>> +     {PERIPH_ID_PWM4,        24,     28,     -1},
>>>>> +     {PERIPH_ID_I2C10,       -1,     8,      -1},
>>>>> +
>>>>> +     {PERIPH_ID_NONE,        -1,     -1,     -1},
>>>>> +};
>>>>> +
>>>>>  /* Epll Clock division values to achive different frequency output */
>>>>>  static struct set_epll_con_val exynos5_epll_div[] = {
>>>>>       { 192000000, 0, 48, 3, 1, 0 },
>>>>> @@ -306,16 +342,22 @@ static unsigned long exynos542x_get_pll_clk(int pllreg)
>>>>>  static struct clk_bit_info *get_clk_bit_info(int peripheral)
>>>>>  {
>>>>>       int i;
>>>>> +     struct clk_bit_info *info;
>>>>>
>>>>> -     for (i = 0; clk_bit_info[i].id != PERIPH_ID_NONE; i++) {
>>>>> -             if (clk_bit_info[i].id == peripheral)
>>>>> +     if (proid_is_exynos5420() || proid_is_exynos5800())
>>>>> +             info = exynos542x_bit_info;
>>>>> +     else
>>>>> +             info = exynos5_bit_info;
>>>>> +
>>>>> +     for (i = 0; info[i].id != PERIPH_ID_NONE; i++) {
>>>>> +             if (info[i].id == peripheral)
>>>>>                       break;
>>>>>       }
>>>>>
>>>>> -     if (clk_bit_info[i].id == PERIPH_ID_NONE)
>>>>> +     if (info[i].id == PERIPH_ID_NONE)
>>>>>               debug("ERROR: Peripheral ID %d not found\n", peripheral);
>>>>>
>>>>> -     return &clk_bit_info[i];
>>>>> +     return &info[i];
>>>>>  }
>>>>>
>>>>>  static unsigned long exynos5_get_periph_rate(int peripheral)
>>>>> @@ -414,12 +456,107 @@ static unsigned long exynos5_get_periph_rate(int peripheral)
>>>>>       return sub_clk;
>>>>>  }
>>>>>
>>>>> +static unsigned long exynos542x_get_periph_rate(int peripheral)
>>>>> +{
>>>>> +     struct clk_bit_info *bit_info = get_clk_bit_info(peripheral);
>>>>> +     unsigned long sclk, sub_clk = 0;
>>>>> +     unsigned int src, div, sub_div = 0;
>>>>> +     struct exynos5420_clock *clk =
>>>>> +                     (struct exynos5420_clock *)samsung_get_base_clock();
>>>>> +
>>>>> +     switch (peripheral) {
>>>>> +     case PERIPH_ID_UART0:
>>>>> +     case PERIPH_ID_UART1:
>>>>> +     case PERIPH_ID_UART2:
>>>>> +     case PERIPH_ID_UART3:
>>>>> +     case PERIPH_ID_PWM0:
>>>>> +     case PERIPH_ID_PWM1:
>>>>> +     case PERIPH_ID_PWM2:
>>>>> +     case PERIPH_ID_PWM3:
>>>>> +     case PERIPH_ID_PWM4:
>>>>> +             src = readl(&clk->src_peric0);
>>>>> +             div = readl(&clk->div_peric0);
>>>>> +             break;
>>>>> +     case PERIPH_ID_SPI0:
>>>>> +     case PERIPH_ID_SPI1:
>>>>> +     case PERIPH_ID_SPI2:
>>>>> +             src = readl(&clk->src_peric1);
>>>>> +             div = readl(&clk->div_peric1);
>>>>> +             sub_div = readl(&clk->div_peric4);
>>>>> +             break;
>>>>> +     case PERIPH_ID_SPI3:
>>>>> +     case PERIPH_ID_SPI4:
>>>>> +             src = readl(&clk->src_isp);
>>>>> +             div = readl(&clk->div_isp1);
>>>>> +             sub_div = readl(&clk->div_isp1);
>>>>> +             break;
>>>>> +     case PERIPH_ID_SDMMC0:
>>>>> +     case PERIPH_ID_SDMMC1:
>>>>> +     case PERIPH_ID_SDMMC2:
>>>>> +     case PERIPH_ID_SDMMC3:
>>>>> +             src = readl(&clk->src_fsys);
>>>>> +             div = readl(&clk->div_fsys1);
>>>>> +             break;
>>>>> +     case PERIPH_ID_I2C0:
>>>>> +     case PERIPH_ID_I2C1:
>>>>> +     case PERIPH_ID_I2C2:
>>>>> +     case PERIPH_ID_I2C3:
>>>>> +     case PERIPH_ID_I2C4:
>>>>> +     case PERIPH_ID_I2C5:
>>>>> +     case PERIPH_ID_I2C6:
>>>>> +     case PERIPH_ID_I2C7:
>>>>> +     case PERIPH_ID_I2C8:
>>>>> +     case PERIPH_ID_I2C9:
>>>>> +     case PERIPH_ID_I2C10:
>>>>> +             sclk = exynos542x_get_pll_clk(MPLL);
>>>>> +             sub_div = ((readl(&clk->div_top1) >> bit_info->div_bit)
>>>>> +                                                             & 0x7) + 1;
>>>>> +             return sclk / sub_div;
>>>>> +     default:
>>>>> +             debug("%s: invalid peripheral %d", __func__, peripheral);
>>>>> +             return -1;
>>>>> +     };
>>>>> +
>>>>> +     if (bit_info->src_bit >= 0)
>>>>> +             src = (src >> bit_info->src_bit) & 0xf;
>>>>> +
>>>>> +     switch (src) {
>>>>> +     case EXYNOS542x_SRC_MPLL:
>>>>> +             sclk = exynos542x_get_pll_clk(MPLL);
>>>>> +             break;
>>>>> +     case EXYNOS542x_SRC_EPLL:
>>>>> +             sclk = exynos542x_get_pll_clk(EPLL);
>>>>> +             break;
>>>>> +     case EXYNOS542x_SRC_RPLL:
>>>>> +             sclk = exynos542x_get_pll_clk(RPLL);
>>>>> +             break;
>>>>> +     default:
>>>>> +             return 0;
>>>>> +     }
>>>>> +
>>>>
>>>> Odroid xu3 board uses SPLL as source clock for SDMMCx, please SPLL case.
>>>
>>> Perhaps this can be sorted out by the maintainer of that board? I'm
>>> not sure how we can deal with this other than a special case.
>>> Certainly Akshay is not going to know what to do here.
>>>
>>
>> I don't think this is special case, SPLL also can be used as source
>> clock like MPLL, EPLL and RPLL.
>>
>>>>
>>>>> +     /* Ratio clock division for this peripheral */
>>>>> +     if (bit_info->div_bit >= 0) {
>>>>> +             div = (div >> bit_info->div_bit) & 0xf;
>>>>
>>>> Hmm, mask bits are different each peripheral, e.g. SDMMCx needs 0x3ff
>>>> mask bits.
>>>>
>>
>> Akshay, could you follow up this?
> 
> Can you please issue a Reviewed-by/Tested-by for those patches you are
> happy with?
> 

Sure, i will reply Reviewed-by or Tested-by if he solves issues.

Thanks.

> I saw a flurry of comments but I'm not sure if you are now happy with
> them or not.
> 
> Regards,
> Simon
>
Simon Glass Jan. 28, 2015, 5:15 a.m. UTC | #6
Hi Joonyoung,

On 27 January 2015 at 22:12, Joonyoung Shim <jy0922.shim@samsung.com> wrote:
> Hi Simon,
>
> On 01/28/2015 02:01 PM, Simon Glass wrote:
>> Hi Joonyoung,
>>
>> On 27 January 2015 at 21:46, Joonyoung Shim <jy0922.shim@samsung.com> wrote:
>>> Hi Simon,
>>>
>>> On 01/28/2015 01:09 PM, Simon Glass wrote:
>>>> Hi,
>>>>
>>>> On 15 January 2015 at 23:09, Joonyoung Shim <jy0922.shim@samsung.com> wrote:
>>>>> Hi,
>>>>>
>>>>> On 01/16/2015 02:48 PM, Akshay Saraswat wrote:
>>>>>> We planned to fetch peripheral rate through one generic API per
>>>>>> peripheral. These generic peripheral functions are in turn
>>>>>> expected to fetch apt values from a function refactored as
>>>>>> per SoC versions. This patch adds support for fetching peripheral
>>>>>> rates for Exynos5420 and Exynos5800.
>>>>>>
>>>>>> Signed-off-by: Akshay Saraswat <akshay.s@samsung.com>
>>>>>> ---
>>>>>> Changes since v2:
>>>>>>       - Fixed enum and exynos542x_get_periph_rate switch.
>>>>>>       - Added checks for negative values in exynos542x_get_periph_rate.
>>>>>>
>>>>>> Changes since v1:
>>>>>>       - Changes suuport -> support in commit message.
>>>>>>       - Removed position change of exynos5420_get_pll_clk.
>>>>>>       - Removed #ifdef.
>>>>>>
>>>>>>  arch/arm/cpu/armv7/exynos/clock.c      | 151 +++++++++++++++++++++++++++++++--
>>>>>>  arch/arm/include/asm/arch-exynos/clk.h |   3 +
>>>>>>  2 files changed, 147 insertions(+), 7 deletions(-)
>>>>
>>>> What else needs to be done to get this applied, please?
>>>>
>>>
>>> As i said, current this patch has some problem like mask bits, so eMMC
>>> doesn't work normally.
>>>
>>>>>>
>>>>>> diff --git a/arch/arm/cpu/armv7/exynos/clock.c b/arch/arm/cpu/armv7/exynos/clock.c
>>>>>> index 5dc9ed2..ee6c13b 100644
>>>>>> --- a/arch/arm/cpu/armv7/exynos/clock.c
>>>>>> +++ b/arch/arm/cpu/armv7/exynos/clock.c
>>>>>> @@ -27,7 +27,7 @@ struct clk_bit_info {
>>>>>>  };
>>>>>>
>>>>>>  /* periph_id src_bit div_bit prediv_bit */
>>>>>> -static struct clk_bit_info clk_bit_info[] = {
>>>>>> +static struct clk_bit_info exynos5_bit_info[] = {
>>>>>>       {PERIPH_ID_UART0,       0,      0,      -1},
>>>>>>       {PERIPH_ID_UART1,       4,      4,      -1},
>>>>>>       {PERIPH_ID_UART2,       8,      8,      -1},
>>>>>> @@ -61,6 +61,42 @@ static struct clk_bit_info clk_bit_info[] = {
>>>>>>       {PERIPH_ID_NONE,        -1,     -1,     -1},
>>>>>>  };
>>>>>>
>>>>>> +static struct clk_bit_info exynos542x_bit_info[] = {
>>>>>> +     {PERIPH_ID_UART0,       4,      8,      -1},
>>>>>> +     {PERIPH_ID_UART1,       8,      12,     -1},
>>>>>> +     {PERIPH_ID_UART2,       12,     16,     -1},
>>>>>> +     {PERIPH_ID_UART3,       16,     20,     -1},
>>>>>> +     {PERIPH_ID_I2C0,        -1,     8,      -1},
>>>>>> +     {PERIPH_ID_I2C1,        -1,     8,      -1},
>>>>>> +     {PERIPH_ID_I2C2,        -1,     8,      -1},
>>>>>> +     {PERIPH_ID_I2C3,        -1,     8,      -1},
>>>>>> +     {PERIPH_ID_I2C4,        -1,     8,      -1},
>>>>>> +     {PERIPH_ID_I2C5,        -1,     8,      -1},
>>>>>> +     {PERIPH_ID_I2C6,        -1,     8,      -1},
>>>>>> +     {PERIPH_ID_I2C7,        -1,     8,      -1},
>>>>>> +     {PERIPH_ID_SPI0,        20,     20,     8},
>>>>>> +     {PERIPH_ID_SPI1,        24,     24,     16},
>>>>>> +     {PERIPH_ID_SPI2,        28,     28,     24},
>>>>>> +     {PERIPH_ID_SDMMC0,      0,      0,      -1},
>>>>>> +     {PERIPH_ID_SDMMC1,      4,      10,     -1},
>>>>>> +     {PERIPH_ID_SDMMC2,      8,      20,     -1},
>>>>>> +     {PERIPH_ID_I2C8,        -1,     8,      -1},
>>>>>> +     {PERIPH_ID_I2C9,        -1,     8,      -1},
>>>>>> +     {PERIPH_ID_I2S0,        0,      0,      4},
>>>>>> +     {PERIPH_ID_I2S1,        4,      12,     16},
>>>>>> +     {PERIPH_ID_SPI3,        12,     16,     0},
>>>>>> +     {PERIPH_ID_SPI4,        16,     20,     8},
>>>>>> +     {PERIPH_ID_SDMMC4,      16,     0,      8},
>>>>>> +     {PERIPH_ID_PWM0,        24,     28,     -1},
>>>>>> +     {PERIPH_ID_PWM1,        24,     28,     -1},
>>>>>> +     {PERIPH_ID_PWM2,        24,     28,     -1},
>>>>>> +     {PERIPH_ID_PWM3,        24,     28,     -1},
>>>>>> +     {PERIPH_ID_PWM4,        24,     28,     -1},
>>>>>> +     {PERIPH_ID_I2C10,       -1,     8,      -1},
>>>>>> +
>>>>>> +     {PERIPH_ID_NONE,        -1,     -1,     -1},
>>>>>> +};
>>>>>> +
>>>>>>  /* Epll Clock division values to achive different frequency output */
>>>>>>  static struct set_epll_con_val exynos5_epll_div[] = {
>>>>>>       { 192000000, 0, 48, 3, 1, 0 },
>>>>>> @@ -306,16 +342,22 @@ static unsigned long exynos542x_get_pll_clk(int pllreg)
>>>>>>  static struct clk_bit_info *get_clk_bit_info(int peripheral)
>>>>>>  {
>>>>>>       int i;
>>>>>> +     struct clk_bit_info *info;
>>>>>>
>>>>>> -     for (i = 0; clk_bit_info[i].id != PERIPH_ID_NONE; i++) {
>>>>>> -             if (clk_bit_info[i].id == peripheral)
>>>>>> +     if (proid_is_exynos5420() || proid_is_exynos5800())
>>>>>> +             info = exynos542x_bit_info;
>>>>>> +     else
>>>>>> +             info = exynos5_bit_info;
>>>>>> +
>>>>>> +     for (i = 0; info[i].id != PERIPH_ID_NONE; i++) {
>>>>>> +             if (info[i].id == peripheral)
>>>>>>                       break;
>>>>>>       }
>>>>>>
>>>>>> -     if (clk_bit_info[i].id == PERIPH_ID_NONE)
>>>>>> +     if (info[i].id == PERIPH_ID_NONE)
>>>>>>               debug("ERROR: Peripheral ID %d not found\n", peripheral);
>>>>>>
>>>>>> -     return &clk_bit_info[i];
>>>>>> +     return &info[i];
>>>>>>  }
>>>>>>
>>>>>>  static unsigned long exynos5_get_periph_rate(int peripheral)
>>>>>> @@ -414,12 +456,107 @@ static unsigned long exynos5_get_periph_rate(int peripheral)
>>>>>>       return sub_clk;
>>>>>>  }
>>>>>>
>>>>>> +static unsigned long exynos542x_get_periph_rate(int peripheral)
>>>>>> +{
>>>>>> +     struct clk_bit_info *bit_info = get_clk_bit_info(peripheral);
>>>>>> +     unsigned long sclk, sub_clk = 0;
>>>>>> +     unsigned int src, div, sub_div = 0;
>>>>>> +     struct exynos5420_clock *clk =
>>>>>> +                     (struct exynos5420_clock *)samsung_get_base_clock();
>>>>>> +
>>>>>> +     switch (peripheral) {
>>>>>> +     case PERIPH_ID_UART0:
>>>>>> +     case PERIPH_ID_UART1:
>>>>>> +     case PERIPH_ID_UART2:
>>>>>> +     case PERIPH_ID_UART3:
>>>>>> +     case PERIPH_ID_PWM0:
>>>>>> +     case PERIPH_ID_PWM1:
>>>>>> +     case PERIPH_ID_PWM2:
>>>>>> +     case PERIPH_ID_PWM3:
>>>>>> +     case PERIPH_ID_PWM4:
>>>>>> +             src = readl(&clk->src_peric0);
>>>>>> +             div = readl(&clk->div_peric0);
>>>>>> +             break;
>>>>>> +     case PERIPH_ID_SPI0:
>>>>>> +     case PERIPH_ID_SPI1:
>>>>>> +     case PERIPH_ID_SPI2:
>>>>>> +             src = readl(&clk->src_peric1);
>>>>>> +             div = readl(&clk->div_peric1);
>>>>>> +             sub_div = readl(&clk->div_peric4);
>>>>>> +             break;
>>>>>> +     case PERIPH_ID_SPI3:
>>>>>> +     case PERIPH_ID_SPI4:
>>>>>> +             src = readl(&clk->src_isp);
>>>>>> +             div = readl(&clk->div_isp1);
>>>>>> +             sub_div = readl(&clk->div_isp1);
>>>>>> +             break;
>>>>>> +     case PERIPH_ID_SDMMC0:
>>>>>> +     case PERIPH_ID_SDMMC1:
>>>>>> +     case PERIPH_ID_SDMMC2:
>>>>>> +     case PERIPH_ID_SDMMC3:
>>>>>> +             src = readl(&clk->src_fsys);
>>>>>> +             div = readl(&clk->div_fsys1);
>>>>>> +             break;
>>>>>> +     case PERIPH_ID_I2C0:
>>>>>> +     case PERIPH_ID_I2C1:
>>>>>> +     case PERIPH_ID_I2C2:
>>>>>> +     case PERIPH_ID_I2C3:
>>>>>> +     case PERIPH_ID_I2C4:
>>>>>> +     case PERIPH_ID_I2C5:
>>>>>> +     case PERIPH_ID_I2C6:
>>>>>> +     case PERIPH_ID_I2C7:
>>>>>> +     case PERIPH_ID_I2C8:
>>>>>> +     case PERIPH_ID_I2C9:
>>>>>> +     case PERIPH_ID_I2C10:
>>>>>> +             sclk = exynos542x_get_pll_clk(MPLL);
>>>>>> +             sub_div = ((readl(&clk->div_top1) >> bit_info->div_bit)
>>>>>> +                                                             & 0x7) + 1;
>>>>>> +             return sclk / sub_div;
>>>>>> +     default:
>>>>>> +             debug("%s: invalid peripheral %d", __func__, peripheral);
>>>>>> +             return -1;
>>>>>> +     };
>>>>>> +
>>>>>> +     if (bit_info->src_bit >= 0)
>>>>>> +             src = (src >> bit_info->src_bit) & 0xf;
>>>>>> +
>>>>>> +     switch (src) {
>>>>>> +     case EXYNOS542x_SRC_MPLL:
>>>>>> +             sclk = exynos542x_get_pll_clk(MPLL);
>>>>>> +             break;
>>>>>> +     case EXYNOS542x_SRC_EPLL:
>>>>>> +             sclk = exynos542x_get_pll_clk(EPLL);
>>>>>> +             break;
>>>>>> +     case EXYNOS542x_SRC_RPLL:
>>>>>> +             sclk = exynos542x_get_pll_clk(RPLL);
>>>>>> +             break;
>>>>>> +     default:
>>>>>> +             return 0;
>>>>>> +     }
>>>>>> +
>>>>>
>>>>> Odroid xu3 board uses SPLL as source clock for SDMMCx, please SPLL case.
>>>>
>>>> Perhaps this can be sorted out by the maintainer of that board? I'm
>>>> not sure how we can deal with this other than a special case.
>>>> Certainly Akshay is not going to know what to do here.
>>>>
>>>
>>> I don't think this is special case, SPLL also can be used as source
>>> clock like MPLL, EPLL and RPLL.
>>>
>>>>>
>>>>>> +     /* Ratio clock division for this peripheral */
>>>>>> +     if (bit_info->div_bit >= 0) {
>>>>>> +             div = (div >> bit_info->div_bit) & 0xf;
>>>>>
>>>>> Hmm, mask bits are different each peripheral, e.g. SDMMCx needs 0x3ff
>>>>> mask bits.
>>>>>
>>>
>>> Akshay, could you follow up this?
>>
>> Can you please issue a Reviewed-by/Tested-by for those patches you are
>> happy with?
>>
>
> Sure, i will reply Reviewed-by or Tested-by if he solves issues.

OK, so are any of the patches OK now? Basically I'm not sure if you
have more comments. It looks like 3-4 of them are OK, but I'm not
sure.

Regards,
Simon
Joonyoung Shim Jan. 28, 2015, 5:55 a.m. UTC | #7
Hi Simon,

On 01/28/2015 02:15 PM, Simon Glass wrote:
> Hi Joonyoung,
> 
> On 27 January 2015 at 22:12, Joonyoung Shim <jy0922.shim@samsung.com> wrote:
>> Hi Simon,
>>
>> On 01/28/2015 02:01 PM, Simon Glass wrote:
>>> Hi Joonyoung,
>>>
>>> On 27 January 2015 at 21:46, Joonyoung Shim <jy0922.shim@samsung.com> wrote:
>>>> Hi Simon,
>>>>
>>>> On 01/28/2015 01:09 PM, Simon Glass wrote:
>>>>> Hi,
>>>>>
>>>>> On 15 January 2015 at 23:09, Joonyoung Shim <jy0922.shim@samsung.com> wrote:
>>>>>> Hi,
>>>>>>
>>>>>> On 01/16/2015 02:48 PM, Akshay Saraswat wrote:
>>>>>>> We planned to fetch peripheral rate through one generic API per
>>>>>>> peripheral. These generic peripheral functions are in turn
>>>>>>> expected to fetch apt values from a function refactored as
>>>>>>> per SoC versions. This patch adds support for fetching peripheral
>>>>>>> rates for Exynos5420 and Exynos5800.
>>>>>>>
>>>>>>> Signed-off-by: Akshay Saraswat <akshay.s@samsung.com>
>>>>>>> ---
>>>>>>> Changes since v2:
>>>>>>>       - Fixed enum and exynos542x_get_periph_rate switch.
>>>>>>>       - Added checks for negative values in exynos542x_get_periph_rate.
>>>>>>>
>>>>>>> Changes since v1:
>>>>>>>       - Changes suuport -> support in commit message.
>>>>>>>       - Removed position change of exynos5420_get_pll_clk.
>>>>>>>       - Removed #ifdef.
>>>>>>>
>>>>>>>  arch/arm/cpu/armv7/exynos/clock.c      | 151 +++++++++++++++++++++++++++++++--
>>>>>>>  arch/arm/include/asm/arch-exynos/clk.h |   3 +
>>>>>>>  2 files changed, 147 insertions(+), 7 deletions(-)
>>>>>
>>>>> What else needs to be done to get this applied, please?
>>>>>
>>>>
>>>> As i said, current this patch has some problem like mask bits, so eMMC
>>>> doesn't work normally.
>>>>
>>>>>>>
>>>>>>> diff --git a/arch/arm/cpu/armv7/exynos/clock.c b/arch/arm/cpu/armv7/exynos/clock.c
>>>>>>> index 5dc9ed2..ee6c13b 100644
>>>>>>> --- a/arch/arm/cpu/armv7/exynos/clock.c
>>>>>>> +++ b/arch/arm/cpu/armv7/exynos/clock.c
>>>>>>> @@ -27,7 +27,7 @@ struct clk_bit_info {
>>>>>>>  };
>>>>>>>
>>>>>>>  /* periph_id src_bit div_bit prediv_bit */
>>>>>>> -static struct clk_bit_info clk_bit_info[] = {
>>>>>>> +static struct clk_bit_info exynos5_bit_info[] = {
>>>>>>>       {PERIPH_ID_UART0,       0,      0,      -1},
>>>>>>>       {PERIPH_ID_UART1,       4,      4,      -1},
>>>>>>>       {PERIPH_ID_UART2,       8,      8,      -1},
>>>>>>> @@ -61,6 +61,42 @@ static struct clk_bit_info clk_bit_info[] = {
>>>>>>>       {PERIPH_ID_NONE,        -1,     -1,     -1},
>>>>>>>  };
>>>>>>>
>>>>>>> +static struct clk_bit_info exynos542x_bit_info[] = {
>>>>>>> +     {PERIPH_ID_UART0,       4,      8,      -1},
>>>>>>> +     {PERIPH_ID_UART1,       8,      12,     -1},
>>>>>>> +     {PERIPH_ID_UART2,       12,     16,     -1},
>>>>>>> +     {PERIPH_ID_UART3,       16,     20,     -1},
>>>>>>> +     {PERIPH_ID_I2C0,        -1,     8,      -1},
>>>>>>> +     {PERIPH_ID_I2C1,        -1,     8,      -1},
>>>>>>> +     {PERIPH_ID_I2C2,        -1,     8,      -1},
>>>>>>> +     {PERIPH_ID_I2C3,        -1,     8,      -1},
>>>>>>> +     {PERIPH_ID_I2C4,        -1,     8,      -1},
>>>>>>> +     {PERIPH_ID_I2C5,        -1,     8,      -1},
>>>>>>> +     {PERIPH_ID_I2C6,        -1,     8,      -1},
>>>>>>> +     {PERIPH_ID_I2C7,        -1,     8,      -1},
>>>>>>> +     {PERIPH_ID_SPI0,        20,     20,     8},
>>>>>>> +     {PERIPH_ID_SPI1,        24,     24,     16},
>>>>>>> +     {PERIPH_ID_SPI2,        28,     28,     24},
>>>>>>> +     {PERIPH_ID_SDMMC0,      0,      0,      -1},
>>>>>>> +     {PERIPH_ID_SDMMC1,      4,      10,     -1},
>>>>>>> +     {PERIPH_ID_SDMMC2,      8,      20,     -1},
>>>>>>> +     {PERIPH_ID_I2C8,        -1,     8,      -1},
>>>>>>> +     {PERIPH_ID_I2C9,        -1,     8,      -1},
>>>>>>> +     {PERIPH_ID_I2S0,        0,      0,      4},
>>>>>>> +     {PERIPH_ID_I2S1,        4,      12,     16},
>>>>>>> +     {PERIPH_ID_SPI3,        12,     16,     0},
>>>>>>> +     {PERIPH_ID_SPI4,        16,     20,     8},
>>>>>>> +     {PERIPH_ID_SDMMC4,      16,     0,      8},
>>>>>>> +     {PERIPH_ID_PWM0,        24,     28,     -1},
>>>>>>> +     {PERIPH_ID_PWM1,        24,     28,     -1},
>>>>>>> +     {PERIPH_ID_PWM2,        24,     28,     -1},
>>>>>>> +     {PERIPH_ID_PWM3,        24,     28,     -1},
>>>>>>> +     {PERIPH_ID_PWM4,        24,     28,     -1},
>>>>>>> +     {PERIPH_ID_I2C10,       -1,     8,      -1},
>>>>>>> +
>>>>>>> +     {PERIPH_ID_NONE,        -1,     -1,     -1},
>>>>>>> +};
>>>>>>> +
>>>>>>>  /* Epll Clock division values to achive different frequency output */
>>>>>>>  static struct set_epll_con_val exynos5_epll_div[] = {
>>>>>>>       { 192000000, 0, 48, 3, 1, 0 },
>>>>>>> @@ -306,16 +342,22 @@ static unsigned long exynos542x_get_pll_clk(int pllreg)
>>>>>>>  static struct clk_bit_info *get_clk_bit_info(int peripheral)
>>>>>>>  {
>>>>>>>       int i;
>>>>>>> +     struct clk_bit_info *info;
>>>>>>>
>>>>>>> -     for (i = 0; clk_bit_info[i].id != PERIPH_ID_NONE; i++) {
>>>>>>> -             if (clk_bit_info[i].id == peripheral)
>>>>>>> +     if (proid_is_exynos5420() || proid_is_exynos5800())
>>>>>>> +             info = exynos542x_bit_info;
>>>>>>> +     else
>>>>>>> +             info = exynos5_bit_info;
>>>>>>> +
>>>>>>> +     for (i = 0; info[i].id != PERIPH_ID_NONE; i++) {
>>>>>>> +             if (info[i].id == peripheral)
>>>>>>>                       break;
>>>>>>>       }
>>>>>>>
>>>>>>> -     if (clk_bit_info[i].id == PERIPH_ID_NONE)
>>>>>>> +     if (info[i].id == PERIPH_ID_NONE)
>>>>>>>               debug("ERROR: Peripheral ID %d not found\n", peripheral);
>>>>>>>
>>>>>>> -     return &clk_bit_info[i];
>>>>>>> +     return &info[i];
>>>>>>>  }
>>>>>>>
>>>>>>>  static unsigned long exynos5_get_periph_rate(int peripheral)
>>>>>>> @@ -414,12 +456,107 @@ static unsigned long exynos5_get_periph_rate(int peripheral)
>>>>>>>       return sub_clk;
>>>>>>>  }
>>>>>>>
>>>>>>> +static unsigned long exynos542x_get_periph_rate(int peripheral)
>>>>>>> +{
>>>>>>> +     struct clk_bit_info *bit_info = get_clk_bit_info(peripheral);
>>>>>>> +     unsigned long sclk, sub_clk = 0;
>>>>>>> +     unsigned int src, div, sub_div = 0;
>>>>>>> +     struct exynos5420_clock *clk =
>>>>>>> +                     (struct exynos5420_clock *)samsung_get_base_clock();
>>>>>>> +
>>>>>>> +     switch (peripheral) {
>>>>>>> +     case PERIPH_ID_UART0:
>>>>>>> +     case PERIPH_ID_UART1:
>>>>>>> +     case PERIPH_ID_UART2:
>>>>>>> +     case PERIPH_ID_UART3:
>>>>>>> +     case PERIPH_ID_PWM0:
>>>>>>> +     case PERIPH_ID_PWM1:
>>>>>>> +     case PERIPH_ID_PWM2:
>>>>>>> +     case PERIPH_ID_PWM3:
>>>>>>> +     case PERIPH_ID_PWM4:
>>>>>>> +             src = readl(&clk->src_peric0);
>>>>>>> +             div = readl(&clk->div_peric0);
>>>>>>> +             break;
>>>>>>> +     case PERIPH_ID_SPI0:
>>>>>>> +     case PERIPH_ID_SPI1:
>>>>>>> +     case PERIPH_ID_SPI2:
>>>>>>> +             src = readl(&clk->src_peric1);
>>>>>>> +             div = readl(&clk->div_peric1);
>>>>>>> +             sub_div = readl(&clk->div_peric4);
>>>>>>> +             break;
>>>>>>> +     case PERIPH_ID_SPI3:
>>>>>>> +     case PERIPH_ID_SPI4:
>>>>>>> +             src = readl(&clk->src_isp);
>>>>>>> +             div = readl(&clk->div_isp1);
>>>>>>> +             sub_div = readl(&clk->div_isp1);
>>>>>>> +             break;
>>>>>>> +     case PERIPH_ID_SDMMC0:
>>>>>>> +     case PERIPH_ID_SDMMC1:
>>>>>>> +     case PERIPH_ID_SDMMC2:
>>>>>>> +     case PERIPH_ID_SDMMC3:
>>>>>>> +             src = readl(&clk->src_fsys);
>>>>>>> +             div = readl(&clk->div_fsys1);
>>>>>>> +             break;
>>>>>>> +     case PERIPH_ID_I2C0:
>>>>>>> +     case PERIPH_ID_I2C1:
>>>>>>> +     case PERIPH_ID_I2C2:
>>>>>>> +     case PERIPH_ID_I2C3:
>>>>>>> +     case PERIPH_ID_I2C4:
>>>>>>> +     case PERIPH_ID_I2C5:
>>>>>>> +     case PERIPH_ID_I2C6:
>>>>>>> +     case PERIPH_ID_I2C7:
>>>>>>> +     case PERIPH_ID_I2C8:
>>>>>>> +     case PERIPH_ID_I2C9:
>>>>>>> +     case PERIPH_ID_I2C10:
>>>>>>> +             sclk = exynos542x_get_pll_clk(MPLL);
>>>>>>> +             sub_div = ((readl(&clk->div_top1) >> bit_info->div_bit)
>>>>>>> +                                                             & 0x7) + 1;
>>>>>>> +             return sclk / sub_div;
>>>>>>> +     default:
>>>>>>> +             debug("%s: invalid peripheral %d", __func__, peripheral);
>>>>>>> +             return -1;
>>>>>>> +     };
>>>>>>> +
>>>>>>> +     if (bit_info->src_bit >= 0)
>>>>>>> +             src = (src >> bit_info->src_bit) & 0xf;
>>>>>>> +
>>>>>>> +     switch (src) {
>>>>>>> +     case EXYNOS542x_SRC_MPLL:
>>>>>>> +             sclk = exynos542x_get_pll_clk(MPLL);
>>>>>>> +             break;
>>>>>>> +     case EXYNOS542x_SRC_EPLL:
>>>>>>> +             sclk = exynos542x_get_pll_clk(EPLL);
>>>>>>> +             break;
>>>>>>> +     case EXYNOS542x_SRC_RPLL:
>>>>>>> +             sclk = exynos542x_get_pll_clk(RPLL);
>>>>>>> +             break;
>>>>>>> +     default:
>>>>>>> +             return 0;
>>>>>>> +     }
>>>>>>> +
>>>>>>
>>>>>> Odroid xu3 board uses SPLL as source clock for SDMMCx, please SPLL case.
>>>>>
>>>>> Perhaps this can be sorted out by the maintainer of that board? I'm
>>>>> not sure how we can deal with this other than a special case.
>>>>> Certainly Akshay is not going to know what to do here.
>>>>>
>>>>
>>>> I don't think this is special case, SPLL also can be used as source
>>>> clock like MPLL, EPLL and RPLL.
>>>>
>>>>>>
>>>>>>> +     /* Ratio clock division for this peripheral */
>>>>>>> +     if (bit_info->div_bit >= 0) {
>>>>>>> +             div = (div >> bit_info->div_bit) & 0xf;
>>>>>>
>>>>>> Hmm, mask bits are different each peripheral, e.g. SDMMCx needs 0x3ff
>>>>>> mask bits.
>>>>>>
>>>>
>>>> Akshay, could you follow up this?
>>>
>>> Can you please issue a Reviewed-by/Tested-by for those patches you are
>>> happy with?
>>>
>>
>> Sure, i will reply Reviewed-by or Tested-by if he solves issues.
> 
> OK, so are any of the patches OK now? Basically I'm not sure if you
> have more comments. It looks like 3-4 of them are OK, but I'm not
> sure.
> 

They are ok to me except 3, 5, 6 patches because if 3 patch isn't fixed
5,6 patches are meaningless.

Thanks.
Jaehoon Chung Jan. 30, 2015, 2:22 a.m. UTC | #8
Hi, All.

On 01/28/2015 02:55 PM, Joonyoung Shim wrote:
> Hi Simon,
> 
> On 01/28/2015 02:15 PM, Simon Glass wrote:
>> Hi Joonyoung,
>>
>> On 27 January 2015 at 22:12, Joonyoung Shim <jy0922.shim@samsung.com> wrote:
>>> Hi Simon,
>>>
>>> On 01/28/2015 02:01 PM, Simon Glass wrote:
>>>> Hi Joonyoung,
>>>>
>>>> On 27 January 2015 at 21:46, Joonyoung Shim <jy0922.shim@samsung.com> wrote:
>>>>> Hi Simon,
>>>>>
>>>>> On 01/28/2015 01:09 PM, Simon Glass wrote:
>>>>>> Hi,
>>>>>>
>>>>>> On 15 January 2015 at 23:09, Joonyoung Shim <jy0922.shim@samsung.com> wrote:
>>>>>>> Hi,
>>>>>>>
>>>>>>> On 01/16/2015 02:48 PM, Akshay Saraswat wrote:
>>>>>>>> We planned to fetch peripheral rate through one generic API per
>>>>>>>> peripheral. These generic peripheral functions are in turn
>>>>>>>> expected to fetch apt values from a function refactored as
>>>>>>>> per SoC versions. This patch adds support for fetching peripheral
>>>>>>>> rates for Exynos5420 and Exynos5800.
>>>>>>>>
>>>>>>>> Signed-off-by: Akshay Saraswat <akshay.s@samsung.com>
>>>>>>>> ---
>>>>>>>> Changes since v2:
>>>>>>>>       - Fixed enum and exynos542x_get_periph_rate switch.
>>>>>>>>       - Added checks for negative values in exynos542x_get_periph_rate.
>>>>>>>>
>>>>>>>> Changes since v1:
>>>>>>>>       - Changes suuport -> support in commit message.
>>>>>>>>       - Removed position change of exynos5420_get_pll_clk.
>>>>>>>>       - Removed #ifdef.
>>>>>>>>
>>>>>>>>  arch/arm/cpu/armv7/exynos/clock.c      | 151 +++++++++++++++++++++++++++++++--
>>>>>>>>  arch/arm/include/asm/arch-exynos/clk.h |   3 +
>>>>>>>>  2 files changed, 147 insertions(+), 7 deletions(-)
>>>>>>
>>>>>> What else needs to be done to get this applied, please?
>>>>>>
>>>>>
>>>>> As i said, current this patch has some problem like mask bits, so eMMC
>>>>> doesn't work normally.
>>>>>
>>>>>>>>
>>>>>>>> diff --git a/arch/arm/cpu/armv7/exynos/clock.c b/arch/arm/cpu/armv7/exynos/clock.c
>>>>>>>> index 5dc9ed2..ee6c13b 100644
>>>>>>>> --- a/arch/arm/cpu/armv7/exynos/clock.c
>>>>>>>> +++ b/arch/arm/cpu/armv7/exynos/clock.c
>>>>>>>> @@ -27,7 +27,7 @@ struct clk_bit_info {
>>>>>>>>  };
>>>>>>>>
>>>>>>>>  /* periph_id src_bit div_bit prediv_bit */
>>>>>>>> -static struct clk_bit_info clk_bit_info[] = {
>>>>>>>> +static struct clk_bit_info exynos5_bit_info[] = {
>>>>>>>>       {PERIPH_ID_UART0,       0,      0,      -1},
>>>>>>>>       {PERIPH_ID_UART1,       4,      4,      -1},
>>>>>>>>       {PERIPH_ID_UART2,       8,      8,      -1},
>>>>>>>> @@ -61,6 +61,42 @@ static struct clk_bit_info clk_bit_info[] = {
>>>>>>>>       {PERIPH_ID_NONE,        -1,     -1,     -1},
>>>>>>>>  };
>>>>>>>>
>>>>>>>> +static struct clk_bit_info exynos542x_bit_info[] = {
>>>>>>>> +     {PERIPH_ID_UART0,       4,      8,      -1},
>>>>>>>> +     {PERIPH_ID_UART1,       8,      12,     -1},
>>>>>>>> +     {PERIPH_ID_UART2,       12,     16,     -1},
>>>>>>>> +     {PERIPH_ID_UART3,       16,     20,     -1},
>>>>>>>> +     {PERIPH_ID_I2C0,        -1,     8,      -1},
>>>>>>>> +     {PERIPH_ID_I2C1,        -1,     8,      -1},
>>>>>>>> +     {PERIPH_ID_I2C2,        -1,     8,      -1},
>>>>>>>> +     {PERIPH_ID_I2C3,        -1,     8,      -1},
>>>>>>>> +     {PERIPH_ID_I2C4,        -1,     8,      -1},
>>>>>>>> +     {PERIPH_ID_I2C5,        -1,     8,      -1},
>>>>>>>> +     {PERIPH_ID_I2C6,        -1,     8,      -1},
>>>>>>>> +     {PERIPH_ID_I2C7,        -1,     8,      -1},
>>>>>>>> +     {PERIPH_ID_SPI0,        20,     20,     8},
>>>>>>>> +     {PERIPH_ID_SPI1,        24,     24,     16},
>>>>>>>> +     {PERIPH_ID_SPI2,        28,     28,     24},
>>>>>>>> +     {PERIPH_ID_SDMMC0,      0,      0,      -1},
>>>>>>>> +     {PERIPH_ID_SDMMC1,      4,      10,     -1},
>>>>>>>> +     {PERIPH_ID_SDMMC2,      8,      20,     -1},
>>>>>>>> +     {PERIPH_ID_I2C8,        -1,     8,      -1},
>>>>>>>> +     {PERIPH_ID_I2C9,        -1,     8,      -1},
>>>>>>>> +     {PERIPH_ID_I2S0,        0,      0,      4},
>>>>>>>> +     {PERIPH_ID_I2S1,        4,      12,     16},
>>>>>>>> +     {PERIPH_ID_SPI3,        12,     16,     0},
>>>>>>>> +     {PERIPH_ID_SPI4,        16,     20,     8},
>>>>>>>> +     {PERIPH_ID_SDMMC4,      16,     0,      8},
>>>>>>>> +     {PERIPH_ID_PWM0,        24,     28,     -1},
>>>>>>>> +     {PERIPH_ID_PWM1,        24,     28,     -1},
>>>>>>>> +     {PERIPH_ID_PWM2,        24,     28,     -1},
>>>>>>>> +     {PERIPH_ID_PWM3,        24,     28,     -1},
>>>>>>>> +     {PERIPH_ID_PWM4,        24,     28,     -1},
>>>>>>>> +     {PERIPH_ID_I2C10,       -1,     8,      -1},
>>>>>>>> +
>>>>>>>> +     {PERIPH_ID_NONE,        -1,     -1,     -1},
>>>>>>>> +};
>>>>>>>> +
>>>>>>>>  /* Epll Clock division values to achive different frequency output */
>>>>>>>>  static struct set_epll_con_val exynos5_epll_div[] = {
>>>>>>>>       { 192000000, 0, 48, 3, 1, 0 },
>>>>>>>> @@ -306,16 +342,22 @@ static unsigned long exynos542x_get_pll_clk(int pllreg)
>>>>>>>>  static struct clk_bit_info *get_clk_bit_info(int peripheral)
>>>>>>>>  {
>>>>>>>>       int i;
>>>>>>>> +     struct clk_bit_info *info;
>>>>>>>>
>>>>>>>> -     for (i = 0; clk_bit_info[i].id != PERIPH_ID_NONE; i++) {
>>>>>>>> -             if (clk_bit_info[i].id == peripheral)
>>>>>>>> +     if (proid_is_exynos5420() || proid_is_exynos5800())
>>>>>>>> +             info = exynos542x_bit_info;
>>>>>>>> +     else
>>>>>>>> +             info = exynos5_bit_info;
>>>>>>>> +
>>>>>>>> +     for (i = 0; info[i].id != PERIPH_ID_NONE; i++) {
>>>>>>>> +             if (info[i].id == peripheral)
>>>>>>>>                       break;
>>>>>>>>       }
>>>>>>>>
>>>>>>>> -     if (clk_bit_info[i].id == PERIPH_ID_NONE)
>>>>>>>> +     if (info[i].id == PERIPH_ID_NONE)
>>>>>>>>               debug("ERROR: Peripheral ID %d not found\n", peripheral);
>>>>>>>>
>>>>>>>> -     return &clk_bit_info[i];
>>>>>>>> +     return &info[i];
>>>>>>>>  }
>>>>>>>>
>>>>>>>>  static unsigned long exynos5_get_periph_rate(int peripheral)
>>>>>>>> @@ -414,12 +456,107 @@ static unsigned long exynos5_get_periph_rate(int peripheral)
>>>>>>>>       return sub_clk;
>>>>>>>>  }
>>>>>>>>
>>>>>>>> +static unsigned long exynos542x_get_periph_rate(int peripheral)
>>>>>>>> +{
>>>>>>>> +     struct clk_bit_info *bit_info = get_clk_bit_info(peripheral);
>>>>>>>> +     unsigned long sclk, sub_clk = 0;
>>>>>>>> +     unsigned int src, div, sub_div = 0;
>>>>>>>> +     struct exynos5420_clock *clk =
>>>>>>>> +                     (struct exynos5420_clock *)samsung_get_base_clock();
>>>>>>>> +
>>>>>>>> +     switch (peripheral) {
>>>>>>>> +     case PERIPH_ID_UART0:
>>>>>>>> +     case PERIPH_ID_UART1:
>>>>>>>> +     case PERIPH_ID_UART2:
>>>>>>>> +     case PERIPH_ID_UART3:
>>>>>>>> +     case PERIPH_ID_PWM0:
>>>>>>>> +     case PERIPH_ID_PWM1:
>>>>>>>> +     case PERIPH_ID_PWM2:
>>>>>>>> +     case PERIPH_ID_PWM3:
>>>>>>>> +     case PERIPH_ID_PWM4:
>>>>>>>> +             src = readl(&clk->src_peric0);
>>>>>>>> +             div = readl(&clk->div_peric0);
>>>>>>>> +             break;
>>>>>>>> +     case PERIPH_ID_SPI0:
>>>>>>>> +     case PERIPH_ID_SPI1:
>>>>>>>> +     case PERIPH_ID_SPI2:
>>>>>>>> +             src = readl(&clk->src_peric1);
>>>>>>>> +             div = readl(&clk->div_peric1);
>>>>>>>> +             sub_div = readl(&clk->div_peric4);
>>>>>>>> +             break;
>>>>>>>> +     case PERIPH_ID_SPI3:
>>>>>>>> +     case PERIPH_ID_SPI4:
>>>>>>>> +             src = readl(&clk->src_isp);
>>>>>>>> +             div = readl(&clk->div_isp1);
>>>>>>>> +             sub_div = readl(&clk->div_isp1);
>>>>>>>> +             break;
>>>>>>>> +     case PERIPH_ID_SDMMC0:
>>>>>>>> +     case PERIPH_ID_SDMMC1:
>>>>>>>> +     case PERIPH_ID_SDMMC2:
>>>>>>>> +     case PERIPH_ID_SDMMC3:
>>>>>>>> +             src = readl(&clk->src_fsys);
>>>>>>>> +             div = readl(&clk->div_fsys1);
>>>>>>>> +             break;
>>>>>>>> +     case PERIPH_ID_I2C0:
>>>>>>>> +     case PERIPH_ID_I2C1:
>>>>>>>> +     case PERIPH_ID_I2C2:
>>>>>>>> +     case PERIPH_ID_I2C3:
>>>>>>>> +     case PERIPH_ID_I2C4:
>>>>>>>> +     case PERIPH_ID_I2C5:
>>>>>>>> +     case PERIPH_ID_I2C6:
>>>>>>>> +     case PERIPH_ID_I2C7:
>>>>>>>> +     case PERIPH_ID_I2C8:
>>>>>>>> +     case PERIPH_ID_I2C9:
>>>>>>>> +     case PERIPH_ID_I2C10:
>>>>>>>> +             sclk = exynos542x_get_pll_clk(MPLL);
>>>>>>>> +             sub_div = ((readl(&clk->div_top1) >> bit_info->div_bit)
>>>>>>>> +                                                             & 0x7) + 1;
>>>>>>>> +             return sclk / sub_div;
>>>>>>>> +     default:
>>>>>>>> +             debug("%s: invalid peripheral %d", __func__, peripheral);
>>>>>>>> +             return -1;
>>>>>>>> +     };
>>>>>>>> +
>>>>>>>> +     if (bit_info->src_bit >= 0)
>>>>>>>> +             src = (src >> bit_info->src_bit) & 0xf;
>>>>>>>> +
>>>>>>>> +     switch (src) {
>>>>>>>> +     case EXYNOS542x_SRC_MPLL:
>>>>>>>> +             sclk = exynos542x_get_pll_clk(MPLL);
>>>>>>>> +             break;
>>>>>>>> +     case EXYNOS542x_SRC_EPLL:
>>>>>>>> +             sclk = exynos542x_get_pll_clk(EPLL);
>>>>>>>> +             break;
>>>>>>>> +     case EXYNOS542x_SRC_RPLL:
>>>>>>>> +             sclk = exynos542x_get_pll_clk(RPLL);
>>>>>>>> +             break;
>>>>>>>> +     default:
>>>>>>>> +             return 0;
>>>>>>>> +     }
>>>>>>>> +
>>>>>>>
>>>>>>> Odroid xu3 board uses SPLL as source clock for SDMMCx, please SPLL case.
>>>>>>
>>>>>> Perhaps this can be sorted out by the maintainer of that board? I'm
>>>>>> not sure how we can deal with this other than a special case.
>>>>>> Certainly Akshay is not going to know what to do here.
>>>>>>
>>>>>
>>>>> I don't think this is special case, SPLL also can be used as source
>>>>> clock like MPLL, EPLL and RPLL.
>>>>>
>>>>>>>
>>>>>>>> +     /* Ratio clock division for this peripheral */
>>>>>>>> +     if (bit_info->div_bit >= 0) {
>>>>>>>> +             div = (div >> bit_info->div_bit) & 0xf;
>>>>>>>
>>>>>>> Hmm, mask bits are different each peripheral, e.g. SDMMCx needs 0x3ff
>>>>>>> mask bits.
>>>>>>>
>>>>>
>>>>> Akshay, could you follow up this?
>>>>
>>>> Can you please issue a Reviewed-by/Tested-by for those patches you are
>>>> happy with?
>>>>
>>>
>>> Sure, i will reply Reviewed-by or Tested-by if he solves issues.
>>
>> OK, so are any of the patches OK now? Basically I'm not sure if you
>> have more comments. It looks like 3-4 of them are OK, but I'm not
>> sure.
>>
> 
> They are ok to me except 3, 5, 6 patches because if 3 patch isn't fixed
> 5,6 patches are meaningless.

Is Akshay working these? As Simon is mentioned, i want to know the plan..
If Akshay is busy, i will rework these with patches based on Akshay.

Best Regards,
Jaehoon Chung

> 
> Thanks.
> 
>
diff mbox

Patch

diff --git a/arch/arm/cpu/armv7/exynos/clock.c b/arch/arm/cpu/armv7/exynos/clock.c
index 5dc9ed2..ee6c13b 100644
--- a/arch/arm/cpu/armv7/exynos/clock.c
+++ b/arch/arm/cpu/armv7/exynos/clock.c
@@ -27,7 +27,7 @@  struct clk_bit_info {
 };
 
 /* periph_id src_bit div_bit prediv_bit */
-static struct clk_bit_info clk_bit_info[] = {
+static struct clk_bit_info exynos5_bit_info[] = {
 	{PERIPH_ID_UART0,	0,	0,	-1},
 	{PERIPH_ID_UART1,	4,	4,	-1},
 	{PERIPH_ID_UART2,	8,	8,	-1},
@@ -61,6 +61,42 @@  static struct clk_bit_info clk_bit_info[] = {
 	{PERIPH_ID_NONE,	-1,	-1,	-1},
 };
 
+static struct clk_bit_info exynos542x_bit_info[] = {
+	{PERIPH_ID_UART0,	4,	8,	-1},
+	{PERIPH_ID_UART1,	8,	12,	-1},
+	{PERIPH_ID_UART2,	12,	16,	-1},
+	{PERIPH_ID_UART3,	16,	20,	-1},
+	{PERIPH_ID_I2C0,	-1,	8,	-1},
+	{PERIPH_ID_I2C1,	-1,	8,	-1},
+	{PERIPH_ID_I2C2,	-1,	8,	-1},
+	{PERIPH_ID_I2C3,	-1,	8,	-1},
+	{PERIPH_ID_I2C4,	-1,	8,	-1},
+	{PERIPH_ID_I2C5,	-1,	8,	-1},
+	{PERIPH_ID_I2C6,	-1,	8,	-1},
+	{PERIPH_ID_I2C7,	-1,	8,	-1},
+	{PERIPH_ID_SPI0,	20,	20,	8},
+	{PERIPH_ID_SPI1,	24,	24,	16},
+	{PERIPH_ID_SPI2,	28,	28,	24},
+	{PERIPH_ID_SDMMC0,	0,	0,	-1},
+	{PERIPH_ID_SDMMC1,	4,	10,	-1},
+	{PERIPH_ID_SDMMC2,	8,	20,	-1},
+	{PERIPH_ID_I2C8,	-1,	8,	-1},
+	{PERIPH_ID_I2C9,	-1,	8,	-1},
+	{PERIPH_ID_I2S0,	0,	0,	4},
+	{PERIPH_ID_I2S1,	4,	12,	16},
+	{PERIPH_ID_SPI3,	12,	16,	0},
+	{PERIPH_ID_SPI4,	16,	20,	8},
+	{PERIPH_ID_SDMMC4,	16,	0,	8},
+	{PERIPH_ID_PWM0,	24,	28,	-1},
+	{PERIPH_ID_PWM1,	24,	28,	-1},
+	{PERIPH_ID_PWM2,	24,	28,	-1},
+	{PERIPH_ID_PWM3,	24,	28,	-1},
+	{PERIPH_ID_PWM4,	24,	28,	-1},
+	{PERIPH_ID_I2C10,	-1,	8,	-1},
+
+	{PERIPH_ID_NONE,	-1,	-1,	-1},
+};
+
 /* Epll Clock division values to achive different frequency output */
 static struct set_epll_con_val exynos5_epll_div[] = {
 	{ 192000000, 0, 48, 3, 1, 0 },
@@ -306,16 +342,22 @@  static unsigned long exynos542x_get_pll_clk(int pllreg)
 static struct clk_bit_info *get_clk_bit_info(int peripheral)
 {
 	int i;
+	struct clk_bit_info *info;
 
-	for (i = 0; clk_bit_info[i].id != PERIPH_ID_NONE; i++) {
-		if (clk_bit_info[i].id == peripheral)
+	if (proid_is_exynos5420() || proid_is_exynos5800())
+		info = exynos542x_bit_info;
+	else
+		info = exynos5_bit_info;
+
+	for (i = 0; info[i].id != PERIPH_ID_NONE; i++) {
+		if (info[i].id == peripheral)
 			break;
 	}
 
-	if (clk_bit_info[i].id == PERIPH_ID_NONE)
+	if (info[i].id == PERIPH_ID_NONE)
 		debug("ERROR: Peripheral ID %d not found\n", peripheral);
 
-	return &clk_bit_info[i];
+	return &info[i];
 }
 
 static unsigned long exynos5_get_periph_rate(int peripheral)
@@ -414,12 +456,107 @@  static unsigned long exynos5_get_periph_rate(int peripheral)
 	return sub_clk;
 }
 
+static unsigned long exynos542x_get_periph_rate(int peripheral)
+{
+	struct clk_bit_info *bit_info = get_clk_bit_info(peripheral);
+	unsigned long sclk, sub_clk = 0;
+	unsigned int src, div, sub_div = 0;
+	struct exynos5420_clock *clk =
+			(struct exynos5420_clock *)samsung_get_base_clock();
+
+	switch (peripheral) {
+	case PERIPH_ID_UART0:
+	case PERIPH_ID_UART1:
+	case PERIPH_ID_UART2:
+	case PERIPH_ID_UART3:
+	case PERIPH_ID_PWM0:
+	case PERIPH_ID_PWM1:
+	case PERIPH_ID_PWM2:
+	case PERIPH_ID_PWM3:
+	case PERIPH_ID_PWM4:
+		src = readl(&clk->src_peric0);
+		div = readl(&clk->div_peric0);
+		break;
+	case PERIPH_ID_SPI0:
+	case PERIPH_ID_SPI1:
+	case PERIPH_ID_SPI2:
+		src = readl(&clk->src_peric1);
+		div = readl(&clk->div_peric1);
+		sub_div = readl(&clk->div_peric4);
+		break;
+	case PERIPH_ID_SPI3:
+	case PERIPH_ID_SPI4:
+		src = readl(&clk->src_isp);
+		div = readl(&clk->div_isp1);
+		sub_div = readl(&clk->div_isp1);
+		break;
+	case PERIPH_ID_SDMMC0:
+	case PERIPH_ID_SDMMC1:
+	case PERIPH_ID_SDMMC2:
+	case PERIPH_ID_SDMMC3:
+		src = readl(&clk->src_fsys);
+		div = readl(&clk->div_fsys1);
+		break;
+	case PERIPH_ID_I2C0:
+	case PERIPH_ID_I2C1:
+	case PERIPH_ID_I2C2:
+	case PERIPH_ID_I2C3:
+	case PERIPH_ID_I2C4:
+	case PERIPH_ID_I2C5:
+	case PERIPH_ID_I2C6:
+	case PERIPH_ID_I2C7:
+	case PERIPH_ID_I2C8:
+	case PERIPH_ID_I2C9:
+	case PERIPH_ID_I2C10:
+		sclk = exynos542x_get_pll_clk(MPLL);
+		sub_div = ((readl(&clk->div_top1) >> bit_info->div_bit)
+								& 0x7) + 1;
+		return sclk / sub_div;
+	default:
+		debug("%s: invalid peripheral %d", __func__, peripheral);
+		return -1;
+	};
+
+	if (bit_info->src_bit >= 0)
+		src = (src >> bit_info->src_bit) & 0xf;
+
+	switch (src) {
+	case EXYNOS542x_SRC_MPLL:
+		sclk = exynos542x_get_pll_clk(MPLL);
+		break;
+	case EXYNOS542x_SRC_EPLL:
+		sclk = exynos542x_get_pll_clk(EPLL);
+		break;
+	case EXYNOS542x_SRC_RPLL:
+		sclk = exynos542x_get_pll_clk(RPLL);
+		break;
+	default:
+		return 0;
+	}
+
+	/* Ratio clock division for this peripheral */
+	if (bit_info->div_bit >= 0) {
+		div = (div >> bit_info->div_bit) & 0xf;
+		sub_clk = sclk / (div + 1);
+	}
+
+	if (bit_info->prediv_bit >= 0) {
+		sub_div = (sub_div >> bit_info->prediv_bit) & 0xff;
+		return sub_clk / (sub_div + 1);
+	}
+
+	return sub_clk;
+}
+
 unsigned long clock_get_periph_rate(int peripheral)
 {
-	if (cpu_is_exynos5())
+	if (cpu_is_exynos5()) {
+		if (proid_is_exynos5420() || proid_is_exynos5800())
+			return exynos542x_get_periph_rate(peripheral);
 		return exynos5_get_periph_rate(peripheral);
-	else
+	} else {
 		return 0;
+	}
 }
 
 /* exynos4: return ARM clock frequency */
diff --git a/arch/arm/include/asm/arch-exynos/clk.h b/arch/arm/include/asm/arch-exynos/clk.h
index db24dc0..da9bfcd 100644
--- a/arch/arm/include/asm/arch-exynos/clk.h
+++ b/arch/arm/include/asm/arch-exynos/clk.h
@@ -26,6 +26,9 @@  enum pll_src_bit {
 	EXYNOS_SRC_MPLL = 6,
 	EXYNOS_SRC_EPLL,
 	EXYNOS_SRC_VPLL,
+	EXYNOS542x_SRC_MPLL = 3,
+	EXYNOS542x_SRC_EPLL = 6,
+	EXYNOS542x_SRC_RPLL,
 };
 
 unsigned long get_pll_clk(int pllreg);