From 1cd9158eb4e5961e225a870195ccc8eed5d90adc Mon Sep 17 00:00:00 2001 From: Sonic Zhang Date: Fri, 8 Feb 2013 17:04:58 +0800 Subject: blackfin: Change the member's type in dma structures. Signed-off-by: Sonic Zhang diff --git a/arch/blackfin/include/asm/dma.h b/arch/blackfin/include/asm/dma.h index ef1db6e..8a7c079 100644 --- a/arch/blackfin/include/asm/dma.h +++ b/arch/blackfin/include/asm/dma.h @@ -17,21 +17,21 @@ struct dmasg_large { void *next_desc_addr; - unsigned long start_addr; - unsigned short cfg; - unsigned short x_count; - short x_modify; - unsigned short y_count; - short y_modify; + u32 start_addr; + u16 cfg; + u16 x_count; + s16 x_modify; + u16 y_count; + s16 y_modify; } __attribute__((packed)); struct dmasg { - unsigned long start_addr; - unsigned short cfg; - unsigned short x_count; - short x_modify; - unsigned short y_count; - short y_modify; + u32 start_addr; + u16 cfg; + u16 x_count; + s16 x_modify; + u16 y_count; + s16 y_modify; } __attribute__((packed)); struct dma_register { -- cgit v0.10.2 From c4239b5341b6eb8126072c853d1eb32e86face7f Mon Sep 17 00:00:00 2001 From: Sonic Zhang Date: Tue, 11 Dec 2012 16:51:23 +0800 Subject: blackfin: limit the max memory dma peripheral transfer size to 4 bytes. Othersize, the bf609 memory dma halts after being enabled. Signed-off-by: Sonic Zhang diff --git a/arch/blackfin/lib/string.c b/arch/blackfin/lib/string.c index 44d8c6d..5b7ac0b 100644 --- a/arch/blackfin/lib/string.c +++ b/arch/blackfin/lib/string.c @@ -128,10 +128,12 @@ static void dma_calc_size(unsigned long ldst, unsigned long lsrc, size_t count, unsigned long limit; #ifdef MSIZE - limit = 6; + /* The max memory DMA memory transfer size is 32 bytes. */ + limit = 5; *dshift = MSIZE_P; #else - limit = 3; + /* The max memory DMA memory transfer size is 4 bytes. */ + limit = 2; *dshift = WDSIZE_P; #endif @@ -170,7 +172,8 @@ void dma_memcpy_nocache(void *dst, const void *src, size_t count) mod = 1 << bpos; #ifdef PSIZE - dsize |= min(3, bpos) << PSIZE_P; + /* The max memory DMA peripheral transfer size is 4 bytes. */ + dsize |= min(2, bpos) << PSIZE_P; #endif /* Copy sram functions from sdram to sram */ -- cgit v0.10.2 From e0ae433e9283728ce3f25e0d3794291c11e48f5e Mon Sep 17 00:00:00 2001 From: Bob Liu Date: Tue, 5 Feb 2013 19:22:20 +0800 Subject: blackfin: reduce size of u-boot.ldr in bf548-ezkit default config. Enable VIDEO and NAND supports only when the config options is defined. Signed-off-by: Bob Liu Signed-off-by: Sonic Zhang diff --git a/include/configs/bf548-ezkit.h b/include/configs/bf548-ezkit.h index e6b05db..7ed0ea9 100644 --- a/include/configs/bf548-ezkit.h +++ b/include/configs/bf548-ezkit.h @@ -120,18 +120,16 @@ #define CONFIG_ENV_SECT_SIZE 0x8000 #endif - /* * NAND Settings */ -#define CONFIG_BFIN_NFC_CTL_VAL 0x0033 #if (CONFIG_BFIN_BOOT_MODE == BFIN_BOOT_NAND) -# define CONFIG_BFIN_NFC_BOOTROM_ECC -#endif +#define CONFIG_BFIN_NFC_CTL_VAL 0x0033 +#define CONFIG_BFIN_NFC_BOOTROM_ECC #define CONFIG_DRIVER_NAND_BFIN -#define CONFIG_SYS_NAND_BASE 0 /* not actually used */ -#define CONFIG_SYS_MAX_NAND_DEVICE 1 - +#define CONFIG_SYS_NAND_BASE 0 /* not actually used */ +#define CONFIG_SYS_MAX_NAND_DEVICE 1 +#endif /* * I2C Settings @@ -184,13 +182,10 @@ #define CONFIG_UART_CONSOLE 1 #define CONFIG_BFIN_SPI_IMG_SIZE 0x50000 -#ifndef __ADSPBF542__ -/* Don't waste time transferring a logo over the UART */ -# if (CONFIG_BFIN_BOOT_MODE != BFIN_BOOT_UART) -# define CONFIG_VIDEO -# define EASYLOGO_HEADER -# endif -# define CONFIG_DEB_DMA_URGENT +#undef CONFIG_VIDEO +#ifdef CONFIG_VIDEO +#define EASYLOGO_HEADER < asm/bfin_logo_230x230_gzip.h > +#define CONFIG_DEB_DMA_URGENT #endif /* Define if want to do post memory test */ -- cgit v0.10.2 From 2e2ed3f4ff5f21a5c39394c55d361e826238ce2d Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Tue, 31 Jul 2012 05:38:56 -0400 Subject: Blackfin: adjust asm constraints with NMI workaround Newer gcc versions will sometimes use a Preg when "r" constraints, but that'll fail if we use an Ireg in the assignment. So force the code to always use a Dreg. This also fixes early boot crashes for older Blackfin parts when compiled with gcc-4.5. This version ends up selecting the same register for the input and output variables which corrupts the output assignment triggering an exception. P2 = 0xffe02008; /* EVT2 */ R0 = RETS; CALL 1f; RTN; 1: P2 = RETS; <-- BAD RETS = R0; [P2] = P2; <-- BAD Signed-off-by: Mike Frysinger Signed-off-by: Sonic Zhang diff --git a/arch/blackfin/cpu/initcode.c b/arch/blackfin/cpu/initcode.c index 1a06680..e8ea0ba 100644 --- a/arch/blackfin/cpu/initcode.c +++ b/arch/blackfin/cpu/initcode.c @@ -262,7 +262,8 @@ program_nmi_handler(void) "%1 = RETS;" /* Load addr of NMI handler */ "RETS = %0;" /* Restore RETS */ "[%2] = %1;" /* Write NMI handler */ - : "=r"(tmp1), "=r"(tmp2) : "ab"(EVT2) + : "=d"(tmp1), "=d"(tmp2) + : "ab"(EVT2) ); } -- cgit v0.10.2 From ddb5c5be1eddd38a47dc197cfacdbf149930740d Mon Sep 17 00:00:00 2001 From: Bob Liu Date: Mon, 13 Aug 2012 14:22:08 +0800 Subject: blackfin: add baudrate to bdinfo Signed-off-by: Bob Liu Signed-off-by: Sonic Zhang diff --git a/arch/blackfin/lib/board.c b/arch/blackfin/lib/board.c index ccea3b9..85b859d 100644 --- a/arch/blackfin/lib/board.c +++ b/arch/blackfin/lib/board.c @@ -231,6 +231,8 @@ static int global_board_data_init(void) bd->bi_sclk = get_sclk(); bd->bi_memstart = CONFIG_SYS_SDRAM_BASE; bd->bi_memsize = CONFIG_SYS_MAX_RAM_SIZE; + bd->bi_baudrate = (gd->baudrate > 0) + ? simple_strtoul(gd->baudrate, NULL, 10) : CONFIG_BAUDRATE; return 0; } -- cgit v0.10.2 From f4d8038439fb372c91c3a27121a911c359603bcf Mon Sep 17 00:00:00 2001 From: Sonic Zhang Date: Tue, 5 Feb 2013 18:57:49 +0800 Subject: blackfin: run core1 from L1 code sram start address in uboot init code on core 0 Define core 1 L1 code sram start address. Add function to enable core 1 for BF609 and BF561. Add config macro to allow customer to run core 1 in uboot init code on core 0. Signed-off-by: Sonic Zhang diff --git a/arch/blackfin/cpu/cpu.c b/arch/blackfin/cpu/cpu.c index 0be2e2b..d841f64 100644 --- a/arch/blackfin/cpu/cpu.c +++ b/arch/blackfin/cpu/cpu.c @@ -23,6 +23,32 @@ ulong bfin_poweron_retx; +#if defined(CONFIG_CORE1_RUN) && defined(COREB_L1_CODE_START) +void bfin_core1_start(void) +{ +#ifdef BF561_FAMILY + /* Enable core 1 */ + bfin_write_SYSCR(bfin_read_SYSCR() & ~0x0020); +#else + /* Enable core 1 */ + bfin_write32(RCU0_SVECT1, COREB_L1_CODE_START); + bfin_write32(RCU0_CRCTL, 0); + + bfin_write32(RCU0_CRCTL, 0x2); + + /* Check if core 1 starts */ + while (!(bfin_read32(RCU0_CRSTAT) & 0x2)) + continue; + + bfin_write32(RCU0_CRCTL, 0); + + /* flag to notify cces core 1 application */ + bfin_write32(SDU0_MSG_SET, (1 << 19)); +#endif +} +#endif + +__attribute__ ((__noreturn__)) void cpu_init_f(ulong bootflag, ulong loaded_from_ldr) { #ifndef CONFIG_BFIN_BOOTROM_USES_EVT1 @@ -72,6 +98,10 @@ void cpu_init_f(ulong bootflag, ulong loaded_from_ldr) # endif #endif +#if defined(CONFIG_CORE1_RUN) && defined(COREB_L1_CODE_START) + bfin_core1_start(); +#endif + serial_early_puts("Board init flash\n"); board_init_f(bootflag); } diff --git a/arch/blackfin/include/asm/mach-bf561/BF561_def.h b/arch/blackfin/include/asm/mach-bf561/BF561_def.h index a7ff5a3..8fd552f 100644 --- a/arch/blackfin/include/asm/mach-bf561/BF561_def.h +++ b/arch/blackfin/include/asm/mach-bf561/BF561_def.h @@ -714,4 +714,6 @@ #define L1_INST_SRAM_SIZE (0xFFA03FFF - 0xFFA00000 + 1) #define L1_INST_SRAM_END (L1_INST_SRAM + L1_INST_SRAM_SIZE) +#define COREB_L1_CODE_START 0xFF600000 + #endif /* __BFIN_DEF_ADSP_BF561_proc__ */ diff --git a/arch/blackfin/include/asm/mach-bf609/BF609_def.h b/arch/blackfin/include/asm/mach-bf609/BF609_def.h index 8c1dcd0..4d3b003 100644 --- a/arch/blackfin/include/asm/mach-bf609/BF609_def.h +++ b/arch/blackfin/include/asm/mach-bf609/BF609_def.h @@ -244,4 +244,6 @@ #define L1_INST_SRAM_SIZE 0x8000 #define L1_INST_SRAM_END (L1_INST_SRAM + L1_INST_SRAM_SIZE) +#define COREB_L1_CODE_START 0xFF600000 + #endif /* __BFIN_DEF_ADSP_BF609_proc__ */ diff --git a/include/configs/bf561-ezkit.h b/include/configs/bf561-ezkit.h index 1a9d27e..6ee1e4c 100644 --- a/include/configs/bf561-ezkit.h +++ b/include/configs/bf561-ezkit.h @@ -98,6 +98,11 @@ */ #define CONFIG_UART_CONSOLE 0 +/* + * Run core 1 from L1 SRAM start address when init uboot on core 0 + */ +/* #define CONFIG_CORE1_RUN 1 */ + /* * Pull in common ADI header for remaining command/environment setup diff --git a/include/configs/bf609-ezkit.h b/include/configs/bf609-ezkit.h index 02149fa..8b90129 100644 --- a/include/configs/bf609-ezkit.h +++ b/include/configs/bf609-ezkit.h @@ -156,6 +156,11 @@ #endif /* + * Run core 1 from L1 SRAM start address when init uboot on core 0 + */ +/* #define CONFIG_CORE1_RUN 1 */ + +/* * Pull in common ADI header for remaining command/environment setup */ #include -- cgit v0.10.2 From 79f2b3992f52334b510214c6b1b60c4200133658 Mon Sep 17 00:00:00 2001 From: Sonic Zhang Date: Tue, 5 Feb 2013 19:10:34 +0800 Subject: blackfin: Set correct early debug serial baudrate. Calculate the early uart clock from the system clock registers set by the bootrom other than the predefine uboot clock macros. Split the early baudrate setting function and the normal baudrate setting one. Signed-off-by: Sonic Zhang diff --git a/arch/blackfin/cpu/initcode.c b/arch/blackfin/cpu/initcode.c index e8ea0ba..5c12726 100644 --- a/arch/blackfin/cpu/initcode.c +++ b/arch/blackfin/cpu/initcode.c @@ -194,15 +194,8 @@ static inline void serial_init(void) #endif if (BFIN_DEBUG_EARLY_SERIAL) { - int enabled = serial_early_enabled(uart_base); - serial_early_init(uart_base); - - /* If the UART is off, that means we need to program - * the baud rate ourselves initially. - */ - if (!enabled) - serial_early_set_baud(uart_base, CONFIG_BAUDRATE); + serial_early_set_baud(uart_base, CONFIG_BAUDRATE); } } @@ -714,37 +707,29 @@ program_clocks(ADI_BOOT_DATA *bs, bool put_into_srfs) __attribute__((always_inline)) static inline void update_serial_clocks(ADI_BOOT_DATA *bs, uint sdivB, uint divB, uint vcoB) { - serial_putc('a'); - /* Since we've changed the SCLK above, we may need to update * the UART divisors (UART baud rates are based on SCLK). * Do the division by hand as there are no native instructions * for dividing which means we'd generate a libgcc reference. */ - if (CONFIG_BFIN_BOOT_MODE == BFIN_BOOT_UART) { - unsigned int sdivR, vcoR; - int dividend = sdivB * divB * vcoR; - int divisor = vcoB * sdivR; - unsigned int quotient; + unsigned int sdivR, vcoR; + unsigned int dividend = sdivB * divB * vcoR; + unsigned int divisor = vcoB * sdivR; + unsigned int quotient; - serial_putc('b'); + serial_putc('a'); #ifdef __ADSPBF60x__ - sdivR = bfin_read_CGU_DIV(); - sdivR = ((sdivR >> 8) & 0x1f) * ((sdivR >> 5) & 0x7); - vcoR = (bfin_read_CGU_CTL() >> 8) & 0x7f; + sdivR = bfin_read_CGU_DIV(); + sdivR = ((sdivR >> 8) & 0x1f) * ((sdivR >> 5) & 0x7); + vcoR = (bfin_read_CGU_CTL() >> 8) & 0x7f; #else - sdivR = bfin_read_PLL_DIV() & 0xf; - vcoR = (bfin_read_PLL_CTL() >> 9) & 0x3f; + sdivR = bfin_read_PLL_DIV() & 0xf; + vcoR = (bfin_read_PLL_CTL() >> 9) & 0x3f; #endif - - for (quotient = 0; dividend > 0; ++quotient) - dividend -= divisor; - serial_early_put_div(quotient - ANOMALY_05000230); - serial_putc('c'); - } - - serial_putc('d'); + quotient = early_division(dividend, divisor); + serial_early_put_div(quotient - ANOMALY_05000230); + serial_putc('c'); } __attribute__((always_inline)) static inline void diff --git a/arch/blackfin/cpu/serial.c b/arch/blackfin/cpu/serial.c index 9847e9f..36d2a5c 100644 --- a/arch/blackfin/cpu/serial.c +++ b/arch/blackfin/cpu/serial.c @@ -195,6 +195,14 @@ static void uart_loop(uint32_t uart_base, int state) #endif +static inline void __serial_set_baud(uint32_t uart_base, uint32_t baud) +{ + uint16_t divisor = (get_uart_clk() + (baud * 8)) / (baud * 16) + - ANOMALY_05000230; + + /* Program the divisor to get the baud rate we want */ + serial_set_divisor(uart_base, divisor); +} #ifdef CONFIG_SYS_BFIN_UART static void uart_puts(uint32_t uart_base, const char *s) @@ -209,7 +217,7 @@ static int uart##n##_init(void) \ const unsigned short pins[] = { _P_UART(n, RX), _P_UART(n, TX), 0, }; \ peripheral_request_list(pins, "bfin-uart"); \ uart_init(MMR_UART(n)); \ - serial_early_set_baud(MMR_UART(n), gd->baudrate); \ + __serial_set_baud(MMR_UART(n), gd->baudrate); \ uart_lsr_clear(MMR_UART(n)); \ return 0; \ } \ @@ -221,7 +229,7 @@ static int uart##n##_uninit(void) \ \ static void uart##n##_setbrg(void) \ { \ - serial_early_set_baud(MMR_UART(n), gd->baudrate); \ + __serial_set_baud(MMR_UART(n), gd->baudrate); \ } \ \ static int uart##n##_getc(void) \ diff --git a/arch/blackfin/cpu/serial1.h b/arch/blackfin/cpu/serial1.h index a20175b..52f1c62 100644 --- a/arch/blackfin/cpu/serial1.h +++ b/arch/blackfin/cpu/serial1.h @@ -15,6 +15,8 @@ #ifndef __ASSEMBLY__ +#include + #define MMR_UART(n) _PASTE_UART(n, UART, DLL) #ifdef UART_DLL # define UART0_DLL UART_DLL @@ -230,19 +232,6 @@ static inline void serial_early_do_portmux(void) } __attribute__((always_inline)) -static inline uint32_t uart_sclk(void) -{ -#if defined(BFIN_IN_INITCODE) || defined(CONFIG_DEBUG_EARLY_SERIAL) - /* We cannot use get_sclk() early on as it uses - * caches in external memory - */ - return CONFIG_CLKIN_HZ * CONFIG_VCO_MULT / CONFIG_SCLK_DIV; -#else - return get_sclk(); -#endif -} - -__attribute__((always_inline)) static inline int uart_init(uint32_t uart_base) { /* always enable UART -- avoids anomalies 05000309 and 05000350 */ @@ -275,21 +264,8 @@ static inline int serial_early_uninit(uint32_t uart_base) } __attribute__((always_inline)) -static inline int serial_early_enabled(uint32_t uart_base) +static inline void serial_set_divisor(uint32_t uart_base, uint16_t divisor) { - return bfin_read(&pUART->gctl) & UCEN; -} - -__attribute__((always_inline)) -static inline void serial_early_set_baud(uint32_t uart_base, uint32_t baud) -{ - /* 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 = (uart_sclk() + (baud * 8)) / (baud * 16) - - ANOMALY_05000230; - /* Set DLAB in LCR to Access DLL and DLH */ ACCESS_LATCH(); SSYNC(); @@ -305,6 +281,19 @@ static inline void serial_early_set_baud(uint32_t uart_base, uint32_t baud) } __attribute__((always_inline)) +static inline void serial_early_set_baud(uint32_t uart_base, uint32_t baud) +{ + /* 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 = early_division(early_get_uart_clk() + (baud * 8), + baud * 16) - ANOMALY_05000230; + + serial_set_divisor(uart_base, divisor); +} + +__attribute__((always_inline)) static inline void serial_early_put_div(uint16_t divisor) { uint32_t uart_base = UART_BASE; diff --git a/arch/blackfin/cpu/serial4.h b/arch/blackfin/cpu/serial4.h index 887845c..6548396 100644 --- a/arch/blackfin/cpu/serial4.h +++ b/arch/blackfin/cpu/serial4.h @@ -15,6 +15,8 @@ #ifndef __ASSEMBLY__ +#include + #define MMR_UART(n) _PASTE_UART(n, UART, REVID) #define UART_BASE MMR_UART(CONFIG_UART_CONSOLE) @@ -84,20 +86,6 @@ static inline void serial_early_do_portmux(void) } __attribute__((always_inline)) -static inline uint32_t uart_sclk(void) -{ -#if defined(BFIN_IN_INITCODE) || defined(CONFIG_DEBUG_EARLY_SERIAL) - /* We cannot use get_sclk() early on as it uses caches in - * external memory - */ - return CONFIG_CLKIN_HZ * CONFIG_VCO_MULT / CONFIG_SCLK_DIV / - CONFIG_SCLK0_DIV; -#else - return get_sclk0(); -#endif -} - -__attribute__((always_inline)) static inline int uart_init(uint32_t uart_base) { /* always enable UART to 8-bit mode */ @@ -127,19 +115,20 @@ static inline int serial_early_uninit(uint32_t uart_base) } __attribute__((always_inline)) -static inline int serial_early_enabled(uint32_t uart_base) +static inline void serial_set_divisor(uint32_t uart_base, uint16_t divisor) { - return bfin_read(&pUART->control) & UEN; + /* Program the divisor to get the baud rate we want */ + bfin_write(&pUART->clock, divisor); + SSYNC(); } __attribute__((always_inline)) static inline void serial_early_set_baud(uint32_t uart_base, uint32_t baud) { - uint32_t divisor = uart_sclk() / (baud * 16); + uint16_t divisor = early_division(early_get_uart_clk(), baud * 16); /* Program the divisor to get the baud rate we want */ - bfin_write(&pUART->clock, divisor); - SSYNC(); + serial_set_divisor(uart_base, divisor); } __attribute__((always_inline)) diff --git a/arch/blackfin/include/asm/clock.h b/arch/blackfin/include/asm/clock.h new file mode 100644 index 0000000..df6cd68 --- /dev/null +++ b/arch/blackfin/include/asm/clock.h @@ -0,0 +1,74 @@ + +/* + * Copyright (C) 2012 Analog Devices Inc. + * Licensed under the GPL-2 or later. + */ + +#ifndef __CLOCK_H__ +#define __CLOCK_H__ + +#include +#ifdef PLL_CTL +#include +# define pll_is_bypassed() (bfin_read_PLL_STAT() & DF) +#else +#include +# define pll_is_bypassed() (bfin_read_CGU_STAT() & PLLBP) +# define bfin_read_PLL_CTL() bfin_read_CGU_CTL() +# define bfin_read_PLL_DIV() bfin_read_CGU_DIV() +# define SSEL SYSSEL +# define SSEL_P SYSSEL_P +#endif + +__attribute__((always_inline)) +static inline uint32_t early_division(uint32_t dividend, uint32_t divisor) +{ + uint32_t quotient; + uint32_t i, j; + + for (quotient = 1, i = 1; dividend > divisor; ++i) { + j = divisor << i; + if (j > dividend || (j & 0x80000000)) { + --i; + quotient += (1 << i); + dividend -= (divisor << i); + i = 0; + } + } + + return quotient; +} + +__attribute__((always_inline)) +static inline uint32_t early_get_uart_clk(void) +{ + uint32_t msel, pll_ctl, vco; + uint32_t div, ssel, sclk, uclk; + + pll_ctl = bfin_read_PLL_CTL(); + msel = (pll_ctl & MSEL) >> MSEL_P; + if (msel == 0) + msel = (MSEL >> MSEL_P) + 1; + + vco = (CONFIG_CLKIN_HZ >> (pll_ctl & DF)) * msel; + sclk = vco; + if (!pll_is_bypassed()) { + div = bfin_read_PLL_DIV(); + ssel = (div & SSEL) >> SSEL_P; + sclk = early_division(vco, ssel); + } + uclk = sclk; +#ifdef CGU_DIV + ssel = (div & S0SEL) >> S0SEL_P; + uclk = early_division(sclk, ssel); +#endif + return uclk; +} + +#ifdef CGU_DIV +# define get_uart_clk get_sclk0 +#else +# define get_uart_clk get_sclk +#endif + +#endif diff --git a/arch/blackfin/lib/clocks.c b/arch/blackfin/lib/clocks.c index d852f5e..97795e1 100644 --- a/arch/blackfin/lib/clocks.c +++ b/arch/blackfin/lib/clocks.c @@ -7,17 +7,7 @@ */ #include -#include - -#ifdef PLL_CTL -# include -# define pll_is_bypassed() (bfin_read_PLL_STAT() & DF) -#else -# include -# define pll_is_bypassed() (bfin_read_CGU_STAT() & PLLBP) -# define bfin_read_PLL_CTL() bfin_read_CGU_CTL() -# define bfin_read_PLL_DIV() bfin_read_CGU_DIV() -#endif +#include /* Get the voltage input multiplier */ u_long get_vco(void) -- cgit v0.10.2 From ab80b6595765a01f774ad2a29fde8b0c325533ac Mon Sep 17 00:00:00 2001 From: Sonic Zhang Date: Fri, 30 Nov 2012 17:39:32 +0800 Subject: blackfin: Correct early serial mess output in BYPASS boot mode. The early serial should not be configured again in initcode() for BYPASS boot mode and in start() for the other LDR boot modes. In BYPASS boot mode, the start up code is located in Nor flash address other than the DRAM address defined in link script. The code embedded string can't be addressed by its compile time symbol. Calculate it according to the flash offset. Signed-off-by: Sonic Zhang diff --git a/arch/blackfin/cpu/initcode.c b/arch/blackfin/cpu/initcode.c index 5c12726..4b10b6c 100644 --- a/arch/blackfin/cpu/initcode.c +++ b/arch/blackfin/cpu/initcode.c @@ -193,10 +193,12 @@ static inline void serial_init(void) } #endif +#if CONFIG_BFIN_BOOT_MODE != BFIN_BOOT_BYPASS if (BFIN_DEBUG_EARLY_SERIAL) { serial_early_init(uart_base); serial_early_set_baud(uart_base, CONFIG_BAUDRATE); } +#endif } __attribute__((always_inline)) diff --git a/arch/blackfin/cpu/serial.h b/arch/blackfin/cpu/serial.h index 9200339..d67fd81 100644 --- a/arch/blackfin/cpu/serial.h +++ b/arch/blackfin/cpu/serial.h @@ -78,19 +78,31 @@ static inline void serial_early_puts(const char *s) #else .macro serial_early_init -#ifdef CONFIG_DEBUG_EARLY_SERIAL +#if defined(CONFIG_DEBUG_EARLY_SERIAL) && defined(BFIN_BOOT_BYPASS) call _serial_initialize; #endif .endm .macro serial_early_set_baud -#ifdef CONFIG_DEBUG_EARLY_SERIAL +#if defined(CONFIG_DEBUG_EARLY_SERIAL) && defined(BFIN_BOOT_BYPASS) R0.L = LO(CONFIG_BAUDRATE); R0.H = HI(CONFIG_BAUDRATE); call _serial_set_baud; #endif .endm +#if CONFIG_BFIN_BOOT_MODE == BFIN_BOOT_BYPASS +#define update_serial_early_string_addr \ + R1.L = _start; \ + R1.H = _start; \ + R0 = R0 - R1; \ + R1.L = 0; \ + R1.H = 0x2000; \ + R0 = R0 + R1; +#else +#define update_serial_early_string_addr +#endif + /* Since we embed the string right into our .text section, we need * to find its address. We do this by getting our PC and adding 2 * bytes (which is the length of the jump instruction). Then we @@ -108,6 +120,7 @@ static inline void serial_early_puts(const char *s) .previous; \ R0.L = 7b; \ R0.H = 7b; \ + update_serial_early_string_addr \ call _serial_puts; #else # define serial_early_puts(str) diff --git a/arch/blackfin/cpu/serial1.h b/arch/blackfin/cpu/serial1.h index 52f1c62..467d381 100644 --- a/arch/blackfin/cpu/serial1.h +++ b/arch/blackfin/cpu/serial1.h @@ -287,8 +287,13 @@ static inline void serial_early_set_baud(uint32_t uart_base, uint32_t baud) * weird multiplication is to make sure we over sample just * a little rather than under sample the incoming signals. */ +#if CONFIG_BFIN_BOOT_MODE == BFIN_BOOT_BYPASS + uint16_t divisor = (early_get_uart_clk() + baud * 8) / (baud * 16) + - ANOMALY_05000230; +#else uint16_t divisor = early_division(early_get_uart_clk() + (baud * 8), baud * 16) - ANOMALY_05000230; +#endif serial_set_divisor(uart_base, divisor); } diff --git a/arch/blackfin/include/asm/clock.h b/arch/blackfin/include/asm/clock.h index df6cd68..f1fcd40 100644 --- a/arch/blackfin/include/asm/clock.h +++ b/arch/blackfin/include/asm/clock.h @@ -10,7 +10,7 @@ #include #ifdef PLL_CTL #include -# define pll_is_bypassed() (bfin_read_PLL_STAT() & DF) +# define pll_is_bypassed() (bfin_read_PLL_CTL() & BYPASS) #else #include # define pll_is_bypassed() (bfin_read_CGU_STAT() & PLLBP) @@ -55,7 +55,11 @@ static inline uint32_t early_get_uart_clk(void) if (!pll_is_bypassed()) { div = bfin_read_PLL_DIV(); ssel = (div & SSEL) >> SSEL_P; +#if CONFIG_BFIN_BOOT_MODE == BFIN_BOOT_BYPASS + sclk = vco/ssel; +#else sclk = early_division(vco, ssel); +#endif } uclk = sclk; #ifdef CGU_DIV -- cgit v0.10.2 From e7b9aa96b15c589ba0e5236be9bbadd69c8bcace Mon Sep 17 00:00:00 2001 From: Sonic Zhang Date: Tue, 29 Nov 2011 15:05:35 +0800 Subject: blackfin: bf609: implement soft switch Set up soft switch pins properly in board init code. Signed-off-by: Sonic Zhang Signed-off-by: Scott Jiang Signed-off-by: Bob Liu diff --git a/board/bf609-ezkit/soft_switch.c b/board/bf609-ezkit/soft_switch.c new file mode 100644 index 0000000..2e1404f --- /dev/null +++ b/board/bf609-ezkit/soft_switch.c @@ -0,0 +1,180 @@ +/* + * U-boot - main board file + * + * Copyright (c) 2008-2011 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + +#include +#include +#include +#include +#include "soft_switch.h" + +#define SWITCH_ADDR 0x21 + +#define NUM_SWITCH 3 +#define IODIRA 0x0 +#define IODIRB 0x1 +#define OLATA 0x14 +#define OLATB 0x15 + +struct switch_config { + uchar dir0; /* IODIRA */ + uchar dir1; /* IODIRB */ + uchar value0; /* OLATA */ + uchar value1; /* OLATB */ +}; + +static struct switch_config switch_config_array[NUM_SWITCH] = { + { +/* + U45 Port A U45 Port B + + 7--------------- RMII_CLK_EN | 7--------------- ~TEMP_THERM_EN + | 6------------- ~CNT0ZM_EN | | 6------------- ~TEMP_IRQ_EN + | | 5----------- ~CNT0DG_EN | | | 5----------- ~UART0CTS_146_EN + | | | 4--------- ~CNT0UD_EN | | | | 4--------- ~UART0CTS_RST_EN + | | | | 3------- ~CAN0RX_EN | | | | | 3------- ~UART0CTS_RTS_LPBK + | | | | | 2----- ~CAN0_ERR_EN | | | | | | 2----- ~UART0CTS_EN + | | | | | | 1--- ~CAN_STB | | | | | | | 1--- ~UART0RX_EN + | | | | | | | 0- CAN_EN | | | | | | | | 0- ~UART0RTS_EN + | | | | | | | | | | | | | | | | | + O O O O O O O O | O O O O O O O O (I/O direction) + 1 0 0 0 0 0 1 1 | 1 1 1 1 1 0 0 0 (value being set) +*/ + .dir0 = 0x0, /* all output */ + .dir1 = 0x0, /* all output */ + .value0 = RMII_CLK_EN | CAN_STB | CAN_EN, + .value1 = TEMP_THERM_EN | TEMP_IRQ_EN | UART0CTS_146_EN + | UART0CTS_RST_EN | UART0CTS_RTS_LPBK, + }, + { +/* + U46 Port A U46 Port B + + 7--------------- ~LED4_GPIO_EN | 7--------------- EMPTY + | 6------------- ~LED3_GPIO_EN | | 6------------- ~SPI0D3_EN + | | 5----------- ~LED2_GPIO_EN | | | 5----------- ~SPI0D2_EN + | | | 4--------- ~LED1_GPIO_EN | | | | 4--------- ~SPIFLASH_CS_EN + | | | | 3------- SMC0_LP0_EN | | | | | 3------- ~SD_WP_EN + | | | | | 2----- EMPTY | | | | | | 2----- ~SD_CD_EN + | | | | | | 1--- SMC0_EPPI2 | | | | | | | 1--- ~PUSHBUTTON2_EN + _LP1_SWITCH + | | | | | | | 0- OVERRIDE_SMC0 | | | | | | | | 0- ~PUSHBUTTON1_EN + _LP0_BOOT + | | | | | | | | | | | | | | | | | + O O O O O O O O | O O O O O O O O (I/O direction) + 0 0 0 0 0 X 0 1 | X 0 0 0 0 0 0 0 (value being set) +*/ + .dir0 = 0x0, /* all output */ + .dir1 = 0x0, /* all output */ +#ifdef CONFIG_BFIN_LINKPORT + .value0 = OVERRIDE_SMC0_LP0_BOOT, +#else + .value0 = SMC0_EPPI2_LP1_SWITCH, +#endif + .value1 = 0x0, + }, + { +/* + U47 Port A U47 Port B + + 7--------------- ~PD2_SPI0MISO | 7--------------- EMPTY + _EI3_EN + | 6------------- ~PD1_SPI0D3 | | 6------------- EMPTY + _EPPI1D17 + _SPI0SEL2 + _EI3_EN + | | 5----------- ~PD0_SPI0D2 | | | 5----------- EMPTY + _EPPI1D16 + _SPI0SEL3 + _EI3_EN + | | | 4--------- ~WAKE_PUSH | | | | 4--------- EMPTY + BUTTON_EN + | | | | 3------- ~ETHERNET_EN | | | | | 3------- EMPTY + | | | | | 2----- PHYAD0 | | | | | | 2----- EMPTY + | | | | | | 1--- PHY_PWR | | | | | | | 1--- ~PD4_SPI0CK_EI3_EN + _DWN_INT + | | | | | | | 0- ~PHYINT_EN | | | | | | | | 0- ~PD3_SPI0MOSI_EI3_EN + | | | | | | | | | | | | | | | | | + O O O O O I I O | O O O O O O O O (I/O direction) + 1 1 1 0 0 0 0 0 | X X X X X X 1 1 (value being set) +*/ + .dir0 = 0x6, /* bits 1 and 2 input, all others output */ + .dir1 = 0x0, /* all output */ + .value0 = PD1_SPI0D3_EN | PD0_SPI0D2_EN, + .value1 = 0, + }, +}; + +static int setup_soft_switch(int addr, struct switch_config *config) +{ + int ret = 0; + + ret = i2c_write(addr, OLATA, 1, &config->value0, 1); + if (ret) + return ret; + ret = i2c_write(addr, OLATB, 1, &config->value1, 1); + if (ret) + return ret; + + ret = i2c_write(addr, IODIRA, 1, &config->dir0, 1); + if (ret) + return ret; + return i2c_write(addr, IODIRB, 1, &config->dir1, 1); +} + +int config_switch_bit(int num, int port, int bit, int dir, uchar value) +{ + int addr = SWITCH_ADDR + num; + int ret, data_reg, dir_reg; + uchar tmp; + + if (port == IO_PORT_A) { + data_reg = OLATA; + dir_reg = IODIRA; + } else { + data_reg = OLATB; + dir_reg = IODIRB; + } + + if (dir == IO_PORT_INPUT) { + ret = i2c_read(addr, dir_reg, 1, &tmp, 1); + if (ret) + return ret; + tmp |= bit; + return i2c_write(addr, dir_reg, 1, &tmp, 1); + } else { + ret = i2c_read(addr, data_reg, 1, &tmp, 1); + if (ret) + return ret; + if (value) + tmp |= bit; + else + tmp &= ~bit; + ret = i2c_write(addr, data_reg, 1, &tmp, 1); + if (ret) + return ret; + ret = i2c_read(addr, dir_reg, 1, &tmp, 1); + if (ret) + return ret; + tmp &= ~bit; + return i2c_write(addr, dir_reg, 1, &tmp, 1); + } +} + +int setup_board_switches(void) +{ + int ret; + int i; + + for (i = 0; i < NUM_SWITCH; i++) { + ret = setup_soft_switch(SWITCH_ADDR + i, + &switch_config_array[i]); + if (ret) + return ret; + } + return 0; +} diff --git a/board/bf609-ezkit/soft_switch.h b/board/bf609-ezkit/soft_switch.h new file mode 100644 index 0000000..8da0e44 --- /dev/null +++ b/board/bf609-ezkit/soft_switch.h @@ -0,0 +1,71 @@ +/* + * U-boot - main board file + * + * Copyright (c) 2008-2011 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + +#ifndef __SOFT_SWITCH_H__ +#define __SOFT_SWITCH_H__ + +/* switch 0 port A */ +#define CAN_EN 0x1 +#define CAN_STB 0x2 +#define CAN0_ERR_EN 0x4 +#define CAN0RX_EN 0x8 +#define CNT0UD_EN 0x10 +#define CNT0DG_EN 0x20 +#define CNT0ZM_EN 0x40 +#define RMII_CLK_EN 0x80 + +/* switch 0 port B */ +#define UART0RTS_EN 0x1 +#define UART0RX_EN 0x2 +#define UART0CTS_EN 0x4 +#define UART0CTS_RTS_LPBK 0x8 +#define UART0CTS_RST_EN 0x10 +#define UART0CTS_146_EN 0x20 +#define TEMP_IRQ_EN 0x40 +#define TEMP_THERM_EN 0x80 + +/* switch 1 port A */ +#define OVERRIDE_SMC0_LP0_BOOT 0x1 +#define SMC0_EPPI2_LP1_SWITCH 0x2 +#define SMC0_LP0_EN 0x8 +#define LED1_GPIO_EN 0x10 +#define LED2_GPIO_EN 0x20 +#define LED3_GPIO_EN 0x40 +#define LED4_GPIO_EN 0x80 + +/* switch 1 port B */ +#define PUSHBUTTON1_EN 0x1 +#define PUSHBUTTON2_EN 0x2 +#define SD_CD_EN 0x4 +#define SD_WP_EN 0x8 +#define SPIFLASH_CS_EN 0x10 +#define SPI0D2_EN 0x20 +#define SPI0D3_EN 0x40 + +/* switch 2 port A */ +#define PHYINT_EN 0x1 +#define PHY_PWR_DWN_INT 0x2 +#define PHYAD0 0x4 +#define ETHERNET_EN 0x8 +#define WAKE_PUSHBUTTON_EN 0x10 +#define PD0_SPI0D2_EN 0x20 +#define PD1_SPI0D3_EN 0x40 +#define PD2_SPI0MISO_EN 0x80 + +/* switch 2 port B */ +#define PD3_SPI0MOSI_EN 0x1 +#define PD4_SPI0CK_EN 0x2 + +#define IO_PORT_A 0 +#define IO_PORT_B 1 +#define IO_PORT_INPUT 0 +#define IO_PORT_OUTPUT 1 + +int config_switch_bit(int num, int port, int bit, int dir, uchar value); +int setup_board_switches(void); +#endif -- cgit v0.10.2 From 7d861d95a315852532d581884b3b72536c25032c Mon Sep 17 00:00:00 2001 From: Bob Liu Date: Tue, 5 Feb 2013 19:05:41 +0800 Subject: blackfin: bf609: add softswitch config command Add softswitch_output command for bf609-ezkit to enable softswitches. Signed-off-by: Bob Liu Signed-off-by: Sonic Zhang diff --git a/README b/README index 0d37d56..defdedb 100644 --- a/README +++ b/README @@ -898,6 +898,7 @@ The following options need to be configured: CONFIG_CMD_SF * Read/write/erase SPI NOR flash CONFIG_CMD_SHA1SUM print sha1 memory digest (requires CONFIG_CMD_MEMORY) + CONFIG_CMD_SOFTSWITCH * Soft switch setting command for BF60x CONFIG_CMD_SOURCE "source" command Support CONFIG_CMD_SPI * SPI serial bus support CONFIG_CMD_TFTPSRV * TFTP transfer in server mode diff --git a/arch/blackfin/include/asm/soft_switch.h b/arch/blackfin/include/asm/soft_switch.h new file mode 100644 index 0000000..ff8e44d --- /dev/null +++ b/arch/blackfin/include/asm/soft_switch.h @@ -0,0 +1,18 @@ +/* + * U-boot - main board file + * + * Copyright (c) 2008-2012 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + +#ifndef __SOFT_SWITCH_H__ +#define __SOFT_SWITCH_H__ + +#define IO_PORT_A 0 +#define IO_PORT_B 1 +#define IO_PORT_INPUT 0 +#define IO_PORT_OUTPUT 1 + +int config_switch_bit(int num, int port, int bit, int dir, uchar value); +#endif diff --git a/board/bf609-ezkit/soft_switch.c b/board/bf609-ezkit/soft_switch.c index 2e1404f..e0c8d93 100644 --- a/board/bf609-ezkit/soft_switch.c +++ b/board/bf609-ezkit/soft_switch.c @@ -12,14 +12,6 @@ #include #include "soft_switch.h" -#define SWITCH_ADDR 0x21 - -#define NUM_SWITCH 3 -#define IODIRA 0x0 -#define IODIRB 0x1 -#define OLATA 0x14 -#define OLATB 0x15 - struct switch_config { uchar dir0; /* IODIRA */ uchar dir1; /* IODIRB */ @@ -126,9 +118,8 @@ static int setup_soft_switch(int addr, struct switch_config *config) return i2c_write(addr, IODIRB, 1, &config->dir1, 1); } -int config_switch_bit(int num, int port, int bit, int dir, uchar value) +int config_switch_bit(int addr, int port, int bit, int dir, uchar value) { - int addr = SWITCH_ADDR + num; int ret, data_reg, dir_reg; uchar tmp; diff --git a/board/bf609-ezkit/soft_switch.h b/board/bf609-ezkit/soft_switch.h index 8da0e44..d147fe1 100644 --- a/board/bf609-ezkit/soft_switch.h +++ b/board/bf609-ezkit/soft_switch.h @@ -6,8 +6,10 @@ * Licensed under the GPL-2 or later. */ -#ifndef __SOFT_SWITCH_H__ -#define __SOFT_SWITCH_H__ +#ifndef __BOARD_SOFT_SWITCH_H__ +#define __BOARD_SOFT_SWITCH_H__ + +#include /* switch 0 port A */ #define CAN_EN 0x1 @@ -61,11 +63,18 @@ #define PD3_SPI0MOSI_EN 0x1 #define PD4_SPI0CK_EN 0x2 -#define IO_PORT_A 0 -#define IO_PORT_B 1 -#define IO_PORT_INPUT 0 -#define IO_PORT_OUTPUT 1 +#ifdef CONFIG_BFIN_BOARD_VERSION_1_0 +#define SWITCH_ADDR 0x21 +#else +#define SWITCH_ADDR 0x20 +#endif + +#define NUM_SWITCH 3 +#define IODIRA 0x0 +#define IODIRB 0x1 +#define OLATA 0x14 +#define OLATB 0x15 -int config_switch_bit(int num, int port, int bit, int dir, uchar value); int setup_board_switches(void); -#endif + +#endif /* __BOARD_SOFT_SWITCH_H__ */ diff --git a/common/Makefile b/common/Makefile index 0e0fff1..0429a3c 100644 --- a/common/Makefile +++ b/common/Makefile @@ -164,6 +164,7 @@ COBJS-$(CONFIG_CMD_SF) += cmd_sf.o COBJS-$(CONFIG_CMD_SCSI) += cmd_scsi.o COBJS-$(CONFIG_CMD_SHA1SUM) += cmd_sha1sum.o COBJS-$(CONFIG_CMD_SETEXPR) += cmd_setexpr.o +COBJS-$(CONFIG_CMD_SOFTSWITCH) += cmd_softswitch.o COBJS-$(CONFIG_CMD_SPI) += cmd_spi.o COBJS-$(CONFIG_CMD_SPIBOOTLDR) += cmd_spibootldr.o COBJS-$(CONFIG_CMD_STRINGS) += cmd_strings.o diff --git a/common/cmd_softswitch.c b/common/cmd_softswitch.c new file mode 100644 index 0000000..f75d926 --- /dev/null +++ b/common/cmd_softswitch.c @@ -0,0 +1,41 @@ +/* + * cmd_softswitch.c - set the softswitch for bf60x + * + * Copyright (c) 2012 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + +#include +#include +#include +#include + +int do_softswitch(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + int switchaddr, value, pin, port; + + if (argc != 5) + return CMD_RET_USAGE; + + if (strcmp(argv[2], "GPA") == 0) + port = IO_PORT_A; + else if (strcmp(argv[2], "GPB") == 0) + port = IO_PORT_B; + else + return CMD_RET_USAGE; + + switchaddr = simple_strtoul(argv[1], NULL, 16); + pin = simple_strtoul(argv[3], NULL, 16); + value = simple_strtoul(argv[4], NULL, 16); + + config_switch_bit(switchaddr, port, (1 << pin), IO_PORT_OUTPUT, value); + + return 0; +} + +U_BOOT_CMD( + softswitch_output, 5, 1, do_softswitch, + "switchaddr GPA/GPB pin_offset value", + "" +); diff --git a/include/configs/bf609-ezkit.h b/include/configs/bf609-ezkit.h index 8b90129..f0ac86b 100644 --- a/include/configs/bf609-ezkit.h +++ b/include/configs/bf609-ezkit.h @@ -144,6 +144,7 @@ #define CONFIG_UART_CONSOLE 0 #define CONFIG_CMD_MEMORY +#define CONFIG_CMD_SOFTSWITCH #define CONFIG_SYS_MEMTEST_END (CONFIG_STACKBASE - 20*1024*1024 + 4) #define CONFIG_BFIN_SOFT_SWITCH -- cgit v0.10.2 From 955020c6c4e656cb4cc1d0b434ed02bcbb6e9dae Mon Sep 17 00:00:00 2001 From: Sonic Zhang Date: Wed, 20 Feb 2013 18:05:16 +0800 Subject: blackfin: Fit u-boot image size into limited nor flash on blackfin. - Disable NAND driver on bf537-stamp. - Make MMC_SPI optional. - Disable LCD driver on bf527-ezkit. - Enlarge BF609 nor flash reserved size from 256k to 512k bytes. Signed-off-by: Sonic Zhang Signed-off-by: Sonic Zhang diff --git a/include/configs/bf527-ezkit.h b/include/configs/bf527-ezkit.h index 7b51b53..db1b613 100644 --- a/include/configs/bf527-ezkit.h +++ b/include/configs/bf527-ezkit.h @@ -149,10 +149,15 @@ #define CONFIG_MUSB_TIMEOUT 100000 #endif +/* Don't waste time transferring a logo over the UART */ +#if (CONFIG_BFIN_BOOT_MODE != BFIN_BOOT_UART) +/*# define CONFIG_VIDEO*/ +#endif /* * Video Settings */ +#ifdef CONFIG_VIDEO #ifdef CONFIG_BF527_EZKIT_REV_2_1 # define CONFIG_LQ035Q1_SPI_BUS 0 # define CONFIG_LQ035Q1_SPI_CS 7 @@ -166,7 +171,7 @@ #else # define EASYLOGO_HEADER #endif - +#endif /* CONFIG_VIDEO */ /* * Misc Settings @@ -175,11 +180,6 @@ #define CONFIG_RTC_BFIN #define CONFIG_UART_CONSOLE 1 -/* Don't waste time transferring a logo over the UART */ -#if (CONFIG_BFIN_BOOT_MODE != BFIN_BOOT_UART) -# define CONFIG_VIDEO -#endif - /* * Pull in common ADI header for remaining command/environment setup diff --git a/include/configs/bf537-stamp.h b/include/configs/bf537-stamp.h index 05029d4..25cebf8 100644 --- a/include/configs/bf537-stamp.h +++ b/include/configs/bf537-stamp.h @@ -52,7 +52,7 @@ #define CONFIG_EBIU_AMBCTL0_VAL 0x7BB07BB0 #define CONFIG_EBIU_AMBCTL1_VAL 0xFFC27BB0 -#define CONFIG_SYS_MONITOR_LEN (512 * 1024) +#define CONFIG_SYS_MONITOR_LEN (768 * 1024) #define CONFIG_SYS_MALLOC_LEN (384 * 1024) @@ -135,15 +135,17 @@ /* * SPI_MMC Settings */ +#define CONFIG_MMC_SPI +#ifdef CONFIG_MMC_SPI #define CONFIG_MMC #define CONFIG_GENERIC_MMC -#define CONFIG_MMC_SPI - +#endif /* * NAND Settings */ /* #define CONFIG_NAND_PLAT */ +#ifdef CONFIG_NAND_PLAT #define CONFIG_SYS_NAND_BASE 0x20212000 #define CONFIG_SYS_MAX_NAND_DEVICE 1 @@ -158,7 +160,7 @@ #define NAND_PLAT_WRITE_CMD(chip, cmd) BFIN_NAND_WRITE(BFIN_NAND_CLE(chip), cmd) #define NAND_PLAT_WRITE_ADR(chip, cmd) BFIN_NAND_WRITE(BFIN_NAND_ALE(chip), cmd) #define NAND_PLAT_GPIO_DEV_READY GPIO_PF3 - +#endif /* CONFIG_NAND_PLAT */ /* * CF-CARD IDE-HDD Support diff --git a/include/configs/bf609-ezkit.h b/include/configs/bf609-ezkit.h index f0ac86b..e7b02a5 100644 --- a/include/configs/bf609-ezkit.h +++ b/include/configs/bf609-ezkit.h @@ -156,6 +156,8 @@ #undef CONFIG_UART_CONSOLE_IS_JTAG #endif +#define CONFIG_BOARD_SIZE_LIMIT $$((512 * 1024)) + /* * Run core 1 from L1 SRAM start address when init uboot on core 0 */ -- cgit v0.10.2 From e76276df74f60eeb3c28418971bbe8cd6fc736e5 Mon Sep 17 00:00:00 2001 From: Scott Jiang Date: Wed, 7 Dec 2011 14:19:55 -0500 Subject: bfin: Remove spi dma function in bf5xx. BF5xx rx dma causes spi flash random read error. Accually spi controller has problems both on tx and rx dma. So remove spi dma support in u-boot. Signed-off-by: Scott Jiang Signed-off-by: Sonic Zhang diff --git a/drivers/spi/bfin_spi.c b/drivers/spi/bfin_spi.c index ab2e8b9..0fa131b 100644 --- a/drivers/spi/bfin_spi.c +++ b/drivers/spi/bfin_spi.c @@ -13,7 +13,6 @@ #include #include -#include #include #include #include @@ -242,106 +241,10 @@ void spi_release_bus(struct spi_slave *slave) SSYNC(); } -#ifdef __ADSPBF54x__ -# define SPI_DMA_BASE DMA4_NEXT_DESC_PTR -#elif defined(__ADSPBF533__) || defined(__ADSPBF532__) || defined(__ADSPBF531__) || \ - defined(__ADSPBF538__) || defined(__ADSPBF539__) -# define SPI_DMA_BASE DMA5_NEXT_DESC_PTR -#elif defined(__ADSPBF561__) -# define SPI_DMA_BASE DMA2_4_NEXT_DESC_PTR -#elif defined(__ADSPBF537__) || defined(__ADSPBF536__) || defined(__ADSPBF534__) || \ - defined(__ADSPBF52x__) || defined(__ADSPBF51x__) -# define SPI_DMA_BASE DMA7_NEXT_DESC_PTR -# elif defined(__ADSPBF50x__) -# define SPI_DMA_BASE DMA6_NEXT_DESC_PTR -#else -# error "Please provide SPI DMA channel defines" -#endif -static volatile struct dma_register *dma = (void *)SPI_DMA_BASE; - #ifndef CONFIG_BFIN_SPI_IDLE_VAL # define CONFIG_BFIN_SPI_IDLE_VAL 0xff #endif -#ifdef CONFIG_BFIN_SPI_NO_DMA -# define SPI_DMA 0 -#else -# define SPI_DMA 1 -#endif - -static int spi_dma_xfer(struct bfin_spi_slave *bss, const u8 *tx, u8 *rx, - uint bytes) -{ - int ret = -1; - u16 ndsize, spi_config, dma_config; - struct dmasg dmasg[2]; - const u8 *buf; - - if (tx) { - debug("%s: doing half duplex TX\n", __func__); - buf = tx; - spi_config = TDBR_DMA; - dma_config = 0; - } else { - debug("%s: doing half duplex RX\n", __func__); - buf = rx; - spi_config = RDBR_DMA; - dma_config = WNR; - } - - dmasg[0].start_addr = (unsigned long)buf; - dmasg[0].x_modify = 1; - dma_config |= WDSIZE_8 | DMAEN; - if (bytes <= 65536) { - blackfin_dcache_flush_invalidate_range(buf, buf + bytes); - ndsize = NDSIZE_5; - dmasg[0].cfg = NDSIZE_0 | dma_config | FLOW_STOP | DI_EN; - dmasg[0].x_count = bytes; - } else { - blackfin_dcache_flush_invalidate_range(buf, buf + 65536 - 1); - ndsize = NDSIZE_7; - dmasg[0].cfg = NDSIZE_5 | dma_config | FLOW_ARRAY | DMA2D; - dmasg[0].x_count = 0; /* 2^16 */ - dmasg[0].y_count = bytes >> 16; /* count / 2^16 */ - dmasg[0].y_modify = 1; - dmasg[1].start_addr = (unsigned long)(buf + (bytes & ~0xFFFF)); - dmasg[1].cfg = NDSIZE_0 | dma_config | FLOW_STOP | DI_EN; - dmasg[1].x_count = bytes & 0xFFFF; /* count % 2^16 */ - dmasg[1].x_modify = 1; - } - - dma->cfg = 0; - dma->irq_status = DMA_DONE | DMA_ERR; - dma->curr_desc_ptr = dmasg; - write_SPI_CTL(bss, (bss->ctl & ~TDBR_CORE)); - write_SPI_STAT(bss, -1); - SSYNC(); - - write_SPI_TDBR(bss, CONFIG_BFIN_SPI_IDLE_VAL); - dma->cfg = ndsize | FLOW_ARRAY | DMAEN; - write_SPI_CTL(bss, (bss->ctl & ~TDBR_CORE) | spi_config); - SSYNC(); - - /* - * We already invalidated the first 64k, - * now while we just wait invalidate the remaining part. - * Its not likely that the DMA is going to overtake - */ - if (bytes > 65536) - blackfin_dcache_flush_invalidate_range(buf + 65536, buf + bytes); - - while (!(dma->irq_status & DMA_DONE)) - if (ctrlc()) - goto done; - - dma->cfg = 0; - - ret = 0; - done: - write_SPI_CTL(bss, bss->ctl); - return ret; -} - static int spi_pio_xfer(struct bfin_spi_slave *bss, const u8 *tx, u8 *rx, uint bytes) { @@ -393,11 +296,7 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout, if (flags & SPI_XFER_BEGIN) spi_cs_activate(slave); - /* TX DMA doesn't work quite right */ - if (SPI_DMA && bytes > 6 && (!tx /*|| !rx*/)) - ret = spi_dma_xfer(bss, tx, rx, bytes); - else - ret = spi_pio_xfer(bss, tx, rx, bytes); + ret = spi_pio_xfer(bss, tx, rx, bytes); done: if (flags & SPI_XFER_END) -- cgit v0.10.2 From d4d4f903773e0e5540baa00157585de25a542ba6 Mon Sep 17 00:00:00 2001 From: Scott Jiang Date: Wed, 7 Dec 2011 14:53:30 -0500 Subject: bfin: discard invalid data and clear RXS in bf5xx spi driver There may be dirty data in RDBR, so we should discard invalid data. This operation also clears RXS bit in STAT register. Signed-off-by: Scott Jiang Signed-off-by: Sonic Zhang diff --git a/drivers/spi/bfin_spi.c b/drivers/spi/bfin_spi.c index 0fa131b..a9a4d92 100644 --- a/drivers/spi/bfin_spi.c +++ b/drivers/spi/bfin_spi.c @@ -248,6 +248,8 @@ void spi_release_bus(struct spi_slave *slave) static int spi_pio_xfer(struct bfin_spi_slave *bss, const u8 *tx, u8 *rx, uint bytes) { + /* discard invalid data and clear RXS */ + read_SPI_RDBR(bss); /* todo: take advantage of hardware fifos */ while (bytes--) { u8 value = (tx ? *tx++ : CONFIG_BFIN_SPI_IDLE_VAL); -- cgit v0.10.2 From 50aadcc560560f7365bb6373d4db1375522c4fe3 Mon Sep 17 00:00:00 2001 From: Sonic Zhang Date: Wed, 13 Mar 2013 19:06:16 +0800 Subject: blackfin: Enable early print via the generic serial API. Remove blackfin specific implementation of the generic serial API when early print macro is defined. In BFIN_BOOT_BYPASS mode, don't call generic serial_puts, because early print in bypass mode is running before code binary is relocated to the link address. Signed-off-by: Sonic Zhang diff --git a/arch/blackfin/cpu/serial.c b/arch/blackfin/cpu/serial.c index 36d2a5c..89290d6 100644 --- a/arch/blackfin/cpu/serial.c +++ b/arch/blackfin/cpu/serial.c @@ -197,13 +197,16 @@ static void uart_loop(uint32_t uart_base, int state) static inline void __serial_set_baud(uint32_t uart_base, uint32_t baud) { +#ifdef CONFIG_DEBUG_EARLY_SERIAL + serial_early_set_baud(uart_base, baud); +#else uint16_t divisor = (get_uart_clk() + (baud * 8)) / (baud * 16) - ANOMALY_05000230; /* Program the divisor to get the baud rate we want */ serial_set_divisor(uart_base, divisor); +#endif } -#ifdef CONFIG_SYS_BFIN_UART static void uart_puts(uint32_t uart_base, const char *s) { @@ -313,65 +316,39 @@ void bfin_serial_initialize(void) #endif } -#else - -/* Symbol for our assembly to call. */ -void serial_set_baud(uint32_t baud) -{ - serial_early_set_baud(UART_BASE, baud); -} - -/* Symbol for common u-boot code to call. - * Setup the baudrate (brg: baudrate generator). - */ -void serial_setbrg(void) +#ifdef CONFIG_DEBUG_EARLY_SERIAL +inline void uart_early_putc(uint32_t uart_base, const char c) { - serial_set_baud(gd->baudrate); -} - -/* Symbol for our assembly to call. */ -void serial_initialize(void) -{ - serial_early_init(UART_BASE); -} - -/* Symbol for common u-boot code to call. */ -int serial_init(void) -{ - serial_initialize(); - serial_setbrg(); - uart_lsr_clear(UART_BASE); - return 0; -} + /* send a \r for compatibility */ + if (c == '\n') + uart_early_putc(uart_base, '\r'); -int serial_tstc(void) -{ - return uart_tstc(UART_BASE); -} + /* wait for the hardware fifo to clear up */ + while (!(_lsr_read(pUART) & THRE)) + continue; -int serial_getc(void) -{ - return uart_getc(UART_BASE); + /* queue the character for transmission */ + bfin_write(&pUART->thr, c); + SSYNC(); } -void serial_putc(const char c) +void uart_early_puts(const char *s) { - uart_putc(UART_BASE, c); + while (*s) + uart_early_putc(UART_BASE, *s++); } -void serial_puts(const char *s) +/* Symbol for our assembly to call. */ +void _serial_early_set_baud(uint32_t baud) { - while (*s) - serial_putc(*s++); + serial_early_set_baud(UART_BASE, baud); } -LOOP( -void serial_loop(int state) +/* Symbol for our assembly to call. */ +void _serial_early_init(void) { - uart_loop(UART_BASE, state); + serial_early_init(UART_BASE); } -) - #endif #endif diff --git a/arch/blackfin/cpu/serial.h b/arch/blackfin/cpu/serial.h index d67fd81..87a337d 100644 --- a/arch/blackfin/cpu/serial.h +++ b/arch/blackfin/cpu/serial.h @@ -78,16 +78,16 @@ static inline void serial_early_puts(const char *s) #else .macro serial_early_init -#if defined(CONFIG_DEBUG_EARLY_SERIAL) && defined(BFIN_BOOT_BYPASS) - call _serial_initialize; +#if defined(CONFIG_DEBUG_EARLY_SERIAL) && !defined(CONFIG_UART_MEM) + call __serial_early_init; #endif .endm .macro serial_early_set_baud -#if defined(CONFIG_DEBUG_EARLY_SERIAL) && defined(BFIN_BOOT_BYPASS) +#if defined(CONFIG_DEBUG_EARLY_SERIAL) && !defined(CONFIG_UART_MEM) R0.L = LO(CONFIG_BAUDRATE); R0.H = HI(CONFIG_BAUDRATE); - call _serial_set_baud; + call __serial_early_set_baud; #endif .endm @@ -121,7 +121,7 @@ static inline void serial_early_puts(const char *s) R0.L = 7b; \ R0.H = 7b; \ update_serial_early_string_addr \ - call _serial_puts; + call _uart_early_puts; #else # define serial_early_puts(str) #endif diff --git a/include/configs/bfin_adi_common.h b/include/configs/bfin_adi_common.h index d3ae3a7..c986ba3 100644 --- a/include/configs/bfin_adi_common.h +++ b/include/configs/bfin_adi_common.h @@ -111,9 +111,6 @@ #ifndef CONFIG_BAUDRATE # define CONFIG_BAUDRATE 57600 #endif -#ifndef CONFIG_DEBUG_EARLY_SERIAL -# define CONFIG_SYS_BFIN_UART -#endif /* * Debug Settings -- cgit v0.10.2 From d68e7faac08be5424c748c0ead9b07dd00a43cc1 Mon Sep 17 00:00:00 2001 From: Sonic Zhang Date: Thu, 14 Mar 2013 15:13:30 +0800 Subject: blackfin: Add memory virtual console to blackfin serial driver. Signed-off-by: Sonic Zhang diff --git a/arch/blackfin/cpu/serial.c b/arch/blackfin/cpu/serial.c index 89290d6..c453a03 100644 --- a/arch/blackfin/cpu/serial.c +++ b/arch/blackfin/cpu/serial.c @@ -351,4 +351,62 @@ void _serial_early_init(void) } #endif -#endif +#elif defined(CONFIG_UART_MEM) + +char serial_logbuf[CONFIG_UART_MEM]; +char *serial_logbuf_head = serial_logbuf; + +int serial_mem_init(void) +{ + serial_logbuf_head = serial_logbuf; + return 0; +} + +void serial_mem_setbrg(void) +{ +} + +int serial_mem_tstc(void) +{ + return 0; +} + +int serial_mem_getc(void) +{ + return 0; +} + +void serial_mem_putc(const char c) +{ + *serial_logbuf_head = c; + if (++serial_logbuf_head == serial_logbuf + CONFIG_UART_MEM) + serial_logbuf_head = serial_logbuf; +} + +void serial_mem_puts(const char *s) +{ + while (*s) + serial_putc(*s++); +} + +struct serial_device bfin_serial_mem_device = { + .name = "bfin_uart_mem", + .start = serial_mem_init, + .setbrg = serial_mem_setbrg, + .getc = serial_mem_getc, + .tstc = serial_mem_tstc, + .putc = serial_mem_putc, + .puts = serial_mem_puts, +}; + + +__weak struct serial_device *default_serial_console(void) +{ + return &bfin_serial_mem_device; +} + +void bfin_serial_initialize(void) +{ + serial_register(&bfin_serial_mem_device); +} +#endif /* CONFIG_UART_MEM */ -- cgit v0.10.2 From 04eeb758e746d80848b4add1515493fe565a735e Mon Sep 17 00:00:00 2001 From: Sonic Zhang Date: Thu, 14 Mar 2013 12:47:12 +0800 Subject: blackfin: Uart divisor should be set after their values are generated. Signed-off-by: Sonic Zhang diff --git a/arch/blackfin/cpu/initcode.c b/arch/blackfin/cpu/initcode.c index 4b10b6c..8ef0b92 100644 --- a/arch/blackfin/cpu/initcode.c +++ b/arch/blackfin/cpu/initcode.c @@ -715,8 +715,8 @@ update_serial_clocks(ADI_BOOT_DATA *bs, uint sdivB, uint divB, uint vcoB) * for dividing which means we'd generate a libgcc reference. */ unsigned int sdivR, vcoR; - unsigned int dividend = sdivB * divB * vcoR; - unsigned int divisor = vcoB * sdivR; + unsigned int dividend; + unsigned int divisor; unsigned int quotient; serial_putc('a'); @@ -729,6 +729,9 @@ update_serial_clocks(ADI_BOOT_DATA *bs, uint sdivB, uint divB, uint vcoB) sdivR = bfin_read_PLL_DIV() & 0xf; vcoR = (bfin_read_PLL_CTL() >> 9) & 0x3f; #endif + + dividend = sdivB * divB * vcoR; + divisor = vcoB * sdivR; quotient = early_division(dividend, divisor); serial_early_put_div(quotient - ANOMALY_05000230); serial_putc('c'); -- cgit v0.10.2 From 13262d4cdab79b6ee8d9c6089f84132a4c9372a4 Mon Sep 17 00:00:00 2001 From: Scott Jiang Date: Mon, 1 Apr 2013 15:55:14 -0400 Subject: bf609: add SPI register base address - BF609 spi driver depend on this. Signed-off-by: Scott Jiang Signed-off-by: Sonic Zhang diff --git a/arch/blackfin/include/asm/mach-bf609/BF609_def.h b/arch/blackfin/include/asm/mach-bf609/BF609_def.h index 4d3b003..02b81d3 100644 --- a/arch/blackfin/include/asm/mach-bf609/BF609_def.h +++ b/arch/blackfin/include/asm/mach-bf609/BF609_def.h @@ -128,6 +128,9 @@ #define EMAC0_MACCFG 0xFFC20000 /* EMAC0 MAC Configuration Register */ #define EMAC1_MACCFG 0xFFC22000 /* EMAC1 MAC Configuration Register */ +#define SPI0_REGBASE 0xFFC40400 /* SPI0 Base Address */ +#define SPI1_REGBASE 0xFFC40500 /* SPI1 Base Address */ + #define DMA10_DSCPTR_NXT 0xFFC05000 /* DMA10 Pointer to Next Initial Desc */ #define DMA10_ADDRSTART 0xFFC05004 /* DMA10 Start Address of Current Buf */ #define DMA10_CFG 0xFFC05008 /* DMA10 Configuration Register */ -- cgit v0.10.2 From e9a389a18477c1c57a0b30e9ea8f4d38c6e26e63 Mon Sep 17 00:00:00 2001 From: Sonic Zhang Date: Sun, 7 Apr 2013 18:02:37 +0800 Subject: blackfin: Move blackfin watchdog driver out of the blackfin arch folder. - Enable hw_watchdog_init() in watchdog.h if CONFIG_HW_WATCHDOG is defined. - Move blackfin hw watchdog driver to the generic driver folder. - Call hw_watchdog_init() from blackfin board init code. - Reuse macro CONFIG_WATCHDOG_TIMEOUT_MSECS - Update README.watchdog accordingly Signed-off-by: Sonic Zhang diff --git a/arch/blackfin/cpu/Makefile b/arch/blackfin/cpu/Makefile index 0a72ec5..145f63e 100644 --- a/arch/blackfin/cpu/Makefile +++ b/arch/blackfin/cpu/Makefile @@ -25,7 +25,6 @@ COBJS-y += os_log.o COBJS-y += reset.o COBJS-y += serial.o COBJS-y += traps.o -COBJS-$(CONFIG_HW_WATCHDOG) += watchdog.o SRCS := $(SEXTRA:.o=.S) $(SOBJS:.o=.S) $(COBJS-y:.o=.c) OBJS := $(addprefix $(obj),$(COBJS-y) $(SOBJS)) diff --git a/arch/blackfin/cpu/initcode.c b/arch/blackfin/cpu/initcode.c index 8ef0b92..078209f 100644 --- a/arch/blackfin/cpu/initcode.c +++ b/arch/blackfin/cpu/initcode.c @@ -13,6 +13,7 @@ #include #include +#include #include #include @@ -468,9 +469,11 @@ program_early_devices(ADI_BOOT_DATA *bs, uint *sdivB, uint *divB, uint *vcoB) bfin_write_SEC_GCTL(0x1); bfin_write_SEC_CCTL(0x1); #endif + bfin_write_WDOG_CTL(WDDIS); + SSYNC(); bfin_write_WDOG_CNT(MSEC_TO_SCLK(CONFIG_HW_WATCHDOG_TIMEOUT_INITCODE)); #if CONFIG_BFIN_BOOT_MODE != BFIN_BOOT_UART - bfin_write_WDOG_CTL(0); + bfin_write_WDOG_CTL(WDEN); #endif serial_putc('f'); } diff --git a/arch/blackfin/cpu/start.S b/arch/blackfin/cpu/start.S index 7155fc8..1c6ae35 100644 --- a/arch/blackfin/cpu/start.S +++ b/arch/blackfin/cpu/start.S @@ -32,6 +32,7 @@ #include #include +#include #include #include @@ -65,20 +66,29 @@ ENTRY(_start) p5.h = HI(COREMMR_BASE); #ifdef CONFIG_HW_WATCHDOG -#ifndef __ADSPBF60x__ -# ifndef CONFIG_HW_WATCHDOG_TIMEOUT_START -# define CONFIG_HW_WATCHDOG_TIMEOUT_START 5000 -# endif - /* Program the watchdog with an initial timeout of ~5 seconds. + /* Program the watchdog with default timeout of ~5 seconds. * That should be long enough to bootstrap ourselves up and * then the common u-boot code can take over. */ + r1 = WDDIS; +# ifdef __ADSPBF60x__ + [p4 + (WDOG_CTL - SYSMMR_BASE)] = r1; +# else + W[p4 + (WDOG_CTL - SYSMMR_BASE)] = r1; +# endif + SSYNC; r0 = 0; - r0.h = HI(MSEC_TO_SCLK(CONFIG_HW_WATCHDOG_TIMEOUT_START)); + r0.h = HI(MSEC_TO_SCLK(CONFIG_WATCHDOG_TIMEOUT_MSECS)); [p4 + (WDOG_CNT - SYSMMR_BASE)] = r0; + SSYNC; + r1 = WDEN; /* fire up the watchdog - R0.L above needs to be 0x0000 */ - W[p4 + (WDOG_CTL - SYSMMR_BASE)] = r0; -#endif +# ifdef __ADSPBF60x__ + [p4 + (WDOG_CTL - SYSMMR_BASE)] = r1; +# else + W[p4 + (WDOG_CTL - SYSMMR_BASE)] = r1; +# endif + SSYNC; #endif /* Turn on the serial for debugging the init process */ diff --git a/arch/blackfin/cpu/watchdog.c b/arch/blackfin/cpu/watchdog.c deleted file mode 100644 index 1886bda..0000000 --- a/arch/blackfin/cpu/watchdog.c +++ /dev/null @@ -1,23 +0,0 @@ -/* - * watchdog.c - driver for Blackfin on-chip watchdog - * - * Copyright (c) 2007-2009 Analog Devices Inc. - * - * Licensed under the GPL-2 or later. - */ - -#include -#include -#include - -void hw_watchdog_reset(void) -{ - bfin_write_WDOG_STAT(0); -} - -void hw_watchdog_init(void) -{ - bfin_write_WDOG_CNT(5 * get_sclk()); /* 5 second timeout */ - hw_watchdog_reset(); - bfin_write_WDOG_CTL(0x0); -} diff --git a/arch/blackfin/lib/board.c b/arch/blackfin/lib/board.c index 85b859d..f1d5547 100644 --- a/arch/blackfin/lib/board.c +++ b/arch/blackfin/lib/board.c @@ -279,9 +279,9 @@ void board_init_f(ulong bootflag) dcache_enable(); #endif -#ifdef CONFIG_WATCHDOG +#ifdef CONFIG_HW_WATCHDOG serial_early_puts("Setting up external watchdog\n"); - watchdog_init(); + hw_watchdog_init(); #endif #ifdef DEBUG diff --git a/doc/README.watchdog b/doc/README.watchdog index 33f31c2..59f306b 100644 --- a/doc/README.watchdog +++ b/doc/README.watchdog @@ -30,3 +30,6 @@ CONFIG_IMX_WATCHDOG CONFIG_XILINX_TB_WATCHDOG Available for Xilinx Axi platforms to service timebase watchdog timer. + +CONFIG_BFIN_WATCHDOG + Available for bf5xx and bf6xx to service the watchdog. diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index 13e7c37..d57578d 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -33,6 +33,7 @@ endif COBJS-$(CONFIG_TNETV107X_WATCHDOG) += tnetv107x_wdt.o COBJS-$(CONFIG_S5P) += s5p_wdt.o COBJS-$(CONFIG_XILINX_TB_WATCHDOG) += xilinx_tb_wdt.o +COBJS-$(CONFIG_BFIN_WATCHDOG) += bfin_wdt.o COBJS := $(COBJS-y) SRCS := $(COBJS:.o=.c) diff --git a/drivers/watchdog/bfin_wdt.c b/drivers/watchdog/bfin_wdt.c new file mode 100644 index 0000000..7a6756b --- /dev/null +++ b/drivers/watchdog/bfin_wdt.c @@ -0,0 +1,26 @@ +/* + * watchdog.c - driver for Blackfin on-chip watchdog + * + * Copyright (c) 2007-2009 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + +#include +#include +#include +#include + +void hw_watchdog_reset(void) +{ + bfin_write_WDOG_STAT(0); +} + +void hw_watchdog_init(void) +{ + bfin_write_WDOG_CTL(WDDIS); + SSYNC(); + bfin_write_WDOG_CNT(CONFIG_WATCHDOG_TIMEOUT_MSECS / 1000 * get_sclk()); + hw_watchdog_reset(); + bfin_write_WDOG_CTL(WDEN); +} diff --git a/include/configs/bfin_adi_common.h b/include/configs/bfin_adi_common.h index c986ba3..0bcccf8 100644 --- a/include/configs/bfin_adi_common.h +++ b/include/configs/bfin_adi_common.h @@ -314,5 +314,11 @@ #define CONFIG_BFIN_SPI_GPIO_CS /* Only matters if BFIN_SPI is enabled */ #define CONFIG_LZMA #define CONFIG_MONITOR_IS_IN_RAM +#ifdef CONFIG_HW_WATCHDOG +# define CONFIG_BFIN_WATCHDOG +# ifndef CONFIG_WATCHDOG_TIMEOUT_MSECS +# define CONFIG_WATCHDOG_TIMEOUT_MSECS 5000 +# endif +#endif #endif diff --git a/include/watchdog.h b/include/watchdog.h index 97ec186..d95e4b1 100644 --- a/include/watchdog.h +++ b/include/watchdog.h @@ -108,8 +108,7 @@ int init_func_watchdog_reset(void); void reset_4xx_watchdog(void); #endif -/* Freescale i.MX */ -#if defined(CONFIG_IMX_WATCHDOG) && !defined(__ASSEMBLY__) +#if defined(CONFIG_HW_WATCHDOG) && !defined(__ASSEMBLY__) void hw_watchdog_init(void); #endif #endif /* _WATCHDOG_H_ */ -- cgit v0.10.2 From 9d803fc8125a3528f700da9064d1bfa3fbc56b13 Mon Sep 17 00:00:00 2001 From: Sonic Zhang Date: Sun, 7 Apr 2013 19:04:14 +0800 Subject: blackfin: Move blackfin serial driver out of blackfin arch folder. - Move blackfin serial driver to the generic driver folder. - Move blackfin serial headers to blackfin arch head folder. - Update the include path to blackfin serial header in start up code. Signed-off-by: Sonic Zhang diff --git a/arch/blackfin/cpu/Makefile b/arch/blackfin/cpu/Makefile index 145f63e..929fc8b 100644 --- a/arch/blackfin/cpu/Makefile +++ b/arch/blackfin/cpu/Makefile @@ -23,7 +23,6 @@ COBJS-y += interrupts.o COBJS-$(CONFIG_JTAG_CONSOLE) += jtag-console.o COBJS-y += os_log.o COBJS-y += reset.o -COBJS-y += serial.o COBJS-y += traps.o SRCS := $(SEXTRA:.o=.S) $(SOBJS:.o=.S) $(COBJS-y:.o=.c) diff --git a/arch/blackfin/cpu/cpu.c b/arch/blackfin/cpu/cpu.c index d841f64..218f57e 100644 --- a/arch/blackfin/cpu/cpu.c +++ b/arch/blackfin/cpu/cpu.c @@ -16,9 +16,9 @@ #include #include #include +#include #include "cpu.h" -#include "serial.h" #include "initcode.h" ulong bfin_poweron_retx; diff --git a/arch/blackfin/cpu/initcode.c b/arch/blackfin/cpu/initcode.c index 078209f..5fc06e1 100644 --- a/arch/blackfin/cpu/initcode.c +++ b/arch/blackfin/cpu/initcode.c @@ -16,10 +16,9 @@ #include #include #include +#include -#define BUG() while (1) { asm volatile("emuexcpt;"); } - -#include "serial.h" +#define BUG() while (1) asm volatile("emuexcpt;"); #ifndef __ADSPBF60x__ #include diff --git a/arch/blackfin/cpu/serial.c b/arch/blackfin/cpu/serial.c deleted file mode 100644 index c453a03..0000000 --- a/arch/blackfin/cpu/serial.c +++ /dev/null @@ -1,412 +0,0 @@ -/* - * U-boot - serial.c Blackfin Serial Driver - * - * Copyright (c) 2005-2008 Analog Devices Inc. - * - * Copyright (c) 2003 Bas Vermeulen , - * BuyWays B.V. (www.buyways.nl) - * - * Based heavily on: - * 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. - * - * Licensed under the GPL-2 or later. - */ - -/* Anomaly notes: - * 05000086 - we don't support autobaud - * 05000099 - we only use DR bit, so losing others is not a problem - * 05000100 - we don't use the UART_IIR register - * 05000215 - we poll the uart (no dma/interrupts) - * 05000225 - no workaround possible, but this shouldnt cause errors ... - * 05000230 - we tweak the baud rate calculation slightly - * 05000231 - we always use 1 stop bit - * 05000309 - we always enable the uart before we modify it in anyway - * 05000350 - we always enable the uart regardless of boot mode - * 05000363 - we don't support break signals, so don't generate one - */ - -#include -#include -#include -#include -#include -#include - -DECLARE_GLOBAL_DATA_PTR; - -#ifdef CONFIG_UART_CONSOLE - -#include "serial.h" - -#ifdef CONFIG_DEBUG_SERIAL -static uart_lsr_t cached_lsr[256]; -static uart_lsr_t cached_rbr[256]; -static 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. This also - * works around anomaly 05000099 at the same time by keeping a cumulative - * tally of all the status bits. - */ -static uart_lsr_t uart_lsr_save; -static uart_lsr_t uart_lsr_read(uint32_t uart_base) -{ - uart_lsr_t lsr = _lsr_read(pUART); - 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(uint32_t uart_base) -{ - uart_lsr_save = 0; - _lsr_write(pUART, -1); -} -#else -/* When debugging is disabled, we only care about the DR bit, so if other - * bits get set/cleared, we don't really care since we don't read them - * anyways (and thus anomaly 05000099 is irrelevant). - */ -static inline uart_lsr_t uart_lsr_read(uint32_t uart_base) -{ - return _lsr_read(pUART); -} -static void uart_lsr_clear(uint32_t uart_base) -{ - _lsr_write(pUART, -1); -} -#endif - -static void uart_putc(uint32_t uart_base, const char c) -{ - /* send a \r for compatibility */ - if (c == '\n') - serial_putc('\r'); - - WATCHDOG_RESET(); - - /* wait for the hardware fifo to clear up */ - while (!(uart_lsr_read(uart_base) & THRE)) - continue; - - /* queue the character for transmission */ - bfin_write(&pUART->thr, c); - SSYNC(); - - WATCHDOG_RESET(); -} - -static int uart_tstc(uint32_t uart_base) -{ - WATCHDOG_RESET(); - return (uart_lsr_read(uart_base) & DR) ? 1 : 0; -} - -static int uart_getc(uint32_t uart_base) -{ - uint16_t uart_rbr_val; - - /* wait for data ! */ - while (!uart_tstc(uart_base)) - continue; - - /* grab the new byte */ - uart_rbr_val = bfin_read(&pUART->rbr); - -#ifdef CONFIG_DEBUG_SERIAL - /* grab & clear the LSR */ - uart_lsr_t uart_lsr_val = uart_lsr_read(uart_base); - - 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)) { - printf("\n[SERIAL ERROR]\n"); - do { - --cache_count; - printf("\t%3zu: 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(uart_base); - - return uart_rbr_val; -} - -#if CONFIG_POST & CONFIG_SYS_POST_UART -# define LOOP(x) x -#else -# define LOOP(x) -#endif - -#if BFIN_UART_HW_VER < 4 - -LOOP( -static void uart_loop(uint32_t uart_base, int state) -{ - u16 mcr; - - /* Drain the TX fifo first so bytes don't come back */ - while (!(uart_lsr_read(uart_base) & TEMT)) - continue; - - mcr = bfin_read(&pUART->mcr); - if (state) - mcr |= LOOP_ENA | MRTS; - else - mcr &= ~(LOOP_ENA | MRTS); - bfin_write(&pUART->mcr, mcr); -} -) - -#else - -LOOP( -static void uart_loop(uint32_t uart_base, int state) -{ - u32 control; - - /* Drain the TX fifo first so bytes don't come back */ - while (!(uart_lsr_read(uart_base) & TEMT)) - continue; - - control = bfin_read(&pUART->control); - if (state) - control |= LOOP_ENA | MRTS; - else - control &= ~(LOOP_ENA | MRTS); - bfin_write(&pUART->control, control); -} -) - -#endif - -static inline void __serial_set_baud(uint32_t uart_base, uint32_t baud) -{ -#ifdef CONFIG_DEBUG_EARLY_SERIAL - serial_early_set_baud(uart_base, baud); -#else - uint16_t divisor = (get_uart_clk() + (baud * 8)) / (baud * 16) - - ANOMALY_05000230; - - /* Program the divisor to get the baud rate we want */ - serial_set_divisor(uart_base, divisor); -#endif -} - -static void uart_puts(uint32_t uart_base, const char *s) -{ - while (*s) - uart_putc(uart_base, *s++); -} - -#define DECL_BFIN_UART(n) \ -static int uart##n##_init(void) \ -{ \ - const unsigned short pins[] = { _P_UART(n, RX), _P_UART(n, TX), 0, }; \ - peripheral_request_list(pins, "bfin-uart"); \ - uart_init(MMR_UART(n)); \ - __serial_set_baud(MMR_UART(n), gd->baudrate); \ - uart_lsr_clear(MMR_UART(n)); \ - return 0; \ -} \ -\ -static int uart##n##_uninit(void) \ -{ \ - return serial_early_uninit(MMR_UART(n)); \ -} \ -\ -static void uart##n##_setbrg(void) \ -{ \ - __serial_set_baud(MMR_UART(n), gd->baudrate); \ -} \ -\ -static int uart##n##_getc(void) \ -{ \ - return uart_getc(MMR_UART(n)); \ -} \ -\ -static int uart##n##_tstc(void) \ -{ \ - return uart_tstc(MMR_UART(n)); \ -} \ -\ -static void uart##n##_putc(const char c) \ -{ \ - uart_putc(MMR_UART(n), c); \ -} \ -\ -static void uart##n##_puts(const char *s) \ -{ \ - uart_puts(MMR_UART(n), s); \ -} \ -\ -LOOP( \ -static void uart##n##_loop(int state) \ -{ \ - uart_loop(MMR_UART(n), state); \ -} \ -) \ -\ -struct serial_device bfin_serial##n##_device = { \ - .name = "bfin_uart"#n, \ - .start = uart##n##_init, \ - .stop = uart##n##_uninit, \ - .setbrg = uart##n##_setbrg, \ - .getc = uart##n##_getc, \ - .tstc = uart##n##_tstc, \ - .putc = uart##n##_putc, \ - .puts = uart##n##_puts, \ - LOOP(.loop = uart##n##_loop) \ -}; - -#ifdef UART0_RBR -DECL_BFIN_UART(0) -#endif -#ifdef UART1_RBR -DECL_BFIN_UART(1) -#endif -#ifdef UART2_RBR -DECL_BFIN_UART(2) -#endif -#ifdef UART3_RBR -DECL_BFIN_UART(3) -#endif - -__weak struct serial_device *default_serial_console(void) -{ -#if CONFIG_UART_CONSOLE == 0 - return &bfin_serial0_device; -#elif CONFIG_UART_CONSOLE == 1 - return &bfin_serial1_device; -#elif CONFIG_UART_CONSOLE == 2 - return &bfin_serial2_device; -#elif CONFIG_UART_CONSOLE == 3 - return &bfin_serial3_device; -#endif -} - -void bfin_serial_initialize(void) -{ -#ifdef UART0_RBR - serial_register(&bfin_serial0_device); -#endif -#ifdef UART1_RBR - serial_register(&bfin_serial1_device); -#endif -#ifdef UART2_RBR - serial_register(&bfin_serial2_device); -#endif -#ifdef UART3_RBR - serial_register(&bfin_serial3_device); -#endif -} - -#ifdef CONFIG_DEBUG_EARLY_SERIAL -inline void uart_early_putc(uint32_t uart_base, const char c) -{ - /* send a \r for compatibility */ - if (c == '\n') - uart_early_putc(uart_base, '\r'); - - /* wait for the hardware fifo to clear up */ - while (!(_lsr_read(pUART) & THRE)) - continue; - - /* queue the character for transmission */ - bfin_write(&pUART->thr, c); - SSYNC(); -} - -void uart_early_puts(const char *s) -{ - while (*s) - uart_early_putc(UART_BASE, *s++); -} - -/* Symbol for our assembly to call. */ -void _serial_early_set_baud(uint32_t baud) -{ - serial_early_set_baud(UART_BASE, baud); -} - -/* Symbol for our assembly to call. */ -void _serial_early_init(void) -{ - serial_early_init(UART_BASE); -} -#endif - -#elif defined(CONFIG_UART_MEM) - -char serial_logbuf[CONFIG_UART_MEM]; -char *serial_logbuf_head = serial_logbuf; - -int serial_mem_init(void) -{ - serial_logbuf_head = serial_logbuf; - return 0; -} - -void serial_mem_setbrg(void) -{ -} - -int serial_mem_tstc(void) -{ - return 0; -} - -int serial_mem_getc(void) -{ - return 0; -} - -void serial_mem_putc(const char c) -{ - *serial_logbuf_head = c; - if (++serial_logbuf_head == serial_logbuf + CONFIG_UART_MEM) - serial_logbuf_head = serial_logbuf; -} - -void serial_mem_puts(const char *s) -{ - while (*s) - serial_putc(*s++); -} - -struct serial_device bfin_serial_mem_device = { - .name = "bfin_uart_mem", - .start = serial_mem_init, - .setbrg = serial_mem_setbrg, - .getc = serial_mem_getc, - .tstc = serial_mem_tstc, - .putc = serial_mem_putc, - .puts = serial_mem_puts, -}; - - -__weak struct serial_device *default_serial_console(void) -{ - return &bfin_serial_mem_device; -} - -void bfin_serial_initialize(void) -{ - serial_register(&bfin_serial_mem_device); -} -#endif /* CONFIG_UART_MEM */ diff --git a/arch/blackfin/cpu/serial.h b/arch/blackfin/cpu/serial.h deleted file mode 100644 index 87a337d..0000000 --- a/arch/blackfin/cpu/serial.h +++ /dev/null @@ -1,131 +0,0 @@ -/* - * serial.h - common serial defines for early debug and serial driver. - * any functions defined here must be always_inline since - * initcode cannot have function calls. - * - * Copyright (c) 2004-2011 Analog Devices Inc. - * - * Licensed under the GPL-2 or later. - */ - -#ifndef __BFIN_CPU_SERIAL_H__ -#define __BFIN_CPU_SERIAL_H__ - -#include -#include - -#ifndef CONFIG_UART_CONSOLE -# define CONFIG_UART_CONSOLE 0 -#endif - -#ifdef CONFIG_DEBUG_EARLY_SERIAL -# define BFIN_DEBUG_EARLY_SERIAL 1 -#else -# define BFIN_DEBUG_EARLY_SERIAL 0 -#endif - -#if defined(__ADSPBF60x__) -# define BFIN_UART_HW_VER 4 -#elif defined(__ADSPBF50x__) || defined(__ADSPBF54x__) -# define BFIN_UART_HW_VER 2 -#else -# define BFIN_UART_HW_VER 1 -#endif - -#define __PASTE_UART(num, pfx, sfx) pfx##num##_##sfx -#define _PASTE_UART(num, pfx, sfx) __PASTE_UART(num, pfx, sfx) -#define _P_UART(n, pin) _PASTE_UART(n, P_UART, pin) -#define P_UART(pin) _P_UART(CONFIG_UART_CONSOLE, pin) - -#define pUART ((volatile struct bfin_mmr_serial *)uart_base) - -#ifndef __ASSEMBLY__ -__attribute__((always_inline)) -static inline void serial_do_portmux(void); -#endif - -#if BFIN_UART_HW_VER < 4 -# include "serial1.h" -#else -# include "serial4.h" -#endif - -#ifndef __ASSEMBLY__ - -__attribute__((always_inline)) -static inline void serial_do_portmux(void) -{ - if (!BFIN_DEBUG_EARLY_SERIAL) { - const unsigned short pins[] = { P_UART(RX), P_UART(TX), 0, }; - peripheral_request_list(pins, "bfin-uart"); - return; - } - - serial_early_do_portmux(); -} - -#ifndef BFIN_IN_INITCODE -__attribute__((always_inline)) -static inline void serial_early_puts(const char *s) -{ - if (BFIN_DEBUG_EARLY_SERIAL) { - serial_puts("Early: "); - serial_puts(s); - } -} -#endif - -#else - -.macro serial_early_init -#if defined(CONFIG_DEBUG_EARLY_SERIAL) && !defined(CONFIG_UART_MEM) - call __serial_early_init; -#endif -.endm - -.macro serial_early_set_baud -#if defined(CONFIG_DEBUG_EARLY_SERIAL) && !defined(CONFIG_UART_MEM) - R0.L = LO(CONFIG_BAUDRATE); - R0.H = HI(CONFIG_BAUDRATE); - call __serial_early_set_baud; -#endif -.endm - -#if CONFIG_BFIN_BOOT_MODE == BFIN_BOOT_BYPASS -#define update_serial_early_string_addr \ - R1.L = _start; \ - R1.H = _start; \ - R0 = R0 - R1; \ - R1.L = 0; \ - R1.H = 0x2000; \ - R0 = R0 + R1; -#else -#define update_serial_early_string_addr -#endif - -/* Since we embed the string right into our .text section, we need - * to find its address. We do this by getting our PC and adding 2 - * bytes (which is the length of the jump instruction). Then we - * pass this address to serial_puts(). - */ -#ifdef CONFIG_DEBUG_EARLY_SERIAL -# define serial_early_puts(str) \ - .section .rodata; \ - 7: \ - .ascii "Early:"; \ - .ascii __FILE__; \ - .ascii ": "; \ - .ascii str; \ - .asciz "\n"; \ - .previous; \ - R0.L = 7b; \ - R0.H = 7b; \ - update_serial_early_string_addr \ - call _uart_early_puts; -#else -# define serial_early_puts(str) -#endif - -#endif - -#endif diff --git a/arch/blackfin/cpu/serial1.h b/arch/blackfin/cpu/serial1.h deleted file mode 100644 index 467d381..0000000 --- a/arch/blackfin/cpu/serial1.h +++ /dev/null @@ -1,342 +0,0 @@ -/* - * serial.h - common serial defines for early debug and serial driver. - * any functions defined here must be always_inline since - * initcode cannot have function calls. - * - * Copyright (c) 2004-2011 Analog Devices Inc. - * - * Licensed under the GPL-2 or later. - */ - -#ifndef __BFIN_CPU_SERIAL1_H__ -#define __BFIN_CPU_SERIAL1_H__ - -#include - -#ifndef __ASSEMBLY__ - -#include - -#define MMR_UART(n) _PASTE_UART(n, UART, DLL) -#ifdef UART_DLL -# define UART0_DLL UART_DLL -# if CONFIG_UART_CONSOLE != 0 -# error CONFIG_UART_CONSOLE must be 0 on parts with only one UART -# endif -#endif -#define UART_BASE MMR_UART(CONFIG_UART_CONSOLE) - -#define LOB(x) ((x) & 0xFF) -#define HIB(x) (((x) >> 8) & 0xFF) - -/* - * All Blackfin system MMRs are padded to 32bits even if the register - * itself is only 16bits. So use a helper macro to streamline this. - */ -struct bfin_mmr_serial { -#if BFIN_UART_HW_VER == 2 - u16 dll; - u16 __pad_0; - u16 dlh; - u16 __pad_1; - u16 gctl; - u16 __pad_2; - u16 lcr; - u16 __pad_3; - u16 mcr; - u16 __pad_4; - u16 lsr; - u16 __pad_5; - u16 msr; - u16 __pad_6; - u16 scr; - u16 __pad_7; - u16 ier_set; - u16 __pad_8; - u16 ier_clear; - u16 __pad_9; - u16 thr; - u16 __pad_10; - u16 rbr; - u16 __pad_11; -#else - union { - u16 dll; - u16 thr; - const u16 rbr; - }; - const u16 __spad0; - union { - u16 dlh; - u16 ier; - }; - const u16 __spad1; - const u16 iir; - u16 __pad_0; - u16 lcr; - u16 __pad_1; - u16 mcr; - u16 __pad_2; - u16 lsr; - u16 __pad_3; - u16 msr; - u16 __pad_4; - u16 scr; - u16 __pad_5; - const u32 __spad2; - u16 gctl; - u16 __pad_6; -#endif -}; - -#define uart_lsr_t uint32_t -#define _lsr_read(p) bfin_read(&p->lsr) -#define _lsr_write(p, v) bfin_write(&p->lsr, v) - -#if BFIN_UART_HW_VER == 2 -# define ACCESS_LATCH() -# define ACCESS_PORT_IER() -#else -# define ACCESS_LATCH() bfin_write_or(&pUART->lcr, DLAB) -# define ACCESS_PORT_IER() bfin_write_and(&pUART->lcr, ~DLAB) -#endif - -__attribute__((always_inline)) -static inline void serial_early_do_mach_portmux(char port, int mux_mask, - int mux_func, int port_pin) -{ - switch (port) { -#if defined(__ADSPBF54x__) - case 'B': - bfin_write_PORTB_MUX((bfin_read_PORTB_MUX() & - ~mux_mask) | mux_func); - bfin_write_PORTB_FER(bfin_read_PORTB_FER() | port_pin); - break; - case 'E': - bfin_write_PORTE_MUX((bfin_read_PORTE_MUX() & - ~mux_mask) | mux_func); - bfin_write_PORTE_FER(bfin_read_PORTE_FER() | port_pin); - break; -#endif -#if defined(__ADSPBF50x__) || defined(__ADSPBF51x__) || defined(__ADSPBF52x__) - case 'F': - bfin_write_PORTF_MUX((bfin_read_PORTF_MUX() & - ~mux_mask) | mux_func); - bfin_write_PORTF_FER(bfin_read_PORTF_FER() | port_pin); - break; - case 'G': - bfin_write_PORTG_MUX((bfin_read_PORTG_MUX() & - ~mux_mask) | mux_func); - bfin_write_PORTG_FER(bfin_read_PORTG_FER() | port_pin); - break; - case 'H': - bfin_write_PORTH_MUX((bfin_read_PORTH_MUX() & - ~mux_mask) | mux_func); - bfin_write_PORTH_FER(bfin_read_PORTH_FER() | port_pin); - break; -#endif - default: - break; - } -} - -__attribute__((always_inline)) -static inline void serial_early_do_portmux(void) -{ -#if defined(__ADSPBF50x__) - switch (CONFIG_UART_CONSOLE) { - case 0: - serial_early_do_mach_portmux('G', PORT_x_MUX_7_MASK, - PORT_x_MUX_7_FUNC_1, PG12); /* TX: G; mux 7; func 1; PG12 */ - serial_early_do_mach_portmux('G', PORT_x_MUX_7_MASK, - PORT_x_MUX_7_FUNC_1, PG13); /* RX: G; mux 7; func 1; PG13 */ - break; - case 1: - serial_early_do_mach_portmux('F', PORT_x_MUX_3_MASK, - PORT_x_MUX_3_FUNC_1, PF7); /* TX: F; mux 3; func 1; PF6 */ - serial_early_do_mach_portmux('F', PORT_x_MUX_3_MASK, - PORT_x_MUX_3_FUNC_1, PF6); /* RX: F; mux 3; func 1; PF7 */ - break; - } -#elif defined(__ADSPBF51x__) - switch (CONFIG_UART_CONSOLE) { - case 0: - serial_early_do_mach_portmux('G', PORT_x_MUX_5_MASK, - PORT_x_MUX_5_FUNC_2, PG9); /* TX: G; mux 5; func 2; PG9 */ - serial_early_do_mach_portmux('G', PORT_x_MUX_5_MASK, - PORT_x_MUX_5_FUNC_2, PG10); /* RX: G; mux 5; func 2; PG10 */ - break; - case 1: - serial_early_do_mach_portmux('H', PORT_x_MUX_3_MASK, - PORT_x_MUX_3_FUNC_2, PH7); /* TX: H; mux 3; func 2; PH6 */ - serial_early_do_mach_portmux('H', PORT_x_MUX_3_MASK, - PORT_x_MUX_3_FUNC_2, PH6); /* RX: H; mux 3; func 2; PH7 */ - break; - } -#elif defined(__ADSPBF52x__) - switch (CONFIG_UART_CONSOLE) { - case 0: - serial_early_do_mach_portmux('G', PORT_x_MUX_2_MASK, - PORT_x_MUX_2_FUNC_3, PG7); /* TX: G; mux 2; func 3; PG7 */ - serial_early_do_mach_portmux('G', PORT_x_MUX_2_MASK, - PORT_x_MUX_2_FUNC_3, PG8); /* RX: G; mux 2; func 3; PG8 */ - break; - case 1: - serial_early_do_mach_portmux('F', PORT_x_MUX_5_MASK, - PORT_x_MUX_5_FUNC_3, PF14); /* TX: F; mux 5; func 3; PF14 */ - serial_early_do_mach_portmux('F', PORT_x_MUX_5_MASK, - PORT_x_MUX_5_FUNC_3, PF15); /* RX: F; mux 5; func 3; PF15 */ - break; - } -#elif defined(__ADSPBF537__) || defined(__ADSPBF536__) || defined(__ADSPBF534__) - const uint16_t func[] = { PFDE, PFTE, }; - bfin_write_PORT_MUX(bfin_read_PORT_MUX() & ~func[CONFIG_UART_CONSOLE]); - bfin_write_PORTF_FER(bfin_read_PORTF_FER() | - (1 << P_IDENT(P_UART(RX))) | - (1 << P_IDENT(P_UART(TX)))); -#elif defined(__ADSPBF54x__) - switch (CONFIG_UART_CONSOLE) { - case 0: - serial_early_do_mach_portmux('E', PORT_x_MUX_7_MASK, - PORT_x_MUX_7_FUNC_1, PE7); /* TX: E; mux 7; func 1; PE7 */ - serial_early_do_mach_portmux('E', PORT_x_MUX_8_MASK, - PORT_x_MUX_8_FUNC_1, PE8); /* RX: E; mux 8; func 1; PE8 */ - break; - case 1: - serial_early_do_mach_portmux('H', PORT_x_MUX_0_MASK, - PORT_x_MUX_0_FUNC_1, PH0); /* TX: H; mux 0; func 1; PH0 */ - serial_early_do_mach_portmux('H', PORT_x_MUX_1_MASK, - PORT_x_MUX_1_FUNC_1, PH1); /* RX: H; mux 1; func 1; PH1 */ - break; - case 2: - serial_early_do_mach_portmux('B', PORT_x_MUX_4_MASK, - PORT_x_MUX_4_FUNC_1, PB4); /* TX: B; mux 4; func 1; PB4 */ - serial_early_do_mach_portmux('B', PORT_x_MUX_5_MASK, - PORT_x_MUX_5_FUNC_1, PB5); /* RX: B; mux 5; func 1; PB5 */ - break; - case 3: - serial_early_do_mach_portmux('B', PORT_x_MUX_6_MASK, - PORT_x_MUX_6_FUNC_1, PB6); /* TX: B; mux 6; func 1; PB6 */ - serial_early_do_mach_portmux('B', PORT_x_MUX_7_MASK, - PORT_x_MUX_7_FUNC_1, PB7); /* RX: B; mux 7; func 1; PB7 */ - break; - } -#elif defined(__ADSPBF561__) - /* UART pins could be GPIO, but they aren't pin muxed. */ -#else -# if (P_UART(RX) & P_DEFINED) || (P_UART(TX) & P_DEFINED) -# error "missing portmux logic for UART" -# endif -#endif - SSYNC(); -} - -__attribute__((always_inline)) -static inline int uart_init(uint32_t uart_base) -{ - /* always enable UART -- avoids anomalies 05000309 and 05000350 */ - bfin_write(&pUART->gctl, UCEN); - - /* Set LCR to Word Lengh 8-bit word select */ - bfin_write(&pUART->lcr, WLS_8); - - SSYNC(); - - return 0; -} - -__attribute__((always_inline)) -static inline int serial_early_init(uint32_t uart_base) -{ - /* handle portmux crap on different Blackfins */ - serial_do_portmux(); - - return uart_init(uart_base); -} - -__attribute__((always_inline)) -static inline int serial_early_uninit(uint32_t uart_base) -{ - /* disable the UART by clearing UCEN */ - bfin_write(&pUART->gctl, 0); - - return 0; -} - -__attribute__((always_inline)) -static inline void serial_set_divisor(uint32_t uart_base, uint16_t divisor) -{ - /* Set DLAB in LCR to Access DLL and DLH */ - ACCESS_LATCH(); - SSYNC(); - - /* Program the divisor to get the baud rate we want */ - bfin_write(&pUART->dll, LOB(divisor)); - bfin_write(&pUART->dlh, HIB(divisor)); - SSYNC(); - - /* Clear DLAB in LCR to Access THR RBR IER */ - ACCESS_PORT_IER(); - SSYNC(); -} - -__attribute__((always_inline)) -static inline void serial_early_set_baud(uint32_t uart_base, uint32_t baud) -{ - /* 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. - */ -#if CONFIG_BFIN_BOOT_MODE == BFIN_BOOT_BYPASS - uint16_t divisor = (early_get_uart_clk() + baud * 8) / (baud * 16) - - ANOMALY_05000230; -#else - uint16_t divisor = early_division(early_get_uart_clk() + (baud * 8), - baud * 16) - ANOMALY_05000230; -#endif - - serial_set_divisor(uart_base, divisor); -} - -__attribute__((always_inline)) -static inline void serial_early_put_div(uint16_t divisor) -{ - uint32_t uart_base = UART_BASE; - - /* Set DLAB in LCR to Access DLL and DLH */ - ACCESS_LATCH(); - SSYNC(); - - /* Program the divisor to get the baud rate we want */ - bfin_write(&pUART->dll, LOB(divisor)); - bfin_write(&pUART->dlh, HIB(divisor)); - SSYNC(); - - /* Clear DLAB in LCR to Access THR RBR IER */ - ACCESS_PORT_IER(); - SSYNC(); -} - -__attribute__((always_inline)) -static inline uint16_t serial_early_get_div(void) -{ - uint32_t uart_base = UART_BASE; - - /* Set DLAB in LCR to Access DLL and DLH */ - ACCESS_LATCH(); - SSYNC(); - - uint8_t dll = bfin_read(&pUART->dll); - uint8_t dlh = bfin_read(&pUART->dlh); - uint16_t divisor = (dlh << 8) | dll; - - /* Clear DLAB in LCR to Access THR RBR IER */ - ACCESS_PORT_IER(); - SSYNC(); - - return divisor; -} - -#endif - -#endif diff --git a/arch/blackfin/cpu/serial4.h b/arch/blackfin/cpu/serial4.h deleted file mode 100644 index 6548396..0000000 --- a/arch/blackfin/cpu/serial4.h +++ /dev/null @@ -1,150 +0,0 @@ -/* - * serial.h - common serial defines for early debug and serial driver. - * any functions defined here must be always_inline since - * initcode cannot have function calls. - * - * Copyright (c) 2004-2011 Analog Devices Inc. - * - * Licensed under the GPL-2 or later. - */ - -#ifndef __BFIN_CPU_SERIAL4_H__ -#define __BFIN_CPU_SERIAL4_H__ - -#include - -#ifndef __ASSEMBLY__ - -#include - -#define MMR_UART(n) _PASTE_UART(n, UART, REVID) -#define UART_BASE MMR_UART(CONFIG_UART_CONSOLE) - -struct bfin_mmr_serial { - u32 revid; - u32 control; - u32 status; - u32 scr; - u32 clock; - u32 emask; - u32 emaskst; - u32 emaskcl; - u32 rbr; - u32 thr; - u32 taip; - u32 tsr; - u32 rsr; - u32 txdiv_cnt; - u32 rxdiv_cnt; -}; -#define uart_lsr_t uint32_t -#define _lsr_read(p) bfin_read(&p->status) -#define _lsr_write(p, v) bfin_write(&p->status, v) - -__attribute__((always_inline)) -static inline void serial_early_do_mach_portmux(char port, int mux_mask, - int mux_func, int port_pin) -{ - switch (port) { - case 'D': - bfin_write_PORTD_MUX((bfin_read_PORTD_MUX() & - ~mux_mask) | mux_func); - bfin_write_PORTD_FER_SET(port_pin); - break; - case 'G': - bfin_write_PORTG_MUX((bfin_read_PORTG_MUX() & - ~mux_mask) | mux_func); - bfin_write_PORTG_FER_SET(port_pin); - break; - } -} - -__attribute__((always_inline)) -static inline void serial_early_do_portmux(void) -{ -#if defined(__ADSPBF60x__) - switch (CONFIG_UART_CONSOLE) { - case 0: - serial_early_do_mach_portmux('D', PORT_x_MUX_7_MASK, - PORT_x_MUX_7_FUNC_2, PD7); /* TX: D; mux 7; func 2; PD7 */ - serial_early_do_mach_portmux('D', PORT_x_MUX_8_MASK, - PORT_x_MUX_8_FUNC_2, PD8); /* RX: D; mux 8; func 2; PD8 */ - break; - case 1: - serial_early_do_mach_portmux('G', PORT_x_MUX_15_MASK, - PORT_x_MUX_15_FUNC_1, PG15); /* TX: G; mux 15; func 1; PG15 */ - serial_early_do_mach_portmux('G', PORT_x_MUX_14_MASK, - PORT_x_MUX_14_FUNC_1, PG14); /* RX: G; mux 14; func 1; PG14 */ - break; - } -#else -# if (P_UART(RX) & P_DEFINED) || (P_UART(TX) & P_DEFINED) -# error "missing portmux logic for UART" -# endif -#endif - SSYNC(); -} - -__attribute__((always_inline)) -static inline int uart_init(uint32_t uart_base) -{ - /* always enable UART to 8-bit mode */ - bfin_write(&pUART->control, UEN | UMOD_UART | WLS_8); - - SSYNC(); - - return 0; -} - -__attribute__((always_inline)) -static inline int serial_early_init(uint32_t uart_base) -{ - /* handle portmux crap on different Blackfins */ - serial_do_portmux(); - - return uart_init(uart_base); -} - -__attribute__((always_inline)) -static inline int serial_early_uninit(uint32_t uart_base) -{ - /* disable the UART by clearing UEN */ - bfin_write(&pUART->control, 0); - - return 0; -} - -__attribute__((always_inline)) -static inline void serial_set_divisor(uint32_t uart_base, uint16_t divisor) -{ - /* Program the divisor to get the baud rate we want */ - bfin_write(&pUART->clock, divisor); - SSYNC(); -} - -__attribute__((always_inline)) -static inline void serial_early_set_baud(uint32_t uart_base, uint32_t baud) -{ - uint16_t divisor = early_division(early_get_uart_clk(), baud * 16); - - /* Program the divisor to get the baud rate we want */ - serial_set_divisor(uart_base, divisor); -} - -__attribute__((always_inline)) -static inline void serial_early_put_div(uint32_t divisor) -{ - uint32_t uart_base = UART_BASE; - bfin_write(&pUART->clock, divisor); -} - -__attribute__((always_inline)) -static inline uint32_t serial_early_get_div(void) -{ - uint32_t uart_base = UART_BASE; - return bfin_read(&pUART->clock); -} - -#endif - -#endif diff --git a/arch/blackfin/cpu/start.S b/arch/blackfin/cpu/start.S index 1c6ae35..da084a8 100644 --- a/arch/blackfin/cpu/start.S +++ b/arch/blackfin/cpu/start.S @@ -35,8 +35,7 @@ #include #include #include - -#include "serial.h" +#include /* It may seem odd that we make calls to functions even though we haven't * relocated ourselves yet out of {flash,ram,wherever}. This is OK because diff --git a/arch/blackfin/include/asm/serial.h b/arch/blackfin/include/asm/serial.h new file mode 100644 index 0000000..87a337d --- /dev/null +++ b/arch/blackfin/include/asm/serial.h @@ -0,0 +1,131 @@ +/* + * serial.h - common serial defines for early debug and serial driver. + * any functions defined here must be always_inline since + * initcode cannot have function calls. + * + * Copyright (c) 2004-2011 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + +#ifndef __BFIN_CPU_SERIAL_H__ +#define __BFIN_CPU_SERIAL_H__ + +#include +#include + +#ifndef CONFIG_UART_CONSOLE +# define CONFIG_UART_CONSOLE 0 +#endif + +#ifdef CONFIG_DEBUG_EARLY_SERIAL +# define BFIN_DEBUG_EARLY_SERIAL 1 +#else +# define BFIN_DEBUG_EARLY_SERIAL 0 +#endif + +#if defined(__ADSPBF60x__) +# define BFIN_UART_HW_VER 4 +#elif defined(__ADSPBF50x__) || defined(__ADSPBF54x__) +# define BFIN_UART_HW_VER 2 +#else +# define BFIN_UART_HW_VER 1 +#endif + +#define __PASTE_UART(num, pfx, sfx) pfx##num##_##sfx +#define _PASTE_UART(num, pfx, sfx) __PASTE_UART(num, pfx, sfx) +#define _P_UART(n, pin) _PASTE_UART(n, P_UART, pin) +#define P_UART(pin) _P_UART(CONFIG_UART_CONSOLE, pin) + +#define pUART ((volatile struct bfin_mmr_serial *)uart_base) + +#ifndef __ASSEMBLY__ +__attribute__((always_inline)) +static inline void serial_do_portmux(void); +#endif + +#if BFIN_UART_HW_VER < 4 +# include "serial1.h" +#else +# include "serial4.h" +#endif + +#ifndef __ASSEMBLY__ + +__attribute__((always_inline)) +static inline void serial_do_portmux(void) +{ + if (!BFIN_DEBUG_EARLY_SERIAL) { + const unsigned short pins[] = { P_UART(RX), P_UART(TX), 0, }; + peripheral_request_list(pins, "bfin-uart"); + return; + } + + serial_early_do_portmux(); +} + +#ifndef BFIN_IN_INITCODE +__attribute__((always_inline)) +static inline void serial_early_puts(const char *s) +{ + if (BFIN_DEBUG_EARLY_SERIAL) { + serial_puts("Early: "); + serial_puts(s); + } +} +#endif + +#else + +.macro serial_early_init +#if defined(CONFIG_DEBUG_EARLY_SERIAL) && !defined(CONFIG_UART_MEM) + call __serial_early_init; +#endif +.endm + +.macro serial_early_set_baud +#if defined(CONFIG_DEBUG_EARLY_SERIAL) && !defined(CONFIG_UART_MEM) + R0.L = LO(CONFIG_BAUDRATE); + R0.H = HI(CONFIG_BAUDRATE); + call __serial_early_set_baud; +#endif +.endm + +#if CONFIG_BFIN_BOOT_MODE == BFIN_BOOT_BYPASS +#define update_serial_early_string_addr \ + R1.L = _start; \ + R1.H = _start; \ + R0 = R0 - R1; \ + R1.L = 0; \ + R1.H = 0x2000; \ + R0 = R0 + R1; +#else +#define update_serial_early_string_addr +#endif + +/* Since we embed the string right into our .text section, we need + * to find its address. We do this by getting our PC and adding 2 + * bytes (which is the length of the jump instruction). Then we + * pass this address to serial_puts(). + */ +#ifdef CONFIG_DEBUG_EARLY_SERIAL +# define serial_early_puts(str) \ + .section .rodata; \ + 7: \ + .ascii "Early:"; \ + .ascii __FILE__; \ + .ascii ": "; \ + .ascii str; \ + .asciz "\n"; \ + .previous; \ + R0.L = 7b; \ + R0.H = 7b; \ + update_serial_early_string_addr \ + call _uart_early_puts; +#else +# define serial_early_puts(str) +#endif + +#endif + +#endif diff --git a/arch/blackfin/include/asm/serial1.h b/arch/blackfin/include/asm/serial1.h new file mode 100644 index 0000000..467d381 --- /dev/null +++ b/arch/blackfin/include/asm/serial1.h @@ -0,0 +1,342 @@ +/* + * serial.h - common serial defines for early debug and serial driver. + * any functions defined here must be always_inline since + * initcode cannot have function calls. + * + * Copyright (c) 2004-2011 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + +#ifndef __BFIN_CPU_SERIAL1_H__ +#define __BFIN_CPU_SERIAL1_H__ + +#include + +#ifndef __ASSEMBLY__ + +#include + +#define MMR_UART(n) _PASTE_UART(n, UART, DLL) +#ifdef UART_DLL +# define UART0_DLL UART_DLL +# if CONFIG_UART_CONSOLE != 0 +# error CONFIG_UART_CONSOLE must be 0 on parts with only one UART +# endif +#endif +#define UART_BASE MMR_UART(CONFIG_UART_CONSOLE) + +#define LOB(x) ((x) & 0xFF) +#define HIB(x) (((x) >> 8) & 0xFF) + +/* + * All Blackfin system MMRs are padded to 32bits even if the register + * itself is only 16bits. So use a helper macro to streamline this. + */ +struct bfin_mmr_serial { +#if BFIN_UART_HW_VER == 2 + u16 dll; + u16 __pad_0; + u16 dlh; + u16 __pad_1; + u16 gctl; + u16 __pad_2; + u16 lcr; + u16 __pad_3; + u16 mcr; + u16 __pad_4; + u16 lsr; + u16 __pad_5; + u16 msr; + u16 __pad_6; + u16 scr; + u16 __pad_7; + u16 ier_set; + u16 __pad_8; + u16 ier_clear; + u16 __pad_9; + u16 thr; + u16 __pad_10; + u16 rbr; + u16 __pad_11; +#else + union { + u16 dll; + u16 thr; + const u16 rbr; + }; + const u16 __spad0; + union { + u16 dlh; + u16 ier; + }; + const u16 __spad1; + const u16 iir; + u16 __pad_0; + u16 lcr; + u16 __pad_1; + u16 mcr; + u16 __pad_2; + u16 lsr; + u16 __pad_3; + u16 msr; + u16 __pad_4; + u16 scr; + u16 __pad_5; + const u32 __spad2; + u16 gctl; + u16 __pad_6; +#endif +}; + +#define uart_lsr_t uint32_t +#define _lsr_read(p) bfin_read(&p->lsr) +#define _lsr_write(p, v) bfin_write(&p->lsr, v) + +#if BFIN_UART_HW_VER == 2 +# define ACCESS_LATCH() +# define ACCESS_PORT_IER() +#else +# define ACCESS_LATCH() bfin_write_or(&pUART->lcr, DLAB) +# define ACCESS_PORT_IER() bfin_write_and(&pUART->lcr, ~DLAB) +#endif + +__attribute__((always_inline)) +static inline void serial_early_do_mach_portmux(char port, int mux_mask, + int mux_func, int port_pin) +{ + switch (port) { +#if defined(__ADSPBF54x__) + case 'B': + bfin_write_PORTB_MUX((bfin_read_PORTB_MUX() & + ~mux_mask) | mux_func); + bfin_write_PORTB_FER(bfin_read_PORTB_FER() | port_pin); + break; + case 'E': + bfin_write_PORTE_MUX((bfin_read_PORTE_MUX() & + ~mux_mask) | mux_func); + bfin_write_PORTE_FER(bfin_read_PORTE_FER() | port_pin); + break; +#endif +#if defined(__ADSPBF50x__) || defined(__ADSPBF51x__) || defined(__ADSPBF52x__) + case 'F': + bfin_write_PORTF_MUX((bfin_read_PORTF_MUX() & + ~mux_mask) | mux_func); + bfin_write_PORTF_FER(bfin_read_PORTF_FER() | port_pin); + break; + case 'G': + bfin_write_PORTG_MUX((bfin_read_PORTG_MUX() & + ~mux_mask) | mux_func); + bfin_write_PORTG_FER(bfin_read_PORTG_FER() | port_pin); + break; + case 'H': + bfin_write_PORTH_MUX((bfin_read_PORTH_MUX() & + ~mux_mask) | mux_func); + bfin_write_PORTH_FER(bfin_read_PORTH_FER() | port_pin); + break; +#endif + default: + break; + } +} + +__attribute__((always_inline)) +static inline void serial_early_do_portmux(void) +{ +#if defined(__ADSPBF50x__) + switch (CONFIG_UART_CONSOLE) { + case 0: + serial_early_do_mach_portmux('G', PORT_x_MUX_7_MASK, + PORT_x_MUX_7_FUNC_1, PG12); /* TX: G; mux 7; func 1; PG12 */ + serial_early_do_mach_portmux('G', PORT_x_MUX_7_MASK, + PORT_x_MUX_7_FUNC_1, PG13); /* RX: G; mux 7; func 1; PG13 */ + break; + case 1: + serial_early_do_mach_portmux('F', PORT_x_MUX_3_MASK, + PORT_x_MUX_3_FUNC_1, PF7); /* TX: F; mux 3; func 1; PF6 */ + serial_early_do_mach_portmux('F', PORT_x_MUX_3_MASK, + PORT_x_MUX_3_FUNC_1, PF6); /* RX: F; mux 3; func 1; PF7 */ + break; + } +#elif defined(__ADSPBF51x__) + switch (CONFIG_UART_CONSOLE) { + case 0: + serial_early_do_mach_portmux('G', PORT_x_MUX_5_MASK, + PORT_x_MUX_5_FUNC_2, PG9); /* TX: G; mux 5; func 2; PG9 */ + serial_early_do_mach_portmux('G', PORT_x_MUX_5_MASK, + PORT_x_MUX_5_FUNC_2, PG10); /* RX: G; mux 5; func 2; PG10 */ + break; + case 1: + serial_early_do_mach_portmux('H', PORT_x_MUX_3_MASK, + PORT_x_MUX_3_FUNC_2, PH7); /* TX: H; mux 3; func 2; PH6 */ + serial_early_do_mach_portmux('H', PORT_x_MUX_3_MASK, + PORT_x_MUX_3_FUNC_2, PH6); /* RX: H; mux 3; func 2; PH7 */ + break; + } +#elif defined(__ADSPBF52x__) + switch (CONFIG_UART_CONSOLE) { + case 0: + serial_early_do_mach_portmux('G', PORT_x_MUX_2_MASK, + PORT_x_MUX_2_FUNC_3, PG7); /* TX: G; mux 2; func 3; PG7 */ + serial_early_do_mach_portmux('G', PORT_x_MUX_2_MASK, + PORT_x_MUX_2_FUNC_3, PG8); /* RX: G; mux 2; func 3; PG8 */ + break; + case 1: + serial_early_do_mach_portmux('F', PORT_x_MUX_5_MASK, + PORT_x_MUX_5_FUNC_3, PF14); /* TX: F; mux 5; func 3; PF14 */ + serial_early_do_mach_portmux('F', PORT_x_MUX_5_MASK, + PORT_x_MUX_5_FUNC_3, PF15); /* RX: F; mux 5; func 3; PF15 */ + break; + } +#elif defined(__ADSPBF537__) || defined(__ADSPBF536__) || defined(__ADSPBF534__) + const uint16_t func[] = { PFDE, PFTE, }; + bfin_write_PORT_MUX(bfin_read_PORT_MUX() & ~func[CONFIG_UART_CONSOLE]); + bfin_write_PORTF_FER(bfin_read_PORTF_FER() | + (1 << P_IDENT(P_UART(RX))) | + (1 << P_IDENT(P_UART(TX)))); +#elif defined(__ADSPBF54x__) + switch (CONFIG_UART_CONSOLE) { + case 0: + serial_early_do_mach_portmux('E', PORT_x_MUX_7_MASK, + PORT_x_MUX_7_FUNC_1, PE7); /* TX: E; mux 7; func 1; PE7 */ + serial_early_do_mach_portmux('E', PORT_x_MUX_8_MASK, + PORT_x_MUX_8_FUNC_1, PE8); /* RX: E; mux 8; func 1; PE8 */ + break; + case 1: + serial_early_do_mach_portmux('H', PORT_x_MUX_0_MASK, + PORT_x_MUX_0_FUNC_1, PH0); /* TX: H; mux 0; func 1; PH0 */ + serial_early_do_mach_portmux('H', PORT_x_MUX_1_MASK, + PORT_x_MUX_1_FUNC_1, PH1); /* RX: H; mux 1; func 1; PH1 */ + break; + case 2: + serial_early_do_mach_portmux('B', PORT_x_MUX_4_MASK, + PORT_x_MUX_4_FUNC_1, PB4); /* TX: B; mux 4; func 1; PB4 */ + serial_early_do_mach_portmux('B', PORT_x_MUX_5_MASK, + PORT_x_MUX_5_FUNC_1, PB5); /* RX: B; mux 5; func 1; PB5 */ + break; + case 3: + serial_early_do_mach_portmux('B', PORT_x_MUX_6_MASK, + PORT_x_MUX_6_FUNC_1, PB6); /* TX: B; mux 6; func 1; PB6 */ + serial_early_do_mach_portmux('B', PORT_x_MUX_7_MASK, + PORT_x_MUX_7_FUNC_1, PB7); /* RX: B; mux 7; func 1; PB7 */ + break; + } +#elif defined(__ADSPBF561__) + /* UART pins could be GPIO, but they aren't pin muxed. */ +#else +# if (P_UART(RX) & P_DEFINED) || (P_UART(TX) & P_DEFINED) +# error "missing portmux logic for UART" +# endif +#endif + SSYNC(); +} + +__attribute__((always_inline)) +static inline int uart_init(uint32_t uart_base) +{ + /* always enable UART -- avoids anomalies 05000309 and 05000350 */ + bfin_write(&pUART->gctl, UCEN); + + /* Set LCR to Word Lengh 8-bit word select */ + bfin_write(&pUART->lcr, WLS_8); + + SSYNC(); + + return 0; +} + +__attribute__((always_inline)) +static inline int serial_early_init(uint32_t uart_base) +{ + /* handle portmux crap on different Blackfins */ + serial_do_portmux(); + + return uart_init(uart_base); +} + +__attribute__((always_inline)) +static inline int serial_early_uninit(uint32_t uart_base) +{ + /* disable the UART by clearing UCEN */ + bfin_write(&pUART->gctl, 0); + + return 0; +} + +__attribute__((always_inline)) +static inline void serial_set_divisor(uint32_t uart_base, uint16_t divisor) +{ + /* Set DLAB in LCR to Access DLL and DLH */ + ACCESS_LATCH(); + SSYNC(); + + /* Program the divisor to get the baud rate we want */ + bfin_write(&pUART->dll, LOB(divisor)); + bfin_write(&pUART->dlh, HIB(divisor)); + SSYNC(); + + /* Clear DLAB in LCR to Access THR RBR IER */ + ACCESS_PORT_IER(); + SSYNC(); +} + +__attribute__((always_inline)) +static inline void serial_early_set_baud(uint32_t uart_base, uint32_t baud) +{ + /* 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. + */ +#if CONFIG_BFIN_BOOT_MODE == BFIN_BOOT_BYPASS + uint16_t divisor = (early_get_uart_clk() + baud * 8) / (baud * 16) + - ANOMALY_05000230; +#else + uint16_t divisor = early_division(early_get_uart_clk() + (baud * 8), + baud * 16) - ANOMALY_05000230; +#endif + + serial_set_divisor(uart_base, divisor); +} + +__attribute__((always_inline)) +static inline void serial_early_put_div(uint16_t divisor) +{ + uint32_t uart_base = UART_BASE; + + /* Set DLAB in LCR to Access DLL and DLH */ + ACCESS_LATCH(); + SSYNC(); + + /* Program the divisor to get the baud rate we want */ + bfin_write(&pUART->dll, LOB(divisor)); + bfin_write(&pUART->dlh, HIB(divisor)); + SSYNC(); + + /* Clear DLAB in LCR to Access THR RBR IER */ + ACCESS_PORT_IER(); + SSYNC(); +} + +__attribute__((always_inline)) +static inline uint16_t serial_early_get_div(void) +{ + uint32_t uart_base = UART_BASE; + + /* Set DLAB in LCR to Access DLL and DLH */ + ACCESS_LATCH(); + SSYNC(); + + uint8_t dll = bfin_read(&pUART->dll); + uint8_t dlh = bfin_read(&pUART->dlh); + uint16_t divisor = (dlh << 8) | dll; + + /* Clear DLAB in LCR to Access THR RBR IER */ + ACCESS_PORT_IER(); + SSYNC(); + + return divisor; +} + +#endif + +#endif diff --git a/arch/blackfin/include/asm/serial4.h b/arch/blackfin/include/asm/serial4.h new file mode 100644 index 0000000..6548396 --- /dev/null +++ b/arch/blackfin/include/asm/serial4.h @@ -0,0 +1,150 @@ +/* + * serial.h - common serial defines for early debug and serial driver. + * any functions defined here must be always_inline since + * initcode cannot have function calls. + * + * Copyright (c) 2004-2011 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + +#ifndef __BFIN_CPU_SERIAL4_H__ +#define __BFIN_CPU_SERIAL4_H__ + +#include + +#ifndef __ASSEMBLY__ + +#include + +#define MMR_UART(n) _PASTE_UART(n, UART, REVID) +#define UART_BASE MMR_UART(CONFIG_UART_CONSOLE) + +struct bfin_mmr_serial { + u32 revid; + u32 control; + u32 status; + u32 scr; + u32 clock; + u32 emask; + u32 emaskst; + u32 emaskcl; + u32 rbr; + u32 thr; + u32 taip; + u32 tsr; + u32 rsr; + u32 txdiv_cnt; + u32 rxdiv_cnt; +}; +#define uart_lsr_t uint32_t +#define _lsr_read(p) bfin_read(&p->status) +#define _lsr_write(p, v) bfin_write(&p->status, v) + +__attribute__((always_inline)) +static inline void serial_early_do_mach_portmux(char port, int mux_mask, + int mux_func, int port_pin) +{ + switch (port) { + case 'D': + bfin_write_PORTD_MUX((bfin_read_PORTD_MUX() & + ~mux_mask) | mux_func); + bfin_write_PORTD_FER_SET(port_pin); + break; + case 'G': + bfin_write_PORTG_MUX((bfin_read_PORTG_MUX() & + ~mux_mask) | mux_func); + bfin_write_PORTG_FER_SET(port_pin); + break; + } +} + +__attribute__((always_inline)) +static inline void serial_early_do_portmux(void) +{ +#if defined(__ADSPBF60x__) + switch (CONFIG_UART_CONSOLE) { + case 0: + serial_early_do_mach_portmux('D', PORT_x_MUX_7_MASK, + PORT_x_MUX_7_FUNC_2, PD7); /* TX: D; mux 7; func 2; PD7 */ + serial_early_do_mach_portmux('D', PORT_x_MUX_8_MASK, + PORT_x_MUX_8_FUNC_2, PD8); /* RX: D; mux 8; func 2; PD8 */ + break; + case 1: + serial_early_do_mach_portmux('G', PORT_x_MUX_15_MASK, + PORT_x_MUX_15_FUNC_1, PG15); /* TX: G; mux 15; func 1; PG15 */ + serial_early_do_mach_portmux('G', PORT_x_MUX_14_MASK, + PORT_x_MUX_14_FUNC_1, PG14); /* RX: G; mux 14; func 1; PG14 */ + break; + } +#else +# if (P_UART(RX) & P_DEFINED) || (P_UART(TX) & P_DEFINED) +# error "missing portmux logic for UART" +# endif +#endif + SSYNC(); +} + +__attribute__((always_inline)) +static inline int uart_init(uint32_t uart_base) +{ + /* always enable UART to 8-bit mode */ + bfin_write(&pUART->control, UEN | UMOD_UART | WLS_8); + + SSYNC(); + + return 0; +} + +__attribute__((always_inline)) +static inline int serial_early_init(uint32_t uart_base) +{ + /* handle portmux crap on different Blackfins */ + serial_do_portmux(); + + return uart_init(uart_base); +} + +__attribute__((always_inline)) +static inline int serial_early_uninit(uint32_t uart_base) +{ + /* disable the UART by clearing UEN */ + bfin_write(&pUART->control, 0); + + return 0; +} + +__attribute__((always_inline)) +static inline void serial_set_divisor(uint32_t uart_base, uint16_t divisor) +{ + /* Program the divisor to get the baud rate we want */ + bfin_write(&pUART->clock, divisor); + SSYNC(); +} + +__attribute__((always_inline)) +static inline void serial_early_set_baud(uint32_t uart_base, uint32_t baud) +{ + uint16_t divisor = early_division(early_get_uart_clk(), baud * 16); + + /* Program the divisor to get the baud rate we want */ + serial_set_divisor(uart_base, divisor); +} + +__attribute__((always_inline)) +static inline void serial_early_put_div(uint32_t divisor) +{ + uint32_t uart_base = UART_BASE; + bfin_write(&pUART->clock, divisor); +} + +__attribute__((always_inline)) +static inline uint32_t serial_early_get_div(void) +{ + uint32_t uart_base = UART_BASE; + return bfin_read(&pUART->clock); +} + +#endif + +#endif diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile index fbc4e97..442b7ea 100644 --- a/drivers/serial/Makefile +++ b/drivers/serial/Makefile @@ -52,6 +52,7 @@ COBJS-$(CONFIG_XILINX_UARTLITE) += serial_xuartlite.o COBJS-$(CONFIG_SANDBOX_SERIAL) += sandbox.o COBJS-$(CONFIG_SCIF_CONSOLE) += serial_sh.o COBJS-$(CONFIG_ZYNQ_SERIAL) += serial_zynq.o +COBJS-$(CONFIG_BFIN_SERIAL) += serial_bfin.o ifndef CONFIG_SPL_BUILD COBJS-$(CONFIG_USB_TTY) += usbtty.o diff --git a/drivers/serial/serial_bfin.c b/drivers/serial/serial_bfin.c new file mode 100644 index 0000000..0443b84 --- /dev/null +++ b/drivers/serial/serial_bfin.c @@ -0,0 +1,411 @@ +/* + * U-boot - serial.c Blackfin Serial Driver + * + * Copyright (c) 2005-2008 Analog Devices Inc. + * + * Copyright (c) 2003 Bas Vermeulen , + * BuyWays B.V. (www.buyways.nl) + * + * Based heavily on: + * 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. + * + * Licensed under the GPL-2 or later. + */ + +/* Anomaly notes: + * 05000086 - we don't support autobaud + * 05000099 - we only use DR bit, so losing others is not a problem + * 05000100 - we don't use the UART_IIR register + * 05000215 - we poll the uart (no dma/interrupts) + * 05000225 - no workaround possible, but this shouldnt cause errors ... + * 05000230 - we tweak the baud rate calculation slightly + * 05000231 - we always use 1 stop bit + * 05000309 - we always enable the uart before we modify it in anyway + * 05000350 - we always enable the uart regardless of boot mode + * 05000363 - we don't support break signals, so don't generate one + */ + +#include +#include +#include +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +#ifdef CONFIG_UART_CONSOLE + +#ifdef CONFIG_DEBUG_SERIAL +static uart_lsr_t cached_lsr[256]; +static uart_lsr_t cached_rbr[256]; +static 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. This also + * works around anomaly 05000099 at the same time by keeping a cumulative + * tally of all the status bits. + */ +static uart_lsr_t uart_lsr_save; +static uart_lsr_t uart_lsr_read(uint32_t uart_base) +{ + uart_lsr_t lsr = _lsr_read(pUART); + 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(uint32_t uart_base) +{ + uart_lsr_save = 0; + _lsr_write(pUART, -1); +} +#else +/* When debugging is disabled, we only care about the DR bit, so if other + * bits get set/cleared, we don't really care since we don't read them + * anyways (and thus anomaly 05000099 is irrelevant). + */ +static inline uart_lsr_t uart_lsr_read(uint32_t uart_base) +{ + return _lsr_read(pUART); +} +static void uart_lsr_clear(uint32_t uart_base) +{ + _lsr_write(pUART, -1); +} +#endif + +static void uart_putc(uint32_t uart_base, const char c) +{ + /* send a \r for compatibility */ + if (c == '\n') + serial_putc('\r'); + + WATCHDOG_RESET(); + + /* wait for the hardware fifo to clear up */ + while (!(uart_lsr_read(uart_base) & THRE)) + continue; + + /* queue the character for transmission */ + bfin_write(&pUART->thr, c); + SSYNC(); + + WATCHDOG_RESET(); +} + +static int uart_tstc(uint32_t uart_base) +{ + WATCHDOG_RESET(); + return (uart_lsr_read(uart_base) & DR) ? 1 : 0; +} + +static int uart_getc(uint32_t uart_base) +{ + uint16_t uart_rbr_val; + + /* wait for data ! */ + while (!uart_tstc(uart_base)) + continue; + + /* grab the new byte */ + uart_rbr_val = bfin_read(&pUART->rbr); + +#ifdef CONFIG_DEBUG_SERIAL + /* grab & clear the LSR */ + uart_lsr_t uart_lsr_val = uart_lsr_read(uart_base); + + 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)) { + printf("\n[SERIAL ERROR]\n"); + do { + --cache_count; + printf("\t%3zu: 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(uart_base); + + return uart_rbr_val; +} + +#if CONFIG_POST & CONFIG_SYS_POST_UART +# define LOOP(x) x +#else +# define LOOP(x) +#endif + +#if BFIN_UART_HW_VER < 4 + +LOOP( +static void uart_loop(uint32_t uart_base, int state) +{ + u16 mcr; + + /* Drain the TX fifo first so bytes don't come back */ + while (!(uart_lsr_read(uart_base) & TEMT)) + continue; + + mcr = bfin_read(&pUART->mcr); + if (state) + mcr |= LOOP_ENA | MRTS; + else + mcr &= ~(LOOP_ENA | MRTS); + bfin_write(&pUART->mcr, mcr); +} +) + +#else + +LOOP( +static void uart_loop(uint32_t uart_base, int state) +{ + u32 control; + + /* Drain the TX fifo first so bytes don't come back */ + while (!(uart_lsr_read(uart_base) & TEMT)) + continue; + + control = bfin_read(&pUART->control); + if (state) + control |= LOOP_ENA | MRTS; + else + control &= ~(LOOP_ENA | MRTS); + bfin_write(&pUART->control, control); +} +) + +#endif + +static inline void __serial_set_baud(uint32_t uart_base, uint32_t baud) +{ +#ifdef CONFIG_DEBUG_EARLY_SERIAL + serial_early_set_baud(uart_base, baud); +#else + uint16_t divisor = (get_uart_clk() + (baud * 8)) / (baud * 16) + - ANOMALY_05000230; + + /* Program the divisor to get the baud rate we want */ + serial_set_divisor(uart_base, divisor); +#endif +} + +static void uart_puts(uint32_t uart_base, const char *s) +{ + while (*s) + uart_putc(uart_base, *s++); +} + +#define DECL_BFIN_UART(n) \ +static int uart##n##_init(void) \ +{ \ + const unsigned short pins[] = { _P_UART(n, RX), _P_UART(n, TX), 0, }; \ + peripheral_request_list(pins, "bfin-uart"); \ + uart_init(MMR_UART(n)); \ + __serial_set_baud(MMR_UART(n), gd->baudrate); \ + uart_lsr_clear(MMR_UART(n)); \ + return 0; \ +} \ +\ +static int uart##n##_uninit(void) \ +{ \ + return serial_early_uninit(MMR_UART(n)); \ +} \ +\ +static void uart##n##_setbrg(void) \ +{ \ + __serial_set_baud(MMR_UART(n), gd->baudrate); \ +} \ +\ +static int uart##n##_getc(void) \ +{ \ + return uart_getc(MMR_UART(n)); \ +} \ +\ +static int uart##n##_tstc(void) \ +{ \ + return uart_tstc(MMR_UART(n)); \ +} \ +\ +static void uart##n##_putc(const char c) \ +{ \ + uart_putc(MMR_UART(n), c); \ +} \ +\ +static void uart##n##_puts(const char *s) \ +{ \ + uart_puts(MMR_UART(n), s); \ +} \ +\ +LOOP( \ +static void uart##n##_loop(int state) \ +{ \ + uart_loop(MMR_UART(n), state); \ +} \ +) \ +\ +struct serial_device bfin_serial##n##_device = { \ + .name = "bfin_uart"#n, \ + .start = uart##n##_init, \ + .stop = uart##n##_uninit, \ + .setbrg = uart##n##_setbrg, \ + .getc = uart##n##_getc, \ + .tstc = uart##n##_tstc, \ + .putc = uart##n##_putc, \ + .puts = uart##n##_puts, \ + LOOP(.loop = uart##n##_loop) \ +}; + +#ifdef UART0_RBR +DECL_BFIN_UART(0) +#endif +#ifdef UART1_RBR +DECL_BFIN_UART(1) +#endif +#ifdef UART2_RBR +DECL_BFIN_UART(2) +#endif +#ifdef UART3_RBR +DECL_BFIN_UART(3) +#endif + +__weak struct serial_device *default_serial_console(void) +{ +#if CONFIG_UART_CONSOLE == 0 + return &bfin_serial0_device; +#elif CONFIG_UART_CONSOLE == 1 + return &bfin_serial1_device; +#elif CONFIG_UART_CONSOLE == 2 + return &bfin_serial2_device; +#elif CONFIG_UART_CONSOLE == 3 + return &bfin_serial3_device; +#endif +} + +void bfin_serial_initialize(void) +{ +#ifdef UART0_RBR + serial_register(&bfin_serial0_device); +#endif +#ifdef UART1_RBR + serial_register(&bfin_serial1_device); +#endif +#ifdef UART2_RBR + serial_register(&bfin_serial2_device); +#endif +#ifdef UART3_RBR + serial_register(&bfin_serial3_device); +#endif +} + +#ifdef CONFIG_DEBUG_EARLY_SERIAL +inline void uart_early_putc(uint32_t uart_base, const char c) +{ + /* send a \r for compatibility */ + if (c == '\n') + uart_early_putc(uart_base, '\r'); + + /* wait for the hardware fifo to clear up */ + while (!(_lsr_read(pUART) & THRE)) + continue; + + /* queue the character for transmission */ + bfin_write(&pUART->thr, c); + SSYNC(); +} + +void uart_early_puts(const char *s) +{ + while (*s) + uart_early_putc(UART_BASE, *s++); +} + +/* Symbol for our assembly to call. */ +void _serial_early_set_baud(uint32_t baud) +{ + serial_early_set_baud(UART_BASE, baud); +} + +/* Symbol for our assembly to call. */ +void _serial_early_init(void) +{ + serial_early_init(UART_BASE); +} +#endif + +#elif defined(CONFIG_UART_MEM) + +char serial_logbuf[CONFIG_UART_MEM]; +char *serial_logbuf_head = serial_logbuf; + +int serial_mem_init(void) +{ + serial_logbuf_head = serial_logbuf; + return 0; +} + +void serial_mem_setbrg(void) +{ +} + +int serial_mem_tstc(void) +{ + return 0; +} + +int serial_mem_getc(void) +{ + return 0; +} + +void serial_mem_putc(const char c) +{ + *serial_logbuf_head = c; + if (++serial_logbuf_head == serial_logbuf + CONFIG_UART_MEM) + serial_logbuf_head = serial_logbuf; +} + +void serial_mem_puts(const char *s) +{ + while (*s) + serial_putc(*s++); +} + +struct serial_device bfin_serial_mem_device = { + .name = "bfin_uart_mem", + .start = serial_mem_init, + .setbrg = serial_mem_setbrg, + .getc = serial_mem_getc, + .tstc = serial_mem_tstc, + .putc = serial_mem_putc, + .puts = serial_mem_puts, +}; + + +__weak struct serial_device *default_serial_console(void) +{ + return &bfin_serial_mem_device; +} + +void bfin_serial_initialize(void) +{ + serial_register(&bfin_serial_mem_device); +} +#endif /* CONFIG_UART_MEM */ diff --git a/include/configs/bfin_adi_common.h b/include/configs/bfin_adi_common.h index 0bcccf8..c751dd7 100644 --- a/include/configs/bfin_adi_common.h +++ b/include/configs/bfin_adi_common.h @@ -111,6 +111,9 @@ #ifndef CONFIG_BAUDRATE # define CONFIG_BAUDRATE 57600 #endif +#ifdef CONFIG_UART_CONSOLE +# define CONFIG_BFIN_SERIAL +#endif /* * Debug Settings -- cgit v0.10.2 From 85f2f8f9adb13535cefcbd4987d2e8e5a978ccd4 Mon Sep 17 00:00:00 2001 From: Sonic Zhang Date: Thu, 11 Apr 2013 17:42:38 +0800 Subject: blackfin: Add comments for watchdog event initialization. - Add comments for watchdog event initialization. - Make sure the writting operation to MMRs are finished. Signed-off-by: Sonic Zhang diff --git a/arch/blackfin/cpu/initcode.c b/arch/blackfin/cpu/initcode.c index 5fc06e1..ffaf101 100644 --- a/arch/blackfin/cpu/initcode.c +++ b/arch/blackfin/cpu/initcode.c @@ -458,15 +458,23 @@ program_early_devices(ADI_BOOT_DATA *bs, uint *sdivB, uint *divB, uint *vcoB) if (CONFIG_BFIN_BOOT_MODE != BFIN_BOOT_BYPASS) { serial_putc('e'); #ifdef __ADSPBF60x__ + /* Reset system event controller */ bfin_write_SEC_GCTL(0x2); + bfin_write_SEC_CCTL(0x2); SSYNC(); + + /* Enable fault event input and system reset action in fault + * controller. Route watchdog timeout event to fault interface. + */ bfin_write_SEC_FCTL(0xc1); + /* Enable watchdog interrupt source */ bfin_write_SEC_SCTL(2, bfin_read_SEC_SCTL(2) | 0x6); - - bfin_write_SEC_CCTL(0x2); SSYNC(); + + /* Enable system event controller */ bfin_write_SEC_GCTL(0x1); bfin_write_SEC_CCTL(0x1); + SSYNC(); #endif bfin_write_WDOG_CTL(WDDIS); SSYNC(); -- cgit v0.10.2 From e6c5ab28c79a40f9f5e525d9faed7df4b89ff168 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Fri, 19 Apr 2013 12:17:42 +0800 Subject: blackfin: The buf variable in bfin_mac.c is not used and produces warning, Signed-off-by: Marek Vasut Signed-off-by: Sonic Zhang diff --git a/drivers/net/bfin_mac.c b/drivers/net/bfin_mac.c index c63398e..0ffd59d 100644 --- a/drivers/net/bfin_mac.c +++ b/drivers/net/bfin_mac.c @@ -122,8 +122,6 @@ static int bfin_EMAC_send(struct eth_device *dev, void *packet, int length) { int i; int result = 0; - unsigned int *buf; - buf = (unsigned int *)packet; if (length <= 0) { printf("Ethernet: bad packet size: %d\n", length); -- cgit v0.10.2 From da34aae5fba36c1f1989fdd41fffa723f300eaad Mon Sep 17 00:00:00 2001 From: Sonic Zhang Date: Thu, 2 May 2013 13:46:21 +0800 Subject: bfin: Move gpio support for bf54x and bf60x into the generic driver folder. The gpio spec for bf54x and bf60x differ a lot from the old gpio driver for bf5xx. A lot of machine macros are used to accomodate both code in one gpio driver. This patch split the old gpio driver and move new gpio2 support to the generic gpio driver folder. - To enable gpio2 driver, macro CONFIG_ADI_GPIO2 should be defined in the board's config header file. - The gpio2 driver supports bf54x, bf60x and future ADI processors, while the older gpio driver supports bf50x, bf51x, bf52x, bf53x and bf561. - All blackfin specific gpio function names are replaced by the generic gpio APIs. Signed-off-by: Sonic Zhang diff --git a/arch/blackfin/cpu/Makefile b/arch/blackfin/cpu/Makefile index 929fc8b..1421cb2 100644 --- a/arch/blackfin/cpu/Makefile +++ b/arch/blackfin/cpu/Makefile @@ -18,7 +18,7 @@ CEXTRA := initcode.o SEXTRA := start.o SOBJS := interrupt.o cache.o COBJS-y += cpu.o -COBJS-y += gpio.o +COBJS-$(CONFIG_ADI_GPIO1) += gpio.o COBJS-y += interrupts.o COBJS-$(CONFIG_JTAG_CONSOLE) += jtag-console.o COBJS-y += os_log.o diff --git a/arch/blackfin/cpu/gpio.c b/arch/blackfin/cpu/gpio.c index f684be5..f74a0b7 100644 --- a/arch/blackfin/cpu/gpio.c +++ b/arch/blackfin/cpu/gpio.c @@ -1,5 +1,6 @@ /* - * GPIO Abstraction Layer + * ADI GPIO1 Abstraction Layer + * Support BF50x, BF51x, BF52x, BF53x and BF561 only. * * Copyright 2006-2010 Analog Devices Inc. * @@ -55,25 +56,6 @@ static struct gpio_port_t * const gpio_array[] = { (struct gpio_port_t *) FIO0_FLAG_D, (struct gpio_port_t *) FIO1_FLAG_D, (struct gpio_port_t *) FIO2_FLAG_D, -#elif defined(CONFIG_BF54x) - (struct gpio_port_t *)PORTA_FER, - (struct gpio_port_t *)PORTB_FER, - (struct gpio_port_t *)PORTC_FER, - (struct gpio_port_t *)PORTD_FER, - (struct gpio_port_t *)PORTE_FER, - (struct gpio_port_t *)PORTF_FER, - (struct gpio_port_t *)PORTG_FER, - (struct gpio_port_t *)PORTH_FER, - (struct gpio_port_t *)PORTI_FER, - (struct gpio_port_t *)PORTJ_FER, -#elif defined(CONFIG_BF60x) - (struct gpio_port_t *)PORTA_FER, - (struct gpio_port_t *)PORTB_FER, - (struct gpio_port_t *)PORTC_FER, - (struct gpio_port_t *)PORTD_FER, - (struct gpio_port_t *)PORTE_FER, - (struct gpio_port_t *)PORTF_FER, - (struct gpio_port_t *)PORTG_FER, #else # error no gpio arrays defined #endif @@ -174,12 +156,6 @@ DECLARE_RESERVED_MAP(peri, gpio_bank(MAX_RESOURCES)); inline int check_gpio(unsigned gpio) { -#if defined(CONFIG_BF54x) - if (gpio == GPIO_PB15 || gpio == GPIO_PC14 || gpio == GPIO_PC15 - || gpio == GPIO_PH14 || gpio == GPIO_PH15 - || gpio == GPIO_PJ14 || gpio == GPIO_PJ15) - return -EINVAL; -#endif if (gpio >= MAX_BLACKFIN_GPIOS) return -EINVAL; return 0; @@ -218,18 +194,6 @@ static void port_setup(unsigned gpio, unsigned short usage) else *port_fer[gpio_bank(gpio)] |= gpio_bit(gpio); SSYNC(); -#elif defined(CONFIG_BF54x) - if (usage == GPIO_USAGE) - gpio_array[gpio_bank(gpio)]->port_fer &= ~gpio_bit(gpio); - else - gpio_array[gpio_bank(gpio)]->port_fer |= gpio_bit(gpio); - SSYNC(); -#elif defined(CONFIG_BF60x) - if (usage == GPIO_USAGE) - gpio_array[gpio_bank(gpio)]->port_fer_clear = gpio_bit(gpio); - else - gpio_array[gpio_bank(gpio)]->port_fer_set = gpio_bit(gpio); - SSYNC(); #endif } @@ -304,30 +268,6 @@ static void portmux_setup(unsigned short per) } } } -#elif defined(CONFIG_BF54x) || defined(CONFIG_BF60x) -inline void portmux_setup(unsigned short per) -{ - u32 pmux; - u16 ident = P_IDENT(per); - u16 function = P_FUNCT2MUX(per); - - pmux = gpio_array[gpio_bank(ident)]->port_mux; - - pmux &= ~(0x3 << (2 * gpio_sub_n(ident))); - pmux |= (function & 0x3) << (2 * gpio_sub_n(ident)); - - gpio_array[gpio_bank(ident)]->port_mux = pmux; -} - -inline u16 get_portmux(unsigned short per) -{ - u32 pmux; - u16 ident = P_IDENT(per); - - pmux = gpio_array[gpio_bank(ident)]->port_mux; - - return (pmux >> (2 * gpio_sub_n(ident)) & 0x3); -} #elif defined(CONFIG_BF52x) || defined(CONFIG_BF51x) inline void portmux_setup(unsigned short per) { @@ -344,7 +284,6 @@ inline void portmux_setup(unsigned short per) # define portmux_setup(...) do { } while (0) #endif -#if !defined(CONFIG_BF54x) && !defined(CONFIG_BF60x) /*********************************************************** * * FUNCTIONS: Blackfin General Purpose Ports Access Functions @@ -491,15 +430,6 @@ GET_GPIO_P(both) GET_GPIO_P(maska) GET_GPIO_P(maskb) -#else /* CONFIG_BF54x */ - -unsigned short get_gpio_dir(unsigned gpio) -{ - return (0x01 & (gpio_array[gpio_bank(gpio)]->dir_clear >> gpio_sub_n(gpio))); -} - -#endif /* CONFIG_BF54x */ - /*********************************************************** * * FUNCTIONS: Blackfin Peripheral Resource Allocation @@ -548,11 +478,7 @@ int peripheral_request(unsigned short per, const char *label) * be requested and used by several drivers */ -#if defined(CONFIG_BF54x) || defined(CONFIG_BF60x) - if (!((per & P_MAYSHARE) && get_portmux(per) == P_FUNCT2MUX(per))) { -#else if (!(per & P_MAYSHARE)) { -#endif /* * Allow that the identical pin function can * be requested from the same driver twice @@ -641,7 +567,7 @@ void peripheral_free_list(const unsigned short per[]) * MODIFICATION HISTORY : **************************************************************/ -int bfin_gpio_request(unsigned gpio, const char *label) +int gpio_request(unsigned gpio, const char *label) { if (check_gpio(gpio) < 0) return -EINVAL; @@ -665,11 +591,9 @@ int bfin_gpio_request(unsigned gpio, const char *label) gpio, get_label(gpio)); return -EBUSY; } -#if !defined(CONFIG_BF54x) && !defined(CONFIG_BF60x) else { /* Reset POLAR setting when acquiring a gpio for the first time */ set_gpio_polar(gpio, 0); } -#endif reserve(gpio, gpio); set_label(gpio, label); @@ -679,27 +603,27 @@ int bfin_gpio_request(unsigned gpio, const char *label) return 0; } -#ifdef CONFIG_BFIN_GPIO_TRACK -void bfin_gpio_free(unsigned gpio) +int gpio_free(unsigned gpio) { if (check_gpio(gpio) < 0) - return; + return -1; if (unlikely(!is_reserved(gpio, gpio, 0))) { gpio_error(gpio); - return; + return -1; } unreserve(gpio, gpio); set_label(gpio, "free"); + + return 0; } -#endif -#ifdef BFIN_SPECIAL_GPIO_BANKS +#ifdef ADI_SPECIAL_GPIO_BANKS DECLARE_RESERVED_MAP(special_gpio, gpio_bank(MAX_RESOURCES)); -int bfin_special_gpio_request(unsigned gpio, const char *label) +int special_gpio_request(unsigned gpio, const char *label) { /* * Allow that the identical GPIO can @@ -731,7 +655,7 @@ int bfin_special_gpio_request(unsigned gpio, const char *label) return 0; } -void bfin_special_gpio_free(unsigned gpio) +void special_gpio_free(unsigned gpio) { if (unlikely(!is_reserved(special_gpio, gpio, 0))) { gpio_error(gpio); @@ -744,21 +668,13 @@ void bfin_special_gpio_free(unsigned gpio) } #endif -static inline void __bfin_gpio_direction_input(unsigned gpio) +static inline void __gpio_direction_input(unsigned gpio) { -#if defined(CONFIG_BF54x) || defined(CONFIG_BF60x) - gpio_array[gpio_bank(gpio)]->dir_clear = gpio_bit(gpio); -#else gpio_array[gpio_bank(gpio)]->dir &= ~gpio_bit(gpio); -#endif -#if defined(CONFIG_BF60x) - gpio_array[gpio_bank(gpio)]->inen_set = gpio_bit(gpio); -#else gpio_array[gpio_bank(gpio)]->inen |= gpio_bit(gpio); -#endif } -int bfin_gpio_direction_input(unsigned gpio) +int gpio_direction_input(unsigned gpio) { unsigned long flags; @@ -768,31 +684,24 @@ int bfin_gpio_direction_input(unsigned gpio) } local_irq_save(flags); - __bfin_gpio_direction_input(gpio); + __gpio_direction_input(gpio); AWA_DUMMY_READ(inen); local_irq_restore(flags); return 0; } -void bfin_gpio_toggle_value(unsigned gpio) -{ -#ifdef CONFIG_BF54x - gpio_set_value(gpio, !gpio_get_value(gpio)); -#else - gpio_array[gpio_bank(gpio)]->toggle = gpio_bit(gpio); -#endif -} - -void bfin_gpio_set_value(unsigned gpio, int arg) +int gpio_set_value(unsigned gpio, int arg) { if (arg) gpio_array[gpio_bank(gpio)]->data_set = gpio_bit(gpio); else gpio_array[gpio_bank(gpio)]->data_clear = gpio_bit(gpio); + + return 0; } -int bfin_gpio_direction_output(unsigned gpio, int value) +int gpio_direction_output(unsigned gpio, int value) { unsigned long flags; @@ -803,17 +712,9 @@ int bfin_gpio_direction_output(unsigned gpio, int value) local_irq_save(flags); -#if defined(CONFIG_BF60x) - gpio_array[gpio_bank(gpio)]->inen_clear = gpio_bit(gpio); -#else gpio_array[gpio_bank(gpio)]->inen &= ~gpio_bit(gpio); -#endif gpio_set_value(gpio, value); -#if defined(CONFIG_BF54x) || defined(CONFIG_BF60x) - gpio_array[gpio_bank(gpio)]->dir_set = gpio_bit(gpio); -#else gpio_array[gpio_bank(gpio)]->dir |= gpio_bit(gpio); -#endif AWA_DUMMY_READ(dir); local_irq_restore(flags); @@ -821,11 +722,8 @@ int bfin_gpio_direction_output(unsigned gpio, int value) return 0; } -int bfin_gpio_get_value(unsigned gpio) +int gpio_get_value(unsigned gpio) { -#if defined(CONFIG_BF54x) || defined(CONFIG_BF60x) - return (1 & (gpio_array[gpio_bank(gpio)]->data >> gpio_sub_n(gpio))); -#else unsigned long flags; if (unlikely(get_gpio_edge(gpio))) { @@ -838,7 +736,6 @@ int bfin_gpio_get_value(unsigned gpio) return ret; } else return get_gpio_data(gpio); -#endif } /* If we are booting from SPI and our board lacks a strong enough pull up, @@ -860,8 +757,7 @@ void bfin_reset_boot_spi_cs(unsigned short pin) udelay(1); } -#ifdef CONFIG_BFIN_GPIO_TRACK -void bfin_gpio_labels(void) +void gpio_labels(void) { int c, gpio; @@ -877,4 +773,3 @@ void bfin_gpio_labels(void) continue; } } -#endif diff --git a/arch/blackfin/include/asm/gpio.h b/arch/blackfin/include/asm/gpio.h index 05131b5..58a6191 100644 --- a/arch/blackfin/include/asm/gpio.h +++ b/arch/blackfin/include/asm/gpio.h @@ -7,6 +7,8 @@ #ifndef __ARCH_BLACKFIN_GPIO_H__ #define __ARCH_BLACKFIN_GPIO_H__ +#include + #define gpio_bank(x) ((x) >> 4) #define gpio_bit(x) (1<<((x) & 0xF)) #define gpio_sub_n(x) ((x) & 0xF) @@ -65,10 +67,11 @@ #define PERIPHERAL_USAGE 1 #define GPIO_USAGE 0 +#define MAX_GPIOS MAX_BLACKFIN_GPIOS #ifndef __ASSEMBLY__ -#if !defined(CONFIG_BF54x) && !defined(CONFIG_BF60x) +#ifdef CONFIG_ADI_GPIO1 void set_gpio_dir(unsigned, unsigned short); void set_gpio_inen(unsigned, unsigned short); void set_gpio_polar(unsigned, unsigned short); @@ -140,61 +143,16 @@ struct gpio_port_t { }; #endif -#ifdef CONFIG_BFIN_GPIO_TRACK -void bfin_gpio_labels(void); -void bfin_gpio_free(unsigned gpio); -#else -#define bfin_gpio_labels() -#define bfin_gpio_free(gpio) -#define bfin_gpio_request(gpio, label) bfin_gpio_request(gpio) -#define bfin_special_gpio_request(gpio, label) bfin_special_gpio_request(gpio) -#endif - -#ifdef BFIN_SPECIAL_GPIO_BANKS -void bfin_special_gpio_free(unsigned gpio); -int bfin_special_gpio_request(unsigned gpio, const char *label); +#ifdef ADI_SPECIAL_GPIO_BANKS +void special_gpio_free(unsigned gpio); +int special_gpio_request(unsigned gpio, const char *label); #endif -int bfin_gpio_request(unsigned gpio, const char *label); -int bfin_gpio_direction_input(unsigned gpio); -int bfin_gpio_direction_output(unsigned gpio, int value); -int bfin_gpio_get_value(unsigned gpio); -void bfin_gpio_set_value(unsigned gpio, int value); -void bfin_gpio_toggle_value(unsigned gpio); - -static inline int gpio_request(unsigned gpio, const char *label) -{ - return bfin_gpio_request(gpio, label); -} - -static inline void gpio_free(unsigned gpio) -{ - return bfin_gpio_free(gpio); -} - -static inline int gpio_direction_input(unsigned gpio) -{ - return bfin_gpio_direction_input(gpio); -} - -static inline int gpio_direction_output(unsigned gpio, int value) -{ - return bfin_gpio_direction_output(gpio, value); -} - -static inline int gpio_get_value(unsigned gpio) -{ - return bfin_gpio_get_value(gpio); -} - -static inline void gpio_set_value(unsigned gpio, int value) -{ - return bfin_gpio_set_value(gpio, value); -} +void gpio_labels(void); static inline int gpio_is_valid(int number) { - return number >= 0 && number < MAX_BLACKFIN_GPIOS; + return number >= 0 && number < MAX_GPIOS; } #include @@ -248,7 +206,7 @@ static inline int name_to_gpio(const char *name) } #define name_to_gpio(n) name_to_gpio(n) -#define gpio_status() bfin_gpio_labels() +#define gpio_status() gpio_labels() #endif /* __ASSEMBLY__ */ diff --git a/arch/blackfin/include/asm/portmux.h b/arch/blackfin/include/asm/portmux.h index 300ef44..003694b 100644 --- a/arch/blackfin/include/asm/portmux.h +++ b/arch/blackfin/include/asm/portmux.h @@ -17,11 +17,6 @@ #define P_MAYSHARE 0x2000 #define P_DONTCARE 0x1000 -#ifndef CONFIG_BFIN_GPIO_TRACK -#define peripheral_request(per, label) peripheral_request(per) -#define peripheral_request_list(per, label) peripheral_request_list(per) -#endif - #ifndef __ASSEMBLY__ int peripheral_request(unsigned short per, const char *label); diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 830e8e6..f77c1ec 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -48,6 +48,7 @@ COBJS-$(CONFIG_DB8500_GPIO) += db8500_gpio.o COBJS-$(CONFIG_BCM2835_GPIO) += bcm2835_gpio.o COBJS-$(CONFIG_S3C2440_GPIO) += s3c2440_gpio.o COBJS-$(CONFIG_XILINX_GPIO) += xilinx_gpio.o +COBJS-$(CONFIG_ADI_GPIO2) += adi_gpio2.o COBJS := $(COBJS-y) SRCS := $(COBJS:.o=.c) diff --git a/drivers/gpio/adi_gpio2.c b/drivers/gpio/adi_gpio2.c new file mode 100644 index 0000000..7a034eb --- /dev/null +++ b/drivers/gpio/adi_gpio2.c @@ -0,0 +1,440 @@ +/* + * ADI GPIO2 Abstraction Layer + * Support BF54x, BF60x and future processors. + * + * Copyright 2008-2013 Analog Devices Inc. + * + * Licensed under the GPL-2 or later + */ + +#include +#include +#include +#include + +static struct gpio_port_t * const gpio_array[] = { + (struct gpio_port_t *)PORTA_FER, + (struct gpio_port_t *)PORTB_FER, + (struct gpio_port_t *)PORTC_FER, + (struct gpio_port_t *)PORTD_FER, + (struct gpio_port_t *)PORTE_FER, + (struct gpio_port_t *)PORTF_FER, + (struct gpio_port_t *)PORTG_FER, +#if defined(CONFIG_BF54x) + (struct gpio_port_t *)PORTH_FER, + (struct gpio_port_t *)PORTI_FER, + (struct gpio_port_t *)PORTJ_FER, +#endif +}; + +#define RESOURCE_LABEL_SIZE 16 + +static struct str_ident { + char name[RESOURCE_LABEL_SIZE]; +} str_ident[MAX_RESOURCES]; + +static void gpio_error(unsigned gpio) +{ + printf("adi_gpio2: GPIO %d wasn't requested!\n", gpio); +} + +static void set_label(unsigned short ident, const char *label) +{ + if (label) { + strncpy(str_ident[ident].name, label, + RESOURCE_LABEL_SIZE); + str_ident[ident].name[RESOURCE_LABEL_SIZE - 1] = 0; + } +} + +static char *get_label(unsigned short ident) +{ + return *str_ident[ident].name ? str_ident[ident].name : "UNKNOWN"; +} + +static int cmp_label(unsigned short ident, const char *label) +{ + if (label == NULL) + printf("adi_gpio2: please provide none-null label\n"); + + if (label) + return strcmp(str_ident[ident].name, label); + else + return -EINVAL; +} + +#define map_entry(m, i) reserved_##m##_map[gpio_bank(i)] +#define is_reserved(m, i, e) (map_entry(m, i) & gpio_bit(i)) +#define reserve(m, i) (map_entry(m, i) |= gpio_bit(i)) +#define unreserve(m, i) (map_entry(m, i) &= ~gpio_bit(i)) +#define DECLARE_RESERVED_MAP(m, c) unsigned short reserved_##m##_map[c] + +static DECLARE_RESERVED_MAP(gpio, GPIO_BANK_NUM); +static DECLARE_RESERVED_MAP(peri, gpio_bank(MAX_RESOURCES)); + +inline int check_gpio(unsigned gpio) +{ +#if defined(CONFIG_BF54x) + if (gpio == GPIO_PB15 || gpio == GPIO_PC14 || gpio == GPIO_PC15 || + gpio == GPIO_PH14 || gpio == GPIO_PH15 || + gpio == GPIO_PJ14 || gpio == GPIO_PJ15) + return -EINVAL; +#endif + if (gpio >= MAX_GPIOS) + return -EINVAL; + return 0; +} + +static void port_setup(unsigned gpio, unsigned short usage) +{ +#if defined(CONFIG_BF54x) + if (usage == GPIO_USAGE) + gpio_array[gpio_bank(gpio)]->port_fer &= ~gpio_bit(gpio); + else + gpio_array[gpio_bank(gpio)]->port_fer |= gpio_bit(gpio); +#else + if (usage == GPIO_USAGE) + gpio_array[gpio_bank(gpio)]->port_fer_clear = gpio_bit(gpio); + else + gpio_array[gpio_bank(gpio)]->port_fer_set = gpio_bit(gpio); +#endif + SSYNC(); +} + +inline void portmux_setup(unsigned short per) +{ + u32 pmux; + u16 ident = P_IDENT(per); + u16 function = P_FUNCT2MUX(per); + + pmux = gpio_array[gpio_bank(ident)]->port_mux; + + pmux &= ~(0x3 << (2 * gpio_sub_n(ident))); + pmux |= (function & 0x3) << (2 * gpio_sub_n(ident)); + + gpio_array[gpio_bank(ident)]->port_mux = pmux; +} + +inline u16 get_portmux(unsigned short per) +{ + u32 pmux; + u16 ident = P_IDENT(per); + + pmux = gpio_array[gpio_bank(ident)]->port_mux; + + return pmux >> (2 * gpio_sub_n(ident)) & 0x3; +} + +unsigned short get_gpio_dir(unsigned gpio) +{ + return 0x01 & + (gpio_array[gpio_bank(gpio)]->dir_clear >> gpio_sub_n(gpio)); +} + +/*********************************************************** +* +* FUNCTIONS: Peripheral Resource Allocation +* and PortMux Setup +* +* INPUTS/OUTPUTS: +* per Peripheral Identifier +* label String +* +* DESCRIPTION: Peripheral Resource Allocation and Setup API +**************************************************************/ + +int peripheral_request(unsigned short per, const char *label) +{ + unsigned short ident = P_IDENT(per); + + /* + * Don't cares are pins with only one dedicated function + */ + + if (per & P_DONTCARE) + return 0; + + if (!(per & P_DEFINED)) + return -ENODEV; + + BUG_ON(ident >= MAX_RESOURCES); + + /* If a pin can be muxed as either GPIO or peripheral, make + * sure it is not already a GPIO pin when we request it. + */ + if (unlikely(!check_gpio(ident) && is_reserved(gpio, ident, 1))) { + printf("%s: Peripheral %d is already reserved as GPIO by %s!\n", + __func__, ident, get_label(ident)); + return -EBUSY; + } + + if (unlikely(is_reserved(peri, ident, 1))) { + /* + * Pin functions like AMC address strobes my + * be requested and used by several drivers + */ + + if (!((per & P_MAYSHARE) && + get_portmux(per) == P_FUNCT2MUX(per))) { + /* + * Allow that the identical pin function can + * be requested from the same driver twice + */ + + if (cmp_label(ident, label) == 0) + goto anyway; + + printf("%s: Peripheral %d function %d is already " + "reserved by %s!\n", __func__, ident, + P_FUNCT2MUX(per), get_label(ident)); + return -EBUSY; + } + } + + anyway: + reserve(peri, ident); + + portmux_setup(per); + port_setup(ident, PERIPHERAL_USAGE); + + set_label(ident, label); + + return 0; +} + +int peripheral_request_list(const unsigned short per[], const char *label) +{ + u16 cnt; + int ret; + + for (cnt = 0; per[cnt] != 0; cnt++) { + ret = peripheral_request(per[cnt], label); + + if (ret < 0) { + for (; cnt > 0; cnt--) + peripheral_free(per[cnt - 1]); + + return ret; + } + } + + return 0; +} + +void peripheral_free(unsigned short per) +{ + unsigned short ident = P_IDENT(per); + + if (per & P_DONTCARE) + return; + + if (!(per & P_DEFINED)) + return; + + if (unlikely(!is_reserved(peri, ident, 0))) + return; + + if (!(per & P_MAYSHARE)) + port_setup(ident, GPIO_USAGE); + + unreserve(peri, ident); + + set_label(ident, "free"); +} + +void peripheral_free_list(const unsigned short per[]) +{ + u16 cnt; + for (cnt = 0; per[cnt] != 0; cnt++) + peripheral_free(per[cnt]); +} + +/*********************************************************** +* +* FUNCTIONS: GPIO Driver +* +* INPUTS/OUTPUTS: +* gpio PIO Number between 0 and MAX_GPIOS +* label String +* +* DESCRIPTION: GPIO Driver API +**************************************************************/ + +int gpio_request(unsigned gpio, const char *label) +{ + if (check_gpio(gpio) < 0) + return -EINVAL; + + /* + * Allow that the identical GPIO can + * be requested from the same driver twice + * Do nothing and return - + */ + + if (cmp_label(gpio, label) == 0) + return 0; + + if (unlikely(is_reserved(gpio, gpio, 1))) { + printf("adi_gpio2: GPIO %d is already reserved by %s!\n", + gpio, get_label(gpio)); + return -EBUSY; + } + if (unlikely(is_reserved(peri, gpio, 1))) { + printf("adi_gpio2: GPIO %d is already reserved as Peripheral " + "by %s!\n", gpio, get_label(gpio)); + return -EBUSY; + } + + reserve(gpio, gpio); + set_label(gpio, label); + + port_setup(gpio, GPIO_USAGE); + + return 0; +} + +int gpio_free(unsigned gpio) +{ + if (check_gpio(gpio) < 0) + return -1; + + if (unlikely(!is_reserved(gpio, gpio, 0))) { + gpio_error(gpio); + return -1; + } + + unreserve(gpio, gpio); + + set_label(gpio, "free"); + + return 0; +} + +#ifdef ADI_SPECIAL_GPIO_BANKS +static DECLARE_RESERVED_MAP(special_gpio, gpio_bank(MAX_RESOURCES)); + +int special_gpio_request(unsigned gpio, const char *label) +{ + /* + * Allow that the identical GPIO can + * be requested from the same driver twice + * Do nothing and return - + */ + + if (cmp_label(gpio, label) == 0) + return 0; + + if (unlikely(is_reserved(special_gpio, gpio, 1))) { + printf("adi_gpio2: GPIO %d is already reserved by %s!\n", + gpio, get_label(gpio)); + return -EBUSY; + } + if (unlikely(is_reserved(peri, gpio, 1))) { + printf("adi_gpio2: GPIO %d is already reserved as Peripheral " + "by %s!\n", gpio, get_label(gpio)); + + return -EBUSY; + } + + reserve(special_gpio, gpio); + reserve(peri, gpio); + + set_label(gpio, label); + port_setup(gpio, GPIO_USAGE); + + return 0; +} + +void special_gpio_free(unsigned gpio) +{ + if (unlikely(!is_reserved(special_gpio, gpio, 0))) { + gpio_error(gpio); + return; + } + + reserve(special_gpio, gpio); + reserve(peri, gpio); + set_label(gpio, "free"); +} +#endif + +static inline void __gpio_direction_input(unsigned gpio) +{ + gpio_array[gpio_bank(gpio)]->dir_clear = gpio_bit(gpio); +#if defined(CONFIG_BF54x) + gpio_array[gpio_bank(gpio)]->inen |= gpio_bit(gpio); +#else + gpio_array[gpio_bank(gpio)]->inen_set = gpio_bit(gpio); +#endif +} + +int gpio_direction_input(unsigned gpio) +{ + unsigned long flags; + + if (!is_reserved(gpio, gpio, 0)) { + gpio_error(gpio); + return -EINVAL; + } + + local_irq_save(flags); + __gpio_direction_input(gpio); + local_irq_restore(flags); + + return 0; +} + +int gpio_set_value(unsigned gpio, int arg) +{ + if (arg) + gpio_array[gpio_bank(gpio)]->data_set = gpio_bit(gpio); + else + gpio_array[gpio_bank(gpio)]->data_clear = gpio_bit(gpio); + + return 0; +} + +int gpio_direction_output(unsigned gpio, int value) +{ + unsigned long flags; + + if (!is_reserved(gpio, gpio, 0)) { + gpio_error(gpio); + return -EINVAL; + } + + local_irq_save(flags); + +#if defined(CONFIG_BF54x) + gpio_array[gpio_bank(gpio)]->inen &= ~gpio_bit(gpio); +#else + gpio_array[gpio_bank(gpio)]->inen_clear = gpio_bit(gpio); +#endif + gpio_set_value(gpio, value); + gpio_array[gpio_bank(gpio)]->dir_set = gpio_bit(gpio); + + local_irq_restore(flags); + + return 0; +} + +int gpio_get_value(unsigned gpio) +{ + return 1 & (gpio_array[gpio_bank(gpio)]->data >> gpio_sub_n(gpio)); +} + +void gpio_labels(void) +{ + int c, gpio; + + for (c = 0; c < MAX_RESOURCES; c++) { + gpio = is_reserved(gpio, c, 1); + if (!check_gpio(c) && gpio) + printf("GPIO_%d:\t%s\tGPIO %s\n", c, get_label(c), + get_gpio_dir(c) ? "OUTPUT" : "INPUT"); + else if (is_reserved(peri, c, 1)) + printf("GPIO_%d:\t%s\tPeripheral\n", c, get_label(c)); + else + continue; + } +} diff --git a/include/configs/bf548-ezkit.h b/include/configs/bf548-ezkit.h index 7ed0ea9..da5f029 100644 --- a/include/configs/bf548-ezkit.h +++ b/include/configs/bf548-ezkit.h @@ -182,6 +182,8 @@ #define CONFIG_UART_CONSOLE 1 #define CONFIG_BFIN_SPI_IMG_SIZE 0x50000 +#define CONFIG_ADI_GPIO2 + #undef CONFIG_VIDEO #ifdef CONFIG_VIDEO #define EASYLOGO_HEADER < asm/bfin_logo_230x230_gzip.h > diff --git a/include/configs/bf609-ezkit.h b/include/configs/bf609-ezkit.h index e7b02a5..1a43e1b 100644 --- a/include/configs/bf609-ezkit.h +++ b/include/configs/bf609-ezkit.h @@ -149,6 +149,8 @@ #define CONFIG_SYS_MEMTEST_END (CONFIG_STACKBASE - 20*1024*1024 + 4) #define CONFIG_BFIN_SOFT_SWITCH +#define CONFIG_ADI_GPIO2 + #if 0 #define CONFIG_UART_MEM 1024 #undef CONFIG_UART_CONSOLE diff --git a/include/configs/bfin_adi_common.h b/include/configs/bfin_adi_common.h index c751dd7..e1a6fe3 100644 --- a/include/configs/bfin_adi_common.h +++ b/include/configs/bfin_adi_common.h @@ -323,5 +323,7 @@ # define CONFIG_WATCHDOG_TIMEOUT_MSECS 5000 # endif #endif - +#ifndef CONFIG_ADI_GPIO2 +# define CONFIG_ADI_GPIO1 +#endif #endif -- cgit v0.10.2