| Submitter | Akshay Saraswat |
|---|---|
| Date | Feb. 28, 2013, 10:59 a.m. |
| Message ID | <1362049164-10297-8-git-send-email-akshay.s@samsung.com> |
| Download | mbox | patch |
| Permalink | /patch/223875/ |
| State | Changes Requested |
| Delegated to: | Minkyu Kang |
| Headers | show |
Comments
On Thu, Feb 28, 2013 at 2:59 AM, Akshay Saraswat <akshay.s@samsung.com> wrote: > Add generic api to get the frequency of the required peripherial. This > API gets the source clock frequency and returns the required frequency > by dividing with first and second dividers based on the requirement. > > Test with command "sf probe 1:0; time sf read 40008000 0 1000". > Try with different numbers of bytes and see that sane values are obtained > Build and boot U-boot with this patch, backlight works properly. > > Signed-off-by: Padmavathi Venna <padma.v@samsung.com> > Signed-off-by: Akshay Saraswat <akshay.s@samsung.com> Acked-by: Simon Glass <sjg@chromium.org> > --- > Changes since v1: > - Fixed few nits. > > arch/arm/cpu/armv7/exynos/clock.c | 138 +++++++++++++++++++++++++++++++++ > arch/arm/include/asm/arch-exynos/clk.h | 17 ++++ > 2 files changed, 155 insertions(+) >
On 28/02/13 19:59, Akshay Saraswat wrote: > Add generic api to get the frequency of the required peripherial. This typo. peripherial -> peripheral > API gets the source clock frequency and returns the required frequency > by dividing with first and second dividers based on the requirement. > > Test with command "sf probe 1:0; time sf read 40008000 0 1000". > Try with different numbers of bytes and see that sane values are obtained > Build and boot U-boot with this patch, backlight works properly. > > Signed-off-by: Padmavathi Venna <padma.v@samsung.com> > Signed-off-by: Akshay Saraswat <akshay.s@samsung.com> > --- > Changes since v1: > - Fixed few nits. > > arch/arm/cpu/armv7/exynos/clock.c | 138 +++++++++++++++++++++++++++++++++ > arch/arm/include/asm/arch-exynos/clk.h | 17 ++++ > 2 files changed, 155 insertions(+) > > diff --git a/arch/arm/cpu/armv7/exynos/clock.c b/arch/arm/cpu/armv7/exynos/clock.c > index 956427c..cc101c2 100644 > --- a/arch/arm/cpu/armv7/exynos/clock.c > +++ b/arch/arm/cpu/armv7/exynos/clock.c > @@ -27,6 +27,49 @@ > #include <asm/arch/clk.h> > #include <asm/arch/periph.h> > > +/* * > + * This structure is to store the src bit, div bit and prediv bit > + * positions of the peripheral clocks of the src and div registers > + */ > +struct clk_bit_info { > + int8_t src_bit; > + int8_t div_bit; > + int8_t prediv_bit; > +}; > + > +/* src_bit div_bit prediv_bit */ > +static struct clk_bit_info clk_bit_info[PERIPH_ID_COUNT] = { > + {0, 0, -1}, > + {4, 4, -1}, > + {8, 8, -1}, > + {12, 12, -1}, > + {0, 0, 8}, > + {4, 16, 24}, > + {8, 0, 8}, > + {12, 16, 24}, > + {-1, -1, -1}, > + {16, 0, 8}, > + {20, 16, 24}, > + {24, 0, 8}, > + {0, 0, 4}, > + {4, 12, 16}, > + {-1, -1, -1}, > + {-1, -1, -1}, > + {-1, 24, 0}, > + {-1, 24, 0}, > + {-1, 24, 0}, > + {-1, 24, 0}, > + {-1, 24, 0}, > + {-1, 24, 0}, > + {-1, 24, 0}, > + {-1, 24, 0}, > + {24, 0, -1}, > + {24, 0, -1}, > + {24, 0, -1}, > + {24, 0, -1}, > + {24, 0, -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 }, > @@ -201,6 +244,101 @@ static unsigned long exynos5_get_pll_clk(int pllreg) > return fout; > } > > +unsigned long exynos5_get_periph_rate(enum periph_id peripheral) static? please int instead of enum periph_id. > +{ > + struct clk_bit_info *bit_info = &clk_bit_info[peripheral]; > + unsigned long sclk, sub_clk; > + unsigned int src, div, sub_div; > + struct exynos5_clock *clk = > + (struct exynos5_clock *)samsung_get_base_clock(); > + > + switch (peripheral) { > + case PERIPH_ID_UART0: > + case PERIPH_ID_UART1: > + case PERIPH_ID_UART2: > + case PERIPH_ID_UART3: > + src = readl(&clk->src_peric0); > + div = readl(&clk->div_peric0); > + break; > + 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_peric3); > + break; > + case PERIPH_ID_SPI0: > + case PERIPH_ID_SPI1: > + src = readl(&clk->src_peric1); > + div = readl(&clk->div_peric1); > + break; > + case PERIPH_ID_SPI2: > + src = readl(&clk->src_peric1); > + div = readl(&clk->div_peric2); > + break; > + case PERIPH_ID_SPI3: > + case PERIPH_ID_SPI4: > + src = readl(&clk->sclk_src_isp); > + div = readl(&clk->sclk_div_isp); > + 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: > + sclk = exynos5_get_pll_clk(MPLL); > + sub_div = ((readl(&clk->div_top1) >> bit_info->div_bit) > + & 0x7) + 1; > + div = ((readl(&clk->div_top0) >> bit_info->prediv_bit) > + & 0x7) + 1; > + return (sclk / sub_div) / div; > + default: > + debug("%s: invalid peripheral %d", __func__, peripheral); > + return -1; > + }; > + > + src = (src >> bit_info->src_bit) & 0xf; please add a blank line here. > + if (src == EXYNOS_SRC_MPLL) > + sclk = exynos5_get_pll_clk(MPLL); > + else if (src == EXYNOS_SRC_EPLL) > + sclk = exynos5_get_pll_clk(EPLL); > + else if (src == EXYNOS_SRC_VPLL) > + sclk = exynos5_get_pll_clk(VPLL); > + else > + return 0; why don't you use switch..case? > + > + /* Ratio clock division for this peripheral */ > + sub_div = (div >> bit_info->div_bit) & 0xf; > + sub_clk = sclk / (sub_div + 1); > + > + /* Pre-ratio clock division for SDMMC0 and 2 */ > + if (peripheral == PERIPH_ID_SDMMC0 || peripheral == PERIPH_ID_SDMMC2) { > + div = (div >> bit_info->prediv_bit) & 0xff; > + return sub_clk / (div + 1); > + } > + > + return sub_clk; > +} > + > +unsigned long clock_get_periph_rate(enum periph_id peripheral) please int instead of enum periph_id. > +{ > + if (cpu_is_exynos5()) > + return exynos5_get_periph_rate(peripheral); > + else > + return 0; > +} > + > /* exynos4: return ARM clock frequency */ > static unsigned long exynos4_get_arm_clk(void) > { > diff --git a/arch/arm/include/asm/arch-exynos/clk.h b/arch/arm/include/asm/arch-exynos/clk.h > index 1935b0b..b72c90e 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/periph.h> I don't want got a dependency with other header file. please remove it. > + > #define APLL 0 > #define MPLL 1 > #define EPLL 2 > @@ -29,6 +31,12 @@ > #define VPLL 4 > #define BPLL 5 > > +enum pll_src_bit { > + EXYNOS_SRC_MPLL = 6, > + EXYNOS_SRC_EPLL, > + EXYNOS_SRC_VPLL, > +}; > + > unsigned long get_pll_clk(int pllreg); > unsigned long get_arm_clk(void); > unsigned long get_i2c_clk(void); > @@ -44,4 +52,13 @@ int set_i2s_clk_prescaler(unsigned int src_frq, unsigned int dst_frq); > int set_epll_clk(unsigned long rate); > int set_spi_clk(int periph_id, unsigned int rate); > > +/** > + * get the clk frequency of the required peripherial > + * > + * @param peripherial Peripherial id > + * > + * @return frequency of the peripherial clk > + */ typo. peripherial -> peripheral > +unsigned long clock_get_periph_rate(enum periph_id peripheral); Please clock_get_periph_rate(int periph_id); > + > #endif > Thanks, Minkyu Kang.
Patch
diff --git a/arch/arm/cpu/armv7/exynos/clock.c b/arch/arm/cpu/armv7/exynos/clock.c index 956427c..cc101c2 100644 --- a/arch/arm/cpu/armv7/exynos/clock.c +++ b/arch/arm/cpu/armv7/exynos/clock.c @@ -27,6 +27,49 @@ #include <asm/arch/clk.h> #include <asm/arch/periph.h> +/* * + * This structure is to store the src bit, div bit and prediv bit + * positions of the peripheral clocks of the src and div registers + */ +struct clk_bit_info { + int8_t src_bit; + int8_t div_bit; + int8_t prediv_bit; +}; + +/* src_bit div_bit prediv_bit */ +static struct clk_bit_info clk_bit_info[PERIPH_ID_COUNT] = { + {0, 0, -1}, + {4, 4, -1}, + {8, 8, -1}, + {12, 12, -1}, + {0, 0, 8}, + {4, 16, 24}, + {8, 0, 8}, + {12, 16, 24}, + {-1, -1, -1}, + {16, 0, 8}, + {20, 16, 24}, + {24, 0, 8}, + {0, 0, 4}, + {4, 12, 16}, + {-1, -1, -1}, + {-1, -1, -1}, + {-1, 24, 0}, + {-1, 24, 0}, + {-1, 24, 0}, + {-1, 24, 0}, + {-1, 24, 0}, + {-1, 24, 0}, + {-1, 24, 0}, + {-1, 24, 0}, + {24, 0, -1}, + {24, 0, -1}, + {24, 0, -1}, + {24, 0, -1}, + {24, 0, -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 }, @@ -201,6 +244,101 @@ static unsigned long exynos5_get_pll_clk(int pllreg) return fout; } +unsigned long exynos5_get_periph_rate(enum periph_id peripheral) +{ + struct clk_bit_info *bit_info = &clk_bit_info[peripheral]; + unsigned long sclk, sub_clk; + unsigned int src, div, sub_div; + struct exynos5_clock *clk = + (struct exynos5_clock *)samsung_get_base_clock(); + + switch (peripheral) { + case PERIPH_ID_UART0: + case PERIPH_ID_UART1: + case PERIPH_ID_UART2: + case PERIPH_ID_UART3: + src = readl(&clk->src_peric0); + div = readl(&clk->div_peric0); + break; + 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_peric3); + break; + case PERIPH_ID_SPI0: + case PERIPH_ID_SPI1: + src = readl(&clk->src_peric1); + div = readl(&clk->div_peric1); + break; + case PERIPH_ID_SPI2: + src = readl(&clk->src_peric1); + div = readl(&clk->div_peric2); + break; + case PERIPH_ID_SPI3: + case PERIPH_ID_SPI4: + src = readl(&clk->sclk_src_isp); + div = readl(&clk->sclk_div_isp); + 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: + sclk = exynos5_get_pll_clk(MPLL); + sub_div = ((readl(&clk->div_top1) >> bit_info->div_bit) + & 0x7) + 1; + div = ((readl(&clk->div_top0) >> bit_info->prediv_bit) + & 0x7) + 1; + return (sclk / sub_div) / div; + default: + debug("%s: invalid peripheral %d", __func__, peripheral); + return -1; + }; + + src = (src >> bit_info->src_bit) & 0xf; + if (src == EXYNOS_SRC_MPLL) + sclk = exynos5_get_pll_clk(MPLL); + else if (src == EXYNOS_SRC_EPLL) + sclk = exynos5_get_pll_clk(EPLL); + else if (src == EXYNOS_SRC_VPLL) + sclk = exynos5_get_pll_clk(VPLL); + else + return 0; + + /* Ratio clock division for this peripheral */ + sub_div = (div >> bit_info->div_bit) & 0xf; + sub_clk = sclk / (sub_div + 1); + + /* Pre-ratio clock division for SDMMC0 and 2 */ + if (peripheral == PERIPH_ID_SDMMC0 || peripheral == PERIPH_ID_SDMMC2) { + div = (div >> bit_info->prediv_bit) & 0xff; + return sub_clk / (div + 1); + } + + return sub_clk; +} + +unsigned long clock_get_periph_rate(enum periph_id peripheral) +{ + if (cpu_is_exynos5()) + return exynos5_get_periph_rate(peripheral); + else + return 0; +} + /* exynos4: return ARM clock frequency */ static unsigned long exynos4_get_arm_clk(void) { diff --git a/arch/arm/include/asm/arch-exynos/clk.h b/arch/arm/include/asm/arch-exynos/clk.h index 1935b0b..b72c90e 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/periph.h> + #define APLL 0 #define MPLL 1 #define EPLL 2 @@ -29,6 +31,12 @@ #define VPLL 4 #define BPLL 5 +enum pll_src_bit { + EXYNOS_SRC_MPLL = 6, + EXYNOS_SRC_EPLL, + EXYNOS_SRC_VPLL, +}; + unsigned long get_pll_clk(int pllreg); unsigned long get_arm_clk(void); unsigned long get_i2c_clk(void); @@ -44,4 +52,13 @@ int set_i2s_clk_prescaler(unsigned int src_frq, unsigned int dst_frq); int set_epll_clk(unsigned long rate); int set_spi_clk(int periph_id, unsigned int rate); +/** + * get the clk frequency of the required peripherial + * + * @param peripherial Peripherial id + * + * @return frequency of the peripherial clk + */ +unsigned long clock_get_periph_rate(enum periph_id peripheral); + #endif