blackfin: bf60x: make clock changeable in kernel menuconfig

Add clock changeable support in kernel menuconfig for bf60x.

Signed-off-by: Bob Liu <lliubbo@gmail.com>
This commit is contained in:
Bob Liu 2012-05-17 17:15:40 +08:00
parent 1c40093976
commit 7c141c1c5c
5 changed files with 197 additions and 29 deletions

View file

@ -435,7 +435,7 @@ config BFIN_KERNEL_CLOCK
config PLL_BYPASS
bool "Bypass PLL"
depends on BFIN_KERNEL_CLOCK
depends on BFIN_KERNEL_CLOCK && (!BF60x)
default n
config CLKIN_HALF
@ -454,7 +454,7 @@ config VCO_MULT
default "20" if (BFIN537_STAMP || BFIN527_EZKIT || BFIN527_EZKIT_V2 || BFIN548_EZKIT || BFIN548_BLUETECHNIX_CM || BFIN538_EZKIT)
default "22" if BFIN533_BLUETECHNIX_CM
default "20" if (BFIN537_BLUETECHNIX_CM_E || BFIN537_BLUETECHNIX_CM_U || BFIN527_BLUETECHNIX_CM || BFIN561_BLUETECHNIX_CM)
default "20" if BFIN561_EZKIT
default "20" if (BFIN561_EZKIT || BF609)
default "16" if (H8606_HVSISTEMAS || BLACKSTAMP || BFIN526_EZBRD || BFIN518F_EZBRD)
default "25" if BFIN527_AD7160EVAL
help
@ -486,12 +486,45 @@ config SCLK_DIV
int "System Clock Divider"
depends on BFIN_KERNEL_CLOCK
range 1 15
default 5
default 4
help
This sets the frequency of the system clock (including SDRAM or DDR).
This sets the frequency of the system clock (including SDRAM or DDR) on
!BF60x else it set the clock for system buses and provides the
source from which SCLK0 and SCLK1 are derived.
This can be between 1 and 15
System Clock = (PLL frequency) / (this setting)
config SCLK0_DIV
int "System Clock0 Divider"
depends on BFIN_KERNEL_CLOCK && BF60x
range 1 15
default 1
help
This sets the frequency of the system clock0 for PVP and all other
peripherals not clocked by SCLK1.
This can be between 1 and 15
System Clock0 = (System Clock) / (this setting)
config SCLK1_DIV
int "System Clock1 Divider"
depends on BFIN_KERNEL_CLOCK && BF60x
range 1 15
default 1
help
This sets the frequency of the system clock1 (including SPORT, SPI and ACM).
This can be between 1 and 15
System Clock1 = (System Clock) / (this setting)
config DCLK_DIV
int "DDR Clock Divider"
depends on BFIN_KERNEL_CLOCK && BF60x
range 1 15
default 2
help
This sets the frequency of the DDR memory.
This can be between 1 and 15
DDR Clock = (PLL frequency) / (this setting)
choice
prompt "DDR SDRAM Chip Type"
depends on BFIN_KERNEL_CLOCK
@ -507,7 +540,7 @@ endchoice
choice
prompt "DDR/SDRAM Timing"
depends on BFIN_KERNEL_CLOCK
depends on BFIN_KERNEL_CLOCK && !BF60x
default BFIN_KERNEL_CLOCK_MEMINIT_CALC
help
This option allows you to specify Blackfin SDRAM/DDR Timing parameters
@ -589,6 +622,7 @@ config MAX_VCO_HZ
default 600000000 if BF548
default 533333333 if BF549
default 600000000 if BF561
default 800000000 if BF609
config MIN_VCO_HZ
int
@ -596,6 +630,7 @@ config MIN_VCO_HZ
config MAX_SCLK_HZ
int
default 200000000 if BF609
default 133333333
config MIN_SCLK_HZ

View file

@ -38,7 +38,7 @@ extern unsigned long get_sclk(void);
#ifdef CONFIG_BF60x
extern unsigned long get_sclk0(void);
extern unsigned long get_sclk1(void);
extern unsigned long get_dramclk(void);
extern unsigned long get_dclk(void);
#endif
extern unsigned long sclk_to_usecs(unsigned long sclk);
extern unsigned long usecs_to_sclk(unsigned long usecs);

View file

@ -892,9 +892,6 @@ void __init setup_arch(char **cmdline_p)
{
u32 mmr;
unsigned long sclk, cclk;
#ifdef CONFIG_BF60x
struct clk *clk;
#endif
native_machine_early_platform_add_devices();
@ -959,24 +956,8 @@ void __init setup_arch(char **cmdline_p)
~HYST_NONEGPIO_MASK) | HYST_NONEGPIO);
#endif
#ifdef CONFIG_BF60x
clk = clk_get(NULL, "CCLK");
if (!IS_ERR(clk)) {
cclk = clk_get_rate(clk);
clk_put(clk);
} else
cclk = 0;
clk = clk_get(NULL, "SCLK0");
if (!IS_ERR(clk)) {
sclk = clk_get_rate(clk);
clk_put(clk);
} else
sclk = 0;
#else
cclk = get_cclk();
sclk = get_sclk();
#endif
if ((ANOMALY_05000273 || ANOMALY_05000274) && (cclk >> 1) < sclk)
panic("ANOMALY 05000273 or 05000274: CCLK must be >= 2*SCLK");
@ -1062,8 +1043,13 @@ void __init setup_arch(char **cmdline_p)
printk(KERN_INFO "Blackfin Linux support by http://blackfin.uclinux.org/\n");
#ifdef CONFIG_BF60x
printk(KERN_INFO "Processor Speed: %lu MHz core clock, %lu MHz SCLk, %lu MHz SCLK0, %lu MHz SCLK1 and %lu MHz DCLK\n",
cclk / 1000000, sclk / 1000000, get_sclk0() / 1000000, get_sclk1() / 1000000, get_dclk() / 1000000);
#else
printk(KERN_INFO "Processor Speed: %lu MHz core clock and %lu MHz System Clock\n",
cclk / 1000000, sclk / 1000000);
#endif
setup_bootmem_allocator();

View file

@ -351,7 +351,7 @@ static struct clk dclk = {
.rate = 500000000,
.mask = CGU0_DIV_DSEL_MASK,
.shift = CGU0_DIV_DSEL_SHIFT,
.parent = &pll_clk,
.parent = &sys_clkin,
.ops = &sys_clk_ops,
};

View file

@ -15,10 +15,121 @@
#include <asm/mem_init.h>
#include <asm/dpmc.h>
#ifdef CONFIG_BF60x
#define CSEL_P 0
#define S0SEL_P 5
#define SYSSEL_P 8
#define S1SEL_P 13
#define DSEL_P 16
#define OSEL_P 22
#define ALGN_P 29
#define UPDT_P 30
#define LOCK_P 31
#define CGU_CTL_VAL ((CONFIG_VCO_MULT << 8) | CLKIN_HALF)
#define CGU_DIV_VAL \
((CONFIG_CCLK_DIV << CSEL_P) | \
(CONFIG_SCLK_DIV << SYSSEL_P) | \
(CONFIG_SCLK0_DIV << S0SEL_P) | \
(CONFIG_SCLK1_DIV << S1SEL_P) | \
(CONFIG_DCLK_DIV << DSEL_P))
#define CONFIG_BFIN_DCLK (((CONFIG_CLKIN_HZ * CONFIG_VCO_MULT) / CONFIG_DCLK_DIV) / 1000000)
#if ((CONFIG_BFIN_DCLK != 125) && \
(CONFIG_BFIN_DCLK != 133) && (CONFIG_BFIN_DCLK != 150) && \
(CONFIG_BFIN_DCLK != 166) && (CONFIG_BFIN_DCLK != 200) && \
(CONFIG_BFIN_DCLK != 225) && (CONFIG_BFIN_DCLK != 250))
#error "DCLK must be in (125, 133, 150, 166, 200, 225, 250)MHz"
#endif
struct ddr_config {
u32 ddr_clk;
u32 dmc_ddrctl;
u32 dmc_ddrcfg;
u32 dmc_ddrtr0;
u32 dmc_ddrtr1;
u32 dmc_ddrtr2;
u32 dmc_ddrmr;
u32 dmc_ddrmr1;
};
struct ddr_config ddr_config_table[] __attribute__((section(".data_l1"))) = {
[0] = {
.ddr_clk = 125,
.dmc_ddrctl = 0x00000904,
.dmc_ddrcfg = 0x00000422,
.dmc_ddrtr0 = 0x20705212,
.dmc_ddrtr1 = 0x201003CF,
.dmc_ddrtr2 = 0x00320107,
.dmc_ddrmr = 0x00000422,
.dmc_ddrmr1 = 0x4,
},
[1] = {
.ddr_clk = 133,
.dmc_ddrctl = 0x00000904,
.dmc_ddrcfg = 0x00000422,
.dmc_ddrtr0 = 0x20806313,
.dmc_ddrtr1 = 0x2013040D,
.dmc_ddrtr2 = 0x00320108,
.dmc_ddrmr = 0x00000632,
.dmc_ddrmr1 = 0x4,
},
[2] = {
.ddr_clk = 150,
.dmc_ddrctl = 0x00000904,
.dmc_ddrcfg = 0x00000422,
.dmc_ddrtr0 = 0x20A07323,
.dmc_ddrtr1 = 0x20160492,
.dmc_ddrtr2 = 0x00320209,
.dmc_ddrmr = 0x00000632,
.dmc_ddrmr1 = 0x4,
},
[3] = {
.ddr_clk = 166,
.dmc_ddrctl = 0x00000904,
.dmc_ddrcfg = 0x00000422,
.dmc_ddrtr0 = 0x20A07323,
.dmc_ddrtr1 = 0x2016050E,
.dmc_ddrtr2 = 0x00320209,
.dmc_ddrmr = 0x00000632,
.dmc_ddrmr1 = 0x4,
},
[4] = {
.ddr_clk = 200,
.dmc_ddrctl = 0x00000904,
.dmc_ddrcfg = 0x00000422,
.dmc_ddrtr0 = 0x20a07323,
.dmc_ddrtr1 = 0x2016050f,
.dmc_ddrtr2 = 0x00320509,
.dmc_ddrmr = 0x00000632,
.dmc_ddrmr1 = 0x4,
},
[5] = {
.ddr_clk = 225,
.dmc_ddrctl = 0x00000904,
.dmc_ddrcfg = 0x00000422,
.dmc_ddrtr0 = 0x20E0A424,
.dmc_ddrtr1 = 0x302006DB,
.dmc_ddrtr2 = 0x0032020D,
.dmc_ddrmr = 0x00000842,
.dmc_ddrmr1 = 0x4,
},
[6] = {
.ddr_clk = 250,
.dmc_ddrctl = 0x00000904,
.dmc_ddrcfg = 0x00000422,
.dmc_ddrtr0 = 0x20E0A424,
.dmc_ddrtr1 = 0x3020079E,
.dmc_ddrtr2 = 0x0032020D,
.dmc_ddrmr = 0x00000842,
.dmc_ddrmr1 = 0x4,
},
};
#else
#define SDGCTL_WIDTH (1 << 31) /* SDRAM external data path width */
#define PLL_CTL_VAL \
(((CONFIG_VCO_MULT & 63) << 9) | CLKIN_HALF | \
(PLL_BYPASS << 8) | (ANOMALY_05000305 ? 0 : 0x8000))
(PLL_BYPASS << 8) | (ANOMALY_05000305 ? 0 : 0x8000))
#endif
__attribute__((l1_text))
static void do_sync(void)
@ -34,7 +145,43 @@ void init_clocks(void)
* For example, any automatic DMAs left by U-Boot for splash screens.
*/
#if 0
#ifdef CONFIG_BF60x
int i, dlldatacycle, dll_ctl;
bfin_write32(CGU0_DIV, CGU_DIV_VAL);
bfin_write32(CGU0_CTL, CGU_CTL_VAL);
while ((bfin_read32(CGU0_STAT) & 0x8) || !(bfin_read32(CGU0_STAT) & 0x4))
continue;
bfin_write32(CGU0_DIV, CGU_DIV_VAL | (1 << UPDT_P));
while (bfin_read32(CGU0_STAT) & (1 << 3))
continue;
for (i = 0; i < 7; i++) {
if (ddr_config_table[i].ddr_clk == CONFIG_BFIN_DCLK) {
bfin_write_DDR0_CFG(ddr_config_table[i].dmc_ddrcfg);
bfin_write_DDR0_TR0(ddr_config_table[i].dmc_ddrtr0);
bfin_write_DDR0_TR1(ddr_config_table[i].dmc_ddrtr1);
bfin_write_DDR0_TR2(ddr_config_table[i].dmc_ddrtr2);
bfin_write_DDR0_MR(ddr_config_table[i].dmc_ddrmr);
bfin_write_DDR0_EMR1(ddr_config_table[i].dmc_ddrmr1);
bfin_write_DDR0_CTL(ddr_config_table[i].dmc_ddrctl);
break;
}
}
do_sync();
while (!(bfin_read_DDR0_STAT() & 0x4))
continue;
dlldatacycle = (bfin_read_DDR0_STAT() & 0x00f00000) >> 20;
dll_ctl = bfin_read_DDR0_DLLCTL();
dll_ctl &= 0x0ff;
bfin_write_DDR0_DLLCTL(dll_ctl | (dlldatacycle << 8));
do_sync();
while (!(bfin_read_DDR0_STAT() & 0x2000))
continue;
#else
size_t i;
for (i = 0; i < MAX_DMA_CHANNELS; ++i) {
struct dma_register *dma = dma_io_base_addr[i];
@ -92,9 +239,9 @@ void init_clocks(void)
#ifdef CONFIG_MEM_EBIU_DDRQUE
bfin_write_EBIU_DDRQUE(CONFIG_MEM_EBIU_DDRQUE);
#endif
#endif
#endif
do_sync();
bfin_read16(0);
#endif
}