From 6d0f6bcf337c5261c08fabe12982178c2c489d76 Mon Sep 17 00:00:00 2001 From: Jean-Christophe PLAGNIOL-VILLARD Date: Thu, 16 Oct 2008 15:01:15 +0200 Subject: rename CFG_ macros to CONFIG_SYS Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD --- cpu/blackfin/interrupts.c | 2 +- cpu/blackfin/start.S | 8 ++++---- cpu/blackfin/traps.c | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) (limited to 'cpu/blackfin') diff --git a/cpu/blackfin/interrupts.c b/cpu/blackfin/interrupts.c index 80c5505..d4dd636 100644 --- a/cpu/blackfin/interrupts.c +++ b/cpu/blackfin/interrupts.c @@ -48,7 +48,7 @@ ulong get_tbclk(void) { ulong tbclk; - tbclk = CFG_HZ; + tbclk = CONFIG_SYS_HZ; return tbclk; } diff --git a/cpu/blackfin/start.S b/cpu/blackfin/start.S index 30212e9..8303292 100644 --- a/cpu/blackfin/start.S +++ b/cpu/blackfin/start.S @@ -145,12 +145,12 @@ ENTRY(_start) r6 = 0 (x); p1 = r0; - p2.l = LO(CFG_MONITOR_BASE); - p2.h = HI(CFG_MONITOR_BASE); + p2.l = LO(CONFIG_SYS_MONITOR_BASE); + p2.h = HI(CONFIG_SYS_MONITOR_BASE); p3 = 0x04; - p4.l = LO(CFG_MONITOR_BASE + CFG_MONITOR_LEN); - p4.h = HI(CFG_MONITOR_BASE + CFG_MONITOR_LEN); + p4.l = LO(CONFIG_SYS_MONITOR_BASE + CONFIG_SYS_MONITOR_LEN); + p4.h = HI(CONFIG_SYS_MONITOR_BASE + CONFIG_SYS_MONITOR_LEN); .Lloop1: r1 = [p1 ++ p3]; [p2 ++ p3] = r1; diff --git a/cpu/blackfin/traps.c b/cpu/blackfin/traps.c index 4474fe5..2eb45b5 100644 --- a/cpu/blackfin/traps.c +++ b/cpu/blackfin/traps.c @@ -229,8 +229,8 @@ static void decode_address(char *buf, unsigned long address) if (!address) sprintf(buf, "<0x%p> /* Maybe null pointer? */", address); - else if (address >= CFG_MONITOR_BASE && - address < CFG_MONITOR_BASE + CFG_MONITOR_LEN) + else if (address >= CONFIG_SYS_MONITOR_BASE && + address < CONFIG_SYS_MONITOR_BASE + CONFIG_SYS_MONITOR_LEN) sprintf(buf, "<0x%p> /* somewhere in u-boot */", address); else sprintf(buf, "<0x%p> /* unknown address */", address); -- cgit v1.1 From e4337968e43698a68ba608369f46d4a4114111ca Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Thu, 7 Aug 2008 15:16:56 -0400 Subject: Blackfin: only enable hardware error irq by default Signed-off-by: Mike Frysinger --- cpu/blackfin/cpu.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'cpu/blackfin') diff --git a/cpu/blackfin/cpu.c b/cpu/blackfin/cpu.c index 53de5ab..0c79932 100644 --- a/cpu/blackfin/cpu.c +++ b/cpu/blackfin/cpu.c @@ -133,9 +133,8 @@ int irq_init(void) bfin_write_EVT15(evt_default); bfin_write_ILAT(0); CSYNC(); - /* enable all interrupts except for core timer */ - irq_flags = 0xffffffbf; + /* enable hardware error irq */ + irq_flags = 0x3f; local_irq_enable(); - CSYNC(); return 0; } -- cgit v1.1 From 50f0d211912a648e31aa9123b4665a0444bb8ca9 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Thu, 7 Aug 2008 15:21:47 -0400 Subject: Blackfin: unify cache handling code Signed-off-by: Mike Frysinger --- cpu/blackfin/cpu.c | 35 ----------------------------------- 1 file changed, 35 deletions(-) (limited to 'cpu/blackfin') diff --git a/cpu/blackfin/cpu.c b/cpu/blackfin/cpu.c index 0c79932..9efd88e 100644 --- a/cpu/blackfin/cpu.c +++ b/cpu/blackfin/cpu.c @@ -14,46 +14,11 @@ #include #include #include -#include #include #include "cpu.h" #include "serial.h" -void icache_enable(void) -{ - bfin_write_IMEM_CONTROL(bfin_read_IMEM_CONTROL() | (IMC | ENICPLB)); - SSYNC(); -} - -void icache_disable(void) -{ - bfin_write_IMEM_CONTROL(bfin_read_IMEM_CONTROL() & ~(IMC | ENICPLB)); - SSYNC(); -} - -int icache_status(void) -{ - return bfin_read_IMEM_CONTROL() & ENICPLB; -} - -void dcache_enable(void) -{ - bfin_write_DMEM_CONTROL(bfin_read_DMEM_CONTROL() | (ACACHE_BCACHE | ENDCPLB | PORT_PREF0)); - SSYNC(); -} - -void dcache_disable(void) -{ - bfin_write_DMEM_CONTROL(bfin_read_DMEM_CONTROL() & ~(ACACHE_BCACHE | ENDCPLB | PORT_PREF0)); - SSYNC(); -} - -int dcache_status(void) -{ - return bfin_read_DMEM_CONTROL() & ENDCPLB; -} - __attribute__ ((__noreturn__)) void cpu_init_f(ulong bootflag, ulong loaded_from_ldr) { -- cgit v1.1 From 2c1ea9e370cb72dd6a5aa32338e87a8a1f77bd76 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Thu, 7 Aug 2008 17:52:59 -0400 Subject: Blackfin: drop unused cache flush code Signed-off-by: Mike Frysinger --- cpu/blackfin/Makefile | 2 +- cpu/blackfin/flush.S | 230 -------------------------------------------------- 2 files changed, 1 insertion(+), 231 deletions(-) delete mode 100644 cpu/blackfin/flush.S (limited to 'cpu/blackfin') diff --git a/cpu/blackfin/Makefile b/cpu/blackfin/Makefile index f194a38..8fed4b4 100644 --- a/cpu/blackfin/Makefile +++ b/cpu/blackfin/Makefile @@ -16,7 +16,7 @@ LIB = $(obj)lib$(CPU).a EXTRA := CEXTRA := initcode.o SEXTRA := start.o -SOBJS := interrupt.o cache.o flush.o +SOBJS := interrupt.o cache.o COBJS := cpu.o traps.o interrupts.o reset.o serial.o i2c.o watchdog.o ifeq ($(CONFIG_BFIN_BOOT_MODE),BFIN_BOOT_BYPASS) diff --git a/cpu/blackfin/flush.S b/cpu/blackfin/flush.S deleted file mode 100644 index 417f798..0000000 --- a/cpu/blackfin/flush.S +++ /dev/null @@ -1,230 +0,0 @@ -/* flush.S - low level cache flushing routines - * Copyright (C) 2003-2007 Analog Devices Inc. - * Licensed under the GPL-2 or later. - */ - -#include -#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 data cache. - */ - -ENTRY(_flush_data_cache) - [--SP] = ( R7:6, P5:4 ); - LINK 12; - SP += -12; - P5.H = HI(DCPLB_ADDR0); - P5.L = LO(DCPLB_ADDR0); - P4.H = HI(DCPLB_DATA0); - P4.L = LO(DCPLB_DATA0); - R7 = CPLB_VALID | CPLB_L1_CHBL | CPLB_DIRTY (Z); - R6 = 16; -.Lnext: R0 = [P5++]; - R1 = [P4++]; - CC = BITTST(R1, 14); /* Is it write-through?*/ - IF CC JUMP .Lskip; /* If so, ignore it.*/ - R2 = R1 & R7; /* Is it a dirty, cached page?*/ - CC = R2; - IF !CC JUMP .Lskip; /* If not, ignore it.*/ - [--SP] = RETS; - CALL _dcplb_flush; /* R0 = page, R1 = data*/ - RETS = [SP++]; -.Lskip: R6 += -1; - CC = R6; - IF CC JUMP .Lnext; - SSYNC; - SP += 12; - UNLINK; - ( R7:6, P5:4 ) = [SP++]; - RTS; -ENDPROC(_flush_data_cache) - -/* 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 .Ldflush_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 = LO(DMEM_CONTROL); - P0.H = HI(DMEM_CONTROL); - - R3 = [P0]; /* If Bank B is not enabled as cache*/ - CC = BITTST(R3, 2); /* then Bank A is our only option.*/ - IF CC JUMP .Lbank_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.*/ - -.Lbank_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*/ - /* Save in extraction pattern for later deposit.*/ - R3.H = R4.L << 0; - - /* 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 = LO(DTEST_COMMAND); - P5.H = HI(DTEST_COMMAND); - P4.L = LO(DTEST_DATA0); - P4.H = HI(DTEST_DATA0); - - 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 (.Lfs1, .Lfe1) LC1 = P2; -.Lfs1: P0 = 64; /* iterate over all sets*/ - LSETUP (.Lfs0, .Lfe0) LC0 = P0; -.Lfs0: 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 .Lfskip; /* and skip if not.*/ - CC = BITTST(R7, 1); /* Check if dirty*/ - IF !CC JUMP .Lfskip; /* 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 .Lfskip; /* 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*/ -.Lfskip: -.Lfe0: R5 += 1; /* Advance to next Set*/ -.Lfe1: BITSET(R2, 26); /* Go to next Way.*/ - -.Ldfinished: - 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; - -.Ldflush_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 (.Leall, .Leall) LC0 = P1; -.Leall: FLUSHINV [P0++]; - SSYNC; - JUMP .Ldfinished; -ENDPROC(_dcplb_flush) - -.align 4; -page_prefix_table: -.byte4 0xFFFFFC00; /* 1K */ -.byte4 0xFFFFF000; /* 4K */ -.byte4 0xFFF00000; /* 1M */ -.byte4 0xFFC00000; /* 4M */ -.page_prefix_table.end: -- cgit v1.1 From 70c4c032ea112cc42aa1ce959c33fc4825eaef95 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Sun, 1 Jun 2008 01:23:48 -0400 Subject: Blackfin: enable support for nested interrupts During cpu init, make sure we initialize the CEC properly so that interrupts can fire and be handled while U-Boot is running. Signed-off-by: Mike Frysinger --- cpu/blackfin/start.S | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'cpu/blackfin') diff --git a/cpu/blackfin/start.S b/cpu/blackfin/start.S index 8303292..c4d52b4 100644 --- a/cpu/blackfin/start.S +++ b/cpu/blackfin/start.S @@ -75,7 +75,7 @@ ENTRY(_start) serial_early_puts("Init Registers"); - /* Disable nested interrupts and enable CYCLES for udelay() */ + /* Disable self-nested interrupts and enable CYCLES for udelay() */ R0 = CCEN | 0x30; SYSCFG = R0; @@ -180,7 +180,7 @@ ENTRY(_start) /* Now lower ourselves from the highest interrupt level to * the lowest. We do this by masking all interrupts but 15, - * setting the 15 handler to "board_init_f", raising the 15 + * setting the 15 handler to ".Lenable_nested", raising the 15 * interrupt, and then returning from the highest interrupt * level to the dummy "jump" until the interrupt controller * services the pending 15 interrupt. @@ -190,8 +190,8 @@ ENTRY(_start) r1 = r6; p0.l = LO(EVT15); p0.h = HI(EVT15); - p1.l = _cpu_init_f; - p1.h = _cpu_init_f; + p1.l = .Lenable_nested; + p1.h = .Lenable_nested; [p0] = p1; p2.l = LO(IMASK); p2.h = HI(IMASK); @@ -204,6 +204,12 @@ ENTRY(_start) reti = p4; rti; + /* Enable nested interrupts before continuing with cpu init */ +.Lenable_nested: + cli r7; + [--sp] = reti; + jump.l _cpu_init_f; + .LWAIT_HERE: jump .LWAIT_HERE; ENDPROC(_start) -- cgit v1.1 From 7133999e6f62a9a01f6a8ffe234b8532b3ad1e4b Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Mon, 6 Oct 2008 04:19:34 -0400 Subject: Blackfin: don't bother displaying reboot msg when crashing The hang function already tells you to reboot, so no point in showing it twice. Signed-off-by: Mike Frysinger --- cpu/blackfin/traps.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'cpu/blackfin') diff --git a/cpu/blackfin/traps.c b/cpu/blackfin/traps.c index 2eb45b5..7307f5d 100644 --- a/cpu/blackfin/traps.c +++ b/cpu/blackfin/traps.c @@ -344,10 +344,6 @@ void bfin_panic(struct pt_regs *regs) ); dump(regs); dump_bfin_trace_buffer(); - printf( - "\n" - "Please reset the board\n" - "\n" - ); + puts("\n"); bfin_reset_or_hang(); } -- cgit v1.1 From 2de95bb20c488f20298df6881b700a5a757ee780 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Mon, 6 Oct 2008 04:20:54 -0400 Subject: Blackfin: fix register dump messages Make sure we report RETI/IPEND correctly. Signed-off-by: Mike Frysinger --- cpu/blackfin/traps.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'cpu/blackfin') diff --git a/cpu/blackfin/traps.c b/cpu/blackfin/traps.c index 7307f5d..5a26c52 100644 --- a/cpu/blackfin/traps.c +++ b/cpu/blackfin/traps.c @@ -244,6 +244,9 @@ void dump(struct pt_regs *fp) if (!ENABLE_DUMP) return; + /* fp->ipend is garbage, so load it ourself */ + fp->ipend = bfin_read_IPEND(); + printf("SEQUENCER STATUS:\n"); printf(" SEQSTAT: %08lx IPEND: %04lx SYSCFG: %04lx\n", fp->seqstat, fp->ipend, fp->syscfg); @@ -263,8 +266,9 @@ void dump(struct pt_regs *fp) printf(" RETX: %s\n", buf); decode_address(buf, fp->rets); printf(" RETS: %s\n", buf); + /* we lie and store RETI in "pc" */ decode_address(buf, fp->pc); - printf(" PC : %s\n", buf); + printf(" RETI: %s\n", buf); if (fp->seqstat & EXCAUSE) { decode_address(buf, bfin_read_DCPLB_FAULT_ADDR()); -- cgit v1.1 From 0ba1da116e5edcb0c5ae4a7585d73f6548400a06 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Mon, 6 Oct 2008 04:21:41 -0400 Subject: Blackfin: decode hwerrcause/excause when crashing Having to decode hwerrcause/excause values is a pain, so automate it. Signed-off-by: Mike Frysinger --- cpu/blackfin/traps.c | 42 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) (limited to 'cpu/blackfin') diff --git a/cpu/blackfin/traps.c b/cpu/blackfin/traps.c index 5a26c52..d17c0a1 100644 --- a/cpu/blackfin/traps.c +++ b/cpu/blackfin/traps.c @@ -236,10 +236,45 @@ static void decode_address(char *buf, unsigned long address) sprintf(buf, "<0x%p> /* unknown address */", address); } +static char *strhwerrcause(uint16_t hwerrcause) +{ + switch (hwerrcause) { + case 0x02: return "system mmr error"; + case 0x03: return "external memory addressing error"; + case 0x12: return "performance monitor overflow"; + case 0x18: return "raise 5 instruction"; + default: return "undef"; + } +} + +static char *strexcause(uint16_t excause) +{ + switch (excause) { + case 0x00 ... 0xf: return "custom exception"; + case 0x10: return "single step"; + case 0x11: return "trace buffer full"; + case 0x21: return "undef inst"; + case 0x22: return "illegal inst"; + case 0x23: return "dcplb prot violation"; + case 0x24: return "misaligned data"; + case 0x25: return "unrecoverable event"; + case 0x26: return "dcplb miss"; + case 0x27: return "multiple dcplb hit"; + case 0x28: return "emulation watchpoint"; + case 0x2a: return "misaligned inst"; + case 0x2b: return "icplb prot violation"; + case 0x2c: return "icplb miss"; + case 0x2d: return "multiple icplb hit"; + case 0x2e: return "illegal use of supervisor resource"; + default: return "undef"; + } +} + void dump(struct pt_regs *fp) { char buf[150]; size_t i; + uint16_t hwerrcause, excause; if (!ENABLE_DUMP) return; @@ -247,11 +282,14 @@ void dump(struct pt_regs *fp) /* fp->ipend is garbage, so load it ourself */ fp->ipend = bfin_read_IPEND(); + hwerrcause = (fp->seqstat & HWERRCAUSE) >> HWERRCAUSE_P; + excause = (fp->seqstat & EXCAUSE) >> EXCAUSE_P; + printf("SEQUENCER STATUS:\n"); printf(" SEQSTAT: %08lx IPEND: %04lx SYSCFG: %04lx\n", fp->seqstat, fp->ipend, fp->syscfg); - printf(" HWERRCAUSE: 0x%lx\n", (fp->seqstat & HWERRCAUSE) >> HWERRCAUSE_P); - printf(" EXCAUSE : 0x%lx\n", (fp->seqstat & EXCAUSE) >> EXCAUSE_P); + printf(" HWERRCAUSE: 0x%lx: %s\n", hwerrcause, strhwerrcause(hwerrcause)); + printf(" EXCAUSE : 0x%lx: %s\n", excause, strexcause(excause)); for (i = 6; i <= 15; ++i) { if (fp->ipend & (1 << i)) { decode_address(buf, bfin_read32(EVT0 + 4*i)); -- cgit v1.1 From 25cd33d82ea521b7bd90ca858f8919fae1e9732b Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Sun, 20 Apr 2008 03:11:53 -0400 Subject: Blackfin: make baud calculation more accurate We should use the algorithm in the Linux kernel so that the UART divisor calculation is more accurate. It also fixes problems on some picky UARTs that have sampling anomalies. Signed-off-by: Mike Frysinger --- cpu/blackfin/serial.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'cpu/blackfin') diff --git a/cpu/blackfin/serial.h b/cpu/blackfin/serial.h index 1f0f4b4..ec40c26 100644 --- a/cpu/blackfin/serial.h +++ b/cpu/blackfin/serial.h @@ -175,11 +175,11 @@ static inline uint32_t serial_early_get_baud(void) __attribute__((always_inline)) static inline void serial_early_set_baud(uint32_t baud) { - /* Translate from baud into divisor in terms of SCLK. - * The +1 is to make sure we over sample just a little - * rather than under sample the incoming signals. + /* Translate from baud into divisor in terms of SCLK. The + * weird multiplication is to make sure we over sample just + * a little rather than under sample the incoming signals. */ - uint16_t divisor = (get_sclk() / (baud * 16)) + 1; + uint16_t divisor = (get_sclk() + (baud * 8)) / (baud * 16) - ANOMALY_05000230; /* Set DLAB in LCR to Access DLL and DLH */ ACCESS_LATCH(); -- cgit v1.1 From 960922291c9594acb575cec7e47d7bed9b58182c Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Sat, 11 Oct 2008 21:18:10 -0400 Subject: Blackfin: set initial stack correctly according to Blackfin ABI Signed-off-by: Mike Frysinger --- cpu/blackfin/start.S | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'cpu/blackfin') diff --git a/cpu/blackfin/start.S b/cpu/blackfin/start.S index c4d52b4..f351fab 100644 --- a/cpu/blackfin/start.S +++ b/cpu/blackfin/start.S @@ -1,7 +1,7 @@ /* * U-boot - start.S Startup file for Blackfin u-boot * - * Copyright (c) 2005-2007 Analog Devices Inc. + * Copyright (c) 2005-2008 Analog Devices Inc. * * This file is based on head.S * Copyright (c) 2003 Metrowerks/Motorola @@ -49,8 +49,8 @@ ENTRY(_start) /* Set our initial stack to L1 scratch space */ - sp.l = LO(L1_SRAM_SCRATCH + L1_SRAM_SCRATCH_SIZE); - sp.h = HI(L1_SRAM_SCRATCH + L1_SRAM_SCRATCH_SIZE); + sp.l = LO(L1_SRAM_SCRATCH_END - 20); + sp.h = HI(L1_SRAM_SCRATCH_END - 20); #ifdef CONFIG_HW_WATCHDOG # ifndef CONFIG_HW_WATCHDOG_TIMEOUT_START -- cgit v1.1 From bd33e5c613cf70e3cb51a73fdd653fe83b942bb0 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Sat, 11 Oct 2008 21:19:39 -0400 Subject: Blackfin: small cpu init optimization while setting interrupt mask Use the sti instruction to set the initial interrupt mask rather than banging on the core IMASK MMR to save both space and time. Signed-off-by: Mike Frysinger --- cpu/blackfin/start.S | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'cpu/blackfin') diff --git a/cpu/blackfin/start.S b/cpu/blackfin/start.S index f351fab..9975a0c 100644 --- a/cpu/blackfin/start.S +++ b/cpu/blackfin/start.S @@ -193,11 +193,8 @@ ENTRY(_start) p1.l = .Lenable_nested; p1.h = .Lenable_nested; [p0] = p1; - p2.l = LO(IMASK); - p2.h = HI(IMASK); - p3.l = LO(EVT_IVG15); - p3.h = HI(EVT_IVG15); - [p2] = p3; + r7 = EVT_IVG15 (z); + sti r7; raise 15; p4.l = .LWAIT_HERE; p4.h = .LWAIT_HERE; -- cgit v1.1 From f177f4250c729727b1629fa8d8d6556c999e9b8c Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Wed, 9 Apr 2008 02:02:07 -0400 Subject: Blackfin: fix up UART status bit handling Some Blackfin UARTs are read-to-clear while others are write-to-clear. This can cause problems when we poll the LSR and then later try and handle any errors detected. Signed-off-by: Mike Frysinger --- cpu/blackfin/serial.c | 72 ++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 60 insertions(+), 12 deletions(-) (limited to 'cpu/blackfin') diff --git a/cpu/blackfin/serial.c b/cpu/blackfin/serial.c index 406d9d0..0d6f377 100644 --- a/cpu/blackfin/serial.c +++ b/cpu/blackfin/serial.c @@ -35,6 +35,32 @@ #include "serial.h" +#ifdef CONFIG_DEBUG_SERIAL +uint16_t cached_lsr[256]; +uint16_t cached_rbr[256]; +size_t cache_count; + +/* The LSR is read-to-clear on some parts, so we have to make sure status + * bits aren't inadvertently lost when doing various tests. + */ +static uint16_t uart_lsr_save; +static uint16_t uart_lsr_read(void) +{ + uint16_t lsr = *pUART_LSR; + uart_lsr_save |= (lsr & (OE|PE|FE|BI)); + return lsr | uart_lsr_save; +} +/* Just do the clear for everyone since it can't hurt. */ +static void uart_lsr_clear(void) +{ + uart_lsr_save = 0; + *pUART_LSR |= -1; +} +#else +static inline uint16_t uart_lsr_read(void) { return *pUART_LSR; } +static inline void uart_lsr_clear(void) { *pUART_LSR = -1; } +#endif + /* Symbol for our assembly to call. */ void serial_set_baud(uint32_t baud) { @@ -61,6 +87,12 @@ int serial_init(void) { serial_initialize(); serial_setbrg(); + uart_lsr_clear(); +#ifdef CONFIG_DEBUG_SERIAL + cache_count = 0; + memset(cached_lsr, 0x00, sizeof(cached_lsr)); + memset(cached_rbr, 0x00, sizeof(cached_rbr)); +#endif return 0; } @@ -73,7 +105,7 @@ void serial_putc(const char c) WATCHDOG_RESET(); /* wait for the hardware fifo to clear up */ - while (!(*pUART_LSR & THRE)) + while (!(uart_lsr_read() & THRE)) continue; /* queue the character for transmission */ @@ -83,38 +115,54 @@ void serial_putc(const char c) WATCHDOG_RESET(); /* wait for the byte to be shifted over the line */ - while (!(*pUART_LSR & TEMT)) + while (!(uart_lsr_read() & TEMT)) continue; } int serial_tstc(void) { WATCHDOG_RESET(); - return (*pUART_LSR & DR) ? 1 : 0; + return (uart_lsr_read() & DR) ? 1 : 0; } int serial_getc(void) { - uint16_t uart_lsr_val, uart_rbr_val; + uint16_t uart_rbr_val; /* wait for data ! */ while (!serial_tstc()) continue; - /* clear the status and grab the new byte */ - uart_lsr_val = *pUART_LSR; + /* grab the new byte */ uart_rbr_val = *pUART_RBR; +#ifdef CONFIG_DEBUG_SERIAL + /* grab & clear the LSR */ + uint16_t uart_lsr_val = uart_lsr_read(); + + cached_lsr[cache_count] = uart_lsr_val; + cached_rbr[cache_count] = uart_rbr_val; + cache_count = (cache_count + 1) % ARRAY_SIZE(cached_lsr); + if (uart_lsr_val & (OE|PE|FE|BI)) { - /* Some parts are read-to-clear while others are - * write-to-clear. Just do the write for everyone - * since it cant hurt (other than code size). - */ - *pUART_LSR = (OE|PE|FE|BI); + uint16_t dll, dlh; + printf("\n[SERIAL ERROR]\n"); + ACCESS_LATCH(); + dll = *pUART_DLL; + dlh = *pUART_DLH; + ACCESS_PORT_IER(); + printf("\tDLL=0x%x DLH=0x%x\n", dll, dlh); + do { + --cache_count; + printf("\t%3i: RBR=0x%02x LSR=0x%02x\n", cache_count, + cached_rbr[cache_count], cached_lsr[cache_count]); + } while (cache_count > 0); return -1; } +#endif + uart_lsr_clear(); - return uart_rbr_val & 0xFF; + return uart_rbr_val; } void serial_puts(const char *s) -- cgit v1.1 From ecf5f077c8e77454f532eaac3e3afb7cfc48c62d Mon Sep 17 00:00:00 2001 From: Timur Tabi Date: Wed, 3 Dec 2008 11:28:30 -0600 Subject: i2c: merge all i2c_reg_read() and i2c_reg_write() into inline functions All implementations of the functions i2c_reg_read() and i2c_reg_write() are identical. We can save space and simplify the code by converting these functions into inlines and putting them in i2c.h. Signed-off-by: Timur Tabi Acked-By: Jean-Christophe PLAGNIOL-VILLARD --- cpu/blackfin/i2c.c | 16 ---------------- 1 file changed, 16 deletions(-) (limited to 'cpu/blackfin') diff --git a/cpu/blackfin/i2c.c b/cpu/blackfin/i2c.c index 60f03d4..2a3e223 100644 --- a/cpu/blackfin/i2c.c +++ b/cpu/blackfin/i2c.c @@ -425,20 +425,4 @@ int i2c_write(uchar chip, uint addr, int alen, uchar * buffer, int len) } -uchar i2c_reg_read(uchar chip, uchar reg) -{ - uchar buf; - - PRINTD("i2c_reg_read: chip=0x%02x, reg=0x%02x\n", chip, reg); - i2c_read(chip, reg, 0, &buf, 1); - return (buf); -} - -void i2c_reg_write(uchar chip, uchar reg, uchar val) -{ - PRINTD("i2c_reg_write: chip=0x%02x, reg=0x%02x, val=0x%02x\n", chip, - reg, val); - i2c_write(chip, reg, 0, &val, 1); -} - #endif /* CONFIG_HARD_I2C */ -- cgit v1.1