[U-Boot] [PATCH 3/9 V9] Exynos5420: Add clock initialization for 5420

Minkyu Kang mk7.kang at samsung.com
Tue Dec 3 07:14:27 CET 2013


Dear Rajeshwari S Shinde,

On 02/12/13 20:47, Rajeshwari S Shinde wrote:
> This patch adds code for clock initialization and clock settings
> of various IP's and controllers, required for Exynos5420
> 
> Signed-off-by: Rajeshwari S Shinde <rajeshwari.s at samsung.com>
> Signed-off-by: Akshay Saraswat <akshay.s at samsung.com>
> Acked-by: Simon Glass <sjg at chromium.org>
> ---
> Changes in V2:
> 	- None
> Changes in V3:
> 	- None
> Changes in V4:
> 	- Corrected the multiline commenting style
> Changes in V5:
> 	- None
> Changes in V6:
> 	- None
> Changes in V7:
> 	- Correct the logic for exynos5420_set_spi_clk api.
> Changes in V8:
> 	- Chnages the if condition loop for pro_id and cpu_id.
> Changes in V9:
> 	- Used samsung_get_base to get base address of clock.
>  arch/arm/cpu/armv7/exynos/clock.c              | 258 ++++++++-
>  arch/arm/cpu/armv7/exynos/clock_init.h         |  17 +
>  arch/arm/cpu/armv7/exynos/clock_init_exynos5.c | 352 +++++++++++-
>  arch/arm/cpu/armv7/exynos/exynos5_setup.h      | 738 +++++++++++++++++++------
>  arch/arm/include/asm/arch-exynos/clk.h         |   1 +
>  arch/arm/include/asm/arch-exynos/clock.h       | 494 +++++++++++++++++
>  6 files changed, 1659 insertions(+), 201 deletions(-)
> 
> diff --git a/arch/arm/cpu/armv7/exynos/clock.c b/arch/arm/cpu/armv7/exynos/clock.c
> index 36fedd6..f2f06ac 100644
> --- a/arch/arm/cpu/armv7/exynos/clock.c
> +++ b/arch/arm/cpu/armv7/exynos/clock.c
> @@ -96,7 +96,7 @@ static int exynos_get_pll_clk(int pllreg, unsigned int r, unsigned int k)
>  
>  	freq = CONFIG_SYS_CLK_FREQ;
>  
> -	if (pllreg == EPLL) {
> +	if (pllreg == EPLL || pllreg == RPLL) {
>  		k = k & 0xffff;
>  		/* FOUT = (MDIV + K / 65536) * FIN / (PDIV * 2^SDIV) */
>  		fout = (m + k / PLL_DIV_65536) * (freq / (p * (1 << s)));
> @@ -117,7 +117,7 @@ static int exynos_get_pll_clk(int pllreg, unsigned int r, unsigned int k)
>  			div = PLL_DIV_1024;
>  		else if (proid_is_exynos4412())
>  			div = PLL_DIV_65535;
> -		else if (proid_is_exynos5250())
> +		else if (proid_is_exynos5250() || proid_is_exynos5420())
>  			div = PLL_DIV_65536;
>  		else
>  			return 0;
> @@ -362,6 +362,43 @@ unsigned long clock_get_periph_rate(int peripheral)
>  		return 0;
>  }
>  
> +/* exynos5420: return pll clock frequency */
> +static unsigned long exynos5420_get_pll_clk(int pllreg)
> +{
> +	struct exynos5420_clock *clk =
> +		(struct exynos5420_clock *)samsung_get_base_clock();
> +	unsigned long r, k = 0;
> +
> +	switch (pllreg) {
> +	case APLL:
> +		r = readl(&clk->apll_con0);
> +		break;
> +	case MPLL:
> +		r = readl(&clk->mpll_con0);
> +		break;
> +	case EPLL:
> +		r = readl(&clk->epll_con0);
> +		k = readl(&clk->epll_con1);
> +		break;
> +	case VPLL:
> +		r = readl(&clk->vpll_con0);
> +		k = readl(&clk->vpll_con1);
> +		break;
> +	case BPLL:
> +		r = readl(&clk->bpll_con0);
> +		break;
> +	case RPLL:
> +		r = readl(&clk->rpll_con0);
> +		k = readl(&clk->rpll_con1);
> +		break;
> +	default:
> +		printf("Unsupported PLL (%d)\n", pllreg);
> +		return 0;
> +	}
> +
> +	return exynos_get_pll_clk(pllreg, r, k);
> +}
> +
>  /* exynos4: return ARM clock frequency */
>  static unsigned long exynos4_get_arm_clk(void)
>  {
> @@ -485,6 +522,27 @@ static unsigned long exynos4x12_get_pwm_clk(void)
>  	return pclk;
>  }
>  
> +/* exynos5420: return pwm clock frequency */
> +static unsigned long exynos5420_get_pwm_clk(void)
> +{
> +	struct exynos5420_clock *clk =
> +		(struct exynos5420_clock *)samsung_get_base_clock();
> +	unsigned long pclk, sclk;
> +	unsigned int ratio;
> +
> +	/*
> +	 * CLK_DIV_PERIC3

peric0?

> +	 * PWM_RATIO [3:0]

then, why you right shift to 28?

> +	 */
> +	ratio = readl(&clk->div_peric0);
> +	ratio = (ratio >> 28) & 0xf;
> +	sclk = get_pll_clk(MPLL);
> +
> +	pclk = sclk / (ratio + 1);
> +
> +	return pclk;
> +}
> +
>  /* exynos4: return uart clock frequency */
>  static unsigned long exynos4_get_uart_clk(int dev_index)
>  {
> @@ -624,6 +682,53 @@ static unsigned long exynos5_get_uart_clk(int dev_index)
>  	return uclk;
>  }
>  
> +/* exynos5420: return uart clock frequency */
> +static unsigned long exynos5420_get_uart_clk(int dev_index)
> +{
> +	struct exynos5420_clock *clk =
> +		(struct exynos5420_clock *)samsung_get_base_clock();
> +	unsigned long uclk, sclk;
> +	unsigned int sel;
> +	unsigned int ratio;
> +
> +	/*
> +	 * CLK_SRC_PERIC0
> +	 * UART0_SEL [3:0]
> +	 * UART1_SEL [7:4]
> +	 * UART2_SEL [8:11]
> +	 * UART3_SEL [12:15]
> +	 * UART4_SEL [16:19]
> +	 * UART5_SEL [23:20]
> +	 */
> +	sel = readl(&clk->src_peric0);
> +	sel = (sel >> ((dev_index * 4) + 4)) & 0x7;

did not matched with comment and code.
please check.

> +
> +	if (sel == 0x3)
> +		sclk = get_pll_clk(MPLL);
> +	else if (sel == 0x6)
> +		sclk = get_pll_clk(EPLL);
> +	else if (sel == 0x7)
> +		sclk = get_pll_clk(RPLL);
> +	else
> +		return 0;
> +
> +	/*
> +	 * CLK_DIV_PERIC0
> +	 * UART0_RATIO [3:0]
> +	 * UART1_RATIO [7:4]
> +	 * UART2_RATIO [8:11]
> +	 * UART3_RATIO [12:15]
> +	 * UART4_RATIO [16:19]
> +	 * UART5_RATIO [23:20]
> +	 */
> +	ratio = readl(&clk->div_peric0);
> +	ratio = (ratio >> ((dev_index * 4) + 8)) & 0xf;

ditto.

> +
> +	uclk = sclk / (ratio + 1);
> +
> +	return uclk;
> +}
> +
>  static unsigned long exynos4_get_mmc_clk(int dev_index)
>  {
>  	struct exynos4_clock *clk =
> @@ -718,6 +823,34 @@ static unsigned long exynos5_get_mmc_clk(int dev_index)
>  	return uclk;
>  }
>  
> +static unsigned long exynos5420_get_mmc_clk(int dev_index)
> +{
> +	struct exynos5420_clock *clk =
> +		(struct exynos5420_clock *)samsung_get_base_clock();
> +	unsigned long uclk, sclk;
> +	unsigned int sel, ratio;
> +	int shift = 0;

initial value (= 0) is unnecessary.

> +
> +	sel = readl(&clk->src_fsys);
> +	sel = (sel >> ((dev_index * 4) + 8)) & 0x7;

could you please add comment for it?

> +
> +	if (sel == 0x3)
> +		sclk = get_pll_clk(MPLL);
> +	else if (sel == 0x6)
> +		sclk = get_pll_clk(EPLL);
> +	else
> +		return 0;
> +
> +	ratio = readl(&clk->div_fsys1);
> +
> +	shift = dev_index * 10;

ditto. need comment.

> +
> +	ratio = (ratio >> shift) & 0x3ff;
> +	uclk = (sclk / (ratio + 1));
> +
> +	return uclk;
> +}
> +
>  /* exynos4: set the mmc clock */
>  static void exynos4_set_mmc_clk(int dev_index, unsigned int div)
>  {
> @@ -804,6 +937,23 @@ static void exynos5_set_mmc_clk(int dev_index, unsigned int div)
>  	writel(val, addr);
>  }
>  
> +/* exynos5: set the mmc clock */
> +static void exynos5420_set_mmc_clk(int dev_index, unsigned int div)
> +{
> +	struct exynos5420_clock *clk =
> +		(struct exynos5420_clock *)samsung_get_base_clock();
> +	unsigned int addr;
> +	unsigned int val, shift;
> +
> +	addr = (unsigned int)&clk->div_fsys1;
> +	shift = dev_index * 10;

ditto.

> +
> +	val = readl(addr);
> +	val &= ~(0x3ff << shift);
> +	val |= (div & 0x3ff) << shift;
> +	writel(val, addr);
> +}
> +
>  /* get_lcd_clk: return lcd clock frequency */
>  static unsigned long exynos4_get_lcd_clk(void)
>  {
> @@ -1324,6 +1474,72 @@ static int exynos5_set_spi_clk(enum periph_id periph_id,
>  	return 0;
>  }
>  
> +static int exynos5420_set_spi_clk(enum periph_id periph_id,
> +					unsigned int rate)
> +{
> +	struct exynos5420_clock *clk =
> +		(struct exynos5420_clock *)samsung_get_base_clock();
> +	int main;
> +	unsigned int fine;
> +	unsigned shift, pre_shift;
> +	unsigned div_mask = 0xf, pre_div_mask = 0xff;
> +	u32 *reg;
> +	u32 *pre_reg;
> +
> +

please remove blank line.

> +	main = clock_calc_best_scalar(4, 8, 400000000, rate, &fine);
> +	if (main < 0) {
> +		debug("%s: Cannot set clock rate for periph %d",
> +		      __func__, periph_id);
> +		return -1;
> +	}
> +	main = main - 1;
> +	fine = fine - 1;
> +
> +	switch (periph_id) {
> +	case PERIPH_ID_SPI0:
> +		reg = &clk->div_peric1;
> +		shift = 20;
> +		pre_reg = &clk->div_peric4;
> +		pre_shift = 8;
> +		break;
> +	case PERIPH_ID_SPI1:
> +		reg = &clk->div_peric1;
> +		shift = 24;
> +		pre_reg = &clk->div_peric4;
> +		pre_shift = 16;
> +		break;
> +	case PERIPH_ID_SPI2:
> +		reg = &clk->div_peric1;
> +		shift = 28;
> +		pre_reg = &clk->div_peric4;
> +		pre_shift = 24;
> +		break;
> +	case PERIPH_ID_SPI3:
> +		reg = &clk->div_isp1;
> +		shift = 16;
> +		pre_reg = &clk->div_isp1;
> +		pre_shift = 0;
> +		break;
> +	case PERIPH_ID_SPI4:
> +		reg = &clk->div_isp1;
> +		shift = 20;
> +		pre_reg = &clk->div_isp1;
> +		pre_shift = 8;
> +		break;
> +	default:
> +		debug("%s: Unsupported peripheral ID %d\n", __func__,
> +		      periph_id);
> +		return -1;
> +	}
> +
> +	clrsetbits_le32(reg, div_mask << shift, (main & div_mask) << shift);
> +	clrsetbits_le32(pre_reg, pre_div_mask << pre_shift,
> +			(fine & pre_div_mask) << pre_shift);
> +
> +	return 0;
> +}
> +
>  static unsigned long exynos4_get_i2c_clk(void)
>  {
>  	struct exynos4_clock *clk =
> @@ -1341,9 +1557,11 @@ static unsigned long exynos4_get_i2c_clk(void)
>  
>  unsigned long get_pll_clk(int pllreg)
>  {
> -	if (cpu_is_exynos5())
> +	if (cpu_is_exynos5()) {
> +		if (proid_is_exynos5420())
> +			return exynos5420_get_pll_clk(pllreg);
>  		return exynos5_get_pll_clk(pllreg);
> -	else {
> +	} else {
>  		if (proid_is_exynos4412())
>  			return exynos4x12_get_pll_clk(pllreg);
>  		return exynos4_get_pll_clk(pllreg);
> @@ -1375,9 +1593,11 @@ unsigned long get_i2c_clk(void)
>  
>  unsigned long get_pwm_clk(void)
>  {
> -	if (cpu_is_exynos5())
> +	if (cpu_is_exynos5()) {
> +		if (proid_is_exynos5420())
> +			return exynos5420_get_pwm_clk();
>  		return clock_get_periph_rate(PERIPH_ID_PWM0);
> -	else {
> +	} else {
>  		if (proid_is_exynos4412())
>  			return exynos4x12_get_pwm_clk();
>  		return exynos4_get_pwm_clk();
> @@ -1386,9 +1606,11 @@ unsigned long get_pwm_clk(void)
>  
>  unsigned long get_uart_clk(int dev_index)
>  {
> -	if (cpu_is_exynos5())
> +	if (cpu_is_exynos5()) {
> +		if (proid_is_exynos5420())
> +			return exynos5420_get_uart_clk(dev_index);
>  		return exynos5_get_uart_clk(dev_index);
> -	else {
> +	} else {
>  		if (proid_is_exynos4412())
>  			return exynos4x12_get_uart_clk(dev_index);
>  		return exynos4_get_uart_clk(dev_index);
> @@ -1397,17 +1619,22 @@ unsigned long get_uart_clk(int dev_index)
>  
>  unsigned long get_mmc_clk(int dev_index)
>  {
> -	if (cpu_is_exynos5())
> +	if (cpu_is_exynos5()) {
> +		if (proid_is_exynos5420())
> +			return exynos5420_get_mmc_clk(dev_index);
>  		return exynos5_get_mmc_clk(dev_index);
> -	else
> +	} else {
>  		return exynos4_get_mmc_clk(dev_index);
> +	}
>  }
>  
>  void set_mmc_clk(int dev_index, unsigned int div)
>  {
> -	if (cpu_is_exynos5())
> +	if (cpu_is_exynos5()) {
> +		if (proid_is_exynos5420())
> +			return exynos5420_set_mmc_clk(dev_index, div);

it's a void function. please do not return.
and add else statement.

>  		exynos5_set_mmc_clk(dev_index, div);
> -	else {
> +	} else {
>  		if (proid_is_exynos4412())
>  			exynos4x12_set_mmc_clk(dev_index, div);
>  		exynos4_set_mmc_clk(dev_index, div);
> @@ -1438,10 +1665,13 @@ void set_mipi_clk(void)
>  
>  int set_spi_clk(int periph_id, unsigned int rate)
>  {
> -	if (cpu_is_exynos5())
> +	if (cpu_is_exynos5()) {
> +		if (proid_is_exynos5420())
> +			return exynos5420_set_spi_clk(periph_id, rate);
>  		return exynos5_set_spi_clk(periph_id, rate);
> -	else
> +	} else {
>  		return 0;
> +	}
>  }
>  
>  int set_i2s_clk_prescaler(unsigned int src_frq, unsigned int dst_frq,

Thanks,
Minkyu Kang.


More information about the U-Boot mailing list