diff options
45 files changed, 1902 insertions, 276 deletions
@@ -824,8 +824,10 @@ The following options need to be configured: CONFIG_CMD_FDOS * Dos diskette Support CONFIG_CMD_FLASH flinfo, erase, protect CONFIG_CMD_FPGA FPGA device initialization support + CONFIG_CMD_GETTIME * Get time since boot CONFIG_CMD_GO * the 'go' command (exec code) CONFIG_CMD_GREPENV * search environment + CONFIG_CMD_HASH * calculate hash / digest CONFIG_CMD_HWFLOW * RTS/CTS hw flow control CONFIG_CMD_I2C * I2C serial bus support CONFIG_CMD_IDE * IDE harddisk support @@ -860,6 +862,7 @@ The following options need to be configured: CONFIG_CMD_PING * send ICMP ECHO_REQUEST to network host CONFIG_CMD_PORTIO * Port I/O + CONFIG_CMD_READ * Read raw data from partition CONFIG_CMD_REGINFO * Register dump CONFIG_CMD_RUN run command in env variable CONFIG_CMD_SAVES * save S record dump @@ -1485,6 +1488,11 @@ CBFS (Coreboot Filesystem) support Support drawing of RLE8-compressed bitmaps on the LCD. + CONFIG_I2C_EDID + + Enables an 'i2c edid' command which can read EDID + information over I2C from an attached LCD display. + - Splash Screen Support: CONFIG_SPLASH_SCREEN @@ -2409,6 +2417,23 @@ CBFS (Coreboot Filesystem) support A better solution is to properly configure the firewall, but sometimes that is not allowed. +- Hashing support: + CONFIG_CMD_HASH + + This enables a generic 'hash' command which can produce + hashes / digests from a few algorithms (e.g. SHA1, SHA256). + + CONFIG_HASH_VERIFY + + Enable the hash verify command (hash -v). This adds to code + size a little. + + CONFIG_SHA1 - support SHA1 hashing + CONFIG_SHA256 - support SHA256 hashing + + Note: There is also a sha1sum command, which should perhaps + be deprecated in favour of 'hash sha1'. + - Show boot progress: CONFIG_SHOW_BOOT_PROGRESS diff --git a/arch/arm/cpu/arm926ejs/mxs/clock.c b/arch/arm/cpu/arm926ejs/mxs/clock.c index bfea6abeb07..4ff19c37efe 100644 --- a/arch/arm/cpu/arm926ejs/mxs/clock.c +++ b/arch/arm/cpu/arm926ejs/mxs/clock.c @@ -333,6 +333,8 @@ uint32_t mxc_get_clock(enum mxc_clock clk) return mx28_get_sspclk(MXC_SSPCLK2); case MXC_SSP3_CLK: return mx28_get_sspclk(MXC_SSPCLK3); + case MXC_XTAL_CLK: + return XTAL_FREQ_KHZ * 1000; } return 0; diff --git a/arch/arm/cpu/armv7/exynos/clock.c b/arch/arm/cpu/armv7/exynos/clock.c index 4f3b451be99..21e45d2e828 100644 --- a/arch/arm/cpu/armv7/exynos/clock.c +++ b/arch/arm/cpu/armv7/exynos/clock.c @@ -732,6 +732,21 @@ static unsigned long exynos5_get_i2c_clk(void) return aclk_66; } +static unsigned long exynos4_get_i2c_clk(void) +{ + struct exynos4_clock *clk = + (struct exynos4_clock *)samsung_get_base_clock(); + unsigned long sclk, aclk_100; + unsigned int ratio; + + sclk = get_pll_clk(APLL); + + ratio = (readl(&clk->div_top)) >> 4; + ratio &= 0xf; + aclk_100 = sclk / (ratio + 1); + return aclk_100; +} + unsigned long get_pll_clk(int pllreg) { if (cpu_is_exynos5()) @@ -752,6 +767,8 @@ unsigned long get_i2c_clk(void) { if (cpu_is_exynos5()) { return exynos5_get_i2c_clk(); + } else if (cpu_is_exynos4()) { + return exynos4_get_i2c_clk(); } else { debug("I2C clock is not set for this CPU\n"); return 0; diff --git a/arch/arm/cpu/armv7/exynos/pinmux.c b/arch/arm/cpu/armv7/exynos/pinmux.c index 7776add9db3..44ce0726e99 100644 --- a/arch/arm/cpu/armv7/exynos/pinmux.c +++ b/arch/arm/cpu/armv7/exynos/pinmux.c @@ -265,10 +265,74 @@ static int exynos5_pinmux_config(int peripheral, int flags) return 0; } +static void exynos4_i2c_config(int peripheral, int flags) +{ + struct exynos4_gpio_part1 *gpio1 = + (struct exynos4_gpio_part1 *) samsung_get_base_gpio_part1(); + + switch (peripheral) { + case PERIPH_ID_I2C0: + s5p_gpio_cfg_pin(&gpio1->d1, 0, GPIO_FUNC(0x2)); + s5p_gpio_cfg_pin(&gpio1->d1, 1, GPIO_FUNC(0x2)); + break; + case PERIPH_ID_I2C1: + s5p_gpio_cfg_pin(&gpio1->d1, 2, GPIO_FUNC(0x2)); + s5p_gpio_cfg_pin(&gpio1->d1, 3, GPIO_FUNC(0x2)); + break; + case PERIPH_ID_I2C2: + s5p_gpio_cfg_pin(&gpio1->a0, 6, GPIO_FUNC(0x3)); + s5p_gpio_cfg_pin(&gpio1->a0, 7, GPIO_FUNC(0x3)); + break; + case PERIPH_ID_I2C3: + s5p_gpio_cfg_pin(&gpio1->a1, 2, GPIO_FUNC(0x3)); + s5p_gpio_cfg_pin(&gpio1->a1, 3, GPIO_FUNC(0x3)); + break; + case PERIPH_ID_I2C4: + s5p_gpio_cfg_pin(&gpio1->b, 2, GPIO_FUNC(0x3)); + s5p_gpio_cfg_pin(&gpio1->b, 3, GPIO_FUNC(0x3)); + break; + case PERIPH_ID_I2C5: + s5p_gpio_cfg_pin(&gpio1->b, 6, GPIO_FUNC(0x3)); + s5p_gpio_cfg_pin(&gpio1->b, 7, GPIO_FUNC(0x3)); + break; + case PERIPH_ID_I2C6: + s5p_gpio_cfg_pin(&gpio1->c1, 3, GPIO_FUNC(0x4)); + s5p_gpio_cfg_pin(&gpio1->c1, 4, GPIO_FUNC(0x4)); + break; + case PERIPH_ID_I2C7: + s5p_gpio_cfg_pin(&gpio1->d0, 2, GPIO_FUNC(0x3)); + s5p_gpio_cfg_pin(&gpio1->d0, 3, GPIO_FUNC(0x3)); + break; + } +} + +static int exynos4_pinmux_config(int peripheral, int flags) +{ + switch (peripheral) { + case PERIPH_ID_I2C0: + case PERIPH_ID_I2C1: + case PERIPH_ID_I2C2: + case PERIPH_ID_I2C3: + case PERIPH_ID_I2C4: + case PERIPH_ID_I2C5: + case PERIPH_ID_I2C6: + case PERIPH_ID_I2C7: + exynos4_i2c_config(peripheral, flags); + break; + default: + debug("%s: invalid peripheral %d", __func__, peripheral); + return -1; + } + + return 0; +} + int exynos_pinmux_config(int peripheral, int flags) { if (cpu_is_exynos5()) return exynos5_pinmux_config(peripheral, flags); + else if (cpu_is_exynos4()) + return exynos4_pinmux_config(peripheral, flags); else { debug("pinmux functionality not supported\n"); return -1; diff --git a/arch/arm/include/asm/arch-exynos/cpu.h b/arch/arm/include/asm/arch-exynos/cpu.h index 2cd4ae15262..3073ca1a811 100644 --- a/arch/arm/include/asm/arch-exynos/cpu.h +++ b/arch/arm/include/asm/arch-exynos/cpu.h @@ -28,6 +28,8 @@ #define EXYNOS4_ADDR_BASE 0x10000000 /* EXYNOS4 */ +#define EXYNOS4_I2C_SPACING 0x10000 + #define EXYNOS4_GPIO_PART3_BASE 0x03860000 #define EXYNOS4_PRO_ID 0x10000000 #define EXYNOS4_SYSREG_BASE 0x10010000 diff --git a/arch/arm/include/asm/arch-mxs/clock.h b/arch/arm/include/asm/arch-mxs/clock.h index 1700fe39155..3d39ef235d6 100644 --- a/arch/arm/include/asm/arch-mxs/clock.h +++ b/arch/arm/include/asm/arch-mxs/clock.h @@ -35,6 +35,7 @@ enum mxc_clock { MXC_SSP1_CLK, MXC_SSP2_CLK, MXC_SSP3_CLK, + MXC_XTAL_CLK, }; enum mxs_ioclock { diff --git a/arch/m68k/include/asm/string.h b/arch/m68k/include/asm/string.h index e0773a88285..ecf5e56e107 100644 --- a/arch/m68k/include/asm/string.h +++ b/arch/m68k/include/asm/string.h @@ -16,7 +16,7 @@ #endif extern int strcasecmp(const char *, const char *); -extern int strncasecmp(const char *, const char *, int); +extern int strncasecmp(const char *, const char *, __kernel_size_t); extern char * strcpy(char *,const char *); extern char * strncpy(char *,const char *, __kernel_size_t); extern __kernel_size_t strlen(const char *); diff --git a/arch/powerpc/include/asm/string.h b/arch/powerpc/include/asm/string.h index d912a6b5fed..036805ede29 100644 --- a/arch/powerpc/include/asm/string.h +++ b/arch/powerpc/include/asm/string.h @@ -14,7 +14,7 @@ #define __HAVE_ARCH_MEMCHR extern int strcasecmp(const char *, const char *); -extern int strncasecmp(const char *, const char *, int); +extern int strncasecmp(const char *, const char *, __kernel_size_t); extern char * strcpy(char *,const char *); extern char * strncpy(char *,const char *, __kernel_size_t); extern __kernel_size_t strlen(const char *); diff --git a/arch/sparc/include/asm/string.h b/arch/sparc/include/asm/string.h index c6bbc203d5d..af6faea234c 100644 --- a/arch/sparc/include/asm/string.h +++ b/arch/sparc/include/asm/string.h @@ -40,7 +40,7 @@ */ extern int strcasecmp(const char *, const char *); -extern int strncasecmp(const char *, const char *, int); +extern int strncasecmp(const char *, const char *, __kernel_size_t); extern char *strcpy(char *, const char *); extern char *strncpy(char *, const char *, __kernel_size_t); extern __kernel_size_t strlen(const char *); diff --git a/common/Makefile b/common/Makefile index c29a7d82e33..083df178136 100644 --- a/common/Makefile +++ b/common/Makefile @@ -30,6 +30,7 @@ ifndef CONFIG_SPL_BUILD COBJS-y += main.o COBJS-y += command.o COBJS-y += exports.o +COBJS-y += hash.o COBJS-$(CONFIG_SYS_HUSH_PARSER) += hush.o COBJS-y += s_record.o COBJS-y += xyzModem.o @@ -100,8 +101,10 @@ ifdef CONFIG_FPGA COBJS-$(CONFIG_CMD_FPGA) += cmd_fpga.o endif COBJS-$(CONFIG_CMD_FS_GENERIC) += cmd_fs.o +COBJS-$(CONFIG_CMD_GETTIME) += cmd_gettime.o COBJS-$(CONFIG_CMD_GPIO) += cmd_gpio.o COBJS-$(CONFIG_CMD_I2C) += cmd_i2c.o +COBJS-$(CONFIG_CMD_HASH) += cmd_hash.o COBJS-$(CONFIG_CMD_IDE) += cmd_ide.o COBJS-$(CONFIG_CMD_IMMAP) += cmd_immap.o COBJS-$(CONFIG_CMD_INI) += cmd_ini.o @@ -117,6 +120,7 @@ COBJS-$(CONFIG_LOGBUFFER) += cmd_log.o COBJS-$(CONFIG_ID_EEPROM) += cmd_mac.o COBJS-$(CONFIG_CMD_MD5SUM) += cmd_md5sum.o COBJS-$(CONFIG_CMD_MEMORY) += cmd_mem.o +COBJS-$(CONFIG_CMD_IO) += cmd_io.o COBJS-$(CONFIG_CMD_MFSL) += cmd_mfsl.o COBJS-$(CONFIG_MII) += miiphyutil.o COBJS-$(CONFIG_CMD_MII) += miiphyutil.o @@ -141,6 +145,7 @@ endif COBJS-y += cmd_pcmcia.o COBJS-$(CONFIG_CMD_PORTIO) += cmd_portio.o COBJS-$(CONFIG_CMD_PXE) += cmd_pxe.o +COBJS-$(CONFIG_CMD_READ) += cmd_read.o COBJS-$(CONFIG_CMD_REGINFO) += cmd_reginfo.o COBJS-$(CONFIG_CMD_REISER) += cmd_reiser.o COBJS-$(CONFIG_CMD_SATA) += cmd_sata.o @@ -184,6 +189,7 @@ COBJS-$(CONFIG_BOOTSTAGE) += bootstage.o COBJS-$(CONFIG_CONSOLE_MUX) += iomux.o COBJS-y += flash.o COBJS-$(CONFIG_CMD_KGDB) += kgdb.o kgdb_stubs.o +COBJS-$(CONFIG_I2C_EDID) += edid.o COBJS-$(CONFIG_KALLSYMS) += kallsyms.o COBJS-$(CONFIG_LCD) += lcd.o COBJS-$(CONFIG_LYNXKDI) += lynxkdi.o diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c index 4dbe952bb0f..f7595c03119 100644 --- a/common/cmd_bootm.c +++ b/common/cmd_bootm.c @@ -537,7 +537,7 @@ static int do_bootm_subcommand(cmd_tbl_t *cmdtp, int flag, int argc, } break; #endif -#if defined(CONFIG_OF_LIBFDT) +#if defined(CONFIG_OF_LIBFDT) && defined(CONFIG_LMB) case BOOTM_STATE_FDT: { boot_fdt_add_mem_rsv_regions(&images.lmb, diff --git a/common/cmd_gettime.c b/common/cmd_gettime.c new file mode 100644 index 00000000000..d7d36a98717 --- /dev/null +++ b/common/cmd_gettime.c @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2011 The Chromium OS Authors. All rights reserved. + * + * Copyright (c) 2009, Code Aurora Forum. All rights reserved. + * + * (C) Copyright 2001 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/* + * Get Timer overflows after 2^32 / CONFIG_SYS_HZ (32Khz) = 131072 sec + */ +#include <common.h> +#include <command.h> + +static int do_gettime(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ + unsigned long int val = get_timer(0); + +#ifdef CONFIG_SYS_HZ + printf("Timer val: %lu\n", val); + printf("Seconds : %lu\n", val / CONFIG_SYS_HZ); + printf("Remainder : %lu\n", val % CONFIG_SYS_HZ); + printf("sys_hz = %lu\n", (unsigned long int)CONFIG_SYS_HZ); +#else + printf("CONFIG_SYS_HZ not defined"); + printf("Timer Val %lu", val); +#endif + + return 0; +} + +U_BOOT_CMD( + gettime, 1, 1, do_gettime, + "get timer val elapsed,\n", + "get time elapsed from uboot start\n" +); diff --git a/common/cmd_hash.c b/common/cmd_hash.c new file mode 100644 index 00000000000..689c6085724 --- /dev/null +++ b/common/cmd_hash.c @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2012 The Chromium OS Authors. + * + * (C) Copyright 2011 + * Joe Hershberger, National Instruments, joe.hershberger@ni.com + * + * (C) Copyright 2000 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <command.h> +#include <hash.h> + +static int do_hash(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ +#ifdef CONFIG_HASH_VERIFY + int verify = 0; + + if (!strcmp(argv[1], "-v")) { + verify = 1; + argc--; + argv++; + } +#endif + /* Move forward to 'algorithm' parameter */ + argc--; + argv++; + return hash_command(*argv, verify, cmdtp, flag, argc - 1, argv + 1); +} + +#ifdef CONFIG_HASH_VERIFY +U_BOOT_CMD( + hash, 6, 1, do_hash, + "compute hash message digest", + "algorithm address count [[*]sum_dest]\n" + " - compute message digest [save to env var / *address]\n" + "hash -v algorithm address count [*]sum\n" + " - verify hash of memory area with env var / *address" +); +#else +U_BOOT_CMD( + hash, 5, 1, do_hash, + "compute message digest", + "algorithm address count [[*]sum_dest]\n" + " - compute message digest [save to env var / *address]" +); +#endif diff --git a/common/cmd_i2c.c b/common/cmd_i2c.c index 4438db594cf..43807944747 100644 --- a/common/cmd_i2c.c +++ b/common/cmd_i2c.c @@ -78,10 +78,12 @@ #include <common.h> #include <command.h> +#include <edid.h> #include <environment.h> #include <i2c.h> #include <malloc.h> #include <asm/byteorder.h> +#include <linux/compiler.h> /* Display values from last command. * Memory modify remembered values are different from display memory. @@ -132,35 +134,65 @@ DECLARE_GLOBAL_DATA_PTR; #define DISP_LINE_LEN 16 -/* implement possible board specific board init */ -static void __def_i2c_init_board(void) +/** + * i2c_init_board() - Board-specific I2C bus init + * + * This function is the default no-op implementation of I2C bus + * initialization. This function can be overriden by board-specific + * implementation if needed. + */ +__weak +void i2c_init_board(void) { return; } -void i2c_init_board(void) - __attribute__((weak, alias("__def_i2c_init_board"))); /* TODO: Implement architecture-specific get/set functions */ -static unsigned int __def_i2c_get_bus_speed(void) + +/** + * i2c_get_bus_speed() - Return I2C bus speed + * + * This function is the default implementation of function for retrieveing + * the current I2C bus speed in Hz. + * + * A driver implementing runtime switching of I2C bus speed must override + * this function to report the speed correctly. Simple or legacy drivers + * can use this fallback. + * + * Returns I2C bus speed in Hz. + */ +__weak +unsigned int i2c_get_bus_speed(void) { return CONFIG_SYS_I2C_SPEED; } -unsigned int i2c_get_bus_speed(void) - __attribute__((weak, alias("__def_i2c_get_bus_speed"))); -static int __def_i2c_set_bus_speed(unsigned int speed) +/** + * i2c_set_bus_speed() - Configure I2C bus speed + * @speed: Newly set speed of the I2C bus in Hz + * + * This function is the default implementation of function for setting + * the I2C bus speed in Hz. + * + * A driver implementing runtime switching of I2C bus speed must override + * this function to report the speed correctly. Simple or legacy drivers + * can use this fallback. + * + * Returns zero on success, negative value on error. + */ +__weak +int i2c_set_bus_speed(unsigned int speed) { if (speed != CONFIG_SYS_I2C_SPEED) return -1; return 0; } -int i2c_set_bus_speed(unsigned int) - __attribute__((weak, alias("__def_i2c_set_bus_speed"))); -/* - * get_alen: small parser helper function to get address length - * returns the address length +/** + * get_alen() - Small parser helper function to get address length + * + * Returns the address length. */ static uint get_alen(char *arg) { @@ -178,11 +210,19 @@ static uint get_alen(char *arg) return alen; } -/* +/** + * do_i2c_read() - Handle the "i2c read" command-line command + * @cmdtp: Command data struct pointer + * @flag: Command flag + * @argc: Command-line argument count + * @argv: Array of command-line arguments + * + * Returns zero on success, CMD_RET_USAGE in case of misuse and negative + * on error. + * * Syntax: * i2c read {i2c_chip} {devaddr}{.0, .1, .2} {len} {memaddr} */ - static int do_i2c_read ( cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { u_char chip; @@ -271,7 +311,16 @@ static int do_i2c_write(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[ return 0; } -/* +/** + * do_i2c_md() - Handle the "i2c md" command-line command + * @cmdtp: Command data struct pointer + * @flag: Command flag + * @argc: Command-line argument count + * @argv: Array of command-line arguments + * + * Returns zero on success, CMD_RET_USAGE in case of misuse and negative + * on error. + * * Syntax: * i2c md {i2c_chip} {addr}{.0, .1, .2} {len} */ @@ -363,8 +412,15 @@ static int do_i2c_md ( cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[] return 0; } - -/* Write (fill) memory +/** + * do_i2c_mw() - Handle the "i2c mw" command-line command + * @cmdtp: Command data struct pointer + * @flag: Command flag + * @argc: Command-line argument count + * @argv: Array of command-line arguments + * + * Returns zero on success, CMD_RET_USAGE in case of misuse and negative + * on error. * * Syntax: * i2c mw {i2c_chip} {addr}{.0, .1, .2} {data} [{count}] @@ -421,10 +477,20 @@ static int do_i2c_mw ( cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[] #endif } - return (0); + return 0; } -/* Calculate a CRC on memory +/** + * do_i2c_crc() - Handle the "i2c crc32" command-line command + * @cmdtp: Command data struct pointer + * @flag: Command flag + * @argc: Command-line argument count + * @argv: Array of command-line arguments + * + * Calculate a CRC on memory + * + * Returns zero on success, CMD_RET_USAGE in case of misuse and negative + * on error. * * Syntax: * i2c crc32 {i2c_chip} {addr}{.0, .1, .2} {count} @@ -481,13 +547,22 @@ static int do_i2c_crc (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[] return 0; } -/* Modify memory. +/** + * mod_i2c_mem() - Handle the "i2c mm" and "i2c nm" command-line command + * @cmdtp: Command data struct pointer + * @flag: Command flag + * @argc: Command-line argument count + * @argv: Array of command-line arguments + * + * Modify memory. + * + * Returns zero on success, CMD_RET_USAGE in case of misuse and negative + * on error. * * Syntax: * i2c mm{.b, .w, .l} {i2c_chip} {addr}{.0, .1, .2} * i2c nm{.b, .w, .l} {i2c_chip} {addr}{.0, .1, .2} */ - static int mod_i2c_mem(cmd_tbl_t *cmdtp, int incrflag, int flag, int argc, char * const argv[]) { @@ -603,7 +678,16 @@ mod_i2c_mem(cmd_tbl_t *cmdtp, int incrflag, int flag, int argc, char * const arg return 0; } -/* +/** + * do_i2c_probe() - Handle the "i2c probe" command-line command + * @cmdtp: Command data struct pointer + * @flag: Command flag + * @argc: Command-line argument count + * @argv: Array of command-line arguments + * + * Returns zero on success, CMD_RET_USAGE in case of misuse and negative + * on error. + * * Syntax: * i2c probe {addr} * @@ -657,7 +741,16 @@ static int do_i2c_probe (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv return (0 == found); } -/* +/** + * do_i2c_loop() - Handle the "i2c loop" command-line command + * @cmdtp: Command data struct pointer + * @flag: Command flag + * @argc: Command-line argument count + * @argv: Array of command-line arguments + * + * Returns zero on success, CMD_RET_USAGE in case of misuse and negative + * on error. + * * Syntax: * i2c loop {i2c_chip} {addr}{.0, .1, .2} [{length}] [{delay}] * {length} - Number of bytes to read @@ -718,6 +811,8 @@ static int do_i2c_loop(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[] /* * The SDRAM command is separately configured because many * (most?) embedded boards don't use SDRAM DIMMs. + * + * FIXME: Document and probably move elsewhere! */ #if defined(CONFIG_CMD_SDRAM) static void print_ddr2_tcyc (u_char const b) @@ -1246,7 +1341,48 @@ static int do_sdram (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) } #endif +/* + * Syntax: + * i2c edid {i2c_chip} + */ +#if defined(CONFIG_I2C_EDID) +int do_edid(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) +{ + u_char chip; + struct edid1_info edid; + + if (argc < 2) { + cmd_usage(cmdtp); + return 1; + } + + chip = simple_strtoul(argv[1], NULL, 16); + if (i2c_read(chip, 0, 1, (uchar *)&edid, sizeof(edid)) != 0) { + puts("Error reading EDID content.\n"); + return 1; + } + + if (edid_check_info(&edid)) { + puts("Content isn't valid EDID.\n"); + return 1; + } + + edid_print_info(&edid); + return 0; + +} +#endif /* CONFIG_I2C_EDID */ + #if defined(CONFIG_I2C_MUX) +/** + * do_i2c_add_bus() - Handle the "i2c bus" command-line command + * @cmdtp: Command data struct pointer + * @flag: Command flag + * @argc: Command-line argument count + * @argv: Array of command-line arguments + * + * Returns zero always. + */ static int do_i2c_add_bus(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) { int ret=0; @@ -1276,6 +1412,16 @@ static int do_i2c_add_bus(cmd_tbl_t * cmdtp, int flag, int argc, char * const ar #endif /* CONFIG_I2C_MUX */ #if defined(CONFIG_I2C_MULTI_BUS) +/** + * do_i2c_bus_num() - Handle the "i2c dev" command-line command + * @cmdtp: Command data struct pointer + * @flag: Command flag + * @argc: Command-line argument count + * @argv: Array of command-line arguments + * + * Returns zero on success, CMD_RET_USAGE in case of misuse and negative + * on error. + */ static int do_i2c_bus_num(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) { int bus_idx, ret=0; @@ -1294,6 +1440,16 @@ static int do_i2c_bus_num(cmd_tbl_t * cmdtp, int flag, int argc, char * const ar } #endif /* CONFIG_I2C_MULTI_BUS */ +/** + * do_i2c_bus_speed() - Handle the "i2c speed" command-line command + * @cmdtp: Command data struct pointer + * @flag: Command flag + * @argc: Command-line argument count + * @argv: Array of command-line arguments + * + * Returns zero on success, CMD_RET_USAGE in case of misuse and negative + * on error. + */ static int do_i2c_bus_speed(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) { int speed, ret=0; @@ -1311,16 +1467,45 @@ static int do_i2c_bus_speed(cmd_tbl_t * cmdtp, int flag, int argc, char * const return ret; } +/** + * do_i2c_mm() - Handle the "i2c mm" command-line command + * @cmdtp: Command data struct pointer + * @flag: Command flag + * @argc: Command-line argument count + * @argv: Array of command-line arguments + * + * Returns zero on success, CMD_RET_USAGE in case of misuse and negative + * on error. + */ static int do_i2c_mm(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) { return mod_i2c_mem (cmdtp, 1, flag, argc, argv); } +/** + * do_i2c_nm() - Handle the "i2c nm" command-line command + * @cmdtp: Command data struct pointer + * @flag: Command flag + * @argc: Command-line argument count + * @argv: Array of command-line arguments + * + * Returns zero on success, CMD_RET_USAGE in case of misuse and negative + * on error. + */ static int do_i2c_nm(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) { return mod_i2c_mem (cmdtp, 0, flag, argc, argv); } +/** + * do_i2c_reset() - Handle the "i2c reset" command-line command + * @cmdtp: Command data struct pointer + * @flag: Command flag + * @argc: Command-line argument count + * @argv: Array of command-line arguments + * + * Returns zero always. + */ static int do_i2c_reset(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) { i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE); @@ -1335,6 +1520,9 @@ static cmd_tbl_t cmd_i2c_sub[] = { #if defined(CONFIG_I2C_MULTI_BUS) U_BOOT_CMD_MKENT(dev, 1, 1, do_i2c_bus_num, "", ""), #endif /* CONFIG_I2C_MULTI_BUS */ +#if defined(CONFIG_I2C_EDID) + U_BOOT_CMD_MKENT(edid, 1, 1, do_edid, "", ""), +#endif /* CONFIG_I2C_EDID */ U_BOOT_CMD_MKENT(loop, 3, 1, do_i2c_loop, "", ""), U_BOOT_CMD_MKENT(md, 3, 1, do_i2c_md, "", ""), U_BOOT_CMD_MKENT(mm, 2, 1, do_i2c_mm, "", ""), @@ -1356,6 +1544,16 @@ void i2c_reloc(void) { } #endif +/** + * do_i2c() - Handle the "i2c" command-line command + * @cmdtp: Command data struct pointer + * @flag: Command flag + * @argc: Command-line argument count + * @argv: Array of command-line arguments + * + * Returns zero on success, CMD_RET_USAGE in case of misuse and negative + * on error. + */ static int do_i2c(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) { cmd_tbl_t *c; @@ -1385,6 +1583,9 @@ static char i2c_help_text[] = #if defined(CONFIG_I2C_MULTI_BUS) "i2c dev [dev] - show or set current I2C bus\n" #endif /* CONFIG_I2C_MULTI_BUS */ +#if defined(CONFIG_I2C_EDID) + "i2c edid chip - print EDID configuration information\n" +#endif /* CONFIG_I2C_EDID */ "i2c loop chip address[.0, .1, .2] [# of objects] - looping read of device\n" "i2c md chip address[.0, .1, .2] [# of objects] - read from I2C device\n" "i2c mm chip address[.0, .1, .2] - write to I2C device (auto-incrementing)\n" diff --git a/common/cmd_io.c b/common/cmd_io.c new file mode 100644 index 00000000000..6450cb576b1 --- /dev/null +++ b/common/cmd_io.c @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2012 The Chromium OS Authors. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/* + * IO space access commands. + */ + +#include <common.h> +#include <command.h> +#include <asm/io.h> + +/* + * IO Display + * + * Syntax: + * iod{.b, .w, .l} {addr} + */ +int do_io_iod(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) +{ + ulong addr; + int size; + + if (argc != 2) + return CMD_RET_USAGE; + + size = cmd_get_data_size(argv[0], 4); + if (size < 0) + return 1; + + addr = simple_strtoul(argv[1], NULL, 16); + + printf("%04x: ", (u16) addr); + + if (size == 4) + printf("%08x\n", inl(addr)); + else if (size == 2) + printf("%04x\n", inw(addr)); + else + printf("%02x\n", inb(addr)); + + return 0; +} + +int do_io_iow(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) +{ + ulong addr, size, val; + + if (argc != 3) + return CMD_RET_USAGE; + + size = cmd_get_data_size(argv[0], 4); + if (size < 0) + return 1; + + addr = simple_strtoul(argv[1], NULL, 16); + val = simple_strtoul(argv[2], NULL, 16); + + if (size == 4) + outl((u32) val, addr); + else if (size == 2) + outw((u16) val, addr); + else + outb((u8) val, addr); + + return 0; +} + +/**************************************************/ +U_BOOT_CMD(iod, 2, 0, do_io_iod, + "IO space display", "[.b, .w, .l] address [# of objects]"); + +U_BOOT_CMD(iow, 3, 0, do_io_iow, + "IO space modify (auto-incrementing address)", + "[.b, .w, .l] address"); diff --git a/common/cmd_read.c b/common/cmd_read.c new file mode 100644 index 00000000000..f0fc9bfe17a --- /dev/null +++ b/common/cmd_read.c @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2011 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + */ + +#include <common.h> +#include <command.h> +#include <part.h> + +int do_read(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + char *ep; + block_dev_desc_t *dev_desc = NULL; + int dev; + int part = 0; + disk_partition_t part_info; + ulong offset = 0u; + ulong limit = 0u; + void *addr; + uint blk; + uint cnt; + + if (argc != 6) { + cmd_usage(cmdtp); + return 1; + } + + dev = (int)simple_strtoul(argv[2], &ep, 16); + if (*ep) { + if (*ep != ':') { + printf("Invalid block device %s\n", argv[2]); + return 1; + } + part = (int)simple_strtoul(++ep, NULL, 16); + } + + dev_desc = get_dev(argv[1], dev); + if (dev_desc == NULL) { + printf("Block device %s %d not supported\n", argv[1], dev); + return 1; + } + + addr = (void *)simple_strtoul(argv[3], NULL, 16); + blk = simple_strtoul(argv[4], NULL, 16); + cnt = simple_strtoul(argv[5], NULL, 16); + + if (part != 0) { + if (get_partition_info(dev_desc, part, &part_info)) { + printf("Cannot find partition %d\n", part); + return 1; + } + offset = part_info.start; + limit = part_info.size; + } else { + /* Largest address not available in block_dev_desc_t. */ + limit = ~0; + } + + if (cnt + blk > limit) { + printf("Read out of range\n"); + return 1; + } + + if (dev_desc->block_read(dev, offset + blk, cnt, addr) < 0) { + printf("Error reading blocks\n"); + return 1; + } + + return 0; +} + +U_BOOT_CMD( + read, 6, 0, do_read, + "Load binary data from a partition", + "<interface> <dev[:part]> addr blk# cnt" +); diff --git a/common/cmd_sha1sum.c b/common/cmd_sha1sum.c index 8db5456c958..fe927ab248f 100644 --- a/common/cmd_sha1sum.c +++ b/common/cmd_sha1sum.c @@ -26,73 +26,11 @@ #include <common.h> #include <command.h> +#include <hash.h> #include <sha1.h> -/* - * Store the resulting sum to an address or variable - */ -static void store_result(const u8 *sum, const char *dest) -{ - unsigned int i; - - if (*dest == '*') { - u8 *ptr; - - ptr = (u8 *)simple_strtoul(dest + 1, NULL, 16); - for (i = 0; i < 20; i++) - *ptr++ = sum[i]; - } else { - char str_output[41]; - char *str_ptr = str_output; - - for (i = 0; i < 20; i++) { - sprintf(str_ptr, "%02x", sum[i]); - str_ptr += 2; - } - str_ptr = '\0'; - setenv(dest, str_output); - } -} - -#ifdef CONFIG_SHA1SUM_VERIFY -static int parse_verify_sum(char *verify_str, u8 *vsum) -{ - if (*verify_str == '*') { - u8 *ptr; - - ptr = (u8 *)simple_strtoul(verify_str + 1, NULL, 16); - memcpy(vsum, ptr, 20); - } else { - unsigned int i; - char *vsum_str; - - if (strlen(verify_str) == 40) - vsum_str = verify_str; - else { - vsum_str = getenv(verify_str); - if (vsum_str == NULL || strlen(vsum_str) != 40) - return 1; - } - - for (i = 0; i < 20; i++) { - char *nullp = vsum_str + (i + 1) * 2; - char end = *nullp; - - *nullp = '\0'; - *(u8 *)(vsum + i) = - simple_strtoul(vsum_str + (i * 2), NULL, 16); - *nullp = end; - } - } - return 0; -} - int do_sha1sum(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { - ulong addr, len; - unsigned int i; - u8 output[20]; - u8 vsum[20]; int verify = 0; int ac; char * const *av; @@ -102,75 +40,16 @@ int do_sha1sum(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) av = argv + 1; ac = argc - 1; +#ifdef CONFIG_SHA1SUM_VERIFY if (strcmp(*av, "-v") == 0) { verify = 1; av++; ac--; - if (ac < 3) - return CMD_RET_USAGE; } +#endif - addr = simple_strtoul(*av++, NULL, 16); - len = simple_strtoul(*av++, NULL, 16); - - sha1_csum_wd((unsigned char *) addr, len, output, CHUNKSZ_SHA1); - - if (!verify) { - printf("SHA1 for %08lx ... %08lx ==> ", addr, addr + len - 1); - for (i = 0; i < 20; i++) - printf("%02x", output[i]); - printf("\n"); - - if (ac > 2) - store_result(output, *av); - } else { - char *verify_str = *av++; - - if (parse_verify_sum(verify_str, vsum)) { - printf("ERROR: %s does not contain a valid SHA1 sum\n", - verify_str); - return 1; - } - if (memcmp(output, vsum, 20) != 0) { - printf("SHA1 for %08lx ... %08lx ==> ", addr, - addr + len - 1); - for (i = 0; i < 20; i++) - printf("%02x", output[i]); - printf(" != "); - for (i = 0; i < 20; i++) - printf("%02x", vsum[i]); - printf(" ** ERROR **\n"); - return 1; - } - } - - return 0; -} -#else -static int do_sha1sum(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - unsigned long addr, len; - unsigned int i; - u8 output[20]; - - if (argc < 3) - return CMD_RET_USAGE; - - addr = simple_strtoul(argv[1], NULL, 16); - len = simple_strtoul(argv[2], NULL, 16); - - sha1_csum_wd((unsigned char *) addr, len, output, CHUNKSZ_SHA1); - printf("SHA1 for %08lx ... %08lx ==> ", addr, addr + len - 1); - for (i = 0; i < 20; i++) - printf("%02x", output[i]); - printf("\n"); - - if (argc > 3) - store_result(output, argv[3]); - - return 0; + return hash_command("sha1", verify, cmdtp, flag, ac, av); } -#endif #ifdef CONFIG_SHA1SUM_VERIFY U_BOOT_CMD( diff --git a/common/cmd_spl.c b/common/cmd_spl.c index 9ec054af3b3..e3c543b46a5 100644 --- a/common/cmd_spl.c +++ b/common/cmd_spl.c @@ -130,10 +130,12 @@ static int spl_export(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) if (call_bootm(argc, argv, subcmd_list[(int)c->cmd])) return -1; switch ((int)c->cmd) { +#ifdef CONFIG_OF_LIBFDT case SPL_EXPORT_FDT: printf("Argument image is now in RAM: 0x%p\n", (void *)images.ft_addr); break; +#endif case SPL_EXPORT_ATAGS: printf("Argument image is now in RAM at: 0x%p\n", (void *)gd->bd->bi_boot_params); diff --git a/common/cmd_tpm.c b/common/cmd_tpm.c index 6f5cd4895d8..0970a6fc191 100644 --- a/common/cmd_tpm.c +++ b/common/cmd_tpm.c @@ -63,19 +63,68 @@ static int tpm_process(int argc, char * const argv[], cmd_tbl_t *cmdtp) return rv; } -static int do_tpm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +#define CHECK(exp) do { \ + int _rv = exp; \ + if (_rv) { \ + printf("CHECK: %s %d %x\n", #exp, __LINE__, _rv);\ + } \ + } while (0) + +static int tpm_process_stress(int repeat_count) { + int i; int rv = 0; + u8 request[] = {0x0, 0xc1, + 0x0, 0x0, 0x0, 0x16, + 0x0, 0x0, 0x0, 0x65, + 0x0, 0x0, 0x0, 0x4, + 0x0, 0x0, 0x0, 0x4, + 0x0, 0x0, 0x1, 0x9}; + u8 response[MAX_TRANSACTION_SIZE]; + u32 rlength = MAX_TRANSACTION_SIZE; + + CHECK(tis_init()); + + for (i = 0; i < repeat_count; i++) { + CHECK(tis_open()); + rv = tis_sendrecv(request, sizeof(request), response, &rlength); + if (rv) { + printf("tpm test failed at step %d with 0x%x\n", i, rv); + CHECK(tis_close()); + break; + } + CHECK(tis_close()); + if ((response[6] || response[7] || response[8] || response[9]) + && response[9] != 0x26) { + /* Ignore postinit errors */ + printf("tpm command failed at step %d\n" + "tpm error code: %02x%02x%02x%02x\n", i, + response[6], response[7], + response[8], response[9]); + rv = -1; + break; + } + } + return rv; +} - /* - * Verify that in case it is present, the first argument, it is - * exactly one character in size. - */ - if (argc < 7) { + +static int do_tpm_many(cmd_tbl_t *cmdtp, int flag, + int argc, char * const argv[], int repeat_count) + +{ + int rv = 0; + + if (argc < 7 && repeat_count == 0) { puts("command should be at least six bytes in size\n"); return -1; } + if (repeat_count > 0) { + rv = tpm_process_stress(repeat_count); + return rv; + } + if (tis_init()) { puts("tis_init() failed!\n"); return -1; @@ -96,8 +145,40 @@ static int do_tpm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) return rv; } + +static int do_tpm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + return do_tpm_many(cmdtp, flag, argc, argv, 0); +} + + U_BOOT_CMD(tpm, MAX_TRANSACTION_SIZE, 1, do_tpm, "<byte> [<byte> ...] - write data and read response", "send arbitrary data (at least 6 bytes) to the TPM " "device and read the response" ); + +static int do_tpm_stress(cmd_tbl_t *cmdtp, int flag, + int argc, char * const argv[]) +{ + long unsigned int n; + int rv; + + if (argc != 2) { + puts("usage: tpm_stress <count>\n"); + return -1; + } + + rv = strict_strtoul(argv[1], 10, &n); + if (rv) { + puts("tpm_stress: bad count"); + return -1; + } + + return do_tpm_many(cmdtp, flag, argc, argv, n); +} + +U_BOOT_CMD(tpm_stress, 2, 1, do_tpm_stress, + "<n> - stress-test communication with TPM", + "Repeat a TPM transaction (request-response) N times" +); diff --git a/common/console.c b/common/console.c index 1177f7d396b..25b141a325a 100644 --- a/common/console.c +++ b/common/console.c @@ -591,7 +591,6 @@ int console_init_f(void) void stdio_print_current_devices(void) { -#ifndef CONFIG_SYS_CONSOLE_INFO_QUIET /* Print information */ puts("In: "); if (stdio_devices[stdin] == NULL) { @@ -613,7 +612,6 @@ void stdio_print_current_devices(void) } else { printf ("%s\n", stdio_devices[stderr]->name); } -#endif /* CONFIG_SYS_CONSOLE_INFO_QUIET */ } #ifdef CONFIG_SYS_CONSOLE_IS_IN_ENV @@ -685,7 +683,9 @@ done: gd->flags |= GD_FLG_DEVINIT; /* device initialization completed */ +#ifndef CONFIG_SYS_CONSOLE_INFO_QUIET stdio_print_current_devices(); +#endif /* CONFIG_SYS_CONSOLE_INFO_QUIET */ #ifdef CONFIG_SYS_CONSOLE_ENV_OVERWRITE /* set the environment variables (will overwrite previous env settings) */ @@ -760,7 +760,9 @@ int console_init_r(void) gd->flags |= GD_FLG_DEVINIT; /* device initialization completed */ +#ifndef CONFIG_SYS_CONSOLE_INFO_QUIET stdio_print_current_devices(); +#endif /* CONFIG_SYS_CONSOLE_INFO_QUIET */ /* Setting environment variables */ for (i = 0; i < 3; i++) { diff --git a/common/edid.c b/common/edid.c new file mode 100644 index 00000000000..c82c298097b --- /dev/null +++ b/common/edid.c @@ -0,0 +1,307 @@ +/* + * Copyright (c) 2012 The Chromium OS Authors. + * + * (C) Copyright 2010 + * Petr Stetiar <ynezz@true.cz> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * Contains stolen code from ddcprobe project which is: + * Copyright (C) Nalin Dahyabhai <bigfun@pobox.com> + * + */ + +#include <common.h> +#include <edid.h> +#include <linux/ctype.h> +#include <linux/string.h> + +int edid_check_info(struct edid1_info *edid_info) +{ + if ((edid_info == NULL) || (edid_info->version == 0)) + return -1; + + if (memcmp(edid_info->header, "\x0\xff\xff\xff\xff\xff\xff\x0", 8)) + return -1; + + if (edid_info->version == 0xff && edid_info->revision == 0xff) + return -1; + + return 0; +} + +int edid_get_ranges(struct edid1_info *edid, unsigned int *hmin, + unsigned int *hmax, unsigned int *vmin, + unsigned int *vmax) +{ + int i; + struct edid_monitor_descriptor *monitor; + + *hmin = *hmax = *vmin = *vmax = 0; + if (edid_check_info(edid)) + return -1; + + for (i = 0; i < ARRAY_SIZE(edid->monitor_details.descriptor); i++) { + monitor = &edid->monitor_details.descriptor[i]; + if (monitor->type == EDID_MONITOR_DESCRIPTOR_RANGE) { + *hmin = monitor->data.range_data.horizontal_min; + *hmax = monitor->data.range_data.horizontal_max; + *vmin = monitor->data.range_data.vertical_min; + *vmax = monitor->data.range_data.vertical_max; + return 0; + } + } + return -1; +} + +/** + * Snip the tailing whitespace/return of a string. + * + * @param string The string to be snipped + * @return the snipped string + */ +static char *snip(char *string) +{ + char *s; + + /* + * This is always a 13 character buffer + * and it's not always terminated. + */ + string[12] = '\0'; + s = &string[strlen(string) - 1]; + + while (s >= string && (isspace(*s) || *s == '\n' || *s == '\r' || + *s == '\0')) + *(s--) = '\0'; + + return string; +} + +/** + * Print an EDID monitor descriptor block + * + * @param monitor The EDID monitor descriptor block + * @have_timing Modifies to 1 if the desciptor contains timing info + */ +static void edid_print_dtd(struct edid_monitor_descriptor *monitor, + unsigned int *have_timing) +{ + unsigned char *bytes = (unsigned char *)monitor; + struct edid_detailed_timing *timing = + (struct edid_detailed_timing *)monitor; + + if (bytes[0] == 0 && bytes[1] == 0) { + if (monitor->type == EDID_MONITOR_DESCRIPTOR_SERIAL) + printf("Monitor serial number: %s\n", + snip(monitor->data.string)); + else if (monitor->type == EDID_MONITOR_DESCRIPTOR_ASCII) + printf("Monitor ID: %s\n", + snip(monitor->data.string)); + else if (monitor->type == EDID_MONITOR_DESCRIPTOR_NAME) + printf("Monitor name: %s\n", + snip(monitor->data.string)); + else if (monitor->type == EDID_MONITOR_DESCRIPTOR_RANGE) + printf("Monitor range limits, horizontal sync: " + "%d-%d kHz, vertical refresh: " + "%d-%d Hz, max pixel clock: " + "%d MHz\n", + monitor->data.range_data.horizontal_min, + monitor->data.range_data.horizontal_max, + monitor->data.range_data.vertical_min, + monitor->data.range_data.vertical_max, + monitor->data.range_data.pixel_clock_max * 10); + } else { + uint32_t pixclock, h_active, h_blanking, v_active, v_blanking; + uint32_t h_total, v_total, vfreq; + + pixclock = EDID_DETAILED_TIMING_PIXEL_CLOCK(*timing); + h_active = EDID_DETAILED_TIMING_HORIZONTAL_ACTIVE(*timing); + h_blanking = EDID_DETAILED_TIMING_HORIZONTAL_BLANKING(*timing); + v_active = EDID_DETAILED_TIMING_VERTICAL_ACTIVE(*timing); + v_blanking = EDID_DETAILED_TIMING_VERTICAL_BLANKING(*timing); + + h_total = h_active + h_blanking; + v_total = v_active + v_blanking; + if (v_total * h_total) + vfreq = pixclock / (v_total * h_total); + else + vfreq = 1; /* Error case */ + printf("\t%dx%d\%c\t%d Hz (detailed)\n", h_active, + v_active, h_active > 1000 ? ' ' : '\t', vfreq); + *have_timing = 1; + } +} + +/** + * Get the manufacturer name from an EDID info. + * + * @param edid_info The EDID info to be printed + * @param name Returns the string of the manufacturer name + */ +static void edid_get_manufacturer_name(struct edid1_info *edid, char *name) +{ + name[0] = EDID1_INFO_MANUFACTURER_NAME_CHAR1(*edid) + 'A' - 1; + name[1] = EDID1_INFO_MANUFACTURER_NAME_CHAR2(*edid) + 'A' - 1; + name[2] = EDID1_INFO_MANUFACTURER_NAME_CHAR3(*edid) + 'A' - 1; + name[3] = '\0'; +} + +void edid_print_info(struct edid1_info *edid_info) +{ + int i; + char manufacturer[4]; + unsigned int have_timing = 0; + uint32_t serial_number; + + if (edid_check_info(edid_info)) { + printf("Not a valid EDID\n"); + return; + } + + printf("EDID version: %d.%d\n", + edid_info->version, edid_info->revision); + + printf("Product ID code: %04x\n", EDID1_INFO_PRODUCT_CODE(*edid_info)); + + edid_get_manufacturer_name(edid_info, manufacturer); + printf("Manufacturer: %s\n", manufacturer); + + serial_number = EDID1_INFO_SERIAL_NUMBER(*edid_info); + if (serial_number != 0xffffffff) { + if (strcmp(manufacturer, "MAG") == 0) + serial_number -= 0x7000000; + if (strcmp(manufacturer, "OQI") == 0) + serial_number -= 456150000; + if (strcmp(manufacturer, "VSC") == 0) + serial_number -= 640000000; + } + printf("Serial number: %08x\n", serial_number); + printf("Manufactured in week: %d year: %d\n", + edid_info->week, edid_info->year + 1990); + + printf("Video input definition: %svoltage level %d%s%s%s%s%s\n", + EDID1_INFO_VIDEO_INPUT_DIGITAL(*edid_info) ? + "digital signal, " : "analog signal, ", + EDID1_INFO_VIDEO_INPUT_VOLTAGE_LEVEL(*edid_info), + EDID1_INFO_VIDEO_INPUT_BLANK_TO_BLACK(*edid_info) ? + ", blank to black" : "", + EDID1_INFO_VIDEO_INPUT_SEPARATE_SYNC(*edid_info) ? + ", separate sync" : "", + EDID1_INFO_VIDEO_INPUT_COMPOSITE_SYNC(*edid_info) ? + ", composite sync" : "", + EDID1_INFO_VIDEO_INPUT_SYNC_ON_GREEN(*edid_info) ? + ", sync on green" : "", + EDID1_INFO_VIDEO_INPUT_SERRATION_V(*edid_info) ? + ", serration v" : ""); + + printf("Monitor is %s\n", + EDID1_INFO_FEATURE_RGB(*edid_info) ? "RGB" : "non-RGB"); + + printf("Maximum visible display size: %d cm x %d cm\n", + edid_info->max_size_horizontal, + edid_info->max_size_vertical); + + printf("Power management features: %s%s, %s%s, %s%s\n", + EDID1_INFO_FEATURE_ACTIVE_OFF(*edid_info) ? + "" : "no ", "active off", + EDID1_INFO_FEATURE_SUSPEND(*edid_info) ? "" : "no ", "suspend", + EDID1_INFO_FEATURE_STANDBY(*edid_info) ? "" : "no ", "standby"); + + printf("Estabilished timings:\n"); + if (EDID1_INFO_ESTABLISHED_TIMING_720X400_70(*edid_info)) + printf("\t720x400\t\t70 Hz (VGA 640x400, IBM)\n"); + if (EDID1_INFO_ESTABLISHED_TIMING_720X400_88(*edid_info)) + printf("\t720x400\t\t88 Hz (XGA2)\n"); + if (EDID1_INFO_ESTABLISHED_TIMING_640X480_60(*edid_info)) + printf("\t640x480\t\t60 Hz (VGA)\n"); + if (EDID1_INFO_ESTABLISHED_TIMING_640X480_67(*edid_info)) + printf("\t640x480\t\t67 Hz (Mac II, Apple)\n"); + if (EDID1_INFO_ESTABLISHED_TIMING_640X480_72(*edid_info)) + printf("\t640x480\t\t72 Hz (VESA)\n"); + if (EDID1_INFO_ESTABLISHED_TIMING_640X480_75(*edid_info)) + printf("\t640x480\t\t75 Hz (VESA)\n"); + if (EDID1_INFO_ESTABLISHED_TIMING_800X600_56(*edid_info)) + printf("\t800x600\t\t56 Hz (VESA)\n"); + if (EDID1_INFO_ESTABLISHED_TIMING_800X600_60(*edid_info)) + printf("\t800x600\t\t60 Hz (VESA)\n"); + if (EDID1_INFO_ESTABLISHED_TIMING_800X600_72(*edid_info)) + printf("\t800x600\t\t72 Hz (VESA)\n"); + if (EDID1_INFO_ESTABLISHED_TIMING_800X600_75(*edid_info)) + printf("\t800x600\t\t75 Hz (VESA)\n"); + if (EDID1_INFO_ESTABLISHED_TIMING_832X624_75(*edid_info)) + printf("\t832x624\t\t75 Hz (Mac II)\n"); + if (EDID1_INFO_ESTABLISHED_TIMING_1024X768_87I(*edid_info)) + printf("\t1024x768\t87 Hz Interlaced (8514A)\n"); + if (EDID1_INFO_ESTABLISHED_TIMING_1024X768_60(*edid_info)) + printf("\t1024x768\t60 Hz (VESA)\n"); + if (EDID1_INFO_ESTABLISHED_TIMING_1024X768_70(*edid_info)) + printf("\t1024x768\t70 Hz (VESA)\n"); + if (EDID1_INFO_ESTABLISHED_TIMING_1024X768_75(*edid_info)) + printf("\t1024x768\t75 Hz (VESA)\n"); + if (EDID1_INFO_ESTABLISHED_TIMING_1280X1024_75(*edid_info)) + printf("\t1280x1024\t75 (VESA)\n"); + if (EDID1_INFO_ESTABLISHED_TIMING_1152X870_75(*edid_info)) + printf("\t1152x870\t75 (Mac II)\n"); + + /* Standard timings. */ + printf("Standard timings:\n"); + for (i = 0; i < ARRAY_SIZE(edid_info->standard_timings); i++) { + unsigned int aspect = 10000; + unsigned int x, y; + unsigned char xres, vfreq; + + xres = EDID1_INFO_STANDARD_TIMING_XRESOLUTION(*edid_info, i); + vfreq = EDID1_INFO_STANDARD_TIMING_VFREQ(*edid_info, i); + if ((xres != vfreq) || + ((xres != 0) && (xres != 1)) || + ((vfreq != 0) && (vfreq != 1))) { + switch (EDID1_INFO_STANDARD_TIMING_ASPECT(*edid_info, + i)) { + case ASPECT_625: + aspect = 6250; + break; + case ASPECT_75: + aspect = 7500; + break; + case ASPECT_8: + aspect = 8000; + break; + case ASPECT_5625: + aspect = 5625; + break; + } + x = (xres + 31) * 8; + y = x * aspect / 10000; + printf("\t%dx%d%c\t%d Hz\n", x, y, + x > 1000 ? ' ' : '\t', (vfreq & 0x3f) + 60); + have_timing = 1; + } + } + + /* Detailed timing information. */ + for (i = 0; i < ARRAY_SIZE(edid_info->monitor_details.descriptor); + i++) { + edid_print_dtd(&edid_info->monitor_details.descriptor[i], + &have_timing); + } + + if (!have_timing) + printf("\tNone\n"); +} diff --git a/common/fdt_support.c b/common/fdt_support.c index 963ea902346..6b9fa0550f1 100644 --- a/common/fdt_support.c +++ b/common/fdt_support.c @@ -1315,7 +1315,7 @@ int fdt_set_status_by_alias(void *fdt, const char* alias, return fdt_set_node_status(fdt, offset, status, error_code); } -#if defined(CONFIG_VIDEO) +#if defined(CONFIG_VIDEO) || defined(CONFIG_LCD) int fdt_add_edid(void *blob, const char *compat, unsigned char *edid_buf) { int noff; diff --git a/common/hash.c b/common/hash.c new file mode 100644 index 00000000000..e3a6e438a3b --- /dev/null +++ b/common/hash.c @@ -0,0 +1,221 @@ +/* + * Copyright (c) 2012 The Chromium OS Authors. + * + * (C) Copyright 2011 + * Joe Hershberger, National Instruments, joe.hershberger@ni.com + * + * (C) Copyright 2000 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <command.h> +#include <hash.h> +#include <sha1.h> +#include <sha256.h> + +/* + * These are the hash algorithms we support. Chips which support accelerated + * crypto could perhaps add named version of these algorithms here. + */ +static struct hash_algo hash_algo[] = { +#ifdef CONFIG_SHA1 + { + "SHA1", + SHA1_SUM_LEN, + sha1_csum_wd, + CHUNKSZ_SHA1, + }, +#endif +#ifdef CONFIG_SHA256 + { + "SHA256", + SHA256_SUM_LEN, + sha256_csum_wd, + CHUNKSZ_SHA256, + }, +#endif +}; + +/** + * store_result: Store the resulting sum to an address or variable + * + * @algo: Hash algorithm being used + * @sum: Hash digest (algo->digest_size bytes) + * @dest: Destination, interpreted as a hex address if it starts + * with * or otherwise as an environment variable. + */ +static void store_result(struct hash_algo *algo, const u8 *sum, + const char *dest) +{ + unsigned int i; + + if (*dest == '*') { + u8 *ptr; + + ptr = (u8 *)simple_strtoul(dest + 1, NULL, 16); + memcpy(ptr, sum, algo->digest_size); + } else { + char str_output[HASH_MAX_DIGEST_SIZE * 2 + 1]; + char *str_ptr = str_output; + + for (i = 0; i < algo->digest_size; i++) { + sprintf(str_ptr, "%02x", sum[i]); + str_ptr += 2; + } + str_ptr = '\0'; + setenv(dest, str_output); + } +} + +/** + * parse_verify_sum: Parse a hash verification parameter + * + * @algo: Hash algorithm being used + * @verify_str: Argument to parse. If it starts with * then it is + * interpreted as a hex address containing the hash. + * If the length is exactly the right number of hex digits + * for the digest size, then we assume it is a hex digest. + * Otherwise we assume it is an environment variable, and + * look up its value (it must contain a hex digest). + * @vsum: Returns binary digest value (algo->digest_size bytes) + * @return 0 if ok, non-zero on error + */ +static int parse_verify_sum(struct hash_algo *algo, char *verify_str, u8 *vsum) +{ + if (*verify_str == '*') { + u8 *ptr; + + ptr = (u8 *)simple_strtoul(verify_str + 1, NULL, 16); + memcpy(vsum, ptr, algo->digest_size); + } else { + unsigned int i; + char *vsum_str; + int digits = algo->digest_size * 2; + + /* + * As with the original code from sha1sum.c, we assume that a + * string which matches the digest size exactly is a hex + * string and not an environment variable. + */ + if (strlen(verify_str) == digits) + vsum_str = verify_str; + else { + vsum_str = getenv(verify_str); + if (vsum_str == NULL || strlen(vsum_str) != digits) { + printf("Expected %d hex digits in env var\n", + digits); + return 1; + } + } + + for (i = 0; i < algo->digest_size; i++) { + char *nullp = vsum_str + (i + 1) * 2; + char end = *nullp; + + *nullp = '\0'; + vsum[i] = simple_strtoul(vsum_str + (i * 2), NULL, 16); + *nullp = end; + } + } + return 0; +} + +static struct hash_algo *find_hash_algo(const char *name) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(hash_algo); i++) { + if (!strcasecmp(name, hash_algo[i].name)) + return &hash_algo[i]; + } + + return NULL; +} + +static void show_hash(struct hash_algo *algo, ulong addr, ulong len, + u8 *output) +{ + int i; + + printf("%s for %08lx ... %08lx ==> ", algo->name, addr, addr + len - 1); + for (i = 0; i < algo->digest_size; i++) + printf("%02x", output[i]); +} + +int hash_command(const char *algo_name, int verify, cmd_tbl_t *cmdtp, int flag, + int argc, char * const argv[]) +{ + struct hash_algo *algo; + ulong addr, len; + u8 output[HASH_MAX_DIGEST_SIZE]; + u8 vsum[HASH_MAX_DIGEST_SIZE]; + + if (argc < 2) + return CMD_RET_USAGE; + + algo = find_hash_algo(algo_name); + if (!algo) { + printf("Unknown hash algorithm '%s'\n", algo_name); + return CMD_RET_USAGE; + } + addr = simple_strtoul(*argv++, NULL, 16); + len = simple_strtoul(*argv++, NULL, 16); + argc -= 2; + + if (algo->digest_size > HASH_MAX_DIGEST_SIZE) { + puts("HASH_MAX_DIGEST_SIZE exceeded\n"); + return 1; + } + + algo->hash_func_ws((const unsigned char *)addr, len, output, + algo->chunk_size); + + /* Try to avoid code bloat when verify is not needed */ +#ifdef CONFIG_HASH_VERIFY + if (verify) { +#else + if (0) { +#endif + if (!argc) + return CMD_RET_USAGE; + if (parse_verify_sum(algo, *argv, vsum)) { + printf("ERROR: %s does not contain a valid %s sum\n", + *argv, algo->name); + return 1; + } + if (memcmp(output, vsum, algo->digest_size) != 0) { + int i; + + show_hash(algo, addr, len, output); + printf(" != "); + for (i = 0; i < algo->digest_size; i++) + printf("%02x", vsum[i]); + puts(" ** ERROR **\n"); + return 1; + } + } else { + show_hash(algo, addr, len, output); + printf("\n"); + + if (argc) + store_result(algo, output, *argv); + } + + return 0; +} diff --git a/common/main.c b/common/main.c index 5362781f187..b145f855658 100644 --- a/common/main.c +++ b/common/main.c @@ -376,6 +376,8 @@ void main_loop (void) char bcs_set[16]; #endif /* CONFIG_BOOTCOUNT_LIMIT */ + bootstage_mark_name(BOOTSTAGE_ID_MAIN_LOOP, "main_loop"); + #ifdef CONFIG_BOOTCOUNT_LIMIT bootcount = bootcount_load(); bootcount++; diff --git a/common/stdio.c b/common/stdio.c index 9f48e5f5034..97ff9cf4a6a 100644 --- a/common/stdio.c +++ b/common/stdio.c @@ -135,7 +135,6 @@ struct stdio_dev* stdio_clone(struct stdio_dev *dev) return NULL; memcpy(_dev, dev, sizeof(struct stdio_dev)); - strncpy(_dev->name, dev->name, 16); return _dev; } diff --git a/drivers/i2c/designware_i2c.c b/drivers/i2c/designware_i2c.c index bf64a2a643a..665387091ae 100644 --- a/drivers/i2c/designware_i2c.c +++ b/drivers/i2c/designware_i2c.c @@ -26,7 +26,12 @@ #include <asm/arch/hardware.h> #include "designware_i2c.h" -static struct i2c_regs *const i2c_regs_p = +#ifdef CONFIG_I2C_MULTI_BUS +static unsigned int bus_initialized[CONFIG_SYS_I2C_BUS_MAX]; +static unsigned int current_bus = 0; +#endif + +static struct i2c_regs *i2c_regs_p = (struct i2c_regs *)CONFIG_SYS_I2C_BASE; /* @@ -39,7 +44,6 @@ static void set_speed(int i2c_spd) { unsigned int cntl; unsigned int hcnt, lcnt; - unsigned int high, low; unsigned int enbl; /* to set speed cltr must be disabled */ @@ -47,39 +51,38 @@ static void set_speed(int i2c_spd) enbl &= ~IC_ENABLE_0B; writel(enbl, &i2c_regs_p->ic_enable); - cntl = (readl(&i2c_regs_p->ic_con) & (~IC_CON_SPD_MSK)); switch (i2c_spd) { case IC_SPEED_MODE_MAX: cntl |= IC_CON_SPD_HS; - high = MIN_HS_SCL_HIGHTIME; - low = MIN_HS_SCL_LOWTIME; + hcnt = (IC_CLK * MIN_HS_SCL_HIGHTIME) / NANO_TO_MICRO; + writel(hcnt, &i2c_regs_p->ic_hs_scl_hcnt); + lcnt = (IC_CLK * MIN_HS_SCL_LOWTIME) / NANO_TO_MICRO; + writel(lcnt, &i2c_regs_p->ic_hs_scl_lcnt); break; case IC_SPEED_MODE_STANDARD: cntl |= IC_CON_SPD_SS; - high = MIN_SS_SCL_HIGHTIME; - low = MIN_SS_SCL_LOWTIME; + hcnt = (IC_CLK * MIN_SS_SCL_HIGHTIME) / NANO_TO_MICRO; + writel(hcnt, &i2c_regs_p->ic_ss_scl_hcnt); + lcnt = (IC_CLK * MIN_SS_SCL_LOWTIME) / NANO_TO_MICRO; + writel(lcnt, &i2c_regs_p->ic_ss_scl_lcnt); break; case IC_SPEED_MODE_FAST: default: cntl |= IC_CON_SPD_FS; - high = MIN_FS_SCL_HIGHTIME; - low = MIN_FS_SCL_LOWTIME; + hcnt = (IC_CLK * MIN_FS_SCL_HIGHTIME) / NANO_TO_MICRO; + writel(hcnt, &i2c_regs_p->ic_fs_scl_hcnt); + lcnt = (IC_CLK * MIN_FS_SCL_LOWTIME) / NANO_TO_MICRO; + writel(lcnt, &i2c_regs_p->ic_fs_scl_lcnt); break; } writel(cntl, &i2c_regs_p->ic_con); - hcnt = (IC_CLK * high) / NANO_TO_MICRO; - writel(hcnt, &i2c_regs_p->ic_fs_scl_hcnt); - - lcnt = (IC_CLK * low) / NANO_TO_MICRO; - writel(lcnt, &i2c_regs_p->ic_fs_scl_lcnt); - - /* re-enable i2c ctrl back now that speed is set */ + /* Enable back i2c now speed set */ enbl |= IC_ENABLE_0B; writel(enbl, &i2c_regs_p->ic_enable); } @@ -150,6 +153,10 @@ void i2c_init(int speed, int slaveadd) enbl = readl(&i2c_regs_p->ic_enable); enbl |= IC_ENABLE_0B; writel(enbl, &i2c_regs_p->ic_enable); + +#ifdef CONFIG_I2C_MULTI_BUS + bus_initialized[current_bus] = 1; +#endif } /* @@ -274,7 +281,10 @@ int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len) start_time_rx = get_timer(0); while (len) { - writel(IC_CMD, &i2c_regs_p->ic_cmd_data); + if (len == 1) + writel(IC_CMD | IC_STOP, &i2c_regs_p->ic_cmd_data); + else + writel(IC_CMD, &i2c_regs_p->ic_cmd_data); if (readl(&i2c_regs_p->ic_status) & IC_STATUS_RFNE) { *buffer++ = (uchar)readl(&i2c_regs_p->ic_cmd_data); @@ -313,9 +323,11 @@ int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len) start_time_tx = get_timer(0); while (len) { if (readl(&i2c_regs_p->ic_status) & IC_STATUS_TFNF) { - writel(*buffer, &i2c_regs_p->ic_cmd_data); + if (--len == 0) + writel(*buffer | IC_STOP, &i2c_regs_p->ic_cmd_data); + else + writel(*buffer, &i2c_regs_p->ic_cmd_data); buffer++; - len--; start_time_tx = get_timer(0); } else if (get_timer(start_time_tx) > (nb * I2C_BYTE_TO)) { @@ -344,3 +356,74 @@ int i2c_probe(uchar chip) return ret; } + +#ifdef CONFIG_I2C_MULTI_BUS +int i2c_set_bus_num(unsigned int bus) +{ + switch (bus) { + case 0: + i2c_regs_p = (void *)CONFIG_SYS_I2C_BASE; + break; +#ifdef CONFIG_SYS_I2C_BASE1 + case 1: + i2c_regs_p = (void *)CONFIG_SYS_I2C_BASE1; + break; +#endif +#ifdef CONFIG_SYS_I2C_BASE2 + case 2: + i2c_regs_p = (void *)CONFIG_SYS_I2C_BASE2; + break; +#endif +#ifdef CONFIG_SYS_I2C_BASE3 + case 3: + i2c_regs_p = (void *)CONFIG_SYS_I2C_BASE3; + break; +#endif +#ifdef CONFIG_SYS_I2C_BASE4 + case 4: + i2c_regs_p = (void *)CONFIG_SYS_I2C_BASE4; + break; +#endif +#ifdef CONFIG_SYS_I2C_BASE5 + case 5: + i2c_regs_p = (void *)CONFIG_SYS_I2C_BASE5; + break; +#endif +#ifdef CONFIG_SYS_I2C_BASE6 + case 6: + i2c_regs_p = (void *)CONFIG_SYS_I2C_BASE6; + break; +#endif +#ifdef CONFIG_SYS_I2C_BASE7 + case 7: + i2c_regs_p = (void *)CONFIG_SYS_I2C_BASE7; + break; +#endif +#ifdef CONFIG_SYS_I2C_BASE8 + case 8: + i2c_regs_p = (void *)CONFIG_SYS_I2C_BASE8; + break; +#endif +#ifdef CONFIG_SYS_I2C_BASE9 + case 9: + i2c_regs_p = (void *)CONFIG_SYS_I2C_BASE9; + break; +#endif + default: + printf("Bad bus: %d\n", bus); + return -1; + } + + current_bus = bus; + + if (!bus_initialized[current_bus]) + i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE); + + return 0; +} + +int i2c_get_bus_num(void) +{ + return current_bus; +} +#endif diff --git a/drivers/i2c/designware_i2c.h b/drivers/i2c/designware_i2c.h index 03b520ed43a..2faf4a8717a 100644 --- a/drivers/i2c/designware_i2c.h +++ b/drivers/i2c/designware_i2c.h @@ -60,14 +60,16 @@ struct i2c_regs { u32 ic_tx_abrt_source; }; +#if !defined(IC_CLK) #define IC_CLK 166 +#endif #define NANO_TO_MICRO 1000 /* High and low times in different speed modes (in ns) */ #define MIN_SS_SCL_HIGHTIME 4000 -#define MIN_SS_SCL_LOWTIME 5000 -#define MIN_FS_SCL_HIGHTIME 800 -#define MIN_FS_SCL_LOWTIME 1700 +#define MIN_SS_SCL_LOWTIME 4700 +#define MIN_FS_SCL_HIGHTIME 600 +#define MIN_FS_SCL_LOWTIME 1300 #define MIN_HS_SCL_HIGHTIME 60 #define MIN_HS_SCL_LOWTIME 160 @@ -95,6 +97,7 @@ struct i2c_regs { /* i2c data buffer and command register definitions */ #define IC_CMD 0x0100 +#define IC_STOP 0x0200 /* i2c interrupt status register definitions */ #define IC_GEN_CALL 0x0800 diff --git a/drivers/i2c/mxc_i2c.c b/drivers/i2c/mxc_i2c.c index 18270b9de64..a73b10b9c49 100644 --- a/drivers/i2c/mxc_i2c.c +++ b/drivers/i2c/mxc_i2c.c @@ -115,7 +115,7 @@ static uint8_t i2c_imx_get_clk(unsigned int rate) /* * Set I2C Bus speed */ -int bus_i2c_set_bus_speed(void *base, int speed) +static int bus_i2c_set_bus_speed(void *base, int speed) { struct mxc_i2c_regs *i2c_regs = (struct mxc_i2c_regs *)base; u8 clk_idx = i2c_imx_get_clk(speed); @@ -133,7 +133,7 @@ int bus_i2c_set_bus_speed(void *base, int speed) /* * Get I2C Speed */ -unsigned int bus_i2c_get_bus_speed(void *base) +static unsigned int bus_i2c_get_bus_speed(void *base) { struct mxc_i2c_regs *i2c_regs = (struct mxc_i2c_regs *)base; u8 clk_idx = readb(&i2c_regs->ifdr); diff --git a/drivers/i2c/mxs_i2c.c b/drivers/i2c/mxs_i2c.c index 2a193c220d7..b907f7b379b 100644 --- a/drivers/i2c/mxs_i2c.c +++ b/drivers/i2c/mxs_i2c.c @@ -28,6 +28,7 @@ #include <common.h> #include <malloc.h> +#include <i2c.h> #include <asm/errno.h> #include <asm/io.h> #include <asm/arch/clock.h> @@ -40,6 +41,7 @@ void mxs_i2c_reset(void) { struct mxs_i2c_regs *i2c_regs = (struct mxs_i2c_regs *)MXS_I2C0_BASE; int ret; + int speed = i2c_get_bus_speed(); ret = mxs_reset_block(&i2c_regs->hw_i2c_ctrl0_reg); if (ret) { @@ -53,6 +55,8 @@ void mxs_i2c_reset(void) &i2c_regs->hw_i2c_ctrl1_clr); writel(I2C_QUEUECTRL_PIO_QUEUE_MODE, &i2c_regs->hw_i2c_queuectrl_set); + + i2c_set_bus_speed(speed); } void mxs_i2c_setup_read(uint8_t chip, int len) @@ -210,37 +214,65 @@ int i2c_probe(uchar chip) return ret; } -void i2c_init(int speed, int slaveadd) +int i2c_set_bus_speed(unsigned int speed) { struct mxs_i2c_regs *i2c_regs = (struct mxs_i2c_regs *)MXS_I2C0_BASE; + /* + * The timing derivation algorithm. There is no documentation for this + * algorithm available, it was derived by using the scope and fiddling + * with constants until the result observed on the scope was good enough + * for 20kHz, 50kHz, 100kHz, 200kHz, 300kHz and 400kHz. It should be + * possible to assume the algorithm works for other frequencies as well. + * + * Note it was necessary to cap the frequency on both ends as it's not + * possible to configure completely arbitrary frequency for the I2C bus + * clock. + */ + uint32_t clk = mxc_get_clock(MXC_XTAL_CLK); + uint32_t base = ((clk / speed) - 38) / 2; + uint16_t high_count = base + 3; + uint16_t low_count = base - 3; + uint16_t rcv_count = (high_count * 3) / 4; + uint16_t xmit_count = low_count / 4; + + if (speed > 540000) { + printf("MXS I2C: Speed too high (%d Hz)\n", speed); + return -EINVAL; + } - mxs_i2c_reset(); - - switch (speed) { - case 100000: - writel((0x0078 << I2C_TIMING0_HIGH_COUNT_OFFSET) | - (0x0030 << I2C_TIMING0_RCV_COUNT_OFFSET), - &i2c_regs->hw_i2c_timing0); - writel((0x0080 << I2C_TIMING1_LOW_COUNT_OFFSET) | - (0x0030 << I2C_TIMING1_XMIT_COUNT_OFFSET), - &i2c_regs->hw_i2c_timing1); - break; - case 400000: - writel((0x000f << I2C_TIMING0_HIGH_COUNT_OFFSET) | - (0x0007 << I2C_TIMING0_RCV_COUNT_OFFSET), - &i2c_regs->hw_i2c_timing0); - writel((0x001f << I2C_TIMING1_LOW_COUNT_OFFSET) | - (0x000f << I2C_TIMING1_XMIT_COUNT_OFFSET), - &i2c_regs->hw_i2c_timing1); - break; - default: - printf("MXS I2C: Invalid speed selected (%d Hz)\n", speed); - return; + if (speed < 12000) { + printf("MXS I2C: Speed too low (%d Hz)\n", speed); + return -EINVAL; } - writel((0x0015 << I2C_TIMING2_BUS_FREE_OFFSET) | - (0x000d << I2C_TIMING2_LEADIN_COUNT_OFFSET), + writel((high_count << 16) | rcv_count, &i2c_regs->hw_i2c_timing0); + writel((low_count << 16) | xmit_count, &i2c_regs->hw_i2c_timing1); + + writel((0x0030 << I2C_TIMING2_BUS_FREE_OFFSET) | + (0x0030 << I2C_TIMING2_LEADIN_COUNT_OFFSET), &i2c_regs->hw_i2c_timing2); + return 0; +} + +unsigned int i2c_get_bus_speed(void) +{ + struct mxs_i2c_regs *i2c_regs = (struct mxs_i2c_regs *)MXS_I2C0_BASE; + uint32_t clk = mxc_get_clock(MXC_XTAL_CLK); + uint32_t timing0; + + timing0 = readl(&i2c_regs->hw_i2c_timing0); + /* + * This is a reverse version of the algorithm presented in + * i2c_set_bus_speed(). Please refer there for details. + */ + return clk / ((((timing0 >> 16) - 3) * 2) + 38); +} + +void i2c_init(int speed, int slaveadd) +{ + mxs_i2c_reset(); + i2c_set_bus_speed(speed); + return; } diff --git a/drivers/i2c/omap24xx_i2c.c b/drivers/i2c/omap24xx_i2c.c index 094305fdf93..af454f901c7 100644 --- a/drivers/i2c/omap24xx_i2c.c +++ b/drivers/i2c/omap24xx_i2c.c @@ -179,7 +179,8 @@ static int i2c_read_byte(u8 devaddr, u16 regoffset, u8 alen, u8 *value) if (status & I2C_STAT_XRDY) { w = tmpbuf[i++]; #if !(defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX) || \ - defined(CONFIG_OMAP44XX) || defined(CONFIG_AM33XX)) + defined(CONFIG_OMAP44XX) || defined(CONFIG_AM33XX) || \ + defined(CONFIG_OMAP54XX)) w |= tmpbuf[i++] << 8; #endif writew(w, &i2c_base->data); @@ -209,7 +210,8 @@ static int i2c_read_byte(u8 devaddr, u16 regoffset, u8 alen, u8 *value) } if (status & I2C_STAT_RRDY) { #if defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX) || \ - defined(CONFIG_OMAP44XX) || defined(CONFIG_AM33XX) + defined(CONFIG_OMAP44XX) || defined(CONFIG_AM33XX) || \ + defined(CONFIG_OMAP54XX) *value = readb(&i2c_base->data); #else *value = readw(&i2c_base->data); @@ -239,7 +241,8 @@ static void flush_fifo(void) stat = readw(&i2c_base->stat); if (stat == I2C_STAT_RRDY) { #if defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX) || \ - defined(CONFIG_OMAP44XX) || defined(CONFIG_AM33XX) + defined(CONFIG_OMAP44XX) || defined(CONFIG_AM33XX) || \ + defined(CONFIG_OMAP54XX) readb(&i2c_base->data); #else readw(&i2c_base->data); @@ -289,7 +292,8 @@ int i2c_probe(uchar chip) if (status & I2C_STAT_RRDY) { res = 0; #if defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX) || \ - defined(CONFIG_OMAP44XX) || defined(CONFIG_AM33XX) + defined(CONFIG_OMAP44XX) || defined(CONFIG_AM33XX) || \ + defined(CONFIG_OMAP54XX) readb(&i2c_base->data); #else readw(&i2c_base->data); @@ -376,7 +380,8 @@ int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len) if (status & I2C_STAT_XRDY) { w = (i < 0) ? tmpbuf[2+i] : buffer[i]; #if !(defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX) || \ - defined(CONFIG_OMAP44XX) || defined(CONFIG_AM33XX)) + defined(CONFIG_OMAP44XX) || defined(CONFIG_AM33XX) || \ + defined(CONFIG_OMAP54XX)) w |= ((++i < 0) ? tmpbuf[2+i] : buffer[i]) << 8; #endif writew(w, &i2c_base->data); diff --git a/drivers/i2c/s3c24x0_i2c.c b/drivers/i2c/s3c24x0_i2c.c index 9bc4c7f1d1c..90d297a2842 100644 --- a/drivers/i2c/s3c24x0_i2c.c +++ b/drivers/i2c/s3c24x0_i2c.c @@ -27,7 +27,7 @@ */ #include <common.h> -#ifdef CONFIG_EXYNOS5 +#if (defined CONFIG_EXYNOS4 || defined CONFIG_EXYNOS5) #include <asm/arch/clk.h> #include <asm/arch/cpu.h> #else @@ -62,7 +62,7 @@ static unsigned int g_current_bus; /* Stores Current I2C Bus */ -#ifndef CONFIG_EXYNOS5 +#if !(defined CONFIG_EXYNOS4 || defined CONFIG_EXYNOS5) static int GetI2CSDA(void) { struct s3c24x0_gpio *gpio = s3c24x0_get_base_gpio(); @@ -121,7 +121,12 @@ static void ReadWriteByte(struct s3c24x0_i2c *i2c) static struct s3c24x0_i2c *get_base_i2c(void) { -#ifdef CONFIG_EXYNOS5 +#ifdef CONFIG_EXYNOS4 + struct s3c24x0_i2c *i2c = (struct s3c24x0_i2c *)(samsung_get_base_i2c() + + (EXYNOS4_I2C_SPACING + * g_current_bus)); + return i2c; +#elif defined CONFIG_EXYNOS5 struct s3c24x0_i2c *i2c = (struct s3c24x0_i2c *)(samsung_get_base_i2c() + (EXYNOS5_I2C_SPACING * g_current_bus)); @@ -134,7 +139,7 @@ static struct s3c24x0_i2c *get_base_i2c(void) static void i2c_ch_init(struct s3c24x0_i2c *i2c, int speed, int slaveadd) { ulong freq, pres = 16, div; -#ifdef CONFIG_EXYNOS5 +#if (defined CONFIG_EXYNOS4 || defined CONFIG_EXYNOS5) freq = get_i2c_clk(); #else freq = get_PCLK(); @@ -188,7 +193,7 @@ unsigned int i2c_get_bus_num(void) void i2c_init(int speed, int slaveadd) { struct s3c24x0_i2c *i2c; -#ifndef CONFIG_EXYNOS5 +#if !(defined CONFIG_EXYNOS4 || defined CONFIG_EXYNOS5) struct s3c24x0_gpio *gpio = s3c24x0_get_base_gpio(); #endif int i; @@ -204,7 +209,7 @@ void i2c_init(int speed, int slaveadd) i--; } -#ifndef CONFIG_EXYNOS5 +#if !(defined CONFIG_EXYNOS4 || defined CONFIG_EXYNOS5) if ((readl(&i2c->iicstat) & I2CSTAT_BSY) || GetI2CSDA() == 0) { #ifdef CONFIG_S3C2410 ulong old_gpecon = readl(&gpio->gpecon); @@ -248,7 +253,7 @@ void i2c_init(int speed, int slaveadd) writel(old_gpecon, &gpio->pgcon); #endif } -#endif /* #ifndef CONFIG_EXYNOS5 */ +#endif /* #if !(defined CONFIG_EXYNOS4 || defined CONFIG_EXYNOS5) */ i2c_ch_init(i2c, speed, slaveadd); } diff --git a/drivers/i2c/soft_i2c.c b/drivers/i2c/soft_i2c.c index 1595c0714a8..ae3c57392b8 100644 --- a/drivers/i2c/soft_i2c.c +++ b/drivers/i2c/soft_i2c.c @@ -30,6 +30,9 @@ #include <ioports.h> #include <asm/io.h> #endif +#if defined(CONFIG_AVR32) +#include <asm/arch/portmux.h> +#endif #if defined(CONFIG_AT91FAMILY) #include <asm/io.h> #include <asm/arch/hardware.h> diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h index 23c96494031..bfedbe44596 100644 --- a/include/asm-generic/gpio.h +++ b/include/asm-generic/gpio.h @@ -42,10 +42,11 @@ */ /** - * Request ownership of a GPIO. + * Request a gpio. This should be called before any of the other functions + * are used on this gpio. * - * @param gpio GPIO number - * @param label Name given to the GPIO + * @param gp GPIO number + * @param label User label for this GPIO * @return 0 if ok, -1 on error */ int gpio_request(unsigned gpio, const char *label); @@ -93,14 +94,4 @@ int gpio_get_value(unsigned gpio); * @return 0 if ok, -1 on error */ int gpio_set_value(unsigned gpio, int value); - -/** - * Request a gpio. This should be called before any of the other functions - * are used on this gpio. - * - * @param gp GPIO number - * @param label User label for this GPIO - * @return 0 if ok, -1 on error - */ -int gpio_request(unsigned gpio, const char *label); #endif /* _ASM_GENERIC_GPIO_H_ */ diff --git a/include/command.h b/include/command.h index 10bc2606c71..476e7cffc28 100644 --- a/include/command.h +++ b/include/command.h @@ -89,10 +89,10 @@ extern int cmd_auto_complete(const char *const prompt, char *buf, int *np, int * */ #if defined(CONFIG_CMD_MEMORY) \ - || defined(CONFIG_CMD_I2C) \ - || defined(CONFIG_CMD_ITEST) \ - || defined(CONFIG_CMD_PCI) \ - || defined(CONFIG_CMD_PORTIO) + || defined(CONFIG_CMD_I2C) \ + || defined(CONFIG_CMD_ITEST) \ + || defined(CONFIG_CMD_PCI) \ + || defined(CONFIG_CMD_PORTIO) #define CMD_DATA_SIZE extern int cmd_get_data_size(char* arg, int default_size); #endif diff --git a/include/config_cmd_all.h b/include/config_cmd_all.h index f434cd08910..e82f6421c0a 100644 --- a/include/config_cmd_all.h +++ b/include/config_cmd_all.h @@ -40,12 +40,15 @@ #define CONFIG_CMD_FDOS /* Floppy DOS support */ #define CONFIG_CMD_FLASH /* flinfo, erase, protect */ #define CONFIG_CMD_FPGA /* FPGA configuration Support */ +#define CONFIG_CMD_GETTIME /* Get time since boot */ +#define CONFIG_CMD_HASH /* calculate hash / digest */ #define CONFIG_CMD_HWFLOW /* RTS/CTS hw flow control */ #define CONFIG_CMD_I2C /* I2C serial bus support */ #define CONFIG_CMD_IDE /* IDE harddisk support */ #define CONFIG_CMD_IMI /* iminfo */ #define CONFIG_CMD_IMLS /* List all found images */ #define CONFIG_CMD_IMMAP /* IMMR dump support */ +#define CONFIG_CMD_IO /* Access to X86 IO space */ #define CONFIG_CMD_IRQ /* irqinfo */ #define CONFIG_CMD_ITEST /* Integer (and string) test */ #define CONFIG_CMD_JFFS2 /* JFFS2 Support */ @@ -70,6 +73,7 @@ #define CONFIG_CMD_REGINFO /* Register dump */ #define CONFIG_CMD_REISER /* Reiserfs support */ #define CONFIG_CMD_RARP /* rarpboot support */ +#define CONFIG_CMD_READ /* Read data from partition */ #define CONFIG_CMD_RUN /* run command in env variable */ #define CONFIG_CMD_SAVEENV /* saveenv */ #define CONFIG_CMD_SAVES /* save S record dump */ diff --git a/include/configs/smdk5250.h b/include/configs/smdk5250.h index c0f86228b08..39a347af84a 100644 --- a/include/configs/smdk5250.h +++ b/include/configs/smdk5250.h @@ -203,6 +203,7 @@ #define CONFIG_I2C_MULTI_BUS #define CONFIG_MAX_I2C_NUM 8 #define CONFIG_SYS_I2C_SLAVE 0x0 +#define CONFIG_I2C_EDID /* Ethernet Controllor Driver */ #ifdef CONFIG_CMD_NET @@ -215,4 +216,10 @@ /* Enable devicetree support */ #define CONFIG_OF_LIBFDT +/* SHA hashing */ +#define CONFIG_CMD_HASH +#define CONFIG_HASH_VERIFY +#define CONFIG_SHA1 +#define CONFIG_SHA256 + #endif /* __CONFIG_H */ diff --git a/include/edid.h b/include/edid.h new file mode 100644 index 00000000000..4788de9392d --- /dev/null +++ b/include/edid.h @@ -0,0 +1,275 @@ +/* + * Copyright (c) 2012 The Chromium OS Authors. + * + * (C) Copyright 2010 + * Petr Stetiar <ynezz@true.cz> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * Contains stolen code from ddcprobe project which is: + * Copyright (C) Nalin Dahyabhai <bigfun@pobox.com> + * + */ + +#ifndef __EDID_H_ +#define __EDID_H_ + +#include <linux/types.h> + +#define GET_BIT(_x, _pos) \ + (((_x) >> (_pos)) & 1) +#define GET_BITS(_x, _pos_msb, _pos_lsb) \ + (((_x) >> (_pos_lsb)) & ((1 << ((_pos_msb) - (_pos_lsb) + 1)) - 1)) + +/* Aspect ratios used in EDID info. */ +enum edid_aspect { + ASPECT_625 = 0, + ASPECT_75, + ASPECT_8, + ASPECT_5625, +}; + +/* Detailed timing information used in EDID v1.x */ +struct edid_detailed_timing { + unsigned char pixel_clock[2]; +#define EDID_DETAILED_TIMING_PIXEL_CLOCK(_x) \ + (((((uint32_t)(_x).pixel_clock[1]) << 8) + \ + (_x).pixel_clock[0]) * 10000) + unsigned char horizontal_active; + unsigned char horizontal_blanking; + unsigned char horizontal_active_blanking_hi; +#define EDID_DETAILED_TIMING_HORIZONTAL_ACTIVE(_x) \ + ((GET_BITS((_x).horizontal_active_blanking_hi, 7, 4) << 8) + \ + (_x).horizontal_active) +#define EDID_DETAILED_TIMING_HORIZONTAL_BLANKING(_x) \ + ((GET_BITS((_x).horizontal_active_blanking_hi, 3, 0) << 8) + \ + (_x).horizontal_blanking) + unsigned char vertical_active; + unsigned char vertical_blanking; + unsigned char vertical_active_blanking_hi; +#define EDID_DETAILED_TIMING_VERTICAL_ACTIVE(_x) \ + ((GET_BITS((_x).vertical_active_blanking_hi, 7, 4) << 8) + \ + (_x).vertical_active) +#define EDID_DETAILED_TIMING_VERTICAL_BLANKING(_x) \ + ((GET_BITS((_x).vertical_active_blanking_hi, 3, 0) << 8) + \ + (_x).vertical_blanking) + unsigned char hsync_offset; + unsigned char hsync_pulse_width; + unsigned char sync_offset_pulse_width; + unsigned char hsync_vsync_offset_pulse_width_hi; +#define EDID_DETAILED_TIMING_HSYNC_OFFSET(_x) \ + ((GET_BITS((_x).hsync_vsync_offset_pulse_width_hi, 7, 6) << 8) + \ + (_x).hsync_offset) +#define EDID_DETAILED_TIMING_HSYNC_PULSE_WIDTH(_x) \ + ((GET_BITS((_x).hsync_vsync_offset_pulse_width_hi, 5, 4) << 8) + \ + (_x).hsync_pulse_width) +#define EDID_DETAILED_TIMING_VSYNC_OFFSET(_x) \ + ((GET_BITS((_x).hsync_vsync_offset_pulse_width_hi, 3, 2) << 4) + \ + GET_BITS((_x).vsync_offset_pulse_width, 7, 4)) +#define EDID_DETAILED_TIMING_VSYNC_PULSE_WIDTH(_x) \ + ((GET_BITS((_x).hsync_vsync_offset_pulse_width_hi, 1, 0) << 4) + \ + GET_BITS((_x).vsync_offset_pulse_width, 3, 0)) + unsigned char himage_size; + unsigned char vimage_size; + unsigned char himage_vimage_size_hi; +#define EDID_DETAILED_TIMING_HIMAGE_SIZE(_x) \ + ((GET_BITS((_x).himage_vimage_size_hi, 7, 4) << 8) + (_x).himage_size) +#define EDID_DETAILED_TIMING_VIMAGE_SIZE(_x) \ + ((GET_BITS((_x).himage_vimage_size_hi, 3, 0) << 8) + (_x).vimage_size) + unsigned char hborder; + unsigned char vborder; + unsigned char flags; +#define EDID_DETAILED_TIMING_FLAG_INTERLACED(_x) \ + GET_BIT((_x).flags, 7) +#define EDID_DETAILED_TIMING_FLAG_STEREO(_x) \ + GET_BITS((_x).flags, 6, 5) +#define EDID_DETAILED_TIMING_FLAG_DIGITAL_COMPOSITE(_x) \ + GET_BITS((_x).flags, 4, 3) +#define EDID_DETAILED_TIMING_FLAG_POLARITY(_x) \ + GET_BITS((_x).flags, 2, 1) +#define EDID_DETAILED_TIMING_FLAG_INTERLEAVED(_x) \ + GET_BIT((_x).flags, 0) +} __attribute__ ((__packed__)); + +enum edid_monitor_descriptor_types { + EDID_MONITOR_DESCRIPTOR_SERIAL = 0xff, + EDID_MONITOR_DESCRIPTOR_ASCII = 0xfe, + EDID_MONITOR_DESCRIPTOR_RANGE = 0xfd, + EDID_MONITOR_DESCRIPTOR_NAME = 0xfc, +}; + +struct edid_monitor_descriptor { + uint16_t zero_flag_1; + unsigned char zero_flag_2; + unsigned char type; + unsigned char zero_flag_3; + union { + char string[13]; + struct { + unsigned char vertical_min; + unsigned char vertical_max; + unsigned char horizontal_min; + unsigned char horizontal_max; + unsigned char pixel_clock_max; + unsigned char gtf_data[8]; + } range_data; + } data; +} __attribute__ ((__packed__)); + +struct edid1_info { + unsigned char header[8]; + unsigned char manufacturer_name[2]; +#define EDID1_INFO_MANUFACTURER_NAME_ZERO(_x) \ + GET_BIT(((_x).manufacturer_name[0]), 7) +#define EDID1_INFO_MANUFACTURER_NAME_CHAR1(_x) \ + GET_BITS(((_x).manufacturer_name[0]), 6, 2) +#define EDID1_INFO_MANUFACTURER_NAME_CHAR2(_x) \ + ((GET_BITS(((_x).manufacturer_name[0]), 1, 0) << 3) + \ + GET_BITS(((_x).manufacturer_name[1]), 7, 5)) +#define EDID1_INFO_MANUFACTURER_NAME_CHAR3(_x) \ + GET_BITS(((_x).manufacturer_name[1]), 4, 0) + unsigned char product_code[2]; +#define EDID1_INFO_PRODUCT_CODE(_x) \ + (((uint16_t)(_x).product_code[1] << 8) + (_x).product_code[0]) + unsigned char serial_number[4]; +#define EDID1_INFO_SERIAL_NUMBER(_x) \ + (((uint32_t)(_x).serial_number[3] << 24) + \ + ((_x).serial_number[2] << 16) + ((_x).serial_number[1] << 8) + \ + (_x).serial_number[0]) + unsigned char week; + unsigned char year; + unsigned char version; + unsigned char revision; + unsigned char video_input_definition; +#define EDID1_INFO_VIDEO_INPUT_DIGITAL(_x) \ + GET_BIT(((_x).video_input_definition), 7) +#define EDID1_INFO_VIDEO_INPUT_VOLTAGE_LEVEL(_x) \ + GET_BITS(((_x).video_input_definition), 6, 5) +#define EDID1_INFO_VIDEO_INPUT_BLANK_TO_BLACK(_x) \ + GET_BIT(((_x).video_input_definition), 4) +#define EDID1_INFO_VIDEO_INPUT_SEPARATE_SYNC(_x) \ + GET_BIT(((_x).video_input_definition), 3) +#define EDID1_INFO_VIDEO_INPUT_COMPOSITE_SYNC(_x) \ + GET_BIT(((_x).video_input_definition), 2) +#define EDID1_INFO_VIDEO_INPUT_SYNC_ON_GREEN(_x) \ + GET_BIT(((_x).video_input_definition), 1) +#define EDID1_INFO_VIDEO_INPUT_SERRATION_V(_x) \ + GET_BIT(((_x).video_input_definition), 0) + unsigned char max_size_horizontal; + unsigned char max_size_vertical; + unsigned char gamma; + unsigned char feature_support; +#define EDID1_INFO_FEATURE_STANDBY(_x) \ + GET_BIT(((_x).feature_support), 7) +#define EDID1_INFO_FEATURE_SUSPEND(_x) \ + GET_BIT(((_x).feature_support), 6) +#define EDID1_INFO_FEATURE_ACTIVE_OFF(_x) \ + GET_BIT(((_x).feature_support), 5) +#define EDID1_INFO_FEATURE_DISPLAY_TYPE(_x) \ + GET_BITS(((_x).feature_support), 4, 3) +#define EDID1_INFO_FEATURE_RGB(_x) \ + GET_BIT(((_x).feature_support), 2) +#define EDID1_INFO_FEATURE_PREFERRED_TIMING_MODE(_x) \ + GET_BIT(((_x).feature_support), 1) +#define EDID1_INFO_FEATURE_DEFAULT_GTF_SUPPORT(_x) \ + GET_BIT(((_x).feature_support), 0) + unsigned char color_characteristics[10]; + unsigned char established_timings[3]; +#define EDID1_INFO_ESTABLISHED_TIMING_720X400_70(_x) \ + GET_BIT(((_x).established_timings[0]), 7) +#define EDID1_INFO_ESTABLISHED_TIMING_720X400_88(_x) \ + GET_BIT(((_x).established_timings[0]), 6) +#define EDID1_INFO_ESTABLISHED_TIMING_640X480_60(_x) \ + GET_BIT(((_x).established_timings[0]), 5) +#define EDID1_INFO_ESTABLISHED_TIMING_640X480_67(_x) \ + GET_BIT(((_x).established_timings[0]), 4) +#define EDID1_INFO_ESTABLISHED_TIMING_640X480_72(_x) \ + GET_BIT(((_x).established_timings[0]), 3) +#define EDID1_INFO_ESTABLISHED_TIMING_640X480_75(_x) \ + GET_BIT(((_x).established_timings[0]), 2) +#define EDID1_INFO_ESTABLISHED_TIMING_800X600_56(_x) \ + GET_BIT(((_x).established_timings[0]), 1) +#define EDID1_INFO_ESTABLISHED_TIMING_800X600_60(_x) \ + GET_BIT(((_x).established_timings[0]), 0) +#define EDID1_INFO_ESTABLISHED_TIMING_800X600_72(_x) \ + GET_BIT(((_x).established_timings[1]), 7) +#define EDID1_INFO_ESTABLISHED_TIMING_800X600_75(_x) \ + GET_BIT(((_x).established_timings[1]), 6) +#define EDID1_INFO_ESTABLISHED_TIMING_832X624_75(_x) \ + GET_BIT(((_x).established_timings[1]), 5) +#define EDID1_INFO_ESTABLISHED_TIMING_1024X768_87I(_x) \ + GET_BIT(((_x).established_timings[1]), 4) +#define EDID1_INFO_ESTABLISHED_TIMING_1024X768_60(_x) \ + GET_BIT(((_x).established_timings[1]), 3) +#define EDID1_INFO_ESTABLISHED_TIMING_1024X768_70(_x) \ + GET_BIT(((_x).established_timings[1]), 2) +#define EDID1_INFO_ESTABLISHED_TIMING_1024X768_75(_x) \ + GET_BIT(((_x).established_timings[1]), 1) +#define EDID1_INFO_ESTABLISHED_TIMING_1280X1024_75(_x) \ + GET_BIT(((_x).established_timings[1]), 0) +#define EDID1_INFO_ESTABLISHED_TIMING_1152X870_75(_x) \ + GET_BIT(((_x).established_timings[2]), 7) + struct { + unsigned char xresolution; + unsigned char aspect_vfreq; + } __attribute__((__packed__)) standard_timings[8]; +#define EDID1_INFO_STANDARD_TIMING_XRESOLUTION(_x, _i) \ + (((_x).standard_timings[_i]).xresolution) +#define EDID1_INFO_STANDARD_TIMING_ASPECT(_x, _i) \ + GET_BITS(((_x).standard_timings[_i].aspect_vfreq), 7, 6) +#define EDID1_INFO_STANDARD_TIMING_VFREQ(_x, _i) \ + GET_BITS(((_x).standard_timings[_i].aspect_vfreq), 5, 0) + union { + unsigned char timing[72]; + struct edid_monitor_descriptor descriptor[4]; + } monitor_details; + unsigned char extension_flag; + unsigned char checksum; +} __attribute__ ((__packed__)); + +/** + * Print the EDID info. + * + * @param edid_info The EDID info to be printed + */ +void edid_print_info(struct edid1_info *edid_info); + +/** + * Check the EDID info. + * + * @param info The EDID info to be checked + * @return 0 on valid, or -1 on invalid + */ +int edid_check_info(struct edid1_info *info); + +/** + * Get the horizontal and vertical rate ranges of the monitor. + * + * @param edid The EDID info + * @param hmin Returns the minimum horizontal rate + * @param hmax Returns the maxium horizontal rate + * @param vmin Returns the minimum vertical rate + * @param vmax Returns the maxium vertical rate + * @return 0 on success, or -1 on error + */ +int edid_get_ranges(struct edid1_info *edid, unsigned int *hmin, + unsigned int *hmax, unsigned int *vmin, + unsigned int *vmax); + +#endif /* __EDID_H_ */ diff --git a/include/hash.h b/include/hash.h new file mode 100644 index 00000000000..34ba558bd09 --- /dev/null +++ b/include/hash.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2012 The Chromium OS Authors. + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef _HASH_H +#define _HASH_H + +#ifdef CONFIG_SHA1SUM_VERIFY +#define CONFIG_HASH_VERIFY +#endif + +struct hash_algo { + const char *name; /* Name of algorithm */ + int digest_size; /* Length of digest */ + /** + * hash_func_ws: Generic hashing function + * + * This is the generic prototype for a hashing function. We only + * have the watchdog version at present. + * + * @input: Input buffer + * @ilen: Input buffer length + * @output: Checksum result (length depends on algorithm) + * @chunk_sz: Trigger watchdog after processing this many bytes + */ + void (*hash_func_ws)(const unsigned char *input, unsigned int ilen, + unsigned char *output, unsigned int chunk_sz); + int chunk_size; /* Watchdog chunk size */ +}; + +/* + * Maximum digest size for all algorithms we support. Having this value + * avoids a malloc() or C99 local declaration in common/cmd_hash.c. + */ +#define HASH_MAX_DIGEST_SIZE 32 + +/** + * hash_command: Process a hash command for a particular algorithm + * + * This common function is used to implement specific hash commands. + * + * @algo_name: Hash algorithm being used + * @verify: Non-zero to enable verify mode + * @cmdtp: Pointer to command table entry + * @flag: Some flags normally 0 (see CMD_FLAG_.. above) + * @argc: Number of arguments (arg 0 must be the command text) + * @argv: Arguments + */ +int hash_command(const char *algo_name, int verify, cmd_tbl_t *cmdtp, int flag, + int argc, char * const argv[]); + +#endif diff --git a/include/linux/string.h b/include/linux/string.h index 9a8cbc24cdc..de833554a1d 100644 --- a/include/linux/string.h +++ b/include/linux/string.h @@ -38,8 +38,11 @@ extern int strcmp(const char *,const char *); #ifndef __HAVE_ARCH_STRNCMP extern int strncmp(const char *,const char *,__kernel_size_t); #endif -#if 0 /* not used - was: #ifndef __HAVE_ARCH_STRNICMP */ -extern int strnicmp(const char *, const char *, __kernel_size_t); +#ifndef __HAVE_ARCH_STRCASECMP +int strcasecmp(const char *s1, const char *s2); +#endif +#ifndef __HAVE_ARCH_STRNCASECMP +extern int strncasecmp(const char *s1, const char *s2, __kernel_size_t len); #endif #ifndef __HAVE_ARCH_STRCHR extern char * strchr(const char *,int); diff --git a/include/sha1.h b/include/sha1.h index 734d1fb153d..da09dab9769 100644 --- a/include/sha1.h +++ b/include/sha1.h @@ -59,7 +59,8 @@ void sha1_starts( sha1_context *ctx ); * \param input buffer holding the data * \param ilen length of the input data */ -void sha1_update( sha1_context *ctx, unsigned char *input, int ilen ); +void sha1_update(sha1_context *ctx, const unsigned char *input, + unsigned int ilen); /** * \brief SHA-1 final digest @@ -76,8 +77,8 @@ void sha1_finish( sha1_context *ctx, unsigned char output[20] ); * \param ilen length of the input data * \param output SHA-1 checksum result */ -void sha1_csum( unsigned char *input, int ilen, - unsigned char output[20] ); +void sha1_csum(const unsigned char *input, unsigned int ilen, + unsigned char *output); /** * \brief Output = SHA-1( input buffer ), with watchdog triggering @@ -87,17 +88,8 @@ void sha1_csum( unsigned char *input, int ilen, * \param output SHA-1 checksum result * \param chunk_sz watchdog triggering period (in bytes of input processed) */ -void sha1_csum_wd (unsigned char *input, int ilen, - unsigned char output[20], unsigned int chunk_sz); - -/** - * \brief Output = SHA-1( file contents ) - * - * \param path input file name - * \param output SHA-1 checksum result - * \return 0 if successful, or 1 if fopen failed - */ -int sha1_file( char *path, unsigned char output[20] ); +void sha1_csum_wd(const unsigned char *input, unsigned int ilen, + unsigned char *output, unsigned int chunk_sz); /** * \brief Output = HMAC-SHA-1( input buffer, hmac key ) @@ -108,9 +100,9 @@ int sha1_file( char *path, unsigned char output[20] ); * \param ilen length of the input data * \param output HMAC-SHA-1 result */ -void sha1_hmac( unsigned char *key, int keylen, - unsigned char *input, int ilen, - unsigned char output[20] ); +void sha1_hmac(const unsigned char *key, int keylen, + const unsigned char *input, unsigned int ilen, + unsigned char *output); /** * \brief Checkup routine diff --git a/include/sha256.h b/include/sha256.h index e38ea898c3e..beadab35ffc 100644 --- a/include/sha256.h +++ b/include/sha256.h @@ -3,6 +3,9 @@ #define SHA256_SUM_LEN 32 +/* Reset watchdog each time we process this many bytes */ +#define CHUNKSZ_SHA256 (64 * 1024) + typedef struct { uint32_t total[2]; uint32_t state[8]; @@ -10,7 +13,10 @@ typedef struct { } sha256_context; void sha256_starts(sha256_context * ctx); -void sha256_update(sha256_context * ctx, uint8_t * input, uint32_t length); +void sha256_update(sha256_context *ctx, const uint8_t *input, uint32_t length); void sha256_finish(sha256_context * ctx, uint8_t digest[SHA256_SUM_LEN]); +void sha256_csum_wd(const unsigned char *input, unsigned int ilen, + unsigned char *output, unsigned int chunk_sz); + #endif /* _SHA256_H */ diff --git a/lib/sha1.c b/lib/sha1.c index da5bc16f3c6..a121224855f 100644 --- a/lib/sha1.c +++ b/lib/sha1.c @@ -73,7 +73,7 @@ void sha1_starts (sha1_context * ctx) ctx->state[4] = 0xC3D2E1F0; } -static void sha1_process (sha1_context * ctx, unsigned char data[64]) +static void sha1_process(sha1_context *ctx, const unsigned char data[64]) { unsigned long temp, W[16], A, B, C, D, E; @@ -230,7 +230,8 @@ static void sha1_process (sha1_context * ctx, unsigned char data[64]) /* * SHA-1 process buffer */ -void sha1_update (sha1_context * ctx, unsigned char *input, int ilen) +void sha1_update(sha1_context *ctx, const unsigned char *input, + unsigned int ilen) { int fill; unsigned long left; @@ -305,7 +306,8 @@ void sha1_finish (sha1_context * ctx, unsigned char output[20]) /* * Output = SHA-1( input buffer ) */ -void sha1_csum (unsigned char *input, int ilen, unsigned char output[20]) +void sha1_csum(const unsigned char *input, unsigned int ilen, + unsigned char *output) { sha1_context ctx; @@ -318,12 +320,12 @@ void sha1_csum (unsigned char *input, int ilen, unsigned char output[20]) * Output = SHA-1( input buffer ). Trigger the watchdog every 'chunk_sz' * bytes of input processed. */ -void sha1_csum_wd (unsigned char *input, int ilen, unsigned char output[20], - unsigned int chunk_sz) +void sha1_csum_wd(const unsigned char *input, unsigned int ilen, + unsigned char *output, unsigned int chunk_sz) { sha1_context ctx; #if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG) - unsigned char *end, *curr; + const unsigned char *end, *curr; int chunk; #endif @@ -350,8 +352,9 @@ void sha1_csum_wd (unsigned char *input, int ilen, unsigned char output[20], /* * Output = HMAC-SHA-1( input buffer, hmac key ) */ -void sha1_hmac (unsigned char *key, int keylen, - unsigned char *input, int ilen, unsigned char output[20]) +void sha1_hmac(const unsigned char *key, int keylen, + const unsigned char *input, unsigned int ilen, + unsigned char *output) { int i; sha1_context ctx; diff --git a/lib/sha256.c b/lib/sha256.c index deb63a40b6d..ab2db4890ae 100644 --- a/lib/sha256.c +++ b/lib/sha256.c @@ -60,7 +60,7 @@ void sha256_starts(sha256_context * ctx) ctx->state[7] = 0x5BE0CD19; } -void sha256_process(sha256_context * ctx, uint8_t data[64]) +static void sha256_process(sha256_context *ctx, const uint8_t data[64]) { uint32_t temp1, temp2; uint32_t W[64]; @@ -191,7 +191,7 @@ void sha256_process(sha256_context * ctx, uint8_t data[64]) ctx->state[7] += H; } -void sha256_update(sha256_context * ctx, uint8_t * input, uint32_t length) +void sha256_update(sha256_context *ctx, const uint8_t *input, uint32_t length) { uint32_t left, fill; @@ -260,3 +260,36 @@ void sha256_finish(sha256_context * ctx, uint8_t digest[32]) PUT_UINT32_BE(ctx->state[6], digest, 24); PUT_UINT32_BE(ctx->state[7], digest, 28); } + +/* + * Output = SHA-256( input buffer ). Trigger the watchdog every 'chunk_sz' + * bytes of input processed. + */ +void sha256_csum_wd(const unsigned char *input, unsigned int ilen, + unsigned char *output, unsigned int chunk_sz) +{ + sha256_context ctx; +#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG) + unsigned char *end, *curr; + int chunk; +#endif + + sha256_starts(&ctx); + +#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG) + curr = input; + end = input + ilen; + while (curr < end) { + chunk = end - curr; + if (chunk > chunk_sz) + chunk = chunk_sz; + sha256_update(&ctx, curr, chunk); + curr += chunk; + WATCHDOG_RESET(); + } +#else + sha256_update(&ctx, input, ilen); +#endif + + sha256_finish(&ctx, output); +} diff --git a/lib/string.c b/lib/string.c index c3ad055e2ca..68f60bea125 100644 --- a/lib/string.c +++ b/lib/string.c @@ -21,14 +21,13 @@ #include <malloc.h> -#if 0 /* not used - was: #ifndef __HAVE_ARCH_STRNICMP */ /** - * strnicmp - Case insensitive, length-limited string comparison + * strncasecmp - Case insensitive, length-limited string comparison * @s1: One string * @s2: The other string * @len: the maximum number of characters to compare */ -int strnicmp(const char *s1, const char *s2, size_t len) +int strncasecmp(const char *s1, const char *s2, size_t len) { /* Yes, Virginia, it had better be unsigned */ unsigned char c1, c2; @@ -52,7 +51,16 @@ int strnicmp(const char *s1, const char *s2, size_t len) } return (int)c1 - (int)c2; } -#endif + +/** + * strcasecmp - Case insensitive string comparison + * @s1: One string + * @s2: The other string + */ +int strcasecmp(const char *s1, const char *s2) +{ + return strncasecmp(s1, s2, -1U); +} char * ___strtok; diff --git a/tools/fit_image.c b/tools/fit_image.c index ef9ffeeec59..76bbba125a8 100644 --- a/tools/fit_image.c +++ b/tools/fit_image.c @@ -80,7 +80,7 @@ static int fit_handle_file (struct mkimage_params *params) } sprintf (tmpfile, "%s%s", params->imagefile, MKIMAGE_TMPFILE_SUFFIX); - /* dtc -I dts -O -p 200 datafile > tmpfile */ + /* dtc -I dts -O dtb -p 500 datafile > tmpfile */ sprintf (cmd, "%s %s %s > %s", MKIMAGE_DTC, params->dtc, params->datafile, tmpfile); debug ("Trying to execute \"%s\"\n", cmd); |