From 9260a56151e9aed923e61994b4c368297690a78e Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Wed, 11 Jan 2006 11:12:57 -0600 Subject: Make System IO Config Registers board configurable on MPC83xx Patch by Kumar Gala, 11 Jan 2006 --- cpu/mpc83xx/cpu_init.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'cpu') diff --git a/cpu/mpc83xx/cpu_init.c b/cpu/mpc83xx/cpu_init.c index dcb34457b10..e75b8b7fde1 100644 --- a/cpu/mpc83xx/cpu_init.c +++ b/cpu/mpc83xx/cpu_init.c @@ -63,8 +63,12 @@ void cpu_init_f (volatile immap_t * im) im->sysconf.spcr |= SPCR_TBEN; /* System General Purpose Register */ - im->sysconf.sicrh = SICRH_TSOBI1; - im->sysconf.sicrl = SICRL_LDP_A; +#ifdef CFG_SICRH + im->sysconf.sicrh = CFG_SICRH; +#endif +#ifdef CFG_SICRL + im->sysconf.sicrl = CFG_SICRL; +#endif /* * Memory Controller: -- cgit v1.2.3 From ce574ff5060b63b1bad143d84f0c386892d3243f Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Wed, 11 Jan 2006 11:19:12 -0600 Subject: Enable time handling on 83xx Patch by Kumar Gala, 11 Jan 2006 --- cpu/mpc83xx/interrupts.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'cpu') diff --git a/cpu/mpc83xx/interrupts.c b/cpu/mpc83xx/interrupts.c index 53474f60c91..dfd51c15fe0 100644 --- a/cpu/mpc83xx/interrupts.c +++ b/cpu/mpc83xx/interrupts.c @@ -43,6 +43,16 @@ struct irq_action { int interrupt_init_cpu (unsigned *decrementer_count) { + DECLARE_GLOBAL_DATA_PTR; + + volatile immap_t *immr = (immap_t *) CFG_IMMRBAR; + + *decrementer_count = (gd->bus_clk / 4) / CFG_HZ; + + /* Enable e300 time base */ + + immr->sysconf.spcr |= 0x00400000; + return 0; } -- cgit v1.2.3 From a15b44dbfa2e4537b231da066b589992b0ee629d Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Wed, 11 Jan 2006 11:21:14 -0600 Subject: Allow config of GPIO direction & data registers at boot on 83xx Patch by Kumar Gala, 11 Jan 2006 --- cpu/mpc83xx/cpu_init.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'cpu') diff --git a/cpu/mpc83xx/cpu_init.c b/cpu/mpc83xx/cpu_init.c index e75b8b7fde1..db28a6a31a8 100644 --- a/cpu/mpc83xx/cpu_init.c +++ b/cpu/mpc83xx/cpu_init.c @@ -154,6 +154,14 @@ void cpu_init_f (volatile immap_t * im) im->sysconf.lblaw[7].bar = CFG_LBLAWBAR7_PRELIM; im->sysconf.lblaw[7].ar = CFG_LBLAWAR7_PRELIM; #endif +#ifdef CFG_GPIO1_PRELIM + im->pgio[0].dir = CFG_GPIO1_DIR; + im->pgio[0].dat = CFG_GPIO1_DAT; +#endif +#ifdef CFG_GPIO2_PRELIM + im->pgio[1].dir = CFG_GPIO2_DIR; + im->pgio[1].dat = CFG_GPIO2_DAT; +#endif } -- cgit v1.2.3 From ec00c335789aea61ec13f41356805c690f059572 Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Wed, 11 Jan 2006 11:23:01 -0600 Subject: Only disable the MPC83xx watchdog if its enabled out of reset. If its disabled out of reset SW can later enable it if so desired Patch by Kumar Gala, 11 Jan 2006 --- cpu/mpc83xx/start.S | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'cpu') diff --git a/cpu/mpc83xx/start.S b/cpu/mpc83xx/start.S index fb001a654c5..0e1a5fd5726 100644 --- a/cpu/mpc83xx/start.S +++ b/cpu/mpc83xx/start.S @@ -426,8 +426,14 @@ init_e300_core: /* time t 10 */ #else /* Disable Wathcdog */ /*-------------------*/ + lwz r4, SWCRR(r3) + /* Check to see if its enabled for disabling + once disabled by SW you can't re-enable */ + andi. r4, r4, 0x4 + beq 1f xor r4, r4, r4 stw r4, SWCRR(r3) +1: #endif /* CONFIG_WATCHDOG */ /* Initialize the Hardware Implementation-dependent Registers */ -- cgit v1.2.3 From 62ec6418d417b1fc887f979441c15fbd6602edc9 Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Wed, 11 Jan 2006 16:48:10 -0600 Subject: Add helper function for generic flat device tree fixups for mpc83xx Patch by Kumar Gala 11 Jan 2006 --- cpu/mpc83xx/cpu.c | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) (limited to 'cpu') diff --git a/cpu/mpc83xx/cpu.c b/cpu/mpc83xx/cpu.c index 8c9b515fa5c..e49e4fe0ee4 100644 --- a/cpu/mpc83xx/cpu.c +++ b/cpu/mpc83xx/cpu.c @@ -35,6 +35,7 @@ #include #include #include +#include #include @@ -151,3 +152,40 @@ void watchdog_reset (void) hang(); /* FIXME: implement watchdog_reset()? */ } #endif /* CONFIG_WATCHDOG */ + +#if defined(CONFIG_OF_FLAT_TREE) +void +ft_cpu_setup(void *blob, bd_t *bd) +{ + u32 *p; + int len; + ulong clock; + + clock = bd->bi_busfreq; + p = ft_get_prop(blob, "/cpus/" OF_CPU "/bus-frequency", &len); + if (p != NULL) + *p = cpu_to_be32(clock); + + p = ft_get_prop(blob, "/" OF_SOC "/bus-frequency", &len); + if (p != NULL) + *p = cpu_to_be32(clock); + + p = ft_get_prop(blob, "/" OF_SOC "/serial@4500/clock-frequency", &len); + if (p != NULL) + *p = cpu_to_be32(clock); + + p = ft_get_prop(blob, "/" OF_SOC "/serial@4600/clock-frequency", &len); + if (p != NULL) + *p = cpu_to_be32(clock); + +#ifdef CONFIG_MPC83XX_TSEC1 + p = ft_get_prop(blob, "/" OF_SOC "/ethernet@24000/address", &len); + memcpy(p, bd->bi_enetaddr, 6); +#endif + +#ifdef CONFIG_MPC83XX_TSEC2 + p = ft_get_prop(blob, "/" OF_SOC "/ethernet@25000/address", &len); + memcpy(p, bd->bi_enet1addr, 6); +#endif +} +#endif -- cgit v1.2.3 From c99f384dce49b0c35ddf61eb5e0cde9fbab51a3b Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Wed, 25 Jan 2006 16:12:46 -0600 Subject: Decopuled setting of OR/BR and LBLAWBAR/LBLAWAR on MPC83xx Patch by Kumar Gala, 25 Jan 2006 --- cpu/mpc83xx/cpu_init.c | 49 +++++++++++++++++++++---------------------------- 1 file changed, 21 insertions(+), 28 deletions(-) (limited to 'cpu') diff --git a/cpu/mpc83xx/cpu_init.c b/cpu/mpc83xx/cpu_init.c index db28a6a31a8..acf6862990f 100644 --- a/cpu/mpc83xx/cpu_init.c +++ b/cpu/mpc83xx/cpu_init.c @@ -91,66 +91,59 @@ void cpu_init_f (volatile immap_t * im) #error CFG_BR0_PRELIM, CFG_OR0_PRELIM, CFG_LBLAWBAR0_PRELIM & CFG_LBLAWAR0_PRELIM must be defined #endif -#if defined(CFG_BR1_PRELIM) \ - && defined(CFG_OR1_PRELIM) \ - && defined(CFG_LBLAWBAR1_PRELIM) \ - && defined(CFG_LBLAWAR1_PRELIM) +#if defined(CFG_BR1_PRELIM) && defined(CFG_OR1_PRELIM) im->lbus.bank[1].br = CFG_BR1_PRELIM; im->lbus.bank[1].or = CFG_OR1_PRELIM; +#endif +#if defined(CFG_LBLAWBAR1_PRELIM) && defined(CFG_LBLAWAR1_PRELIM) im->sysconf.lblaw[1].bar = CFG_LBLAWBAR1_PRELIM; im->sysconf.lblaw[1].ar = CFG_LBLAWAR1_PRELIM; #endif -#if defined(CFG_BR2_PRELIM) \ - && defined(CFG_OR2_PRELIM) \ - && defined(CFG_LBLAWBAR2_PRELIM) \ - && defined(CFG_LBLAWAR2_PRELIM) +#if defined(CFG_BR2_PRELIM) && defined(CFG_OR2_PRELIM) im->lbus.bank[2].br = CFG_BR2_PRELIM; im->lbus.bank[2].or = CFG_OR2_PRELIM; +#endif +#if defined(CFG_LBLAWBAR2_PRELIM) && defined(CFG_LBLAWAR2_PRELIM) im->sysconf.lblaw[2].bar = CFG_LBLAWBAR2_PRELIM; im->sysconf.lblaw[2].ar = CFG_LBLAWAR2_PRELIM; #endif -#if defined(CFG_BR3_PRELIM) \ - && defined(CFG_OR3_PRELIM) \ - && defined(CFG_LBLAWBAR3_PRELIM) \ - && defined(CFG_LBLAWAR3_PRELIM) +#if defined(CFG_BR3_PRELIM) && defined(CFG_OR3_PRELIM) im->lbus.bank[3].br = CFG_BR3_PRELIM; im->lbus.bank[3].or = CFG_OR3_PRELIM; +#endif +#if defined(CFG_LBLAWBAR3_PRELIM) && defined(CFG_LBLAWAR3_PRELIM) im->sysconf.lblaw[3].bar = CFG_LBLAWBAR3_PRELIM; im->sysconf.lblaw[3].ar = CFG_LBLAWAR3_PRELIM; #endif -#if defined(CFG_BR4_PRELIM) \ - && defined(CFG_OR4_PRELIM) \ - && defined(CFG_LBLAWBAR4_PRELIM) \ - && defined(CFG_LBLAWAR4_PRELIM) +#if defined(CFG_BR4_PRELIM) && defined(CFG_OR4_PRELIM) im->lbus.bank[4].br = CFG_BR4_PRELIM; im->lbus.bank[4].or = CFG_OR4_PRELIM; +#endif +#if defined(CFG_LBLAWBAR4_PRELIM) && defined(CFG_LBLAWAR4_PRELIM) im->sysconf.lblaw[4].bar = CFG_LBLAWBAR4_PRELIM; im->sysconf.lblaw[4].ar = CFG_LBLAWAR4_PRELIM; #endif -#if defined(CFG_BR5_PRELIM) \ - && defined(CFG_OR5_PRELIM) \ - && defined(CFG_LBLAWBAR5_PRELIM) \ - && defined(CFG_LBLAWAR5_PRELIM) +#if defined(CFG_BR5_PRELIM) && defined(CFG_OR5_PRELIM) im->lbus.bank[5].br = CFG_BR5_PRELIM; im->lbus.bank[5].or = CFG_OR5_PRELIM; +#endif +#if defined(CFG_LBLAWBAR5_PRELIM) && defined(CFG_LBLAWAR5_PRELIM) im->sysconf.lblaw[5].bar = CFG_LBLAWBAR5_PRELIM; im->sysconf.lblaw[5].ar = CFG_LBLAWAR5_PRELIM; #endif -#if defined(CFG_BR6_PRELIM) \ - && defined(CFG_OR6_PRELIM) \ - && defined(CFG_LBLAWBAR6_PRELIM) \ - && defined(CFG_LBLAWAR6_PRELIM) +#if defined(CFG_BR6_PRELIM) && defined(CFG_OR6_PRELIM) im->lbus.bank[6].br = CFG_BR6_PRELIM; im->lbus.bank[6].or = CFG_OR6_PRELIM; +#endif +#if defined(CFG_LBLAWBAR6_PRELIM) && defined(CFG_LBLAWAR6_PRELIM) im->sysconf.lblaw[6].bar = CFG_LBLAWBAR6_PRELIM; im->sysconf.lblaw[6].ar = CFG_LBLAWAR6_PRELIM; #endif -#if defined(CFG_BR7_PRELIM) \ - && defined(CFG_OR7_PRELIM) \ - && defined(CFG_LBLAWBAR7_PRELIM) \ - && defined(CFG_LBLAWAR7_PRELIM) +#if defined(CFG_BR7_PRELIM) && defined(CFG_OR7_PRELIM) im->lbus.bank[7].br = CFG_BR7_PRELIM; im->lbus.bank[7].or = CFG_OR7_PRELIM; +#endif +#if defined(CFG_LBLAWBAR7_PRELIM) && defined(CFG_LBLAWAR7_PRELIM) im->sysconf.lblaw[7].bar = CFG_LBLAWBAR7_PRELIM; im->sysconf.lblaw[7].ar = CFG_LBLAWAR7_PRELIM; #endif -- cgit v1.2.3 From 2688e2f972bd124be87cb86bce58aa1b186b5aa7 Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Fri, 10 Feb 2006 15:40:06 -0600 Subject: Enable address translation on MPC83xx Patch by Kumar Gala, 10 Feb 2006 --- cpu/mpc83xx/start.S | 477 ++++++++++++++++++++++++++++++++-------------------- 1 file changed, 298 insertions(+), 179 deletions(-) (limited to 'cpu') diff --git a/cpu/mpc83xx/start.S b/cpu/mpc83xx/start.S index 0e1a5fd5726..46c748f7905 100644 --- a/cpu/mpc83xx/start.S +++ b/cpu/mpc83xx/start.S @@ -179,10 +179,47 @@ in_flash: #endif #endif /* CFG_RAMBOOT */ - bl setup_stack_in_data_cache_on_r1 + /* setup the bats */ + bl setup_bats + sync + + /* + * Cache must be enabled here for stack-in-cache trick. + * This means we need to enable the BATS. + * This means: + * 1) for the EVB, original gt regs need to be mapped + * 2) need to have an IBAT for the 0xf region, + * we are running there! + * Cache should be turned on after BATs, since by default + * everything is write-through. + * The init-mem BAT can be reused after reloc. The old + * gt-regs BAT can be reused after board_init_f calls + * board_early_init_f (EVB only). + */ + /* enable address translation */ + bl enable_addr_trans + sync + + /* enable and invalidate the data cache */ + bl dcache_enable + sync +#ifdef CFG_INIT_RAM_LOCK + bl lock_ram_in_cache + sync +#endif + + /* set up the stack pointer in our newly created + * cache-ram (r1) */ + lis r1, (CFG_INIT_RAM_ADDR + CFG_GBL_DATA_OFFSET)@h + ori r1, r1, (CFG_INIT_RAM_ADDR + CFG_GBL_DATA_OFFSET)@l + + li r0, 0 /* Make room for stack frame header and */ + stwu r0, -4(r1) /* clear final stack frame so that */ + stwu r0, -4(r1) /* stack backtraces terminate cleanly */ + /* let the C-code set up the rest */ - /* */ + /* */ /* Be careful to keep code relocatable & stack humble */ /*------------------------------------------------------*/ @@ -509,6 +546,221 @@ init_e300_core: /* time t 10 */ /*------------------------------*/ blr + .globl invalidate_bats +invalidate_bats: + /* invalidate BATs */ + mtspr IBAT0U, r0 + mtspr IBAT1U, r0 + mtspr IBAT2U, r0 + mtspr IBAT3U, r0 +#if (CFG_HID2 & HID2_HBE) + mtspr IBAT4U, r0 + mtspr IBAT5U, r0 + mtspr IBAT6U, r0 + mtspr IBAT7U, r0 +#endif + isync + mtspr DBAT0U, r0 + mtspr DBAT1U, r0 + mtspr DBAT2U, r0 + mtspr DBAT3U, r0 +#if (CFG_HID2 & HID2_HBE) + mtspr DBAT4U, r0 + mtspr DBAT5U, r0 + mtspr DBAT6U, r0 + mtspr DBAT7U, r0 +#endif + isync + sync + blr + + /* setup_bats - set them up to some initial state */ + .globl setup_bats +setup_bats: + addis r0, r0, 0x0000 + + /* IBAT 0 */ + addis r4, r0, CFG_IBAT0L@h + ori r4, r4, CFG_IBAT0L@l + addis r3, r0, CFG_IBAT0U@h + ori r3, r3, CFG_IBAT0U@l + mtspr IBAT0L, r4 + mtspr IBAT0U, r3 + isync + + /* DBAT 0 */ + addis r4, r0, CFG_DBAT0L@h + ori r4, r4, CFG_DBAT0L@l + addis r3, r0, CFG_DBAT0U@h + ori r3, r3, CFG_DBAT0U@l + mtspr DBAT0L, r4 + mtspr DBAT0U, r3 + isync + + /* IBAT 1 */ + addis r4, r0, CFG_IBAT1L@h + ori r4, r4, CFG_IBAT1L@l + addis r3, r0, CFG_IBAT1U@h + ori r3, r3, CFG_IBAT1U@l + mtspr IBAT1L, r4 + mtspr IBAT1U, r3 + isync + + /* DBAT 1 */ + addis r4, r0, CFG_DBAT1L@h + ori r4, r4, CFG_DBAT1L@l + addis r3, r0, CFG_DBAT1U@h + ori r3, r3, CFG_DBAT1U@l + mtspr DBAT1L, r4 + mtspr DBAT1U, r3 + isync + + /* IBAT 2 */ + addis r4, r0, CFG_IBAT2L@h + ori r4, r4, CFG_IBAT2L@l + addis r3, r0, CFG_IBAT2U@h + ori r3, r3, CFG_IBAT2U@l + mtspr IBAT2L, r4 + mtspr IBAT2U, r3 + isync + + /* DBAT 2 */ + addis r4, r0, CFG_DBAT2L@h + ori r4, r4, CFG_DBAT2L@l + addis r3, r0, CFG_DBAT2U@h + ori r3, r3, CFG_DBAT2U@l + mtspr DBAT2L, r4 + mtspr DBAT2U, r3 + isync + + /* IBAT 3 */ + addis r4, r0, CFG_IBAT3L@h + ori r4, r4, CFG_IBAT3L@l + addis r3, r0, CFG_IBAT3U@h + ori r3, r3, CFG_IBAT3U@l + mtspr IBAT3L, r4 + mtspr IBAT3U, r3 + isync + + /* DBAT 3 */ + addis r4, r0, CFG_DBAT3L@h + ori r4, r4, CFG_DBAT3L@l + addis r3, r0, CFG_DBAT3U@h + ori r3, r3, CFG_DBAT3U@l + mtspr DBAT3L, r4 + mtspr DBAT3U, r3 + isync + +#if (CFG_HID2 & HID2_HBE) + /* IBAT 4 */ + addis r4, r0, CFG_IBAT4L@h + ori r4, r4, CFG_IBAT4L@l + addis r3, r0, CFG_IBAT4U@h + ori r3, r3, CFG_IBAT4U@l + mtspr IBAT4L, r4 + mtspr IBAT4U, r3 + isync + + /* DBAT 4 */ + addis r4, r0, CFG_DBAT4L@h + ori r4, r4, CFG_DBAT4L@l + addis r3, r0, CFG_DBAT4U@h + ori r3, r3, CFG_DBAT4U@l + mtspr DBAT4L, r4 + mtspr DBAT4U, r3 + isync + + /* IBAT 5 */ + addis r4, r0, CFG_IBAT5L@h + ori r4, r4, CFG_IBAT5L@l + addis r3, r0, CFG_IBAT5U@h + ori r3, r3, CFG_IBAT5U@l + mtspr IBAT5L, r4 + mtspr IBAT5U, r3 + isync + + /* DBAT 5 */ + addis r4, r0, CFG_DBAT5L@h + ori r4, r4, CFG_DBAT5L@l + addis r3, r0, CFG_DBAT5U@h + ori r3, r3, CFG_DBAT5U@l + mtspr DBAT5L, r4 + mtspr DBAT5U, r3 + isync + + /* IBAT 6 */ + addis r4, r0, CFG_IBAT6L@h + ori r4, r4, CFG_IBAT6L@l + addis r3, r0, CFG_IBAT6U@h + ori r3, r3, CFG_IBAT6U@l + mtspr IBAT6L, r4 + mtspr IBAT6U, r3 + isync + + /* DBAT 6 */ + addis r4, r0, CFG_DBAT6L@h + ori r4, r4, CFG_DBAT6L@l + addis r3, r0, CFG_DBAT6U@h + ori r3, r3, CFG_DBAT6U@l + mtspr DBAT6L, r4 + mtspr DBAT6U, r3 + isync + + /* IBAT 7 */ + addis r4, r0, CFG_IBAT7L@h + ori r4, r4, CFG_IBAT7L@l + addis r3, r0, CFG_IBAT7U@h + ori r3, r3, CFG_IBAT7U@l + mtspr IBAT7L, r4 + mtspr IBAT7U, r3 + isync + + /* DBAT 7 */ + addis r4, r0, CFG_DBAT7L@h + ori r4, r4, CFG_DBAT7L@l + addis r3, r0, CFG_DBAT7U@h + ori r3, r3, CFG_DBAT7U@l + mtspr DBAT7L, r4 + mtspr DBAT7U, r3 + isync +#endif + + /* Invalidate TLBs. + * -> for (val = 0; val < 0x20000; val+=0x1000) + * -> tlbie(val); + */ + lis r3, 0 + lis r5, 2 + +1: + tlbie r3 + addi r3, r3, 0x1000 + cmp 0, 0, r3, r5 + blt 1b + + blr + + .globl enable_addr_trans +enable_addr_trans: + /* enable address translation */ + mfmsr r5 + ori r5, r5, (MSR_IR | MSR_DR) + mtmsr r5 + isync + blr + + .globl disable_addr_trans +disable_addr_trans: + /* disable address translation */ + mflr r4 + mfmsr r3 + andi. r0, r3, (MSR_IR | MSR_DR) + beqlr + andc r3, r3, r0 + mtspr SRR0, r4 + mtspr SRR1, r3 + rfi + /* Cache functions. * * Note: requires that all cache bits in @@ -550,26 +802,25 @@ icache_status: .globl dcache_enable dcache_enable: mfspr r3, HID0 - ori r3, r3, HID0_ENABLE_DATA_CACHE - lis r4, 0 - ori r4, r4, HID0_LOCK_DATA_CACHE - andc r3, r3, r4 - ori r4, r3, HID0_LOCK_INSTRUCTION_CACHE - sync - mtspr HID0, r4 /* sets enable and invalidate, clears lock */ + li r5, HID0_DCFI|HID0_DLOCK + andc r3, r3, r5 + mtspr HID0, r3 /* no invalidate, unlock */ + ori r3, r3, HID0_DCE + ori r5, r3, HID0_DCFI + mtspr HID0, r5 /* enable + invalidate */ + mtspr HID0, r3 /* enable */ sync - mtspr HID0, r3 /* clears invalidate */ blr .globl dcache_disable dcache_disable: mfspr r3, HID0 lis r4, 0 - ori r4, r4, HID0_ENABLE_DATA_CACHE|HID0_LOCK_DATA_CACHE + ori r4, r4, HID0_DCE|HID0_DLOCK andc r3, r3, r4 - ori r4, r3, HID0_INVALIDATE_DATA_CACHE + ori r4, r3, HID0_DCI sync - mtspr HID0, r4 /* sets invalidate, clears enable and lock */ + mtspr HID0, r4 /* sets invalidate, clears enable and lock */ sync mtspr HID0, r3 /* clears invalidate */ blr @@ -674,46 +925,29 @@ relocate_code: * Now flush the cache: note that we must start from a cache aligned * address. Otherwise we might miss one cache line. */ -4: - bl un_setup_stack_in_data_cache - mr r7, r3 - mr r8, r4 - bl dcache_disable - mr r3, r7 - mr r4, r8 - - cmpwi r6,0 +4: cmpwi r6,0 add r5,r3,r5 - beq 7f /* Always flush prefetch queue in any case */ + beq 7f /* Always flush prefetch queue in any case */ subi r0,r6,1 andc r3,r3,r0 - mfspr r7,HID0 /* don't do dcbst if dcache is disabled*/ - rlwinm r7,r7,HID0_DCE_SHIFT,31,31 - cmpwi r7,0 - beq 9f mr r4,r3 5: dcbst 0,r4 add r4,r4,r6 cmplw r4,r5 blt 5b - sync /* Wait for all dcbst to complete on bus */ -9: mfspr r7,HID0 /* don't do icbi if icache is disabled */ - rlwinm r7,r7,HID0_DCE_SHIFT,31,31 - cmpwi r7,0 - beq 7f + sync /* Wait for all dcbst to complete on bus */ mr r4,r3 6: icbi 0,r4 add r4,r4,r6 cmplw r4,r5 blt 6b -7: sync /* Wait for all icbi to complete on bus */ +7: sync /* Wait for all icbi to complete on bus */ isync /* * We are done. Do not return, instead branch to second part of board * initialization, now running from RAM. */ - addi r0, r10, in_ram - _start + EXC_OFF_SYS_RESET mtlr r0 blr @@ -871,6 +1105,27 @@ trap_reloc: blr #ifdef CFG_INIT_RAM_LOCK +lock_ram_in_cache: + /* Allocate Initial RAM in data cache. + */ + lis r3, (CFG_INIT_RAM_ADDR & ~31)@h + ori r3, r3, (CFG_INIT_RAM_ADDR & ~31)@l + li r2, ((CFG_INIT_RAM_END & ~31) + \ + (CFG_INIT_RAM_ADDR & 31) + 31) / 32 + mtctr r2 +1: + dcbz r0, r3 + addi r3, r3, 32 + bdnz 1b + + /* Lock the data cache */ + mfspr r0, HID0 + ori r0, r0, 0x1000 + sync + mtspr HID0, r0 + sync + blr + .globl unlock_ram_in_cache unlock_ram_in_cache: /* invalidate the INIT_RAM section */ @@ -884,6 +1139,15 @@ unlock_ram_in_cache: bdnz 1b sync /* Wait for all icbi to complete on bus */ isync + + /* Unlock the data cache and invalidate it */ + mfspr r3, HID0 + li r5, HID0_DLOCK|HID0_DCFI + andc r3, r3, r5 /* no invalidate, unlock */ + ori r5, r3, HID0_DCFI /* invalidate, unlock */ + mtspr HID0, r5 /* invalidate, unlock */ + mtspr HID0, r3 /* no invalidate, unlock */ + sync blr #endif @@ -952,148 +1216,3 @@ remap_flash_by_law0: stw r4, LBLAWBAR1(r3) stw r4, LBLAWAR1(r3) /* Off LBIU LAW1 */ blr - -setup_stack_in_data_cache_on_r1: - lis r3, (CFG_IMMRBAR)@h - - /* setup D-BAT for the D-Cache (with out real memory backup) */ - - lis r4, (CFG_INIT_RAM_ADDR & 0xFFFE0000)@h - mtspr DBAT0U, r4 - ori r4, r4, 0x0002 - mtspr DBAT0L, r4 - isync - -#if 0 - /* Enable MMU */ - mfmsr r4 - ori r4, r4, (MSR_DR | MSR_IR)@l - mtmsr r4 -#endif - - /* Enable and invalidate data cache. */ - mfspr r4, HID0 - mr r5, r4 - ori r4, r4, HID0_DCE | HID0_DCI - ori r5, r5, HID0_DCE - sync - mtspr HID0, r4 - mtspr HID0, r5 - sync - - /* Allocate Initial RAM in data cache.*/ - li r0, 0 - lis r4, (CFG_INIT_RAM_ADDR)@h - ori r4, r4, (CFG_INIT_RAM_ADDR)@l - li r5, 128*8 /* 128*8*32=32Kb */ - mtctr r5 -1: - dcbz r0, r4 - addi r4, r4, 32 - bdnz 1b - isync - - /* Lock all the D-cache, basically leaving the reset of the program without dcache */ - mfspr r4, HID0 - ori r4, r4, (HID0_DLOCK)@l - sync - mtspr HID0 , r4 - - /* setup the stack pointer in r1 */ - lis r1, (CFG_INIT_RAM_ADDR + CFG_GBL_DATA_OFFSET)@h - ori r1, r1, (CFG_INIT_RAM_ADDR + CFG_GBL_DATA_OFFSET)@l - li r0, 0 /* Make room for stack frame header and */ - - stwu r0, -4(r1) /* clear final stack frame so that */ - stwu r0, -4(r1) /* stack backtraces terminate cleanly */ - - blr - -un_setup_stack_in_data_cache: - blr - mr r14, r4 - mr r15, r5 - - - lis r4, (CFG_INIT_RAM_ADDR & 0xFFFE0000)@h - mtspr DBAT0U, r4 - ori r4, r4, 0x0002 - mtspr DBAT0L, r4 - isync - - /* un lock all the D-cache */ - mfspr r4, HID0 - lis r5, (~(HID0_DLOCK))@h - ori r5, r5, (~(HID0_DLOCK))@l - and r4, r4, r5 - sync - mtspr HID0 , r4 - - /* Re - Allocate Initial RAM in data cache.*/ - li r0, 0 - lis r4, (CFG_INIT_RAM_ADDR)@h - ori r4, r4, (CFG_INIT_RAM_ADDR)@l - li r5, 128*8 /* 128*8*32=32Kb */ - mtctr r5 -1: - dcbz r0, r4 - addi r4, r4, 32 - bdnz 1b - isync - - mflr r16 - bl dcache_disable - mtlr r16 - - blr - -#if 0 -#define GREEN_LIGHT 0x2B0D4046 -#define RED_LIGHT 0x250D4046 -#define LIB_CNT 0x4FFF - -/* - * Lib Light - */ - - .globl liblight -liblight: - lis r3, CFG_IMMRBAR@h - ori r3, r3, CFG_IMMRBAR@l - li r4, 0x3002 - mtmsr r4 - xor r4, r4, r4 - mtspr HID0, r4 - mtspr HID2, r4 - lis r4, 0xF8000000@h - ori r4, r4, 0xF8000000@l - stw r4, LBLAWBAR1(r3) - lis r4, 0x8000000E@h - ori r4, r4, 0x8000000E@l - stw r4, LBLAWAR1(r3) - lis r4, 0xF8000801@h - ori r4, r4, 0xF8000801@l - stw r4, BR1(r3) - lis r4, 0xFFFFE8f0@h - ori r4, r4, 0xFFFFE8f0@l - stw r4, OR1(r3) - - lis r4, 0xF8000000@h - ori r4, r4, 0xF8000000@l - lis r5, GREEN_LIGHT@h - ori r5, r5, GREEN_LIGHT@l - lis r6, RED_LIGHT@h - ori r6, r6, RED_LIGHT@l - lis r7, LIB_CNT@h - ori r7, r7, LIB_CNT@l - -1: - stw r5, 0(r4) - mtctr r7 -2: bdnz 2b - stw r6, 0(r4) - mtctr r7 -3: bdnz 3b - b 1b - -#endif -- cgit v1.2.3 From d52fb7e3d135704334bd6f97f3444e824665b76f Mon Sep 17 00:00:00 2001 From: Wolfgang Denk Date: Sat, 11 Mar 2006 22:53:33 +0100 Subject: Some code cleanup for GCC 4.x --- cpu/arm920t/at91rm9200/i2c.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'cpu') diff --git a/cpu/arm920t/at91rm9200/i2c.c b/cpu/arm920t/at91rm9200/i2c.c index 2565998e484..826cea8e264 100644 --- a/cpu/arm920t/at91rm9200/i2c.c +++ b/cpu/arm920t/at91rm9200/i2c.c @@ -111,7 +111,7 @@ at91_xfer(unsigned char chip, unsigned int addr, int alen, int i2c_probe(unsigned char chip) { - char buffer[1]; + unsigned char buffer[1]; return at91_xfer(chip, 0, 0, buffer, 1, 1); } @@ -191,7 +191,7 @@ i2c_init(int speed, int slaveaddr) uchar i2c_reg_read(uchar i2c_addr, uchar reg) { - char buf; + unsigned char buf; i2c_read(i2c_addr, reg, 1, &buf, 1); -- cgit v1.2.3 From d2ed2f661b6f74b68105d27a399801bdef287ef5 Mon Sep 17 00:00:00 2001 From: Wolfgang Denk Date: Sat, 11 Mar 2006 23:07:09 +0100 Subject: More GCC 4.x woes --- cpu/arm920t/s3c24x0/usb_ohci.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'cpu') diff --git a/cpu/arm920t/s3c24x0/usb_ohci.c b/cpu/arm920t/s3c24x0/usb_ohci.c index b4cc74476b0..869ca79d032 100644 --- a/cpu/arm920t/s3c24x0/usb_ohci.c +++ b/cpu/arm920t/s3c24x0/usb_ohci.c @@ -1647,7 +1647,8 @@ int usb_lowlevel_init(void) } /* FIXME this is a second HC reset; why?? */ - writel (gohci.hc_control = OHCI_USB_RESET, &gohci.regs->control); + gohci.hc_control = OHCI_USB_RESET; + writel (gohci.hc_control, &gohci.regs->control); wait_ms (10); if (hc_start (&gohci) < 0) { -- cgit v1.2.3 From 6cb142fa3b732a2cea257ca39ef4a7dbe81a32e1 Mon Sep 17 00:00:00 2001 From: Wolfgang Denk Date: Sun, 12 Mar 2006 02:12:27 +0100 Subject: Add missing Blackfin files. --- cpu/bf533/Makefile | 46 ++++ cpu/bf533/bf533_serial.h | 78 ++++++ cpu/bf533/cache.S | 125 ++++++++++ cpu/bf533/config.mk | 27 +++ cpu/bf533/cplbhdlr.S | 194 +++++++++++++++ cpu/bf533/cplbmgr.S | 601 +++++++++++++++++++++++++++++++++++++++++++++++ cpu/bf533/cpu.c | 194 +++++++++++++++ cpu/bf533/cpu.h | 65 +++++ cpu/bf533/flush.S | 402 +++++++++++++++++++++++++++++++ cpu/bf533/interrupt.S | 391 ++++++++++++++++++++++++++++++ cpu/bf533/interrupts.c | 165 +++++++++++++ cpu/bf533/ints.c | 107 +++++++++ cpu/bf533/serial.c | 194 +++++++++++++++ cpu/bf533/start.S | 435 ++++++++++++++++++++++++++++++++++ cpu/bf533/start1.S | 38 +++ cpu/bf533/traps.c | 73 ++++++ 16 files changed, 3135 insertions(+) create mode 100644 cpu/bf533/Makefile create mode 100644 cpu/bf533/bf533_serial.h create mode 100644 cpu/bf533/cache.S create mode 100644 cpu/bf533/config.mk create mode 100644 cpu/bf533/cplbhdlr.S create mode 100644 cpu/bf533/cplbmgr.S create mode 100644 cpu/bf533/cpu.c create mode 100644 cpu/bf533/cpu.h create mode 100644 cpu/bf533/flush.S create mode 100644 cpu/bf533/interrupt.S create mode 100644 cpu/bf533/interrupts.c create mode 100644 cpu/bf533/ints.c create mode 100644 cpu/bf533/serial.c create mode 100644 cpu/bf533/start.S create mode 100644 cpu/bf533/start1.S create mode 100644 cpu/bf533/traps.c (limited to 'cpu') diff --git a/cpu/bf533/Makefile b/cpu/bf533/Makefile new file mode 100644 index 00000000000..c63a8f6d01d --- /dev/null +++ b/cpu/bf533/Makefile @@ -0,0 +1,46 @@ +# U-boot - Makefile +# +# Copyright (c) 2005 blackfin.uclinux.org +# +# (C) Copyright 2000-2004 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# + +include $(TOPDIR)/config.mk + +LIB = lib$(CPU).a + +START = start.o start1.o interrupt.o cache.o cplbhdlr.o cplbmgr.o flush.o +OBJS = cpu.o traps.o ints.o serial.o interrupts.o + +all: .depend $(START) $(LIB) + +$(LIB): $(OBJS) + $(AR) crv $@ $(OBJS) + +######################################################################### + +.depend: Makefile $(START:.o=.S) $(OBJS:.o=.c) + $(CC) -M $(CFLAGS) $(START:.o=.S) $(OBJS:.o=.c) > $@ + +sinclude .depend + +######################################################################### diff --git a/cpu/bf533/bf533_serial.h b/cpu/bf533/bf533_serial.h new file mode 100644 index 00000000000..ec63a5e00ad --- /dev/null +++ b/cpu/bf533/bf533_serial.h @@ -0,0 +1,78 @@ +/* + * U-boot - bf533_serial.h Serial Driver defines + * + * Copyright (c) 2005 blackfin.uclinux.org + * + * This file is based on + * bf533_serial.h: Definitions for the BlackFin BF533 DSP serial driver. + * Copyright (C) 2003 Bas Vermeulen + * BuyWays B.V. (www.buyways.nl) + * + * Based heavily on: + * blkfinserial.h: Definitions for the BlackFin DSP serial driver. + * + * Copyright (C) 2001 Tony Z. Kou tonyko@arcturusnetworks.com + * Copyright (C) 2001 Arcturus Networks Inc. + * + * Based on code from 68328serial.c which was: + * Copyright (C) 1995 David S. Miller + * Copyright (C) 1998 Kenneth Albanowski + * Copyright (C) 1998, 1999 D. Jeff Dionne + * Copyright (C) 1999 Vladimir Gurevich + * + * (C) Copyright 2000-2004 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef _Bf533_SERIAL_H +#define _Bf533_SERIAL_H + +#include +#include + +#define SYNC_ALL __asm__ __volatile__ ("ssync;\n") +#define ACCESS_LATCH *pUART_LCR |= UART_LCR_DLAB; +#define ACCESS_PORT_IER *pUART_LCR &= (~UART_LCR_DLAB); + +void serial_setbrg(void); +static void local_put_char(char ch); +void calc_baud(void); +void serial_setbrg(void); +int serial_init(void); +void serial_putc(const char c); +int serial_tstc(void); +int serial_getc(void); +void serial_puts(const char *s); +static void local_put_char(char ch); + +extern int get_clock(void); +int baud_table[5] = {9600, 19200, 38400, 57600, 115200}; + +struct { + unsigned char dl_high; + unsigned char dl_low; +} hw_baud_table[5]; + +#ifdef CONFIG_STAMP +extern unsigned long pll_div_fact; +#endif + +#endif diff --git a/cpu/bf533/cache.S b/cpu/bf533/cache.S new file mode 100644 index 00000000000..1822d1f3290 --- /dev/null +++ b/cpu/bf533/cache.S @@ -0,0 +1,125 @@ + + +#define ASSEMBLY +#include +#include + +.text +.align 2 +ENTRY(blackfin_icache_flush_range) + R2 = -32; + R2 = R0 & R2; + P0 = R2; + P1 = R1; + CSYNC; +1: + IFLUSH[P0++]; + CC = P0 < P1(iu); + IF CC JUMP 1b(bp); + IFLUSH[P0]; + SSYNC; + RTS; + +ENTRY(blackfin_dcache_flush_range) + R2 = -32; + R2 = R0 & R2; + P0 = R2; + P1 = R1; + CSYNC; +1: + FLUSH[P0++]; + CC = P0 < P1(iu); + IF CC JUMP 1b(bp); + FLUSH[P0]; + SSYNC; + RTS; + +ENTRY(_icache_invalidate) +ENTRY(invalidate_entire_icache) + [--SP] = ( R7:5); + + P0.L = (IMEM_CONTROL & 0xFFFF); + P0.H = (IMEM_CONTROL >> 16); + R7 = [P0]; + + /* Clear the IMC bit , All valid bits in the instruction + * cache are set to the invalid state + */ + BITCLR(R7,IMC_P); + CLI R6; + SSYNC; /* SSYNC required before invalidating cache. */ + .align 8; + [P0] = R7; + SSYNC; + STI R6; + + /* Configures the instruction cache agian */ + R6 = (IMC | ENICPLB); + R7 = R7 | R6; + + CLI R6; + SSYNC; /* SSYNC required before writing to IMEM_CONTROL. */ + .align 8; + [P0] = R7; + SSYNC; + STI R6; + + ( R7:5) = [SP++]; + RTS; + +/* Invalidate the Entire Data cache by + * clearing DMC[1:0] bits + */ +ENTRY(invalidate_entire_dcache) +ENTRY(_dcache_invalidate) + [--SP] = ( R7:6); + + P0.L = (DMEM_CONTROL & 0xFFFF); + P0.H = (DMEM_CONTROL >> 16); + R7 = [P0]; + + /* Clear the DMC[1:0] bits, All valid bits in the data + * cache are set to the invalid state + */ + BITCLR(R7,DMC0_P); + BITCLR(R7,DMC1_P); + CLI R6; + SSYNC; /* SSYNC required before writing to DMEM_CONTROL. */ + .align 8; + [P0] = R7; + SSYNC; + STI R6; + + /* Configures the data cache again */ + + R6 = (ACACHE_BCACHE | ENDCPLB | PORT_PREF0); + R7 = R7 | R6; + + CLI R6; + SSYNC; /* SSYNC required before writing to DMEM_CONTROL. */ + .align 8; + [P0] = R7; + SSYNC; + STI R6; + + ( R7:6) = [SP++]; + RTS; + +ENTRY(blackfin_dcache_invalidate_range) + R2 = -32; + R2 = R0 & R2; + P0 = R2; + P1 = R1; + CSYNC; +1: + FLUSHINV[P0++]; + CC = P0 < P1 (iu); + IF CC JUMP 1b (bp); + + /* If the data crosses a cache line, then we'll be pointing to + ** the last cache line, but won't have flushed/invalidated it yet, so do + ** one more. + */ + FLUSHINV[P0]; + SSYNC; + RTS; diff --git a/cpu/bf533/config.mk b/cpu/bf533/config.mk new file mode 100644 index 00000000000..a9d529ecd88 --- /dev/null +++ b/cpu/bf533/config.mk @@ -0,0 +1,27 @@ +# U-boot - config.mk +# +# Copyright (c) 2005 blackfin.uclinux.org +# +# (C) Copyright 2000-2004 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# + +PLATFORM_RELFLAGS += -ffixed-P5 diff --git a/cpu/bf533/cplbhdlr.S b/cpu/bf533/cplbhdlr.S new file mode 100644 index 00000000000..b5abbbcbb63 --- /dev/null +++ b/cpu/bf533/cplbhdlr.S @@ -0,0 +1,194 @@ +/* Copyright (C) 2003 Analog Devices, Inc. All Rights Reserved. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. + * + * Blackfin BF533/2.6 support : LG Soft India + */ + + +/* Include an exception handler to invoke the CPLB manager + */ + +#include +#include +#include + + +.text + +.globl _cplb_hdr; +.type _cplb_hdr, STT_FUNC; +.extern _cplb_mgr; +.type _cplb_mgr, STT_FUNC; +.extern __unknown_exception_occurred; +.type __unknown_exception_occurred, STT_FUNC; +.extern __cplb_miss_all_locked; +.type __cplb_miss_all_locked, STT_FUNC; +.extern __cplb_miss_without_replacement; +.type __cplb_miss_without_replacement, STT_FUNC; +.extern __cplb_protection_violation; +.type __cplb_protection_violation, STT_FUNC; +.extern panic_pv; + +.align 2; + +ENTRY(_cplb_hdr) + SSYNC; + [--SP] = ( R7:0, P5:0 ); + [--SP] = ASTAT; + [--SP] = SEQSTAT; + [--SP] = I0; + [--SP] = I1; + [--SP] = I2; + [--SP] = I3; + [--SP] = LT0; + [--SP] = LB0; + [--SP] = LC0; + [--SP] = LT1; + [--SP] = LB1; + [--SP] = LC1; + R2 = SEQSTAT; + + /*Mask the contents of SEQSTAT and leave only EXCAUSE in R2*/ + R2 <<= 26; + R2 >>= 26; + + R1 = 0x23; /* Data access CPLB protection violation */ + CC = R2 == R1; + IF !CC JUMP not_data_write; + R0 = 2; /* is a write to data space*/ + JUMP is_icplb_miss; + +not_data_write: + R1 = 0x2C; /* CPLB miss on an instruction fetch */ + CC = R2 == R1; + R0 = 0; /* is_data_miss == False*/ + IF CC JUMP is_icplb_miss; + + R1 = 0x26; + CC = R2 == R1; + IF !CC JUMP unknown; + + R0 = 1; /* is_data_miss == True*/ + +is_icplb_miss: + +#if ( defined (CONFIG_BLKFIN_CACHE) || defined (CONFIG_BLKFIN_DCACHE)) +#if ( defined (CONFIG_BLKFIN_CACHE) && !defined (CONFIG_BLKFIN_DCACHE)) + R1 = CPLB_ENABLE_ICACHE; +#endif +#if ( !defined (CONFIG_BLKFIN_CACHE) && defined (CONFIG_BLKFIN_DCACHE)) + R1 = CPLB_ENABLE_DCACHE; +#endif +#if ( defined (CONFIG_BLKFIN_CACHE) && defined (CONFIG_BLKFIN_DCACHE)) + R1 = CPLB_ENABLE_DCACHE | CPLB_ENABLE_ICACHE; +#endif +#else + R1 = 0; +#endif + + [--SP] = RETS; + CALL _cplb_mgr; + RETS = [SP++]; + CC = R0 == 0; + IF !CC JUMP not_replaced; + LC1 = [SP++]; + LB1 = [SP++]; + LT1 = [SP++]; + LC0 = [SP++]; + LB0 = [SP++]; + LT0 = [SP++]; + I3 = [SP++]; + I2 = [SP++]; + I1 = [SP++]; + I0 = [SP++]; + SEQSTAT = [SP++]; + ASTAT = [SP++]; + ( R7:0, P5:0 ) = [SP++]; + RTS; + +unknown: + [--SP] = RETS; + CALL __unknown_exception_occurred; + RETS = [SP++]; + JUMP unknown; +not_replaced: + CC = R0 == CPLB_NO_UNLOCKED; + IF !CC JUMP next_check; + [--SP] = RETS; + CALL __cplb_miss_all_locked; + RETS = [SP++]; +next_check: + CC = R0 == CPLB_NO_ADDR_MATCH; + IF !CC JUMP next_check2; + [--SP] = RETS; + CALL __cplb_miss_without_replacement; + RETS = [SP++]; + JUMP not_replaced; +next_check2: + CC = R0 == CPLB_PROT_VIOL; + IF !CC JUMP strange_return_from_cplb_mgr; + [--SP] = RETS; + CALL __cplb_protection_violation; + RETS = [SP++]; + JUMP not_replaced; +strange_return_from_cplb_mgr: + IDLE; + CSYNC; + JUMP strange_return_from_cplb_mgr; + +/************************************ + * Diagnostic exception handlers + */ + +__cplb_miss_all_locked: + sp += -12; + R0 = CPLB_NO_UNLOCKED; + call panic_bfin; + SP += 12; + RTS; + + __cplb_miss_without_replacement: + sp += -12; + R0 = CPLB_NO_ADDR_MATCH; + call panic_bfin; + SP += 12; + RTS; + +__cplb_protection_violation: + sp += -12; + R0 = CPLB_PROT_VIOL; + call panic_bfin; + SP += 12; + RTS; + +__unknown_exception_occurred: + + /* This function is invoked by the default exception + * handler, if it does not recognise the kind of + * exception that has occurred. In other words, the + * default handler only handles some of the system's + * exception types, and it does not expect any others + * to occur. If your application is going to be using + * other kinds of exceptions, you must replace the + * default handler with your own, that handles all the + * exceptions you will use. + * + * Since there's nothing we can do, we just loop here + * at what we hope is a suitably informative label. + */ + + IDLE; +do_not_know_what_to_do: + CSYNC; + JUMP __unknown_exception_occurred; + + RTS; +.__unknown_exception_occurred.end: +.global __unknown_exception_occurred; +.type __unknown_exception_occurred, STT_FUNC; + +panic_bfin: + RTS; + diff --git a/cpu/bf533/cplbmgr.S b/cpu/bf533/cplbmgr.S new file mode 100644 index 00000000000..fc3e3a8832b --- /dev/null +++ b/cpu/bf533/cplbmgr.S @@ -0,0 +1,601 @@ +/*This file is subject to the terms and conditions of the GNU General Public + * License. + * + * Blackfin BF533/2.6 support : LG Soft India + * Modification: Dec 07 2004 + * 1. Correction in icheck_lock. Valid lock entries were + * geting victimized, for instruction cplb replacement. + * 2. Setup loop's are modified as now toolchain support's P Indexed + * addressing + * :LG Soft India + * + */ + +/* Usage: int _cplb_mgr(is_data_miss,int enable_cache) + * is_data_miss==2 => Mark as Dirty, write to the clean data page + * is_data_miss==1 => Replace a data CPLB. + * is_data_miss==0 => Replace an instruction CPLB. + * + * Returns: + * CPLB_RELOADED => Successfully updated CPLB table. + * CPLB_NO_UNLOCKED => All CPLBs are locked, so cannot be evicted.This indicates + * that the CPLBs in the configuration tablei are badly + * configured, as this should never occur. + * CPLB_NO_ADDR_MATCH => The address being accessed, that triggered the exception, + * is not covered by any of the CPLBs in the configuration + * table. The application isi presumably misbehaving. + * CPLB_PROT_VIOL => The address being accessed, that triggered thei exception, + * was not a first-write to a clean Write Back Data page, + * and so presumably is a genuine violation of the page's + * protection attributes. The application is misbehaving. + */ +#define ASSEMBLY + +#include +#include +#include +#include + +.text + +.align 2; +ENTRY(_cplb_mgr) + + [--SP]=( R7:0,P5:0 ); + + CC = R0 == 2; + IF CC JUMP dcplb_write; + + CC = R0 == 0; + IF !CC JUMP dcplb_miss_compare; + + /* ICPLB Miss Exception. We need to choose one of the + * currently-installed CPLBs, and replace it with one + * from the configuration table. + */ + + P4.L = (ICPLB_FAULT_ADDR & 0xFFFF); + P4.H = (ICPLB_FAULT_ADDR >> 16); + + P1 = 16; + P5.L = page_size_table; + P5.H = page_size_table; + + P0.L = (ICPLB_DATA0 & 0xFFFF); + P0.H = (ICPLB_DATA0 >> 16); + R4 = [P4]; /* Get faulting address*/ + R6 = 64; /* Advance past the fault address, which*/ + R6 = R6 + R4; /* we'll use if we find a match*/ + R3 = ((16 << 8) | 2); /* Extract mask, bits 16 and 17.*/ + + R5 = 0; +isearch: + + R1 = [P0-0x100]; /* Address for this CPLB */ + + R0 = [P0++]; /* Info for this CPLB*/ + CC = BITTST(R0,0); /* Is the CPLB valid?*/ + IF !CC JUMP nomatch; /* Skip it, if not.*/ + CC = R4 < R1(IU); /* If fault address less than page start*/ + IF CC JUMP nomatch; /* then skip this one.*/ + R2 = EXTRACT(R0,R3.L) (Z); /* Get page size*/ + P1 = R2; + P1 = P5 + (P1<<2); /* index into page-size table*/ + R2 = [P1]; /* Get the page size*/ + R1 = R1 + R2; /* and add to page start, to get page end*/ + CC = R4 < R1(IU); /* and see whether fault addr is in page.*/ + IF !CC R4 = R6; /* If so, advance the address and finish loop.*/ + IF !CC JUMP isearch_done; +nomatch: + /* Go around again*/ + R5 += 1; + CC = BITTST(R5, 4); /* i.e CC = R5 >= 16*/ + IF !CC JUMP isearch; + +isearch_done: + I0 = R4; /* Fault address we'll search for*/ + + /* set up pointers */ + P0.L = (ICPLB_DATA0 & 0xFFFF); + P0.H = (ICPLB_DATA0 >> 16); + + /* The replacement procedure for ICPLBs */ + + P4.L = (IMEM_CONTROL & 0xFFFF); + P4.H = (IMEM_CONTROL >> 16); + + /* disable cplbs */ + R5 = [P4]; /* Control Register*/ + BITCLR(R5,ENICPLB_P); + CLI R1; + SSYNC; /* SSYNC required before writing to IMEM_CONTROL. */ + .align 8; + [P4] = R5; + SSYNC; + STI R1; + + R1 = -1; /* end point comparison */ + R3 = 16; /* counter */ + + /* Search through CPLBs for first non-locked entry */ + /* Overwrite it by moving everyone else up by 1 */ +icheck_lock: + R0 = [P0++]; + R3 = R3 + R1; + CC = R3 == R1; + IF CC JUMP all_locked; + CC = BITTST(R0, 0); /* an invalid entry is good */ + IF !CC JUMP ifound_victim; + CC = BITTST(R0,1); /* but a locked entry isn't */ + IF CC JUMP icheck_lock; + +ifound_victim: +#ifdef CONFIG_CPLB_INFO + R7 = [P0 - 0x104]; + P2.L = ipdt_table; + P2.H = ipdt_table; + P3.L = ipdt_swapcount_table; + P3.H = ipdt_swapcount_table; + P3 += -4; +icount: + R2 = [P2]; /* address from config table */ + P2 += 8; + P3 += 8; + CC = R2==-1; + IF CC JUMP icount_done; + CC = R7==R2; + IF !CC JUMP icount; + R7 = [P3]; + R7 += 1; + [P3] = R7; + CSYNC; +icount_done: +#endif + LC0=R3; + LSETUP(is_move,ie_move) LC0; +is_move: + R0 = [P0]; + [P0 - 4] = R0; + R0 = [P0 - 0x100]; + [P0-0x104] = R0; +ie_move:P0+=4; + + /* We've made space in the ICPLB table, so that ICPLB15 + * is now free to be overwritten. Next, we have to determine + * which CPLB we need to install, from the configuration + * table. This is a matter of getting the start-of-page + * addresses and page-lengths from the config table, and + * determining whether the fault address falls within that + * range. + */ + + P2.L = ipdt_table; + P2.H = ipdt_table; +#ifdef CONFIG_CPLB_INFO + P3.L = ipdt_swapcount_table; + P3.H = ipdt_swapcount_table; + P3 += -8; +#endif + P0.L = page_size_table; + P0.H = page_size_table; + + /* Retrieve our fault address (which may have been advanced + * because the faulting instruction crossed a page boundary). + */ + + R0 = I0; + + /* An extraction pattern, to get the page-size bits from + * the CPLB data entry. Bits 16-17, so two bits at posn 16. + */ + + R1 = ((16<<8)|2); +inext: R4 = [P2++]; /* address from config table */ + R2 = [P2++]; /* data from config table */ +#ifdef CONFIG_CPLB_INFO + P3 += 8; +#endif + + CC = R4 == -1; /* End of config table*/ + IF CC JUMP no_page_in_table; + + /* See if failed address > start address */ + CC = R4 <= R0(IU); + IF !CC JUMP inext; + + /* extract page size (17:16)*/ + R3 = EXTRACT(R2, R1.L) (Z); + + /* add page size to addr to get range */ + + P5 = R3; + P5 = P0 + (P5 << 2); /* scaled, for int access*/ + R3 = [P5]; + R3 = R3 + R4; + + /* See if failed address < (start address + page size) */ + CC = R0 < R3(IU); + IF !CC JUMP inext; + + /* We've found a CPLB in the config table that covers + * the faulting address, so install this CPLB into the + * last entry of the table. + */ + + P1.L = (ICPLB_DATA15 & 0xFFFF); /*ICPLB_DATA15*/ + P1.H = (ICPLB_DATA15 >> 16); + [P1] = R2; + [P1-0x100] = R4; +#ifdef CONFIG_CPLB_INFO + R3 = [P3]; + R3 += 1; + [P3] = R3; +#endif + + /* P4 points to IMEM_CONTROL, and R5 contains its old + * value, after we disabled ICPLBS. Re-enable them. + */ + + BITSET(R5,ENICPLB_P); + CLI R2; + SSYNC; /* SSYNC required before writing to IMEM_CONTROL. */ + .align 8; + [P4] = R5; + SSYNC; + STI R2; + + ( R7:0,P5:0 ) = [SP++]; + R0 = CPLB_RELOADED; + RTS; + +/* FAILED CASES*/ +no_page_in_table: + ( R7:0,P5:0 ) = [SP++]; + R0 = CPLB_NO_ADDR_MATCH; + RTS; +all_locked: + ( R7:0,P5:0 ) = [SP++]; + R0 = CPLB_NO_UNLOCKED; + RTS; +prot_violation: + ( R7:0,P5:0 ) = [SP++]; + R0 = CPLB_PROT_VIOL; + RTS; + +dcplb_write: + + /* if a DCPLB is marked as write-back (CPLB_WT==0), and + * it is clean (CPLB_DIRTY==0), then a write to the + * CPLB's page triggers a protection violation. We have to + * mark the CPLB as dirty, to indicate that there are + * pending writes associated with the CPLB. + */ + + P4.L = (DCPLB_STATUS & 0xFFFF); + P4.H = (DCPLB_STATUS >> 16); + P3.L = (DCPLB_DATA0 & 0xFFFF); + P3.H = (DCPLB_DATA0 >> 16); + R5 = [P4]; + + /* A protection violation can be caused by more than just writes + * to a clean WB page, so we have to ensure that: + * - It's a write + * - to a clean WB page + * - and is allowed in the mode the access occurred. + */ + + CC = BITTST(R5, 16); /* ensure it was a write*/ + IF !CC JUMP prot_violation; + + /* to check the rest, we have to retrieve the DCPLB.*/ + + /* The low half of DCPLB_STATUS is a bit mask*/ + + R2 = R5.L (Z); /* indicating which CPLB triggered the event.*/ + R3 = 30; /* so we can use this to determine the offset*/ + R2.L = SIGNBITS R2; + R2 = R2.L (Z); /* into the DCPLB table.*/ + R3 = R3 - R2; + P4 = R3; + P3 = P3 + (P4<<2); + R3 = [P3]; /* Retrieve the CPLB*/ + + /* Now we can check whether it's a clean WB page*/ + + CC = BITTST(R3, 14); /* 0==WB, 1==WT*/ + IF CC JUMP prot_violation; + CC = BITTST(R3, 7); /* 0 == clean, 1 == dirty*/ + IF CC JUMP prot_violation; + + /* Check whether the write is allowed in the mode that was active.*/ + + R2 = 1<<3; /* checking write in user mode*/ + CC = BITTST(R5, 17); /* 0==was user, 1==was super*/ + R5 = CC; + R2 <<= R5; /* if was super, check write in super mode*/ + R2 = R3 & R2; + CC = R2 == 0; + IF CC JUMP prot_violation; + + /* It's a genuine write-to-clean-page.*/ + + BITSET(R3, 7); /* mark as dirty*/ + [P3] = R3; /* and write back.*/ + CSYNC; + ( R7:0,P5:0 ) = [SP++]; + R0 = CPLB_RELOADED; + RTS; + +dcplb_miss_compare: + + /* Data CPLB Miss event. We need to choose a CPLB to + * evict, and then locate a new CPLB to install from the + * config table, that covers the faulting address. + */ + + P1.L = (DCPLB_DATA15 & 0xFFFF); + P1.H = (DCPLB_DATA15 >> 16); + + P4.L = (DCPLB_FAULT_ADDR & 0xFFFF); + P4.H = (DCPLB_FAULT_ADDR >> 16); + R4 = [P4]; + I0 = R4; + + /* The replacement procedure for DCPLBs*/ + + R6 = R1; /* Save for later*/ + + /* Turn off CPLBs while we work.*/ + P4.L = (DMEM_CONTROL & 0xFFFF); + P4.H = (DMEM_CONTROL >> 16); + R5 = [P4]; + BITCLR(R5,ENDCPLB_P); + CLI R0; + SSYNC; /* SSYNC required before writing to DMEM_CONTROL. */ + .align 8; + [P4] = R5; + SSYNC; + STI R0; + + /* Start looking for a CPLB to evict. Our order of preference + * is: invalid CPLBs, clean CPLBs, dirty CPLBs. Locked CPLBs + * are no good. + */ + + I1.L = (DCPLB_DATA0 & 0xFFFF); + I1.H = (DCPLB_DATA0 >> 16); + P1 = 3; + P2 = 16; + I2.L = dcplb_preference; + I2.H = dcplb_preference; + LSETUP(sdsearch1, edsearch1) LC0 = P1; +sdsearch1: + R0 = [I2++]; /* Get the bits we're interested in*/ + P0 = I1; /* Go back to start of table*/ + LSETUP (sdsearch2, edsearch2) LC1 = P2; +sdsearch2: + R1 = [P0++]; /* Fetch each installed CPLB in turn*/ + R2 = R1 & R0; /* and test for interesting bits.*/ + CC = R2 == 0; /* If none are set, it'll do.*/ + IF !CC JUMP skip_stack_check; + + R2 = [P0 - 0x104]; /* R2 - PageStart */ + P3.L = page_size_table; /* retrive end address */ + P3.H = page_size_table; /* retrive end address */ + R3 = 0x2; /* 0th - position, 2 bits -length */ + nop; /*Anamoly 05000209*/ + R7 = EXTRACT(R1,R3.l); + R7 = R7 << 2; /* Page size index offset */ + P5 = R7; + P3 = P3 + P5; + R7 = [P3]; /* page size in 1K bytes */ + + R7 = R7 << 0xA; /* in bytes * 1024*/ + R7 = R2 + R7; /* R7 - PageEnd */ + R4 = SP; /* Test SP is in range */ + + CC = R7 < R4; /* if PageEnd < SP */ + IF CC JUMP dfound_victim; + R3 = 0x284; /* stack length from start of trap till the point */ + /* 20 stack locations for future modifications */ + R4 = R4 + R3; + CC = R4 < R2; /* if SP + stacklen < PageStart */ + IF CC JUMP dfound_victim; +skip_stack_check: + +edsearch2: NOP; +edsearch1: NOP; + + /* If we got here, we didn't find a DCPLB we considered + * replacable, which means all of them were locked. + */ + + JUMP all_locked; +dfound_victim: + +#ifdef CONFIG_CPLB_INFO + R1 = [P0 - 0x104]; + P2.L = dpdt_table; + P2.H = dpdt_table; + P3.L = dpdt_swapcount_table; + P3.H = dpdt_swapcount_table; + P3 += -4; +dicount: + R2 = [P2]; + P2 += 8; + P3 += 8; + CC = R2==-1; + IF CC JUMP dicount_done; + CC = R1==R2; + IF !CC JUMP dicount; + R1 = [P3]; + R1 += 1; + [P3] = R1; + CSYNC; +dicount_done: +#endif + + /* Clean down the hardware loops*/ + R2 = 0; + LC1 = R2; + LC0 = R2; + + /* There's a suitable victim in [P0-4] (because we've + * advanced already). If it's a valid dirty write-back + * CPLB, we need to flush the pending writes first. + */ + + CC = BITTST(R1, 0); /* Is it valid?*/ + IF !CC JUMP Ddoverwrite;/* nope.*/ + CC = BITTST(R1, 7); /* Is it dirty?*/ + IF !CC JUMP Ddoverwrite (BP); /* Nope.*/ + CC = BITTST(R1, 14); /* Is it Write-Through?*/ + IF CC JUMP Ddoverwrite; /* Yep*/ + + /* This is a dirty page, so we need to flush all writes + * that are pending on the page. + */ + + /* Retrieve the page start address*/ + R0 = [P0 - 0x104]; + [--sp] = rets; + CALL dcplb_flush; /* R0==CPLB addr, R1==CPLB data*/ + rets = [sp++]; +Ddoverwrite: + + /* [P0-4] is a suitable victim CPLB, so we want to + * overwrite it by moving all the following CPLBs + * one space closer to the start. + */ + + R1.L = ((DCPLB_DATA15+4) & 0xFFFF); /*DCPLB_DATA15+4*/ + R1.H = ((DCPLB_DATA15+4) >> 16); + R0 = P0; + + /* If the victim happens to be in DCPLB15, + * we don't need to move anything. + */ + + CC = R1 == R0; + IF CC JUMP de_moved; + R1 = R1 - R0; + R1 >>= 2; + P1 = R1; + LSETUP(ds_move, de_move) LC0=P1; +ds_move: + R0 = [P0++]; /* move data */ + [P0 - 8] = R0; + R0 = [P0-0x104] /* move address */ +de_move: [P0-0x108] = R0; + + /* We've now made space in DCPLB15 for the new CPLB to be + * installed. The next stage is to locate a CPLB in the + * config table that covers the faulting address. + */ + +de_moved:NOP; + R0 = I0; /* Our faulting address */ + + P2.L = dpdt_table; + P2.H = dpdt_table; +#ifdef CONFIG_CPLB_INFO + P3.L = dpdt_swapcount_table; + P3.H = dpdt_swapcount_table; + P3 += -8; +#endif + + P1.L = page_size_table; + P1.H = page_size_table; + + /* An extraction pattern, to retrieve bits 17:16.*/ + + R1 = (16<<8)|2; +dnext: R4 = [P2++]; /* address */ + R2 = [P2++]; /* data */ +#ifdef CONFIG_CPLB_INFO + P3 += 8; +#endif + + CC = R4 == -1; + IF CC JUMP no_page_in_table; + + /* See if failed address > start address */ + CC = R4 <= R0(IU); + IF !CC JUMP dnext; + + /* extract page size (17:16)*/ + R3 = EXTRACT(R2, R1.L) (Z); + + /* add page size to addr to get range */ + + P5 = R3; + P5 = P1 + (P5 << 2); + R3 = [P5]; + R3 = R3 + R4; + + /* See if failed address < (start address + page size) */ + CC = R0 < R3(IU); + IF !CC JUMP dnext; + + /* We've found the CPLB that should be installed, so + * write it into CPLB15, masking off any caching bits + * if necessary. + */ + + P1.L = (DCPLB_DATA15 & 0xFFFF); + P1.H = (DCPLB_DATA15 >> 16); + + /* If the DCPLB has cache bits set, but caching hasn't + * been enabled, then we want to mask off the cache-in-L1 + * bit before installing. Moreover, if caching is off, we + * also want to ensure that the DCPLB has WT mode set, rather + * than WB, since WB pages still trigger first-write exceptions + * even when not caching is off, and the page isn't marked as + * cachable. Finally, we could mark the page as clean, not dirty, + * but we choose to leave that decision to the user; if the user + * chooses to have a CPLB pre-defined as dirty, then they always + * pay the cost of flushing during eviction, but don't pay the + * cost of first-write exceptions to mark the page as dirty. + */ + +#ifdef CONFIG_BLKFIN_WT + BITSET(R6, 14); /* Set WT*/ +#endif + + [P1] = R2; + [P1-0x100] = R4; +#ifdef CONFIG_CPLB_INFO + R3 = [P3]; + R3 += 1; + [P3] = R3; +#endif + + /* We've installed the CPLB, so re-enable CPLBs. P4 + * points to DMEM_CONTROL, and R5 is the value we + * last wrote to it, when we were disabling CPLBs. + */ + + BITSET(R5,ENDCPLB_P); + CLI R2; + .align 8; + [P4] = R5; + SSYNC; + STI R2; + + ( R7:0,P5:0 ) = [SP++]; + R0 = CPLB_RELOADED; + RTS; + +.data +.align 4; +page_size_table: +.byte4 0x00000400; /* 1K */ +.byte4 0x00001000; /* 4K */ +.byte4 0x00100000; /* 1M */ +.byte4 0x00400000; /* 4M */ + +.align 4; +dcplb_preference: +.byte4 0x00000001; /* valid bit */ +.byte4 0x00000082; /* dirty+lock bits */ +.byte4 0x00000002; /* lock bit */ diff --git a/cpu/bf533/cpu.c b/cpu/bf533/cpu.c new file mode 100644 index 00000000000..2c139f547da --- /dev/null +++ b/cpu/bf533/cpu.c @@ -0,0 +1,194 @@ +/* + * U-boot - cpu.c CPU specific functions + * + * Copyright (c) 2005 blackfin.uclinux.org + * + * (C) Copyright 2000-2004 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include +#include +#include +#include + +#define SSYNC() asm("ssync;") +#define CACHE_ON 1 +#define CACHE_OFF 0 + +/* Data Attibutes*/ + +#define SDRAM_IGENERIC (PAGE_SIZE_4MB | CPLB_L1_CHBL | CPLB_USER_RD | CPLB_VALID) +#define SDRAM_IKERNEL (PAGE_SIZE_4MB | CPLB_L1_CHBL | CPLB_USER_RD | CPLB_VALID | CPLB_LOCK) +#define L1_IMEMORY (PAGE_SIZE_1MB | CPLB_L1_CHBL | CPLB_USER_RD | CPLB_VALID | CPLB_LOCK) +#define SDRAM_INON_CHBL (PAGE_SIZE_4MB | CPLB_USER_RD | CPLB_VALID) + +#define ANOMALY_05000158 0x200 +#define SDRAM_DGENERIC (PAGE_SIZE_4MB | CPLB_L1_CHBL | CPLB_WT | CPLB_L1_AOW | CPLB_SUPV_WR | CPLB_USER_RD | CPLB_USER_WR | CPLB_VALID | ANOMALY_05000158) +#define SDRAM_DNON_CHBL (PAGE_SIZE_4MB | CPLB_WT | CPLB_L1_AOW | CPLB_SUPV_WR | CPLB_USER_WR | CPLB_USER_RD | CPLB_VALID | ANOMALY_05000158) +#define SDRAM_DKERNEL (PAGE_SIZE_4MB | CPLB_L1_CHBL | CPLB_WT | CPLB_L1_AOW | CPLB_USER_RD | CPLB_SUPV_WR | CPLB_USER_WR | CPLB_VALID | CPLB_LOCK | ANOMALY_05000158) +#define L1_DMEMORY (PAGE_SIZE_4KB | CPLB_L1_CHBL | CPLB_L1_AOW | CPLB_WT | CPLB_SUPV_WR | CPLB_USER_WR | CPLB_VALID | ANOMALY_05000158) +#define SDRAM_EBIU (PAGE_SIZE_4MB | CPLB_WT | CPLB_L1_AOW | CPLB_USER_RD | CPLB_USER_WR | CPLB_SUPV_WR | CPLB_VALID | ANOMALY_05000158) + +static unsigned int icplb_table[16][2]={ + {0xFFA00000, L1_IMEMORY}, + {0x00000000, SDRAM_IKERNEL}, /*SDRAM_Page1*/ + {0x00400000, SDRAM_IKERNEL}, /*SDRAM_Page1*/ + {0x07C00000, SDRAM_IKERNEL}, /*SDRAM_Page14*/ + {0x00800000, SDRAM_IGENERIC}, /*SDRAM_Page2*/ + {0x00C00000, SDRAM_IGENERIC}, /*SDRAM_Page2*/ + {0x01000000, SDRAM_IGENERIC}, /*SDRAM_Page4*/ + {0x01400000, SDRAM_IGENERIC}, /*SDRAM_Page5*/ + {0x01800000, SDRAM_IGENERIC}, /*SDRAM_Page6*/ + {0x01C00000, SDRAM_IGENERIC}, /*SDRAM_Page7*/ + {0x02000000, SDRAM_IGENERIC}, /*SDRAM_Page8*/ + {0x02400000, SDRAM_IGENERIC}, /*SDRAM_Page9*/ + {0x02800000, SDRAM_IGENERIC}, /*SDRAM_Page10*/ + {0x02C00000, SDRAM_IGENERIC}, /*SDRAM_Page11*/ + {0x03000000, SDRAM_IGENERIC}, /*SDRAM_Page12*/ + {0x03400000, SDRAM_IGENERIC}, /*SDRAM_Page13*/ +}; + +static unsigned int dcplb_table[16][2]={ + {0xFFA00000,L1_DMEMORY}, + {0x00000000,SDRAM_DKERNEL}, /*SDRAM_Page1*/ + {0x00400000,SDRAM_DKERNEL}, /*SDRAM_Page1*/ + {0x07C00000,SDRAM_DKERNEL}, /*SDRAM_Page15*/ + {0x00800000,SDRAM_DGENERIC}, /*SDRAM_Page2*/ + {0x00C00000,SDRAM_DGENERIC}, /*SDRAM_Page3*/ + {0x01000000,SDRAM_DGENERIC}, /*SDRAM_Page4*/ + {0x01400000,SDRAM_DGENERIC}, /*SDRAM_Page5*/ + {0x01800000,SDRAM_DGENERIC}, /*SDRAM_Page6*/ + {0x01C00000,SDRAM_DGENERIC}, /*SDRAM_Page7*/ + {0x02000000,SDRAM_DGENERIC}, /*SDRAM_Page8*/ + {0x02400000,SDRAM_DGENERIC}, /*SDRAM_Page9*/ + {0x02800000,SDRAM_DGENERIC}, /*SDRAM_Page10*/ + {0x02C00000,SDRAM_DGENERIC}, /*SDRAM_Page11*/ + {0x03000000,SDRAM_DGENERIC}, /*SDRAM_Page12*/ + {0x20000000,SDRAM_EBIU}, /*For Network */ +}; + + + + + +int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + __asm__ __volatile__ + ("cli r3;" + "P0 = %0;" + "JUMP (P0);" + : + : "r" (L1_ISRAM) + ); + + return 0; +} + +/* These functions are just used to satisfy the linker */ +int cpu_init(void) +{ + return 0; +} + +int cleanup_before_linux(void) +{ + return 0; +} + +void icache_enable(void) +{ + unsigned int *I0,*I1; + int i; + + I0 = (unsigned int *)ICPLB_ADDR0; + I1 = (unsigned int *)ICPLB_DATA0; + + for(i=0;i<16;i++){ + *I0++ = icplb_table[i][0]; + *I1++ = icplb_table[i][1]; + } + cli(); + SSYNC(); + *(unsigned int *)IMEM_CONTROL = IMC | ENICPLB; + SSYNC(); + sti(); +} + +void icache_disable(void) +{ + cli(); + SSYNC(); + *(unsigned int *)IMEM_CONTROL &= ~(IMC | ENICPLB); + SSYNC(); + sti(); +} + +int icache_status(void) +{ + unsigned int value; + value = *(unsigned int *)IMEM_CONTROL; + + if( value & (IMC|ENICPLB) ) + return CACHE_ON; + else + return CACHE_OFF; +} + +void dcache_enable(void) +{ + unsigned int *I0,*I1; + unsigned int temp; + int i; + I0 = (unsigned int *)DCPLB_ADDR0; + I1 = (unsigned int *)DCPLB_DATA0; + + for(i=0;i<16;i++){ + *I0++ = dcplb_table[i][0]; + *I1++ = dcplb_table[i][1]; + } + cli(); + temp = *(unsigned int *)DMEM_CONTROL; + SSYNC(); + *(unsigned int *)DMEM_CONTROL = ACACHE_BCACHE |ENDCPLB |PORT_PREF0|temp; + SSYNC(); + sti(); +} + + +void dcache_disable(void) +{ + cli(); + SSYNC(); + *(unsigned int *)DMEM_CONTROL &= ~(ACACHE_BCACHE |ENDCPLB |PORT_PREF0); + SSYNC(); + sti(); +} + +int dcache_status(void) +{ + unsigned int value; + value = *(unsigned int *)DMEM_CONTROL; + if( value & (ENDCPLB)) + return CACHE_ON; + else + return CACHE_OFF; +} diff --git a/cpu/bf533/cpu.h b/cpu/bf533/cpu.h new file mode 100644 index 00000000000..7ec33878eaf --- /dev/null +++ b/cpu/bf533/cpu.h @@ -0,0 +1,65 @@ +/* + * U-boot - cpu.h + * + * Copyright (c) 2005 blackfin.uclinux.org + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef _CPU_H_ +#define _CPU_H_ + +#include + +#define INTERNAL_IRQS (32) +#define NUM_IRQ_NODES 16 +#define DEF_INTERRUPT_FLAGS 1 +#define MAX_TIM_LOAD 0xFFFFFFFF + +void blackfin_irq_panic(int reason, struct pt_regs * reg); +extern void dump(struct pt_regs * regs); +void display_excp(void); +asmlinkage void evt_nmi(void); +asmlinkage void evt_exception(void); +asmlinkage void trap(void); +asmlinkage void evt_ivhw(void); +asmlinkage void evt_rst(void); +asmlinkage void evt_timer(void); +asmlinkage void evt_evt7(void); +asmlinkage void evt_evt8(void); +asmlinkage void evt_evt9(void); +asmlinkage void evt_evt10(void); +asmlinkage void evt_evt11(void); +asmlinkage void evt_evt12(void); +asmlinkage void evt_evt13(void); +asmlinkage void evt_soft_int1(void); +asmlinkage void evt_system_call(void); +void blackfin_irq_panic(int reason, struct pt_regs * regs); +void blackfin_free_irq(unsigned int irq, void *dev_id); +void call_isr(int irq, struct pt_regs * fp); +void blackfin_do_irq(int vec, struct pt_regs *fp); +void blackfin_init_IRQ(void); +void blackfin_enable_irq(unsigned int irq); +void blackfin_disable_irq(unsigned int irq); +extern int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); +int blackfin_request_irq(unsigned int irq, + void (*handler)(int, void *, struct pt_regs *), + unsigned long flags,const char *devname,void *dev_id); +void timer_init(void); +#endif diff --git a/cpu/bf533/flush.S b/cpu/bf533/flush.S new file mode 100644 index 00000000000..1f9ec9899e5 --- /dev/null +++ b/cpu/bf533/flush.S @@ -0,0 +1,402 @@ +/* Copyright (C) 2003 Analog Devices, Inc. All Rights Reserved. + * Copyright (C) 2004 LG SOft India. All Rights Reserved. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. + * + * Blackfin BF533/2.6 support : LG Soft India + */ +#define ASSEMBLY + +#include +#include +#include + +.text + +/* This is an external function being called by the user + * application through __flush_cache_all. Currently this function + * serves the purpose of flushing all the pending writes in + * in the instruction cache. + */ + +ENTRY(flush_instruction_cache) + [--SP] = ( R7:6, P5:4 ); + LINK 12; + SP += -12; + P5.H = (ICPLB_ADDR0 >> 16); + P5.L = (ICPLB_ADDR0 & 0xFFFF); + P4.H = (ICPLB_DATA0 >> 16); + P4.L = (ICPLB_DATA0 & 0xFFFF); + R7 = CPLB_VALID | CPLB_L1_CHBL; + R6 = 16; +inext: R0 = [P5++]; + R1 = [P4++]; + [--SP] = RETS; + CALL icplb_flush; /* R0 = page, R1 = data*/ + RETS = [SP++]; +iskip: R6 += -1; + CC = R6; + IF CC JUMP inext; + SSYNC; + SP += 12; + UNLINK; + ( R7:6, P5:4 ) = [SP++]; + RTS; + +/* This is an internal function to flush all pending + * writes in the cache associated with a particular ICPLB. + * + * R0 - page's start address + * R1 - CPLB's data field. + */ + +.align 2 +ENTRY(icplb_flush) + [--SP] = ( R7:0, P5:0 ); + [--SP] = LC0; + [--SP] = LT0; + [--SP] = LB0; + [--SP] = LC1; + [--SP] = LT1; + [--SP] = LB1; + + /* If it's a 1K or 4K page, then it's quickest to + * just systematically flush all the addresses in + * the page, regardless of whether they're in the + * cache, or dirty. If it's a 1M or 4M page, there + * are too many addresses, and we have to search the + * cache for lines corresponding to the page. + */ + + CC = BITTST(R1, 17); /* 1MB or 4MB */ + IF !CC JUMP iflush_whole_page; + + /* We're only interested in the page's size, so extract + * this from the CPLB (bits 17:16), and scale to give an + * offset into the page_size and page_prefix tables. + */ + + R1 <<= 14; + R1 >>= 30; + R1 <<= 2; + + /* We can also determine the sub-bank used, because this is + * taken from bits 13:12 of the address. + */ + + R3 = ((12<<8)|2); /* Extraction pattern */ + nop; /*Anamoly 05000209*/ + R4 = EXTRACT(R0, R3.L) (Z); /* Extract bits*/ + R3.H = R4.L << 0 ; /* Save in extraction pattern for later deposit.*/ + + + /* So: + * R0 = Page start + * R1 = Page length (actually, offset into size/prefix tables) + * R3 = sub-bank deposit values + * + * The cache has 2 Ways, and 64 sets, so we iterate through + * the sets, accessing the tag for each Way, for our Bank and + * sub-bank, looking for dirty, valid tags that match our + * address prefix. + */ + + P5.L = (ITEST_COMMAND & 0xFFFF); + P5.H = (ITEST_COMMAND >> 16); + P4.L = (ITEST_DATA0 & 0xFFFF); + P4.H = (ITEST_DATA0 >> 16); + + P0.L = page_prefix_table; + P0.H = page_prefix_table; + P1 = R1; + R5 = 0; /* Set counter*/ + P0 = P1 + P0; + R4 = [P0]; /* This is the address prefix*/ + + /* We're reading (bit 1==0) the tag (bit 2==0), and we + * don't care about which double-word, since we're only + * fetching tags, so we only have to set Set, Bank, + * Sub-bank and Way. + */ + + P2 = 4; + LSETUP (ifs1, ife1) LC1 = P2; +ifs1: P0 = 32; /* iterate over all sets*/ + LSETUP (ifs0, ife0) LC0 = P0; +ifs0: R6 = R5 << 5; /* Combine set*/ + R6.H = R3.H << 0 ; /* and sub-bank*/ + [P5] = R6; /* Issue Command*/ + SSYNC; /* CSYNC will not work here :(*/ + R7 = [P4]; /* and read Tag.*/ + CC = BITTST(R7, 0); /* Check if valid*/ + IF !CC JUMP ifskip; /* and skip if not.*/ + + /* Compare against the page address. First, plant bits 13:12 + * into the tag, since those aren't part of the returned data. + */ + + R7 = DEPOSIT(R7, R3); /* set 13:12*/ + R1 = R7 & R4; /* Mask off lower bits*/ + CC = R1 == R0; /* Compare against page start.*/ + IF !CC JUMP ifskip; /* Skip it if it doesn't match.*/ + + /* Tag address matches against page, so this is an entry + * we must flush. + */ + + R7 >>= 10; /* Mask off the non-address bits*/ + R7 <<= 10; + P3 = R7; + IFLUSH [P3]; /* And flush the entry*/ +ifskip: +ife0: R5 += 1; /* Advance to next Set*/ +ife1: NOP; + +ifinished: + SSYNC; /* Ensure the data gets out to mem.*/ + + /*Finished. Restore context.*/ + LB1 = [SP++]; + LT1 = [SP++]; + LC1 = [SP++]; + LB0 = [SP++]; + LT0 = [SP++]; + LC0 = [SP++]; + ( R7:0, P5:0 ) = [SP++]; + RTS; + +iflush_whole_page: + /* It's a 1K or 4K page, so quicker to just flush the + * entire page. + */ + + P1 = 32; /* For 1K pages*/ + P2 = P1 << 2; /* For 4K pages*/ + P0 = R0; /* Start of page*/ + CC = BITTST(R1, 16); /* Whether 1K or 4K*/ + IF CC P1 = P2; + P1 += -1; /* Unroll one iteration*/ + SSYNC; + IFLUSH [P0++]; /* because CSYNC can't end loops.*/ + LSETUP (isall, ieall) LC0 = P1; +isall:IFLUSH [P0++]; +ieall: NOP; + SSYNC; + JUMP ifinished; + +/* This is an external function being called by the user + * application through __flush_cache_all. Currently this function + * serves the purpose of flushing all the pending writes in + * in the data cache. + */ + +ENTRY(flush_data_cache) + [--SP] = ( R7:6, P5:4 ); + LINK 12; + SP += -12; + P5.H = (DCPLB_ADDR0 >> 16); + P5.L = (DCPLB_ADDR0 & 0xFFFF); + P4.H = (DCPLB_DATA0 >> 16); + P4.L = (DCPLB_DATA0 & 0xFFFF); + R7 = CPLB_VALID | CPLB_L1_CHBL | CPLB_DIRTY (Z); + R6 = 16; +next: R0 = [P5++]; + R1 = [P4++]; + CC = BITTST(R1, 14); /* Is it write-through?*/ + IF CC JUMP skip; /* If so, ignore it.*/ + R2 = R1 & R7; /* Is it a dirty, cached page?*/ + CC = R2; + IF !CC JUMP skip; /* If not, ignore it.*/ + [--SP] = RETS; + CALL dcplb_flush; /* R0 = page, R1 = data*/ + RETS = [SP++]; +skip: R6 += -1; + CC = R6; + IF CC JUMP next; + SSYNC; + SP += 12; + UNLINK; + ( R7:6, P5:4 ) = [SP++]; + RTS; + +/* This is an internal function to flush all pending + * writes in the cache associated with a particular DCPLB. + * + * R0 - page's start address + * R1 - CPLB's data field. + */ + +.align 2 +ENTRY(dcplb_flush) + [--SP] = ( R7:0, P5:0 ); + [--SP] = LC0; + [--SP] = LT0; + [--SP] = LB0; + [--SP] = LC1; + [--SP] = LT1; + [--SP] = LB1; + + /* If it's a 1K or 4K page, then it's quickest to + * just systematically flush all the addresses in + * the page, regardless of whether they're in the + * cache, or dirty. If it's a 1M or 4M page, there + * are too many addresses, and we have to search the + * cache for lines corresponding to the page. + */ + + CC = BITTST(R1, 17); /* 1MB or 4MB */ + IF !CC JUMP dflush_whole_page; + + /* We're only interested in the page's size, so extract + * this from the CPLB (bits 17:16), and scale to give an + * offset into the page_size and page_prefix tables. + */ + + R1 <<= 14; + R1 >>= 30; + R1 <<= 2; + + /* The page could be mapped into Bank A or Bank B, depending + * on (a) whether both banks are configured as cache, and + * (b) on whether address bit A[x] is set. x is determined + * by DCBS in DMEM_CONTROL + */ + + R2 = 0; /* Default to Bank A (Bank B would be 1)*/ + + P0.L = (DMEM_CONTROL & 0xFFFF); + P0.H = (DMEM_CONTROL >> 16); + + R3 = [P0]; /* If Bank B is not enabled as cache*/ + CC = BITTST(R3, 2); /* then Bank A is our only option.*/ + IF CC JUMP bank_chosen; + + R4 = 1<<14; /* If DCBS==0, use A[14].*/ + R5 = R4 << 7; /* If DCBS==1, use A[23];*/ + CC = BITTST(R3, 4); + IF CC R4 = R5; /* R4 now has either bit 14 or bit 23 set.*/ + R5 = R0 & R4; /* Use it to test the Page address*/ + CC = R5; /* and if that bit is set, we use Bank B,*/ + R2 = CC; /* else we use Bank A.*/ + R2 <<= 23; /* The Bank selection's at posn 23.*/ + +bank_chosen: + + /* We can also determine the sub-bank used, because this is + * taken from bits 13:12 of the address. + */ + + R3 = ((12<<8)|2); /* Extraction pattern */ + nop; /*Anamoly 05000209*/ + R4 = EXTRACT(R0, R3.L) (Z); /* Extract bits*/ + R3.H = R4.L << 0 ; /* Save in extraction pattern for later deposit.*/ + + /* So: + * R0 = Page start + * R1 = Page length (actually, offset into size/prefix tables) + * R2 = Bank select mask + * R3 = sub-bank deposit values + * + * The cache has 2 Ways, and 64 sets, so we iterate through + * the sets, accessing the tag for each Way, for our Bank and + * sub-bank, looking for dirty, valid tags that match our + * address prefix. + */ + + P5.L = (DTEST_COMMAND & 0xFFFF); + P5.H = (DTEST_COMMAND >> 16); + P4.L = (DTEST_DATA0 & 0xFFFF); + P4.H = (DTEST_DATA0 >> 16); + + P0.L = page_prefix_table; + P0.H = page_prefix_table; + P1 = R1; + R5 = 0; /* Set counter*/ + P0 = P1 + P0; + R4 = [P0]; /* This is the address prefix*/ + + + /* We're reading (bit 1==0) the tag (bit 2==0), and we + * don't care about which double-word, since we're only + * fetching tags, so we only have to set Set, Bank, + * Sub-bank and Way. + */ + + P2 = 2; + LSETUP (fs1, fe1) LC1 = P2; +fs1: P0 = 64; /* iterate over all sets*/ + LSETUP (fs0, fe0) LC0 = P0; +fs0: R6 = R5 << 5; /* Combine set*/ + R6.H = R3.H << 0 ; /* and sub-bank*/ + R6 = R6 | R2; /* and Bank. Leave Way==0 at first.*/ + BITSET(R6,14); + [P5] = R6; /* Issue Command*/ + SSYNC; + R7 = [P4]; /* and read Tag.*/ + CC = BITTST(R7, 0); /* Check if valid*/ + IF !CC JUMP fskip; /* and skip if not.*/ + CC = BITTST(R7, 1); /* Check if dirty*/ + IF !CC JUMP fskip; /* and skip if not.*/ + + /* Compare against the page address. First, plant bits 13:12 + * into the tag, since those aren't part of the returned data. + */ + + R7 = DEPOSIT(R7, R3); /* set 13:12*/ + R1 = R7 & R4; /* Mask off lower bits*/ + CC = R1 == R0; /* Compare against page start.*/ + IF !CC JUMP fskip; /* Skip it if it doesn't match.*/ + + /* Tag address matches against page, so this is an entry + * we must flush. + */ + + R7 >>= 10; /* Mask off the non-address bits*/ + R7 <<= 10; + P3 = R7; + SSYNC; + FLUSHINV [P3]; /* And flush the entry*/ +fskip: +fe0: R5 += 1; /* Advance to next Set*/ +fe1: BITSET(R2, 26); /* Go to next Way.*/ + +dfinished: + SSYNC; /* Ensure the data gets out to mem.*/ + + /*Finished. Restore context.*/ + LB1 = [SP++]; + LT1 = [SP++]; + LC1 = [SP++]; + LB0 = [SP++]; + LT0 = [SP++]; + LC0 = [SP++]; + ( R7:0, P5:0 ) = [SP++]; + RTS; + +dflush_whole_page: + + /* It's a 1K or 4K page, so quicker to just flush the + * entire page. + */ + + P1 = 32; /* For 1K pages*/ + P2 = P1 << 2; /* For 4K pages*/ + P0 = R0; /* Start of page*/ + CC = BITTST(R1, 16); /* Whether 1K or 4K*/ + IF CC P1 = P2; + P1 += -1; /* Unroll one iteration*/ + SSYNC; + FLUSHINV [P0++]; /* because CSYNC can't end loops.*/ + LSETUP (eall, eall) LC0 = P1; +eall: FLUSHINV [P0++]; + SSYNC; + JUMP dfinished; + +.align 4; +page_prefix_table: +.byte4 0xFFFFFC00; /* 1K */ +.byte4 0xFFFFF000; /* 4K */ +.byte4 0xFFF00000; /* 1M */ +.byte4 0xFFC00000; /* 4M */ +.page_prefix_table.end: diff --git a/cpu/bf533/interrupt.S b/cpu/bf533/interrupt.S new file mode 100644 index 00000000000..b4d2579c44c --- /dev/null +++ b/cpu/bf533/interrupt.S @@ -0,0 +1,391 @@ +/* + * U-boot - interrupt.S Processing of interrupts and exception handling + * + * Copyright (c) 2005 blackfin.uclinux.org + * + * (C) Copyright 2000-2004 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * This file is based on interrupt.S + * + * Copyright (C) 2003 Metrowerks, Inc. + * Copyright (C) 2002 Arcturus Networks Ltd. Ted Ma + * Copyright (C) 1998 D. Jeff Dionne , + * Kenneth Albanowski , + * The Silver Hammer Group, Ltd. + * + * (c) 1995, Dionne & Associates + * (c) 1995, DKG Display Tech. + * + * This file is also based on exception.asm + * (C) Copyright 2001-2005 - Analog Devices, Inc. All rights reserved. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#define ASSEMBLY + +#include +#include +#include +#include + +.global blackfin_irq_panic; + +.text +.align 2 + +#ifndef CONFIG_KGDB +.global evt_emulation +evt_emulation: + SAVE_CONTEXT + r0 = IRQ_EMU; + r1 = seqstat; + sp += -12; + call blackfin_irq_panic; + sp += 12; + rte; +#endif + +.global evt_nmi +evt_nmi: + SAVE_CONTEXT + r0 = IRQ_NMI; + r1 = RETN; + sp += -12; + call blackfin_irq_panic; + sp += 12; + +_evt_nmi_exit: + rtn; + +.global trap +trap: + [--sp] = r0; + [--sp] = r1; + [--sp] = p0; + [--sp] = p1; + [--sp] = astat; + r0 = seqstat; + R0 <<= 26; + R0 >>= 26; + p0 = r0; + p1.l = EVTABLE; + p1.h = EVTABLE; + p0 = p1 + (p0 << 1); + r1 = W[p0] (Z); + p1 = r1; + jump (pc + p1); + +.global _EVENT1 +_EVENT1: + RAISE 14; + JUMP.S _EXIT; + +.global _EVENT2 +_EVENT2: + RAISE 14; + JUMP.S _EXIT; + +.global _EVENT3 +_EVENT3: + RAISE 14; + JUMP.S _EXIT; + +.global _EVENT4 +_EVENT4: + RAISE 14; + JUMP.S _EXIT; + +.global _EVENT5 +_EVENT5: + RAISE 14; + JUMP.S _EXIT; + +.global _EVENT6 +_EVENT6: + RAISE 14; + JUMP.S _EXIT; + +.global _EVENT7 +_EVENT7: + RAISE 15; + JUMP.S _EXIT; + +.global _EVENT8 +_EVENT8: + RAISE 14; + JUMP.S _EXIT; + +.global _EVENT9 +_EVENT9: + RAISE 14; + JUMP.S _EXIT; + +.global _EVENT10 +_EVENT10: + RAISE 14; + JUMP.S _EXIT; + +.global _EVENT11 +_EVENT11: + RAISE 14; + JUMP.S _EXIT; + +.global _EVENT12 +_EVENT12: + RAISE 14; + JUMP.S _EXIT; + +.global _EVENT13 +_EVENT13: + RAISE 14; + JUMP.S _EXIT; + +.global _EVENT14 +_EVENT14: +/* RAISE 14; */ + CALL _cplb_hdr; + JUMP.S _EXIT; + +.global _EVENT19 +_EVENT19: + RAISE 14; + JUMP.S _EXIT; + +.global _EVENT20 +_EVENT20: + RAISE 14; + JUMP.S _EXIT; + +.global _EVENT21 +_EVENT21: + RAISE 14; + JUMP.S _EXIT; + +.global _EXIT +_EXIT: + ASTAT = [sp++]; + p1 = [sp++]; + p0 = [sp++]; + r1 = [sp++]; + r0 = [sp++]; + RTX; + +EVTABLE: + .byte2 0x0000; + .byte2 0x0000; + .byte2 0x0000; + .byte2 0x0000; + .byte2 0x0000; + .byte2 0x0000; + .byte2 0x0000; + .byte2 0x0000; + .byte2 0x0000; + .byte2 0x0000; + .byte2 0x0000; + .byte2 0x0000; + .byte2 0x0000; + .byte2 0x0000; + .byte2 0x0000; + .byte2 0x0000; + .byte2 0x003E; + .byte2 0x0042; + .byte4 0x0000; + .byte4 0x0000; + .byte4 0x0000; + .byte4 0x0000; + .byte4 0x0000; + .byte4 0x0000; + .byte4 0x0000; + .byte2 0x0000; + .byte2 0x001E; + .byte2 0x0022; + .byte2 0x0032; + .byte2 0x002e; + .byte2 0x0002; + .byte2 0x0036; + .byte2 0x002A; + .byte2 0x001A; + .byte2 0x0016; + .byte2 0x000A; + .byte2 0x000E; + .byte2 0x0012; + .byte2 0x0006; + .byte2 0x0026; + +.global evt_rst +evt_rst: + SAVE_CONTEXT + r0 = IRQ_RST; + r1 = RETN; + sp += -12; + call do_reset; + sp += 12; + +_evt_rst_exit: + rtn; + +irq_panic: + r0 = IRQ_EVX; + r1 = sp; + sp += -12; + call blackfin_irq_panic; + sp += 12; + +.global evt_ivhw +evt_ivhw: + SAVE_CONTEXT + RAISE 14; + +_evt_ivhw_exit: + rti; + +.global evt_timer +evt_timer: + SAVE_CONTEXT + r0 = IRQ_CORETMR; + sp += -12; + /* Polling method used now. */ + /* call timer_int; */ + sp += 12; + RESTORE_CONTEXT + rti; + nop; + +.global evt_evt7 +evt_evt7: + SAVE_CONTEXT + r0 = 7; + sp += -12; + call process_int; + sp += 12; + +evt_evt7_exit: + RESTORE_CONTEXT + rti; + +.global evt_evt8 +evt_evt8: + SAVE_CONTEXT + r0 = 8; + sp += -12; + call process_int; + sp += 12; + +evt_evt8_exit: + RESTORE_CONTEXT + rti; + +.global evt_evt9 +evt_evt9: + SAVE_CONTEXT + r0 = 9; + sp += -12; + call process_int; + sp += 12; + +evt_evt9_exit: + RESTORE_CONTEXT + rti; + +.global evt_evt10 +evt_evt10: + SAVE_CONTEXT + r0 = 10; + sp += -12; + call process_int; + sp += 12; + +evt_evt10_exit: + RESTORE_CONTEXT + rti; + +.global evt_evt11 +evt_evt11: + SAVE_CONTEXT + r0 = 11; + sp += -12; + call process_int; + sp += 12; + +evt_evt11_exit: + RESTORE_CONTEXT + rti; + +.global evt_evt12 +evt_evt12: + SAVE_CONTEXT + r0 = 12; + sp += -12; + call process_int; + sp += 12; +evt_evt12_exit: + RESTORE_CONTEXT + rti; + +.global evt_evt13 +evt_evt13: + SAVE_CONTEXT + r0 = 13; + sp += -12; + call process_int; + sp += 12; + +evt_evt13_exit: + RESTORE_CONTEXT + rti; + +.global evt_system_call +evt_system_call: + [--sp] = r0; + [--SP] = RETI; + r0 = [sp++]; + r0 += 2; + [--sp] = r0; + RETI = [SP++]; + r0 = [SP++]; + SAVE_CONTEXT + sp += -12; + call display_excp; + sp += 12; + RESTORE_CONTEXT + RTI; + +evt_system_call_exit: + rti; + +.global evt_soft_int1 +evt_soft_int1: + [--sp] = r0; + [--SP] = RETI; + r0 = [sp++]; + r0 += 2; + [--sp] = r0; + RETI = [SP++]; + r0 = [SP++]; + SAVE_CONTEXT + sp += -12; + call display_excp; + sp += 12; + RESTORE_CONTEXT + RTI; + +evt_soft_int1_exit: + rti; diff --git a/cpu/bf533/interrupts.c b/cpu/bf533/interrupts.c new file mode 100644 index 00000000000..df1a25ec755 --- /dev/null +++ b/cpu/bf533/interrupts.c @@ -0,0 +1,165 @@ +/* + * U-boot - interrupts.c Interrupt related routines + * + * Copyright (c) 2005 blackfin.uclinux.org + * + * This file is based on interrupts.c + * Copyright 1996 Roman Zippel + * Copyright 1999 D. Jeff Dionne + * Copyright 2000-2001 Lineo, Inc. D. Jefff Dionne + * Copyright 2002 Arcturus Networks Inc. MaTed + * Copyright 2003 Metrowerks/Motorola + * Copyright 2003 Bas Vermeulen , + * BuyWays B.V. (www.buyways.nl) + * + * (C) Copyright 2000-2004 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include "cpu.h" + +static ulong timestamp; +static ulong last_time; +static int int_flag; + +int irq_flags; /* needed by asm-blackfin/system.h */ + +/* Functions just to satisfy the linker */ + +/* + * This function is derived from PowerPC code (read timebase as long long). + * On BF533 it just returns the timer value. + */ +unsigned long long get_ticks(void) +{ + return get_timer(0); +} + +/* + * This function is derived from PowerPC code (timebase clock frequency). + * On BF533 it returns the number of timer ticks per second. + */ +ulong get_tbclk (void) +{ + ulong tbclk; + + tbclk = CFG_HZ; + return tbclk; +} + +void enable_interrupts(void) +{ + restore_flags(int_flag); +} + +int disable_interrupts(void) +{ + save_and_cli(int_flag); + return 1; +} + +int interrupt_init(void) +{ + return (0); +} + +void udelay(unsigned long usec) +{ + unsigned long delay, start, stop; + unsigned long cclk; + cclk = (CONFIG_CCLK_HZ); + + while ( usec > 1 ) { + /* + * how many clock ticks to delay? + * - request(in useconds) * clock_ticks(Hz) / useconds/second + */ + if (usec < 1000) { + delay = (usec * (cclk/244)) >> 12 ; + usec = 0; + } else { + delay = (1000 * (cclk/244)) >> 12 ; + usec -= 1000; + } + + asm volatile (" %0 = CYCLES;": "=g"(start)); + do { + asm volatile (" %0 = CYCLES; ": "=g"(stop)); + } while (stop - start < delay); + } + + return; +} + +void timer_init(void) +{ + *pTCNTL = 0x1; + *pTSCALE = 0x0; + *pTCOUNT = MAX_TIM_LOAD; + *pTPERIOD = MAX_TIM_LOAD; + *pTCNTL = 0x7; + asm("CSYNC;"); + + timestamp = 0; + last_time = 0; +} + +/* Any network command or flash + * command is started get_timer shall + * be called before TCOUNT gets reset, + * to implement the accurate timeouts. + * + * How ever milliconds doesn't return + * the number that has been elapsed from + * the last reset. + * + * As get_timer is used in the u-boot + * only for timeouts this should be + * sufficient + */ +ulong get_timer(ulong base) +{ + ulong milisec; + + /* Number of clocks elapsed */ + ulong clocks = (MAX_TIM_LOAD - (*pTCOUNT)); + + /* Find if the TCOUNT is reset + timestamp gives the number of times + TCOUNT got reset */ + if(clocks < last_time) + timestamp++; + last_time = clocks; + + /* Get the number of milliseconds */ + milisec = clocks/(CONFIG_CCLK_HZ / 1000); + + /* Find the number of millisonds + that got elapsed before this TCOUNT + cycle */ + milisec += timestamp * (MAX_TIM_LOAD/(CONFIG_CCLK_HZ / 1000)); + + return (milisec - base); +} diff --git a/cpu/bf533/ints.c b/cpu/bf533/ints.c new file mode 100644 index 00000000000..859f4b2f098 --- /dev/null +++ b/cpu/bf533/ints.c @@ -0,0 +1,107 @@ +/* + * U-boot - ints.c Interrupt related routines + * + * Copyright (c) 2005 blackfin.uclinux.org + * + * This file is based on ints.c + * + * Apr18 2003, Changed by HuTao to support interrupt cascading for Blackfin + * drivers + * + * Copyright 1996 Roman Zippel + * Copyright 1999 D. Jeff Dionne + * Copyright 2000-2001 Lineo, Inc. D. Jefff Dionne + * Copyright 2002 Arcturus Networks Inc. MaTed + * Copyright 2003 Metrowerks/Motorola + * + * (C) Copyright 2000-2004 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "cpu.h" + +void blackfin_irq_panic(int reason, struct pt_regs *regs) +{ + printf("\n\nException: IRQ 0x%x entered\n", reason); + printf("code=[0x%x], ", (unsigned int) (regs->seqstat & 0x3f)); + printf("stack frame=0x%x, ", (unsigned int) regs); + printf("bad PC=0x%04x\n", (unsigned int) regs->pc); + dump(regs); + printf("Unhandled IRQ or exceptions!\n"); + printf("Please reset the board \n"); +} + +void blackfin_init_IRQ(void) +{ + *(unsigned volatile long *) (SIC_IMASK) = SIC_UNMASK_ALL; + cli(); +#ifndef CONFIG_KGDB + *(unsigned volatile long *) (EVT_EMULATION_ADDR) = 0x0; +#endif + *(unsigned volatile long *) (EVT_NMI_ADDR) = + (unsigned volatile long) evt_nmi; + *(unsigned volatile long *) (EVT_EXCEPTION_ADDR) = + (unsigned volatile long) trap; + *(unsigned volatile long *) (EVT_HARDWARE_ERROR_ADDR) = + (unsigned volatile long) evt_ivhw; + *(unsigned volatile long *) (EVT_RESET_ADDR) = + (unsigned volatile long) evt_rst; + *(unsigned volatile long *) (EVT_TIMER_ADDR) = + (unsigned volatile long) evt_timer; + *(unsigned volatile long *) (EVT_IVG7_ADDR) = + (unsigned volatile long) evt_evt7; + *(unsigned volatile long *) (EVT_IVG8_ADDR) = + (unsigned volatile long) evt_evt8; + *(unsigned volatile long *) (EVT_IVG9_ADDR) = + (unsigned volatile long) evt_evt9; + *(unsigned volatile long *) (EVT_IVG10_ADDR) = + (unsigned volatile long) evt_evt10; + *(unsigned volatile long *) (EVT_IVG11_ADDR) = + (unsigned volatile long) evt_evt11; + *(unsigned volatile long *) (EVT_IVG12_ADDR) = + (unsigned volatile long) evt_evt12; + *(unsigned volatile long *) (EVT_IVG13_ADDR) = + (unsigned volatile long) evt_evt13; + *(unsigned volatile long *) (EVT_IVG14_ADDR) = + (unsigned volatile long) evt_system_call; + *(unsigned volatile long *) (EVT_IVG15_ADDR) = + (unsigned volatile long) evt_soft_int1; + *(volatile unsigned long *) ILAT = 0; + asm("csync;"); + sti(); + *(volatile unsigned long *) IMASK = 0xffbf; + asm("csync;"); +} + +void display_excp(void) +{ + printf("Exception!\n"); +} diff --git a/cpu/bf533/serial.c b/cpu/bf533/serial.c new file mode 100644 index 00000000000..8f0cd1649d6 --- /dev/null +++ b/cpu/bf533/serial.c @@ -0,0 +1,194 @@ +/* + * U-boot - serial.c Serial driver for BF533 + * + * Copyright (c) 2005 blackfin.uclinux.org + * + * This file is based on + * bf533_serial.c: Serial driver for BlackFin BF533 DSP internal UART. + * Copyright (c) 2003 Bas Vermeulen , + * BuyWays B.V. (www.buyways.nl) + * + * Based heavily on blkfinserial.c + * blkfinserial.c: Serial driver for BlackFin DSP internal USRTs. + * Copyright(c) 2003 Metrowerks + * Copyright(c) 2001 Tony Z. Kou + * Copyright(c) 2001-2002 Arcturus Networks Inc. + * + * Based on code from 68328 version serial driver imlpementation which was: + * Copyright (C) 1995 David S. Miller + * Copyright (C) 1998 Kenneth Albanowski + * Copyright (C) 1998, 1999 D. Jeff Dionne + * Copyright (C) 1999 Vladimir Gurevich + * + * (C) Copyright 2000-2004 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include "bf533_serial.h" + +unsigned long pll_div_fact; + +void calc_baud(void) +{ + unsigned char i; + int temp; + + for(i = 0; i < sizeof(baud_table)/sizeof(int); i++) { + temp = CONFIG_SCLK_HZ/(baud_table[i]*8); + if ( temp && 0x1 == 1 ) { + temp++; + } + temp = temp/2; + hw_baud_table[i].dl_high = (temp >> 8)& 0xFF; + hw_baud_table[i].dl_low = (temp) & 0xFF; + } +} + +void serial_setbrg(void) +{ + int i; + DECLARE_GLOBAL_DATA_PTR; + + calc_baud(); + + for (i = 0; i < sizeof(baud_table) / sizeof(int); i++) { + if (gd->baudrate == baud_table[i]) + break; + } + + /* Enable UART */ + *pUART_GCTL |= UART_GCTL_UCEN; + asm("ssync;"); + + /* Set DLAB in LCR to Access DLL and DLH */ + ACCESS_LATCH; + asm("ssync;"); + + *pUART_DLL = hw_baud_table[i].dl_low; + asm("ssync;"); + *pUART_DLH = hw_baud_table[i].dl_high; + asm("ssync;"); + + /* Clear DLAB in LCR to Access THR RBR IER */ + ACCESS_PORT_IER; + asm("ssync;"); + + /* Enable ERBFI and ELSI interrupts + * to poll SIC_ISR register*/ + *pUART_IER = UART_IER_ELSI | UART_IER_ERBFI | UART_IER_ETBEI; + asm("ssync;"); + + /* Set LCR to Word Lengh 8-bit word select */ + *pUART_LCR = UART_LCR_WLS8; + asm("ssync;"); + + return; +} + +int serial_init(void) +{ + serial_setbrg(); + return (0); +} + +void serial_putc(const char c) +{ + if ((*pUART_LSR) & UART_LSR_TEMT) + { + if (c == '\n') + serial_putc('\r'); + + local_put_char(c); + } + + while (!((*pUART_LSR) & UART_LSR_TEMT)) + SYNC_ALL; + + return; +} + +int serial_tstc(void) +{ + if (*pUART_LSR & UART_LSR_DR) + return 1; + else + return 0; +} + +int serial_getc(void) +{ + unsigned short uart_lsr_val, uart_rbr_val; + unsigned long isr_val; + int ret; + + /* Poll for RX Interrupt */ + while (!((isr_val = *(volatile unsigned long *)SIC_ISR) & IRQ_UART_RX_BIT)); + asm("csync;"); + + uart_lsr_val = *pUART_LSR; /* Clear status bit */ + uart_rbr_val = *pUART_RBR; /* getc() */ + + if (isr_val & IRQ_UART_ERROR_BIT) { + ret = -1; + } + else + { + ret = uart_rbr_val & 0xff; + } + + return ret; +} + +void serial_puts(const char *s) +{ + while (*s) { + serial_putc(*s++); + } +} + +static void local_put_char(char ch) +{ + int flags = 0; + unsigned long isr_val; + + save_and_cli(flags); + + /* Poll for TX Interruput */ + while (!((isr_val = *pSIC_ISR) & IRQ_UART_TX_BIT)); + asm("csync;"); + + *pUART_THR = ch; /* putc() */ + + if (isr_val & IRQ_UART_ERROR_BIT) { + printf("?"); + } + + restore_flags(flags); + + return ; +} diff --git a/cpu/bf533/start.S b/cpu/bf533/start.S new file mode 100644 index 00000000000..7414d8873d2 --- /dev/null +++ b/cpu/bf533/start.S @@ -0,0 +1,435 @@ +/* + * U-boot - start.S Startup file of u-boot for BF533 + * + * Copyright (c) 2005 blackfin.uclinux.org + * + * This file is based on head.S + * Copyright (c) 2003 Metrowerks/Motorola + * Copyright (C) 1998 D. Jeff Dionne , + * Kenneth Albanowski , + * The Silver Hammer Group, Ltd. + * (c) 1995, Dionne & Associates + * (c) 1995, DKG Display Tech. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/* + * Note: A change in this file subsequently requires a change in + * board/$(board_name)/config.mk for a valid u-boot.bin + */ + +#define ASSEMBLY + +#include +#include +#include +#include + +#if (CONFIG_CCLK_DIV == 1) +#define CONFIG_CCLK_ACT_DIV CCLK_DIV1 +#endif +#if (CONFIG_CCLK_DIV == 2) +#define CONFIG_CCLK_ACT_DIV CCLK_DIV2 +#endif +#if (CONFIG_CCLK_DIV == 4) +#define CONFIG_CCLK_ACT_DIV CCLK_DIV4 +#endif +#if (CONFIG_CCLK_DIV == 8) +#define CONFIG_CCLK_ACT_DIV CCLK_DIV8 +#endif +#ifndef CONFIG_CCLK_ACT_DIV +#define CONFIG_CCLK_ACT_DIV CONFIG_CCLK_DIV_not_defined_properly +#endif + +.global _stext; +.global __bss_start; +.global start; +.global _start; +.global _rambase; +.global _ramstart; +.global _ramend; +.global _bf533_data_dest; +.global _bf533_data_size; +.global edata; +.global _initialize; +.global _exit; +.global flashdataend; + +.text +_start: +start: +_stext: + + R0 = 0x30; + SYSCFG = R0; + SSYNC; + + /* As per HW reference manual DAG registers, + * DATA and Address resgister shall be zero'd + * in initialization, after a reset state + */ + r1 = 0; /* Data registers zero'd */ + r2 = 0; + r3 = 0; + r4 = 0; + r5 = 0; + r6 = 0; + r7 = 0; + + p0 = 0; /* Address registers zero'd */ + p1 = 0; + p2 = 0; + p3 = 0; + p4 = 0; + p5 = 0; + + i0 = 0; /* DAG Registers zero'd */ + i1 = 0; + i2 = 0; + i3 = 0; + m0 = 0; + m1 = 0; + m3 = 0; + m3 = 0; + l0 = 0; + l1 = 0; + l2 = 0; + l3 = 0; + b0 = 0; + b1 = 0; + b2 = 0; + b3 = 0; + + /* Set loop counters to zero, to make sure that + * hw loops are disabled. + */ + lc0 = 0; + lc1 = 0; + + SSYNC; + + /* Check soft reset status */ + p0.h = SWRST >> 16; + p0.l = SWRST & 0xFFFF; + r0.l = w[p0]; + + cc = bittst(r0, 15); + if !cc jump no_soft_reset; + + /* Clear Soft reset */ + r0 = 0x0000; + w[p0] = r0; + ssync; + +no_soft_reset: + nop; + + /* Clear EVT registers */ + p0.h = (EVT_EMULATION_ADDR >> 16); + p0.l = (EVT_EMULATION_ADDR & 0xFFFF); + p0 += 8; + p1 = 14; + r1 = 0; + LSETUP(4,4) lc0 = p1; + [ p0 ++ ] = r1; + + /* + * Set PLL_CTL + * - [14:09] = MSEL[5:0] : CLKIN / VCO multiplication factors + * - [8] = BYPASS : BYPASS the PLL, run CLKIN into CCLK/SCLK + * - [7] = output delay (add 200ps of delay to mem signals) + * - [6] = input delay (add 200ps of input delay to mem signals) + * - [5] = PDWN : 1=All Clocks off + * - [3] = STOPCK : 1=Core Clock off + * - [1] = PLL_OFF : 1=Disable Power to PLL + * - [0] = DF : 1=Pass CLKIN/2 to PLL / 0=Pass CLKIN to PLL + * all other bits set to zero + */ + + r0 = CONFIG_VCO_MULT; /* Load the VCO multiplier */ + r0 = r0 << 9; /* Shift it over */ + r1 = CONFIG_CLKIN_HALF; /* Do we need to divide CLKIN by 2? */ + r0 = r1 | r0; + r1 = CONFIG_PLL_BYPASS; /* Bypass the PLL? */ + r1 = r1 << 8; /* Shift it over */ + r0 = r1 | r0; /* add them all together */ + + p0.h = (PLL_CTL >> 16); + p0.l = (PLL_CTL & 0xFFFF); /* Load the address */ + cli r2; /* Disable interrupts */ + w[p0] = r0; /* Set the value */ + idle; /* Wait for the PLL to stablize */ + sti r2; /* Enable interrupts */ + ssync; + + /* + * Turn on the CYCLES COUNTER + */ + r2 = SYSCFG; + BITSET (r2,1); + SYSCFG = r2; + + /* Configure SCLK & CCLK Dividers */ + r0 = CONFIG_CCLK_ACT_DIV | CONFIG_SCLK_DIV; + p0.h = (PLL_DIV >> 16); + p0.l = (PLL_DIV & 0xFFFF); + w[p0] = r0; + ssync; + +wait_for_pll_stab: + p0.h = (PLL_STAT >> 16); + p0.l = (PLL_STAT & 0xFFFF); + r0.l = w[p0]; + cc = bittst(r0,5); + if !cc jump wait_for_pll_stab; + + /* Configure SDRAM if SDRAM is already not enabled */ + p0.l = (EBIU_SDSTAT & 0xFFFF); + p0.h = (EBIU_SDSTAT >> 16); + r0.l = w[p0]; + cc = bittst(r0, 3); + if !cc jump skip_sdram_enable; + + /* SDRAM initialization */ + p0.l = (EBIU_SDGCTL & 0xFFFF); + p0.h = (EBIU_SDGCTL >> 16); /* SDRAM Memory Global Control Register */ + r0.h = (mem_SDGCTL >> 16); + r0.l = (mem_SDGCTL & 0xFFFF); + [p0] = r0; + ssync; + + p0.l = (EBIU_SDBCTL & 0xFFFF); + p0.h = (EBIU_SDBCTL >> 16); /* SDRAM Memory Bank Control Register */ + r0 = mem_SDBCTL; + w[p0] = r0.l; + ssync; + + p0.l = (EBIU_SDRRC & 0xFFFF); + p0.h = (EBIU_SDRRC >> 16); /* SDRAM Refresh Rate Control Register */ + r0 = mem_SDRRC; + w[p0] = r0.l; + ssync; + +skip_sdram_enable: + nop; + +#ifndef CFG_NO_FLASH + /* relocate into to RAM */ + p1.l = (CFG_FLASH_BASE & 0xffff); + p1.h = (CFG_FLASH_BASE >> 16); + p2.l = (CFG_MONITOR_BASE & 0xffff); + p2.h = (CFG_MONITOR_BASE >> 16); + r0.l = (CFG_MONITOR_LEN & 0xffff); + r0.h = (CFG_MONITOR_LEN >> 16); +loop1: + r1 = [p1]; + [p2] = r1; + p3=0x4; + p1=p1+p3; + p2=p2+p3; + r2=0x4; + r0=r0-r2; + cc=r0==0x0; + if !cc jump loop1; +#endif + /* + * configure STACK + */ + r0.h = (CONFIG_STACKBASE >> 16); + r0.l = (CONFIG_STACKBASE & 0xFFFF); + sp = r0; + fp = sp; + + /* + * This next section keeps the processor in supervisor mode + * during kernel boot. Switches to user mode at end of boot. + * See page 3-9 of Hardware Reference manual for documentation. + */ + + /* To keep ourselves in the supervisor mode */ + p0.l = (EVT_IVG15_ADDR & 0xFFFF); + p0.h = (EVT_IVG15_ADDR >> 16); + + p1.l = _real_start; + p1.h = _real_start; + [p0] = p1; + + p0.l = (IMASK & 0xFFFF); + p0.h = (IMASK >> 16); + r0 = IVG15_POS; + [p0] = r0; + raise 15; + p0.l = WAIT_HERE; + p0.h = WAIT_HERE; + reti = p0; + rti; + +WAIT_HERE: + jump WAIT_HERE; + +.global _real_start; +_real_start: + [ -- sp ] = reti; + +#ifdef CONFIG_EZKIT533 + p0.l = (WDOG_CTL & 0xFFFF); + p0.h = (WDOG_CTL >> 16); + r0 = WATCHDOG_DISABLE(z); + w[p0] = r0; +#endif + + /* Code for initializing Async mem banks */ + p2.h = (EBIU_AMBCTL1 >> 16); + p2.l = (EBIU_AMBCTL1 & 0xFFFF); + r0.h = (AMBCTL1VAL >> 16); + r0.l = (AMBCTL1VAL & 0xFFFF); + [p2] = r0; + ssync; + + p2.h = (EBIU_AMBCTL0 >> 16); + p2.l = (EBIU_AMBCTL0 & 0xFFFF); + r0.h = (AMBCTL0VAL >> 16); + r0.l = (AMBCTL0VAL & 0xFFFF); + [p2] = r0; + ssync; + + p2.h = (EBIU_AMGCTL >> 16); + p2.l = (EBIU_AMGCTL & 0xffff); + r0 = AMGCTLVAL; + w[p2] = r0; + ssync; + + /* DMA reset code to Hi of L1 SRAM */ +copy: + P1.H = hi(SYSMMR_BASE); /* P1 Points to the beginning of SYSTEM MMR Space */ + P1.L = lo(SYSMMR_BASE); + + R0.H = reset_start; /* Source Address (high) */ + R0.L = reset_start; /* Source Address (low) */ + R1.H = reset_end; + R1.L = reset_end; + R2 = R1 - R0; /* Count */ + R1.H = hi(L1_ISRAM); /* Destination Address (high) */ + R1.L = lo(L1_ISRAM); /* Destination Address (low) */ + R3.L = DMAEN; /* Source DMAConfig Value (8-bit words) */ + R4.L = (DI_EN | WNR | DMAEN); /* Destination DMAConfig Value (8-bit words) */ + +DMA: + R6 = 0x1 (Z); + W[P1+OFFSET_(MDMA_S0_X_MODIFY)] = R6; /* Source Modify = 1 */ + W[P1+OFFSET_(MDMA_D0_X_MODIFY)] = R6; /* Destination Modify = 1 */ + + [P1+OFFSET_(MDMA_S0_START_ADDR)] = R0; /* Set Source Base Address */ + W[P1+OFFSET_(MDMA_S0_X_COUNT)] = R2; /* Set Source Count */ + /* Set Source DMAConfig = DMA Enable, + Memory Read, 8-Bit Transfers, 1-D DMA, Flow - Stop */ + W[P1+OFFSET_(MDMA_S0_CONFIG)] = R3; + + [P1+OFFSET_(MDMA_D0_START_ADDR)] = R1; /* Set Destination Base Address */ + W[P1+OFFSET_(MDMA_D0_X_COUNT)] = R2; /* Set Destination Count */ + /* Set Destination DMAConfig = DMA Enable, + Memory Write, 8-Bit Transfers, 1-D DMA, Flow - Stop, IOC */ + W[P1+OFFSET_(MDMA_D0_CONFIG)] = R4; + + IDLE; /* Wait for DMA to Complete */ + + R0 = 0x1; + W[P1+OFFSET_(MDMA_D0_IRQ_STATUS)] = R0; /* Write 1 to clear DMA interrupt */ + + /* DMA reset code to DATA BANK A which uses this port + * to avoid following problem + * " Data from a Data Cache fill can be corrupoted after or during + * instruction DMA if certain core stalls exist" + */ + +copy_as_data: + R0.H = reset_start; /* Source Address (high) */ + R0.L = reset_start; /* Source Address (low) */ + R1.H = reset_end; + R1.L = reset_end; + R2 = R1 - R0; /* Count */ + R1.H = hi(DATA_BANKA_SRAM); /* Destination Address (high) */ + R1.L = lo(DATA_BANKA_SRAM); /* Destination Address (low) */ + R3.L = DMAEN; /* Source DMAConfig Value (8-bit words) */ + R4.L = (DI_EN | WNR | DMAEN); /* Destination DMAConfig Value (8-bit words) */ + +DMA_DATA: + R6 = 0x1 (Z); + W[P1+OFFSET_(MDMA_S0_X_MODIFY)] = R6; /* Source Modify = 1 */ + W[P1+OFFSET_(MDMA_D0_X_MODIFY)] = R6; /* Destination Modify = 1 */ + + [P1+OFFSET_(MDMA_S0_START_ADDR)] = R0; /* Set Source Base Address */ + W[P1+OFFSET_(MDMA_S0_X_COUNT)] = R2; /* Set Source Count */ + /* Set Source DMAConfig = DMA Enable, + Memory Read, 8-Bit Transfers, 1-D DMA, Flow - Stop */ + W[P1+OFFSET_(MDMA_S0_CONFIG)] = R3; + + [P1+OFFSET_(MDMA_D0_START_ADDR)] = R1; /* Set Destination Base Address */ + W[P1+OFFSET_(MDMA_D0_X_COUNT)] = R2; /* Set Destination Count */ + /* Set Destination DMAConfig = DMA Enable, + Memory Write, 8-Bit Transfers, 1-D DMA, Flow - Stop, IOC */ + W[P1+OFFSET_(MDMA_D0_CONFIG)] = R4; + + IDLE; /* Wait for DMA to Complete */ + + R0 = 0x1; + W[P1+OFFSET_(MDMA_D0_IRQ_STATUS)] = R0; /* Write 1 to clear DMA interrupt */ + +copy_end: nop; + + /* Initialize BSS Section with 0 s */ + p1.l = __bss_start; + p1.h = __bss_start; + p2.l = _end; + p2.h = _end; + r1 = p1; + r2 = p2; + r3 = r2 - r1; + r3 = r3 >> 2; + p3 = r3; + lsetup (_clear_bss, _clear_bss_end ) lc1 = p3; + CC = p2<=p1; + if CC jump _clear_bss_skip; + r0 = 0; +_clear_bss: +_clear_bss_end: + [p1++] = r0; +_clear_bss_skip: + + p0.l = _start1; + p0.h = _start1; + jump (p0); + +reset_start: + p0.h = WDOG_CNT >> 16; + p0.l = WDOG_CNT & 0xffff; + r0 = 0x0010; + w[p0] = r0; + p0.h = WDOG_CTL >> 16; + p0.l = WDOG_CTL & 0xffff; + r0 = 0x0000; + w[p0] = r0; +reset_wait: + jump reset_wait; + +reset_end: nop; + +_exit: + jump.s _exit; diff --git a/cpu/bf533/start1.S b/cpu/bf533/start1.S new file mode 100644 index 00000000000..6f481240553 --- /dev/null +++ b/cpu/bf533/start1.S @@ -0,0 +1,38 @@ +/* + * U-boot - start1.S Code running out of RAM after relocation + * + * Copyright (c) 2005 blackfin.uclinux.org + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#define ASSEMBLY +#include +#include +#include + +.global start1; +.global _start1; + +.text +_start1: +start1: + sp += -12; + call board_init_f; + sp += 12; diff --git a/cpu/bf533/traps.c b/cpu/bf533/traps.c new file mode 100644 index 00000000000..37470d583e2 --- /dev/null +++ b/cpu/bf533/traps.c @@ -0,0 +1,73 @@ +/* + * U-boot - traps.c Routines related to interrupts and exceptions + * + * Copyright (c) 2005 blackfin.uclinux.org + * + * This file is based on + * No original Copyright holder listed, + * Probabily original (C) Roman Zippel (assigned DJD, 1999) + * + * Copyright 2003 Metrowerks - for Blackfin + * Copyright 2000-2001 Lineo, Inc. D. Jeff Dionne + * Copyright 1999-2000 D. Jeff Dionne, + * + * (C) Copyright 2000-2004 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "cpu.h" + +void init_IRQ(void) +{ + blackfin_init_IRQ(); + return; +} + +void process_int(unsigned long vec, struct pt_regs *fp) +{ + return; +} + +void dump(struct pt_regs *fp) +{ + printf("PC: %08lx\n", fp->pc); + printf("SEQSTAT: %08lx SP: %08lx\n", (long) fp->seqstat, + (long) fp); + printf("R0: %08lx R1: %08lx R2: %08lx R3: %08lx\n", + fp->r0, fp->r1, fp->r2, fp->r3); + printf("R4: %08lx R5: %08lx R6: %08lx R7: %08lx\n", + fp->r4, fp->r5, fp->r6, fp->r7); + printf("P0: %08lx P1: %08lx P2: %08lx P3: %08lx\n", + fp->p0, fp->p1, fp->p2, fp->p3); + printf("P4: %08lx P5: %08lx FP: %08lx\n", fp->p4, fp->p5, + fp->fp); + printf("A0.w: %08lx A0.x: %08lx A1.w: %08lx A1.x: %08lx\n", + fp->a0w, fp->a0x, fp->a1w, fp->a1x); + printf("\n"); +} -- cgit v1.2.3 From 8e7b703a62783f0e88d3a7e4b1dd1c033bc95ec8 Mon Sep 17 00:00:00 2001 From: Wolfgang Denk Date: Sun, 12 Mar 2006 02:55:22 +0100 Subject: Coding Style cleanup --- cpu/bf533/bf533_serial.h | 2 +- cpu/bf533/cache.S | 144 +++++++++++++++++++++++------------------------ cpu/bf533/cplbhdlr.S | 33 ++++++----- cpu/bf533/cplbmgr.S | 88 ++++++++++++++--------------- cpu/bf533/cpu.c | 15 ++--- cpu/bf533/flush.S | 30 +++++----- cpu/bf533/interrupt.S | 4 +- cpu/bf533/serial.c | 10 ++-- cpu/bf533/start.S | 10 ++-- 9 files changed, 165 insertions(+), 171 deletions(-) (limited to 'cpu') diff --git a/cpu/bf533/bf533_serial.h b/cpu/bf533/bf533_serial.h index ec63a5e00ad..d430e6cabd9 100644 --- a/cpu/bf533/bf533_serial.h +++ b/cpu/bf533/bf533_serial.h @@ -3,7 +3,7 @@ * * Copyright (c) 2005 blackfin.uclinux.org * - * This file is based on + * This file is based on * bf533_serial.h: Definitions for the BlackFin BF533 DSP serial driver. * Copyright (C) 2003 Bas Vermeulen * BuyWays B.V. (www.buyways.nl) diff --git a/cpu/bf533/cache.S b/cpu/bf533/cache.S index 1822d1f3290..8fac4027405 100644 --- a/cpu/bf533/cache.S +++ b/cpu/bf533/cache.S @@ -22,88 +22,88 @@ ENTRY(blackfin_icache_flush_range) ENTRY(blackfin_dcache_flush_range) R2 = -32; - R2 = R0 & R2; - P0 = R2; - P1 = R1; - CSYNC; + R2 = R0 & R2; + P0 = R2; + P1 = R1; + CSYNC; 1: - FLUSH[P0++]; - CC = P0 < P1(iu); - IF CC JUMP 1b(bp); - FLUSH[P0]; - SSYNC; - RTS; + FLUSH[P0++]; + CC = P0 < P1(iu); + IF CC JUMP 1b(bp); + FLUSH[P0]; + SSYNC; + RTS; ENTRY(_icache_invalidate) ENTRY(invalidate_entire_icache) - [--SP] = ( R7:5); - - P0.L = (IMEM_CONTROL & 0xFFFF); - P0.H = (IMEM_CONTROL >> 16); - R7 = [P0]; - - /* Clear the IMC bit , All valid bits in the instruction - * cache are set to the invalid state - */ - BITCLR(R7,IMC_P); - CLI R6; - SSYNC; /* SSYNC required before invalidating cache. */ - .align 8; - [P0] = R7; - SSYNC; - STI R6; - - /* Configures the instruction cache agian */ - R6 = (IMC | ENICPLB); - R7 = R7 | R6; - - CLI R6; - SSYNC; /* SSYNC required before writing to IMEM_CONTROL. */ - .align 8; - [P0] = R7; - SSYNC; - STI R6; - - ( R7:5) = [SP++]; - RTS; + [--SP] = ( R7:5); + + P0.L = (IMEM_CONTROL & 0xFFFF); + P0.H = (IMEM_CONTROL >> 16); + R7 = [P0]; + + /* Clear the IMC bit , All valid bits in the instruction + * cache are set to the invalid state + */ + BITCLR(R7,IMC_P); + CLI R6; + SSYNC; /* SSYNC required before invalidating cache. */ + .align 8; + [P0] = R7; + SSYNC; + STI R6; + + /* Configures the instruction cache agian */ + R6 = (IMC | ENICPLB); + R7 = R7 | R6; + + CLI R6; + SSYNC; /* SSYNC required before writing to IMEM_CONTROL. */ + .align 8; + [P0] = R7; + SSYNC; + STI R6; + + ( R7:5) = [SP++]; + RTS; /* Invalidate the Entire Data cache by * clearing DMC[1:0] bits */ ENTRY(invalidate_entire_dcache) ENTRY(_dcache_invalidate) - [--SP] = ( R7:6); - - P0.L = (DMEM_CONTROL & 0xFFFF); - P0.H = (DMEM_CONTROL >> 16); - R7 = [P0]; - - /* Clear the DMC[1:0] bits, All valid bits in the data - * cache are set to the invalid state - */ - BITCLR(R7,DMC0_P); - BITCLR(R7,DMC1_P); - CLI R6; - SSYNC; /* SSYNC required before writing to DMEM_CONTROL. */ - .align 8; - [P0] = R7; - SSYNC; - STI R6; - - /* Configures the data cache again */ - - R6 = (ACACHE_BCACHE | ENDCPLB | PORT_PREF0); - R7 = R7 | R6; - - CLI R6; - SSYNC; /* SSYNC required before writing to DMEM_CONTROL. */ - .align 8; - [P0] = R7; - SSYNC; - STI R6; - - ( R7:6) = [SP++]; - RTS; + [--SP] = ( R7:6); + + P0.L = (DMEM_CONTROL & 0xFFFF); + P0.H = (DMEM_CONTROL >> 16); + R7 = [P0]; + + /* Clear the DMC[1:0] bits, All valid bits in the data + * cache are set to the invalid state + */ + BITCLR(R7,DMC0_P); + BITCLR(R7,DMC1_P); + CLI R6; + SSYNC; /* SSYNC required before writing to DMEM_CONTROL. */ + .align 8; + [P0] = R7; + SSYNC; + STI R6; + + /* Configures the data cache again */ + + R6 = (ACACHE_BCACHE | ENDCPLB | PORT_PREF0); + R7 = R7 | R6; + + CLI R6; + SSYNC; /* SSYNC required before writing to DMEM_CONTROL. */ + .align 8; + [P0] = R7; + SSYNC; + STI R6; + + ( R7:6) = [SP++]; + RTS; ENTRY(blackfin_dcache_invalidate_range) R2 = -32; diff --git a/cpu/bf533/cplbhdlr.S b/cpu/bf533/cplbhdlr.S index b5abbbcbb63..61be5bb90ca 100644 --- a/cpu/bf533/cplbhdlr.S +++ b/cpu/bf533/cplbhdlr.S @@ -1,9 +1,9 @@ -/* Copyright (C) 2003 Analog Devices, Inc. All Rights Reserved. +/* Copyright (C) 2003 Analog Devices, Inc. All Rights Reserved. * * This file is subject to the terms and conditions of the GNU General Public - * License. + * License. * - * Blackfin BF533/2.6 support : LG Soft India + * Blackfin BF533/2.6 support : LG Soft India */ @@ -16,7 +16,7 @@ .text - + .globl _cplb_hdr; .type _cplb_hdr, STT_FUNC; .extern _cplb_mgr; @@ -76,19 +76,19 @@ is_icplb_miss: #if ( defined (CONFIG_BLKFIN_CACHE) || defined (CONFIG_BLKFIN_DCACHE)) #if ( defined (CONFIG_BLKFIN_CACHE) && !defined (CONFIG_BLKFIN_DCACHE)) - R1 = CPLB_ENABLE_ICACHE; + R1 = CPLB_ENABLE_ICACHE; #endif #if ( !defined (CONFIG_BLKFIN_CACHE) && defined (CONFIG_BLKFIN_DCACHE)) - R1 = CPLB_ENABLE_DCACHE; + R1 = CPLB_ENABLE_DCACHE; #endif #if ( defined (CONFIG_BLKFIN_CACHE) && defined (CONFIG_BLKFIN_DCACHE)) - R1 = CPLB_ENABLE_DCACHE | CPLB_ENABLE_ICACHE; + R1 = CPLB_ENABLE_DCACHE | CPLB_ENABLE_ICACHE; #endif #else R1 = 0; #endif - [--SP] = RETS; + [--SP] = RETS; CALL _cplb_mgr; RETS = [SP++]; CC = R0 == 0; @@ -109,27 +109,27 @@ is_icplb_miss: RTS; unknown: - [--SP] = RETS; + [--SP] = RETS; CALL __unknown_exception_occurred; RETS = [SP++]; JUMP unknown; not_replaced: CC = R0 == CPLB_NO_UNLOCKED; IF !CC JUMP next_check; - [--SP] = RETS; + [--SP] = RETS; CALL __cplb_miss_all_locked; RETS = [SP++]; next_check: CC = R0 == CPLB_NO_ADDR_MATCH; IF !CC JUMP next_check2; - [--SP] = RETS; + [--SP] = RETS; CALL __cplb_miss_without_replacement; RETS = [SP++]; JUMP not_replaced; next_check2: CC = R0 == CPLB_PROT_VIOL; IF !CC JUMP strange_return_from_cplb_mgr; - [--SP] = RETS; + [--SP] = RETS; CALL __cplb_protection_violation; RETS = [SP++]; JUMP not_replaced; @@ -139,8 +139,8 @@ strange_return_from_cplb_mgr: JUMP strange_return_from_cplb_mgr; /************************************ - * Diagnostic exception handlers - */ + * Diagnostic exception handlers + */ __cplb_miss_all_locked: sp += -12; @@ -174,11 +174,11 @@ __unknown_exception_occurred: * other kinds of exceptions, you must replace the * default handler with your own, that handles all the * exceptions you will use. - * + * * Since there's nothing we can do, we just loop here * at what we hope is a suitably informative label. */ - + IDLE; do_not_know_what_to_do: CSYNC; @@ -191,4 +191,3 @@ do_not_know_what_to_do: panic_bfin: RTS; - diff --git a/cpu/bf533/cplbmgr.S b/cpu/bf533/cplbmgr.S index fc3e3a8832b..7a0b048629f 100644 --- a/cpu/bf533/cplbmgr.S +++ b/cpu/bf533/cplbmgr.S @@ -3,7 +3,7 @@ * * Blackfin BF533/2.6 support : LG Soft India * Modification: Dec 07 2004 - * 1. Correction in icheck_lock. Valid lock entries were + * 1. Correction in icheck_lock. Valid lock entries were * geting victimized, for instruction cplb replacement. * 2. Setup loop's are modified as now toolchain support's P Indexed * addressing @@ -18,15 +18,15 @@ * * Returns: * CPLB_RELOADED => Successfully updated CPLB table. - * CPLB_NO_UNLOCKED => All CPLBs are locked, so cannot be evicted.This indicates - * that the CPLBs in the configuration tablei are badly + * CPLB_NO_UNLOCKED => All CPLBs are locked, so cannot be evicted.This indicates + * that the CPLBs in the configuration tablei are badly * configured, as this should never occur. - * CPLB_NO_ADDR_MATCH => The address being accessed, that triggered the exception, - * is not covered by any of the CPLBs in the configuration + * CPLB_NO_ADDR_MATCH => The address being accessed, that triggered the exception, + * is not covered by any of the CPLBs in the configuration * table. The application isi presumably misbehaving. - * CPLB_PROT_VIOL => The address being accessed, that triggered thei exception, - * was not a first-write to a clean Write Back Data page, - * and so presumably is a genuine violation of the page's + * CPLB_PROT_VIOL => The address being accessed, that triggered thei exception, + * was not a first-write to a clean Write Back Data page, + * and so presumably is a genuine violation of the page's * protection attributes. The application is misbehaving. */ #define ASSEMBLY @@ -35,9 +35,9 @@ #include #include #include - + .text - + .align 2; ENTRY(_cplb_mgr) @@ -51,8 +51,8 @@ ENTRY(_cplb_mgr) /* ICPLB Miss Exception. We need to choose one of the * currently-installed CPLBs, and replace it with one - * from the configuration table. - */ + * from the configuration table. + */ P4.L = (ICPLB_FAULT_ADDR & 0xFFFF); P4.H = (ICPLB_FAULT_ADDR >> 16); @@ -72,7 +72,7 @@ ENTRY(_cplb_mgr) isearch: R1 = [P0-0x100]; /* Address for this CPLB */ - + R0 = [P0++]; /* Info for this CPLB*/ CC = BITTST(R0,0); /* Is the CPLB valid?*/ IF !CC JUMP nomatch; /* Skip it, if not.*/ @@ -94,7 +94,7 @@ nomatch: isearch_done: I0 = R4; /* Fault address we'll search for*/ - + /* set up pointers */ P0.L = (ICPLB_DATA0 & 0xFFFF); P0.H = (ICPLB_DATA0 >> 16); @@ -138,7 +138,7 @@ ifound_victim: P3.H = ipdt_swapcount_table; P3 += -4; icount: - R2 = [P2]; /* address from config table */ + R2 = [P2]; /* address from config table */ P2 += 8; P3 += 8; CC = R2==-1; @@ -153,13 +153,13 @@ icount_done: #endif LC0=R3; LSETUP(is_move,ie_move) LC0; -is_move: +is_move: R0 = [P0]; [P0 - 4] = R0; R0 = [P0 - 0x100]; - [P0-0x104] = R0; + [P0-0x104] = R0; ie_move:P0+=4; - + /* We've made space in the ICPLB table, so that ICPLB15 * is now free to be overwritten. Next, we have to determine * which CPLB we need to install, from the configuration @@ -167,8 +167,8 @@ ie_move:P0+=4; * addresses and page-lengths from the config table, and * determining whether the fault address falls within that * range. - */ - + */ + P2.L = ipdt_table; P2.H = ipdt_table; #ifdef CONFIG_CPLB_INFO @@ -190,7 +190,7 @@ ie_move:P0+=4; */ R1 = ((16<<8)|2); -inext: R4 = [P2++]; /* address from config table */ +inext: R4 = [P2++]; /* address from config table */ R2 = [P2++]; /* data from config table */ #ifdef CONFIG_CPLB_INFO P3 += 8; @@ -201,7 +201,7 @@ inext: R4 = [P2++]; /* address from config table */ /* See if failed address > start address */ CC = R4 <= R0(IU); - IF !CC JUMP inext; + IF !CC JUMP inext; /* extract page size (17:16)*/ R3 = EXTRACT(R2, R1.L) (Z); @@ -250,17 +250,17 @@ inext: R4 = [P2++]; /* address from config table */ /* FAILED CASES*/ no_page_in_table: - ( R7:0,P5:0 ) = [SP++]; - R0 = CPLB_NO_ADDR_MATCH; - RTS; + ( R7:0,P5:0 ) = [SP++]; + R0 = CPLB_NO_ADDR_MATCH; + RTS; all_locked: - ( R7:0,P5:0 ) = [SP++]; - R0 = CPLB_NO_UNLOCKED; - RTS; + ( R7:0,P5:0 ) = [SP++]; + R0 = CPLB_NO_UNLOCKED; + RTS; prot_violation: - ( R7:0,P5:0 ) = [SP++]; - R0 = CPLB_PROT_VIOL; - RTS; + ( R7:0,P5:0 ) = [SP++]; + R0 = CPLB_PROT_VIOL; + RTS; dcplb_write: @@ -275,7 +275,7 @@ dcplb_write: P4.H = (DCPLB_STATUS >> 16); P3.L = (DCPLB_DATA0 & 0xFFFF); P3.H = (DCPLB_DATA0 >> 16); - R5 = [P4]; + R5 = [P4]; /* A protection violation can be caused by more than just writes * to a clean WB page, so we have to ensure that: @@ -315,7 +315,7 @@ dcplb_write: R2 <<= R5; /* if was super, check write in super mode*/ R2 = R3 & R2; CC = R2 == 0; - IF CC JUMP prot_violation; + IF CC JUMP prot_violation; /* It's a genuine write-to-clean-page.*/ @@ -333,7 +333,7 @@ dcplb_miss_compare: * config table, that covers the faulting address. */ - P1.L = (DCPLB_DATA15 & 0xFFFF); + P1.L = (DCPLB_DATA15 & 0xFFFF); P1.H = (DCPLB_DATA15 >> 16); P4.L = (DCPLB_FAULT_ADDR & 0xFFFF); @@ -379,7 +379,7 @@ sdsearch2: CC = R2 == 0; /* If none are set, it'll do.*/ IF !CC JUMP skip_stack_check; - R2 = [P0 - 0x104]; /* R2 - PageStart */ + R2 = [P0 - 0x104]; /* R2 - PageStart */ P3.L = page_size_table; /* retrive end address */ P3.H = page_size_table; /* retrive end address */ R3 = 0x2; /* 0th - position, 2 bits -length */ @@ -392,13 +392,13 @@ sdsearch2: R7 = R7 << 0xA; /* in bytes * 1024*/ R7 = R2 + R7; /* R7 - PageEnd */ - R4 = SP; /* Test SP is in range */ + R4 = SP; /* Test SP is in range */ CC = R7 < R4; /* if PageEnd < SP */ IF CC JUMP dfound_victim; R3 = 0x284; /* stack length from start of trap till the point */ /* 20 stack locations for future modifications */ - R4 = R4 + R3; + R4 = R4 + R3; CC = R4 < R2; /* if SP + stacklen < PageStart */ IF CC JUMP dfound_victim; skip_stack_check: @@ -409,7 +409,7 @@ edsearch1: NOP; /* If we got here, we didn't find a DCPLB we considered * replacable, which means all of them were locked. */ - + JUMP all_locked; dfound_victim: @@ -450,14 +450,14 @@ dicount_done: CC = BITTST(R1, 7); /* Is it dirty?*/ IF !CC JUMP Ddoverwrite (BP); /* Nope.*/ CC = BITTST(R1, 14); /* Is it Write-Through?*/ - IF CC JUMP Ddoverwrite; /* Yep*/ + IF CC JUMP Ddoverwrite; /* Yep*/ /* This is a dirty page, so we need to flush all writes * that are pending on the page. */ /* Retrieve the page start address*/ - R0 = [P0 - 0x104]; + R0 = [P0 - 0x104]; [--sp] = rets; CALL dcplb_flush; /* R0==CPLB addr, R1==CPLB data*/ rets = [sp++]; @@ -467,7 +467,7 @@ Ddoverwrite: * overwrite it by moving all the following CPLBs * one space closer to the start. */ - + R1.L = ((DCPLB_DATA15+4) & 0xFFFF); /*DCPLB_DATA15+4*/ R1.H = ((DCPLB_DATA15+4) >> 16); R0 = P0; @@ -485,7 +485,7 @@ Ddoverwrite: ds_move: R0 = [P0++]; /* move data */ [P0 - 8] = R0; - R0 = [P0-0x104] /* move address */ + R0 = [P0-0x104] /* move address */ de_move: [P0-0x108] = R0; /* We've now made space in DCPLB15 for the new CPLB to be @@ -510,7 +510,7 @@ de_moved:NOP; /* An extraction pattern, to retrieve bits 17:16.*/ R1 = (16<<8)|2; -dnext: R4 = [P2++]; /* address */ +dnext: R4 = [P2++]; /* address */ R2 = [P2++]; /* data */ #ifdef CONFIG_CPLB_INFO P3 += 8; @@ -521,7 +521,7 @@ dnext: R4 = [P2++]; /* address */ /* See if failed address > start address */ CC = R4 <= R0(IU); - IF !CC JUMP dnext; + IF !CC JUMP dnext; /* extract page size (17:16)*/ R3 = EXTRACT(R2, R1.L) (Z); diff --git a/cpu/bf533/cpu.c b/cpu/bf533/cpu.c index 2c139f547da..78e2b966bb4 100644 --- a/cpu/bf533/cpu.c +++ b/cpu/bf533/cpu.c @@ -41,7 +41,7 @@ #define L1_IMEMORY (PAGE_SIZE_1MB | CPLB_L1_CHBL | CPLB_USER_RD | CPLB_VALID | CPLB_LOCK) #define SDRAM_INON_CHBL (PAGE_SIZE_4MB | CPLB_USER_RD | CPLB_VALID) -#define ANOMALY_05000158 0x200 +#define ANOMALY_05000158 0x200 #define SDRAM_DGENERIC (PAGE_SIZE_4MB | CPLB_L1_CHBL | CPLB_WT | CPLB_L1_AOW | CPLB_SUPV_WR | CPLB_USER_RD | CPLB_USER_WR | CPLB_VALID | ANOMALY_05000158) #define SDRAM_DNON_CHBL (PAGE_SIZE_4MB | CPLB_WT | CPLB_L1_AOW | CPLB_SUPV_WR | CPLB_USER_WR | CPLB_USER_RD | CPLB_VALID | ANOMALY_05000158) #define SDRAM_DKERNEL (PAGE_SIZE_4MB | CPLB_L1_CHBL | CPLB_WT | CPLB_L1_AOW | CPLB_USER_RD | CPLB_SUPV_WR | CPLB_USER_WR | CPLB_VALID | CPLB_LOCK | ANOMALY_05000158) @@ -68,7 +68,7 @@ static unsigned int icplb_table[16][2]={ }; static unsigned int dcplb_table[16][2]={ - {0xFFA00000,L1_DMEMORY}, + {0xFFA00000,L1_DMEMORY}, {0x00000000,SDRAM_DKERNEL}, /*SDRAM_Page1*/ {0x00400000,SDRAM_DKERNEL}, /*SDRAM_Page1*/ {0x07C00000,SDRAM_DKERNEL}, /*SDRAM_Page15*/ @@ -83,13 +83,9 @@ static unsigned int dcplb_table[16][2]={ {0x02800000,SDRAM_DGENERIC}, /*SDRAM_Page10*/ {0x02C00000,SDRAM_DGENERIC}, /*SDRAM_Page11*/ {0x03000000,SDRAM_DGENERIC}, /*SDRAM_Page12*/ - {0x20000000,SDRAM_EBIU}, /*For Network */ + {0x20000000,SDRAM_EBIU}, /*For Network */ }; - - - - int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) { __asm__ __volatile__ @@ -121,7 +117,7 @@ void icache_enable(void) I0 = (unsigned int *)ICPLB_ADDR0; I1 = (unsigned int *)ICPLB_DATA0; - + for(i=0;i<16;i++){ *I0++ = icplb_table[i][0]; *I1++ = icplb_table[i][1]; @@ -166,13 +162,12 @@ void dcache_enable(void) *I1++ = dcplb_table[i][1]; } cli(); - temp = *(unsigned int *)DMEM_CONTROL; + temp = *(unsigned int *)DMEM_CONTROL; SSYNC(); *(unsigned int *)DMEM_CONTROL = ACACHE_BCACHE |ENDCPLB |PORT_PREF0|temp; SSYNC(); sti(); } - void dcache_disable(void) { diff --git a/cpu/bf533/flush.S b/cpu/bf533/flush.S index 1f9ec9899e5..9fbdefc9db4 100644 --- a/cpu/bf533/flush.S +++ b/cpu/bf533/flush.S @@ -60,7 +60,7 @@ ENTRY(icplb_flush) [--SP] = LC1; [--SP] = LT1; [--SP] = LB1; - + /* If it's a 1K or 4K page, then it's quickest to * just systematically flush all the addresses in * the page, regardless of whether they're in the @@ -90,7 +90,7 @@ ENTRY(icplb_flush) R4 = EXTRACT(R0, R3.L) (Z); /* Extract bits*/ R3.H = R4.L << 0 ; /* Save in extraction pattern for later deposit.*/ - + /* So: * R0 = Page start * R1 = Page length (actually, offset into size/prefix tables) @@ -101,7 +101,7 @@ ENTRY(icplb_flush) * sub-bank, looking for dirty, valid tags that match our * address prefix. */ - + P5.L = (ITEST_COMMAND & 0xFFFF); P5.H = (ITEST_COMMAND >> 16); P4.L = (ITEST_DATA0 & 0xFFFF); @@ -119,7 +119,7 @@ ENTRY(icplb_flush) * fetching tags, so we only have to set Set, Bank, * Sub-bank and Way. */ - + P2 = 4; LSETUP (ifs1, ife1) LC1 = P2; ifs1: P0 = 32; /* iterate over all sets*/ @@ -142,7 +142,7 @@ ifs0: R6 = R5 << 5; /* Combine set*/ IF !CC JUMP ifskip; /* Skip it if it doesn't match.*/ /* Tag address matches against page, so this is an entry - * we must flush. + * we must flush. */ R7 >>= 10; /* Mask off the non-address bits*/ @@ -181,11 +181,11 @@ iflush_whole_page: IFLUSH [P0++]; /* because CSYNC can't end loops.*/ LSETUP (isall, ieall) LC0 = P1; isall:IFLUSH [P0++]; -ieall: NOP; +ieall: NOP; SSYNC; JUMP ifinished; -/* This is an external function being called by the user +/* This is an external function being called by the user * application through __flush_cache_all. Currently this function * serves the purpose of flushing all the pending writes in * in the data cache. @@ -222,7 +222,7 @@ skip: R6 += -1; /* This is an internal function to flush all pending * writes in the cache associated with a particular DCPLB. - * + * * R0 - page's start address * R1 - CPLB's data field. */ @@ -236,7 +236,7 @@ ENTRY(dcplb_flush) [--SP] = LC1; [--SP] = LT1; [--SP] = LB1; - + /* If it's a 1K or 4K page, then it's quickest to * just systematically flush all the addresses in * the page, regardless of whether they're in the @@ -250,9 +250,9 @@ ENTRY(dcplb_flush) /* We're only interested in the page's size, so extract * this from the CPLB (bits 17:16), and scale to give an - * offset into the page_size and page_prefix tables. + * offset into the page_size and page_prefix tables. */ - + R1 <<= 14; R1 >>= 30; R1 <<= 2; @@ -260,9 +260,9 @@ ENTRY(dcplb_flush) /* The page could be mapped into Bank A or Bank B, depending * on (a) whether both banks are configured as cache, and * (b) on whether address bit A[x] is set. x is determined - * by DCBS in DMEM_CONTROL + * by DCBS in DMEM_CONTROL */ - + R2 = 0; /* Default to Bank A (Bank B would be 1)*/ P0.L = (DMEM_CONTROL & 0xFFFF); @@ -303,7 +303,7 @@ bank_chosen: * sub-bank, looking for dirty, valid tags that match our * address prefix. */ - + P5.L = (DTEST_COMMAND & 0xFFFF); P5.H = (DTEST_COMMAND >> 16); P4.L = (DTEST_DATA0 & 0xFFFF); @@ -322,7 +322,7 @@ bank_chosen: * fetching tags, so we only have to set Set, Bank, * Sub-bank and Way. */ - + P2 = 2; LSETUP (fs1, fe1) LC1 = P2; fs1: P0 = 64; /* iterate over all sets*/ diff --git a/cpu/bf533/interrupt.S b/cpu/bf533/interrupt.S index b4d2579c44c..e780dc6d6b0 100644 --- a/cpu/bf533/interrupt.S +++ b/cpu/bf533/interrupt.S @@ -240,7 +240,7 @@ evt_rst: sp += 12; _evt_rst_exit: - rtn; + rtn; irq_panic: r0 = IRQ_EVX; @@ -279,7 +279,7 @@ evt_evt7: evt_evt7_exit: RESTORE_CONTEXT - rti; + rti; .global evt_evt8 evt_evt8: diff --git a/cpu/bf533/serial.c b/cpu/bf533/serial.c index 8f0cd1649d6..84ae9d9cde6 100644 --- a/cpu/bf533/serial.c +++ b/cpu/bf533/serial.c @@ -13,12 +13,12 @@ * Copyright(c) 2003 Metrowerks * Copyright(c) 2001 Tony Z. Kou * Copyright(c) 2001-2002 Arcturus Networks Inc. - * + * * Based on code from 68328 version serial driver imlpementation which was: * Copyright (C) 1995 David S. Miller * Copyright (C) 1998 Kenneth Albanowski * Copyright (C) 1998, 1999 D. Jeff Dionne - * Copyright (C) 1999 Vladimir Gurevich + * Copyright (C) 1999 Vladimir Gurevich * * (C) Copyright 2000-2004 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. @@ -178,9 +178,9 @@ static void local_put_char(char ch) save_and_cli(flags); - /* Poll for TX Interruput */ - while (!((isr_val = *pSIC_ISR) & IRQ_UART_TX_BIT)); - asm("csync;"); + /* Poll for TX Interruput */ + while (!((isr_val = *pSIC_ISR) & IRQ_UART_TX_BIT)); + asm("csync;"); *pUART_THR = ch; /* putc() */ diff --git a/cpu/bf533/start.S b/cpu/bf533/start.S index 7414d8873d2..6d585751abe 100644 --- a/cpu/bf533/start.S +++ b/cpu/bf533/start.S @@ -32,7 +32,7 @@ /* * Note: A change in this file subsequently requires a change in - * board/$(board_name)/config.mk for a valid u-boot.bin + * board/$(board_name)/config.mk for a valid u-boot.bin */ #define ASSEMBLY @@ -82,7 +82,7 @@ _stext: SSYNC; /* As per HW reference manual DAG registers, - * DATA and Address resgister shall be zero'd + * DATA and Address resgister shall be zero'd * in initialization, after a reset state */ r1 = 0; /* Data registers zero'd */ @@ -99,7 +99,7 @@ _stext: p3 = 0; p4 = 0; p5 = 0; - + i0 = 0; /* DAG Registers zero'd */ i1 = 0; i2 = 0; @@ -242,9 +242,9 @@ loop1: r1 = [p1]; [p2] = r1; p3=0x4; - p1=p1+p3; + p1=p1+p3; p2=p2+p3; - r2=0x4; + r2=0x4; r0=r0-r2; cc=r0==0x0; if !cc jump loop1; -- cgit v1.2.3 From 23466d6a3304433ba8d7ff10f17260010fcc4580 Mon Sep 17 00:00:00 2001 From: Wolfgang Denk Date: Sun, 12 Mar 2006 16:14:29 +0100 Subject: Fix PCIDF calculation in cpu/mpc8260/speed.c for MPC8280EC Patch by KokHow Teh, 16 Jun 2005 --- cpu/mpc8260/speed.c | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) (limited to 'cpu') diff --git a/cpu/mpc8260/speed.c b/cpu/mpc8260/speed.c index a761a178bc1..99afe7609f7 100644 --- a/cpu/mpc8260/speed.c +++ b/cpu/mpc8260/speed.c @@ -163,7 +163,7 @@ int prt_8260_clks (void) volatile immap_t *immap = (immap_t *) CFG_IMMR; ulong sccr, dfbrg; - ulong scmr, corecnf, busdf, cpmdf, plldf, pllmf; + ulong scmr, corecnf, busdf, cpmdf, plldf, pllmf, pcidf; corecnf_t *cp; sccr = immap->im_clkrst.car_sccr; @@ -175,6 +175,7 @@ int prt_8260_clks (void) cpmdf = (scmr & SCMR_CPMDF_MSK) >> SCMR_CPMDF_SHIFT; plldf = (scmr & SCMR_PLLDF) ? 1 : 0; pllmf = (scmr & SCMR_PLLMF_MSK) >> SCMR_PLLMF_SHIFT; + pcidf = (sccr & SCCR_PCIDF_MSK) >> SCCR_PCIDF_SHIFT; cp = &corecnf_tab[corecnf]; @@ -204,8 +205,9 @@ int prt_8260_clks (void) cp->vco_div, cp->freq_60x, cp->freq_core); printf (" - dfbrg %ld, corecnf 0x%02lx, busdf %ld, cpmdf %ld, " - "plldf %ld, pllmf %ld\n", dfbrg, corecnf, busdf, cpmdf, plldf, - pllmf); + "plldf %ld, pllmf %ld, pcidf %ld\n", + dfbrg, corecnf, busdf, cpmdf, + plldf, pllmf, pcidf); printf (" - vco_out %10ld, scc_clk %10ld, brg_clk %10ld\n", gd->vco_out, gd->scc_clk, gd->brg_clk); @@ -215,9 +217,20 @@ int prt_8260_clks (void) if (sccr & SCCR_PCI_MODE) { uint pci_div; - - pci_div = ( (sccr & SCCR_PCI_MODCK) ? 2 : 1) * - ( ( (sccr & SCCR_PCIDF_MSK) >> SCCR_PCIDF_SHIFT) + 1); + uint pcidf = (sccr & SCCR_PCIDF_MSK) >> SCCR_PCIDF_SHIFT; + + if (sccr & SCCR_PCI_MODCK) { + pci_div = 2; + if (pcidf == 9) { + pci_div *= 5; + } else if (pcidf == 0xB) { + pci_div *= 6; + } else { + pci_div *= (pcidf + 1); + } + } else { + pci_div = pcidf + 1; + } printf (" - pci_clk %10ld\n", (gd->cpm_clk * 2) / pci_div); } @@ -225,5 +238,3 @@ int prt_8260_clks (void) return (0); } - -/* ------------------------------------------------------------------------- */ -- cgit v1.2.3 From b38dbd4622a2abeedf9fcb1806958d9afac0bbd4 Mon Sep 17 00:00:00 2001 From: Wolfgang Denk Date: Mon, 13 Mar 2006 00:46:05 +0100 Subject: Fix bug in [id]cache_status commands for MPC85xx processors; should look at LSB of L1CSRn registers to determine if L1 cache is enabled, not the MSB. Patch by Murray Jensen, 19 Jul 2005 --- cpu/mpc85xx/start.S | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'cpu') diff --git a/cpu/mpc85xx/start.S b/cpu/mpc85xx/start.S index 7ac65736bc0..f96a4c3f8b0 100644 --- a/cpu/mpc85xx/start.S +++ b/cpu/mpc85xx/start.S @@ -715,7 +715,7 @@ icache_disable: .globl icache_status icache_status: mfspr r3,L1CSR1 - srwi r3, r3, 31 /* >>31 => select bit 0 */ + andi. r3,r3,1 blr .globl dcache_enable @@ -748,7 +748,7 @@ dcache_disable: .globl dcache_status dcache_status: mfspr r3,L1CSR0 - srwi r3, r3, 31 /* >>31 => select bit 0 */ + andi. r3,r3,1 blr .globl get_pir -- cgit v1.2.3 From 95515306155b8b7fca1a38f192f23ea49251edf8 Mon Sep 17 00:00:00 2001 From: Wolfgang Denk Date: Mon, 13 Mar 2006 01:00:22 +0100 Subject: au1x00_eth.c: check malloc return value and abort if it failed Patch by Andrew Dyer, 26 Jul 2005 --- cpu/mips/au1x00_eth.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'cpu') diff --git a/cpu/mips/au1x00_eth.c b/cpu/mips/au1x00_eth.c index 9ce9b353978..078e8328b62 100644 --- a/cpu/mips/au1x00_eth.c +++ b/cpu/mips/au1x00_eth.c @@ -224,10 +224,14 @@ static void au1x00_halt(struct eth_device* dev){ int au1x00_enet_initialize(bd_t *bis){ struct eth_device* dev; - dev = (struct eth_device*) malloc(sizeof *dev); + if ((dev = (struct eth_device*)malloc(sizeof *dev)) == NULL) { + puts ("malloc failed\n"); + return 0; + } + memset(dev, 0, sizeof *dev); - sprintf(dev->name, "Au1X00 ETHERNET"); + sprintf(dev->name, "Au1X00 ethernet"); dev->iobase = 0; dev->priv = 0; dev->init = au1x00_init; -- cgit v1.2.3 From 9a7b408c116e1fcb4de607ddee15834319cd1ea0 Mon Sep 17 00:00:00 2001 From: Stefan Roese Date: Mon, 13 Mar 2006 09:42:28 +0100 Subject: cpu/ppc4xx/start.S : exceptions are enabled after relocation Patch by Cedric Vincent, 6 June 2005 --- cpu/ppc4xx/start.S | 41 ++++++++++++++++++----------------------- 1 file changed, 18 insertions(+), 23 deletions(-) (limited to 'cpu') diff --git a/cpu/ppc4xx/start.S b/cpu/ppc4xx/start.S index 48b430d14d8..948de43d142 100644 --- a/cpu/ppc4xx/start.S +++ b/cpu/ppc4xx/start.S @@ -340,23 +340,6 @@ _start: mtspr tcr,r0 /* disable all */ mtspr esr,r0 /* clear exception syndrome register */ mtxer r0 /* clear integer exception register */ -#if !defined(CONFIG_440GX) - lis r1,0x0002 /* set CE bit (Critical Exceptions) */ - ori r1,r1,0x1000 /* set ME bit (Machine Exceptions) */ - mtmsr r1 /* change MSR */ -#elif !defined(CONFIG_440EP) && !defined(CONFIG_440GR) - bl __440gx_msr_set - b __440gx_msr_continue - -__440gx_msr_set: - lis r1, 0x0002 /* set CE bit (Critical Exceptions) */ - ori r1,r1,0x1000 /* set ME bit (Machine Exceptions) */ - mtspr srr1,r1 - mflr r1 - mtspr srr0,r1 - rfi -__440gx_msr_continue: -#endif /*----------------------------------------------------------------*/ /* Debug setup -- some (not very good) ice's need an event*/ @@ -458,9 +441,6 @@ __440gx_msr_continue: mtspr esr,r0 /* clear Exception Syndrome Reg */ mttcr r0 /* timer control register */ mtexier r0 /* disable all interrupts */ - addi r4,r0,0x1000 /* set ME bit (Machine Exceptions) */ - oris r4,r4,0x2 /* set CE bit (Critical Exceptions) */ - mtmsr r4 /* change MSR */ addis r4,r0,0xFFFF /* set r4 to 0xFFFFFFFF (status in the */ ori r4,r4,0xFFFF /* dbsr is cleared by setting bits to 1) */ mtdbsr r4 /* clear/reset the dbsr */ @@ -571,9 +551,6 @@ __440gx_msr_continue: mttcr r4 /* clear Timer Control Reg */ mtxer r4 /* clear Fixed-Point Exception Reg */ mtevpr r4 /* clear Exception Vector Prefix Reg */ - addi r4,r0,0x1000 /* set ME bit (Machine Exceptions) */ - oris r4,r4,0x0002 /* set CE bit (Critical Exceptions) */ - mtmsr r4 /* change MSR */ addi r4,r0,(0xFFFF-0x10000) /* set r4 to 0xFFFFFFFF (status in the */ /* dbsr is cleared by setting bits to 1) */ mtdbsr r4 /* clear/reset the dbsr */ @@ -1428,6 +1405,24 @@ trap_init: cmplw 0, r7, r8 blt 4b +#if !defined(CONFIG_440_GX) + addi r7,r0,0x1000 /* set ME bit (Machine Exceptions) */ + oris r7,r7,0x0002 /* set CE bit (Critical Exceptions) */ + mtmsr r7 /* change MSR */ +#else + bl __440gx_msr_set + b __440gx_msr_continue + +__440gx_msr_set: + addi r7,r0,0x1000 /* set ME bit (Machine Exceptions) */ + oris r7,r7,0x0002 /* set CE bit (Critical Exceptions) */ + mtspr srr1,r7 + mflr r7 + mtspr srr0,r7 + rfi +__440gx_msr_continue: +#endif + mtlr r4 /* restore link register */ blr -- cgit v1.2.3 From f3fecfe6d7cf07a2c5879d64fc1d849a94a0b67d Mon Sep 17 00:00:00 2001 From: Stefan Roese Date: Mon, 13 Mar 2006 09:43:01 +0100 Subject: Fix problem with updated PCI code in cpu/ppc4xx/405gp_pci.c Patch by Stefan Roese, 13 Mar 2006 --- cpu/ppc4xx/405gp_pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'cpu') diff --git a/cpu/ppc4xx/405gp_pci.c b/cpu/ppc4xx/405gp_pci.c index f6b29e9d6e1..947b85e28a6 100644 --- a/cpu/ppc4xx/405gp_pci.c +++ b/cpu/ppc4xx/405gp_pci.c @@ -373,7 +373,7 @@ void pci_405gp_setup_vga(struct pci_controller *hose, pci_dev_t dev, { unsigned int cmdstat = 0; - pciauto_setup_device(hose, dev, 6, hose->pci_mem, hose->pci_io); + pciauto_setup_device(hose, dev, 6, hose->pci_mem, hose->pci_prefetch, hose->pci_io); /* always enable io space on vga boards */ pci_hose_read_config_dword(hose, dev, PCI_COMMAND, &cmdstat); -- cgit v1.2.3 From ff7fefe6797246b2748530f965f2e41de34a982a Mon Sep 17 00:00:00 2001 From: Wolfgang Denk Date: Mon, 13 Mar 2006 12:37:35 +0100 Subject: Apply SoC concept to arm926ejs CPUs, i.e. move the SoC specific timer and cpu_reset code from cpu/$(CPU) into the new cpu/$(CPU)/$(SOC) directories Patch by Andreas Engel, 13 Mar 2006 --- cpu/arm926ejs/interrupts.c | 148 +------------------------------- cpu/arm926ejs/omap/Makefile | 43 ++++++++++ cpu/arm926ejs/omap/reset.S | 45 ++++++++++ cpu/arm926ejs/omap/timer.c | 177 +++++++++++++++++++++++++++++++++++++++ cpu/arm926ejs/start.S | 22 ----- cpu/arm926ejs/versatile/Makefile | 43 ++++++++++ cpu/arm926ejs/versatile/reset.S | 45 ++++++++++ cpu/arm926ejs/versatile/timer.c | 175 ++++++++++++++++++++++++++++++++++++++ 8 files changed, 531 insertions(+), 167 deletions(-) create mode 100644 cpu/arm926ejs/omap/Makefile create mode 100644 cpu/arm926ejs/omap/reset.S create mode 100644 cpu/arm926ejs/omap/timer.c create mode 100644 cpu/arm926ejs/versatile/Makefile create mode 100644 cpu/arm926ejs/versatile/reset.S create mode 100644 cpu/arm926ejs/versatile/timer.c (limited to 'cpu') diff --git a/cpu/arm926ejs/interrupts.c b/cpu/arm926ejs/interrupts.c index 0457bff9645..9cac969f64a 100644 --- a/cpu/arm926ejs/interrupts.c +++ b/cpu/arm926ejs/interrupts.c @@ -39,16 +39,6 @@ #include #include -#define TIMER_LOAD_VAL 0xffffffff - -/* macro to read the 32 bit timer */ -#ifdef CONFIG_OMAP -#define READ_TIMER (*(volatile ulong *)(CFG_TIMERBASE+8)) -#endif -#ifdef CONFIG_VERSATILE -#define READ_TIMER (*(volatile ulong *)(CFG_TIMERBASE+4)) -#endif - #ifdef CONFIG_USE_IRQ /* enable IRQ interrupts */ void enable_interrupts (void) @@ -188,146 +178,14 @@ void do_irq (struct pt_regs *pt_regs) #else -static ulong timestamp; -static ulong lastdec; - /* nothing really to do with interrupts, just starts up a counter. */ int interrupt_init (void) { -#ifdef CONFIG_OMAP - int32_t val; - - /* Start the decrementer ticking down from 0xffffffff */ - *((int32_t *) (CFG_TIMERBASE + LOAD_TIM)) = TIMER_LOAD_VAL; - val = MPUTIM_ST | MPUTIM_AR | MPUTIM_CLOCK_ENABLE | (CFG_PVT << MPUTIM_PTV_BIT); - *((int32_t *) (CFG_TIMERBASE + CNTL_TIMER)) = val; -#endif /* CONFIG_OMAP */ - -#ifdef CONFIG_VERSATILE - *(volatile ulong *)(CFG_TIMERBASE + 0) = CFG_TIMER_RELOAD; /* TimerLoad */ - *(volatile ulong *)(CFG_TIMERBASE + 4) = CFG_TIMER_RELOAD; /* TimerValue */ - *(volatile ulong *)(CFG_TIMERBASE + 8) = 0x8C; -#endif /* CONFIG_VERSATILE */ - - /* init the timestamp and lastdec value */ - reset_timer_masked(); - - return (0); -} - -/* - * timer without interrupts - */ - -void reset_timer (void) -{ - reset_timer_masked (); -} + extern void timer_init(void); -ulong get_timer (ulong base) -{ - return get_timer_masked () - base; -} + timer_init(); -void set_timer (ulong t) -{ - timestamp = t; -} - -/* delay x useconds AND perserve advance timstamp value */ -void udelay (unsigned long usec) -{ - ulong tmo, tmp; - - if(usec >= 1000){ /* if "big" number, spread normalization to seconds */ - tmo = usec / 1000; /* start to normalize for usec to ticks per sec */ - tmo *= CFG_HZ; /* find number of "ticks" to wait to achieve target */ - tmo /= 1000; /* finish normalize. */ - }else{ /* else small number, don't kill it prior to HZ multiply */ - tmo = usec * CFG_HZ; - tmo /= (1000*1000); - } - - tmp = get_timer (0); /* get current timestamp */ - if( (tmo + tmp + 1) < tmp ) /* if setting this fordward will roll time stamp */ - reset_timer_masked (); /* reset "advancing" timestamp to 0, set lastdec value */ - else - tmo += tmp; /* else, set advancing stamp wake up time */ - - while (get_timer_masked () < tmo)/* loop till event */ - /*NOP*/; -} - -void reset_timer_masked (void) -{ - /* reset time */ - lastdec = READ_TIMER; /* capure current decrementer value time */ - timestamp = 0; /* start "advancing" time stamp from 0 */ -} - -ulong get_timer_masked (void) -{ - ulong now = READ_TIMER; /* current tick value */ - - if (lastdec >= now) { /* normal mode (non roll) */ - /* normal mode */ - timestamp += lastdec - now; /* move stamp fordward with absoulte diff ticks */ - } else { /* we have overflow of the count down timer */ - /* nts = ts + ld + (TLV - now) - * ts=old stamp, ld=time that passed before passing through -1 - * (TLV-now) amount of time after passing though -1 - * nts = new "advancing time stamp"...it could also roll and cause problems. - */ - timestamp += lastdec + TIMER_LOAD_VAL - now; - } - lastdec = now; - - return timestamp; -} - -/* waits specified delay value and resets timestamp */ -void udelay_masked (unsigned long usec) -{ - ulong tmo; - ulong endtime; - signed long diff; - - if (usec >= 1000) { /* if "big" number, spread normalization to seconds */ - tmo = usec / 1000; /* start to normalize for usec to ticks per sec */ - tmo *= CFG_HZ; /* find number of "ticks" to wait to achieve target */ - tmo /= 1000; /* finish normalize. */ - } else { /* else small number, don't kill it prior to HZ multiply */ - tmo = usec * CFG_HZ; - tmo /= (1000*1000); - } - - endtime = get_timer_masked () + tmo; - - do { - ulong now = get_timer_masked (); - diff = endtime - now; - } while (diff >= 0); -} - -/* - * This function is derived from PowerPC code (read timebase as long long). - * On ARM it just returns the timer value. - */ -unsigned long long get_ticks(void) -{ - return get_timer(0); -} - -/* - * This function is derived from PowerPC code (timebase clock frequency). - * On ARM it returns the number of timer ticks per second. - */ -ulong get_tbclk (void) -{ - ulong tbclk; - - tbclk = CFG_HZ; - return tbclk; + return 0; } #endif /* CONFIG_INTEGRATOR */ diff --git a/cpu/arm926ejs/omap/Makefile b/cpu/arm926ejs/omap/Makefile new file mode 100644 index 00000000000..f9d33781974 --- /dev/null +++ b/cpu/arm926ejs/omap/Makefile @@ -0,0 +1,43 @@ +# +# (C) Copyright 2000-2005 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# + +include $(TOPDIR)/config.mk + +LIB = lib$(SOC).a + +OBJS = timer.o +SOBJS = reset.o + +all: .depend $(LIB) + +$(LIB): $(OBJS) $(SOBJS) + $(AR) crv $@ $(OBJS) $(SOBJS) + +######################################################################### + +.depend: Makefile $(OBJS:.o=.c) + $(CC) -M $(CFLAGS) $(OBJS:.o=.c) > $@ + +sinclude .depend + +######################################################################### diff --git a/cpu/arm926ejs/omap/reset.S b/cpu/arm926ejs/omap/reset.S new file mode 100644 index 00000000000..e8989028e24 --- /dev/null +++ b/cpu/arm926ejs/omap/reset.S @@ -0,0 +1,45 @@ +/* + * armboot - Startup Code for ARM926EJS CPU-core + * + * Copyright (c) 2003 Texas Instruments + * + * ----- Adapted for OMAP1610 OMAP730 from ARM925t code ------ + * + * Copyright (c) 2001 Marius Gröger + * Copyright (c) 2002 Alex Züpke + * Copyright (c) 2002 Gary Jennejohn + * Copyright (c) 2003 Richard Woodruff + * Copyright (c) 2003 Kshitij + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + + .align 5 +.globl reset_cpu +reset_cpu: + ldr r1, rstctl1 /* get clkm1 reset ctl */ + mov r3, #0x0 + strh r3, [r1] /* clear it */ + mov r3, #0x8 + strh r3, [r1] /* force dsp+arm reset */ +_loop_forever: + b _loop_forever + +rstctl1: + .word 0xfffece10 diff --git a/cpu/arm926ejs/omap/timer.c b/cpu/arm926ejs/omap/timer.c new file mode 100644 index 00000000000..a2a9133ee05 --- /dev/null +++ b/cpu/arm926ejs/omap/timer.c @@ -0,0 +1,177 @@ +/* + * (C) Copyright 2003 + * Texas Instruments + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH + * Marius Groeger + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH + * Alex Zuepke + * + * (C) Copyright 2002-2004 + * Gary Jennejohn, DENX Software Engineering, + * + * (C) Copyright 2004 + * Philippe Robin, ARM Ltd. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include +#include + +#define TIMER_LOAD_VAL 0xffffffff + +/* macro to read the 32 bit timer */ +#define READ_TIMER (*(volatile ulong *)(CFG_TIMERBASE+8)) + +static ulong timestamp; +static ulong lastdec; + +int timer_init (void) +{ + int32_t val; + + /* Start the decrementer ticking down from 0xffffffff */ + *((int32_t *) (CFG_TIMERBASE + LOAD_TIM)) = TIMER_LOAD_VAL; + val = MPUTIM_ST | MPUTIM_AR | MPUTIM_CLOCK_ENABLE | (CFG_PVT << MPUTIM_PTV_BIT); + *((int32_t *) (CFG_TIMERBASE + CNTL_TIMER)) = val; + + /* init the timestamp and lastdec value */ + reset_timer_masked(); + + return 0; +} + +/* + * timer without interrupts + */ + +void reset_timer (void) +{ + reset_timer_masked (); +} + +ulong get_timer (ulong base) +{ + return get_timer_masked () - base; +} + +void set_timer (ulong t) +{ + timestamp = t; +} + +/* delay x useconds AND perserve advance timstamp value */ +void udelay (unsigned long usec) +{ + ulong tmo, tmp; + + if(usec >= 1000){ /* if "big" number, spread normalization to seconds */ + tmo = usec / 1000; /* start to normalize for usec to ticks per sec */ + tmo *= CFG_HZ; /* find number of "ticks" to wait to achieve target */ + tmo /= 1000; /* finish normalize. */ + }else{ /* else small number, don't kill it prior to HZ multiply */ + tmo = usec * CFG_HZ; + tmo /= (1000*1000); + } + + tmp = get_timer (0); /* get current timestamp */ + if( (tmo + tmp + 1) < tmp ) /* if setting this fordward will roll time stamp */ + reset_timer_masked (); /* reset "advancing" timestamp to 0, set lastdec value */ + else + tmo += tmp; /* else, set advancing stamp wake up time */ + + while (get_timer_masked () < tmo)/* loop till event */ + /*NOP*/; +} + +void reset_timer_masked (void) +{ + /* reset time */ + lastdec = READ_TIMER; /* capure current decrementer value time */ + timestamp = 0; /* start "advancing" time stamp from 0 */ +} + +ulong get_timer_masked (void) +{ + ulong now = READ_TIMER; /* current tick value */ + + if (lastdec >= now) { /* normal mode (non roll) */ + /* normal mode */ + timestamp += lastdec - now; /* move stamp fordward with absoulte diff ticks */ + } else { /* we have overflow of the count down timer */ + /* nts = ts + ld + (TLV - now) + * ts=old stamp, ld=time that passed before passing through -1 + * (TLV-now) amount of time after passing though -1 + * nts = new "advancing time stamp"...it could also roll and cause problems. + */ + timestamp += lastdec + TIMER_LOAD_VAL - now; + } + lastdec = now; + + return timestamp; +} + +/* waits specified delay value and resets timestamp */ +void udelay_masked (unsigned long usec) +{ + ulong tmo; + ulong endtime; + signed long diff; + + if (usec >= 1000) { /* if "big" number, spread normalization to seconds */ + tmo = usec / 1000; /* start to normalize for usec to ticks per sec */ + tmo *= CFG_HZ; /* find number of "ticks" to wait to achieve target */ + tmo /= 1000; /* finish normalize. */ + } else { /* else small number, don't kill it prior to HZ multiply */ + tmo = usec * CFG_HZ; + tmo /= (1000*1000); + } + + endtime = get_timer_masked () + tmo; + + do { + ulong now = get_timer_masked (); + diff = endtime - now; + } while (diff >= 0); +} + +/* + * This function is derived from PowerPC code (read timebase as long long). + * On ARM it just returns the timer value. + */ +unsigned long long get_ticks(void) +{ + return get_timer(0); +} + +/* + * This function is derived from PowerPC code (timebase clock frequency). + * On ARM it returns the number of timer ticks per second. + */ +ulong get_tbclk (void) +{ + ulong tbclk; + + tbclk = CFG_HZ; + return tbclk; +} diff --git a/cpu/arm926ejs/start.S b/cpu/arm926ejs/start.S index fc6b20b21e3..725c6639a1e 100644 --- a/cpu/arm926ejs/start.S +++ b/cpu/arm926ejs/start.S @@ -392,25 +392,3 @@ fiq: bl do_fiq #endif - -# ifdef CONFIG_INTEGRATOR - - /* Satisfied by Integrator routine (AP or CP) */ - -#else - - .align 5 -.globl reset_cpu -reset_cpu: - ldr r1, rstctl1 /* get clkm1 reset ctl */ - mov r3, #0x0 - strh r3, [r1] /* clear it */ - mov r3, #0x8 - strh r3, [r1] /* force dsp+arm reset */ -_loop_forever: - b _loop_forever - -rstctl1: - .word 0xfffece10 - -#endif /* #ifdef CONFIG_INTEGRATOR */ diff --git a/cpu/arm926ejs/versatile/Makefile b/cpu/arm926ejs/versatile/Makefile new file mode 100644 index 00000000000..f9d33781974 --- /dev/null +++ b/cpu/arm926ejs/versatile/Makefile @@ -0,0 +1,43 @@ +# +# (C) Copyright 2000-2005 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# + +include $(TOPDIR)/config.mk + +LIB = lib$(SOC).a + +OBJS = timer.o +SOBJS = reset.o + +all: .depend $(LIB) + +$(LIB): $(OBJS) $(SOBJS) + $(AR) crv $@ $(OBJS) $(SOBJS) + +######################################################################### + +.depend: Makefile $(OBJS:.o=.c) + $(CC) -M $(CFLAGS) $(OBJS:.o=.c) > $@ + +sinclude .depend + +######################################################################### diff --git a/cpu/arm926ejs/versatile/reset.S b/cpu/arm926ejs/versatile/reset.S new file mode 100644 index 00000000000..e8989028e24 --- /dev/null +++ b/cpu/arm926ejs/versatile/reset.S @@ -0,0 +1,45 @@ +/* + * armboot - Startup Code for ARM926EJS CPU-core + * + * Copyright (c) 2003 Texas Instruments + * + * ----- Adapted for OMAP1610 OMAP730 from ARM925t code ------ + * + * Copyright (c) 2001 Marius Gröger + * Copyright (c) 2002 Alex Züpke + * Copyright (c) 2002 Gary Jennejohn + * Copyright (c) 2003 Richard Woodruff + * Copyright (c) 2003 Kshitij + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + + .align 5 +.globl reset_cpu +reset_cpu: + ldr r1, rstctl1 /* get clkm1 reset ctl */ + mov r3, #0x0 + strh r3, [r1] /* clear it */ + mov r3, #0x8 + strh r3, [r1] /* force dsp+arm reset */ +_loop_forever: + b _loop_forever + +rstctl1: + .word 0xfffece10 diff --git a/cpu/arm926ejs/versatile/timer.c b/cpu/arm926ejs/versatile/timer.c new file mode 100644 index 00000000000..32872d2b66c --- /dev/null +++ b/cpu/arm926ejs/versatile/timer.c @@ -0,0 +1,175 @@ +/* + * (C) Copyright 2003 + * Texas Instruments + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH + * Marius Groeger + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH + * Alex Zuepke + * + * (C) Copyright 2002-2004 + * Gary Jennejohn, DENX Software Engineering, + * + * (C) Copyright 2004 + * Philippe Robin, ARM Ltd. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include +#include + +#define TIMER_LOAD_VAL 0xffffffff + +/* macro to read the 32 bit timer */ +#define READ_TIMER (*(volatile ulong *)(CFG_TIMERBASE+4)) + +static ulong timestamp; +static ulong lastdec; + +/* nothing really to do with interrupts, just starts up a counter. */ +int timer_init (void) +{ + *(volatile ulong *)(CFG_TIMERBASE + 0) = CFG_TIMER_RELOAD; /* TimerLoad */ + *(volatile ulong *)(CFG_TIMERBASE + 4) = CFG_TIMER_RELOAD; /* TimerValue */ + *(volatile ulong *)(CFG_TIMERBASE + 8) = 0x8C; + + /* init the timestamp and lastdec value */ + reset_timer_masked(); + + return 0; +} + +/* + * timer without interrupts + */ + +void reset_timer (void) +{ + reset_timer_masked (); +} + +ulong get_timer (ulong base) +{ + return get_timer_masked () - base; +} + +void set_timer (ulong t) +{ + timestamp = t; +} + +/* delay x useconds AND perserve advance timstamp value */ +void udelay (unsigned long usec) +{ + ulong tmo, tmp; + + if(usec >= 1000){ /* if "big" number, spread normalization to seconds */ + tmo = usec / 1000; /* start to normalize for usec to ticks per sec */ + tmo *= CFG_HZ; /* find number of "ticks" to wait to achieve target */ + tmo /= 1000; /* finish normalize. */ + }else{ /* else small number, don't kill it prior to HZ multiply */ + tmo = usec * CFG_HZ; + tmo /= (1000*1000); + } + + tmp = get_timer (0); /* get current timestamp */ + if( (tmo + tmp + 1) < tmp ) /* if setting this fordward will roll time stamp */ + reset_timer_masked (); /* reset "advancing" timestamp to 0, set lastdec value */ + else + tmo += tmp; /* else, set advancing stamp wake up time */ + + while (get_timer_masked () < tmo)/* loop till event */ + /*NOP*/; +} + +void reset_timer_masked (void) +{ + /* reset time */ + lastdec = READ_TIMER; /* capure current decrementer value time */ + timestamp = 0; /* start "advancing" time stamp from 0 */ +} + +ulong get_timer_masked (void) +{ + ulong now = READ_TIMER; /* current tick value */ + + if (lastdec >= now) { /* normal mode (non roll) */ + /* normal mode */ + timestamp += lastdec - now; /* move stamp fordward with absoulte diff ticks */ + } else { /* we have overflow of the count down timer */ + /* nts = ts + ld + (TLV - now) + * ts=old stamp, ld=time that passed before passing through -1 + * (TLV-now) amount of time after passing though -1 + * nts = new "advancing time stamp"...it could also roll and cause problems. + */ + timestamp += lastdec + TIMER_LOAD_VAL - now; + } + lastdec = now; + + return timestamp; +} + +/* waits specified delay value and resets timestamp */ +void udelay_masked (unsigned long usec) +{ + ulong tmo; + ulong endtime; + signed long diff; + + if (usec >= 1000) { /* if "big" number, spread normalization to seconds */ + tmo = usec / 1000; /* start to normalize for usec to ticks per sec */ + tmo *= CFG_HZ; /* find number of "ticks" to wait to achieve target */ + tmo /= 1000; /* finish normalize. */ + } else { /* else small number, don't kill it prior to HZ multiply */ + tmo = usec * CFG_HZ; + tmo /= (1000*1000); + } + + endtime = get_timer_masked () + tmo; + + do { + ulong now = get_timer_masked (); + diff = endtime - now; + } while (diff >= 0); +} + +/* + * This function is derived from PowerPC code (read timebase as long long). + * On ARM it just returns the timer value. + */ +unsigned long long get_ticks(void) +{ + return get_timer(0); +} + +/* + * This function is derived from PowerPC code (timebase clock frequency). + * On ARM it returns the number of timer ticks per second. + */ +ulong get_tbclk (void) +{ + ulong tbclk; + + tbclk = CFG_HZ; + return tbclk; +} -- cgit v1.2.3 From a7c66ad2e52b49a7cf5efb9665dd0527db96ea29 Mon Sep 17 00:00:00 2001 From: Marian Balakowicz Date: Tue, 14 Mar 2006 16:01:25 +0100 Subject: Correct shift offsets in icache_status and dcache_status for MPC83xx. --- cpu/mpc83xx/start.S | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'cpu') diff --git a/cpu/mpc83xx/start.S b/cpu/mpc83xx/start.S index 46c748f7905..324f6c36fe6 100644 --- a/cpu/mpc83xx/start.S +++ b/cpu/mpc83xx/start.S @@ -796,7 +796,7 @@ icache_disable: .globl icache_status icache_status: mfspr r3, HID0 - rlwinm r3, r3, HID0_ICE_SHIFT, 31, 31 + rlwinm r3, r3, (31 - HID0_ICE_SHIFT + 1), 31, 31 blr .globl dcache_enable @@ -828,7 +828,7 @@ dcache_disable: .globl dcache_status dcache_status: mfspr r3, HID0 - rlwinm r3, r3, HID0_DCE_SHIFT, 31, 31 + rlwinm r3, r3, (31 - HID0_DCE_SHIFT + 1), 31, 31 blr .globl get_pvr -- cgit v1.2.3 From cd94ba397ed9c7d06578977d6c34c24732b2a9f1 Mon Sep 17 00:00:00 2001 From: Marian Balakowicz Date: Tue, 14 Mar 2006 16:02:31 +0100 Subject: Add Dcbz(), Dcbi() and Dcbf() routines for MPC83xx. --- cpu/mpc83xx/start.S | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) (limited to 'cpu') diff --git a/cpu/mpc83xx/start.S b/cpu/mpc83xx/start.S index 324f6c36fe6..6e02cce799d 100644 --- a/cpu/mpc83xx/start.S +++ b/cpu/mpc83xx/start.S @@ -836,6 +836,40 @@ get_pvr: mfspr r3, PVR blr +/*------------------------------------------------------------------------------- */ +/* Function: ppcDcbf */ +/* Description: Data Cache block flush */ +/* Input: r3 = effective address */ +/* Output: none. */ +/*------------------------------------------------------------------------------- */ + .globl ppcDcbf +ppcDcbf: + dcbf r0,r3 + blr + +/*------------------------------------------------------------------------------- */ +/* Function: ppcDcbi */ +/* Description: Data Cache block Invalidate */ +/* Input: r3 = effective address */ +/* Output: none. */ +/*------------------------------------------------------------------------------- */ + .globl ppcDcbi +ppcDcbi: + dcbi r0,r3 + blr + +/*-------------------------------------------------------------------------- + * Function: ppcDcbz + * Description: Data Cache block zero. + * Input: r3 = effective address + * Output: none. + *-------------------------------------------------------------------------- */ + + .globl ppcDcbz +ppcDcbz: + dcbz r0,r3 + blr + /*-------------------------------------------------------------------*/ /* -- cgit v1.2.3 From 6d8ae5abb5311bd8e306a5a060dcfbeb0874a169 Mon Sep 17 00:00:00 2001 From: Marian Balakowicz Date: Tue, 14 Mar 2006 16:12:48 +0100 Subject: Add sync in do_reset() routine for MPC83xx after RPR register was written to. It is need on some targets when BAT translation is enabled. --- cpu/mpc83xx/cpu.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'cpu') diff --git a/cpu/mpc83xx/cpu.c b/cpu/mpc83xx/cpu.c index e49e4fe0ee4..63f82422f5b 100644 --- a/cpu/mpc83xx/cpu.c +++ b/cpu/mpc83xx/cpu.c @@ -93,6 +93,8 @@ do_reset (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) /* enable Reset Control Reg */ immap->reset.rpr = 0x52535445; + __asm__ __volatile__ ("sync"); + __asm__ __volatile__ ("isync"); /* confirm Reset Control Reg is enabled */ while(!((immap->reset.rcer) & RCER_CRE)); -- cgit v1.2.3 From 61f25155acd99caef08897da390382d5c7fbfd74 Mon Sep 17 00:00:00 2001 From: Marian Balakowicz Date: Tue, 14 Mar 2006 16:14:48 +0100 Subject: Add DMA support for MPC83xx. --- cpu/mpc83xx/cpu.c | 85 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) (limited to 'cpu') diff --git a/cpu/mpc83xx/cpu.c b/cpu/mpc83xx/cpu.c index 63f82422f5b..f24d3a4b1cd 100644 --- a/cpu/mpc83xx/cpu.c +++ b/cpu/mpc83xx/cpu.c @@ -191,3 +191,88 @@ ft_cpu_setup(void *blob, bd_t *bd) #endif } #endif + +#if defined(CONFIG_DDR_ECC) +void dma_init(void) +{ + volatile immap_t *immap = (immap_t *)CFG_IMMRBAR; + volatile dma8349_t *dma = &immap->dma; + volatile u32 status = swab32(dma->dmasr0); + volatile u32 dmamr0 = swab32(dma->dmamr0); + + debug("DMA-init\n"); + + /* initialize DMASARn, DMADAR and DMAABCRn */ + dma->dmadar0 = (u32)0; + dma->dmasar0 = (u32)0; + dma->dmabcr0 = 0; + + __asm__ __volatile__ ("sync"); + __asm__ __volatile__ ("isync"); + + /* clear CS bit */ + dmamr0 &= ~DMA_CHANNEL_START; + dma->dmamr0 = swab32(dmamr0); + __asm__ __volatile__ ("sync"); + __asm__ __volatile__ ("isync"); + + /* while the channel is busy, spin */ + while(status & DMA_CHANNEL_BUSY) { + status = swab32(dma->dmasr0); + } + + debug("DMA-init end\n"); +} + +uint dma_check(void) +{ + volatile immap_t *immap = (immap_t *)CFG_IMMRBAR; + volatile dma8349_t *dma = &immap->dma; + volatile u32 status = swab32(dma->dmasr0); + volatile u32 byte_count = swab32(dma->dmabcr0); + + /* while the channel is busy, spin */ + while (status & DMA_CHANNEL_BUSY) { + status = swab32(dma->dmasr0); + } + + if (status & DMA_CHANNEL_TRANSFER_ERROR) { + printf ("DMA Error: status = %x @ %d\n", status, byte_count); + } + + return status; +} + +int dma_xfer(void *dest, u32 count, void *src) +{ + volatile immap_t *immap = (immap_t *)CFG_IMMRBAR; + volatile dma8349_t *dma = &immap->dma; + volatile u32 dmamr0; + + /* initialize DMASARn, DMADAR and DMAABCRn */ + dma->dmadar0 = swab32((u32)dest); + dma->dmasar0 = swab32((u32)src); + dma->dmabcr0 = swab32(count); + + __asm__ __volatile__ ("sync"); + __asm__ __volatile__ ("isync"); + + /* init direct transfer, clear CS bit */ + dmamr0 = (DMA_CHANNEL_TRANSFER_MODE_DIRECT | + DMA_CHANNEL_SOURCE_ADDRESS_HOLD_8B | + DMA_CHANNEL_SOURCE_ADRESSS_HOLD_EN); + + dma->dmamr0 = swab32(dmamr0); + + __asm__ __volatile__ ("sync"); + __asm__ __volatile__ ("isync"); + + /* set CS to start DMA transfer */ + dmamr0 |= DMA_CHANNEL_START; + dma->dmamr0 = swab32(dmamr0); + __asm__ __volatile__ ("sync"); + __asm__ __volatile__ ("isync"); + + return ((int)dma_check()); +} +#endif /*CONFIG_DDR_ECC*/ -- cgit v1.2.3 From 4c8d1ecce23b848dee028d223551a8867de627ff Mon Sep 17 00:00:00 2001 From: Marian Balakowicz Date: Tue, 14 Mar 2006 16:23:35 +0100 Subject: Add support for ECC DDR initialization on MPC83xx. --- cpu/mpc83xx/spd_sdram.c | 130 ++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 108 insertions(+), 22 deletions(-) (limited to 'cpu') diff --git a/cpu/mpc83xx/spd_sdram.c b/cpu/mpc83xx/spd_sdram.c index 63dcd664be2..06a7da8f063 100644 --- a/cpu/mpc83xx/spd_sdram.c +++ b/cpu/mpc83xx/spd_sdram.c @@ -63,12 +63,16 @@ picos_to_clk(int picos) return clks; } -unsigned int -banksize(unsigned char row_dens) +unsigned int banksize(unsigned char row_dens) { return ((row_dens >> 2) | ((row_dens & 3) << 6)) << 24; } +int read_spd(uint addr) +{ + return ((int) addr); +} + long int spd_sdram(int(read_spd)(uint addr)) { volatile immap_t *immap = (immap_t *)CFG_IMMRBAR; @@ -84,7 +88,7 @@ long int spd_sdram(int(read_spd)(uint addr)) #warning Current spd_sdram does not fit its usage... adjust implementation or API... CFG_READ_SPD(SPD_EEPROM_ADDRESS, 0, 1, (uchar *) & spd, sizeof (spd)); - + if (spd.nrows > 2) { puts("DDR:Only two chip selects are supported on ADS.\n"); return 0; @@ -282,8 +286,13 @@ long int spd_sdram(int(read_spd)(uint addr)) */ #if defined(CONFIG_DDR_ECC) if (spd.config == 0x02) { - ddr->err_disable = 0x0000000d; - ddr->err_sbe = 0x00ff0000; + /* disable error detection */ + ddr->err_disable = ~ECC_ERROR_ENABLE; + + /* set single bit error threshold to maximum value, + * reset counter to zero */ + ddr->err_sbe = (255 << ECC_ERROR_MAN_SBET_SHIFT) | + (0 << ECC_ERROR_MAN_SBEC_SHIFT); } debug("DDR:err_disable=0x%08x\n", ddr->err_disable); debug("DDR:err_sbe=0x%08x\n", ddr->err_sbe); @@ -297,7 +306,8 @@ long int spd_sdram(int(read_spd)(uint addr)) * CLK_ADJST = 2-MCK/MCK_B, is lauched 1/2 of one SDRAM * clock cycle after address/command */ - ddr->sdram_clk_cntl = 0x82000000; + /*ddr->sdram_clk_cntl = 0x82000000;*/ + ddr->sdram_clk_cntl = (DDR_SDRAM_CLK_CNTL_SS_EN|DDR_SDRAM_CLK_CNTL_CLK_ADJUST_05); /* * Figure out the settings for the sdram_cfg register. Build up @@ -324,7 +334,7 @@ long int spd_sdram(int(read_spd)(uint addr)) * If the user wanted ECC (enabled via sdram_cfg[2]) */ if (spd.config == 0x02) { - tmp |= 0x20000000; + tmp |= SDRAM_CFG_ECC_EN; } #endif @@ -348,29 +358,87 @@ long int spd_sdram(int(read_spd)(uint addr)) #if defined(CONFIG_DDR_ECC) /* - * Initialize all of memory for ECC, then enable errors. + * Use timebase counter, get_timer() is not availabe + * at this point of initialization yet. */ +static __inline__ unsigned long get_tbms (void) +{ + unsigned long tbl; + unsigned long tbu1, tbu2; + unsigned long ms; + unsigned long long tmp; + + ulong tbclk = get_tbclk(); + + /* get the timebase ticks */ + do { + asm volatile ("mftbu %0":"=r" (tbu1):); + asm volatile ("mftb %0":"=r" (tbl):); + asm volatile ("mftbu %0":"=r" (tbu2):); + } while (tbu1 != tbu2); + + /* convert ticks to ms */ + tmp = (unsigned long long)(tbu1); + tmp = (tmp << 32); + tmp += (unsigned long long)(tbl); + ms = tmp/(tbclk/1000); + + return ms; +} -void -ddr_enable_ecc(unsigned int dram_size) +/* + * Initialize all of memory for ECC, then enable errors. + */ +//#define CONFIG_DDR_ECC_INIT_VIA_DMA +void ddr_enable_ecc(unsigned int dram_size) { -#ifndef FIXME - uint *p = 0; - uint i = 0; + uint *p; volatile immap_t *immap = (immap_t *)CFG_IMMRBAR; - volatile ccsr_ddr_t *ddr= &immap->im_ddr; + volatile ddr8349_t *ddr = &immap->ddr; + unsigned long t_start, t_end; +#if defined(CONFIG_DDR_ECC_INIT_VIA_DMA) + uint i; +#endif + debug("Initialize a Cachline in DRAM\n"); + icache_enable(); + +#if defined(CONFIG_DDR_ECC_INIT_VIA_DMA) + /* Initialise DMA for direct Transfers */ dma_init(); +#endif - for (*p = 0; p < (uint *)(8 * 1024); p++) { + t_start = get_tbms(); + +#if !defined(CONFIG_DDR_ECC_INIT_VIA_DMA) + debug("DDR init: Cache flush method\n"); + for (p = 0; p < (uint *)(dram_size); p++) { if (((unsigned int)p & 0x1f) == 0) { ppcDcbz((unsigned long) p); } + + /* write pattern to cache and flush */ *p = (unsigned int)0xdeadbeef; + if (((unsigned int)p & 0x1c) == 0x1c) { ppcDcbf((unsigned long) p); } } +#else + printf("DDR init: DMA method\n"); + for (p = 0; p < (uint *)(8 * 1024); p++) { + /* zero one data cache line */ + if (((unsigned int)p & 0x1f) == 0) { + ppcDcbz((unsigned long)p); + } + + /* write pattern to it and flush */ + *p = (unsigned int)0xdeadbeef; + + if (((unsigned int)p & 0x1c) == 0x1c) { + ppcDcbf((unsigned long)p); + } + } /* 8K */ dma_xfer((uint *)0x2000, 0x2000, (uint *)0); @@ -396,13 +464,31 @@ ddr_enable_ecc(unsigned int dram_size) for (i = 1; i < dram_size / 0x800000; i++) { dma_xfer((uint *)(0x800000*i), 0x800000, (uint *)0); } - - /* - * Enable errors for ECC. - */ - ddr->err_disable = 0x00000000; - asm("sync;isync"); #endif -} + t_end = get_tbms(); + icache_disable(); + + debug("\nREADY!!\n"); + debug("ddr init duration: %ld ms\n", t_end - t_start); + + /* Clear All ECC Errors */ + if ((ddr->err_detect & ECC_ERROR_DETECT_MME) == ECC_ERROR_DETECT_MME) + ddr->err_detect |= ECC_ERROR_DETECT_MME; + if ((ddr->err_detect & ECC_ERROR_DETECT_MBE) == ECC_ERROR_DETECT_MBE) + ddr->err_detect |= ECC_ERROR_DETECT_MBE; + if ((ddr->err_detect & ECC_ERROR_DETECT_SBE) == ECC_ERROR_DETECT_SBE) + ddr->err_detect |= ECC_ERROR_DETECT_SBE; + if ((ddr->err_detect & ECC_ERROR_DETECT_MSE) == ECC_ERROR_DETECT_MSE) + ddr->err_detect |= ECC_ERROR_DETECT_MSE; + + /* Disable ECC-Interrupts */ + ddr->err_int_en &= ECC_ERR_INT_DISABLE; + + /* Enable errors for ECC */ + ddr->err_disable &= ECC_ERROR_ENABLE; + + __asm__ __volatile__ ("sync"); + __asm__ __volatile__ ("isync"); +} #endif /* CONFIG_DDR_ECC */ -- cgit v1.2.3 From dc9e499c620a590e0f906e807e24c85807af3338 Mon Sep 17 00:00:00 2001 From: Rafal Jaworowski Date: Thu, 16 Mar 2006 17:46:46 +0100 Subject: Support for DDR with 32-data path. Addotional notes on injecting multiple-bit errors. --- cpu/mpc83xx/spd_sdram.c | 61 +++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 49 insertions(+), 12 deletions(-) (limited to 'cpu') diff --git a/cpu/mpc83xx/spd_sdram.c b/cpu/mpc83xx/spd_sdram.c index 06a7da8f063..b4012a8ddfc 100644 --- a/cpu/mpc83xx/spd_sdram.c +++ b/cpu/mpc83xx/spd_sdram.c @@ -1,4 +1,7 @@ /* + * (C) Copyright 2006 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * * Copyright 2004 Freescale Semiconductor. * (C) Copyright 2003 Motorola Inc. * Xianghua Xiao (X.Xiao@motorola.com) @@ -73,7 +76,32 @@ int read_spd(uint addr) return ((int) addr); } -long int spd_sdram(int(read_spd)(uint addr)) +#undef SPD_DEBUG +#ifdef SPD_DEBUG +static void spd_debug(spd_eeprom_t *spd) +{ + printf ("\nDIMM type: %-18.18s\n", spd->mpart); + printf ("SPD size: %d\n", spd->info_size); + printf ("EEPROM size: %d\n", 1 << spd->chip_size); + printf ("Memory type: %d\n", spd->mem_type); + printf ("Row addr: %d\n", spd->nrow_addr); + printf ("Column addr: %d\n", spd->ncol_addr); + printf ("# of rows: %d\n", spd->nrows); + printf ("Row density: %d\n", spd->row_dens); + printf ("# of banks: %d\n", spd->nbanks); + printf ("Data width: %d\n", + 256 * spd->dataw_msb + spd->dataw_lsb); + printf ("Chip width: %d\n", spd->primw); + printf ("Refresh rate: %02X\n", spd->refresh); + printf ("CAS latencies: %02X\n", spd->cas_lat); + printf ("Write latencies: %02X\n", spd->write_lat); + printf ("tRP: %d\n", spd->trp); + printf ("tRCD: %d\n", spd->trcd); + printf ("\n"); +} +#endif /* SPD_DEBUG */ + +long int spd_sdram() { volatile immap_t *immap = (immap_t *)CFG_IMMRBAR; volatile ddr8349_t *ddr = &immap->ddr; @@ -85,10 +113,10 @@ long int spd_sdram(int(read_spd)(uint addr)) unsigned char caslat; unsigned int trfc, trfc_clk, trfc_low; -#warning Current spd_sdram does not fit its usage... adjust implementation or API... - CFG_READ_SPD(SPD_EEPROM_ADDRESS, 0, 1, (uchar *) & spd, sizeof (spd)); - +#ifdef SPD_DEBUG + spd_debug(&spd); +#endif if (spd.nrows > 2) { puts("DDR:Only two chip selects are supported on ADS.\n"); return 0; @@ -223,25 +251,31 @@ long int spd_sdram(int(read_spd)(uint addr)) * Only DDR I is supported * DDR I and II have different mode-register-set definition */ - - /* burst length is always 4 */ switch(caslat) { case 2: - ddr->sdram_mode = 0x52; /* 1.5 */ + tmp = 0x50; /* 1.5 */ break; case 3: - ddr->sdram_mode = 0x22; /* 2.0 */ + tmp = 0x20; /* 2.0 */ break; case 4: - ddr->sdram_mode = 0x62; /* 2.5 */ + tmp = 0x60; /* 2.5 */ break; case 5: - ddr->sdram_mode = 0x32; /* 3.0 */ + tmp = 0x30; /* 3.0 */ break; default: puts("DDR:only CAS Latency 1.5, 2.0, 2.5, 3.0 is supported.\n"); return 0; } +#if defined (CONFIG_DDR_32BIT) + /* set burst length to 8 for 32-bit data path */ + tmp |= 0x03; +#else + /* set burst length to 4 - default for 64-bit data path */ + tmp |= 0x02; +#endif + ddr->sdram_mode = tmp; debug("DDR:sdram_mode=0x%08x\n", ddr->sdram_mode); switch(spd.refresh) { @@ -321,6 +355,10 @@ long int spd_sdram(int(read_spd)(uint addr)) */ tmp = 0xc2000000; +#if defined (CONFIG_DDR_32BIT) + /* in 32-Bit mode burst len is 8 beats */ + tmp |= (SDRAM_CFG_32_BE | SDRAM_CFG_8_BE); +#endif /* * sdram_cfg[3] = RD_EN - registered DIMM enable * A value of 0x26 indicates micron registered DIMMS (micron.com) @@ -350,8 +388,7 @@ long int spd_sdram(int(read_spd)(uint addr)) udelay(500); debug("DDR:sdram_cfg=0x%08x\n", ddr->sdram_cfg); - - return memsize;/*in MBytes*/ + return memsize; /*in MBytes*/ } #endif /* CONFIG_SPD_EEPROM */ -- cgit v1.2.3 From 7b4fd36b0322ec98836a8459d9be80e2777fdc05 Mon Sep 17 00:00:00 2001 From: Wolfgang Denk Date: Sat, 18 Mar 2006 23:31:12 +0100 Subject: Add support for MPC859/866 Rev. A.0 --- cpu/mpc8xx/cpu.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'cpu') diff --git a/cpu/mpc8xx/cpu.c b/cpu/mpc8xx/cpu.c index 4a32986a2e7..c4a0cba13a6 100644 --- a/cpu/mpc8xx/cpu.c +++ b/cpu/mpc8xx/cpu.c @@ -69,14 +69,15 @@ static int check_CPU (long clock, uint pvr, uint immr) k = (immr << 16) | *((ushort *) & immap->im_cpm.cp_dparam[0xB0]); m = 0; + suf = ""; /* * Some boards use sockets so different CPUs can be used. * We have to check chip version in run time. */ switch (k) { - case 0x00020001: pre = 'P'; suf = ""; break; - case 0x00030001: suf = ""; break; + case 0x00020001: pre = 'P'; break; + case 0x00030001: break; case 0x00120003: suf = "A"; break; case 0x00130003: suf = "A3"; break; @@ -93,7 +94,11 @@ static int check_CPU (long clock, uint pvr, uint immr) /* this value is not documented anywhere */ case 0x40000000: pre = 'P'; suf = "D"; m = 1; break; /* MPC866P/MPC866T/MPC859T/MPC859DSL/MPC852T */ - case 0x08000003: pre = 'M'; suf = ""; m = 1; + case 0x08010004: /* Rev. A.0 */ + suf = "A"; + /* fall through */ + case 0x08000003: /* Rev. 0.3 */ + pre = 'M'; m = 1; if (id_str == NULL) id_str = # if defined(CONFIG_MPC852T) -- cgit v1.2.3