9
0
Fork 0
barebox/arch/arm/mach-samsung/clocks-s3c24xx.c

158 lines
3.6 KiB
C

/*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <config.h>
#include <common.h>
#include <init.h>
#include <clock.h>
#include <io.h>
#include <mach/s3c-iomap.h>
#include <mach/s3c-generic.h>
#include <mach/s3c-clocks.h>
#include <mach/s3c-busctl.h>
/**
* Calculate the current M-PLL clock.
* @return Current frequency in Hz
*/
uint32_t s3c_get_mpllclk(void)
{
uint32_t m, p, s, reg_val;
reg_val = readl(S3C_MPLLCON);
m = ((reg_val & 0xFF000) >> 12) + 8;
p = ((reg_val & 0x003F0) >> 4) + 2;
s = reg_val & 0x3;
#ifdef CONFIG_CPU_S3C2410
return (S3C24XX_CLOCK_REFERENCE * m) / (p << s);
#endif
#ifdef CONFIG_CPU_S3C2440
return 2 * m * (S3C24XX_CLOCK_REFERENCE / (p << s));
#endif
}
/**
* Calculate the current U-PLL clock
* @return Current frequency in Hz
*/
uint32_t s3c_get_upllclk(void)
{
uint32_t m, p, s, reg_val;
reg_val = readl(S3C_UPLLCON);
m = ((reg_val & 0xFF000) >> 12) + 8;
p = ((reg_val & 0x003F0) >> 4) + 2;
s = reg_val & 0x3;
return (S3C24XX_CLOCK_REFERENCE * m) / (p << s);
}
/**
* Calculate the FCLK frequency used for the ARM CPU core
* @return Current frequency in Hz
*/
uint32_t s3c_get_fclk(void)
{
return s3c_get_mpllclk();
}
/**
* Calculate the HCLK frequency used for the AHB bus (CPU to main peripheral)
* @return Current frequency in Hz
*/
uint32_t s3c_get_hclk(void)
{
uint32_t f_clk;
f_clk = s3c_get_fclk();
#ifdef CONFIG_CPU_S3C2410
if (readl(S3C_CLKDIVN) & 0x02)
return f_clk >> 1;
#endif
#ifdef CONFIG_CPU_S3C2440
switch(readl(S3C_CLKDIVN) & 0x06) {
case 2:
return f_clk >> 1;
case 4:
return f_clk >> 2; /* TODO consider CAMDIVN */
case 6:
return f_clk / 3; /* TODO consider CAMDIVN */
}
#endif
return f_clk;
}
/**
* Calculate the PCLK frequency used for the slower peripherals
* @return Current frequency in Hz
*/
uint32_t s3c_get_pclk(void)
{
uint32_t p_clk;
p_clk = s3c_get_hclk();
if (readl(S3C_CLKDIVN) & 0x01)
return p_clk >> 1;
return p_clk;
}
/**
* Calculate the UCLK frequency used by the USB host device
* @return Current frequency in Hz
*/
uint32_t s3c24_get_uclk(void)
{
return s3c_get_upllclk();
}
/**
* Return correct UART frequency based on the UCON register
*/
unsigned s3c_get_uart_clk(unsigned src)
{
switch (src & 3) {
case 0:
case 2:
return s3c_get_pclk();
case 1:
return 0; /* TODO UEXTCLK */
case 3:
return 0; /* TODO FCLK/n */
}
return 0; /* not reached, to make compiler happy */
}
/**
* Show the user the current clock settings
*/
int s3c24xx_dump_clocks(void)
{
printf("refclk: %7d kHz\n", S3C24XX_CLOCK_REFERENCE / 1000);
printf("mpll: %7d kHz\n", s3c_get_mpllclk() / 1000);
printf("upll: %7d kHz\n", s3c_get_upllclk() / 1000);
printf("fclk: %7d kHz\n", s3c_get_fclk() / 1000);
printf("hclk: %7d kHz\n", s3c_get_hclk() / 1000);
printf("pclk: %7d kHz\n", s3c_get_pclk() / 1000);
printf("SDRAM1: CL%d@%dMHz\n", ((readl(S3C_BANKCON6) & 0xc) >> 2) + 2,
s3c_get_hclk() / 1000000);
if ((readl(S3C_BANKCON7) & (0x3 << 15)) == (0x3 << 15))
printf("SDRAM2: CL%d@%dMHz\n",
((readl(S3C_BANKCON7) & 0xc) >> 2) + 2,
s3c_get_hclk() / 1000000);
return 0;
}
late_initcall(s3c24xx_dump_clocks);