diff options
40 files changed, 1889 insertions, 1129 deletions
diff --git a/arch/blackfin/config.mk b/arch/blackfin/config.mk index 7b17b75..584b38b 100644 --- a/arch/blackfin/config.mk +++ b/arch/blackfin/config.mk @@ -20,6 +20,9 @@ CONFIG_BFIN_CPU := $(strip $(CONFIG_BFIN_CPU:"%"=%)) endif CONFIG_BFIN_BOOT_MODE := $(strip $(CONFIG_BFIN_BOOT_MODE:"%"=%)) +# Support generic board on Blackfin +__HAVE_ARCH_GENERIC_BOARD := y + PLATFORM_RELFLAGS += -ffixed-P3 -fomit-frame-pointer -mno-fdpic LDFLAGS_FINAL += --gc-sections diff --git a/arch/blackfin/cpu/cpu.c b/arch/blackfin/cpu/cpu.c index 2409c30..b7f1188 100644 --- a/arch/blackfin/cpu/cpu.c +++ b/arch/blackfin/cpu/cpu.c @@ -11,17 +11,22 @@ #include <common.h> #include <command.h> +#include <serial.h> +#include <version.h> +#include <i2c.h> + #include <asm/blackfin.h> #include <asm/cplb.h> +#include <asm/clock.h> #include <asm/mach-common/bits/core.h> #include <asm/mach-common/bits/ebiu.h> #include <asm/mach-common/bits/trace.h> -#include <asm/serial.h> #include "cpu.h" #include "initcode.h" ulong bfin_poweron_retx; +DECLARE_GLOBAL_DATA_PTR; #if defined(CONFIG_CORE1_RUN) && defined(COREB_L1_CODE_START) void bfin_core1_start(void) @@ -48,6 +53,252 @@ void bfin_core1_start(void) } #endif +__attribute__((always_inline)) +static inline void serial_early_puts(const char *s) +{ +#ifdef CONFIG_DEBUG_EARLY_SERIAL + serial_puts("Early: "); + serial_puts(s); +#endif +} + +static int global_board_data_init(void) +{ +#ifndef CONFIG_SYS_GBL_DATA_ADDR +# define CONFIG_SYS_GBL_DATA_ADDR 0 +#endif +#ifndef CONFIG_SYS_BD_INFO_ADDR +# define CONFIG_SYS_BD_INFO_ADDR 0 +#endif + + bd_t *bd; + + if (CONFIG_SYS_GBL_DATA_ADDR) { + gd = (gd_t *)(CONFIG_SYS_GBL_DATA_ADDR); + memset((void *)gd, 0, GENERATED_GBL_DATA_SIZE); + } else { + static gd_t _bfin_gd; + gd = &_bfin_gd; + } + if (CONFIG_SYS_BD_INFO_ADDR) { + bd = (bd_t *)(CONFIG_SYS_BD_INFO_ADDR); + memset(bd, 0, GENERATED_BD_INFO_SIZE); + } else { + static bd_t _bfin_bd; + bd = &_bfin_bd; + } + + gd->bd = bd; + + bd->bi_r_version = version_string; + bd->bi_cpu = __stringify(CONFIG_BFIN_CPU); + bd->bi_board_name = CONFIG_SYS_BOARD; + bd->bi_vco = get_vco(); + bd->bi_cclk = get_cclk(); + bd->bi_sclk = get_sclk(); + bd->bi_memstart = CONFIG_SYS_SDRAM_BASE; + bd->bi_memsize = CONFIG_SYS_MAX_RAM_SIZE; + + gd->ram_size = CONFIG_SYS_MAX_RAM_SIZE; + + return 0; +} + +static void display_global_data(void) +{ + bd_t *bd; + +#ifndef CONFIG_DEBUG_EARLY_SERIAL + return; +#endif + + bd = gd->bd; + printf(" gd: %p\n", gd); + printf(" |-flags: %lx\n", gd->flags); + printf(" |-board_type: %lx\n", gd->arch.board_type); + printf(" |-baudrate: %u\n", gd->baudrate); + printf(" |-have_console: %lx\n", gd->have_console); + printf(" |-ram_size: %lx\n", gd->ram_size); + printf(" |-env_addr: %lx\n", gd->env_addr); + printf(" |-env_valid: %lx\n", gd->env_valid); + printf(" |-jt(%p): %p\n", gd->jt, *(gd->jt)); + printf(" \\-bd: %p\n", gd->bd); + printf(" |-bi_boot_params: %lx\n", bd->bi_boot_params); + printf(" |-bi_memstart: %lx\n", bd->bi_memstart); + printf(" |-bi_memsize: %lx\n", bd->bi_memsize); + printf(" |-bi_flashstart: %lx\n", bd->bi_flashstart); + printf(" |-bi_flashsize: %lx\n", bd->bi_flashsize); + printf(" \\-bi_flashoffset: %lx\n", bd->bi_flashoffset); +} + +#define CPLB_PAGE_SIZE (4 * 1024 * 1024) +#define CPLB_PAGE_MASK (~(CPLB_PAGE_SIZE - 1)) +#if defined(__ADSPBF60x__) +#define CPLB_EX_PAGE_SIZE (16 * 1024 * 1024) +#define CPLB_EX_PAGE_MASK (~(CPLB_EX_PAGE_SIZE - 1)) +#else +#define CPLB_EX_PAGE_SIZE CPLB_PAGE_SIZE +#define CPLB_EX_PAGE_MASK CPLB_PAGE_MASK +#endif +void init_cplbtables(void) +{ + uint32_t *ICPLB_ADDR, *ICPLB_DATA; + uint32_t *DCPLB_ADDR, *DCPLB_DATA; + uint32_t extern_memory; + size_t i; + + void icplb_add(uint32_t addr, uint32_t data) + { + bfin_write32(ICPLB_ADDR + i, addr); + bfin_write32(ICPLB_DATA + i, data); + } + void dcplb_add(uint32_t addr, uint32_t data) + { + bfin_write32(DCPLB_ADDR + i, addr); + bfin_write32(DCPLB_DATA + i, data); + } + + /* populate a few common entries ... we'll let + * the memory map and cplb exception handler do + * the rest of the work. + */ + i = 0; + ICPLB_ADDR = (uint32_t *)ICPLB_ADDR0; + ICPLB_DATA = (uint32_t *)ICPLB_DATA0; + DCPLB_ADDR = (uint32_t *)DCPLB_ADDR0; + DCPLB_DATA = (uint32_t *)DCPLB_DATA0; + + icplb_add(0xFFA00000, L1_IMEMORY); + dcplb_add(0xFF800000, L1_DMEMORY); + ++i; +#if defined(__ADSPBF60x__) + icplb_add(0x0, 0x0); + dcplb_add(CONFIG_SYS_FLASH_BASE, PAGE_SIZE_16MB | CPLB_DIRTY | + CPLB_SUPV_WR | CPLB_USER_WR | CPLB_USER_RD | CPLB_VALID); + ++i; +#endif + + if (CONFIG_MEM_SIZE) { + uint32_t mbase = CONFIG_SYS_MONITOR_BASE; + uint32_t mend = mbase + CONFIG_SYS_MONITOR_LEN - 1; + mbase &= CPLB_PAGE_MASK; + mend &= CPLB_PAGE_MASK; + + icplb_add(mbase, SDRAM_IKERNEL); + dcplb_add(mbase, SDRAM_DKERNEL); + ++i; + + /* + * If the monitor crosses a 4 meg boundary, we'll need + * to lock two entries for it. We assume it doesn't + * cross two 4 meg boundaries ... + */ + if (mbase != mend) { + icplb_add(mend, SDRAM_IKERNEL); + dcplb_add(mend, SDRAM_DKERNEL); + ++i; + } + } + +#ifndef __ADSPBF60x__ + icplb_add(0x20000000, SDRAM_INON_CHBL); + dcplb_add(0x20000000, SDRAM_EBIU); + ++i; +#endif + + /* Add entries for the rest of external RAM up to the bootrom */ + extern_memory = 0; + +#ifdef CONFIG_DEBUG_NULL_PTR + icplb_add(extern_memory, + (SDRAM_IKERNEL & ~PAGE_SIZE_MASK) | PAGE_SIZE_1KB); + dcplb_add(extern_memory, + (SDRAM_DKERNEL & ~PAGE_SIZE_MASK) | PAGE_SIZE_1KB); + ++i; + icplb_add(extern_memory, SDRAM_IKERNEL); + dcplb_add(extern_memory, SDRAM_DKERNEL); + extern_memory += CPLB_PAGE_SIZE; + ++i; +#endif + + while (i < 16 && extern_memory < + (CONFIG_SYS_MONITOR_BASE & CPLB_EX_PAGE_MASK)) { + icplb_add(extern_memory, SDRAM_IGENERIC); + dcplb_add(extern_memory, SDRAM_DGENERIC); + extern_memory += CPLB_EX_PAGE_SIZE; + ++i; + } + while (i < 16) { + icplb_add(0, 0); + dcplb_add(0, 0); + ++i; + } +} + +int print_cpuinfo(void) +{ + char buf[32]; + + printf("CPU: ADSP %s (Detected Rev: 0.%d) (%s boot)\n", + gd->bd->bi_cpu, + bfin_revid(), + get_bfin_boot_mode(CONFIG_BFIN_BOOT_MODE)); + + printf("Clock: VCO: %s MHz, ", strmhz(buf, get_vco())); + printf("Core: %s MHz, ", strmhz(buf, get_cclk())); +#if defined(__ADSPBF60x__) + printf("System0: %s MHz, ", strmhz(buf, get_sclk0())); + printf("System1: %s MHz, ", strmhz(buf, get_sclk1())); + printf("Dclk: %s MHz\n", strmhz(buf, get_dclk())); +#else + printf("System: %s MHz\n", strmhz(buf, get_sclk())); +#endif + + return 0; +} + +int exception_init(void) +{ + bfin_write_EVT3(trap); + return 0; +} + +int irq_init(void) +{ +#ifdef SIC_IMASK0 + bfin_write_SIC_IMASK0(0); + bfin_write_SIC_IMASK1(0); +# ifdef SIC_IMASK2 + bfin_write_SIC_IMASK2(0); +# endif +#elif defined(SICA_IMASK0) + bfin_write_SICA_IMASK0(0); + bfin_write_SICA_IMASK1(0); +#elif defined(SIC_IMASK) + bfin_write_SIC_IMASK(0); +#endif + /* Set up a dummy NMI handler if needed. */ + if (CONFIG_BFIN_BOOT_MODE == BFIN_BOOT_BYPASS || ANOMALY_05000219) + bfin_write_EVT2(evt_nmi); /* NMI */ + bfin_write_EVT5(evt_default); /* hardware error */ + bfin_write_EVT6(evt_default); /* core timer */ + bfin_write_EVT7(evt_default); + bfin_write_EVT8(evt_default); + bfin_write_EVT9(evt_default); + bfin_write_EVT10(evt_default); + bfin_write_EVT11(evt_default); + bfin_write_EVT12(evt_default); + bfin_write_EVT13(evt_default); + bfin_write_EVT14(evt_default); + bfin_write_EVT15(evt_default); + bfin_write_ILAT(0); + CSYNC(); + /* enable hardware error irq */ + irq_flags = 0x3f; + local_irq_enable(); + return 0; +} + __attribute__ ((__noreturn__)) void cpu_init_f(ulong bootflag, ulong loaded_from_ldr) { @@ -102,51 +353,62 @@ void cpu_init_f(ulong bootflag, ulong loaded_from_ldr) bfin_core1_start(); #endif - serial_early_puts("Board init flash\n"); - board_init_f(bootflag); + serial_early_puts("Init global data\n"); + global_board_data_init(); + + board_init_f(0); /* should not be reached */ while (1); } -int exception_init(void) +int arch_cpu_init(void) { - bfin_write_EVT3(trap); + serial_early_puts("Init CPLB tables\n"); + init_cplbtables(); + + serial_early_puts("Exceptions setup\n"); + exception_init(); + +#ifndef CONFIG_ICACHE_OFF + serial_early_puts("Turn on ICACHE\n"); + icache_enable(); +#endif +#ifndef CONFIG_DCACHE_OFF + serial_early_puts("Turn on DCACHE\n"); + dcache_enable(); +#endif + +#ifdef DEBUG + if (GENERATED_GBL_DATA_SIZE < sizeof(*gd)) + hang(); +#endif + + /* Initialize */ + serial_early_puts("IRQ init\n"); + irq_init(); + return 0; } -int irq_init(void) +int arch_misc_init(void) { -#ifdef SIC_IMASK0 - bfin_write_SIC_IMASK0(0); - bfin_write_SIC_IMASK1(0); -# ifdef SIC_IMASK2 - bfin_write_SIC_IMASK2(0); -# endif -#elif defined(SICA_IMASK0) - bfin_write_SICA_IMASK0(0); - bfin_write_SICA_IMASK1(0); -#elif defined(SIC_IMASK) - bfin_write_SIC_IMASK(0); +#if defined(CONFIG_SYS_I2C) + i2c_reloc_fixup(); #endif - /* Set up a dummy NMI handler if needed. */ - if (CONFIG_BFIN_BOOT_MODE == BFIN_BOOT_BYPASS || ANOMALY_05000219) - bfin_write_EVT2(evt_nmi); /* NMI */ - bfin_write_EVT5(evt_default); /* hardware error */ - bfin_write_EVT6(evt_default); /* core timer */ - bfin_write_EVT7(evt_default); - bfin_write_EVT8(evt_default); - bfin_write_EVT9(evt_default); - bfin_write_EVT10(evt_default); - bfin_write_EVT11(evt_default); - bfin_write_EVT12(evt_default); - bfin_write_EVT13(evt_default); - bfin_write_EVT14(evt_default); - bfin_write_EVT15(evt_default); - bfin_write_ILAT(0); - CSYNC(); - /* enable hardware error irq */ - irq_flags = 0x3f; - local_irq_enable(); + + display_global_data(); + + if (CONFIG_MEM_SIZE && bfin_os_log_check()) { + puts("\nLog buffer from operating system:\n"); + bfin_os_log_dump(); + puts("\n"); + } + + return 0; +} + +int interrupt_init(void) +{ return 0; } diff --git a/arch/blackfin/cpu/start.S b/arch/blackfin/cpu/start.S index 29a7c23..f31abfa 100644 --- a/arch/blackfin/cpu/start.S +++ b/arch/blackfin/cpu/start.S @@ -196,8 +196,8 @@ ENTRY(_start) * takes care of clearing things for us. */ serial_early_puts("Zero BSS"); - r0.l = __bss_vma; - r0.h = __bss_vma; + r0.l = __bss_start; + r0.h = __bss_start; r1 = 0 (x); r2.l = __bss_len; r2.h = __bss_len; @@ -251,3 +251,13 @@ LENTRY(_get_pc) #endif rts; ENDPROC(_get_pc) + +ENTRY(_relocate_code) + /* Fake relocate code. Setup the new stack only */ + sp = r0; + fp = sp; + r0 = p3; + r1.h = 0x2000; + r1.l = 0x10; + jump.l _board_init_r +ENDPROC(_relocate_code) diff --git a/arch/blackfin/cpu/u-boot.lds b/arch/blackfin/cpu/u-boot.lds index 7f0411f..ae1b813 100644 --- a/arch/blackfin/cpu/u-boot.lds +++ b/arch/blackfin/cpu/u-boot.lds @@ -135,6 +135,8 @@ SECTIONS *(COMMON) . = ALIGN(4); } >ram_data - __bss_vma = ADDR(.bss); + __bss_end = .; + __bss_start = ADDR(.bss); __bss_len = SIZEOF(.bss); + __init_end = .; } diff --git a/arch/blackfin/include/asm/clock.h b/arch/blackfin/include/asm/clock.h index 59d3faa..05ae03c 100644 --- a/arch/blackfin/include/asm/clock.h +++ b/arch/blackfin/include/asm/clock.h @@ -78,7 +78,7 @@ extern u_long get_sclk1(void); extern u_long get_dclk(void); # define get_uart_clk get_sclk0 # define get_i2c_clk get_sclk0 -# define get_spi_clk get_sclk0 +# define get_spi_clk get_sclk1 #else # define get_uart_clk get_sclk # define get_i2c_clk get_sclk diff --git a/arch/blackfin/include/asm/config.h b/arch/blackfin/include/asm/config.h index 1da386e..836658a 100644 --- a/arch/blackfin/include/asm/config.h +++ b/arch/blackfin/include/asm/config.h @@ -174,4 +174,8 @@ } #endif +#define CONFIG_SYS_GENERIC_BOARD +#define CONFIG_DISPLAY_CPUINFO +#define CONFIG_ARCH_MISC_INIT + #endif diff --git a/arch/blackfin/include/asm/mach-bf609/BF609_def.h b/arch/blackfin/include/asm/mach-bf609/BF609_def.h index 02b81d3..fd0d86d 100644 --- a/arch/blackfin/include/asm/mach-bf609/BF609_def.h +++ b/arch/blackfin/include/asm/mach-bf609/BF609_def.h @@ -125,6 +125,8 @@ #define WDOG1_CNT 0xFFC17804 /* WDOG1 Count Register */ #define WDOG1_STAT 0xFFC17808 /* WDOG1 Watchdog Timer Status Register */ +#define SDU0_MSG_SET 0xFFC1F084 /* SDU0 Message Set Register */ + #define EMAC0_MACCFG 0xFFC20000 /* EMAC0 MAC Configuration Register */ #define EMAC1_MACCFG 0xFFC22000 /* EMAC1 MAC Configuration Register */ diff --git a/arch/blackfin/include/asm/u-boot.h b/arch/blackfin/include/asm/u-boot.h index acaeee9..7b5cf6a 100644 --- a/arch/blackfin/include/asm/u-boot.h +++ b/arch/blackfin/include/asm/u-boot.h @@ -25,9 +25,12 @@ typedef struct bd_info { unsigned long bi_vco; unsigned long bi_cclk; unsigned long bi_sclk; + unsigned char bi_enetaddr[6]; } bd_t; /* For image.h:image_check_target_arch() */ #define IH_ARCH_DEFAULT IH_ARCH_BLACKFIN +int arch_misc_init(void); + #endif /* _U_BOOT_H_ */ diff --git a/arch/blackfin/lib/Makefile b/arch/blackfin/lib/Makefile index 4ba7bf6..b534a98 100644 --- a/arch/blackfin/lib/Makefile +++ b/arch/blackfin/lib/Makefile @@ -9,11 +9,6 @@ # SPDX-License-Identifier: GPL-2.0+ # -# Unnecessary. -# Use CONFIG_SYS_BOARD instead of BFIN_BOARD_NAME -# and delete this. -ccflags-y += -DBFIN_BOARD_NAME='"$(BOARD)"' - obj-y += ins.o obj-y += memcmp.o obj-y += memcpy.o @@ -21,7 +16,6 @@ obj-y += memmove.o obj-y += memset.o obj-y += outs.o obj-$(CONFIG_CMD_KGDB) += __kgdb.o -obj-y += board.o obj-y += boot.o obj-y += cache.o obj-y += clocks.o @@ -30,3 +24,4 @@ obj-$(CONFIG_CMD_KGDB) += kgdb.o obj-y += muldi3.o obj-$(CONFIG_HAS_POST) += post.o obj-y += string.o +obj-y += sections.o diff --git a/arch/blackfin/lib/board.c b/arch/blackfin/lib/board.c deleted file mode 100644 index 8784255..0000000 --- a/arch/blackfin/lib/board.c +++ /dev/null @@ -1,443 +0,0 @@ -/* - * U-boot - board.c First C file to be called contains init routines - * - * Copyright (c) 2005-2008 Analog Devices Inc. - * - * (C) Copyright 2000-2004 - * Wolfgang Denk, DENX Software Engineering, wd@denx.de. - * - * Licensed under the GPL-2 or later. - */ - -#include <common.h> -#include <command.h> -#include <stdio_dev.h> -#include <serial.h> -#include <environment.h> -#include <malloc.h> -#include <mmc.h> -#include <net.h> -#include <status_led.h> -#include <version.h> -#include <watchdog.h> - -#include <asm/cplb.h> -#include <asm/mach-common/bits/mpu.h> -#include <asm/clock.h> -#include <kgdb.h> - -#ifdef CONFIG_CMD_NAND -#include <nand.h> /* cannot even include nand.h if it isnt configured */ -#endif - -#ifdef CONFIG_BITBANGMII -#include <miiphy.h> -#endif - -#if defined(CONFIG_POST) -#include <post.h> -int post_flag; -#endif - -#if defined(CONFIG_SYS_I2C) -#include <i2c.h> -#endif - -DECLARE_GLOBAL_DATA_PTR; - -__attribute__((always_inline)) -static inline void serial_early_puts(const char *s) -{ -#ifdef CONFIG_DEBUG_EARLY_SERIAL - serial_puts("Early: "); - serial_puts(s); -#endif -} - -static int display_banner(void) -{ - display_options(); - printf("CPU: ADSP %s " - "(Detected Rev: 0.%d) " - "(%s boot)\n", - gd->bd->bi_cpu, - bfin_revid(), - get_bfin_boot_mode(CONFIG_BFIN_BOOT_MODE)); - return 0; -} - -static int init_baudrate(void) -{ - gd->baudrate = getenv_ulong("baudrate", 10, CONFIG_BAUDRATE); - return 0; -} - -static void display_global_data(void) -{ - bd_t *bd; - -#ifndef CONFIG_DEBUG_EARLY_SERIAL - return; -#endif - - bd = gd->bd; - printf(" gd: %p\n", gd); - printf(" |-flags: %lx\n", gd->flags); - printf(" |-board_type: %lx\n", gd->arch.board_type); - printf(" |-baudrate: %u\n", gd->baudrate); - printf(" |-have_console: %lx\n", gd->have_console); - printf(" |-ram_size: %lx\n", gd->ram_size); - printf(" |-env_addr: %lx\n", gd->env_addr); - printf(" |-env_valid: %lx\n", gd->env_valid); - printf(" |-jt(%p): %p\n", gd->jt, *(gd->jt)); - printf(" \\-bd: %p\n", gd->bd); - printf(" |-bi_boot_params: %lx\n", bd->bi_boot_params); - printf(" |-bi_memstart: %lx\n", bd->bi_memstart); - printf(" |-bi_memsize: %lx\n", bd->bi_memsize); - printf(" |-bi_flashstart: %lx\n", bd->bi_flashstart); - printf(" |-bi_flashsize: %lx\n", bd->bi_flashsize); - printf(" \\-bi_flashoffset: %lx\n", bd->bi_flashoffset); -} - -#define CPLB_PAGE_SIZE (4 * 1024 * 1024) -#define CPLB_PAGE_MASK (~(CPLB_PAGE_SIZE - 1)) -#if defined(__ADSPBF60x__) -#define CPLB_EX_PAGE_SIZE (16 * 1024 * 1024) -#define CPLB_EX_PAGE_MASK (~(CPLB_EX_PAGE_SIZE - 1)) -#else -#define CPLB_EX_PAGE_SIZE CPLB_PAGE_SIZE -#define CPLB_EX_PAGE_MASK CPLB_PAGE_MASK -#endif -void init_cplbtables(void) -{ - volatile uint32_t *ICPLB_ADDR, *ICPLB_DATA; - volatile uint32_t *DCPLB_ADDR, *DCPLB_DATA; - uint32_t extern_memory; - size_t i; - - void icplb_add(uint32_t addr, uint32_t data) - { - *(ICPLB_ADDR + i) = addr; - *(ICPLB_DATA + i) = data; - } - void dcplb_add(uint32_t addr, uint32_t data) - { - *(DCPLB_ADDR + i) = addr; - *(DCPLB_DATA + i) = data; - } - - /* populate a few common entries ... we'll let - * the memory map and cplb exception handler do - * the rest of the work. - */ - i = 0; - ICPLB_ADDR = (uint32_t *)ICPLB_ADDR0; - ICPLB_DATA = (uint32_t *)ICPLB_DATA0; - DCPLB_ADDR = (uint32_t *)DCPLB_ADDR0; - DCPLB_DATA = (uint32_t *)DCPLB_DATA0; - - icplb_add(0xFFA00000, L1_IMEMORY); - dcplb_add(0xFF800000, L1_DMEMORY); - ++i; -#if defined(__ADSPBF60x__) - icplb_add(0x0, 0x0); - dcplb_add(CONFIG_SYS_FLASH_BASE, PAGE_SIZE_16MB | CPLB_DIRTY | - CPLB_SUPV_WR | CPLB_USER_WR | CPLB_USER_RD | CPLB_VALID); - ++i; -#endif - - if (CONFIG_MEM_SIZE) { - uint32_t mbase = CONFIG_SYS_MONITOR_BASE; - uint32_t mend = mbase + CONFIG_SYS_MONITOR_LEN; - mbase &= CPLB_PAGE_MASK; - mend &= CPLB_PAGE_MASK; - - icplb_add(mbase, SDRAM_IKERNEL); - dcplb_add(mbase, SDRAM_DKERNEL); - ++i; - - /* - * If the monitor crosses a 4 meg boundary, we'll need - * to lock two entries for it. We assume it doesn't - * cross two 4 meg boundaries ... - */ - if (mbase != mend) { - icplb_add(mend, SDRAM_IKERNEL); - dcplb_add(mend, SDRAM_DKERNEL); - ++i; - } - } - -#ifndef __ADSPBF60x__ - icplb_add(0x20000000, SDRAM_INON_CHBL); - dcplb_add(0x20000000, SDRAM_EBIU); - ++i; -#endif - - /* Add entries for the rest of external RAM up to the bootrom */ - extern_memory = 0; - -#ifdef CONFIG_DEBUG_NULL_PTR - icplb_add(extern_memory, (SDRAM_IKERNEL & ~PAGE_SIZE_MASK) | PAGE_SIZE_1KB); - dcplb_add(extern_memory, (SDRAM_DKERNEL & ~PAGE_SIZE_MASK) | PAGE_SIZE_1KB); - ++i; - icplb_add(extern_memory, SDRAM_IKERNEL); - dcplb_add(extern_memory, SDRAM_DKERNEL); - extern_memory += CPLB_PAGE_SIZE; - ++i; -#endif - - while (i < 16 && extern_memory < - (CONFIG_SYS_MONITOR_BASE & CPLB_EX_PAGE_MASK)) { - icplb_add(extern_memory, SDRAM_IGENERIC); - dcplb_add(extern_memory, SDRAM_DGENERIC); - extern_memory += CPLB_EX_PAGE_SIZE; - ++i; - } - while (i < 16) { - icplb_add(0, 0); - dcplb_add(0, 0); - ++i; - } -} - -static int global_board_data_init(void) -{ -#ifndef CONFIG_SYS_GBL_DATA_ADDR -# define CONFIG_SYS_GBL_DATA_ADDR 0 -#endif -#ifndef CONFIG_SYS_BD_INFO_ADDR -# define CONFIG_SYS_BD_INFO_ADDR 0 -#endif - - bd_t *bd; - - if (CONFIG_SYS_GBL_DATA_ADDR) { - gd = (gd_t *) (CONFIG_SYS_GBL_DATA_ADDR); - memset((void *)gd, 0, GENERATED_GBL_DATA_SIZE); - } else { - static gd_t _bfin_gd; - gd = &_bfin_gd; - } - - if (CONFIG_SYS_BD_INFO_ADDR) { - bd = (bd_t *) (CONFIG_SYS_BD_INFO_ADDR); - memset(bd, 0, GENERATED_BD_INFO_SIZE); - } else { - static bd_t _bfin_bd; - bd = &_bfin_bd; - } - gd->bd = bd; - - bd->bi_r_version = version_string; - bd->bi_cpu = __stringify(CONFIG_BFIN_CPU); - bd->bi_board_name = BFIN_BOARD_NAME; - bd->bi_vco = get_vco(); - bd->bi_cclk = get_cclk(); - bd->bi_sclk = get_sclk(); - bd->bi_memstart = CONFIG_SYS_SDRAM_BASE; - bd->bi_memsize = CONFIG_SYS_MAX_RAM_SIZE; - - return 0; -} - -/* - * All attempts to come up with a "common" initialization sequence - * that works for all boards and architectures failed: some of the - * requirements are just _too_ different. To get rid of the resulting - * mess of board dependend #ifdef'ed code we now make the whole - * initialization sequence configurable to the user. - * - * The requirements for any new initalization function is simple: it - * receives a pointer to the "global data" structure as it's only - * argument, and returns an integer return code, where 0 means - * "continue" and != 0 means "fatal error, hang the system". - */ - -extern int watchdog_init(void); -extern int exception_init(void); -extern int irq_init(void); -extern int timer_init(void); - -void board_init_f(ulong bootflag) -{ - char buf[32]; - -#ifdef CONFIG_BOARD_EARLY_INIT_F - serial_early_puts("Board early init flash\n"); - board_early_init_f(); -#endif - - serial_early_puts("Init CPLB tables\n"); - init_cplbtables(); - - serial_early_puts("Exceptions setup\n"); - exception_init(); - -#ifndef CONFIG_ICACHE_OFF - serial_early_puts("Turn on ICACHE\n"); - icache_enable(); -#endif -#ifndef CONFIG_DCACHE_OFF - serial_early_puts("Turn on DCACHE\n"); - dcache_enable(); -#endif - -#ifdef CONFIG_HW_WATCHDOG - serial_early_puts("Setting up external watchdog\n"); - hw_watchdog_init(); -#endif - -#ifdef DEBUG - if (GENERATED_GBL_DATA_SIZE < sizeof(*gd)) - hang(); -#endif - serial_early_puts("Init global data\n"); - - global_board_data_init(); - - /* Initialize */ - serial_early_puts("IRQ init\n"); - irq_init(); - serial_early_puts("Environment init\n"); - env_init(); - serial_early_puts("Baudrate init\n"); - init_baudrate(); - serial_early_puts("Serial init\n"); - serial_init(); - serial_initialize(); - serial_early_puts("Console init flash\n"); - console_init_f(); - serial_early_puts("End of early debugging\n"); - display_banner(); - - checkboard(); - timer_init(); - - printf("Clock: VCO: %s MHz, ", strmhz(buf, get_vco())); - printf("Core: %s MHz, ", strmhz(buf, get_cclk())); -#if defined(__ADSPBF60x__) - printf("System0: %s MHz, ", strmhz(buf, get_sclk0())); - printf("System1: %s MHz, ", strmhz(buf, get_sclk1())); - printf("Dclk: %s MHz\n", strmhz(buf, get_dclk())); -#else - printf("System: %s MHz\n", strmhz(buf, get_sclk())); -#endif - - if (CONFIG_MEM_SIZE) { - printf("RAM: "); - print_size(gd->bd->bi_memsize, "\n"); - } - -#if defined(CONFIG_POST) - post_init_f(); - post_bootmode_init(); - post_run(NULL, POST_ROM | post_bootmode_get(0)); -#endif - - board_init_r((gd_t *) gd, 0x20000010); -} - -static void board_net_init_r(bd_t *bd) -{ -#ifdef CONFIG_BITBANGMII - bb_miiphy_init(); -#endif -#ifdef CONFIG_CMD_NET - printf("Net: "); - eth_initialize(bd); -#endif -} - -void board_init_r(gd_t * id, ulong dest_addr) -{ - bd_t *bd; - gd = id; - gd->flags |= GD_FLG_RELOC; /* tell others: relocation done */ - bd = gd->bd; - -#if defined(CONFIG_POST) - post_output_backlog(); -#endif - - /* initialize malloc() area */ - mem_malloc_init(CONFIG_SYS_MALLOC_BASE, CONFIG_SYS_MALLOC_LEN); - -#if !defined(CONFIG_SYS_NO_FLASH) - /* Initialize the flash and protect u-boot by default */ - extern flash_info_t flash_info[]; - puts("Flash: "); - ulong size = flash_init(); - print_size(size, "\n"); - flash_protect(FLAG_PROTECT_SET, CONFIG_SYS_FLASH_BASE, - CONFIG_SYS_FLASH_BASE + CONFIG_SYS_MONITOR_LEN - 1, - &flash_info[0]); - bd->bi_flashstart = CONFIG_SYS_FLASH_BASE; - bd->bi_flashsize = size; - bd->bi_flashoffset = 0; -#else - bd->bi_flashstart = 0; - bd->bi_flashsize = 0; - bd->bi_flashoffset = 0; -#endif - -#ifdef CONFIG_CMD_NAND - puts("NAND: "); - nand_init(); /* go init the NAND */ -#endif - -#ifdef CONFIG_GENERIC_MMC - puts("MMC: "); - mmc_initialize(bd); -#endif - -#if defined(CONFIG_SYS_I2C) - i2c_reloc_fixup(); -#endif - /* relocate environment function pointers etc. */ - env_relocate(); - - /* Initialize stdio devices */ - stdio_init(); - jumptable_init(); - - /* Initialize the console (after the relocation and devices init) */ - console_init_r(); - -#ifdef CONFIG_CMD_KGDB - puts("KGDB: "); - kgdb_init(); -#endif - -#ifdef CONFIG_STATUS_LED - status_led_set(STATUS_LED_BOOT, STATUS_LED_BLINKING); - status_led_set(STATUS_LED_CRASH, STATUS_LED_OFF); -#endif - - /* Initialize from environment */ - load_addr = getenv_ulong("loadaddr", 16, load_addr); - -#if defined(CONFIG_MISC_INIT_R) - /* miscellaneous platform dependent initialisations */ - misc_init_r(); -#endif - - board_net_init_r(bd); - - display_global_data(); - -#if defined(CONFIG_POST) - if (post_flag) - post_run(NULL, POST_RAM | post_bootmode_get(0)); -#endif - - if (CONFIG_MEM_SIZE && bfin_os_log_check()) { - puts("\nLog buffer from operating system:\n"); - bfin_os_log_dump(); - puts("\n"); - } - - /* main_loop() can return to retry autoboot, if so just run it again. */ - for (;;) - main_loop(); -} diff --git a/arch/blackfin/lib/sections.c b/arch/blackfin/lib/sections.c new file mode 100644 index 0000000..b50f30a --- /dev/null +++ b/arch/blackfin/lib/sections.c @@ -0,0 +1,11 @@ +/* + * U-boot - section.c + * + * Copyright (c) 2014 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + +char __bss_start[0] __attribute__((section(".__bss_start"))); +char __bss_end[0] __attribute__((section(".__bss_end"))); +char __init_end[0] __attribute__((section(".__init_end"))); diff --git a/board/samsung/common/Makefile b/board/samsung/common/Makefile index 41d0cc3..93347ef 100644 --- a/board/samsung/common/Makefile +++ b/board/samsung/common/Makefile @@ -6,7 +6,7 @@ # obj-$(CONFIG_SOFT_I2C_MULTI_BUS) += multi_i2c.o -obj-$(CONFIG_THOR_FUNCTION) += thor.o +obj-$(CONFIG_USBDOWNLOAD_GADGET) += gadget.o obj-$(CONFIG_MISC_COMMON) += misc.o ifndef CONFIG_SPL_BUILD diff --git a/board/samsung/common/thor.c b/board/samsung/common/gadget.c index 1c7630d..6a1e57f 100644 --- a/board/samsung/common/thor.c +++ b/board/samsung/common/gadget.c @@ -13,6 +13,9 @@ int g_dnl_bind_fixup(struct usb_device_descriptor *dev, const char *name) if (!strcmp(name, "usb_dnl_thor")) { put_unaligned(CONFIG_G_DNL_THOR_VENDOR_NUM, &dev->idVendor); put_unaligned(CONFIG_G_DNL_THOR_PRODUCT_NUM, &dev->idProduct); + } else if (!strcmp(name, "usb_dnl_ums")) { + put_unaligned(CONFIG_G_DNL_UMS_VENDOR_NUM, &dev->idVendor); + put_unaligned(CONFIG_G_DNL_UMS_PRODUCT_NUM, &dev->idProduct); } else { put_unaligned(CONFIG_G_DNL_VENDOR_NUM, &dev->idVendor); put_unaligned(CONFIG_G_DNL_PRODUCT_NUM, &dev->idProduct); diff --git a/common/board_f.c b/common/board_f.c index 6203d85..d5e7622 100644 --- a/common/board_f.c +++ b/common/board_f.c @@ -106,9 +106,14 @@ __weak void blue_led_off(void) {} * Could the CONFIG_SPL_BUILD infection become a flag in gd? */ -#if defined(CONFIG_WATCHDOG) +#if defined(CONFIG_WATCHDOG) || defined(CONFIG_HW_WATCHDOG) static int init_func_watchdog_init(void) { +# if defined(CONFIG_HW_WATCHDOG) && (defined(CONFIG_BLACKFIN) || \ + defined(CONFIG_M68K) || defined(CONFIG_MICROBLAZE) || \ + defined(CONFIG_SH)) + hw_watchdog_init(); +# endif puts(" Watchdog enabled\n"); WATCHDOG_RESET(); @@ -146,7 +151,11 @@ static int display_text_info(void) bss_end = (ulong)&__bss_end; debug("U-Boot code: %08X -> %08lX BSS: -> %08lX\n", +#ifdef CONFIG_SYS_TEXT_BASE CONFIG_SYS_TEXT_BASE, bss_start, bss_end); +#else + CONFIG_SYS_MONITOR_BASE, bss_start, bss_end); +#endif #endif #ifdef CONFIG_MODEM_SUPPORT @@ -261,6 +270,8 @@ static int setup_mon_len(void) gd->mon_len = (ulong)&__bss_end - (ulong)_start; #elif defined(CONFIG_SANDBOX) gd->mon_len = (ulong)&_end - (ulong)_init; +#elif defined(CONFIG_BLACKFIN) + gd->mon_len = CONFIG_SYS_MONITOR_LEN; #else /* TODO: use (ulong)&__bss_end - (ulong)&__text_start; ? */ gd->mon_len = (ulong)&__bss_end - CONFIG_SYS_MONITOR_BASE; @@ -470,8 +481,9 @@ static int reserve_trace(void) return 0; } -#if defined(CONFIG_VIDEO) && (!defined(CONFIG_PPC) || defined(CONFIG_8xx)) \ - && !defined(CONFIG_ARM) && !defined(CONFIG_X86) +#if defined(CONFIG_VIDEO) && (!defined(CONFIG_PPC) || defined(CONFIG_8xx)) && \ + !defined(CONFIG_ARM) && !defined(CONFIG_X86) && \ + !defined(CONFIG_BLACKFIN) static int reserve_video(void) { /* reserve memory for video display (always full pages) */ @@ -516,11 +528,13 @@ static int reserve_malloc(void) /* (permanently) allocate a Board Info struct */ static int reserve_board(void) { - gd->start_addr_sp -= sizeof(bd_t); - gd->bd = (bd_t *)map_sysmem(gd->start_addr_sp, sizeof(bd_t)); - memset(gd->bd, '\0', sizeof(bd_t)); - debug("Reserving %zu Bytes for Board Info at: %08lx\n", - sizeof(bd_t), gd->start_addr_sp); + if (!gd->bd) { + gd->start_addr_sp -= sizeof(bd_t); + gd->bd = (bd_t *)map_sysmem(gd->start_addr_sp, sizeof(bd_t)); + memset(gd->bd, '\0', sizeof(bd_t)); + debug("Reserving %zu Bytes for Board Info at: %08lx\n", + sizeof(bd_t), gd->start_addr_sp); + } return 0; } #endif @@ -721,7 +735,9 @@ static int reloc_fdt(void) static int setup_reloc(void) { +#ifdef CONFIG_SYS_TEXT_BASE gd->reloc_off = gd->relocaddr - CONFIG_SYS_TEXT_BASE; +#endif memcpy(gd->new_gd, (char *)gd, sizeof(gd_t)); debug("Relocation Offset is: %08lx\n", gd->reloc_off); @@ -828,7 +844,7 @@ static init_fnc_t init_sequence_f[] = { /* TODO: can we rename this to timer_init()? */ init_timebase, #endif -#if defined(CONFIG_ARM) || defined(CONFIG_MIPS) +#if defined(CONFIG_ARM) || defined(CONFIG_MIPS) || defined(CONFIG_BLACKFIN) timer_init, /* initialize timer */ #endif #ifdef CONFIG_SYS_ALLOC_DPRAM @@ -929,6 +945,10 @@ static init_fnc_t init_sequence_f[] = { * - board info struct */ setup_dest_addr, +#if defined(CONFIG_BLACKFIN) + /* Blackfin u-boot monitor should be on top of the ram */ + reserve_uboot, +#endif #if defined(CONFIG_LOGBUFFER) && !defined(CONFIG_ALT_LB_ADDR) reserve_logbuffer, #endif @@ -945,11 +965,14 @@ static init_fnc_t init_sequence_f[] = { #endif reserve_trace, /* TODO: Why the dependency on CONFIG_8xx? */ -#if defined(CONFIG_VIDEO) && (!defined(CONFIG_PPC) || defined(CONFIG_8xx)) \ - && !defined(CONFIG_ARM) && !defined(CONFIG_X86) +#if defined(CONFIG_VIDEO) && (!defined(CONFIG_PPC) || defined(CONFIG_8xx)) && \ + !defined(CONFIG_ARM) && !defined(CONFIG_X86) && \ + !defined(CONFIG_BLACKFIN) reserve_video, #endif +#if !defined(CONFIG_BLACKFIN) reserve_uboot, +#endif #ifndef CONFIG_SPL_BUILD reserve_malloc, reserve_board, diff --git a/common/lcd.c b/common/lcd.c index feb913a..217ec9d 100644 --- a/common/lcd.c +++ b/common/lcd.c @@ -100,7 +100,8 @@ #if LCD_BPP == LCD_MONOCHROME # define COLOR_MASK(c) ((c) | (c) << 1 | (c) << 2 | (c) << 3 | \ (c) << 4 | (c) << 5 | (c) << 6 | (c) << 7) -#elif (LCD_BPP == LCD_COLOR8) || (LCD_BPP == LCD_COLOR16) +#elif (LCD_BPP == LCD_COLOR8) || (LCD_BPP == LCD_COLOR16) || \ + (LCD_BPP == LCD_COLOR32) # define COLOR_MASK(c) (c) #else # error Unsupported LCD BPP. @@ -109,14 +110,12 @@ DECLARE_GLOBAL_DATA_PTR; static void lcd_drawchars(ushort x, ushort y, uchar *str, int count); -static inline void lcd_puts_xy(ushort x, ushort y, uchar *s); static inline void lcd_putc_xy(ushort x, ushort y, uchar c); static int lcd_init(void *lcdbase); static void *lcd_logo(void); -static int lcd_getbgcolor(void); static void lcd_setfgcolor(int color); static void lcd_setbgcolor(int color); @@ -177,10 +176,20 @@ static void console_scrollup(void) CONSOLE_SIZE - CONSOLE_ROW_SIZE * rows); /* Clear the last rows */ +#if (LCD_BPP != LCD_COLOR32) memset(lcd_console_address + CONSOLE_SIZE - CONSOLE_ROW_SIZE * rows, COLOR_MASK(lcd_color_bg), CONSOLE_ROW_SIZE * rows); - +#else + u32 *ppix = lcd_console_address + + CONSOLE_SIZE - CONSOLE_ROW_SIZE * rows; + u32 i; + for (i = 0; + i < (CONSOLE_ROW_SIZE * rows) / NBYTES(panel_info.vl_bpix); + i++) { + *ppix++ = COLOR_MASK(lcd_color_bg); + } +#endif lcd_sync(); console_row -= rows; } @@ -308,13 +317,15 @@ static void lcd_drawchars(ushort x, ushort y, uchar *str, int count) ushort off = x * (1 << LCD_BPP) % 8; #endif - dest = (uchar *)(lcd_base + y * lcd_line_length + x * (1 << LCD_BPP) / 8); + dest = (uchar *)(lcd_base + y * lcd_line_length + x * NBITS(LCD_BPP)/8); for (row = 0; row < VIDEO_FONT_HEIGHT; ++row, dest += lcd_line_length) { uchar *s = str; int i; #if LCD_BPP == LCD_COLOR16 ushort *d = (ushort *)dest; +#elif LCD_BPP == LCD_COLOR32 + u32 *d = (u32 *)dest; #else uchar *d = dest; #endif @@ -347,6 +358,12 @@ static void lcd_drawchars(ushort x, ushort y, uchar *str, int count) lcd_color_fg : lcd_color_bg; bits <<= 1; } +#elif LCD_BPP == LCD_COLOR32 + for (c = 0; c < 8; ++c) { + *d++ = (bits & 0x80) ? + lcd_color_fg : lcd_color_bg; + bits <<= 1; + } #endif } #if LCD_BPP == LCD_MONOCHROME @@ -355,15 +372,6 @@ static void lcd_drawchars(ushort x, ushort y, uchar *str, int count) } } -/*----------------------------------------------------------------------*/ - -static inline void lcd_puts_xy(ushort x, ushort y, uchar *s) -{ - lcd_drawchars(x, y, s, strlen((char *)s)); -} - -/*----------------------------------------------------------------------*/ - static inline void lcd_putc_xy(ushort x, ushort y, uchar c) { lcd_drawchars(x, y, &c, 1); @@ -476,9 +484,19 @@ void lcd_clear(void) test_pattern(); #else /* set framebuffer to background color */ +#if (LCD_BPP != LCD_COLOR32) memset((char *)lcd_base, - COLOR_MASK(lcd_getbgcolor()), + COLOR_MASK(lcd_color_bg), lcd_line_length * panel_info.vl_row); +#else + u32 *ppix = lcd_base; + u32 i; + for (i = 0; + i < (lcd_line_length * panel_info.vl_row)/NBYTES(panel_info.vl_bpix); + i++) { + *ppix++ = COLOR_MASK(lcd_color_bg); + } +#endif #endif /* Paint the logo and retrieve LCD base address */ debug("[LCD] Drawing the logo...\n"); @@ -586,20 +604,6 @@ static void lcd_setbgcolor(int color) lcd_color_bg = color; } -/*----------------------------------------------------------------------*/ - -int lcd_getfgcolor(void) -{ - return lcd_color_fg; -} - -/*----------------------------------------------------------------------*/ - -static int lcd_getbgcolor(void) -{ - return lcd_color_bg; -} - /************************************************************************/ /* ** Chipset depending Bitmap / Logo stuff... */ /************************************************************************/ @@ -938,8 +942,13 @@ int lcd_display_bitmap(ulong bmp_image, int x, int y) return 1; } - /* We support displaying 8bpp BMPs on 16bpp LCDs */ - if (bpix != bmp_bpix && !(bmp_bpix == 8 && bpix == 16)) { + /* + * We support displaying 8bpp BMPs on 16bpp LCDs + * and displaying 24bpp BMPs on 32bpp LCDs + * */ + if (bpix != bmp_bpix && + !(bmp_bpix == 8 && bpix == 16) && + !(bmp_bpix == 24 && bpix == 32)) { printf ("Error: %d bit/pixel mode, but BMP has %d bit/pixel\n", bpix, get_unaligned_le16(&bmp->header.bit_count)); return 1; @@ -1060,7 +1069,19 @@ int lcd_display_bitmap(ulong bmp_image, int x, int y) } break; #endif /* CONFIG_BMP_16BPP */ - +#if defined(CONFIG_BMP_24BMP) + case 24: + for (i = 0; i < height; ++i) { + for (j = 0; j < width; j++) { + *(fb++) = *(bmap++); + *(fb++) = *(bmap++); + *(fb++) = *(bmap++); + *(fb++) = 0; + } + fb -= lcd_line_length + width * (bpix / 8); + } + break; +#endif /* CONFIG_BMP_24BMP */ #if defined(CONFIG_BMP_32BPP) case 32: for (i = 0; i < height; ++i) { diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 945f35d..93a91c3 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -41,3 +41,4 @@ obj-$(CONFIG_VIDEO_SMI_LYNXEM) += smiLynxEM.o videomodes.o obj-$(CONFIG_VIDEO_TEGRA) += tegra.o obj-$(CONFIG_VIDEO_VCXK) += bus_vcxk.o obj-$(CONFIG_FORMIKE) += formike.o +obj-$(CONFIG_AM335X_LCD) += am335x-fb.o diff --git a/drivers/video/am335x-fb.c b/drivers/video/am335x-fb.c new file mode 100644 index 0000000..ab98941 --- /dev/null +++ b/drivers/video/am335x-fb.c @@ -0,0 +1,169 @@ +/* + * Copyright (C) 2013 Hannes Petermaier <oe5hpm@oevsv.at> + * Bernecker & Rainer Industrieelektronik GmbH - http://www.br-automation.com + * + * minimal framebuffer driver for TI's AM335x SoC to be compatible with + * Wolfgang Denk's LCD-Framework (CONFIG_LCD, common/lcd.c) + * + * - supporting only 24bit RGB/TFT raster Mode (not using palette) + * - sets up LCD controller as in 'am335x_lcdpanel' struct given + * - starts output DMA from gd->fb_base buffer + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#include <common.h> +#include <asm/arch/hardware.h> +#include <lcd.h> +#include "am335x-fb.h" + +#if !defined(LCD_CNTL_BASE) +#error "hw-base address of LCD-Controller (LCD_CNTL_BASE) not defined!" +#endif + + +/* LCD Control Register */ +#define LCD_CLK_DIVISOR(x) ((x) << 8) +#define LCD_RASTER_MODE 0x01 +/* LCD Clock Enable Register */ +#define LCD_CORECLKEN (0x01 << 0) +#define LCD_LIDDCLKEN (0x01 << 1) +#define LCD_DMACLKEN (0x01 << 2) +/* LCD DMA Control Register */ +#define LCD_DMA_BURST_SIZE(x) ((x) << 4) +#define LCD_DMA_BURST_1 0x0 +#define LCD_DMA_BURST_2 0x1 +#define LCD_DMA_BURST_4 0x2 +#define LCD_DMA_BURST_8 0x3 +#define LCD_DMA_BURST_16 0x4 +/* LCD Timing_0 Register */ +#define LCD_HBPLSB(x) ((((x)-1) & 0xFF) << 24) +#define LCD_HFPLSB(x) ((((x)-1) & 0xFF) << 16) +#define LCD_HSWLSB(x) ((((x)-1) & 0x3F) << 10) +#define LCD_HORLSB(x) (((((x) >> 4)-1) & 0x3F) << 4) +#define LCD_HORMSB(x) (((((x) >> 4)-1) & 0x40) >> 4) +/* LCD Timing_1 Register */ +#define LCD_VBP(x) ((x) << 24) +#define LCD_VFP(x) ((x) << 16) +#define LCD_VSW(x) (((x)-1) << 10) +#define LCD_VERLSB(x) (((x)-1) & 0x3FF) +/* LCD Timing_2 Register */ +#define LCD_HSWMSB(x) ((((x)-1) & 0x3C0) << 21) +#define LCD_VERMSB(x) ((((x)-1) & 0x400) << 16) +#define LCD_HBPMSB(x) ((((x)-1) & 0x300) >> 4) +#define LCD_HFPMSB(x) ((((x)-1) & 0x300) >> 8) +#define LCD_INVMASK(x) ((x) & 0x3F00000) +/* LCD Raster Ctrl Register */ +#define LCD_TFT_24BPP_MODE (1 << 25) +#define LCD_TFT_24BPP_UNPACK (1 << 26) +#define LCD_PALMODE_RAWDATA (0x10 << 20) +#define LCD_TFT_MODE (0x01 << 7) +#define LCD_RASTER_ENABLE (0x01 << 0) + + +/* Macro definitions */ +#define FBSIZE(x) ((x->hactive * x->vactive * x->bpp) >> 3) + +struct am335x_lcdhw { + unsigned int pid; /* 0x00 */ + unsigned int ctrl; /* 0x04 */ + unsigned int gap0; /* 0x08 */ + unsigned int lidd_ctrl; /* 0x0C */ + unsigned int lidd_cs0_conf; /* 0x10 */ + unsigned int lidd_cs0_addr; /* 0x14 */ + unsigned int lidd_cs0_data; /* 0x18 */ + unsigned int lidd_cs1_conf; /* 0x1C */ + unsigned int lidd_cs1_addr; /* 0x20 */ + unsigned int lidd_cs1_data; /* 0x24 */ + unsigned int raster_ctrl; /* 0x28 */ + unsigned int raster_timing0; /* 0x2C */ + unsigned int raster_timing1; /* 0x30 */ + unsigned int raster_timing2; /* 0x34 */ + unsigned int raster_subpanel; /* 0x38 */ + unsigned int raster_subpanel2; /* 0x3C */ + unsigned int lcddma_ctrl; /* 0x40 */ + unsigned int lcddma_fb0_base; /* 0x44 */ + unsigned int lcddma_fb0_ceiling; /* 0x48 */ + unsigned int lcddma_fb1_base; /* 0x4C */ + unsigned int lcddma_fb1_ceiling; /* 0x50 */ + unsigned int sysconfig; /* 0x54 */ + unsigned int irqstatus_raw; /* 0x58 */ + unsigned int irqstatus; /* 0x5C */ + unsigned int irqenable_set; /* 0x60 */ + unsigned int irqenable_clear; /* 0x64 */ + unsigned int gap1; /* 0x68 */ + unsigned int clkc_enable; /* 0x6C */ + unsigned int clkc_reset; /* 0x70 */ +}; + +static struct am335x_lcdhw *lcdhw = (void *)LCD_CNTL_BASE; +DECLARE_GLOBAL_DATA_PTR; + +int lcd_get_size(int *line_length) +{ + *line_length = (panel_info.vl_col * NBITS(panel_info.vl_bpix)) / 8; + return *line_length * panel_info.vl_row + 0x20; +} + +int am335xfb_init(struct am335x_lcdpanel *panel) +{ + if (0 == gd->fb_base) { + printf("ERROR: no valid fb_base stored in GLOBAL_DATA_PTR!\n"); + return -1; + } + if (0 == panel) { + printf("ERROR: missing ptr to am335x_lcdpanel!\n"); + return -1; + } + + debug("setting up LCD-Controller for %dx%dx%d (hfp=%d,hbp=%d,hsw=%d / ", + panel->hactive, panel->vactive, panel->bpp, + panel->hfp, panel->hbp, panel->hsw); + debug("vfp=%d,vbp=%d,vsw=%d / clk-div=%d)\n", + panel->vfp, panel->vfp, panel->vsw, panel->pxl_clk_div); + debug("using frambuffer at 0x%08x with size %d.\n", + (unsigned int)gd->fb_base, FBSIZE(panel)); + + /* palette default entry */ + memset((void *)gd->fb_base, 0, 0x20); + *(unsigned int *)gd->fb_base = 0x4000; + + lcdhw->clkc_enable = LCD_CORECLKEN | LCD_LIDDCLKEN | LCD_DMACLKEN; + lcdhw->raster_ctrl = 0; + lcdhw->ctrl = LCD_CLK_DIVISOR(panel->pxl_clk_div) | LCD_RASTER_MODE; + lcdhw->lcddma_fb0_base = gd->fb_base; + lcdhw->lcddma_fb0_ceiling = gd->fb_base + FBSIZE(panel) + 0x20; + lcdhw->lcddma_fb1_base = gd->fb_base; + lcdhw->lcddma_fb1_ceiling = gd->fb_base + FBSIZE(panel) + 0x20; + lcdhw->lcddma_ctrl = LCD_DMA_BURST_SIZE(LCD_DMA_BURST_16); + + lcdhw->raster_timing0 = LCD_HORLSB(panel->hactive) | + LCD_HORMSB(panel->hactive) | + LCD_HFPLSB(panel->hfp) | + LCD_HBPLSB(panel->hbp) | + LCD_HSWLSB(panel->hsw); + lcdhw->raster_timing1 = LCD_VBP(panel->vbp) | + LCD_VFP(panel->vfp) | + LCD_VSW(panel->vsw) | + LCD_VERLSB(panel->vactive); + lcdhw->raster_timing2 = LCD_HSWMSB(panel->hsw) | + LCD_VERMSB(panel->vactive) | + LCD_INVMASK(panel->pol) | + LCD_HBPMSB(panel->hbp) | + LCD_HFPMSB(panel->hfp) | + 0x0000FF00; /* clk cycles for ac-bias */ + lcdhw->raster_ctrl = LCD_TFT_24BPP_MODE | + LCD_TFT_24BPP_UNPACK | + LCD_PALMODE_RAWDATA | + LCD_TFT_MODE | + LCD_RASTER_ENABLE; + + gd->fb_base += 0x20; /* point fb behind palette */ + + /* turn ON display through powercontrol function if accessible */ + if (0 != panel->panel_power_ctrl) { + mdelay(panel->pon_delay); + panel->panel_power_ctrl(1); + } + + return 0; +} diff --git a/drivers/video/am335x-fb.h b/drivers/video/am335x-fb.h new file mode 100644 index 0000000..8a0b131 --- /dev/null +++ b/drivers/video/am335x-fb.h @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2013 Hannes Petermaier <oe5hpm@oevsv.at> - + * Bernecker & Rainer Industrieelektronik GmbH - http://www.br-automation.com + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef AM335X_FB_H +#define AM335X_FB_H + +#define HSVS_CONTROL (0x01 << 25) /* + * 0 = lcd_lp and lcd_fp are driven on + * opposite edges of pixel clock than + * the lcd_pixel_o + * 1 = lcd_lp and lcd_fp are driven + * according to bit 24 Note that this + * bit MUST be set to '0' for Passive + * Matrix displays the edge timing is + * fixed + */ +#define HSVS_RISEFALL (0x01 << 24) /* + * 0 = lcd_lp and lcd_fp are driven on + * the rising edge of pixel clock (bit + * 25 must be set to 1) + * 1 = lcd_lp and lcd_fp are driven on + * the falling edge of pixel clock (bit + * 25 must be set to 1) + */ +#define DE_INVERT (0x01 << 23) /* + * 0 = DE is low-active + * 1 = DE is high-active + */ +#define PXCLK_INVERT (0x01 << 22) /* + * 0 = pix-clk is high-active + * 1 = pic-clk is low-active + */ +#define HSYNC_INVERT (0x01 << 21) /* + * 0 = HSYNC is active high + * 1 = HSYNC is avtive low + */ +#define VSYNC_INVERT (0x01 << 20) /* + * 0 = VSYNC is active high + * 1 = VSYNC is active low + */ + +struct am335x_lcdpanel { + unsigned int hactive; /* Horizontal active area */ + unsigned int vactive; /* Vertical active area */ + unsigned int bpp; /* bits per pixel */ + unsigned int hfp; /* Horizontal front porch */ + unsigned int hbp; /* Horizontal back porch */ + unsigned int hsw; /* Horizontal Sync Pulse Width */ + unsigned int vfp; /* Vertical front porch */ + unsigned int vbp; /* Vertical back porch */ + unsigned int vsw; /* Vertical Sync Pulse Width */ + unsigned int pxl_clk_div; /* Pixel clock divider*/ + unsigned int pol; /* polarity of sync, clock signals */ + unsigned int pon_delay; /* + * time in ms for turning on lcd after + * initializing lcd-controller + */ + void (*panel_power_ctrl)(int); /* fp for power on/off display */ +}; + +int am335xfb_init(struct am335x_lcdpanel *panel); + +#endif /* AM335X_FB_H */ diff --git a/drivers/video/ipu.h b/drivers/video/ipu.h index 3d2741f..091b58f 100644 --- a/drivers/video/ipu.h +++ b/drivers/video/ipu.h @@ -176,6 +176,14 @@ typedef union { } ipu_channel_params_t; /* + * Enumeration of IPU interrupts. + */ +enum ipu_irq_line { + IPU_IRQ_DP_SF_END = 448 + 3, + IPU_IRQ_DC_FC_1 = 448 + 9, +}; + +/* * Bitfield of Display Interface signal polarities. */ typedef struct { diff --git a/drivers/video/ipu_disp.c b/drivers/video/ipu_disp.c index cefd2dc..948e1fc 100644 --- a/drivers/video/ipu_disp.c +++ b/drivers/video/ipu_disp.c @@ -33,7 +33,7 @@ enum csc_type_t { struct dp_csc_param_t { int mode; - void *coeff; + const int (*coeff)[5][3]; }; #define SYNC_WAVE 0 @@ -666,13 +666,16 @@ void ipu_dp_dc_disable(ipu_channel_t channel, unsigned char swap) uint32_t csc; uint32_t dc_chan = 0; int timeout = 50; + int irq = 0; dc_swap = swap; if (channel == MEM_DC_SYNC) { dc_chan = 1; + irq = IPU_IRQ_DC_FC_1; } else if (channel == MEM_BG_SYNC) { dc_chan = 5; + irq = IPU_IRQ_DP_SF_END; } else if (channel == MEM_FG_SYNC) { /* Disable FG channel */ dc_chan = 5; @@ -723,25 +726,11 @@ void ipu_dp_dc_disable(ipu_channel_t channel, unsigned char swap) reg ^= DC_WR_CH_CONF_PROG_DI_ID; __raw_writel(reg, DC_WR_CH_CONF(dc_chan)); } else { - timeout = 50; - - /* Wait for DC triple buffer to empty */ - if (g_dc_di_assignment[dc_chan] == 0) - while ((__raw_readl(DC_STAT) & 0x00000002) - != 0x00000002) { - udelay(2000); - timeout -= 2; - if (timeout <= 0) - break; - } - else if (g_dc_di_assignment[dc_chan] == 1) - while ((__raw_readl(DC_STAT) & 0x00000020) - != 0x00000020) { - udelay(2000); - timeout -= 2; - if (timeout <= 0) - break; - } + /* Make sure that we leave at the irq starting edge */ + __raw_writel(IPUIRQ_2_MASK(irq), IPUIRQ_2_STATREG(irq)); + do { + reg = __raw_readl(IPUIRQ_2_STATREG(irq)); + } while (!(reg & IPUIRQ_2_MASK(irq))); reg = __raw_readl(DC_WR_CH_CONF(dc_chan)); reg &= ~DC_WR_CH_CONF_PROG_TYPE_MASK; diff --git a/drivers/video/ipu_regs.h b/drivers/video/ipu_regs.h index 21e9c99..c2c134a 100644 --- a/drivers/video/ipu_regs.h +++ b/drivers/video/ipu_regs.h @@ -313,9 +313,12 @@ struct ipu_dmfc { #define IPU_STAT ((struct ipu_stat *)(IPU_CTRL_BASE_ADDR + \ IPU_STAT_REG_BASE)) +#define IPU_INT_STAT(n) (&IPU_STAT->int_stat[(n) - 1]) #define IPU_CHA_CUR_BUF(ch) (&IPU_STAT->cur_buf[ch / 32]) #define IPU_CHA_BUF0_RDY(ch) (&IPU_STAT->ch_buf0_rdy[ch / 32]) #define IPU_CHA_BUF1_RDY(ch) (&IPU_STAT->ch_buf1_rdy[ch / 32]) +#define IPUIRQ_2_STATREG(irq) (IPU_INT_STAT(1) + ((irq) / 32)) +#define IPUIRQ_2_MASK(irq) (1UL << ((irq) & 0x1F)) #define IPU_INT_CTRL(n) (&IPU_CM_REG->int_ctrl[(n) - 1]) diff --git a/include/configs/bf506f-ezkit.h b/include/configs/bf506f-ezkit.h index eed2d5b..5db1819 100644 --- a/include/configs/bf506f-ezkit.h +++ b/include/configs/bf506f-ezkit.h @@ -56,7 +56,7 @@ /* * Flash Settings */ - +/* #define CONFIG_FLASH_CFI_DRIVER #define CONFIG_SYS_FLASH_BASE 0x20000000 #define CONFIG_SYS_FLASH_CFI @@ -64,9 +64,8 @@ #define CONFIG_SYS_MAX_FLASH_SECT 71 #define CONFIG_CMD_FLASH #define CONFIG_MONITOR_IS_IN_RAM -/* -#define CONFIG_SYS_NO_FLASH */ +#define CONFIG_SYS_NO_FLASH /* * SPI Settings diff --git a/include/configs/bf533-stamp.h b/include/configs/bf533-stamp.h index d82c5b2..3d36d84 100644 --- a/include/configs/bf533-stamp.h +++ b/include/configs/bf533-stamp.h @@ -98,10 +98,11 @@ */ #define CONFIG_BFIN_SPI #define CONFIG_ENV_SPI_MAX_HZ 30000000 +/* #define CONFIG_SF_DEFAULT_SPEED 30000000 #define CONFIG_SPI_FLASH #define CONFIG_SPI_FLASH_ALL - +*/ /* * Env Storage Settings diff --git a/include/configs/bf538f-ezkit.h b/include/configs/bf538f-ezkit.h index 742c299..32df5ec 100644 --- a/include/configs/bf538f-ezkit.h +++ b/include/configs/bf538f-ezkit.h @@ -83,10 +83,11 @@ */ #define CONFIG_BFIN_SPI #define CONFIG_ENV_SPI_MAX_HZ 30000000 +/* #define CONFIG_SF_DEFAULT_SPEED 30000000 #define CONFIG_SPI_FLASH #define CONFIG_SPI_FLASH_ALL - +*/ /* * Env Storage Settings diff --git a/include/configs/exynos4-dt.h b/include/configs/exynos4-dt.h index 44e6ab4..7dac1a3 100644 --- a/include/configs/exynos4-dt.h +++ b/include/configs/exynos4-dt.h @@ -105,6 +105,8 @@ #define CONFIG_G_DNL_PRODUCT_NUM 0x6601 #define CONFIG_G_DNL_THOR_VENDOR_NUM CONFIG_G_DNL_VENDOR_NUM #define CONFIG_G_DNL_THOR_PRODUCT_NUM 0x685D +#define CONFIG_G_DNL_UMS_VENDOR_NUM 0x0525 +#define CONFIG_G_DNL_UMS_PRODUCT_NUM 0xA4A5 #define CONFIG_G_DNL_MANUFACTURER "Samsung" /* Miscellaneous configurable options */ diff --git a/include/lcd.h b/include/lcd.h index cc2ee3f..ea5860c 100644 --- a/include/lcd.h +++ b/include/lcd.h @@ -26,8 +26,6 @@ void lcd_enable(void); void lcd_setcolreg(ushort regno, ushort red, ushort green, ushort blue); void lcd_initcolregs(void); -int lcd_getfgcolor(void); - /* gunzip_bmp used if CONFIG_VIDEO_BMP_GZIP */ struct bmp_image *gunzip_bmp(unsigned long addr, unsigned long *lenp, void **alloc_addr); @@ -333,7 +331,7 @@ void lcd_sync(void); #define LCD_COLOR4 2 #define LCD_COLOR8 3 #define LCD_COLOR16 4 - +#define LCD_COLOR32 5 /*----------------------------------------------------------------------*/ #if defined(CONFIG_LCD_INFO_BELOW_LOGO) # define LCD_INFO_X 0 @@ -384,6 +382,21 @@ void lcd_sync(void); # define CONSOLE_COLOR_GREY 14 # define CONSOLE_COLOR_WHITE 15 /* Must remain last / highest */ +#elif LCD_BPP == LCD_COLOR32 +/* + * 32bpp color definitions + */ +# define CONSOLE_COLOR_RED 0x00ff0000 +# define CONSOLE_COLOR_GREEN 0x0000ff00 +# define CONSOLE_COLOR_YELLOW 0x00ffff00 +# define CONSOLE_COLOR_BLUE 0x000000ff +# define CONSOLE_COLOR_MAGENTA 0x00ff00ff +# define CONSOLE_COLOR_CYAN 0x0000ffff +# define CONSOLE_COLOR_GREY 0x00aaaaaa +# define CONSOLE_COLOR_BLACK 0x00000000 +# define CONSOLE_COLOR_WHITE 0x00ffffff /* Must remain last / highest*/ +# define NBYTES(bit_code) (NBITS(bit_code) >> 3) + #else /* diff --git a/include/watchdog.h b/include/watchdog.h index bd0a8d6..9273fa1 100644 --- a/include/watchdog.h +++ b/include/watchdog.h @@ -21,7 +21,8 @@ int init_func_watchdog_reset(void); #endif -#ifdef CONFIG_WATCHDOG +#if defined(CONFIG_SYS_GENERIC_BOARD) && \ + (defined(CONFIG_WATCHDOG) || defined(CONFIG_HW_WATCHDOG)) #define INIT_FUNC_WATCHDOG_INIT init_func_watchdog_init, #define INIT_FUNC_WATCHDOG_RESET init_func_watchdog_reset, #else diff --git a/test/dfu/dfu_gadget_test.sh b/test/dfu/dfu_gadget_test.sh index 4133155..2f5b7db 100755 --- a/test/dfu/dfu_gadget_test.sh +++ b/test/dfu/dfu_gadget_test.sh @@ -1,5 +1,15 @@ #! /bin/bash +# Copyright (C) 2014 Samsung Electronics +# Lukasz Majewski <l.majewski@samsung.com> +# +# Script fixes, enhancements and testing: +# Stephen Warren <swarren@nvidia.com> +# +# DFU operation test script +# +# SPDX-License-Identifier: GPL-2.0+ + set -e # any command return if not equal to zero clear diff --git a/test/dfu/dfu_gadget_test_init.sh b/test/dfu/dfu_gadget_test_init.sh index 2163a68..640628e 100755 --- a/test/dfu/dfu_gadget_test_init.sh +++ b/test/dfu/dfu_gadget_test_init.sh @@ -1,5 +1,15 @@ #! /bin/bash +# Copyright (C) 2014 Samsung Electronics +# Lukasz Majewski <l.majewski@samsung.com> +# +# Script fixes, enhancements and testing: +# Stephen Warren <swarren@nvidia.com> +# +# Script for test files generation +# +# SPDX-License-Identifier: GPL-2.0+ + set -e # any command return if not equal to zero clear @@ -9,7 +19,11 @@ COLOUR_DEFAULT="\33[0m" LOG_DIR="./log" -TEST_FILES_SIZES="63 64 65 127 128 129 4095 4096 4097 959 960 961 1048575 1048576 8M" +if [ $# -eq 0 ]; then + TEST_FILES_SIZES="63 64 65 127 128 129 4095 4096 4097 959 960 961 1048575 1048576 8M" +else + TEST_FILES_SIZES=$@ +fi printf "Init script for generating data necessary for DFU test script" diff --git a/test/ums/README b/test/ums/README new file mode 100644 index 0000000..c80fbfe --- /dev/null +++ b/test/ums/README @@ -0,0 +1,30 @@ +UMS test script. + +ums_gadget_test.sh +================== + +Example usage: +1. On the target: + create UMS exportable partitions (with e.g. gpt write), or specify a + partition number (PART_NUM) as "-" to use the entire device + ums 0 mmc 0 +2. On the host: + sudo test/ums/ums_gadget_test.sh VID PID PART_NUM [-f FILE_SYSTEM] [test_file] + e.g. sudo test/ums/ums_gadget_test.sh 0525 a4a5 6 -f vfat ./dat_14M.img + +... where: + VID - UMS device USB Vendor ID + PID - UMS device USB Product ID + PART_NUM - is the partition number on which UMS operates or "-" to use the + whole device + +Information about available partitions on the target one can read with using +the 'mmc part' or 'part list' commands. + +The partition num (PART_NUM) can be specified as '-' for using the whole device. + +The [-f FILE_SYSTEM] optional switch allows for formatting target partition to +FILE_SYSTEM. + +The last, optional [test_file] parameter is for specifying the exact test file +to use. diff --git a/test/ums/ums_gadget_test.sh b/test/ums/ums_gadget_test.sh new file mode 100755 index 0000000..56d4616 --- /dev/null +++ b/test/ums/ums_gadget_test.sh @@ -0,0 +1,175 @@ +#! /bin/bash + +# Copyright (C) 2014 Samsung Electronics +# Lukasz Majewski <l.majewski@samsung.com> +# +# UMS operation test script +# +# SPDX-License-Identifier: GPL-2.0+ + +clear + +COLOUR_RED="\33[31m" +COLOUR_GREEN="\33[32m" +COLOUR_DEFAULT="\33[0m" + +DIR=./ +SUFFIX=img +RCV_DIR=rcv/ +LOG_FILE=./log/log-`date +%d-%m-%Y_%H-%M-%S` + +cd `dirname $0` +../dfu/dfu_gadget_test_init.sh 33M 97M + +cleanup () { + rm -rf $RCV_DIR $MNT_DIR +} + +control_c() +# run if user hits control-c +{ + echo -en "\n*** CTRL+C ***\n" + umount $MNT_DIR + cleanup + exit 0 +} + +# trap keyboard interrupt (control-c) +trap control_c SIGINT + +die () { + printf " $COLOUR_RED FAILED $COLOUR_DEFAULT \n" + cleanup + exit 1 +} + +calculate_md5sum () { + MD5SUM=`md5sum $1` + MD5SUM=`echo $MD5SUM | cut -d ' ' -f1` + echo "md5sum:"$MD5SUM +} + +ums_test_file () { + printf "$COLOUR_GREEN========================================================================================= $COLOUR_DEFAULT\n" + printf "File:$COLOUR_GREEN %s $COLOUR_DEFAULT\n" $1 + + mount /dev/$MEM_DEV $MNT_DIR + if [ -f $MNT_DIR/dat_* ]; then + rm $MNT_DIR/dat_* + fi + + cp ./$1 $MNT_DIR + umount $MNT_DIR + + + echo -n "TX: " + calculate_md5sum $1 + + MD5_TX=$MD5SUM + sleep 1 + N_FILE=$DIR$RCV_DIR${1:2}"_rcv" + + mount /dev/$MEM_DEV $MNT_DIR + cp $MNT_DIR/$1 $N_FILE || die $? + rm $MNT_DIR/$1 + umount $MNT_DIR + + echo -n "RX: " + calculate_md5sum $N_FILE + MD5_RX=$MD5SUM + + if [ "$MD5_TX" == "$MD5_RX" ]; then + printf " $COLOUR_GREEN -------> OK $COLOUR_DEFAULT \n" + else + printf " $COLOUR_RED -------> FAILED $COLOUR_DEFAULT \n" + cleanup + exit 1 + fi +} + +printf "$COLOUR_GREEN========================================================================================= $COLOUR_DEFAULT\n" +echo "U-boot UMS test program" + +if [ $EUID -ne 0 ]; then + echo "You must be root to do this." 1>&2 + exit 100 +fi + +if [ $# -lt 3 ]; then + echo "Wrong number of arguments" + echo "Example:" + echo "sudo ./ums_gadget_test.sh VID PID PART_NUM [-f ext4] [test_file]" + die +fi + +MNT_DIR="/mnt/tmp-ums-test" + +VID=$1; shift +PID=$1; shift +PART_NUM=$1; shift + +if [ "$1" == "-f" ]; then + shift + FS_TO_FORMAT=$1; shift +fi + +TEST_FILE=$1 + +for f in `find /sys -type f -name idProduct`; do + d=`dirname ${f}` + if [ `cat ${d}/idVendor` != "${VID}" ]; then + continue + fi + if [ `cat ${d}/idProduct` != "${PID}" ]; then + continue + fi + USB_DEV=${d} + break +done + +if [ -z "${USB_DEV}" ]; then + echo "Connect target" + echo "e.g. ums 0 mmc 0" + exit 1 +fi + +MEM_DEV=`find $USB_DEV -type d -name "sd[a-z]" | awk -F/ '{print $(NF)}' -` + +mkdir -p $RCV_DIR +if [ ! -d $MNT_DIR ]; then + mkdir -p $MNT_DIR +fi + +if [ "$PART_NUM" == "-" ]; then + PART_NUM="" +fi +MEM_DEV=$MEM_DEV$PART_NUM + +if [ -n "$FS_TO_FORMAT" ]; then + echo -n "Formatting partition /dev/$MEM_DEV to $FS_TO_FORMAT" + mkfs -t $FS_TO_FORMAT /dev/$MEM_DEV > /dev/null 2>&1 + if [ $? -eq 0 ]; then + printf " $COLOUR_GREEN DONE $COLOUR_DEFAULT \n" + else + die + fi +fi + +printf "Mount: /dev/$MEM_DEV \n" + +if [ -n "$TEST_FILE" ]; then + if [ ! -e $TEST_FILE ]; then + echo "No file: $TEST_FILE" + die + fi + ums_test_file $TEST_FILE +else + for file in $DIR*.$SUFFIX + do + ums_test_file $file + done +fi + +cleanup + +exit 0 diff --git a/tools/buildman/README b/tools/buildman/README index c30c1d4..d4e8404 100644 --- a/tools/buildman/README +++ b/tools/buildman/README @@ -3,6 +3,8 @@ # SPDX-License-Identifier: GPL-2.0+ # +(Please read 'How to change from MAKEALL' if you are used to that tool) + What is this? ============= @@ -39,9 +41,10 @@ Theory of Operation Buildman is a builder. It is not make, although it runs make. It does not produce any useful output on the terminal while building, except for -progress information. All the output (errors, warnings and binaries if you -are ask for them) is stored in output directories, which you can look at -while the build is progressing, or when it is finished. +progress information (except with -v, see below). All the output (errors, +warnings and binaries if you are ask for them) is stored in output +directories, which you can look at while the build is progressing, or when +it is finished. Buildman produces a concise summary of which boards succeeded and failed. It shows which commit introduced which board failure using a simple @@ -71,16 +74,21 @@ directory. It clones this repository into a copy for each thread, and the threads do not affect the state of your git repository. Any checkouts done by the thread affect only the working directory for that thread. -Buildman automatically selects the correct toolchain for each board. You -must supply suitable toolchains, but buildman takes care of selecting the +Buildman automatically selects the correct tool chain for each board. You +must supply suitable tool chains, but buildman takes care of selecting the right one. -Buildman always builds a branch, and always builds the upstream commit as -well, for comparison. It cannot build individual commits at present, unless -(maybe) you point it at an empty branch. Put all your commits in a branch, -set the branch's upstream to a valid value, and all will be well. Otherwise -buildman will perform random actions. Use -n to check what the random -actions might be. +Buildman generally builds a branch (with the -b flag), and in this case +builds the upstream commit as well, for comparison. It cannot build +individual commits at present, unless (maybe) you point it at an empty +branch. Put all your commits in a branch, set the branch's upstream to a +valid value, and all will be well. Otherwise buildman will perform random +actions. Use -n to check what the random actions might be. + +If you just want to build the current source tree, leave off the -b flag. +This will display results and errors as they happen. You can still look +at them later using -s. Note that buildman will assume that the source +has changed, and will build all specified boards in this case. Buildman is optimised for building many commits at once, for many boards. On multi-core machines, Buildman is fast because it uses most of the @@ -100,6 +108,15 @@ behaviour is a superset of exact or substring matching. Examples are: * '^tegra[23]0$' All boards with either Tegra20 or Tegra30 SoC * 'powerpc' All PowerPC boards +While the default is to OR the terms together, you can also make use of +the '&' operator to limit the selection: + +* 'freescale & arm sandbox' All Freescale boards with ARM architecture, + plus sandbox + +It is convenient to use the -n option to see whaat will be built based on +the subset given. + Buildman does not store intermediate object files. It optionally copies the binary output into a directory when a build is successful. Size information is always recorded. It needs a fair bit of disk space to work, @@ -126,6 +143,8 @@ example: root: / rest: /toolchains/* eldk: /opt/eldk-4.2 +arm: /opt/linaro/gcc-linaro-arm-linux-gnueabihf-4.8-2013.08_linux +aarch64: /opt/linaro/gcc-linaro-aarch64-none-elf-4.8-2013.10_linux [toolchain-alias] x86: i386 @@ -287,7 +306,7 @@ If it can't detect the upstream branch, try checking out the branch, and doing something like 'git branch --set-upstream <branch> upstream/master' or something similar. -As an exmmple: +As an example: Dry run, so not doing much. But I would do this: @@ -339,7 +358,7 @@ Building 18 commits for 1059 boards (4 threads, 1 job per thread) 528 36 124 /19062 1:13:30 : SIMPC8313_SP This means that it is building 19062 board/commit combinations. So far it -has managed to succesfully build 528. Another 36 have built with warnings, +has managed to successfully build 528. Another 36 have built with warnings, and 124 more didn't build at all. Buildman expects to complete the process in an hour and 15 minutes. Use this time to buy a faster computer. @@ -413,7 +432,7 @@ again. At commit 16, the error moves - you can see that the old error at line 120 is fixed, but there is a new one at line 126. This is probably only because -we added some code and moved the broken line futher down the file. +we added some code and moved the broken line father down the file. If many boards have the same error, then -e will display the error only once. This makes the output as concise as possible. @@ -491,7 +510,7 @@ You can also use -d to see a detailed size breakdown for each board. This list is sorted in order from largest growth to largest reduction. It is possible to go a little further with the -B option (--bloat). This -shows where U-Boot has bloted, breaking the size change down to the function +shows where U-Boot has bloated, breaking the size change down to the function level. Example output is below: $ ./tools/buildman/buildman -b us-mem4 -sSdB @@ -657,12 +676,122 @@ It is expected that any variables added are dealt with in U-Boot's config.mk file and documented in the README. +Quick Sanity Check +================== + +If you have made changes and want to do a quick sanity check of the +currently-checked-out source, run buildman without the -b flag. This will +build the selected boards and display build status and errors as it runs +(i.e. -v amd -e are enabled automatically). + + Other options ============= Buildman has various other command line options. Try --help to see them. +How to change from MAKEALL +========================== + +Buildman includes most of the features of MAKEALL and is generally faster +and easier to use. In particular it builds entire branches: if a particular +commit introduces an error in a particular board, buildman can easily show +you this, even if a later commit fixes that error. + +The reasons to deprecate MAKEALL are: +- We don't want to maintain two build systems +- Buildman is typically faster +- Buildman has a lot more features + +But still, many people will be sad to lose MAKEALL. If you are used to +MAKEALL, here are a few pointers. + +First you need to set up your tool chains - see the 'Setting up' section +for details. Once you have your required toolchain(s) detected then you are +ready to go. + +To build the current source tree, run buildman without a -b flag: + + ./tools/buildman/buildman <list of things to build> + +This will build the current source tree for the given boards and display +the results and errors. + +However buildman usually works on entire branches, and for that you must +specify a board flag: + + ./tools/buildman/buildman -b <branch_name> <list of things to build> + +followed by (afterwards, or perhaps concurrently in another terminal): + + ./tools/buildman/buildman -b <branch_name> -s <list of things to build> + +to see the results of the build. Rather than showing you all the output, +buildman just shows a summary, with red indicating that a commit introduced +an error and green indicating that a commit fixed an error. Use the -e +flag to see the full errors. + +If you really want to see build results as they happen, use -v when doing a +build (and -e if you want to see errors as well). + +You don't need to stick around on that branch while buildman is running. It +checks out its own copy of the source code, so you can change branches, +add commits, etc. without affecting the build in progress. + +The <list of things to build> can include board names, architectures or the +like. There are no flags to disambiguate since ambiguities are rare. Using +the examples from MAKEALL: + +Examples: + - build all Power Architecture boards: + MAKEALL -a powerpc + MAKEALL --arch powerpc + MAKEALL powerpc + ** buildman -b <branch> powerpc + - build all PowerPC boards manufactured by vendor "esd": + MAKEALL -a powerpc -v esd + ** buildman -b <branch> esd + - build all PowerPC boards manufactured either by "keymile" or "siemens": + MAKEALL -a powerpc -v keymile -v siemens + ** buildman -b <branch> keymile siemens + - build all Freescale boards with MPC83xx CPUs, plus all 4xx boards: + MAKEALL -c mpc83xx -v freescale 4xx + ** buildman -b <branch> mpc83xx freescale 4xx + +Buildman automatically tries to use all the CPUs in your machine. If you +are building a lot of boards it will use one thread for every CPU core +it detects in your machine. This is like MAKEALL's BUILD_NBUILDS option. +You can use the -T flag to change the number of threads. If you are only +building a few boards, buildman will automatically run make with the -j +flag to increase the number of concurrent make tasks. It isn't normally +that helpful to fiddle with this option, but if you use the BUILD_NCPUS +option in MAKEALL then -j is the equivalent in buildman. + +Buildman puts its output in ../<branch_name> by default but you can change +this with the -o option. Buildman normally does out-of-tree builds: use -i +to disable that if you really want to. But be careful that once you have +used -i you pollute buildman's copies of the source tree, and you will need +to remove the build directory (normally ../<branch_name>) to run buildman +in normal mode (without -i). + +Buildman doesn't keep the output result normally, but use the -k option to +do this. + +Please read 'Theory of Operation' a few times as it will make a lot of +things clearer. + +Some options you might like are: + + -B shows which functions are growing/shrinking in which commit - great + for finding code bloat. + -S shows image sizes for each commit (just an overall summary) + -u shows boards that you haven't built yet + --step 0 will build just the upstream commit and the last commit of your + branch. This is often a quick sanity check that your branch doesn't + break anything. But note this does not check bisectability! + + TODO ==== diff --git a/tools/buildman/board.py b/tools/buildman/board.py index 7bcc932..a333287 100644 --- a/tools/buildman/board.py +++ b/tools/buildman/board.py @@ -5,6 +5,72 @@ import re +class Expr: + """A single regular expression for matching boards to build""" + + def __init__(self, expr): + """Set up a new Expr object. + + Args: + expr: String cotaining regular expression to store + """ + self._expr = expr + self._re = re.compile(expr) + + def Matches(self, props): + """Check if any of the properties match the regular expression. + + Args: + props: List of properties to check + Returns: + True if any of the properties match the regular expression + """ + for prop in props: + if self._re.match(prop): + return True + return False + + def __str__(self): + return self._expr + +class Term: + """A list of expressions each of which must match with properties. + + This provides a list of 'AND' expressions, meaning that each must + match the board properties for that board to be built. + """ + def __init__(self): + self._expr_list = [] + self._board_count = 0 + + def AddExpr(self, expr): + """Add an Expr object to the list to check. + + Args: + expr: New Expr object to add to the list of those that must + match for a board to be built. + """ + self._expr_list.append(Expr(expr)) + + def __str__(self): + """Return some sort of useful string describing the term""" + return '&'.join([str(expr) for expr in self._expr_list]) + + def Matches(self, props): + """Check if any of the properties match this term + + Each of the expressions in the term is checked. All must match. + + Args: + props: List of properties to check + Returns: + True if all of the expressions in the Term match, else False + """ + for expr in self._expr_list: + if not expr.Matches(props): + return False + return True + class Board: """A particular board that we can build""" def __init__(self, status, arch, cpu, soc, vendor, board_name, target, options): @@ -124,6 +190,55 @@ class Boards: """ return [board.target for board in self._boards if board.build_it] + def _BuildTerms(self, args): + """Convert command line arguments to a list of terms. + + This deals with parsing of the arguments. It handles the '&' + operator, which joins several expressions into a single Term. + + For example: + ['arm & freescale sandbox', 'tegra'] + + will produce 3 Terms containing expressions as follows: + arm, freescale + sandbox + tegra + + The first Term has two expressions, both of which must match for + a board to be selected. + + Args: + args: List of command line arguments + Returns: + A list of Term objects + """ + syms = [] + for arg in args: + for word in arg.split(): + sym_build = [] + for term in word.split('&'): + if term: + sym_build.append(term) + sym_build.append('&') + syms += sym_build[:-1] + terms = [] + term = None + oper = None + for sym in syms: + if sym == '&': + oper = sym + elif oper: + term.AddExpr(sym) + oper = None + else: + if term: + terms.append(term) + term = Term() + term.AddExpr(sym) + if term: + terms.append(term) + return terms + def SelectBoards(self, args): """Mark boards selected based on args @@ -137,26 +252,21 @@ class Boards: due to each argument, arranged by argument. """ result = {} - argres = {} - for arg in args: - result[arg] = 0 - argres[arg] = re.compile(arg) + terms = self._BuildTerms(args) + result['all'] = 0 + for term in terms: + result[str(term)] = 0 for board in self._boards: - if args: - for arg in args: - argre = argres[arg] - match = False - for prop in board.props: - match = argre.match(prop) - if match: - break - if match: - if not board.build_it: - board.build_it = True - result[arg] += 1 - result['all'] += 1 + if terms: + match = False + for term in terms: + if term.Matches(board.props): + board.build_it = True + result[str(term)] += 1 + result['all'] += 1 + break else: board.build_it = True result['all'] += 1 diff --git a/tools/buildman/builder.py b/tools/buildman/builder.py index 48408ff..d5b8454 100644 --- a/tools/buildman/builder.py +++ b/tools/buildman/builder.py @@ -6,7 +6,6 @@ # import collections -import errno from datetime import datetime, timedelta import glob import os @@ -15,9 +14,9 @@ import Queue import shutil import string import sys -import threading import time +import builderthread import command import gitutil import terminal @@ -97,409 +96,6 @@ OUTCOME_OK, OUTCOME_WARNING, OUTCOME_ERROR, OUTCOME_UNKNOWN = range(4) trans_valid_chars = string.maketrans("/: ", "---") -def Mkdir(dirname): - """Make a directory if it doesn't already exist. - - Args: - dirname: Directory to create - """ - try: - os.mkdir(dirname) - except OSError as err: - if err.errno == errno.EEXIST: - pass - else: - raise - -class BuilderJob: - """Holds information about a job to be performed by a thread - - Members: - board: Board object to build - commits: List of commit options to build. - """ - def __init__(self): - self.board = None - self.commits = [] - - -class ResultThread(threading.Thread): - """This thread processes results from builder threads. - - It simply passes the results on to the builder. There is only one - result thread, and this helps to serialise the build output. - """ - def __init__(self, builder): - """Set up a new result thread - - Args: - builder: Builder which will be sent each result - """ - threading.Thread.__init__(self) - self.builder = builder - - def run(self): - """Called to start up the result thread. - - We collect the next result job and pass it on to the build. - """ - while True: - result = self.builder.out_queue.get() - self.builder.ProcessResult(result) - self.builder.out_queue.task_done() - - -class BuilderThread(threading.Thread): - """This thread builds U-Boot for a particular board. - - An input queue provides each new job. We run 'make' to build U-Boot - and then pass the results on to the output queue. - - Members: - builder: The builder which contains information we might need - thread_num: Our thread number (0-n-1), used to decide on a - temporary directory - """ - def __init__(self, builder, thread_num): - """Set up a new builder thread""" - threading.Thread.__init__(self) - self.builder = builder - self.thread_num = thread_num - - def Make(self, commit, brd, stage, cwd, *args, **kwargs): - """Run 'make' on a particular commit and board. - - The source code will already be checked out, so the 'commit' - argument is only for information. - - Args: - commit: Commit object that is being built - brd: Board object that is being built - stage: Stage of the build. Valid stages are: - distclean - can be called to clean source - config - called to configure for a board - build - the main make invocation - it does the build - args: A list of arguments to pass to 'make' - kwargs: A list of keyword arguments to pass to command.RunPipe() - - Returns: - CommandResult object - """ - return self.builder.do_make(commit, brd, stage, cwd, *args, - **kwargs) - - def RunCommit(self, commit_upto, brd, work_dir, do_config, force_build, - force_build_failures): - """Build a particular commit. - - If the build is already done, and we are not forcing a build, we skip - the build and just return the previously-saved results. - - Args: - commit_upto: Commit number to build (0...n-1) - brd: Board object to build - work_dir: Directory to which the source will be checked out - do_config: True to run a make <board>_defconfig on the source - force_build: Force a build even if one was previously done - force_build_failures: Force a bulid if the previous result showed - failure - - Returns: - tuple containing: - - CommandResult object containing the results of the build - - boolean indicating whether 'make config' is still needed - """ - # Create a default result - it will be overwritte by the call to - # self.Make() below, in the event that we do a build. - result = command.CommandResult() - result.return_code = 0 - if self.builder.in_tree: - out_dir = work_dir - else: - out_dir = os.path.join(work_dir, 'build') - - # Check if the job was already completed last time - done_file = self.builder.GetDoneFile(commit_upto, brd.target) - result.already_done = os.path.exists(done_file) - will_build = (force_build or force_build_failures or - not result.already_done) - if result.already_done and will_build: - # Get the return code from that build and use it - with open(done_file, 'r') as fd: - result.return_code = int(fd.readline()) - err_file = self.builder.GetErrFile(commit_upto, brd.target) - if os.path.exists(err_file) and os.stat(err_file).st_size: - result.stderr = 'bad' - elif not force_build: - # The build passed, so no need to build it again - will_build = False - - if will_build: - # We are going to have to build it. First, get a toolchain - if not self.toolchain: - try: - self.toolchain = self.builder.toolchains.Select(brd.arch) - except ValueError as err: - result.return_code = 10 - result.stdout = '' - result.stderr = str(err) - # TODO(sjg@chromium.org): This gets swallowed, but needs - # to be reported. - - if self.toolchain: - # Checkout the right commit - if commit_upto is not None: - commit = self.builder.commits[commit_upto] - if self.builder.checkout: - git_dir = os.path.join(work_dir, '.git') - gitutil.Checkout(commit.hash, git_dir, work_dir, - force=True) - else: - commit = self.builder.commit # Ick, fix this for BuildCommits() - - # Set up the environment and command line - env = self.toolchain.MakeEnvironment() - Mkdir(out_dir) - args = [] - if not self.builder.in_tree: - args.append('O=build') - args.append('-s') - if self.builder.num_jobs is not None: - args.extend(['-j', str(self.builder.num_jobs)]) - config_args = ['%s_defconfig' % brd.target] - config_out = '' - args.extend(self.builder.toolchains.GetMakeArguments(brd)) - - # If we need to reconfigure, do that now - if do_config: - result = self.Make(commit, brd, 'distclean', work_dir, - 'distclean', *args, env=env) - result = self.Make(commit, brd, 'config', work_dir, - *(args + config_args), env=env) - config_out = result.combined - do_config = False # No need to configure next time - if result.return_code == 0: - result = self.Make(commit, brd, 'build', work_dir, *args, - env=env) - result.stdout = config_out + result.stdout - else: - result.return_code = 1 - result.stderr = 'No tool chain for %s\n' % brd.arch - result.already_done = False - - result.toolchain = self.toolchain - result.brd = brd - result.commit_upto = commit_upto - result.out_dir = out_dir - return result, do_config - - def _WriteResult(self, result, keep_outputs): - """Write a built result to the output directory. - - Args: - result: CommandResult object containing result to write - keep_outputs: True to store the output binaries, False - to delete them - """ - # Fatal error - if result.return_code < 0: - return - - # Aborted? - if result.stderr and 'No child processes' in result.stderr: - return - - if result.already_done: - return - - # Write the output and stderr - output_dir = self.builder._GetOutputDir(result.commit_upto) - Mkdir(output_dir) - build_dir = self.builder.GetBuildDir(result.commit_upto, - result.brd.target) - Mkdir(build_dir) - - outfile = os.path.join(build_dir, 'log') - with open(outfile, 'w') as fd: - if result.stdout: - fd.write(result.stdout) - - errfile = self.builder.GetErrFile(result.commit_upto, - result.brd.target) - if result.stderr: - with open(errfile, 'w') as fd: - fd.write(result.stderr) - elif os.path.exists(errfile): - os.remove(errfile) - - if result.toolchain: - # Write the build result and toolchain information. - done_file = self.builder.GetDoneFile(result.commit_upto, - result.brd.target) - with open(done_file, 'w') as fd: - fd.write('%s' % result.return_code) - with open(os.path.join(build_dir, 'toolchain'), 'w') as fd: - print >>fd, 'gcc', result.toolchain.gcc - print >>fd, 'path', result.toolchain.path - print >>fd, 'cross', result.toolchain.cross - print >>fd, 'arch', result.toolchain.arch - fd.write('%s' % result.return_code) - - with open(os.path.join(build_dir, 'toolchain'), 'w') as fd: - print >>fd, 'gcc', result.toolchain.gcc - print >>fd, 'path', result.toolchain.path - - # Write out the image and function size information and an objdump - env = result.toolchain.MakeEnvironment() - lines = [] - for fname in ['u-boot', 'spl/u-boot-spl']: - cmd = ['%snm' % self.toolchain.cross, '--size-sort', fname] - nm_result = command.RunPipe([cmd], capture=True, - capture_stderr=True, cwd=result.out_dir, - raise_on_error=False, env=env) - if nm_result.stdout: - nm = self.builder.GetFuncSizesFile(result.commit_upto, - result.brd.target, fname) - with open(nm, 'w') as fd: - print >>fd, nm_result.stdout, - - cmd = ['%sobjdump' % self.toolchain.cross, '-h', fname] - dump_result = command.RunPipe([cmd], capture=True, - capture_stderr=True, cwd=result.out_dir, - raise_on_error=False, env=env) - rodata_size = '' - if dump_result.stdout: - objdump = self.builder.GetObjdumpFile(result.commit_upto, - result.brd.target, fname) - with open(objdump, 'w') as fd: - print >>fd, dump_result.stdout, - for line in dump_result.stdout.splitlines(): - fields = line.split() - if len(fields) > 5 and fields[1] == '.rodata': - rodata_size = fields[2] - - cmd = ['%ssize' % self.toolchain.cross, fname] - size_result = command.RunPipe([cmd], capture=True, - capture_stderr=True, cwd=result.out_dir, - raise_on_error=False, env=env) - if size_result.stdout: - lines.append(size_result.stdout.splitlines()[1] + ' ' + - rodata_size) - - # Write out the image sizes file. This is similar to the output - # of binutil's 'size' utility, but it omits the header line and - # adds an additional hex value at the end of each line for the - # rodata size - if len(lines): - sizes = self.builder.GetSizesFile(result.commit_upto, - result.brd.target) - with open(sizes, 'w') as fd: - print >>fd, '\n'.join(lines) - - # Now write the actual build output - if keep_outputs: - patterns = ['u-boot', '*.bin', 'u-boot.dtb', '*.map', - 'include/autoconf.mk', 'spl/u-boot-spl', - 'spl/u-boot-spl.bin'] - for pattern in patterns: - file_list = glob.glob(os.path.join(result.out_dir, pattern)) - for fname in file_list: - shutil.copy(fname, build_dir) - - - def RunJob(self, job): - """Run a single job - - A job consists of a building a list of commits for a particular board. - - Args: - job: Job to build - """ - brd = job.board - work_dir = self.builder.GetThreadDir(self.thread_num) - self.toolchain = None - if job.commits: - # Run 'make board_defconfig' on the first commit - do_config = True - commit_upto = 0 - force_build = False - for commit_upto in range(0, len(job.commits), job.step): - result, request_config = self.RunCommit(commit_upto, brd, - work_dir, do_config, - force_build or self.builder.force_build, - self.builder.force_build_failures) - failed = result.return_code or result.stderr - did_config = do_config - if failed and not do_config: - # If our incremental build failed, try building again - # with a reconfig. - if self.builder.force_config_on_failure: - result, request_config = self.RunCommit(commit_upto, - brd, work_dir, True, True, False) - did_config = True - if not self.builder.force_reconfig: - do_config = request_config - - # If we built that commit, then config is done. But if we got - # an warning, reconfig next time to force it to build the same - # files that created warnings this time. Otherwise an - # incremental build may not build the same file, and we will - # think that the warning has gone away. - # We could avoid this by using -Werror everywhere... - # For errors, the problem doesn't happen, since presumably - # the build stopped and didn't generate output, so will retry - # that file next time. So we could detect warnings and deal - # with them specially here. For now, we just reconfigure if - # anything goes work. - # Of course this is substantially slower if there are build - # errors/warnings (e.g. 2-3x slower even if only 10% of builds - # have problems). - if (failed and not result.already_done and not did_config and - self.builder.force_config_on_failure): - # If this build failed, try the next one with a - # reconfigure. - # Sometimes if the board_config.h file changes it can mess - # with dependencies, and we get: - # make: *** No rule to make target `include/autoconf.mk', - # needed by `depend'. - do_config = True - force_build = True - else: - force_build = False - if self.builder.force_config_on_failure: - if failed: - do_config = True - result.commit_upto = commit_upto - if result.return_code < 0: - raise ValueError('Interrupt') - - # We have the build results, so output the result - self._WriteResult(result, job.keep_outputs) - self.builder.out_queue.put(result) - else: - # Just build the currently checked-out build - result = self.RunCommit(None, True) - result.commit_upto = self.builder.upto - self.builder.out_queue.put(result) - - def run(self): - """Our thread's run function - - This thread picks a job from the queue, runs it, and then goes to the - next job. - """ - alive = True - while True: - job = self.builder.queue.get() - try: - if self.builder.active and alive: - self.RunJob(job) - except Exception as err: - alive = False - print err - self.builder.queue.task_done() - - class Builder: """Class for building U-Boot for a particular commit. @@ -614,19 +210,20 @@ class Builder: self.force_reconfig = False self._step = step self.in_tree = False + self._error_lines = 0 self.col = terminal.Color() self.queue = Queue.Queue() self.out_queue = Queue.Queue() for i in range(self.num_threads): - t = BuilderThread(self, i) + t = builderthread.BuilderThread(self, i) t.setDaemon(True) t.start() self.threads.append(t) self.last_line_len = 0 - t = ResultThread(self) + t = builderthread.ResultThread(self) t.setDaemon(True) t.start() self.threads.append(t) @@ -639,6 +236,20 @@ class Builder: for t in self.threads: del t + def SetDisplayOptions(self, show_errors=False, show_sizes=False, + show_detail=False, show_bloat=False): + """Setup display options for the builder. + + show_errors: True to show summarised error/warning info + show_sizes: Show size deltas + show_detail: Show detail for each board + show_bloat: Show detail for each function + """ + self._show_errors = show_errors + self._show_sizes = show_sizes + self._show_detail = show_detail + self._show_bloat = show_bloat + def _AddTimestamp(self): """Add a new timestamp to the list and record the build period. @@ -711,7 +322,8 @@ class Builder: """Process the result of a build, showing progress information Args: - result: A CommandResult object + result: A CommandResult object, which indicates the result for + a single build """ col = terminal.Color() if result: @@ -729,6 +341,13 @@ class Builder: self.warned += 1 if result.already_done: self.already_done += 1 + if self._verbose: + print '\r', + self.ClearLine(0) + boards_selected = {target : result.brd} + self.ResetResultSummary(boards_selected) + self.ProduceResultSummary(result.commit_upto, self.commits, + boards_selected) else: target = '(starting)' @@ -752,7 +371,7 @@ class Builder: name += target print line + name, - length = 13 + len(name) + length = 14 + len(name) self.ClearLine(length) def _GetOutputDir(self, commit_upto): @@ -763,10 +382,13 @@ class Builder: Args: commit_upto: Commit number to use (0..self.count-1) """ - commit = self.commits[commit_upto] - subject = commit.subject.translate(trans_valid_chars) - commit_dir = ('%02d_of_%02d_g%s_%s' % (commit_upto + 1, - self.commit_count, commit.hash, subject[:20])) + if self.commits: + commit = self.commits[commit_upto] + subject = commit.subject.translate(trans_valid_chars) + commit_dir = ('%02d_of_%02d_g%s_%s' % (commit_upto + 1, + self.commit_count, commit.hash, subject[:20])) + else: + commit_dir = 'current' output_dir = os.path.join(self.base_dir, commit_dir) return output_dir @@ -1270,10 +892,13 @@ class Builder: self.col.MAGENTA) for arch, target_list in arch_list.iteritems(): print '%10s: %s' % (arch, target_list) + self._error_lines += 1 if better_err: print self.col.Color(self.col.GREEN, '\n'.join(better_err)) + self._error_lines += 1 if worse_err: print self.col.Color(self.col.RED, '\n'.join(worse_err)) + self._error_lines += 1 if show_sizes: self.PrintSizeSummary(board_selected, board_dict, show_detail, @@ -1292,9 +917,18 @@ class Builder: print "Boards not built (%d): %s" % (len(not_built), ', '.join(not_built)) + def ProduceResultSummary(self, commit_upto, commits, board_selected): + board_dict, err_lines = self.GetResultSummary(board_selected, + commit_upto, read_func_sizes=self._show_bloat) + if commits: + msg = '%02d: %s' % (commit_upto + 1, + commits[commit_upto].subject) + print self.col.Color(self.col.BLUE, msg) + self.PrintResultSummary(board_selected, board_dict, + err_lines if self._show_errors else [], + self._show_sizes, self._show_detail, self._show_bloat) - def ShowSummary(self, commits, board_selected, show_errors, show_sizes, - show_detail, show_bloat): + def ShowSummary(self, commits, board_selected): """Show a build summary for U-Boot for a given board list. Reset the result summary, then repeatedly call GetResultSummary on @@ -1303,23 +937,16 @@ class Builder: Args: commit: Commit objects to summarise board_selected: Dict containing boards to summarise - show_errors: Show errors that occured - show_sizes: Show size deltas - show_detail: Show detail for each board - show_bloat: Show detail for each function """ - self.commit_count = len(commits) + self.commit_count = len(commits) if commits else 1 self.commits = commits self.ResetResultSummary(board_selected) + self._error_lines = 0 for commit_upto in range(0, self.commit_count, self._step): - board_dict, err_lines = self.GetResultSummary(board_selected, - commit_upto, read_func_sizes=show_bloat) - msg = '%02d: %s' % (commit_upto + 1, commits[commit_upto].subject) - print self.col.Color(self.col.BLUE, msg) - self.PrintResultSummary(board_selected, board_dict, - err_lines if show_errors else [], show_sizes, show_detail, - show_bloat) + self.ProduceResultSummary(commit_upto, commits, board_selected) + if not self._error_lines: + print self.col.Color(self.col.GREEN, '(no errors to report)') def SetupBuild(self, board_selected, commits): @@ -1330,45 +957,11 @@ class Builder: commits: Selected commits to build """ # First work out how many commits we will build - count = (len(commits) + self._step - 1) / self._step + count = (self.commit_count + self._step - 1) / self._step self.count = len(board_selected) * count self.upto = self.warned = self.fail = 0 self._timestamps = collections.deque() - def BuildBoardsForCommit(self, board_selected, keep_outputs): - """Build all boards for a single commit""" - self.SetupBuild(board_selected) - self.count = len(board_selected) - for brd in board_selected.itervalues(): - job = BuilderJob() - job.board = brd - job.commits = None - job.keep_outputs = keep_outputs - self.queue.put(brd) - - self.queue.join() - self.out_queue.join() - print - self.ClearLine(0) - - def BuildCommits(self, commits, board_selected, show_errors, keep_outputs): - """Build all boards for all commits (non-incremental)""" - self.commit_count = len(commits) - - self.ResetResultSummary(board_selected) - for self.commit_upto in range(self.commit_count): - self.SelectCommit(commits[self.commit_upto]) - self.SelectOutputDir() - Mkdir(self.output_dir) - - self.BuildBoardsForCommit(board_selected, keep_outputs) - board_dict, err_lines = self.GetResultSummary() - self.PrintResultSummary(board_selected, board_dict, - err_lines if show_errors else []) - - if self.already_done: - print '%d builds already done' % self.already_done - def GetThreadDir(self, thread_num): """Get the directory path to the working dir for a thread. @@ -1377,22 +970,23 @@ class Builder: """ return os.path.join(self._working_dir, '%02d' % thread_num) - def _PrepareThread(self, thread_num): + def _PrepareThread(self, thread_num, setup_git): """Prepare the working directory for a thread. This clones or fetches the repo into the thread's work directory. Args: thread_num: Thread number (0, 1, ...) + setup_git: True to set up a git repo clone """ thread_dir = self.GetThreadDir(thread_num) - Mkdir(thread_dir) + builderthread.Mkdir(thread_dir) git_dir = os.path.join(thread_dir, '.git') # Clone the repo if it doesn't already exist # TODO(sjg@chromium): Perhaps some git hackery to symlink instead, so # we have a private index but uses the origin repo's contents? - if self.git_dir: + if setup_git and self.git_dir: src_dir = os.path.abspath(self.git_dir) if os.path.exists(git_dir): gitutil.Fetch(git_dir, thread_dir) @@ -1400,17 +994,18 @@ class Builder: print 'Cloning repo for thread %d' % thread_num gitutil.Clone(src_dir, thread_dir) - def _PrepareWorkingSpace(self, max_threads): + def _PrepareWorkingSpace(self, max_threads, setup_git): """Prepare the working directory for use. Set up the git repo for each thread. Args: max_threads: Maximum number of threads we expect to need. + setup_git: True to set up a git repo clone """ - Mkdir(self._working_dir) + builderthread.Mkdir(self._working_dir) for thread in range(max_threads): - self._PrepareThread(thread) + self._PrepareThread(thread, setup_git) def _PrepareOutputSpace(self): """Get the output directories ready to receive files. @@ -1427,29 +1022,31 @@ class Builder: if dirname not in dir_list: shutil.rmtree(dirname) - def BuildBoards(self, commits, board_selected, show_errors, keep_outputs): + def BuildBoards(self, commits, board_selected, keep_outputs, verbose): """Build all commits for a list of boards Args: commits: List of commits to be build, each a Commit object boards_selected: Dict of selected boards, key is target name, value is Board object - show_errors: True to show summarised error/warning info keep_outputs: True to save build output files + verbose: Display build results as they are completed """ - self.commit_count = len(commits) + self.commit_count = len(commits) if commits else 1 self.commits = commits + self._verbose = verbose self.ResetResultSummary(board_selected) - Mkdir(self.base_dir) - self._PrepareWorkingSpace(min(self.num_threads, len(board_selected))) + builderthread.Mkdir(self.base_dir) + self._PrepareWorkingSpace(min(self.num_threads, len(board_selected)), + commits is not None) self._PrepareOutputSpace() self.SetupBuild(board_selected, commits) self.ProcessResult(None) # Create jobs to build all commits for each board for brd in board_selected.itervalues(): - job = BuilderJob() + job = builderthread.BuilderJob() job.board = brd job.commits = commits job.keep_outputs = keep_outputs diff --git a/tools/buildman/builderthread.py b/tools/buildman/builderthread.py new file mode 100644 index 0000000..32297e2 --- /dev/null +++ b/tools/buildman/builderthread.py @@ -0,0 +1,434 @@ +# Copyright (c) 2014 Google, Inc +# +# SPDX-License-Identifier: GPL-2.0+ +# + +import errno +import glob +import os +import shutil +import threading + +import command +import gitutil + +def Mkdir(dirname): + """Make a directory if it doesn't already exist. + + Args: + dirname: Directory to create + """ + try: + os.mkdir(dirname) + except OSError as err: + if err.errno == errno.EEXIST: + pass + else: + raise + +class BuilderJob: + """Holds information about a job to be performed by a thread + + Members: + board: Board object to build + commits: List of commit options to build. + """ + def __init__(self): + self.board = None + self.commits = [] + + +class ResultThread(threading.Thread): + """This thread processes results from builder threads. + + It simply passes the results on to the builder. There is only one + result thread, and this helps to serialise the build output. + """ + def __init__(self, builder): + """Set up a new result thread + + Args: + builder: Builder which will be sent each result + """ + threading.Thread.__init__(self) + self.builder = builder + + def run(self): + """Called to start up the result thread. + + We collect the next result job and pass it on to the build. + """ + while True: + result = self.builder.out_queue.get() + self.builder.ProcessResult(result) + self.builder.out_queue.task_done() + + +class BuilderThread(threading.Thread): + """This thread builds U-Boot for a particular board. + + An input queue provides each new job. We run 'make' to build U-Boot + and then pass the results on to the output queue. + + Members: + builder: The builder which contains information we might need + thread_num: Our thread number (0-n-1), used to decide on a + temporary directory + """ + def __init__(self, builder, thread_num): + """Set up a new builder thread""" + threading.Thread.__init__(self) + self.builder = builder + self.thread_num = thread_num + + def Make(self, commit, brd, stage, cwd, *args, **kwargs): + """Run 'make' on a particular commit and board. + + The source code will already be checked out, so the 'commit' + argument is only for information. + + Args: + commit: Commit object that is being built + brd: Board object that is being built + stage: Stage of the build. Valid stages are: + distclean - can be called to clean source + config - called to configure for a board + build - the main make invocation - it does the build + args: A list of arguments to pass to 'make' + kwargs: A list of keyword arguments to pass to command.RunPipe() + + Returns: + CommandResult object + """ + return self.builder.do_make(commit, brd, stage, cwd, *args, + **kwargs) + + def RunCommit(self, commit_upto, brd, work_dir, do_config, force_build, + force_build_failures): + """Build a particular commit. + + If the build is already done, and we are not forcing a build, we skip + the build and just return the previously-saved results. + + Args: + commit_upto: Commit number to build (0...n-1) + brd: Board object to build + work_dir: Directory to which the source will be checked out + do_config: True to run a make <board>_defconfig on the source + force_build: Force a build even if one was previously done + force_build_failures: Force a bulid if the previous result showed + failure + + Returns: + tuple containing: + - CommandResult object containing the results of the build + - boolean indicating whether 'make config' is still needed + """ + # Create a default result - it will be overwritte by the call to + # self.Make() below, in the event that we do a build. + result = command.CommandResult() + result.return_code = 0 + if self.builder.in_tree: + out_dir = work_dir + else: + out_dir = os.path.join(work_dir, 'build') + + # Check if the job was already completed last time + done_file = self.builder.GetDoneFile(commit_upto, brd.target) + result.already_done = os.path.exists(done_file) + will_build = (force_build or force_build_failures or + not result.already_done) + if result.already_done and will_build: + # Get the return code from that build and use it + with open(done_file, 'r') as fd: + result.return_code = int(fd.readline()) + err_file = self.builder.GetErrFile(commit_upto, brd.target) + if os.path.exists(err_file) and os.stat(err_file).st_size: + result.stderr = 'bad' + elif not force_build: + # The build passed, so no need to build it again + will_build = False + + if will_build: + # We are going to have to build it. First, get a toolchain + if not self.toolchain: + try: + self.toolchain = self.builder.toolchains.Select(brd.arch) + except ValueError as err: + result.return_code = 10 + result.stdout = '' + result.stderr = str(err) + # TODO(sjg@chromium.org): This gets swallowed, but needs + # to be reported. + + if self.toolchain: + # Checkout the right commit + if self.builder.commits: + commit = self.builder.commits[commit_upto] + if self.builder.checkout: + git_dir = os.path.join(work_dir, '.git') + gitutil.Checkout(commit.hash, git_dir, work_dir, + force=True) + else: + commit = 'current' + + # Set up the environment and command line + env = self.toolchain.MakeEnvironment() + Mkdir(out_dir) + args = [] + cwd = work_dir + if not self.builder.in_tree: + if commit_upto is None: + # In this case we are building in the original source + # directory (i.e. the current directory where buildman + # is invoked. The output directory is set to this + # thread's selected work directory. + # + # Symlinks can confuse U-Boot's Makefile since + # we may use '..' in our path, so remove them. + work_dir = os.path.realpath(work_dir) + args.append('O=%s/build' % work_dir) + cwd = None + else: + args.append('O=build') + args.append('-s') + if self.builder.num_jobs is not None: + args.extend(['-j', str(self.builder.num_jobs)]) + config_args = ['%s_defconfig' % brd.target] + config_out = '' + args.extend(self.builder.toolchains.GetMakeArguments(brd)) + + # If we need to reconfigure, do that now + if do_config: + result = self.Make(commit, brd, 'distclean', cwd, + 'distclean', *args, env=env) + result = self.Make(commit, brd, 'config', cwd, + *(args + config_args), env=env) + config_out = result.combined + do_config = False # No need to configure next time + if result.return_code == 0: + result = self.Make(commit, brd, 'build', cwd, *args, + env=env) + result.stdout = config_out + result.stdout + else: + result.return_code = 1 + result.stderr = 'No tool chain for %s\n' % brd.arch + result.already_done = False + + result.toolchain = self.toolchain + result.brd = brd + result.commit_upto = commit_upto + result.out_dir = out_dir + return result, do_config + + def _WriteResult(self, result, keep_outputs): + """Write a built result to the output directory. + + Args: + result: CommandResult object containing result to write + keep_outputs: True to store the output binaries, False + to delete them + """ + # Fatal error + if result.return_code < 0: + return + + # Aborted? + if result.stderr and 'No child processes' in result.stderr: + return + + if result.already_done: + return + + # Write the output and stderr + output_dir = self.builder._GetOutputDir(result.commit_upto) + Mkdir(output_dir) + build_dir = self.builder.GetBuildDir(result.commit_upto, + result.brd.target) + Mkdir(build_dir) + + outfile = os.path.join(build_dir, 'log') + with open(outfile, 'w') as fd: + if result.stdout: + fd.write(result.stdout) + + errfile = self.builder.GetErrFile(result.commit_upto, + result.brd.target) + if result.stderr: + with open(errfile, 'w') as fd: + fd.write(result.stderr) + elif os.path.exists(errfile): + os.remove(errfile) + + if result.toolchain: + # Write the build result and toolchain information. + done_file = self.builder.GetDoneFile(result.commit_upto, + result.brd.target) + with open(done_file, 'w') as fd: + fd.write('%s' % result.return_code) + with open(os.path.join(build_dir, 'toolchain'), 'w') as fd: + print >>fd, 'gcc', result.toolchain.gcc + print >>fd, 'path', result.toolchain.path + print >>fd, 'cross', result.toolchain.cross + print >>fd, 'arch', result.toolchain.arch + fd.write('%s' % result.return_code) + + with open(os.path.join(build_dir, 'toolchain'), 'w') as fd: + print >>fd, 'gcc', result.toolchain.gcc + print >>fd, 'path', result.toolchain.path + + # Write out the image and function size information and an objdump + env = result.toolchain.MakeEnvironment() + lines = [] + for fname in ['u-boot', 'spl/u-boot-spl']: + cmd = ['%snm' % self.toolchain.cross, '--size-sort', fname] + nm_result = command.RunPipe([cmd], capture=True, + capture_stderr=True, cwd=result.out_dir, + raise_on_error=False, env=env) + if nm_result.stdout: + nm = self.builder.GetFuncSizesFile(result.commit_upto, + result.brd.target, fname) + with open(nm, 'w') as fd: + print >>fd, nm_result.stdout, + + cmd = ['%sobjdump' % self.toolchain.cross, '-h', fname] + dump_result = command.RunPipe([cmd], capture=True, + capture_stderr=True, cwd=result.out_dir, + raise_on_error=False, env=env) + rodata_size = '' + if dump_result.stdout: + objdump = self.builder.GetObjdumpFile(result.commit_upto, + result.brd.target, fname) + with open(objdump, 'w') as fd: + print >>fd, dump_result.stdout, + for line in dump_result.stdout.splitlines(): + fields = line.split() + if len(fields) > 5 and fields[1] == '.rodata': + rodata_size = fields[2] + + cmd = ['%ssize' % self.toolchain.cross, fname] + size_result = command.RunPipe([cmd], capture=True, + capture_stderr=True, cwd=result.out_dir, + raise_on_error=False, env=env) + if size_result.stdout: + lines.append(size_result.stdout.splitlines()[1] + ' ' + + rodata_size) + + # Write out the image sizes file. This is similar to the output + # of binutil's 'size' utility, but it omits the header line and + # adds an additional hex value at the end of each line for the + # rodata size + if len(lines): + sizes = self.builder.GetSizesFile(result.commit_upto, + result.brd.target) + with open(sizes, 'w') as fd: + print >>fd, '\n'.join(lines) + + # Now write the actual build output + if keep_outputs: + patterns = ['u-boot', '*.bin', 'u-boot.dtb', '*.map', + 'include/autoconf.mk', 'spl/u-boot-spl', + 'spl/u-boot-spl.bin'] + for pattern in patterns: + file_list = glob.glob(os.path.join(result.out_dir, pattern)) + for fname in file_list: + shutil.copy(fname, build_dir) + + + def RunJob(self, job): + """Run a single job + + A job consists of a building a list of commits for a particular board. + + Args: + job: Job to build + """ + brd = job.board + work_dir = self.builder.GetThreadDir(self.thread_num) + self.toolchain = None + if job.commits: + # Run 'make board_defconfig' on the first commit + do_config = True + commit_upto = 0 + force_build = False + for commit_upto in range(0, len(job.commits), job.step): + result, request_config = self.RunCommit(commit_upto, brd, + work_dir, do_config, + force_build or self.builder.force_build, + self.builder.force_build_failures) + failed = result.return_code or result.stderr + did_config = do_config + if failed and not do_config: + # If our incremental build failed, try building again + # with a reconfig. + if self.builder.force_config_on_failure: + result, request_config = self.RunCommit(commit_upto, + brd, work_dir, True, True, False) + did_config = True + if not self.builder.force_reconfig: + do_config = request_config + + # If we built that commit, then config is done. But if we got + # an warning, reconfig next time to force it to build the same + # files that created warnings this time. Otherwise an + # incremental build may not build the same file, and we will + # think that the warning has gone away. + # We could avoid this by using -Werror everywhere... + # For errors, the problem doesn't happen, since presumably + # the build stopped and didn't generate output, so will retry + # that file next time. So we could detect warnings and deal + # with them specially here. For now, we just reconfigure if + # anything goes work. + # Of course this is substantially slower if there are build + # errors/warnings (e.g. 2-3x slower even if only 10% of builds + # have problems). + if (failed and not result.already_done and not did_config and + self.builder.force_config_on_failure): + # If this build failed, try the next one with a + # reconfigure. + # Sometimes if the board_config.h file changes it can mess + # with dependencies, and we get: + # make: *** No rule to make target `include/autoconf.mk', + # needed by `depend'. + do_config = True + force_build = True + else: + force_build = False + if self.builder.force_config_on_failure: + if failed: + do_config = True + result.commit_upto = commit_upto + if result.return_code < 0: + raise ValueError('Interrupt') + + # We have the build results, so output the result + self._WriteResult(result, job.keep_outputs) + self.builder.out_queue.put(result) + else: + # Just build the currently checked-out build + result, request_config = self.RunCommit(None, brd, work_dir, True, + True, self.builder.force_build_failures) + result.commit_upto = 0 + self._WriteResult(result, job.keep_outputs) + self.builder.out_queue.put(result) + + def run(self): + """Our thread's run function + + This thread picks a job from the queue, runs it, and then goes to the + next job. + """ + alive = True + while True: + job = self.builder.queue.get() + if self.builder.active and alive: + self.RunJob(job) + ''' + try: + if self.builder.active and alive: + self.RunJob(job) + except Exception as err: + alive = False + print err + ''' + self.builder.queue.task_done() diff --git a/tools/buildman/buildman.py b/tools/buildman/buildman.py index 42847ac..6ca8dc6 100755 --- a/tools/buildman/buildman.py +++ b/tools/buildman/buildman.py @@ -70,6 +70,9 @@ parser.add_option('-c', '--count', dest='count', type='int', parser.add_option('-C', '--force-reconfig', dest='force_reconfig', action='store_true', default=False, help='Reconfigure for every commit (disable incremental build)') +parser.add_option('-d', '--detail', dest='show_detail', + action='store_true', default=False, + help='Show detailed information for each board in summary') parser.add_option('-e', '--show_errors', action='store_true', default=False, help='Show errors and warnings') parser.add_option('-f', '--force-build', dest='force_build', @@ -78,11 +81,10 @@ parser.add_option('-f', '--force-build', dest='force_build', parser.add_option('-F', '--force-build-failures', dest='force_build_failures', action='store_true', default=False, help='Force build of previously-failed build') -parser.add_option('-d', '--detail', dest='show_detail', - action='store_true', default=False, - help='Show detailed information for each board in summary') parser.add_option('-g', '--git', type='string', help='Git repo containing branch to build', default='.') +parser.add_option('-G', '--config-file', type='string', + help='Path to buildman config file', default='') parser.add_option('-H', '--full-help', action='store_true', dest='full_help', default=False, help='Display the README file') parser.add_option('-i', '--in-tree', dest='in_tree', @@ -96,6 +98,9 @@ parser.add_option('--list-tool-chains', action='store_true', default=False, help='List available tool chains') parser.add_option('-n', '--dry-run', action='store_true', dest='dry_run', default=False, help="Do a try run (describe actions, but no nothing)") +parser.add_option('-o', '--output-dir', type='string', + dest='output_dir', default='..', + help='Directory where all builds happen and buildman has its workspace (default is ../)') parser.add_option('-Q', '--quick', action='store_true', default=False, help='Do a rough build, with limited warning resolution') parser.add_option('-s', '--summary', action='store_true', @@ -110,9 +115,8 @@ parser.add_option('-T', '--threads', type='int', default=None, help='Number of builder threads to use') parser.add_option('-u', '--show_unknown', action='store_true', default=False, help='Show boards with unknown build result') -parser.add_option('-o', '--output-dir', type='string', - dest='output_dir', default='..', - help='Directory where all builds happen and buildman has its workspace (default is ../)') +parser.add_option('-v', '--verbose', action='store_true', + default=False, help='Show build results while the build progresses') parser.usage = """buildman -b <branch> [options] diff --git a/tools/buildman/control.py b/tools/buildman/control.py index 75b6498..98a07a2 100644 --- a/tools/buildman/control.py +++ b/tools/buildman/control.py @@ -21,15 +21,20 @@ def GetPlural(count): """Returns a plural 's' if count is not 1""" return 's' if count != 1 else '' -def GetActionSummary(is_summary, count, selected, options): +def GetActionSummary(is_summary, commits, selected, options): """Return a string summarising the intended action. Returns: Summary string. """ - count = (count + options.step - 1) / options.step - str = '%s %d commit%s for %d boards' % ( - 'Summary of' if is_summary else 'Building', count, GetPlural(count), + if commits: + count = len(commits) + count = (count + options.step - 1) / options.step + commit_str = '%d commit%s' % (count, GetPlural(count)) + else: + commit_str = 'current source' + str = '%s %s for %d boards' % ( + 'Summary of' if is_summary else 'Building', commit_str, len(selected)) str += ' (%d thread%s, %d job%s per thread)' % (options.threads, GetPlural(options.threads), options.jobs, GetPlural(options.jobs)) @@ -53,13 +58,18 @@ def ShowActions(series, why_selected, boards_selected, builder, options): col = terminal.Color() print 'Dry run, so not doing much. But I would do this:' print - print GetActionSummary(False, len(series.commits), boards_selected, + if series: + commits = series.commits + else: + commits = None + print GetActionSummary(False, commits, boards_selected, options) print 'Build directory: %s' % builder.base_dir - for upto in range(0, len(series.commits), options.step): - commit = series.commits[upto] - print ' ', col.Color(col.YELLOW, commit.hash, bright=False), - print commit.subject + if commits: + for upto in range(0, len(series.commits), options.step): + commit = series.commits[upto] + print ' ', col.Color(col.YELLOW, commit.hash, bright=False), + print commit.subject print for arg in why_selected: if arg != 'all': @@ -76,7 +86,7 @@ def DoBuildman(options, args): """ gitutil.Setup() - bsettings.Setup() + bsettings.Setup(options.config_file) options.git_dir = os.path.join(options.git, '.git') toolchains = toolchain.Toolchains() @@ -93,15 +103,16 @@ def DoBuildman(options, args): count = options.count if count == -1: if not options.branch: - str = 'Please use -b to specify a branch to build' - print col.Color(col.RED, str) - sys.exit(1) - count = gitutil.CountCommitsInBranch(options.git_dir, options.branch) - if count is None: - str = "Branch '%s' not found or has no upstream" % options.branch - print col.Color(col.RED, str) - sys.exit(1) - count += 1 # Build upstream commit also + count = 1 + else: + count = gitutil.CountCommitsInBranch(options.git_dir, + options.branch) + if count is None: + str = ("Branch '%s' not found or has no upstream" % + options.branch) + print col.Color(col.RED, str) + sys.exit(1) + count += 1 # Build upstream commit also if not count: str = ("No commits found to process in branch '%s': " @@ -132,17 +143,30 @@ def DoBuildman(options, args): # upstream/master~..branch but that isn't possible if upstream/master is # a merge commit (it will list all the commits that form part of the # merge) - range_expr = gitutil.GetRangeInBranch(options.git_dir, options.branch) - upstream_commit = gitutil.GetUpstream(options.git_dir, options.branch) - series = patchstream.GetMetaDataForList(upstream_commit, options.git_dir, - 1) - # Conflicting tags are not a problem for buildman, since it does not use - # them. For example, Series-version is not useful for buildman. On the - # other hand conflicting tags will cause an error. So allow later tags - # to overwrite earlier ones. - series.allow_overwrite = True - series = patchstream.GetMetaDataForList(range_expr, options.git_dir, None, - series) + if options.branch: + if count == -1: + range_expr = gitutil.GetRangeInBranch(options.git_dir, + options.branch) + upstream_commit = gitutil.GetUpstream(options.git_dir, + options.branch) + series = patchstream.GetMetaDataForList(upstream_commit, + options.git_dir, 1) + + # Conflicting tags are not a problem for buildman, since it does + # not use them. For example, Series-version is not useful for + # buildman. On the other hand conflicting tags will cause an + # error. So allow later tags to overwrite earlier ones. + series.allow_overwrite = True + series = patchstream.GetMetaDataForList(range_expr, + options.git_dir, None, series) + else: + # Honour the count + series = patchstream.GetMetaDataForList(options.branch, + options.git_dir, count) + else: + series = None + options.verbose = True + options.show_errors = True # By default we have one thread per CPU. But if there are not enough jobs # we can have fewer threads and use a high '-j' value for make. @@ -162,7 +186,11 @@ def DoBuildman(options, args): sys.exit(1) # Create a new builder with the selected options - output_dir = os.path.join(options.output_dir, options.branch) + if options.branch: + dirname = options.branch + else: + dirname = 'current' + output_dir = os.path.join(options.output_dir, dirname) builder = Builder(toolchains, output_dir, options.git_dir, options.threads, options.jobs, gnu_make=gnu_make, checkout=True, show_unknown=options.show_unknown, step=options.step) @@ -180,15 +208,21 @@ def DoBuildman(options, args): # Work out which boards to build board_selected = boards.GetSelectedDict() - print GetActionSummary(options.summary, count, board_selected, options) + if series: + commits = series.commits + else: + commits = None + + print GetActionSummary(options.summary, commits, board_selected, + options) + builder.SetDisplayOptions(options.show_errors, options.show_sizes, + options.show_detail, options.show_bloat) if options.summary: # We can't show function sizes without board details at present if options.show_bloat: options.show_detail = True - builder.ShowSummary(series.commits, board_selected, - options.show_errors, options.show_sizes, - options.show_detail, options.show_bloat) + builder.ShowSummary(commits, board_selected) else: - builder.BuildBoards(series.commits, board_selected, - options.show_errors, options.keep_outputs) + builder.BuildBoards(commits, board_selected, + options.keep_outputs, options.verbose) diff --git a/tools/buildman/test.py b/tools/buildman/test.py index 068784a..a51c942 100644 --- a/tools/buildman/test.py +++ b/tools/buildman/test.py @@ -136,10 +136,10 @@ class TestBuild(unittest.TestCase): build.do_make = self.Make board_selected = self.boards.GetSelectedDict() - #build.BuildCommits(self.commits, board_selected, False) - build.BuildBoards(self.commits, board_selected, False, False) - build.ShowSummary(self.commits, board_selected, True, False, - False, False) + build.BuildBoards(self.commits, board_selected, keep_outputs=False, + verbose=False) + build.SetDisplayOptions(show_errors=True); + build.ShowSummary(self.commits, board_selected) def _testGit(self): """Test basic builder operation by building a branch""" @@ -165,5 +165,53 @@ class TestBuild(unittest.TestCase): args = ['tegra20'] control.DoBuildman(options, args) + def testBoardSingle(self): + """Test single board selection""" + self.assertEqual(self.boards.SelectBoards(['sandbox']), + {'all': 1, 'sandbox': 1}) + + def testBoardArch(self): + """Test single board selection""" + self.assertEqual(self.boards.SelectBoards(['arm']), + {'all': 2, 'arm': 2}) + + def testBoardArchSingle(self): + """Test single board selection""" + self.assertEqual(self.boards.SelectBoards(['arm sandbox']), + {'all': 3, 'arm': 2, 'sandbox' : 1}) + + def testBoardArchSingleMultiWord(self): + """Test single board selection""" + self.assertEqual(self.boards.SelectBoards(['arm', 'sandbox']), + {'all': 3, 'arm': 2, 'sandbox' : 1}) + + def testBoardSingleAnd(self): + """Test single board selection""" + self.assertEqual(self.boards.SelectBoards(['Tester & arm']), + {'all': 2, 'Tester&arm': 2}) + + def testBoardTwoAnd(self): + """Test single board selection""" + self.assertEqual(self.boards.SelectBoards(['Tester', '&', 'arm', + 'Tester' '&', 'powerpc', + 'sandbox']), + {'all': 5, 'Tester&powerpc': 2, 'Tester&arm': 2, + 'sandbox' : 1}) + + def testBoardAll(self): + """Test single board selection""" + self.assertEqual(self.boards.SelectBoards([]), {'all': 5}) + + def testBoardRegularExpression(self): + """Test single board selection""" + self.assertEqual(self.boards.SelectBoards(['T.*r&^Po']), + {'T.*r&^Po': 2, 'all': 2}) + + def testBoardDuplicate(self): + """Test single board selection""" + self.assertEqual(self.boards.SelectBoards(['sandbox sandbox', + 'sandbox']), + {'all': 1, 'sandbox': 1}) + if __name__ == "__main__": unittest.main() diff --git a/tools/patman/gitutil.py b/tools/patman/gitutil.py index 65754f5..735c8dd 100644 --- a/tools/patman/gitutil.py +++ b/tools/patman/gitutil.py @@ -14,6 +14,35 @@ import terminal import checkpatch import settings +# True to use --no-decorate - we check this in Setup() +use_no_decorate = True + +def LogCmd(commit_range, git_dir=None, oneline=False, reverse=False, + count=None): + """Create a command to perform a 'git log' + + Args: + commit_range: Range expression to use for log, None for none + git_dir: Path to git repositiory (None to use default) + oneline: True to use --oneline, else False + reverse: True to reverse the log (--reverse) + count: Number of commits to list, or None for no limit + Return: + List containing command and arguments to run + """ + cmd = ['git'] + if git_dir: + cmd += ['--git-dir', git_dir] + cmd += ['log', '--no-color'] + if oneline: + cmd.append('--oneline') + if use_no_decorate: + cmd.append('--no-decorate') + if count is not None: + cmd.append('-n%d' % count) + if commit_range: + cmd.append(commit_range) + return cmd def CountCommitsToBranch(): """Returns number of commits between HEAD and the tracking branch. @@ -24,8 +53,7 @@ def CountCommitsToBranch(): Return: Number of patches that exist on top of the branch """ - pipe = [['git', 'log', '--no-color', '--oneline', '--no-decorate', - '@{upstream}..'], + pipe = [LogCmd('@{upstream}..', oneline=True), ['wc', '-l']] stdout = command.RunPipe(pipe, capture=True, oneline=True).stdout patch_count = int(stdout) @@ -87,8 +115,7 @@ def CountCommitsInBranch(git_dir, branch, include_upstream=False): range_expr = GetRangeInBranch(git_dir, branch, include_upstream) if not range_expr: return None - pipe = [['git', '--git-dir', git_dir, 'log', '--oneline', '--no-decorate', - range_expr], + pipe = [LogCmd(range_expr, git_dir=git_dir, oneline=True), ['wc', '-l']] result = command.RunPipe(pipe, capture=True, oneline=True) patch_count = int(result.stdout) @@ -102,7 +129,7 @@ def CountCommits(commit_range): Return: Number of patches that exist on top of the branch """ - pipe = [['git', 'log', '--oneline', '--no-decorate', commit_range], + pipe = [LogCmd(commit_range, oneline=True), ['wc', '-l']] stdout = command.RunPipe(pipe, capture=True, oneline=True).stdout patch_count = int(stdout) @@ -543,6 +570,9 @@ def Setup(): alias_fname = GetAliasFile() if alias_fname: settings.ReadGitAliases(alias_fname) + cmd = LogCmd(None, count=0) + use_no_decorate = (command.RunPipe([cmd], raise_on_error=False) + .return_code == 0) def GetHead(): """Get the hash of the current HEAD diff --git a/tools/patman/patchstream.py b/tools/patman/patchstream.py index 3228719..0040468 100644 --- a/tools/patman/patchstream.py +++ b/tools/patman/patchstream.py @@ -379,14 +379,9 @@ def GetMetaDataForList(commit_range, git_dir=None, count=None, Returns: A Series object containing information about the commits. """ - params = ['git', 'log', '--no-color', '--reverse', '--no-decorate', - commit_range] - if count is not None: - params[2:2] = ['-n%d' % count] - if git_dir: - params[1:1] = ['--git-dir', git_dir] - pipe = [params] - stdout = command.RunPipe(pipe, capture=True).stdout + params = gitutil.LogCmd(commit_range,reverse=True, count=count, + git_dir=git_dir) + stdout = command.RunPipe([params], capture=True).stdout ps = PatchStream(series, is_log=True) for line in stdout.splitlines(): ps.ProcessLine(line) |