[U-Boot] [PATCH 2/6 V5] EXYNOS: Add clock for SPI.
Hatim Rv
rv.hatimali at gmail.com
Wed Oct 17 07:21:00 CEST 2012
Dear Minkyu Kang,
On Wed, Oct 17, 2012 at 7:36 AM, Minkyu Kang <promsoft at gmail.com> wrote:
> Dear Hatim,
>
> On 16 October 2012 19:58, Hatim Ali <hatim.rv at samsung.com> wrote:
>> From: Rajeshwari Shinde <rajeshwari.s at samsung.com>
>>
>> This patch adds api to calculate and set the clock for SPI channels
>>
>> Signed-off-by: James Miller <jamesmiller at chromium.org>
>> Signed-off-by: Simon Glass <sjg at chromium.org>
>> Signed-off-by: Rajeshwari Shinde <rajeshwari.s at samsung.com>
>> ---
>>
>> Changes since v4:
>> Added Signed-off-by of James Miller
>>
>> arch/arm/cpu/armv7/exynos/clock.c | 124 ++++++++++++++++++++++++++++++++
>> arch/arm/include/asm/arch-exynos/clk.h | 4 +-
>> 2 files changed, 127 insertions(+), 1 deletions(-)
>>
>> diff --git a/arch/arm/cpu/armv7/exynos/clock.c b/arch/arm/cpu/armv7/exynos/clock.c
>> index 4f3b451..44dff2b 100644
>> --- a/arch/arm/cpu/armv7/exynos/clock.c
>> +++ b/arch/arm/cpu/armv7/exynos/clock.c
>> @@ -732,6 +732,122 @@ static unsigned long exynos5_get_i2c_clk(void)
>> return aclk_66;
>> }
>>
>> +/**
>> + * Linearly searches for the most accurate main and fine stage clock scalars
>> + * (divisors) for a specified target frequency and scalar bit sizes by checking
>> + * all multiples of main_scalar_bits values. Will always return scalars up to or
>> + * slower than target.
>> + *
>> + * @param main_scalar_bits Number of main scalar bits, must be > 0 and < 32
>> + * @param fine_scalar_bits Number of fine scalar bits, must be > 0 and < 32
>> + * @param input_freq Clock frequency to be scaled in Hz
>> + * @param target_freq Desired clock frequency in Hz
>> + * @param best_fine_scalar Pointer to store the fine stage divisor
>> + *
>> + * @return best_main_scalar Main scalar for desired frequency or -1 if none
>> + * found
>> + */
>> +static int clock_calc_best_scalar(unsigned int main_scaler_bits,
>> + unsigned int fine_scalar_bits, unsigned int input_rate,
>> + unsigned int target_rate, unsigned int *best_fine_scalar)
>> +{
>> + int i;
>> + int best_main_scalar = -1;
>> + unsigned int best_error = target_rate;
>> + const unsigned int cap = (1 << fine_scalar_bits) - 1;
>> + const unsigned int loops = 1 << main_scaler_bits;
>> +
>> + debug("Input Rate is %u, Target is %u, Cap is %u\n", input_rate,
>> + target_rate, cap);
>> +
>> + assert(best_fine_scalar != NULL);
>> + assert(main_scaler_bits <= fine_scalar_bits);
>> +
>> + *best_fine_scalar = 1;
>> +
>> + if (input_rate == 0 || target_rate == 0)
>> + return -1;
>> +
>> + if (target_rate >= input_rate)
>> + return 1;
>> +
>> + for (i = 1; i <= loops; i++) {
>> + const unsigned int effective_div = max(min(input_rate / i /
>> + target_rate, cap), 1);
>> + const unsigned int effective_rate = input_rate / i /
>> + effective_div;
>> + const int error = target_rate - effective_rate;
>> +
>> + debug("%d|effdiv:%u, effrate:%u, error:%d\n", i, effective_div,
>> + effective_rate, error);
>> +
>> + if (error >= 0 && error <= best_error) {
>> + best_error = error;
>> + best_main_scalar = i;
>> + *best_fine_scalar = effective_div;
>> + }
>> + }
>> +
>> + return best_main_scalar;
>> +}
>> +
>> +static int exynos5_spi_set_clock_rate(enum periph_id periph_id,
>
> please modify to exynos5_set_spi_clk(int periph_id, ....
>
Done. Reworked patches posted.
>> + unsigned int rate)
>> +{
>> + struct exynos5_clock *clk =
>> + (struct exynos5_clock *)samsung_get_base_clock();
>> + int main;
>> + unsigned int fine;
>> + unsigned shift, pre_shift;
>> + unsigned mask = 0xff;
>> + u32 *reg;
>> +
>> + 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 = 0;
>> + pre_shift = 8;
>> + break;
>> + case PERIPH_ID_SPI1:
>> + reg = &clk->div_peric1;
>> + shift = 16;
>> + pre_shift = 24;
>> + break;
>> + case PERIPH_ID_SPI2:
>> + reg = &clk->div_peric2;
>> + shift = 0;
>> + pre_shift = 8;
>> + break;
>> + case PERIPH_ID_SPI3:
>> + reg = &clk->sclk_div_isp;
>> + shift = 0;
>> + pre_shift = 4;
>> + break;
>> + case PERIPH_ID_SPI4:
>> + reg = &clk->sclk_div_isp;
>> + shift = 12;
>> + pre_shift = 16;
>> + break;
>> + default:
>> + debug("%s: Unsupported peripheral ID %d\n", __func__,
>> + periph_id);
>> + return -1;
>> + }
>> + clrsetbits_le32(reg, mask << shift, (main & mask) << shift);
>> + clrsetbits_le32(reg, mask << pre_shift, (fine & mask) << pre_shift);
>> +
>> + return 0;
>> +}
>> +
>> unsigned long get_pll_clk(int pllreg)
>> {
>> if (cpu_is_exynos5())
>> @@ -803,3 +919,11 @@ void set_mipi_clk(void)
>> if (cpu_is_exynos4())
>> exynos4_set_mipi_clk();
>> }
>> +
>> +int spi_set_clock_rate(enum periph_id periph_id, unsigned int rate)
>
> set_spi_clk()
>
Done. Reworked patches posted.
>> +{
>> + if (cpu_is_exynos5())
>> + return exynos5_spi_set_clock_rate(periph_id, rate);
>> + else
>> + return 0;
>> +}
>> diff --git a/arch/arm/include/asm/arch-exynos/clk.h b/arch/arm/include/asm/arch-exynos/clk.h
>> index 5529025..4e51402 100644
>> --- a/arch/arm/include/asm/arch-exynos/clk.h
>> +++ b/arch/arm/include/asm/arch-exynos/clk.h
>> @@ -22,6 +22,8 @@
>> #ifndef __ASM_ARM_ARCH_CLK_H_
>> #define __ASM_ARM_ARCH_CLK_H_
>>
>> +#include <asm/arch/pinmux.h>
>
> no. we don't need this header file.
>
Actually we do need the asm/arch/periph.h file as we are using the
'enum periph_id'. Otherwise it will give compilation errors.
>> +
>> #define APLL 0
>> #define MPLL 1
>> #define EPLL 2
>> @@ -38,5 +40,5 @@ void set_mmc_clk(int dev_index, unsigned int div);
>> unsigned long get_lcd_clk(void);
>> void set_lcd_clk(void);
>> void set_mipi_clk(void);
>> -
>> +int spi_set_clock_rate(enum periph_id periph_id, unsigned int rate);
>> #endif
>> --
>> 1.7.2.3
>>
>
> Thanks.
> Minkyu Kang.
> --
> from. prom.
> www.promsoft.net
> _______________________________________________
Regards,
Hatim Ali
More information about the U-Boot
mailing list