Skip to content

Commit

Permalink
blackfin: bf60x: make clock changeable in kernel menuconfig
Browse files Browse the repository at this point in the history
Add clock changeable support in kernel menuconfig for bf60x.

Signed-off-by: Bob Liu <[email protected]>
  • Loading branch information
aet00 committed May 21, 2012
1 parent 1c40093 commit 7c141c1
Show file tree
Hide file tree
Showing 5 changed files with 197 additions and 29 deletions.
45 changes: 40 additions & 5 deletions arch/blackfin/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -589,13 +622,15 @@ 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
default 50000000

config MAX_SCLK_HZ
int
default 200000000 if BF609
default 133333333

config MIN_SCLK_HZ
Expand Down
2 changes: 1 addition & 1 deletion arch/blackfin/include/asm/bfin-global.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
24 changes: 5 additions & 19 deletions arch/blackfin/kernel/setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand Down Expand Up @@ -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");
Expand Down Expand Up @@ -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();

Expand Down
2 changes: 1 addition & 1 deletion arch/blackfin/mach-bf609/clock.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
};

Expand Down
153 changes: 150 additions & 3 deletions arch/blackfin/mach-common/clocks-init.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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];
Expand Down Expand Up @@ -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
}

0 comments on commit 7c141c1

Please sign in to comment.