exynos5420: re-factor clock_get_periph_rate()
This re-factors clock_get_periph_rate() to be a simpler and also make a few corrections along the way. To summarize: - clk_bit_info is no longer used. It had numerous errors and was really painful anyway since it was just a bunch of opaque magic numbers that made bugs non-obvious. - Clock source bitfields for peripherals handled in the switch statement are 3 bits, not 4. Some divider values are 3 bits, some are 4. The earlier code always assumed 4 bits for both which included reserved bits in many cases. - UART source clock and divider shift values were wrong. - PWM clock divider was being read from the wrong register. - SPI3 divider value was being read from the wrong register. - There was a really confusing calculation for SDMMC0 and SDMMC2 clock rates, but it was never actually used since the switch statement never handled PERIPH_ID_SDMMC{0,2} and would thus return if they were ever passed into this function. Signed-off-by: David Hendricks <dhendrix@chromium.org> Change-Id: I0a03a64d8b42fbe83dbf377292597ce681b22f4b Reviewed-on: https://gerrit.chromium.org/gerrit/65284 Commit-Queue: David Hendricks <dhendrix@chromium.org> Tested-by: David Hendricks <dhendrix@chromium.org> Reviewed-by: Gabe Black <gabeblack@chromium.org> Reviewed-on: http://review.coreboot.org/4463 Tested-by: build bot (Jenkins) Reviewed-by: Patrick Georgi <patrick@georgi-clan.de>
This commit is contained in:
parent
efd4b9e936
commit
401da25827
|
@ -38,16 +38,6 @@ enum periph_id;
|
||||||
#define DPLL 9
|
#define DPLL 9
|
||||||
#define IPLL 10
|
#define IPLL 10
|
||||||
|
|
||||||
/* *
|
|
||||||
* 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 {
|
|
||||||
s8 src_bit; /* offset in register to clock source field */
|
|
||||||
s8 div_bit;
|
|
||||||
s8 prediv_bit;
|
|
||||||
};
|
|
||||||
|
|
||||||
unsigned long get_pll_clk(int pllreg);
|
unsigned long get_pll_clk(int pllreg);
|
||||||
unsigned long get_arm_clk(void);
|
unsigned long get_arm_clk(void);
|
||||||
unsigned long get_pwm_clk(void);
|
unsigned long get_pwm_clk(void);
|
||||||
|
|
|
@ -29,32 +29,6 @@
|
||||||
/* input clock of PLL: SMDK5420 has 24MHz input clock */
|
/* input clock of PLL: SMDK5420 has 24MHz input clock */
|
||||||
#define CONFIG_SYS_CLK_FREQ 24000000
|
#define CONFIG_SYS_CLK_FREQ 24000000
|
||||||
|
|
||||||
/* 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}, /* PERIPH_ID_SROMC */
|
|
||||||
{20, 20, 24},
|
|
||||||
{24, 24, 8},
|
|
||||||
{28, 28, 4},
|
|
||||||
{4, 12, 16},
|
|
||||||
{-1, -1, -1},
|
|
||||||
{-1, -1, -1},
|
|
||||||
[PERIPH_ID_DPHPD]
|
|
||||||
{24, 0, -1},
|
|
||||||
{24, 0, -1},
|
|
||||||
{24, 0, -1},
|
|
||||||
{24, 0, -1},
|
|
||||||
{24, 0, -1},
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Epll Clock division values to achive different frequency output */
|
/* Epll Clock division values to achive different frequency output */
|
||||||
static struct st_epll_con_val epll_div[] = {
|
static struct st_epll_con_val epll_div[] = {
|
||||||
{ 192000000, 0, 48, 3, 1, 0 },
|
{ 192000000, 0, 48, 3, 1, 0 },
|
||||||
|
@ -197,37 +171,54 @@ static int clock_select_to_pll(enum peripheral_clock_select sel)
|
||||||
|
|
||||||
unsigned long clock_get_periph_rate(enum periph_id peripheral)
|
unsigned long clock_get_periph_rate(enum periph_id peripheral)
|
||||||
{
|
{
|
||||||
struct clk_bit_info *bit_info = &clk_bit_info[peripheral];
|
unsigned long sclk;
|
||||||
unsigned long sclk, sub_clk;
|
unsigned int src, div;
|
||||||
unsigned int src, div, sub_div;
|
|
||||||
struct exynos5420_clock *clk = samsung_get_base_clock();
|
struct exynos5420_clock *clk = samsung_get_base_clock();
|
||||||
|
|
||||||
switch (peripheral) {
|
switch (peripheral) {
|
||||||
case PERIPH_ID_UART0:
|
case PERIPH_ID_UART0:
|
||||||
|
src = (readl(&clk->clk_src_peric0) >> 4) & 0x7;
|
||||||
|
div = (readl(&clk->clk_div_peric0) >> 8) & 0xf;
|
||||||
|
break;
|
||||||
case PERIPH_ID_UART1:
|
case PERIPH_ID_UART1:
|
||||||
|
src = (readl(&clk->clk_src_peric0) >> 8) & 0x7;
|
||||||
|
div = (readl(&clk->clk_div_peric0) >> 12) & 0xf;
|
||||||
|
break;
|
||||||
case PERIPH_ID_UART2:
|
case PERIPH_ID_UART2:
|
||||||
|
src = (readl(&clk->clk_src_peric0) >> 12) & 0x7;
|
||||||
|
div = (readl(&clk->clk_div_peric0) >> 16) & 0xf;
|
||||||
|
break;
|
||||||
case PERIPH_ID_UART3:
|
case PERIPH_ID_UART3:
|
||||||
src = readl(&clk->clk_src_peric0);
|
src = (readl(&clk->clk_src_peric0) >> 16) & 0x7;
|
||||||
div = readl(&clk->clk_div_peric0);
|
div = (readl(&clk->clk_div_peric0) >> 20) & 0xf;
|
||||||
break;
|
break;
|
||||||
case PERIPH_ID_PWM0:
|
case PERIPH_ID_PWM0:
|
||||||
case PERIPH_ID_PWM1:
|
case PERIPH_ID_PWM1:
|
||||||
case PERIPH_ID_PWM2:
|
case PERIPH_ID_PWM2:
|
||||||
case PERIPH_ID_PWM3:
|
case PERIPH_ID_PWM3:
|
||||||
case PERIPH_ID_PWM4:
|
case PERIPH_ID_PWM4:
|
||||||
src = readl(&clk->clk_src_peric0);
|
src = (readl(&clk->clk_src_peric0) >> 24) & 0x7;
|
||||||
div = readl(&clk->clk_div_peric3);
|
div = (readl(&clk->clk_div_peric0) >> 28) & 0x7;
|
||||||
break;
|
break;
|
||||||
case PERIPH_ID_SPI0:
|
case PERIPH_ID_SPI0:
|
||||||
case PERIPH_ID_SPI1:
|
src = (readl(&clk->clk_src_peric1) >> 20) & 0x7;
|
||||||
case PERIPH_ID_SPI2:
|
div = (readl(&clk->clk_div_peric1) >> 20) & 0xf;
|
||||||
src = readl(&clk->clk_src_peric1);
|
|
||||||
div = readl(&clk->clk_div_peric1);
|
|
||||||
break;
|
break;
|
||||||
case PERIPH_ID_SPI3:
|
case PERIPH_ID_SPI1:
|
||||||
case PERIPH_ID_SPI4:
|
src = (readl(&clk->clk_src_peric1) >> 24) & 0x7;
|
||||||
src = readl(&clk->clk_src_isp);
|
div = (readl(&clk->clk_div_peric1) >> 24) & 0xf;
|
||||||
div = readl(&clk->clk_div_isp1);
|
break;
|
||||||
|
case PERIPH_ID_SPI2:
|
||||||
|
src = (readl(&clk->clk_src_peric1) >> 28) & 0x7;
|
||||||
|
div = (readl(&clk->clk_div_peric1) >> 28) & 0xf;
|
||||||
|
break;
|
||||||
|
case PERIPH_ID_SPI3: /* aka SPI0_ISP */
|
||||||
|
src = (readl(&clk->clk_src_isp) >> 16) & 0x7;
|
||||||
|
div = (readl(&clk->clk_div_isp0) >> 0) & 0x7;
|
||||||
|
break;
|
||||||
|
case PERIPH_ID_SPI4: /* aka SPI1_ISP */
|
||||||
|
src = (readl(&clk->clk_src_isp) >> 12) & 0x7;
|
||||||
|
div = (readl(&clk->clk_div_isp1) >> 4) & 0x7;
|
||||||
break;
|
break;
|
||||||
case PERIPH_ID_I2C0:
|
case PERIPH_ID_I2C0:
|
||||||
case PERIPH_ID_I2C1:
|
case PERIPH_ID_I2C1:
|
||||||
|
@ -244,12 +235,11 @@ unsigned long clock_get_periph_rate(enum periph_id peripheral)
|
||||||
div = ((readl(&clk->clk_div_top1) >> 8) & 0x3f) + 1;
|
div = ((readl(&clk->clk_div_top1) >> 8) & 0x3f) + 1;
|
||||||
return sclk / div;
|
return sclk / div;
|
||||||
default:
|
default:
|
||||||
printk(BIOS_DEBUG, "%s: invalid peripheral %d", __func__, peripheral);
|
printk(BIOS_DEBUG, "%s: invalid peripheral %d",
|
||||||
|
__func__, peripheral);
|
||||||
return -1;
|
return -1;
|
||||||
};
|
};
|
||||||
|
|
||||||
src = (src >> bit_info->src_bit) & 0xf;
|
|
||||||
|
|
||||||
src = clock_select_to_pll(src);
|
src = clock_select_to_pll(src);
|
||||||
if (src < 0) {
|
if (src < 0) {
|
||||||
printk(BIOS_DEBUG, "%s: cannot determine source PLL", __func__);
|
printk(BIOS_DEBUG, "%s: cannot determine source PLL", __func__);
|
||||||
|
@ -258,17 +248,7 @@ unsigned long clock_get_periph_rate(enum periph_id peripheral)
|
||||||
|
|
||||||
sclk = get_pll_clk(src);
|
sclk = get_pll_clk(src);
|
||||||
|
|
||||||
/* Ratio clock division for this peripheral */
|
return sclk / (div + 1);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* exynos5: return ARM clock frequency */
|
/* exynos5: return ARM clock frequency */
|
||||||
|
|
Loading…
Reference in New Issue