diff --git a/.travis.yml b/.travis.yml index 2b759c9..f78749a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -47,6 +47,7 @@ install: - virtualenv /tmp/venv - . /tmp/venv/bin/activate - pip install pytest + - pip install python-subunit - grub-mkimage -o ~/grub_x86.efi -O i386-efi normal echo lsefimmap lsefi lsefisystab efinet tftp minicmd - mkdir ~/grub2-arm - ( cd ~/grub2-arm; wget -O - http://download.opensuse.org/ports/armv7hl/distribution/leap/42.2/repo/oss/suse/armv7hl/grub2-arm-efi-2.02~beta2-87.1.armv7hl.rpm | rpm2cpio | cpio -di ) diff --git a/Makefile b/Makefile index 1d7d5f2..aadd1ec 100644 --- a/Makefile +++ b/Makefile @@ -1524,7 +1524,7 @@ $(defaultenv_h): $(CONFIG_DEFAULT_ENV_FILE:"%"=%) FORCE # --------------------------------------------------------------------------- quiet_cmd_cpp_lds = LDS $@ cmd_cpp_lds = $(CPP) -Wp,-MD,$(depfile) $(cpp_flags) $(LDPPFLAGS) \ - -D__ASSEMBLY__ -x assembler-with-cpp -P -o $@ $< + -D__ASSEMBLY__ -x assembler-with-cpp -std=c99 -P -o $@ $< u-boot.lds: $(LDSCRIPT) prepare FORCE $(call if_changed_dep,cpp_lds) @@ -1698,6 +1698,10 @@ help: @echo 'Configuration targets:' @$(MAKE) -f $(srctree)/scripts/kconfig/Makefile help @echo '' + @echo 'Test targets:' + @echo '' + @echo ' check - Run all automated tests that use sandbox' + @echo '' @echo 'Other generic targets:' @echo ' all - Build all necessary images depending on configuration' @echo ' tests - Build U-Boot for sandbox and run tests' @@ -1736,7 +1740,7 @@ help: @echo 'Execute "make" or "make all" to build all targets marked with [*] ' @echo 'For further info see the ./README file' -tests: +tests check: $(srctree)/test/run # Documentation targets diff --git a/arch/sandbox/cpu/os.c b/arch/sandbox/cpu/os.c index 9fbcb9e..07e4647 100644 --- a/arch/sandbox/cpu/os.c +++ b/arch/sandbox/cpu/os.c @@ -38,14 +38,6 @@ ssize_t os_read(int fd, void *buf, size_t count) return read(fd, buf, count); } -ssize_t os_read_no_block(int fd, void *buf, size_t count) -{ - const int flags = fcntl(fd, F_GETFL, 0); - - fcntl(fd, F_SETFL, flags | O_NONBLOCK); - return os_read(fd, buf, count); -} - ssize_t os_write(int fd, const void *buf, size_t count) { return write(fd, buf, count); @@ -85,6 +77,8 @@ int os_open(const char *pathname, int os_flags) if (os_flags & OS_O_CREAT) flags |= O_CREAT; + if (os_flags & OS_O_TRUNC) + flags |= O_TRUNC; return open(pathname, flags, 0777); } @@ -104,14 +98,41 @@ void os_exit(int exit_code) exit(exit_code); } +int os_write_file(const char *name, const void *buf, int size) +{ + char fname[256]; + int fd; + + fd = os_open(fname, OS_O_WRONLY | OS_O_CREAT | OS_O_TRUNC); + if (fd < 0) { + printf("Cannot open file '%s'\n", fname); + return -EIO; + } + if (os_write(fd, buf, size) != size) { + printf("Cannot write to file '%s'\n", fname); + return -EIO; + } + os_close(fd); + printf("Write '%s', size %#x (%d)\n", name, size, size); + + return 0; +} + /* Restore tty state when we exit */ static struct termios orig_term; static bool term_setup; +static bool term_nonblock; void os_fd_restore(void) { if (term_setup) { + int flags; + tcsetattr(0, TCSANOW, &orig_term); + if (term_nonblock) { + flags = fcntl(0, F_GETFL, 0); + fcntl(0, F_SETFL, flags & ~O_NONBLOCK); + } term_setup = false; } } @@ -120,6 +141,7 @@ void os_fd_restore(void) void os_tty_raw(int fd, bool allow_sigs) { struct termios term; + int flags; if (term_setup) return; @@ -136,6 +158,13 @@ void os_tty_raw(int fd, bool allow_sigs) if (tcsetattr(fd, TCSANOW, &term)) return; + flags = fcntl(fd, F_GETFL, 0); + if (!(flags & O_NONBLOCK)) { + if (fcntl(fd, F_SETFL, flags | O_NONBLOCK)) + return; + term_nonblock = true; + } + term_setup = true; atexit(os_fd_restore); } @@ -569,15 +598,40 @@ int os_find_u_boot(char *fname, int maxlen) struct sandbox_state *state = state_get_current(); const char *progname = state->argv[0]; int len = strlen(progname); + const char *suffix; char *p; int fd; if (len >= maxlen || len < 4) return -ENOSPC; - /* Look for 'u-boot' in the same directory as 'u-boot-spl' */ strcpy(fname, progname); - if (!strcmp(fname + len - 4, "-spl")) { + suffix = fname + len - 4; + + /* If we are TPL, boot to SPL */ + if (!strcmp(suffix, "-tpl")) { + fname[len - 3] = 's'; + fd = os_open(fname, O_RDONLY); + if (fd >= 0) { + close(fd); + return 0; + } + + /* Look for 'u-boot-tpl' in the tpl/ directory */ + p = strstr(fname, "/tpl/"); + if (p) { + p[1] = 's'; + fd = os_open(fname, O_RDONLY); + if (fd >= 0) { + close(fd); + return 0; + } + } + return -ENOENT; + } + + /* Look for 'u-boot' in the same directory as 'u-boot-spl' */ + if (!strcmp(suffix, "-spl")) { fname[len - 4] = '\0'; fd = os_open(fname, O_RDONLY); if (fd >= 0) { @@ -636,3 +690,14 @@ void os_abort(void) { abort(); } + +int os_mprotect_allow(void *start, size_t len) +{ + int page_size = getpagesize(); + + /* Move start to the start of a page, len to the end */ + start = (void *)(((ulong)start) & ~(page_size - 1)); + len = (len + page_size * 2) & ~(page_size - 1); + + return mprotect(start, len, PROT_READ | PROT_WRITE); +} diff --git a/arch/sandbox/cpu/start.c b/arch/sandbox/cpu/start.c index 59c68a2..2ee3b48 100644 --- a/arch/sandbox/cpu/start.c +++ b/arch/sandbox/cpu/start.c @@ -177,7 +177,7 @@ static int sandbox_cmdline_cb_memory(struct sandbox_state *state, err = os_read_ram_buf(arg); if (err) { - printf("Failed to read RAM buffer\n"); + printf("Failed to read RAM buffer '%s': %d\n", arg, err); return err; } @@ -273,6 +273,16 @@ static int sandbox_cmdline_cb_verbose(struct sandbox_state *state, } SANDBOX_CMDLINE_OPT_SHORT(verbose, 'v', 0, "Show test output"); +static int sandbox_cmdline_cb_log_level(struct sandbox_state *state, + const char *arg) +{ + state->default_log_level = simple_strtol(arg, NULL, 10); + + return 0; +} +SANDBOX_CMDLINE_OPT_SHORT(log_level, 'L', 1, + "Set log level (0=panic, 7=debug)"); + int board_run_command(const char *cmdline) { printf("## Commands are disabled. Please enable CONFIG_CMDLINE.\n"); @@ -304,15 +314,14 @@ int main(int argc, char *argv[]) if (ret) goto err; - /* Remove old memory file if required */ - if (state->ram_buf_rm && state->ram_buf_fname) - os_unlink(state->ram_buf_fname); - memset(&data, '\0', sizeof(data)); gd = &data; #if CONFIG_VAL(SYS_MALLOC_F_LEN) gd->malloc_base = CONFIG_MALLOC_F_ADDR; #endif +#if CONFIG_IS_ENABLED(LOG) + gd->default_log_level = state->default_log_level; +#endif setup_ram_buf(state); /* Do pre- and post-relocation init */ diff --git a/arch/sandbox/cpu/state.c b/arch/sandbox/cpu/state.c index 04a11fe..d3b9c05 100644 --- a/arch/sandbox/cpu/state.c +++ b/arch/sandbox/cpu/state.c @@ -393,7 +393,7 @@ int state_uninit(void) state = &main_state; - if (state->write_ram_buf && !state->ram_buf_rm) { + if (state->write_ram_buf) { err = os_write_ram_buf(state->ram_buf_fname); if (err) { printf("Failed to write RAM buffer\n"); @@ -408,6 +408,10 @@ int state_uninit(void) } } + /* Remove old memory file if required */ + if (state->ram_buf_rm && state->ram_buf_fname) + os_unlink(state->ram_buf_fname); + /* Delete this at the last moment so as not to upset gdb too much */ if (state->jumped_fname) os_unlink(state->jumped_fname); diff --git a/arch/sandbox/dts/sandbox.dts b/arch/sandbox/dts/sandbox.dts index 48db781..fb866e8 100644 --- a/arch/sandbox/dts/sandbox.dts +++ b/arch/sandbox/dts/sandbox.dts @@ -18,7 +18,7 @@ stdout-path = "/serial"; }; - cros_ec: cros-ec@0 { + cros_ec: cros-ec { reg = <0 0>; compatible = "google,cros-ec-sandbox"; @@ -26,23 +26,23 @@ * This describes the flash memory within the EC. Note * that the STM32L flash erases to 0, not 0xff. */ - #address-cells = <1>; - #size-cells = <1>; - flash@8000000 { - reg = <0x08000000 0x20000>; + flash { + image-pos = <0x08000000>; + size = <0x20000>; erase-value = <0>; - #address-cells = <1>; - #size-cells = <1>; /* Information for sandbox */ ro { - reg = <0 0xf000>; + image-pos = <0>; + size = <0xf000>; }; wp-ro { - reg = <0xf000 0x1000>; + image-pos = <0xf000>; + size = <0x1000>; }; rw { - reg = <0x10000 0x10000>; + image-pos = <0x10000>; + size = <0x10000>; }; }; }; diff --git a/arch/sandbox/dts/sandbox64.dts b/arch/sandbox/dts/sandbox64.dts index 0e32fda..2c6d351 100644 --- a/arch/sandbox/dts/sandbox64.dts +++ b/arch/sandbox/dts/sandbox64.dts @@ -17,7 +17,7 @@ stdout-path = "/serial"; }; - cros_ec: cros-ec@0 { + cros_ec: cros-ec { reg = <0 0 0 0>; compatible = "google,cros-ec-sandbox"; @@ -25,23 +25,23 @@ * This describes the flash memory within the EC. Note * that the STM32L flash erases to 0, not 0xff. */ - #address-cells = <1>; - #size-cells = <1>; - flash@8000000 { - reg = <0x08000000 0x20000>; + flash { + image-pos = <0x08000000>; + size = <0x20000>; erase-value = <0>; - #address-cells = <1>; - #size-cells = <1>; /* Information for sandbox */ ro { - reg = <0 0xf000>; + image-pos = <0>; + size = <0xf000>; }; wp-ro { - reg = <0xf000 0x1000>; + image-pos = <0xf000>; + size = <0x1000>; }; rw { - reg = <0x10000 0x10000>; + image-pos = <0x10000>; + size = <0x10000>; }; }; }; diff --git a/arch/sandbox/dts/sandbox_pmic.dtsi b/arch/sandbox/dts/sandbox_pmic.dtsi index 403656f..5ecafaa 100644 --- a/arch/sandbox/dts/sandbox_pmic.dtsi +++ b/arch/sandbox/dts/sandbox_pmic.dtsi @@ -60,7 +60,7 @@ regulator-max-microvolt = <3300000>; }; - ldo1 { + ldo_1: ldo1 { regulator-name = "VDD_EMMC_1.8V"; regulator-min-microvolt = <1800000>; regulator-max-microvolt = <1800000>; diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts index ad94901..420b72f 100644 --- a/arch/sandbox/dts/test.dts +++ b/arch/sandbox/dts/test.dts @@ -11,6 +11,8 @@ eth0 = "/eth@10002000"; eth3 = ð_3; eth5 = ð_5; + gpio1 = &gpio_a; + gpio2 = &gpio_b; i2c0 = "/i2c@0"; mmc0 = "/mmc0"; mmc1 = "/mmc1"; @@ -40,6 +42,35 @@ osd0 = "/osd"; }; + cros_ec: cros-ec { + reg = <0 0>; + compatible = "google,cros-ec-sandbox"; + + /* + * This describes the flash memory within the EC. Note + * that the STM32L flash erases to 0, not 0xff. + */ + flash { + image-pos = <0x08000000>; + size = <0x20000>; + erase-value = <0>; + + /* Information for sandbox */ + ro { + image-pos = <0>; + size = <0xf000>; + }; + wp-ro { + image-pos = <0xf000>; + size = <0x1000>; + }; + rw { + image-pos = <0x10000>; + size = <0x10000>; + }; + }; + }; + a-test { reg = <0 1>; compatible = "denx,u-boot-fdt-test"; @@ -62,6 +93,15 @@ reg = <2 1>; }; + backlight: backlight { + compatible = "pwm-backlight"; + enable-gpios = <&gpio_a 1>; + power-supply = <&ldo_1>; + pwms = <&pwm 0 1000>; + default-brightness-level = <5>; + brightness-levels = <0 16 32 64 128 170 202 234 255>; + }; + bind-test { bind-test-child1 { compatible = "sandbox,phy"; @@ -412,12 +452,14 @@ power-domains = <&pwrdom 2>; }; - pwm { + pwm: pwm { compatible = "sandbox,pwm"; + #pwm-cells = <2>; }; pwm2 { compatible = "sandbox,pwm"; + #pwm-cells = <2>; }; ram { @@ -454,6 +496,11 @@ remoteproc-name = "remoteproc-test-dev2"; }; + panel { + compatible = "simple-panel"; + backlight = <&backlight 0 100>; + }; + smem@0 { compatible = "sandbox,smem"; }; diff --git a/arch/sandbox/include/asm/state.h b/arch/sandbox/include/asm/state.h index a612ce8..dcb6d5f 100644 --- a/arch/sandbox/include/asm/state.h +++ b/arch/sandbox/include/asm/state.h @@ -36,7 +36,6 @@ enum state_terminal_raw { }; struct sandbox_spi_info { - const char *spec; struct udevice *emul; }; @@ -89,6 +88,7 @@ struct sandbox_state { enum state_terminal_raw term_raw; /* Terminal raw/cooked */ bool skip_delays; /* Ignore any time delays (for test) */ bool show_test_output; /* Don't suppress stdout in tests */ + int default_log_level; /* Default log level for sandbox */ /* Pointer to information for each SPI bus/cs */ struct sandbox_spi_info spi[CONFIG_SANDBOX_SPI_MAX_BUS] diff --git a/arch/sandbox/include/asm/test.h b/arch/sandbox/include/asm/test.h index 89f3d90..8e60f80 100644 --- a/arch/sandbox/include/asm/test.h +++ b/arch/sandbox/include/asm/test.h @@ -98,4 +98,19 @@ int sandbox_usb_keyb_add_string(struct udevice *dev, const char *str); * @buflen: length of buffer in bytes */ int sandbox_osd_get_mem(struct udevice *dev, u8 *buf, size_t buflen); + +/** + * sandbox_pwm_get_config() - get the PWM config for a channel + * + * @dev: Device to check + * @channel: Channel number to check + * @period_ns: Period of the PWM in nanoseconds + * @duty_ns: Current duty cycle of the PWM in nanoseconds + * @enable: true if the PWM is enabled + * @polarity: true if the PWM polarity is active high + * @return 0 if OK, -ENOSPC if the PWM number is invalid + */ +int sandbox_pwm_get_config(struct udevice *dev, uint channel, uint *period_nsp, + uint *duty_nsp, bool *enablep, bool *polarityp); + #endif diff --git a/arch/x86/cpu/coreboot/coreboot.c b/arch/x86/cpu/coreboot/coreboot.c index a6fd3a8..aaf0d07 100644 --- a/arch/x86/cpu/coreboot/coreboot.c +++ b/arch/x86/cpu/coreboot/coreboot.c @@ -55,10 +55,10 @@ static void board_final_cleanup(void) if (top_type == MTRR_TYPE_WRPROT) { struct mtrr_state state; - mtrr_open(&state); + mtrr_open(&state, true); wrmsrl(MTRR_PHYS_BASE_MSR(top_mtrr), 0); wrmsrl(MTRR_PHYS_MASK_MSR(top_mtrr), 0); - mtrr_close(&state); + mtrr_close(&state, true); } if (!fdtdec_get_config_bool(gd->fdt_blob, "u-boot,no-apm-finalize")) { diff --git a/arch/x86/cpu/mtrr.c b/arch/x86/cpu/mtrr.c index 3094006..0939736 100644 --- a/arch/x86/cpu/mtrr.c +++ b/arch/x86/cpu/mtrr.c @@ -11,6 +11,11 @@ * System Programming */ +/* + * Note that any console output (e.g. debug()) in this file will likely fail + * since the MTRR registers are sometimes in flux. + */ + #include #include #include @@ -19,27 +24,29 @@ DECLARE_GLOBAL_DATA_PTR; /* Prepare to adjust MTRRs */ -void mtrr_open(struct mtrr_state *state) +void mtrr_open(struct mtrr_state *state, bool do_caches) { if (!gd->arch.has_mtrr) return; - state->enable_cache = dcache_status(); + if (do_caches) { + state->enable_cache = dcache_status(); - if (state->enable_cache) - disable_caches(); + if (state->enable_cache) + disable_caches(); + } state->deftype = native_read_msr(MTRR_DEF_TYPE_MSR); wrmsrl(MTRR_DEF_TYPE_MSR, state->deftype & ~MTRR_DEF_TYPE_EN); } /* Clean up after adjusting MTRRs, and enable them */ -void mtrr_close(struct mtrr_state *state) +void mtrr_close(struct mtrr_state *state, bool do_caches) { if (!gd->arch.has_mtrr) return; wrmsrl(MTRR_DEF_TYPE_MSR, state->deftype | MTRR_DEF_TYPE_EN); - if (state->enable_cache) + if (do_caches && state->enable_cache) enable_caches(); } @@ -50,10 +57,14 @@ int mtrr_commit(bool do_caches) uint64_t mask; int i; + debug("%s: enabled=%d, count=%d\n", __func__, gd->arch.has_mtrr, + gd->arch.mtrr_req_count); if (!gd->arch.has_mtrr) return -ENOSYS; - mtrr_open(&state); + debug("open\n"); + mtrr_open(&state, do_caches); + debug("open done\n"); for (i = 0; i < gd->arch.mtrr_req_count; i++, req++) { mask = ~(req->size - 1); mask &= (1ULL << CONFIG_CPU_ADDR_BITS) - 1; @@ -62,9 +73,12 @@ int mtrr_commit(bool do_caches) } /* Clear the ones that are unused */ + debug("clear\n"); for (; i < MTRR_COUNT; i++) wrmsrl(MTRR_PHYS_MASK_MSR(i), 0); - mtrr_close(&state); + debug("close\n"); + mtrr_close(&state, do_caches); + debug("mtrr done\n"); return 0; } @@ -74,6 +88,7 @@ int mtrr_add_request(int type, uint64_t start, uint64_t size) struct mtrr_request *req; uint64_t mask; + debug("%s: count=%d\n", __func__, gd->arch.mtrr_req_count); if (!gd->arch.has_mtrr) return -ENOSYS; diff --git a/arch/x86/include/asm/mtrr.h b/arch/x86/include/asm/mtrr.h index 05cd7b7..2d897f8 100644 --- a/arch/x86/include/asm/mtrr.h +++ b/arch/x86/include/asm/mtrr.h @@ -77,8 +77,9 @@ struct mtrr_state { * possibly the cache. * * @state: Empty structure to pass in to hold settings + * @do_caches: true to disable caches before opening */ -void mtrr_open(struct mtrr_state *state); +void mtrr_open(struct mtrr_state *state, bool do_caches); /** * mtrr_open() - Clean up after adjusting MTRRs, and enable them @@ -86,8 +87,9 @@ void mtrr_open(struct mtrr_state *state); * This uses the structure containing information returned from mtrr_open(). * * @state: Structure from mtrr_open() + * @state: true to restore cache state to that before mtrr_open() */ -void mtrr_close(struct mtrr_state *state); +void mtrr_close(struct mtrr_state *state, bool do_caches); /** * mtrr_add_request() - Add a new MTRR request diff --git a/board/atmel/common/video_display.c b/board/atmel/common/video_display.c index 7dd7b85..c7d3f8a 100644 --- a/board/atmel/common/video_display.c +++ b/board/atmel/common/video_display.c @@ -18,6 +18,7 @@ DECLARE_GLOBAL_DATA_PTR; int at91_video_show_board_info(void) { + struct vidconsole_priv *priv; ulong dram_size, nand_size; int i; u32 len = 0; @@ -63,7 +64,9 @@ int at91_video_show_board_info(void) if (ret) return ret; - vidconsole_position_cursor(con, 0, logo_info.logo_height); + priv = dev_get_uclass_priv(con); + vidconsole_position_cursor(con, 0, (logo_info.logo_height + + priv->y_charsize - 1) / priv->y_charsize); for (s = buf, i = 0; i < len; s++, i++) vidconsole_put_char(con, *s); diff --git a/cmd/cros_ec.c b/cmd/cros_ec.c index 60c8783..9e2f1b0 100644 --- a/cmd/cros_ec.c +++ b/cmd/cros_ec.c @@ -27,7 +27,7 @@ static int cros_ec_decode_region(int argc, char * const argv[]) { if (argc > 0) { if (0 == strcmp(*argv, "rw")) - return EC_FLASH_REGION_RW; + return EC_FLASH_REGION_ACTIVE; else if (0 == strcmp(*argv, "ro")) return EC_FLASH_REGION_RO; @@ -49,7 +49,7 @@ static int cros_ec_decode_region(int argc, char * const argv[]) * @return 0 for ok, 1 for a usage error or -ve for ec command error * (negative EC_RES_...) */ -static int do_read_write(struct cros_ec_dev *dev, int is_write, int argc, +static int do_read_write(struct udevice *dev, int is_write, int argc, char * const argv[]) { uint32_t offset, size = -1U, region_size; @@ -94,8 +94,7 @@ static int do_read_write(struct cros_ec_dev *dev, int is_write, int argc, static int do_cros_ec(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { - struct cros_ec_dev *dev; - struct udevice *udev; + struct udevice *dev; const char *cmd; int ret = 0; @@ -105,10 +104,10 @@ static int do_cros_ec(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) cmd = argv[1]; if (0 == strcmp("init", cmd)) { /* Remove any existing device */ - ret = uclass_find_device(UCLASS_CROS_EC, 0, &udev); + ret = uclass_find_device(UCLASS_CROS_EC, 0, &dev); if (!ret) - device_remove(udev, DM_REMOVE_NORMAL); - ret = uclass_get_device(UCLASS_CROS_EC, 0, &udev); + device_remove(dev, DM_REMOVE_NORMAL); + ret = uclass_get_device(UCLASS_CROS_EC, 0, &dev); if (ret) { printf("Could not init cros_ec device (err %d)\n", ret); return 1; @@ -116,12 +115,11 @@ static int do_cros_ec(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) return 0; } - ret = uclass_get_device(UCLASS_CROS_EC, 0, &udev); + ret = uclass_get_device(UCLASS_CROS_EC, 0, &dev); if (ret) { printf("Cannot get cros-ec device (err=%d)\n", ret); return 1; } - dev = dev_get_uclass_priv(udev); if (0 == strcmp("id", cmd)) { char id[MSG_BYTES]; @@ -139,7 +137,6 @@ static int do_cros_ec(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) } printf("rows = %u\n", info.rows); printf("cols = %u\n", info.cols); - printf("switches = %#x\n", info.switches); } else if (0 == strcmp("curimage", cmd)) { enum ec_current_image image; @@ -152,7 +149,7 @@ static int do_cros_ec(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) struct ec_response_vboot_hash hash; int i; - if (cros_ec_read_hash(dev, &hash)) { + if (cros_ec_read_hash(dev, EC_VBOOT_HASH_OFFSET_ACTIVE, &hash)) { debug("%s: Could not read KBC hash\n", __func__); return 1; } @@ -179,7 +176,7 @@ static int do_cros_ec(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) region = cros_ec_decode_region(argc - 2, argv + 2); if (region == EC_FLASH_REGION_RO) cmd = EC_REBOOT_JUMP_RO; - else if (region == EC_FLASH_REGION_RW) + else if (region == EC_FLASH_REGION_ACTIVE) cmd = EC_REBOOT_JUMP_RW; else return CMD_RET_USAGE; @@ -262,7 +259,8 @@ static int do_cros_ec(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) unsigned long result; if (argc <= 2) { - ret = cros_ec_read_vbnvcontext(dev, block); + ret = cros_ec_read_nvdata(dev, block, + EC_VBNV_BLOCK_SIZE); if (!ret) { printf("vbnv_block: "); for (i = 0; i < EC_VBNV_BLOCK_SIZE; i++) @@ -288,7 +286,8 @@ static int do_cros_ec(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) strict_strtoul(buf, 16, &result); block[i] = result; } - ret = cros_ec_write_vbnvcontext(dev, block); + ret = cros_ec_write_nvdata(dev, block, + EC_VBNV_BLOCK_SIZE); } if (ret) { debug("%s: Could not %s VbNvContext\n", __func__, @@ -336,9 +335,9 @@ static int do_cros_ec(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) state = simple_strtoul(argv[3], &endp, 10); if (*argv[3] == 0 || *endp != 0) return CMD_RET_USAGE; - ret = cros_ec_set_ldo(udev, index, state); + ret = cros_ec_set_ldo(dev, index, state); } else { - ret = cros_ec_get_ldo(udev, index, &state); + ret = cros_ec_get_ldo(dev, index, &state); if (!ret) { printf("LDO%d: %s\n", index, state == EC_LDO_STATE_ON ? diff --git a/cmd/tpm_test.c b/cmd/tpm_test.c index 35f3c96..f21ad5d 100644 --- a/cmd/tpm_test.c +++ b/cmd/tpm_test.c @@ -62,14 +62,6 @@ static uint32_t tpm_get_flags(uint8_t *disable, uint8_t *deactivated, return 0; } -static uint32_t tpm_set_global_lock(void) -{ - uint32_t x; - - debug("TPM: Set global lock\n"); - return tpm_nv_write_value(INDEX0, (uint8_t *)&x, 0); -} - static uint32_t tpm_nv_write_value_lock(uint32_t index) { debug("TPM: Write lock 0x%x\n", index); @@ -77,13 +69,6 @@ static uint32_t tpm_nv_write_value_lock(uint32_t index) return tpm_nv_write_value(index, NULL, 0); } -static uint32_t tpm_nv_set_locked(void) -{ - debug("TPM: Set NV locked\n"); - - return tpm_nv_define_space(TPM_NV_INDEX_LOCK, 0, 0); -} - static int tpm_is_owned(void) { uint8_t response[TPM_PUBEK_SIZE]; diff --git a/cmd/x86/mtrr.c b/cmd/x86/mtrr.c index 70f373a..d3fd959 100644 --- a/cmd/x86/mtrr.c +++ b/cmd/x86/mtrr.c @@ -73,10 +73,10 @@ static int do_mtrr_set(uint reg, int argc, char * const argv[]) mask |= MTRR_PHYS_MASK_VALID; printf("base=%llx, mask=%llx\n", base, mask); - mtrr_open(&state); + mtrr_open(&state, true); wrmsrl(MTRR_PHYS_BASE_MSR(reg), base); wrmsrl(MTRR_PHYS_MASK_MSR(reg), mask); - mtrr_close(&state); + mtrr_close(&state, true); return 0; } @@ -86,14 +86,14 @@ static int mtrr_set_valid(int reg, bool valid) struct mtrr_state state; uint64_t mask; - mtrr_open(&state); + mtrr_open(&state, true); mask = native_read_msr(MTRR_PHYS_MASK_MSR(reg)); if (valid) mask |= MTRR_PHYS_MASK_VALID; else mask &= ~MTRR_PHYS_MASK_VALID; wrmsrl(MTRR_PHYS_MASK_MSR(reg), mask); - mtrr_close(&state); + mtrr_close(&state, true); return 0; } diff --git a/common/cros_ec.c b/common/cros_ec.c index 1a0caf8..4ca15e1 100644 --- a/common/cros_ec.c +++ b/common/cros_ec.c @@ -13,7 +13,7 @@ #include #include -struct cros_ec_dev *board_get_cros_ec_dev(void) +struct udevice *board_get_cros_ec_dev(void) { struct udevice *dev; int ret; @@ -23,7 +23,7 @@ struct cros_ec_dev *board_get_cros_ec_dev(void) debug("%s: Error %d\n", __func__, ret); return NULL; } - return dev_get_uclass_priv(dev); + return dev; } int cros_ec_get_error(void) diff --git a/common/log.c b/common/log.c index 59869cd..ec14644 100644 --- a/common/log.c +++ b/common/log.c @@ -315,7 +315,8 @@ int log_init(void) drv++; } gd->flags |= GD_FLG_LOG_READY; - gd->default_log_level = LOGL_INFO; + if (!gd->default_log_level) + gd->default_log_level = LOGL_INFO; gd->log_fmt = LOGF_DEFAULT; return 0; diff --git a/configs/chromebook_link64_defconfig b/configs/chromebook_link64_defconfig index fe6544b..2c51a2f 100644 --- a/configs/chromebook_link64_defconfig +++ b/configs/chromebook_link64_defconfig @@ -69,6 +69,7 @@ CONFIG_DM_I2C=y CONFIG_SYS_I2C_INTEL=y CONFIG_CROS_EC=y CONFIG_CROS_EC_LPC=y +CONFIG_SPL_DM_RTC=y CONFIG_SYS_NS16550=y CONFIG_SPI=y CONFIG_SPL_TIMER=y diff --git a/configs/edison_defconfig b/configs/edison_defconfig index f0f3449..eb9f9a0 100644 --- a/configs/edison_defconfig +++ b/configs/edison_defconfig @@ -33,6 +33,7 @@ CONFIG_CPU=y CONFIG_DFU_MMC=y CONFIG_DFU_RAM=y CONFIG_DM_PCI_COMPAT=y +CONFIG_RTC_MC146818=y CONFIG_USB_DWC3_GADGET=y CONFIG_USB_GADGET=y CONFIG_USB_GADGET_MANUFACTURER="Intel" diff --git a/configs/malta64_defconfig b/configs/malta64_defconfig index c509581..9950326 100644 --- a/configs/malta64_defconfig +++ b/configs/malta64_defconfig @@ -23,4 +23,5 @@ CONFIG_DEFAULT_DEVICE_TREE="mti,malta" CONFIG_ENV_IS_IN_FLASH=y CONFIG_MTD_NOR_FLASH=y CONFIG_PCI=y +CONFIG_RTC_MC146818=y CONFIG_SYS_NS16550=y diff --git a/configs/malta64el_defconfig b/configs/malta64el_defconfig index 992c855..63989ce 100644 --- a/configs/malta64el_defconfig +++ b/configs/malta64el_defconfig @@ -24,4 +24,5 @@ CONFIG_DEFAULT_DEVICE_TREE="mti,malta" CONFIG_ENV_IS_IN_FLASH=y CONFIG_MTD_NOR_FLASH=y CONFIG_PCI=y +CONFIG_RTC_MC146818=y CONFIG_SYS_NS16550=y diff --git a/configs/malta_defconfig b/configs/malta_defconfig index 5854405..8265dae 100644 --- a/configs/malta_defconfig +++ b/configs/malta_defconfig @@ -22,4 +22,5 @@ CONFIG_DEFAULT_DEVICE_TREE="mti,malta" CONFIG_ENV_IS_IN_FLASH=y CONFIG_MTD_NOR_FLASH=y CONFIG_PCI=y +CONFIG_RTC_MC146818=y CONFIG_SYS_NS16550=y diff --git a/configs/maltael_defconfig b/configs/maltael_defconfig index 9cba722..c9c4c8f 100644 --- a/configs/maltael_defconfig +++ b/configs/maltael_defconfig @@ -23,4 +23,5 @@ CONFIG_DEFAULT_DEVICE_TREE="mti,malta" CONFIG_ENV_IS_IN_FLASH=y CONFIG_MTD_NOR_FLASH=y CONFIG_PCI=y +CONFIG_RTC_MC146818=y CONFIG_SYS_NS16550=y diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig index 1c4a333..2ce336f 100644 --- a/configs/sandbox_defconfig +++ b/configs/sandbox_defconfig @@ -1,5 +1,6 @@ CONFIG_SYS_TEXT_BASE=0 CONFIG_SYS_MALLOC_F_LEN=0x2000 +CONFIG_DEBUG_UART=y CONFIG_DISTRO_DEFAULTS=y CONFIG_NR_DRAM_BANKS=1 CONFIG_ANDROID_BOOT_IMAGE=y @@ -173,6 +174,7 @@ CONFIG_REMOTEPROC_SANDBOX=y CONFIG_DM_RESET=y CONFIG_SANDBOX_RESET=y CONFIG_DM_RTC=y +CONFIG_DEBUG_UART_SANDBOX=y CONFIG_SANDBOX_SERIAL=y CONFIG_SMEM=y CONFIG_SANDBOX_SMEM=y diff --git a/configs/sandbox_flattree_defconfig b/configs/sandbox_flattree_defconfig index 9f672e5..2f8a98c 100644 --- a/configs/sandbox_flattree_defconfig +++ b/configs/sandbox_flattree_defconfig @@ -15,6 +15,7 @@ CONFIG_BOOTSTAGE_STASH_SIZE=0x4096 CONFIG_CONSOLE_RECORD=y CONFIG_CONSOLE_RECORD_OUT_SIZE=0x1000 CONFIG_SILENT_CONSOLE=y +CONFIG_LOG_MAX_LEVEL=6 CONFIG_DISPLAY_BOARDINFO_LATE=y CONFIG_CMD_CPU=y CONFIG_CMD_LICENSE=y diff --git a/disk/part_efi.c b/disk/part_efi.c index 519a637..d6bb53e 100644 --- a/disk/part_efi.c +++ b/disk/part_efi.c @@ -82,11 +82,11 @@ static int validate_gpt_header(gpt_header *gpt_h, lbaint_t lba, uint32_t calc_crc32; /* Check the GPT header signature */ - if (le64_to_cpu(gpt_h->signature) != GPT_HEADER_SIGNATURE) { + if (le64_to_cpu(gpt_h->signature) != GPT_HEADER_SIGNATURE_UBOOT) { printf("%s signature is wrong: 0x%llX != 0x%llX\n", "GUID Partition Table Header", le64_to_cpu(gpt_h->signature), - GPT_HEADER_SIGNATURE); + GPT_HEADER_SIGNATURE_UBOOT); return -1; } @@ -603,7 +603,7 @@ static uint32_t partition_entries_offset(struct blk_desc *dev_desc) int gpt_fill_header(struct blk_desc *dev_desc, gpt_header *gpt_h, char *str_guid, int parts_count) { - gpt_h->signature = cpu_to_le64(GPT_HEADER_SIGNATURE); + gpt_h->signature = cpu_to_le64(GPT_HEADER_SIGNATURE_UBOOT); gpt_h->revision = cpu_to_le32(GPT_HEADER_REVISION_V1); gpt_h->header_size = cpu_to_le32(sizeof(gpt_header)); gpt_h->my_lba = cpu_to_le64(1); diff --git a/doc/README.fdt-control b/doc/README.fdt-control index 634a106..d6ab7bf 100644 --- a/doc/README.fdt-control +++ b/doc/README.fdt-control @@ -56,7 +56,11 @@ In case you are wondering, OF stands for Open Firmware. Tools ----- -To use this feature you will need to get the device tree compiler here: +To use this feature you will need to get the device tree compiler. This is +provided by U-Boot automatically. If you have a system version of dtc +(typically in the 'device-tree-compiler' package), it is currently not used. + +If you want to build your own dtc, it is kept here: git://git.kernel.org/pub/scm/utils/dtc/dtc.git @@ -170,6 +174,16 @@ After board configuration is done, fdt supported u-boot can be build in two ways $ make DEVICE_TREE= +Relocation, SPL and TPL +----------------------- + +U-Boot can be divided into three phases: TPL, SPL and U-Boot proper. + +The full device tree is available to U-Boot proper, but normally only a subset +(or none at all) is available to TPL and SPL. See 'Pre-Relocation Support' and +'SPL Support' in doc/driver-model/README.txt for more details. + + Limitations ----------- diff --git a/doc/driver-model/README.txt b/doc/driver-model/README.txt index e949ff6..3654163 100644 --- a/doc/driver-model/README.txt +++ b/doc/driver-model/README.txt @@ -832,11 +832,14 @@ Pre-Relocation Support For pre-relocation we simply call the driver model init function. Only drivers marked with DM_FLAG_PRE_RELOC or the device tree 'u-boot,dm-pre-reloc' flag are initialised prior to relocation. This helps -to reduce the driver model overhead. +to reduce the driver model overhead. This flag applies to SPL and TPL as +well, if device tree is enabled there. It is possible to limit this to specific relocation steps, by using the more specialized 'u-boot,dm-spl' and 'u-boot,dm-tpl' flags -in the devicetree. +in the device tree node. For U-Boot proper you can use 'u-boot,dm-pre-proper' +which means that it will be processed (and a driver bound) in U-Boot proper +prior to relocation, but will not be available in SPL or TPL. Then post relocation we throw that away and re-init driver model again. For drivers which require some sort of continuity between pre- and diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig index f9502b3..33f4aa2 100644 --- a/drivers/block/Kconfig +++ b/drivers/block/Kconfig @@ -27,6 +27,18 @@ config SPL_BLK be partitioned into several areas, called 'partitions' in U-Boot. A filesystem can be placed in each partition. +config TPL_BLK + bool "Support block devices in TPL" + depends on TPL_DM && BLK + default y + help + Enable support for block devices, such as SCSI, MMC and USB + flash sticks. These provide a block-level interface which permits + reading, writing and (in some cases) erasing blocks. Block + devices often have a partition table which allows the device to + be partitioned into several areas, called 'partitions' in U-Boot. + A filesystem can be placed in each partition. + config BLOCK_CACHE bool "Use block device cache" depends on BLK diff --git a/drivers/block/Makefile b/drivers/block/Makefile index 0e80ce9..055d42f 100644 --- a/drivers/block/Makefile +++ b/drivers/block/Makefile @@ -11,4 +11,4 @@ endif obj-$(CONFIG_IDE) += ide.o obj-$(CONFIG_SANDBOX) += sandbox.o -obj-$(CONFIG_$(SPL_)BLOCK_CACHE) += blkcache.o +obj-$(CONFIG_$(SPL_TPL_)BLOCK_CACHE) += blkcache.o diff --git a/drivers/core/device.c b/drivers/core/device.c index feed43c..5176aa3 100644 --- a/drivers/core/device.c +++ b/drivers/core/device.c @@ -331,7 +331,8 @@ int device_probe(struct udevice *dev) /* Allocate private data if requested and not reentered */ size = dev->uclass->uc_drv->per_device_auto_alloc_size; if (size && !dev->uclass_priv) { - dev->uclass_priv = calloc(1, size); + dev->uclass_priv = alloc_priv(size, + dev->uclass->uc_drv->flags); if (!dev->uclass_priv) { ret = -ENOMEM; goto fail; @@ -441,7 +442,7 @@ fail: return ret; } -void *dev_get_platdata(struct udevice *dev) +void *dev_get_platdata(const struct udevice *dev) { if (!dev) { dm_warn("%s: null device\n", __func__); @@ -451,7 +452,7 @@ void *dev_get_platdata(struct udevice *dev) return dev->platdata; } -void *dev_get_parent_platdata(struct udevice *dev) +void *dev_get_parent_platdata(const struct udevice *dev) { if (!dev) { dm_warn("%s: null device\n", __func__); @@ -461,7 +462,7 @@ void *dev_get_parent_platdata(struct udevice *dev) return dev->parent_platdata; } -void *dev_get_uclass_platdata(struct udevice *dev) +void *dev_get_uclass_platdata(const struct udevice *dev) { if (!dev) { dm_warn("%s: null device\n", __func__); @@ -471,7 +472,7 @@ void *dev_get_uclass_platdata(struct udevice *dev) return dev->uclass_platdata; } -void *dev_get_priv(struct udevice *dev) +void *dev_get_priv(const struct udevice *dev) { if (!dev) { dm_warn("%s: null device\n", __func__); @@ -481,7 +482,7 @@ void *dev_get_priv(struct udevice *dev) return dev->priv; } -void *dev_get_uclass_priv(struct udevice *dev) +void *dev_get_uclass_priv(const struct udevice *dev) { if (!dev) { dm_warn("%s: null device\n", __func__); @@ -491,7 +492,7 @@ void *dev_get_uclass_priv(struct udevice *dev) return dev->uclass_priv; } -void *dev_get_parent_priv(struct udevice *dev) +void *dev_get_parent_priv(const struct udevice *dev) { if (!dev) { dm_warn("%s: null device\n", __func__); @@ -680,17 +681,35 @@ int device_find_next_child(struct udevice **devp) return 0; } -struct udevice *dev_get_parent(struct udevice *child) +int device_find_first_inactive_child(struct udevice *parent, + enum uclass_id uclass_id, + struct udevice **devp) +{ + struct udevice *dev; + + *devp = NULL; + list_for_each_entry(dev, &parent->child_head, sibling_node) { + if (!device_active(dev) && + device_get_uclass_id(dev) == uclass_id) { + *devp = dev; + return 0; + } + } + + return -ENODEV; +} + +struct udevice *dev_get_parent(const struct udevice *child) { return child->parent; } -ulong dev_get_driver_data(struct udevice *dev) +ulong dev_get_driver_data(const struct udevice *dev) { return dev->driver_data; } -const void *dev_get_driver_ops(struct udevice *dev) +const void *dev_get_driver_ops(const struct udevice *dev) { if (!dev || !dev->driver->ops) return NULL; @@ -698,12 +717,12 @@ const void *dev_get_driver_ops(struct udevice *dev) return dev->driver->ops; } -enum uclass_id device_get_uclass_id(struct udevice *dev) +enum uclass_id device_get_uclass_id(const struct udevice *dev) { return dev->uclass->uc_drv->id; } -const char *dev_get_uclass_name(struct udevice *dev) +const char *dev_get_uclass_name(const struct udevice *dev) { if (!dev) return NULL; @@ -711,7 +730,7 @@ const char *dev_get_uclass_name(struct udevice *dev) return dev->uclass->uc_drv->name; } -bool device_has_children(struct udevice *dev) +bool device_has_children(const struct udevice *dev) { return !list_empty(&dev->child_head); } diff --git a/drivers/core/of_extra.c b/drivers/core/of_extra.c index aa48917..f1f393c 100644 --- a/drivers/core/of_extra.c +++ b/drivers/core/of_extra.c @@ -13,19 +13,30 @@ int ofnode_read_fmap_entry(ofnode node, struct fmap_entry *entry) { const char *prop; - u32 reg[2]; - if (ofnode_read_u32_array(node, "reg", reg, 2)) { - debug("Node '%s' has bad/missing 'reg' property\n", + if (ofnode_read_u32(node, "image-pos", &entry->offset)) { + debug("Node '%s' has bad/missing 'image-pos' property\n", ofnode_get_name(node)); - return -log_ret(ENOENT); + return log_ret(-ENOENT); + } + if (ofnode_read_u32(node, "size", &entry->length)) { + debug("Node '%s' has bad/missing 'size' property\n", + ofnode_get_name(node)); + return log_ret(-ENOENT); } - entry->offset = reg[0]; - entry->length = reg[1]; entry->used = ofnode_read_s32_default(node, "used", entry->length); prop = ofnode_read_string(node, "compress"); - entry->compress_algo = prop && !strcmp(prop, "lzo") ? - FMAP_COMPRESS_LZO : FMAP_COMPRESS_NONE; + if (prop) { + if (!strcmp(prop, "lz4")) + entry->compress_algo = FMAP_COMPRESS_LZ4; + else + return log_msg_ret("Unknown compression algo", + -EINVAL); + } else { + entry->compress_algo = FMAP_COMPRESS_NONE; + } + entry->unc_length = ofnode_read_s32_default(node, "uncomp-size", + entry->length); prop = ofnode_read_string(node, "hash"); if (prop) entry->hash_size = strlen(prop); diff --git a/drivers/core/ofnode.c b/drivers/core/ofnode.c index 1e35480..b7b7ad3 100644 --- a/drivers/core/ofnode.c +++ b/drivers/core/ofnode.c @@ -541,9 +541,13 @@ fdt_addr_t ofnode_get_addr_size(ofnode node, const char *property, if (!prop) return FDT_ADDR_T_NONE; na = of_n_addr_cells(np); - ns = of_n_addr_cells(np); + ns = of_n_size_cells(np); *sizep = of_read_number(prop + na, ns); - return of_read_number(prop, na); + + if (IS_ENABLED(CONFIG_OF_TRANSLATE) && ns > 0) + return of_translate_address(np, prop); + else + return of_read_number(prop, na); } else { return fdtdec_get_addr_size(gd->fdt_blob, ofnode_to_offset(node), property, @@ -695,6 +699,8 @@ bool ofnode_pre_reloc(ofnode node) { if (ofnode_read_bool(node, "u-boot,dm-pre-reloc")) return true; + if (ofnode_read_bool(node, "u-boot,dm-pre-proper")) + return true; #ifdef CONFIG_TPL_BUILD if (ofnode_read_bool(node, "u-boot,dm-tpl")) diff --git a/drivers/input/Kconfig b/drivers/input/Kconfig index 7ffb949..7afdafe 100644 --- a/drivers/input/Kconfig +++ b/drivers/input/Kconfig @@ -1,3 +1,16 @@ +config INPUT + bool "Enable input subsystem" + depends on DM + default y + +config SPL_INPUT + bool "Enable input subsystem for SPL" + depends on SPL_DM + +config TPL_INPUT + bool "Enable input subsystem for TPL" + depends on TPL_DM + config DM_KEYBOARD bool "Enable driver model keyboard support" depends on DM @@ -7,8 +20,43 @@ config DM_KEYBOARD includes methods to start/stop the device, check for available input and update LEDs if the keyboard has them. +config SPL_DM_KEYBOARD + bool "Enable driver model keyboard support" + depends on SPL_DM + help + This adds a uclass for keyboards and implements keyboard support + using driver model. The API is implemented by keyboard.h and + includes methods to start/stop the device, check for available + input and update LEDs if the keyboard has them. + +config TPL_DM_KEYBOARD + bool "Enable driver model keyboard support" + depends on TPL_DM + help + This adds a uclass for keyboards and implements keyboard support + using driver model. The API is implemented by keyboard.h and + includes methods to start/stop the device, check for available + input and update LEDs if the keyboard has them. + config CROS_EC_KEYB bool "Enable Chrome OS EC keyboard support" + depends on INPUT + help + Most ARM Chromebooks use an EC to provide access to the keyboard. + Messages are used to request key scans from the EC and these are + then decoded into keys by this driver. + +config SPL_CROS_EC_KEYB + bool "Enable Chrome OS EC keyboard support in SPL" + depends on SPL_INPUT + help + Most ARM Chromebooks use an EC to provide access to the keyboard. + Messages are used to request key scans from the EC and these are + then decoded into keys by this driver. + +config TPL_CROS_EC_KEYB + bool "Enable Chrome OS EC keyboard support in TPL" + depends on TPL_INPUT help Most ARM Chromebooks use an EC to provide access to the keyboard. Messages are used to request key scans from the EC and these are diff --git a/drivers/input/Makefile b/drivers/input/Makefile index d13baf3..fd56d7b 100644 --- a/drivers/input/Makefile +++ b/drivers/input/Makefile @@ -3,12 +3,15 @@ # (C) Copyright 2000-2007 # Wolfgang Denk, DENX Software Engineering, wd@denx.de. -obj-$(CONFIG_DM_KEYBOARD) += keyboard-uclass.o +obj-y += input.o +obj-$(CONFIG_$(SPL_TPL_)CROS_EC_KEYB) += cros_ec_keyb.o +obj-$(CONFIG_$(SPL_TPL_)OF_CONTROL) += key_matrix.o +obj-$(CONFIG_$(SPL_TPL_)DM_KEYBOARD) += keyboard-uclass.o + +ifndef CONFIG_SPL_BUILD obj-$(CONFIG_I8042_KEYB) += i8042.o obj-$(CONFIG_TEGRA_KEYBOARD) += tegra-kbc.o obj-$(CONFIG_TWL4030_INPUT) += twl4030.o obj-$(CONFIG_TWL6030_INPUT) += twl6030.o -obj-$(CONFIG_CROS_EC_KEYB) += cros_ec_keyb.o -obj-y += input.o -obj-$(CONFIG_$(SPL_)OF_CONTROL) += key_matrix.o +endif diff --git a/drivers/input/input.c b/drivers/input/input.c index 29620a9..4f514db 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -652,7 +652,7 @@ int input_stdio_register(struct stdio_dev *dev) int error; error = stdio_register(dev); - +#if !defined(CONFIG_SPL_BUILD) || CONFIG_IS_ENABLED(ENV_SUPPORT) /* check if this is the standard input device */ if (!error && strcmp(env_get("stdin"), dev->name) == 0) { /* reassign the console */ @@ -660,6 +660,9 @@ int input_stdio_register(struct stdio_dev *dev) console_assign(stdin, dev->name)) return -1; } +#else + error = error; +#endif return 0; } diff --git a/drivers/misc/cros_ec.c b/drivers/misc/cros_ec.c index 6f299d4..190505c 100644 --- a/drivers/misc/cros_ec.c +++ b/drivers/misc/cros_ec.c @@ -83,15 +83,15 @@ int cros_ec_calc_checksum(const uint8_t *data, int size) * @param dout_len Size of output data in bytes * @return packet size in bytes, or <0 if error. */ -static int create_proto3_request(struct cros_ec_dev *dev, +static int create_proto3_request(struct cros_ec_dev *cdev, int cmd, int cmd_version, const void *dout, int dout_len) { - struct ec_host_request *rq = (struct ec_host_request *)dev->dout; + struct ec_host_request *rq = (struct ec_host_request *)cdev->dout; int out_bytes = dout_len + sizeof(*rq); /* Fail if output size is too big */ - if (out_bytes > (int)sizeof(dev->dout)) { + if (out_bytes > (int)sizeof(cdev->dout)) { debug("%s: Cannot send %d bytes\n", __func__, dout_len); return -EC_RES_REQUEST_TRUNCATED; } @@ -108,9 +108,9 @@ static int create_proto3_request(struct cros_ec_dev *dev, memcpy(rq + 1, dout, dout_len); /* Write checksum field so the entire packet sums to 0 */ - rq->checksum = (uint8_t)(-cros_ec_calc_checksum(dev->dout, out_bytes)); + rq->checksum = (uint8_t)(-cros_ec_calc_checksum(cdev->dout, out_bytes)); - cros_ec_dump_data("out", cmd, dev->dout, out_bytes); + cros_ec_dump_data("out", cmd, cdev->dout, out_bytes); /* Return size of request packet */ return out_bytes; @@ -123,12 +123,12 @@ static int create_proto3_request(struct cros_ec_dev *dev, * @param din_len Maximum size of response in bytes * @return maximum expected number of bytes in response, or <0 if error. */ -static int prepare_proto3_response_buffer(struct cros_ec_dev *dev, int din_len) +static int prepare_proto3_response_buffer(struct cros_ec_dev *cdev, int din_len) { int in_bytes = din_len + sizeof(struct ec_host_response); /* Fail if input size is too big */ - if (in_bytes > (int)sizeof(dev->din)) { + if (in_bytes > (int)sizeof(cdev->din)) { debug("%s: Cannot receive %d bytes\n", __func__, din_len); return -EC_RES_RESPONSE_TOO_BIG; } @@ -197,7 +197,7 @@ static int handle_proto3_response(struct cros_ec_dev *dev, return rs->data_len; } -static int send_command_proto3(struct cros_ec_dev *dev, +static int send_command_proto3(struct cros_ec_dev *cdev, int cmd, int cmd_version, const void *dout, int dout_len, uint8_t **dinp, int din_len) @@ -207,23 +207,24 @@ static int send_command_proto3(struct cros_ec_dev *dev, int rv; /* Create request packet */ - out_bytes = create_proto3_request(dev, cmd, cmd_version, + out_bytes = create_proto3_request(cdev, cmd, cmd_version, dout, dout_len); if (out_bytes < 0) return out_bytes; /* Prepare response buffer */ - in_bytes = prepare_proto3_response_buffer(dev, din_len); + in_bytes = prepare_proto3_response_buffer(cdev, din_len); if (in_bytes < 0) return in_bytes; - ops = dm_cros_ec_get_ops(dev->dev); - rv = ops->packet ? ops->packet(dev->dev, out_bytes, in_bytes) : -ENOSYS; + ops = dm_cros_ec_get_ops(cdev->dev); + rv = ops->packet ? ops->packet(cdev->dev, out_bytes, in_bytes) : + -ENOSYS; if (rv < 0) return rv; /* Process the response */ - return handle_proto3_response(dev, dinp, din_len); + return handle_proto3_response(cdev, dinp, din_len); } static int send_command(struct cros_ec_dev *dev, uint8_t cmd, int cmd_version, @@ -262,15 +263,16 @@ static int send_command(struct cros_ec_dev *dev, uint8_t cmd, int cmd_version, * @param din_len Maximum size of response in bytes * @return number of bytes in response, or -ve on error */ -static int ec_command_inptr(struct cros_ec_dev *dev, uint8_t cmd, - int cmd_version, const void *dout, int dout_len, uint8_t **dinp, - int din_len) +static int ec_command_inptr(struct udevice *dev, uint8_t cmd, + int cmd_version, const void *dout, int dout_len, + uint8_t **dinp, int din_len) { + struct cros_ec_dev *cdev = dev_get_uclass_priv(dev); uint8_t *din = NULL; int len; - len = send_command(dev, cmd, cmd_version, dout, dout_len, - &din, din_len); + len = send_command(cdev, cmd, cmd_version, dout, dout_len, &din, + din_len); /* If the command doesn't complete, wait a while */ if (len == -EC_RES_IN_PROGRESS) { @@ -283,9 +285,9 @@ static int ec_command_inptr(struct cros_ec_dev *dev, uint8_t cmd, int ret; mdelay(50); /* Insert some reasonable delay */ - ret = send_command(dev, EC_CMD_GET_COMMS_STATUS, 0, - NULL, 0, - (uint8_t **)&resp, sizeof(*resp)); + ret = send_command(cdev, EC_CMD_GET_COMMS_STATUS, 0, + NULL, 0, + (uint8_t **)&resp, sizeof(*resp)); if (ret < 0) return ret; @@ -298,8 +300,8 @@ static int ec_command_inptr(struct cros_ec_dev *dev, uint8_t cmd, /* OK it completed, so read the status response */ /* not sure why it was 0 for the last argument */ - len = send_command(dev, EC_CMD_RESEND_RESPONSE, 0, - NULL, 0, &din, din_len); + len = send_command(cdev, EC_CMD_RESEND_RESPONSE, 0, NULL, 0, + &din, din_len); } debug("%s: len=%d, din=%p\n", __func__, len, din); @@ -328,7 +330,7 @@ static int ec_command_inptr(struct cros_ec_dev *dev, uint8_t cmd, * @param din_len Maximum size of response in bytes * @return number of bytes in response, or -ve on error */ -static int ec_command(struct cros_ec_dev *dev, uint8_t cmd, int cmd_version, +static int ec_command(struct udevice *dev, uint8_t cmd, int cmd_version, const void *dout, int dout_len, void *din, int din_len) { @@ -337,7 +339,7 @@ static int ec_command(struct cros_ec_dev *dev, uint8_t cmd, int cmd_version, assert((din_len == 0) || din); len = ec_command_inptr(dev, cmd, cmd_version, dout, dout_len, - &in_buffer, din_len); + &in_buffer, din_len); if (len > 0) { /* * If we were asked to put it somewhere, do so, otherwise just @@ -353,16 +355,14 @@ static int ec_command(struct cros_ec_dev *dev, uint8_t cmd, int cmd_version, int cros_ec_scan_keyboard(struct udevice *dev, struct mbkp_keyscan *scan) { - struct cros_ec_dev *cdev = dev_get_uclass_priv(dev); - - if (ec_command(cdev, EC_CMD_MKBP_STATE, 0, NULL, 0, scan, + if (ec_command(dev, EC_CMD_MKBP_STATE, 0, NULL, 0, scan, sizeof(scan->data)) != sizeof(scan->data)) return -1; return 0; } -int cros_ec_read_id(struct cros_ec_dev *dev, char *id, int maxlen) +int cros_ec_read_id(struct udevice *dev, char *id, int maxlen) { struct ec_response_get_version *r; @@ -388,8 +388,8 @@ int cros_ec_read_id(struct cros_ec_dev *dev, char *id, int maxlen) return 0; } -int cros_ec_read_version(struct cros_ec_dev *dev, - struct ec_response_get_version **versionp) +int cros_ec_read_version(struct udevice *dev, + struct ec_response_get_version **versionp) { if (ec_command_inptr(dev, EC_CMD_GET_VERSION, 0, NULL, 0, (uint8_t **)versionp, sizeof(**versionp)) @@ -399,7 +399,7 @@ int cros_ec_read_version(struct cros_ec_dev *dev, return 0; } -int cros_ec_read_build_info(struct cros_ec_dev *dev, char **strp) +int cros_ec_read_build_info(struct udevice *dev, char **strp) { if (ec_command_inptr(dev, EC_CMD_GET_BUILD_INFO, 0, NULL, 0, (uint8_t **)strp, EC_PROTO2_MAX_PARAM_SIZE) < 0) @@ -408,8 +408,8 @@ int cros_ec_read_build_info(struct cros_ec_dev *dev, char **strp) return 0; } -int cros_ec_read_current_image(struct cros_ec_dev *dev, - enum ec_current_image *image) +int cros_ec_read_current_image(struct udevice *dev, + enum ec_current_image *image) { struct ec_response_get_version *r; @@ -421,8 +421,8 @@ int cros_ec_read_current_image(struct cros_ec_dev *dev, return 0; } -static int cros_ec_wait_on_hash_done(struct cros_ec_dev *dev, - struct ec_response_vboot_hash *hash) +static int cros_ec_wait_on_hash_done(struct udevice *dev, + struct ec_response_vboot_hash *hash) { struct ec_params_vboot_hash p; ulong start; @@ -444,14 +444,14 @@ static int cros_ec_wait_on_hash_done(struct cros_ec_dev *dev, return 0; } - -int cros_ec_read_hash(struct cros_ec_dev *dev, - struct ec_response_vboot_hash *hash) +int cros_ec_read_hash(struct udevice *dev, uint hash_offset, + struct ec_response_vboot_hash *hash) { struct ec_params_vboot_hash p; int rv; p.cmd = EC_VBOOT_HASH_GET; + p.offset = hash_offset; if (ec_command(dev, EC_CMD_VBOOT_HASH, 0, &p, sizeof(p), hash, sizeof(*hash)) < 0) return -1; @@ -474,7 +474,7 @@ int cros_ec_read_hash(struct cros_ec_dev *dev, p.cmd = EC_VBOOT_HASH_START; p.hash_type = EC_VBOOT_HASH_TYPE_SHA256; p.nonce_size = 0; - p.offset = EC_VBOOT_HASH_OFFSET_RW; + p.offset = hash_offset; if (ec_command(dev, EC_CMD_VBOOT_HASH, 0, &p, sizeof(p), hash, sizeof(*hash)) < 0) @@ -489,7 +489,7 @@ int cros_ec_read_hash(struct cros_ec_dev *dev, return 0; } -static int cros_ec_invalidate_hash(struct cros_ec_dev *dev) +static int cros_ec_invalidate_hash(struct udevice *dev) { struct ec_params_vboot_hash p; struct ec_response_vboot_hash *hash; @@ -514,8 +514,7 @@ static int cros_ec_invalidate_hash(struct cros_ec_dev *dev) return 0; } -int cros_ec_reboot(struct cros_ec_dev *dev, enum ec_reboot_cmd cmd, - uint8_t flags) +int cros_ec_reboot(struct udevice *dev, enum ec_reboot_cmd cmd, uint8_t flags) { struct ec_params_reboot_ec p; @@ -555,7 +554,7 @@ int cros_ec_interrupt_pending(struct udevice *dev) return dm_gpio_get_value(&cdev->ec_int); } -int cros_ec_info(struct cros_ec_dev *dev, struct ec_response_mkbp_info *info) +int cros_ec_info(struct udevice *dev, struct ec_response_mkbp_info *info) { if (ec_command(dev, EC_CMD_MKBP_INFO, 0, NULL, 0, info, sizeof(*info)) != sizeof(*info)) @@ -564,7 +563,7 @@ int cros_ec_info(struct cros_ec_dev *dev, struct ec_response_mkbp_info *info) return 0; } -int cros_ec_get_host_events(struct cros_ec_dev *dev, uint32_t *events_ptr) +int cros_ec_get_host_events(struct udevice *dev, uint32_t *events_ptr) { struct ec_response_host_event_mask *resp; @@ -583,7 +582,7 @@ int cros_ec_get_host_events(struct cros_ec_dev *dev, uint32_t *events_ptr) return 0; } -int cros_ec_clear_host_events(struct cros_ec_dev *dev, uint32_t events) +int cros_ec_clear_host_events(struct udevice *dev, uint32_t events) { struct ec_params_host_event_mask params; @@ -600,9 +599,9 @@ int cros_ec_clear_host_events(struct cros_ec_dev *dev, uint32_t events) return 0; } -int cros_ec_flash_protect(struct cros_ec_dev *dev, - uint32_t set_mask, uint32_t set_flags, - struct ec_response_flash_protect *resp) +int cros_ec_flash_protect(struct udevice *dev, uint32_t set_mask, + uint32_t set_flags, + struct ec_response_flash_protect *resp) { struct ec_params_flash_protect params; @@ -617,17 +616,18 @@ int cros_ec_flash_protect(struct cros_ec_dev *dev, return 0; } -static int cros_ec_check_version(struct cros_ec_dev *dev) +static int cros_ec_check_version(struct udevice *dev) { + struct cros_ec_dev *cdev = dev_get_uclass_priv(dev); struct ec_params_hello req; struct ec_response_hello *resp; struct dm_cros_ec_ops *ops; int ret; - ops = dm_cros_ec_get_ops(dev->dev); + ops = dm_cros_ec_get_ops(dev); if (ops->check_version) { - ret = ops->check_version(dev->dev); + ret = ops->check_version(dev); if (ret) return ret; } @@ -647,7 +647,7 @@ static int cros_ec_check_version(struct cros_ec_dev *dev) */ /* Try sending a version 3 packet */ - dev->protocol_version = 3; + cdev->protocol_version = 3; req.in_data = 0; if (ec_command_inptr(dev, EC_CMD_HELLO, 0, &req, sizeof(req), (uint8_t **)&resp, sizeof(*resp)) > 0) { @@ -655,9 +655,9 @@ static int cros_ec_check_version(struct cros_ec_dev *dev) } /* Try sending a version 2 packet */ - dev->protocol_version = 2; + cdev->protocol_version = 2; if (ec_command_inptr(dev, EC_CMD_HELLO, 0, &req, sizeof(req), - (uint8_t **)&resp, sizeof(*resp)) > 0) { + (uint8_t **)&resp, sizeof(*resp)) > 0) { return 0; } @@ -667,12 +667,12 @@ static int cros_ec_check_version(struct cros_ec_dev *dev) * version is no longer supported, and we don't know about any new * protocol versions. */ - dev->protocol_version = 0; + cdev->protocol_version = 0; printf("%s: ERROR: old EC interface not supported\n", __func__); return -1; } -int cros_ec_test(struct cros_ec_dev *dev) +int cros_ec_test(struct udevice *dev) { struct ec_params_hello req; struct ec_response_hello *resp; @@ -691,7 +691,7 @@ int cros_ec_test(struct cros_ec_dev *dev) return 0; } -int cros_ec_flash_offset(struct cros_ec_dev *dev, enum ec_flash_region region, +int cros_ec_flash_offset(struct udevice *dev, enum ec_flash_region region, uint32_t *offset, uint32_t *size) { struct ec_params_flash_region_info p; @@ -713,7 +713,7 @@ int cros_ec_flash_offset(struct cros_ec_dev *dev, enum ec_flash_region region, return 0; } -int cros_ec_flash_erase(struct cros_ec_dev *dev, uint32_t offset, uint32_t size) +int cros_ec_flash_erase(struct udevice *dev, uint32_t offset, uint32_t size) { struct ec_params_flash_erase p; @@ -741,8 +741,8 @@ int cros_ec_flash_erase(struct cros_ec_dev *dev, uint32_t offset, uint32_t size) * @param size Number of bytes to write * @return 0 if ok, -1 on error */ -static int cros_ec_flash_write_block(struct cros_ec_dev *dev, - const uint8_t *data, uint32_t offset, uint32_t size) +static int cros_ec_flash_write_block(struct udevice *dev, const uint8_t *data, + uint32_t offset, uint32_t size) { struct ec_params_flash_write *p; int ret; @@ -767,7 +767,7 @@ static int cros_ec_flash_write_block(struct cros_ec_dev *dev, /** * Return optimal flash write burst size */ -static int cros_ec_flash_write_burst_size(struct cros_ec_dev *dev) +static int cros_ec_flash_write_burst_size(struct udevice *dev) { return EC_FLASH_WRITE_VER0_SIZE; } @@ -801,8 +801,8 @@ static int cros_ec_data_is_erased(const uint32_t *data, int size) * @param dev Pointer to device * @param info Pointer to output flash info struct */ -int cros_ec_read_flashinfo(struct cros_ec_dev *dev, - struct ec_response_flash_info *info) +int cros_ec_read_flashinfo(struct udevice *dev, + struct ec_response_flash_info *info) { int ret; @@ -814,9 +814,10 @@ int cros_ec_read_flashinfo(struct cros_ec_dev *dev, return ret < sizeof(*info) ? -1 : 0; } -int cros_ec_flash_write(struct cros_ec_dev *dev, const uint8_t *data, - uint32_t offset, uint32_t size) +int cros_ec_flash_write(struct udevice *dev, const uint8_t *data, + uint32_t offset, uint32_t size) { + struct cros_ec_dev *cdev = dev_get_uclass_priv(dev); uint32_t burst = cros_ec_flash_write_burst_size(dev); uint32_t end, off; int ret; @@ -831,8 +832,8 @@ int cros_ec_flash_write(struct cros_ec_dev *dev, const uint8_t *data, /* If the data is empty, there is no point in programming it */ todo = min(end - off, burst); - if (dev->optimise_flash_write && - cros_ec_data_is_erased((uint32_t *)data, todo)) + if (cdev->optimise_flash_write && + cros_ec_data_is_erased((uint32_t *)data, todo)) continue; ret = cros_ec_flash_write_block(dev, data, off, todo); @@ -858,8 +859,8 @@ int cros_ec_flash_write(struct cros_ec_dev *dev, const uint8_t *data, * @param size Number of bytes to read * @return 0 if ok, -1 on error */ -static int cros_ec_flash_read_block(struct cros_ec_dev *dev, uint8_t *data, - uint32_t offset, uint32_t size) +static int cros_ec_flash_read_block(struct udevice *dev, uint8_t *data, + uint32_t offset, uint32_t size) { struct ec_params_flash_read p; @@ -870,8 +871,8 @@ static int cros_ec_flash_read_block(struct cros_ec_dev *dev, uint8_t *data, &p, sizeof(p), data, size) >= 0 ? 0 : -1; } -int cros_ec_flash_read(struct cros_ec_dev *dev, uint8_t *data, uint32_t offset, - uint32_t size) +int cros_ec_flash_read(struct udevice *dev, uint8_t *data, uint32_t offset, + uint32_t size) { uint32_t burst = cros_ec_flash_write_burst_size(dev); uint32_t end, off; @@ -888,13 +889,14 @@ int cros_ec_flash_read(struct cros_ec_dev *dev, uint8_t *data, uint32_t offset, return 0; } -int cros_ec_flash_update_rw(struct cros_ec_dev *dev, - const uint8_t *image, int image_size) +int cros_ec_flash_update_rw(struct udevice *dev, const uint8_t *image, + int image_size) { uint32_t rw_offset, rw_size; int ret; - if (cros_ec_flash_offset(dev, EC_FLASH_REGION_RW, &rw_offset, &rw_size)) + if (cros_ec_flash_offset(dev, EC_FLASH_REGION_ACTIVE, &rw_offset, + &rw_size)) return -1; if (image_size > (int)rw_size) return -1; @@ -927,26 +929,31 @@ int cros_ec_flash_update_rw(struct cros_ec_dev *dev, return 0; } -int cros_ec_read_vbnvcontext(struct cros_ec_dev *dev, uint8_t *block) +int cros_ec_read_nvdata(struct udevice *dev, uint8_t *block, int size) { struct ec_params_vbnvcontext p; int len; + if (size != EC_VBNV_BLOCK_SIZE) + return -EINVAL; + p.op = EC_VBNV_CONTEXT_OP_READ; len = ec_command(dev, EC_CMD_VBNV_CONTEXT, EC_VER_VBNV_CONTEXT, &p, sizeof(p), block, EC_VBNV_BLOCK_SIZE); if (len < EC_VBNV_BLOCK_SIZE) - return -1; + return -EIO; return 0; } -int cros_ec_write_vbnvcontext(struct cros_ec_dev *dev, const uint8_t *block) +int cros_ec_write_nvdata(struct udevice *dev, const uint8_t *block, int size) { struct ec_params_vbnvcontext p; int len; + if (size != EC_VBNV_BLOCK_SIZE) + return -EINVAL; p.op = EC_VBNV_CONTEXT_OP_WRITE; memcpy(p.block, block, sizeof(p.block)); @@ -960,13 +967,12 @@ int cros_ec_write_vbnvcontext(struct cros_ec_dev *dev, const uint8_t *block) int cros_ec_set_ldo(struct udevice *dev, uint8_t index, uint8_t state) { - struct cros_ec_dev *cdev = dev_get_uclass_priv(dev); struct ec_params_ldo_set params; params.index = index; params.state = state; - if (ec_command_inptr(cdev, EC_CMD_LDO_SET, 0, ¶ms, sizeof(params), + if (ec_command_inptr(dev, EC_CMD_LDO_SET, 0, ¶ms, sizeof(params), NULL, 0)) return -1; @@ -975,13 +981,12 @@ int cros_ec_set_ldo(struct udevice *dev, uint8_t index, uint8_t state) int cros_ec_get_ldo(struct udevice *dev, uint8_t index, uint8_t *state) { - struct cros_ec_dev *cdev = dev_get_uclass_priv(dev); struct ec_params_ldo_get params; struct ec_response_ldo_get *resp; params.index = index; - if (ec_command_inptr(cdev, EC_CMD_LDO_GET, 0, ¶ms, sizeof(params), + if (ec_command_inptr(dev, EC_CMD_LDO_GET, 0, ¶ms, sizeof(params), (uint8_t **)&resp, sizeof(*resp)) != sizeof(*resp)) return -1; @@ -1001,12 +1006,12 @@ int cros_ec_register(struct udevice *dev) GPIOD_IS_IN); cdev->optimise_flash_write = dev_read_bool(dev, "optimise-flash-write"); - if (cros_ec_check_version(cdev)) { + if (cros_ec_check_version(dev)) { debug("%s: Could not detect CROS-EC version\n", __func__); return -CROS_EC_ERR_CHECK_VERSION; } - if (cros_ec_read_id(cdev, id, sizeof(id))) { + if (cros_ec_read_id(dev, id, sizeof(id))) { debug("%s: Could not read KBC ID\n", __func__); return -CROS_EC_ERR_READ_ID; } @@ -1042,7 +1047,7 @@ int cros_ec_decode_ec_flash(struct udevice *dev, struct fdt_cros_ec *config) if (0 == strcmp(name, "ro")) { region = EC_FLASH_REGION_RO; } else if (0 == strcmp(name, "rw")) { - region = EC_FLASH_REGION_RW; + region = EC_FLASH_REGION_ACTIVE; } else if (0 == strcmp(name, "wp-ro")) { region = EC_FLASH_REGION_WP_RO; } else { @@ -1062,7 +1067,6 @@ int cros_ec_decode_ec_flash(struct udevice *dev, struct fdt_cros_ec *config) int cros_ec_i2c_tunnel(struct udevice *dev, int port, struct i2c_msg *in, int nmsgs) { - struct cros_ec_dev *cdev = dev_get_uclass_priv(dev); union { struct ec_params_i2c_passthru p; uint8_t outbuf[EC_PROTO2_MAX_PARAM_SIZE]; @@ -1112,7 +1116,7 @@ int cros_ec_i2c_tunnel(struct udevice *dev, int port, struct i2c_msg *in, } } - rv = ec_command(cdev, EC_CMD_I2C_PASSTHRU, 0, p, pdata - (uint8_t *)p, + rv = ec_command(dev, EC_CMD_I2C_PASSTHRU, 0, p, pdata - (uint8_t *)p, r, sizeof(*r) + read_len); if (rv < 0) return rv; diff --git a/drivers/misc/cros_ec_lpc.c b/drivers/misc/cros_ec_lpc.c index be17adc..71d03bf 100644 --- a/drivers/misc/cros_ec_lpc.c +++ b/drivers/misc/cros_ec_lpc.c @@ -40,6 +40,38 @@ static int wait_for_sync(struct cros_ec_dev *dev) return 0; } +int cros_ec_lpc_packet(struct udevice *udev, int out_bytes, int in_bytes) +{ + struct cros_ec_dev *dev = dev_get_uclass_priv(udev); + uint8_t *d; + int i; + + if (out_bytes > EC_LPC_HOST_PACKET_SIZE) + return log_msg_ret("Cannot send that many bytes\n", -E2BIG); + + if (in_bytes > EC_LPC_HOST_PACKET_SIZE) + return log_msg_ret("Cannot receive that many bytes\n", -E2BIG); + + if (wait_for_sync(dev)) + return log_msg_ret("Timeout waiting ready\n", -ETIMEDOUT); + + /* Write data */ + for (i = 0, d = (uint8_t *)dev->dout; i < out_bytes; i++, d++) + outb(*d, EC_LPC_ADDR_HOST_PACKET + i); + + /* Start the command */ + outb(EC_COMMAND_PROTOCOL_3, EC_LPC_ADDR_HOST_CMD); + + if (wait_for_sync(dev)) + return log_msg_ret("Timeout waiting ready\n", -ETIMEDOUT); + + /* Read back args */ + for (i = 0, d = dev->din; i < in_bytes; i++, d++) + *d = inb(EC_LPC_ADDR_HOST_PACKET + i); + + return in_bytes; +} + int cros_ec_lpc_command(struct udevice *udev, uint8_t cmd, int cmd_version, const uint8_t *dout, int dout_len, uint8_t **dinp, int din_len) @@ -200,6 +232,7 @@ static int cros_ec_probe(struct udevice *dev) } static struct dm_cros_ec_ops cros_ec_ops = { + .packet = cros_ec_lpc_packet, .command = cros_ec_lpc_command, .check_version = cros_ec_lpc_check_version, }; diff --git a/drivers/misc/cros_ec_sandbox.c b/drivers/misc/cros_ec_sandbox.c index 47a9d26..d741554 100644 --- a/drivers/misc/cros_ec_sandbox.c +++ b/drivers/misc/cros_ec_sandbox.c @@ -365,7 +365,7 @@ static int process_cmd(struct ec_state *ec, struct fmap_entry *entry; int ret, size; - entry = &ec->ec_config.region[EC_FLASH_REGION_RW]; + entry = &ec->ec_config.region[EC_FLASH_REGION_ACTIVE]; switch (req->cmd) { case EC_VBOOT_HASH_RECALC: @@ -420,7 +420,7 @@ static int process_cmd(struct ec_state *ec, switch (req->region) { case EC_FLASH_REGION_RO: - case EC_FLASH_REGION_RW: + case EC_FLASH_REGION_ACTIVE: case EC_FLASH_REGION_WP_RO: entry = &ec->ec_config.region[req->region]; resp->offset = entry->offset; @@ -491,9 +491,9 @@ int cros_ec_sandbox_packet(struct udevice *udev, int out_bytes, int in_bytes) return in_bytes; } -void cros_ec_check_keyboard(struct cros_ec_dev *dev) +void cros_ec_check_keyboard(struct udevice *dev) { - struct ec_state *ec = dev_get_priv(dev->dev); + struct ec_state *ec = dev_get_priv(dev); ulong start; printf("Press keys for EC to detect on reset (ESC=recovery)..."); diff --git a/drivers/mtd/spi/sandbox.c b/drivers/mtd/spi/sandbox.c index 1b6c028..7fef754 100644 --- a/drivers/mtd/spi/sandbox.c +++ b/drivers/mtd/spi/sandbox.c @@ -8,6 +8,8 @@ * Licensed under the GPL-2 or later. */ +#define LOG_CATEGORY UCLASS_SPI_FLASH + #include #include #include @@ -41,6 +43,7 @@ enum sandbox_sf_state { SF_WRITE_STATUS, /* write the flash's status register */ }; +#if CONFIG_IS_ENABLED(LOG) static const char *sandbox_sf_state_name(enum sandbox_sf_state state) { static const char * const states[] = { @@ -49,6 +52,7 @@ static const char *sandbox_sf_state_name(enum sandbox_sf_state state) }; return states[state]; } +#endif /* LOG */ /* Bits for the status register */ #define STAT_WIP (1 << 0) @@ -101,69 +105,44 @@ struct sandbox_spi_flash_plat_data { /** * This is a very strange probe function. If it has platform data (which may * have come from the device tree) then this function gets the filename and - * device type from there. Failing that it looks at the command line - * parameter. + * device type from there. */ static int sandbox_sf_probe(struct udevice *dev) { /* spec = idcode:file */ struct sandbox_spi_flash *sbsf = dev_get_priv(dev); - const char *file; size_t len, idname_len; const struct spi_flash_info *data; struct sandbox_spi_flash_plat_data *pdata = dev_get_platdata(dev); struct sandbox_state *state = state_get_current(); + struct dm_spi_slave_platdata *slave_plat; struct udevice *bus = dev->parent; const char *spec = NULL; + struct udevice *emul; int ret = 0; int cs = -1; - int i; debug("%s: bus %d, looking for emul=%p: ", __func__, bus->seq, dev); - if (bus->seq >= 0 && bus->seq < CONFIG_SANDBOX_SPI_MAX_BUS) { - for (i = 0; i < CONFIG_SANDBOX_SPI_MAX_CS; i++) { - if (state->spi[bus->seq][i].emul == dev) - cs = i; - } - } - if (cs == -1) { + ret = sandbox_spi_get_emul(state, bus, dev, &emul); + if (ret) { printf("Error: Unknown chip select for device '%s'\n", - dev->name); - return -EINVAL; + dev->name); + return ret; } + slave_plat = dev_get_parent_platdata(dev); + cs = slave_plat->cs; debug("found at cs %d\n", cs); if (!pdata->filename) { - struct sandbox_state *state = state_get_current(); - - assert(bus->seq != -1); - if (bus->seq < CONFIG_SANDBOX_SPI_MAX_BUS) - spec = state->spi[bus->seq][cs].spec; - if (!spec) { - debug("%s: No spec found for bus %d, cs %d\n", - __func__, bus->seq, cs); - ret = -ENOENT; - goto error; - } - - file = strchr(spec, ':'); - if (!file) { - printf("%s: unable to parse file\n", __func__); - ret = -EINVAL; - goto error; - } - idname_len = file - spec; - pdata->filename = file + 1; - pdata->device_name = spec; - ++file; - } else { - spec = strchr(pdata->device_name, ','); - if (spec) - spec++; - else - spec = pdata->device_name; - idname_len = strlen(spec); + printf("Error: No filename available\n"); + return -EINVAL; } + spec = strchr(pdata->device_name, ','); + if (spec) + spec++; + else + spec = pdata->device_name; + idname_len = strlen(spec); debug("%s: device='%s'\n", __func__, spec); for (data = spi_flash_ids; data->name; data++) { @@ -214,7 +193,7 @@ static void sandbox_sf_cs_activate(struct udevice *dev) { struct sandbox_spi_flash *sbsf = dev_get_priv(dev); - debug("sandbox_sf: CS activated; state is fresh!\n"); + log_content("sandbox_sf: CS activated; state is fresh!\n"); /* CS is asserted, so reset state */ sbsf->off = 0; @@ -226,7 +205,7 @@ static void sandbox_sf_cs_activate(struct udevice *dev) static void sandbox_sf_cs_deactivate(struct udevice *dev) { - debug("sandbox_sf: CS deactivated; cmd done processing!\n"); + log_content("sandbox_sf: CS deactivated; cmd done processing!\n"); } /* @@ -302,8 +281,8 @@ static int sandbox_sf_process_cmd(struct sandbox_spi_flash *sbsf, const u8 *rx, } if (oldstate != sbsf->state) - debug(" cmd: transition to %s state\n", - sandbox_sf_state_name(sbsf->state)); + log_content(" cmd: transition to %s state\n", + sandbox_sf_state_name(sbsf->state)); return 0; } @@ -334,8 +313,8 @@ static int sandbox_sf_xfer(struct udevice *dev, unsigned int bitlen, int bytes = bitlen / 8; int ret; - debug("sandbox_sf: state:%x(%s) bytes:%u\n", sbsf->state, - sandbox_sf_state_name(sbsf->state), bytes); + log_content("sandbox_sf: state:%x(%s) bytes:%u\n", sbsf->state, + sandbox_sf_state_name(sbsf->state), bytes); if ((flags & SPI_XFER_BEGIN)) sandbox_sf_cs_activate(dev); @@ -354,7 +333,7 @@ static int sandbox_sf_xfer(struct udevice *dev, unsigned int bitlen, case SF_ID: { u8 id; - debug(" id: off:%u tx:", sbsf->off); + log_content(" id: off:%u tx:", sbsf->off); if (sbsf->off < IDCODE_LEN) { /* Extract correct byte from ID 0x00aabbcc */ id = ((JEDEC_MFR(sbsf->data) << 16) | @@ -363,18 +342,18 @@ static int sandbox_sf_xfer(struct udevice *dev, unsigned int bitlen, } else { id = 0; } - debug("%d %02x\n", sbsf->off, id); + log_content("%d %02x\n", sbsf->off, id); tx[pos++] = id; ++sbsf->off; break; } case SF_ADDR: - debug(" addr: bytes:%u rx:%02x ", sbsf->addr_bytes, - rx[pos]); + log_content(" addr: bytes:%u rx:%02x ", + sbsf->addr_bytes, rx[pos]); if (sbsf->addr_bytes++ < SF_ADDR_LEN) sbsf->off = (sbsf->off << 8) | rx[pos]; - debug("addr:%06x\n", sbsf->off); + log_content("addr:%06x\n", sbsf->off); if (tx) sandbox_spi_tristate(&tx[pos], 1); @@ -403,8 +382,8 @@ static int sandbox_sf_xfer(struct udevice *dev, unsigned int bitlen, sbsf->state = SF_ERASE; goto case_sf_erase; } - debug(" cmd: transition to %s state\n", - sandbox_sf_state_name(sbsf->state)); + log_content(" cmd: transition to %s state\n", + sandbox_sf_state_name(sbsf->state)); break; case SF_READ: /* @@ -413,7 +392,7 @@ static int sandbox_sf_xfer(struct udevice *dev, unsigned int bitlen, */ cnt = bytes - pos; - debug(" tx: read(%u)\n", cnt); + log_content(" tx: read(%u)\n", cnt); assert(tx); ret = os_read(sbsf->fd, tx + pos, cnt); if (ret < 0) { @@ -423,19 +402,19 @@ static int sandbox_sf_xfer(struct udevice *dev, unsigned int bitlen, pos += ret; break; case SF_READ_STATUS: - debug(" read status: %#x\n", sbsf->status); + log_content(" read status: %#x\n", sbsf->status); cnt = bytes - pos; memset(tx + pos, sbsf->status, cnt); pos += cnt; break; case SF_READ_STATUS1: - debug(" read status: %#x\n", sbsf->status); + log_content(" read status: %#x\n", sbsf->status); cnt = bytes - pos; memset(tx + pos, sbsf->status >> 8, cnt); pos += cnt; break; case SF_WRITE_STATUS: - debug(" write status: %#x (ignored)\n", rx[pos]); + log_content(" write status: %#x (ignored)\n", rx[pos]); pos = bytes; break; case SF_WRITE: @@ -451,7 +430,7 @@ static int sandbox_sf_xfer(struct udevice *dev, unsigned int bitlen, } cnt = bytes - pos; - debug(" rx: write(%u)\n", cnt); + log_content(" rx: write(%u)\n", cnt); if (tx) sandbox_spi_tristate(&tx[pos], cnt); ret = os_write(sbsf->fd, rx + pos, cnt); @@ -471,15 +450,15 @@ static int sandbox_sf_xfer(struct udevice *dev, unsigned int bitlen, /* verify address is aligned */ if (sbsf->off & (sbsf->erase_size - 1)) { - debug(" sector erase: cmd:%#x needs align:%#x, but we got %#x\n", - sbsf->cmd, sbsf->erase_size, - sbsf->off); + log_content(" sector erase: cmd:%#x needs align:%#x, but we got %#x\n", + sbsf->cmd, sbsf->erase_size, + sbsf->off); sbsf->status &= ~STAT_WEL; goto done; } - debug(" sector erase addr: %u, size: %u\n", sbsf->off, - sbsf->erase_size); + log_content(" sector erase addr: %u, size: %u\n", + sbsf->off, sbsf->erase_size); cnt = bytes - pos; if (tx) @@ -493,13 +472,13 @@ static int sandbox_sf_xfer(struct udevice *dev, unsigned int bitlen, ret = sandbox_erase_part(sbsf, sbsf->erase_size); sbsf->status &= ~STAT_WEL; if (ret) { - debug("sandbox_sf: Erase failed\n"); + log_content("sandbox_sf: Erase failed\n"); goto done; } goto done; } default: - debug(" ??? no idea what to do ???\n"); + log_content(" ??? no idea what to do ???\n"); goto done; } } @@ -530,31 +509,6 @@ static const struct dm_spi_emul_ops sandbox_sf_emul_ops = { }; #ifdef CONFIG_SPI_FLASH -static int sandbox_cmdline_cb_spi_sf(struct sandbox_state *state, - const char *arg) -{ - unsigned long bus, cs; - const char *spec = sandbox_spi_parse_spec(arg, &bus, &cs); - - if (!spec) - return 1; - - /* - * It is safe to not make a copy of 'spec' because it comes from the - * command line. - * - * TODO(sjg@chromium.org): It would be nice if we could parse the - * spec here, but the problem is that no U-Boot init has been done - * yet. Perhaps we can figure something out. - */ - state->spi[bus][cs].spec = spec; - debug("%s: Setting up spec '%s' for bus %ld, cs %ld\n", __func__, - spec, bus, cs); - - return 0; -} -SANDBOX_CMDLINE_OPT(spi_sf, 1, "connect a SPI flash: :::"); - int sandbox_sf_bind_emul(struct sandbox_state *state, int busnum, int cs, struct udevice *bus, ofnode node, const char *spec) { @@ -597,33 +551,6 @@ void sandbox_sf_unbind_emul(struct sandbox_state *state, int busnum, int cs) state->spi[busnum][cs].emul = NULL; } -static int sandbox_sf_bind_bus_cs(struct sandbox_state *state, int busnum, - int cs, const char *spec) -{ - struct udevice *bus, *slave; - int ret; - - ret = uclass_find_device_by_seq(UCLASS_SPI, busnum, true, &bus); - if (ret) { - printf("Invalid bus %d for spec '%s' (err=%d)\n", busnum, - spec, ret); - return ret; - } - ret = spi_find_chip_select(bus, cs, &slave); - if (!ret) { - printf("Chip select %d already exists for spec '%s'\n", cs, - spec); - return -EEXIST; - } - - ret = device_bind_driver(bus, "spi_flash_std", spec, &slave); - if (ret) - return ret; - - return sandbox_sf_bind_emul(state, busnum, cs, bus, ofnode_null(), - spec); -} - int sandbox_spi_get_emul(struct sandbox_state *state, struct udevice *bus, struct udevice *slave, struct udevice **emulp) @@ -650,35 +577,6 @@ int sandbox_spi_get_emul(struct sandbox_state *state, return 0; } - -int dm_scan_other(bool pre_reloc_only) -{ - struct sandbox_state *state = state_get_current(); - int busnum, cs; - - if (pre_reloc_only) - return 0; - for (busnum = 0; busnum < CONFIG_SANDBOX_SPI_MAX_BUS; busnum++) { - for (cs = 0; cs < CONFIG_SANDBOX_SPI_MAX_CS; cs++) { - const char *spec = state->spi[busnum][cs].spec; - int ret; - - if (spec) { - ret = sandbox_sf_bind_bus_cs(state, busnum, - cs, spec); - if (ret) { - debug("%s: Bind failed for bus %d, cs %d\n", - __func__, busnum, cs); - return ret; - } - debug("%s: Setting up spec '%s' for bus %d, cs %d\n", - __func__, spec, busnum, cs); - } - } - } - - return 0; -} #endif static const struct udevice_id sandbox_sf_ids[] = { diff --git a/drivers/mtd/spi/sf-uclass.c b/drivers/mtd/spi/sf-uclass.c index 3858f77..662525f 100644 --- a/drivers/mtd/spi/sf-uclass.c +++ b/drivers/mtd/spi/sf-uclass.c @@ -14,18 +14,18 @@ DECLARE_GLOBAL_DATA_PTR; int spi_flash_read_dm(struct udevice *dev, u32 offset, size_t len, void *buf) { - return sf_get_ops(dev)->read(dev, offset, len, buf); + return log_ret(sf_get_ops(dev)->read(dev, offset, len, buf)); } int spi_flash_write_dm(struct udevice *dev, u32 offset, size_t len, const void *buf) { - return sf_get_ops(dev)->write(dev, offset, len, buf); + return log_ret(sf_get_ops(dev)->write(dev, offset, len, buf)); } int spi_flash_erase_dm(struct udevice *dev, u32 offset, size_t len) { - return sf_get_ops(dev)->erase(dev, offset, len); + return log_ret(sf_get_ops(dev)->erase(dev, offset, len)); } /* diff --git a/drivers/mtd/spi/sf_probe.c b/drivers/mtd/spi/sf_probe.c index 42c7cde..94fde2a 100644 --- a/drivers/mtd/spi/sf_probe.c +++ b/drivers/mtd/spi/sf_probe.c @@ -97,7 +97,7 @@ static int spi_flash_std_read(struct udevice *dev, u32 offset, size_t len, { struct spi_flash *flash = dev_get_uclass_priv(dev); - return spi_flash_cmd_read_ops(flash, offset, len, buf); + return log_ret(spi_flash_cmd_read_ops(flash, offset, len, buf)); } static int spi_flash_std_write(struct udevice *dev, u32 offset, size_t len, diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c index c159124..9230060 100644 --- a/drivers/mtd/spi/spi_flash.c +++ b/drivers/mtd/spi/spi_flash.c @@ -468,17 +468,17 @@ int spi_flash_cmd_read_ops(struct spi_flash *flash, u32 offset, size_t len, void *data) { struct spi_slave *spi = flash->spi; - u8 *cmd, cmdsz; + u8 cmdsz; u32 remain_len, read_len, read_addr; int bank_sel = 0; - int ret = -1; + int ret = 0; /* Handle memory-mapped SPI */ if (flash->memory_map) { ret = spi_claim_bus(spi); if (ret) { debug("SF: unable to claim SPI bus\n"); - return ret; + return log_ret(ret); } spi_xfer(spi, 0, NULL, NULL, SPI_XFER_MMAP); spi_flash_copy_mmap(data, flash->memory_map + offset, len); @@ -488,11 +488,7 @@ int spi_flash_cmd_read_ops(struct spi_flash *flash, u32 offset, } cmdsz = SPI_FLASH_CMD_LEN + flash->dummy_byte; - cmd = calloc(1, cmdsz); - if (!cmd) { - debug("SF: Failed to allocate cmd\n"); - return -ENOMEM; - } + u8 cmd[cmdsz]; cmd[0] = flash->read_cmd; while (len) { @@ -505,7 +501,7 @@ int spi_flash_cmd_read_ops(struct spi_flash *flash, u32 offset, #ifdef CONFIG_SPI_FLASH_BAR ret = write_bar(flash, read_addr); if (ret < 0) - return ret; + return log_ret(ret); bank_sel = flash->bank_curr; #endif remain_len = ((SPI_FLASH_16MB_BOUN << flash->shift) * @@ -535,8 +531,7 @@ int spi_flash_cmd_read_ops(struct spi_flash *flash, u32 offset, ret = clean_bar(flash); #endif - free(cmd); - return ret; + return log_ret(ret); } #ifdef CONFIG_SPI_FLASH_SST diff --git a/drivers/pci/pci_rom.c b/drivers/pci/pci_rom.c index 29113f7..eaacd40 100644 --- a/drivers/pci/pci_rom.c +++ b/drivers/pci/pci_rom.c @@ -247,7 +247,7 @@ int dm_pci_run_vga_bios(struct udevice *dev, int (*int15_handler)(void), } if (!board_should_load_oprom(dev)) - return -ENXIO; + return log_msg_ret("Should not load OPROM", -ENXIO); ret = pci_rom_probe(dev, &rom); if (ret) @@ -328,7 +328,7 @@ int vbe_setup_video_priv(struct vesa_mode_info *vesa, struct video_uc_platdata *plat) { if (!vesa->x_resolution) - return -ENXIO; + return log_msg_ret("No x resolution", -ENXIO); uc_priv->xsize = vesa->x_resolution; uc_priv->ysize = vesa->y_resolution; switch (vesa->bits_per_pixel) { diff --git a/drivers/pwm/sandbox_pwm.c b/drivers/pwm/sandbox_pwm.c index 4b50b19..2898818 100644 --- a/drivers/pwm/sandbox_pwm.c +++ b/drivers/pwm/sandbox_pwm.c @@ -14,6 +14,14 @@ enum { NUM_CHANNELS = 3, }; +/** + * struct sandbox_pwm_chan - a sandbox PWM channel + * + * @period_ns: Period of the PWM in nanoseconds + * @duty_ns: Current duty cycle of the PWM in nanoseconds + * @enable: true if the PWM is enabled + * @polarity: true if the PWM polarity is active high + */ struct sandbox_pwm_chan { uint period_ns; uint duty_ns; @@ -25,6 +33,23 @@ struct sandbox_pwm_priv { struct sandbox_pwm_chan chan[NUM_CHANNELS]; }; +int sandbox_pwm_get_config(struct udevice *dev, uint channel, uint *period_nsp, + uint *duty_nsp, bool *enablep, bool *polarityp) +{ + struct sandbox_pwm_priv *priv = dev_get_priv(dev); + struct sandbox_pwm_chan *chan; + + if (channel >= NUM_CHANNELS) + return -ENOSPC; + chan = &priv->chan[channel]; + *period_nsp = chan->period_ns; + *duty_nsp = chan->duty_ns; + *enablep = chan->enable; + *polarityp = chan->polarity; + + return 0; +} + static int sandbox_pwm_set_config(struct udevice *dev, uint channel, uint period_ns, uint duty_ns) { diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 5436509..bcc01b1 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -13,6 +13,24 @@ config DM_RTC drivers to perform the actual functions. See rtc.h for a description of the API. +config SPL_DM_RTC + bool "Enable Driver Model for RTC drivers in SPL" + depends on SPL_DM + help + Enable drver model for real-time-clock drivers. The RTC uclass + then provides the rtc_get()/rtc_set() interface, delegating to + drivers to perform the actual functions. See rtc.h for a + description of the API. + +config TPL_DM_RTC + bool "Enable Driver Model for RTC drivers in TPL" + depends on TPL_DM + help + Enable drver model for real-time-clock drivers. The RTC uclass + then provides the rtc_get()/rtc_set() interface, delegating to + drivers to perform the actual functions. See rtc.h for a + description of the API. + config RTC_PCF2127 bool "Enable PCF2127 driver" depends on DM_RTC @@ -68,4 +86,12 @@ config RTC_S35392A help Enable s35392a driver which provides rtc get and set function. +config RTC_MC146818 + bool "Enable MC146818 driver" + help + This is a widely used real-time clock chip originally by Motorola + and now available from NXP. It includes a battery-backed real-time + clock with a wide array of features and 50 bytes of general-purpose, + battery-backed RAM. The driver supports access to the clock and RAM. + endmenu diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 513e3ff..1724602 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -4,7 +4,7 @@ # Wolfgang Denk, DENX Software Engineering, wd@denx.de. #ccflags-y += -DDEBUG -obj-$(CONFIG_DM_RTC) += rtc-uclass.o +obj-$(CONFIG_$(SPL_TPL_)DM_RTC) += rtc-uclass.o obj-$(CONFIG_RTC_AT91SAM9_RTT) += at91sam9_rtt.o obj-y += date.o diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 5fa2725..597db4b 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -53,6 +53,16 @@ config SPL_SERIAL_PRESENT This option enables the full UART in SPL, so if is it disabled, the full UART driver will be omitted, thus saving space. +config TPL_SERIAL_PRESENT + bool "Provide a serial driver in TPL" + depends on DM_SERIAL + default y + help + In very space-constrained devices even the full UART driver is too + large. In this case the debug UART can still be used in some cases. + This option enables the full UART in TPL, so if is it disabled, + the full UART driver will be omitted, thus saving space. + # Logic to allow us to use the imply keyword to set what the default port # should be. The default is otherwise 1. config CONS_INDEX_0 @@ -324,6 +334,15 @@ config DEBUG_UART_MXC will need to provide parameters to make this work. The driver will be available until the real driver model serial is running. +config DEBUG_UART_SANDBOX + bool "sandbox" + depends on SANDBOX_SERIAL + help + Select this to enable the debug UART using the sandbox driver. This + provides basic serial output from the console without needing to + start up driver model. The driver will be available until the real + driver model serial is running. + config DEBUG_UART_STM32 bool "STMicroelectronics STM32" depends on STM32_SERIAL @@ -354,6 +373,7 @@ endchoice config DEBUG_UART_BASE hex "Base address of UART" depends on DEBUG_UART + default 0 if DEBUG_UART_SANDBOX help This is the base address of your UART for memory-mapped UARTs. @@ -363,6 +383,7 @@ config DEBUG_UART_BASE config DEBUG_UART_CLOCK int "UART input clock" depends on DEBUG_UART + default 0 if DEBUG_UART_SANDBOX help The UART input clock determines the speed of the internal UART circuitry. The baud rate is derived from this by dividing the input diff --git a/drivers/serial/sandbox.c b/drivers/serial/sandbox.c index 94b4fdf..4a05ea4 100644 --- a/drivers/serial/sandbox.c +++ b/drivers/serial/sandbox.c @@ -22,6 +22,8 @@ DECLARE_GLOBAL_DATA_PTR; +#if CONFIG_IS_ENABLED(OF_CONTROL) + /* * * serial_buf: A buffer that holds keyboard characters for the @@ -124,7 +126,7 @@ static int sandbox_serial_pending(struct udevice *dev, bool input) if (next_index == serial_buf_read) return 1; /* buffer full */ - count = os_read_no_block(0, &serial_buf[serial_buf_write], 1); + count = os_read(0, &serial_buf[serial_buf_write], 1); if (count == 1) serial_buf_write = next_index; @@ -142,6 +144,24 @@ static int sandbox_serial_getc(struct udevice *dev) serial_buf_read = increment_buffer_index(serial_buf_read); return result; } +#endif /* CONFIG_IS_ENABLED(OF_CONTROL) */ + +#ifdef CONFIG_DEBUG_UART_SANDBOX + +#include + +static inline void _debug_uart_init(void) +{ +} + +static inline void _debug_uart_putc(int ch) +{ + os_putc(ch); +} + +DEBUG_UART_FUNCS + +#endif /* CONFIG_DEBUG_UART_SANDBOX */ static int sandbox_serial_setconfig(struct udevice *dev, uint serial_config) { @@ -156,6 +176,7 @@ static int sandbox_serial_setconfig(struct udevice *dev, uint serial_config) return 0; } +#if CONFIG_IS_ENABLED(OF_CONTROL) static const char * const ansi_colour[] = { "black", "red", "green", "yellow", "blue", "megenta", "cyan", "white", @@ -215,3 +236,4 @@ U_BOOT_DEVICE(serial_sandbox_non_fdt) = { .name = "serial_sandbox", .platdata = &platdata_non_fdt, }; +#endif /* CONFIG_IS_ENABLED(OF_CONTROL) */ diff --git a/drivers/serial/serial-uclass.c b/drivers/serial/serial-uclass.c index ffdcae0..e50f0aa 100644 --- a/drivers/serial/serial-uclass.c +++ b/drivers/serial/serial-uclass.c @@ -26,6 +26,7 @@ static const unsigned long baudrate_table[] = CONFIG_SYS_BAUDRATE_TABLE; #error "Serial is required before relocation - define CONFIG_$(SPL_)SYS_MALLOC_F_LEN to make this work" #endif +#if CONFIG_IS_ENABLED(SERIAL_PRESENT) static int serial_check_stdout(const void *blob, struct udevice **devp) { int node; @@ -150,12 +151,15 @@ static void serial_find_console_or_panic(void) panic_str("No serial driver found"); #endif } +#endif /* CONFIG_SERIAL_PRESENT */ /* Called prior to relocation */ int serial_init(void) { +#if CONFIG_IS_ENABLED(SERIAL_PRESENT) serial_find_console_or_panic(); gd->flags |= GD_FLG_SERIAL_READY; +#endif return 0; } diff --git a/drivers/spi/sandbox_spi.c b/drivers/spi/sandbox_spi.c index 75ba6a1..906401e 100644 --- a/drivers/spi/sandbox_spi.c +++ b/drivers/spi/sandbox_spi.c @@ -8,6 +8,8 @@ * Licensed under the GPL-2 or later. */ +#define LOG_CATEGORY UCLASS_SPI + #include #include #include @@ -56,7 +58,6 @@ static int sandbox_spi_xfer(struct udevice *slave, unsigned int bitlen, struct udevice *emul; uint bytes = bitlen / 8, i; int ret; - u8 *tx = (void *)dout, *rx = din; uint busnum, cs; if (bitlen == 0) @@ -87,37 +88,16 @@ static int sandbox_spi_xfer(struct udevice *slave, unsigned int bitlen, if (ret) return ret; - /* make sure rx/tx buffers are full so clients can assume */ - if (!tx) { - debug("sandbox_spi: xfer: auto-allocating tx scratch buffer\n"); - tx = malloc(bytes); - if (!tx) { - debug("sandbox_spi: Out of memory\n"); - return -ENOMEM; - } - } - if (!rx) { - debug("sandbox_spi: xfer: auto-allocating rx scratch buffer\n"); - rx = malloc(bytes); - if (!rx) { - debug("sandbox_spi: Out of memory\n"); - return -ENOMEM; - } - } - ops = spi_emul_get_ops(emul); ret = ops->xfer(emul, bitlen, dout, din, flags); - debug("sandbox_spi: xfer: got back %i (that's %s)\n rx:", - ret, ret ? "bad" : "good"); - for (i = 0; i < bytes; ++i) - debug(" %u:%02x", i, rx[i]); - debug("\n"); - - if (tx != dout) - free(tx); - if (rx != din) - free(rx); + log_content("sandbox_spi: xfer: got back %i (that's %s)\n rx:", + ret, ret ? "bad" : "good"); + if (din) { + for (i = 0; i < bytes; ++i) + log_content(" %u:%02x", i, ((u8 *)din)[i]); + } + log_content("\n"); return ret; } diff --git a/drivers/spi/spi-uclass.c b/drivers/spi/spi-uclass.c index c517d06..b84255b 100644 --- a/drivers/spi/spi-uclass.c +++ b/drivers/spi/spi-uclass.c @@ -63,11 +63,11 @@ int dm_spi_claim_bus(struct udevice *dev) int ret = spi_set_speed_mode(bus, speed, slave->mode); if (ret) - return ret; + return log_ret(ret); slave->speed = speed; } - return ops->claim_bus ? ops->claim_bus(dev) : 0; + return log_ret(ops->claim_bus ? ops->claim_bus(dev) : 0); } void dm_spi_release_bus(struct udevice *dev) @@ -92,7 +92,7 @@ int dm_spi_xfer(struct udevice *dev, unsigned int bitlen, int spi_claim_bus(struct spi_slave *slave) { - return dm_spi_claim_bus(slave->dev); + return log_ret(dm_spi_claim_bus(slave->dev)); } void spi_release_bus(struct spi_slave *slave) diff --git a/drivers/sysreset/sysreset-uclass.c b/drivers/sysreset/sysreset-uclass.c index 06ef0ed..ad831c7 100644 --- a/drivers/sysreset/sysreset-uclass.c +++ b/drivers/sysreset/sysreset-uclass.c @@ -4,6 +4,8 @@ * Written by Simon Glass */ +#define LOG_CATEGORY UCLASS_SYSRESET + #include #include #include @@ -34,6 +36,16 @@ int sysreset_get_status(struct udevice *dev, char *buf, int size) return ops->get_status(dev, buf, size); } +int sysreset_get_last(struct udevice *dev) +{ + struct sysreset_ops *ops = sysreset_get_ops(dev); + + if (!ops->get_last) + return -ENOSYS; + + return ops->get_last(dev); +} + int sysreset_walk(enum sysreset_t type) { struct udevice *dev; @@ -53,6 +65,26 @@ int sysreset_walk(enum sysreset_t type) return ret; } +int sysreset_get_last_walk(void) +{ + struct udevice *dev; + int value = -ENOENT; + + for (uclass_first_device(UCLASS_SYSRESET, &dev); + dev; + uclass_next_device(&dev)) { + int ret; + + ret = sysreset_get_last(dev); + if (ret >= 0) { + value = ret; + break; + } + } + + return value; +} + void sysreset_walk_halt(enum sysreset_t type) { int ret; @@ -64,7 +96,7 @@ void sysreset_walk_halt(enum sysreset_t type) mdelay(100); /* Still no reset? Give up */ - debug("System reset not supported on this platform\n"); + log_err("System reset not supported on this platform\n"); hang(); } diff --git a/drivers/sysreset/sysreset_sandbox.c b/drivers/sysreset/sysreset_sandbox.c index 75004d9..7f6d418 100644 --- a/drivers/sysreset/sysreset_sandbox.c +++ b/drivers/sysreset/sysreset_sandbox.c @@ -36,6 +36,11 @@ int sandbox_warm_sysreset_get_status(struct udevice *dev, char *buf, int size) return 0; } +int sandbox_warm_sysreset_get_last(struct udevice *dev) +{ + return SYSRESET_WARM; +} + static int sandbox_sysreset_request(struct udevice *dev, enum sysreset_t type) { struct sandbox_state *state = state_get_current(); @@ -58,6 +63,9 @@ static int sandbox_sysreset_request(struct udevice *dev, enum sysreset_t type) return -EACCES; sandbox_exit(); break; + case SYSRESET_POWER_OFF: + if (!state->sysreset_allowed[type]) + return -EACCES; default: return -ENOSYS; } @@ -74,9 +82,15 @@ int sandbox_sysreset_get_status(struct udevice *dev, char *buf, int size) return 0; } +int sandbox_sysreset_get_last(struct udevice *dev) +{ + return SYSRESET_COLD; +} + static struct sysreset_ops sandbox_sysreset_ops = { .request = sandbox_sysreset_request, .get_status = sandbox_sysreset_get_status, + .get_last = sandbox_sysreset_get_last, }; static const struct udevice_id sandbox_sysreset_ids[] = { @@ -94,6 +108,7 @@ U_BOOT_DRIVER(sysreset_sandbox) = { static struct sysreset_ops sandbox_warm_sysreset_ops = { .request = sandbox_warm_sysreset_request, .get_status = sandbox_warm_sysreset_get_status, + .get_last = sandbox_warm_sysreset_get_last, }; static const struct udevice_id sandbox_warm_sysreset_ids[] = { diff --git a/drivers/tpm/Makefile b/drivers/tpm/Makefile index af473ef..94c337b 100644 --- a/drivers/tpm/Makefile +++ b/drivers/tpm/Makefile @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0+ # Copyright (c) 2011 The Chromium OS Authors. All rights reserved. -obj-$(CONFIG_TPM) += tpm-uclass.o +obj-$(CONFIG_$(SPL_TPL_)TPM) += tpm-uclass.o obj-$(CONFIG_TPM_ATMEL_TWI) += tpm_atmel_twi.o obj-$(CONFIG_TPM_TIS_INFINEON) += tpm_tis_infineon.o diff --git a/drivers/tpm/tpm-uclass.c b/drivers/tpm/tpm-uclass.c index c83f53a..1b11c93 100644 --- a/drivers/tpm/tpm-uclass.c +++ b/drivers/tpm/tpm-uclass.c @@ -126,8 +126,11 @@ int tpm_xfer(struct udevice *dev, const uint8_t *sendbuf, size_t send_size, } UCLASS_DRIVER(tpm) = { - .id = UCLASS_TPM, - .name = "tpm", - .flags = DM_UC_FLAG_SEQ_ALIAS, + .id = UCLASS_TPM, + .name = "tpm", + .flags = DM_UC_FLAG_SEQ_ALIAS, +#if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA) + .post_bind = dm_scan_fdt_dev, +#endif .per_device_auto_alloc_size = sizeof(struct tpm_chip_priv), }; diff --git a/drivers/tpm/tpm_tis_lpc.c b/drivers/tpm/tpm_tis_lpc.c index 7664bb1..e993fd9 100644 --- a/drivers/tpm/tpm_tis_lpc.c +++ b/drivers/tpm/tpm_tis_lpc.c @@ -164,7 +164,7 @@ static int tpm_tis_lpc_probe(struct udevice *dev) u32 didvid; ulong chip_type = dev_get_driver_data(dev); - addr = devfdt_get_addr(dev); + addr = dev_read_addr(dev); if (addr == FDT_ADDR_T_NONE) return -EINVAL; priv->regs = map_sysmem(addr, 0); diff --git a/drivers/tpm/tpm_tis_sandbox.c b/drivers/tpm/tpm_tis_sandbox.c index 8816d55..79517f0 100644 --- a/drivers/tpm/tpm_tis_sandbox.c +++ b/drivers/tpm/tpm_tis_sandbox.c @@ -13,6 +13,10 @@ /* TPM NVRAM location indices. */ #define FIRMWARE_NV_INDEX 0x1007 #define KERNEL_NV_INDEX 0x1008 +#define BACKUP_NV_INDEX 0x1009 +#define FWMP_NV_INDEX 0x100a +#define REC_HASH_NV_INDEX 0x100b +#define REC_HASH_NV_SIZE VB2_SHA256_DIGEST_SIZE #define NV_DATA_PUBLIC_PERMISSIONS_OFFSET 60 @@ -45,18 +49,28 @@ enum { NV_GLOBAL_LOCK, NV_SEQ_FIRMWARE, NV_SEQ_KERNEL, + NV_SEQ_BACKUP, + NV_SEQ_FWMP, + NV_SEQ_REC_HASH, + NV_SEQ_COUNT, }; /* Size of each non-volatile space */ #define NV_DATA_SIZE 0x20 +struct nvdata_state { + bool present; + u8 data[NV_DATA_SIZE]; +}; + /* * Information about our TPM emulation. This is preserved in the sandbox * state file if enabled. */ static struct tpm_state { - uint8_t nvdata[NV_SEQ_COUNT][NV_DATA_SIZE]; + bool valid; + struct nvdata_state nvdata[NV_SEQ_COUNT]; } g_state; /** @@ -82,9 +96,12 @@ static int sandbox_tpm_read_state(const void *blob, int node) sprintf(prop_name, "nvdata%d", i); prop = fdt_getprop(blob, node, prop_name, &len); - if (prop && len == NV_DATA_SIZE) - memcpy(g_state.nvdata[i], prop, NV_DATA_SIZE); + if (prop && len == NV_DATA_SIZE) { + memcpy(g_state.nvdata[i].data, prop, NV_DATA_SIZE); + g_state.nvdata[i].present = true; + } } + g_state.valid = true; return 0; } @@ -110,9 +127,11 @@ static int sandbox_tpm_write_state(void *blob, int node) for (i = 0; i < NV_SEQ_COUNT; i++) { char prop_name[20]; - sprintf(prop_name, "nvdata%d", i); - fdt_setprop(blob, node, prop_name, g_state.nvdata[i], - NV_DATA_SIZE); + if (g_state.nvdata[i].present) { + sprintf(prop_name, "nvdata%d", i); + fdt_setprop(blob, node, prop_name, + g_state.nvdata[i].data, NV_DATA_SIZE); + } } return 0; @@ -128,6 +147,12 @@ static int index_to_seq(uint32_t index) return NV_SEQ_FIRMWARE; case KERNEL_NV_INDEX: return NV_SEQ_KERNEL; + case BACKUP_NV_INDEX: + return NV_SEQ_BACKUP; + case FWMP_NV_INDEX: + return NV_SEQ_FWMP; + case REC_HASH_NV_INDEX: + return NV_SEQ_REC_HASH; case 0: return NV_GLOBAL_LOCK; } @@ -136,6 +161,21 @@ static int index_to_seq(uint32_t index) return -1; } +static void handle_cap_flag_space(u8 **datap, uint index) +{ + struct tpm_nv_data_public pub; + + /* TPM_NV_PER_PPWRITE */ + memset(&pub, '\0', sizeof(pub)); + pub.nv_index = __cpu_to_be32(index); + pub.pcr_info_read.pcr_selection.size_of_select = __cpu_to_be16( + sizeof(pub.pcr_info_read.pcr_selection.pcr_select)); + pub.permission.attributes = __cpu_to_be32(1); + pub.pcr_info_write = pub.pcr_info_read; + memcpy(*datap, &pub, sizeof(pub)); + *datap += sizeof(pub); +} + static int sandbox_tpm_xfer(struct udevice *dev, const uint8_t *sendbuf, size_t send_size, uint8_t *recvbuf, size_t *recv_len) @@ -151,29 +191,45 @@ static int sandbox_tpm_xfer(struct udevice *dev, const uint8_t *sendbuf, *recv_len, code); print_buffer(0, sendbuf, 1, send_size, 0); switch (code) { - case 0x65: /* get flags */ + case TPM_CMD_GET_CAPABILITY: type = get_unaligned_be32(sendbuf + 14); switch (type) { - case 4: + case TPM_CAP_FLAG: index = get_unaligned_be32(sendbuf + 18); printf("Get flags index %#02x\n", index); *recv_len = 22; memset(recvbuf, '\0', *recv_len); - put_unaligned_be32(22, recvbuf + - TPM_RESPONSE_HEADER_LENGTH); data = recvbuf + TPM_RESPONSE_HEADER_LENGTH + sizeof(uint32_t); switch (index) { case FIRMWARE_NV_INDEX: break; case KERNEL_NV_INDEX: - /* TPM_NV_PER_PPWRITE */ - put_unaligned_be32(1, data + - NV_DATA_PUBLIC_PERMISSIONS_OFFSET); + handle_cap_flag_space(&data, index); + *recv_len = data - recvbuf - + TPM_RESPONSE_HEADER_LENGTH - + sizeof(uint32_t); + break; + case TPM_CAP_FLAG_PERMANENT: { + struct tpm_permanent_flags *pflags; + + pflags = (struct tpm_permanent_flags *)data; + memset(pflags, '\0', sizeof(*pflags)); + put_unaligned_be32(TPM_TAG_PERMANENT_FLAGS, + &pflags->tag); + *recv_len = TPM_HEADER_SIZE + 4 + + sizeof(*pflags); break; } + default: + printf(" ** Unknown flags index %x\n", index); + return -ENOSYS; + } + put_unaligned_be32(*recv_len, + recvbuf + + TPM_RESPONSE_HEADER_LENGTH); break; - case 0x11: /* TPM_CAP_NV_INDEX */ + case TPM_CAP_NV_INDEX: index = get_unaligned_be32(sendbuf + 18); printf("Get cap nv index %#02x\n", index); put_unaligned_be32(22, recvbuf + @@ -182,27 +238,29 @@ static int sandbox_tpm_xfer(struct udevice *dev, const uint8_t *sendbuf, default: printf(" ** Unknown 0x65 command type %#02x\n", type); - return -1; + return -ENOSYS; } break; - case 0xcd: /* nvwrite */ + case TPM_CMD_NV_WRITE_VALUE: index = get_unaligned_be32(sendbuf + 10); length = get_unaligned_be32(sendbuf + 18); seq = index_to_seq(index); if (seq < 0) - return -1; + return -EINVAL; printf("tpm: nvwrite index=%#02x, len=%#02x\n", index, length); - memcpy(&tpm->nvdata[seq], sendbuf + 22, length); + memcpy(&tpm->nvdata[seq].data, sendbuf + 22, length); + tpm->nvdata[seq].present = true; *recv_len = 12; memset(recvbuf, '\0', *recv_len); break; - case 0xcf: /* nvread */ + case TPM_CMD_NV_READ_VALUE: /* nvread */ index = get_unaligned_be32(sendbuf + 10); length = get_unaligned_be32(sendbuf + 18); seq = index_to_seq(index); if (seq < 0) - return -1; - printf("tpm: nvread index=%#02x, len=%#02x\n", index, length); + return -EINVAL; + printf("tpm: nvread index=%#02x, len=%#02x, seq=%#02x\n", index, + length, seq); *recv_len = TPM_RESPONSE_HEADER_LENGTH + sizeof(uint32_t) + length; memset(recvbuf, '\0', *recv_len); @@ -220,24 +278,33 @@ static int sandbox_tpm_xfer(struct udevice *dev, const uint8_t *sendbuf, offsetof(struct rollback_space_kernel, crc8)); memcpy(data, &rsk, sizeof(rsk)); + } else if (!tpm->nvdata[seq].present) { + put_unaligned_be32(TPM_BADINDEX, recvbuf + + sizeof(uint16_t) + sizeof(uint32_t)); } else { memcpy(recvbuf + TPM_RESPONSE_HEADER_LENGTH + - sizeof(uint32_t), &tpm->nvdata[seq], length); + sizeof(uint32_t), &tpm->nvdata[seq].data, + length); } break; - case 0x14: /* tpm extend */ + case TPM_CMD_EXTEND: + *recv_len = 30; + memset(recvbuf, '\0', *recv_len); + break; + case TPM_CMD_NV_DEFINE_SPACE: case 0x15: /* pcr read */ case 0x5d: /* force clear */ case 0x6f: /* physical enable */ case 0x72: /* physical set deactivated */ case 0x99: /* startup */ + case 0x50: /* self test full */ case 0x4000000a: /* assert physical presence */ *recv_len = 12; memset(recvbuf, '\0', *recv_len); break; default: printf("Unknown tpm command %02x\n", code); - return -1; + return -ENOSYS; } return 0; diff --git a/drivers/video/backlight-uclass.c b/drivers/video/backlight-uclass.c index 92715e2..0aadf8a 100644 --- a/drivers/video/backlight-uclass.c +++ b/drivers/video/backlight-uclass.c @@ -18,6 +18,16 @@ int backlight_enable(struct udevice *dev) return ops->enable(dev); } +int backlight_set_brightness(struct udevice *dev, int percent) +{ + const struct backlight_ops *ops = backlight_get_ops(dev); + + if (!ops->set_brightness) + return -ENOSYS; + + return ops->set_brightness(dev, percent); +} + UCLASS_DRIVER(backlight) = { .id = UCLASS_PANEL_BACKLIGHT, .name = "backlight", diff --git a/drivers/video/panel-uclass.c b/drivers/video/panel-uclass.c index aec44a8..246d1b2 100644 --- a/drivers/video/panel-uclass.c +++ b/drivers/video/panel-uclass.c @@ -18,6 +18,24 @@ int panel_enable_backlight(struct udevice *dev) return ops->enable_backlight(dev); } +/** + * panel_set_backlight - Set brightness for the panel backlight + * + * @dev: Panel device containing the backlight to update + * @percent: Brightness value (0=off, 1=min brightness, + * 100=full brightness) + * @return 0 if OK, -ve on error + */ +int panel_set_backlight(struct udevice *dev, int percent) +{ + struct panel_ops *ops = panel_get_ops(dev); + + if (!ops->set_backlight) + return -ENOSYS; + + return ops->set_backlight(dev, percent); +} + int panel_get_display_timing(struct udevice *dev, struct display_timing *timings) { diff --git a/drivers/video/pwm_backlight.c b/drivers/video/pwm_backlight.c index 5395317..c13a907 100644 --- a/drivers/video/pwm_backlight.c +++ b/drivers/video/pwm_backlight.c @@ -4,6 +4,8 @@ * Written by Simon Glass */ +#define LOG_CATEGORY UCLASS_PANEL_BACKLIGHT + #include #include #include @@ -11,48 +13,156 @@ #include #include +/** + * Private information for the PWM backlight + * + * If @num_levels is 0 then the levels are simple values with the backlight + * value going between the minimum (default 0) and the maximum (default 255). + * Otherwise the levels are an index into @levels (0..n-1). + * + * @reg: Regulator to enable to turn the backlight on (NULL if none) + * @enable, GPIO to set to enable the backlight (can be missing) + * @pwm: PWM to use to change the backlight brightness + * @channel: PWM channel to use + * @period_ns: Period of the backlight in nanoseconds + * @levels: Levels for the backlight, or NULL if not using indexed levels + * @num_levels: Number of levels + * @cur_level: Current level for the backlight (index or value) + * @default_level: Default level for the backlight (index or value) + * @min_level: Minimum level of the backlight (full off) + * @min_level: Maximum level of the backlight (full on) + * @enabled: true if backlight is enabled + */ struct pwm_backlight_priv { struct udevice *reg; struct gpio_desc enable; struct udevice *pwm; uint channel; uint period_ns; + u32 *levels; + int num_levels; uint default_level; + int cur_level; uint min_level; uint max_level; + bool enabled; }; -static int pwm_backlight_enable(struct udevice *dev) +static int set_pwm(struct pwm_backlight_priv *priv) { - struct pwm_backlight_priv *priv = dev_get_priv(dev); - struct dm_regulator_uclass_platdata *plat; uint duty_cycle; int ret; - if (priv->reg) { - plat = dev_get_uclass_platdata(priv->reg); - debug("%s: Enable '%s', regulator '%s'/'%s'\n", __func__, - dev->name, priv->reg->name, plat->name); - ret = regulator_set_enable(priv->reg, true); - if (ret) { - debug("%s: Cannot enable regulator for PWM '%s'\n", - __func__, dev->name); - return ret; - } - mdelay(120); - } - - duty_cycle = priv->period_ns * (priv->default_level - priv->min_level) / + duty_cycle = priv->period_ns * (priv->cur_level - priv->min_level) / (priv->max_level - priv->min_level + 1); ret = pwm_set_config(priv->pwm, priv->channel, priv->period_ns, duty_cycle); + + return log_ret(ret); +} + +static int enable_sequence(struct udevice *dev, int seq) +{ + struct pwm_backlight_priv *priv = dev_get_priv(dev); + int ret; + + switch (seq) { + case 0: + if (priv->reg) { + __maybe_unused struct dm_regulator_uclass_platdata + *plat; + + plat = dev_get_uclass_platdata(priv->reg); + log_debug("Enable '%s', regulator '%s'/'%s'\n", + dev->name, priv->reg->name, plat->name); + ret = regulator_set_enable(priv->reg, true); + if (ret) { + log_debug("Cannot enable regulator for PWM '%s'\n", + __func__, dev->name); + return log_ret(ret); + } + mdelay(120); + } + break; + case 1: + mdelay(10); + dm_gpio_set_value(&priv->enable, 1); + break; + } + + return 0; +} + +static int pwm_backlight_enable(struct udevice *dev) +{ + struct pwm_backlight_priv *priv = dev_get_priv(dev); + int ret; + + ret = enable_sequence(dev, 0); + if (ret) + return log_ret(ret); + ret = set_pwm(priv); if (ret) - return ret; + return log_ret(ret); ret = pwm_set_enable(priv->pwm, priv->channel, true); if (ret) - return ret; - mdelay(10); - dm_gpio_set_value(&priv->enable, 1); + return log_ret(ret); + ret = enable_sequence(dev, 1); + if (ret) + return log_ret(ret); + priv->enabled = true; + + return 0; +} + +static int pwm_backlight_set_brightness(struct udevice *dev, int percent) +{ + struct pwm_backlight_priv *priv = dev_get_priv(dev); + bool disable = false; + int level; + int ret; + + if (!priv->enabled) { + ret = enable_sequence(dev, 0); + if (ret) + return log_ret(ret); + } + if (percent == BACKLIGHT_OFF) { + disable = true; + percent = 0; + } + if (percent == BACKLIGHT_DEFAULT) { + level = priv->default_level; + } else { + if (priv->levels) { + level = priv->levels[percent * (priv->num_levels - 1) + / 100]; + } else { + level = priv->min_level + + (priv->max_level - priv->min_level) * + percent / 100; + } + } + priv->cur_level = level; + + ret = set_pwm(priv); + if (ret) + return log_ret(ret); + if (!priv->enabled) { + ret = enable_sequence(dev, 1); + if (ret) + return log_ret(ret); + priv->enabled = true; + } + if (disable) { + dm_gpio_set_value(&priv->enable, 0); + if (priv->reg) { + ret = regulator_set_enable(priv->reg, false); + if (ret) + return log_ret(ret); + } + priv->enabled = false; + } return 0; } @@ -64,31 +174,32 @@ static int pwm_backlight_ofdata_to_platdata(struct udevice *dev) int index, ret, count, len; const u32 *cell; - debug("%s: start\n", __func__); + log_debug("start\n"); ret = uclass_get_device_by_phandle(UCLASS_REGULATOR, dev, "power-supply", &priv->reg); if (ret) - debug("%s: Cannot get power supply: ret=%d\n", __func__, ret); + log_debug("Cannot get power supply: ret=%d\n", ret); ret = gpio_request_by_name(dev, "enable-gpios", 0, &priv->enable, GPIOD_IS_OUT); if (ret) { - debug("%s: Warning: cannot get enable GPIO: ret=%d\n", - __func__, ret); + log_debug("Warning: cannot get enable GPIO: ret=%d\n", ret); if (ret != -ENOENT) - return ret; + return log_ret(ret); } ret = dev_read_phandle_with_args(dev, "pwms", "#pwm-cells", 0, 0, &args); if (ret) { - debug("%s: Cannot get PWM phandle: ret=%d\n", __func__, ret); - return ret; + log_debug("Cannot get PWM phandle: ret=%d\n", ret); + return log_ret(ret); } ret = uclass_get_device_by_ofnode(UCLASS_PWM, args.node, &priv->pwm); if (ret) { - debug("%s: Cannot get PWM: ret=%d\n", __func__, ret); - return ret; + log_debug("Cannot get PWM: ret=%d\n", ret); + return log_ret(ret); } + if (args.args_count < 2) + return log_msg_ret("Not enough arguments to pwm\n", -EINVAL); priv->channel = args.args[0]; priv->period_ns = args.args[1]; @@ -96,13 +207,20 @@ static int pwm_backlight_ofdata_to_platdata(struct udevice *dev) cell = dev_read_prop(dev, "brightness-levels", &len); count = len / sizeof(u32); if (cell && count > index) { - priv->default_level = fdt32_to_cpu(cell[index]); - priv->max_level = fdt32_to_cpu(cell[count - 1]); + priv->levels = malloc(len); + if (!priv->levels) + return log_ret(-ENOMEM); + dev_read_u32_array(dev, "brightness-levels", priv->levels, + count); + priv->num_levels = count; + priv->default_level = priv->levels[index]; + priv->max_level = priv->levels[count - 1]; } else { priv->default_level = index; priv->max_level = 255; } - debug("%s: done\n", __func__); + priv->cur_level = priv->default_level; + log_debug("done\n"); return 0; @@ -114,7 +232,8 @@ static int pwm_backlight_probe(struct udevice *dev) } static const struct backlight_ops pwm_backlight_ops = { - .enable = pwm_backlight_enable, + .enable = pwm_backlight_enable, + .set_brightness = pwm_backlight_set_brightness, }; static const struct udevice_id pwm_backlight_ids[] = { diff --git a/drivers/video/simple_panel.c b/drivers/video/simple_panel.c index 6c604f9..7a968e7 100644 --- a/drivers/video/simple_panel.c +++ b/drivers/video/simple_panel.c @@ -32,6 +32,21 @@ static int simple_panel_enable_backlight(struct udevice *dev) return 0; } +static int simple_panel_set_backlight(struct udevice *dev, int percent) +{ + struct simple_panel_priv *priv = dev_get_priv(dev); + int ret; + + debug("%s: start, backlight = '%s'\n", __func__, priv->backlight->name); + dm_gpio_set_value(&priv->enable, 1); + ret = backlight_set_brightness(priv->backlight, percent); + debug("%s: done, ret = %d\n", __func__, ret); + if (ret) + return ret; + + return 0; +} + static int simple_panel_ofdata_to_platdata(struct udevice *dev) { struct simple_panel_priv *priv = dev_get_priv(dev); @@ -51,7 +66,7 @@ static int simple_panel_ofdata_to_platdata(struct udevice *dev) "backlight", &priv->backlight); if (ret) { debug("%s: Cannot get backlight: ret=%d\n", __func__, ret); - return ret; + return log_ret(ret); } ret = gpio_request_by_name(dev, "enable-gpios", 0, &priv->enable, GPIOD_IS_OUT); @@ -59,7 +74,7 @@ static int simple_panel_ofdata_to_platdata(struct udevice *dev) debug("%s: Warning: cannot get enable GPIO: ret=%d\n", __func__, ret); if (ret != -ENOENT) - return ret; + return log_ret(ret); } return 0; @@ -82,6 +97,7 @@ static int simple_panel_probe(struct udevice *dev) static const struct panel_ops simple_panel_ops = { .enable_backlight = simple_panel_enable_backlight, + .set_backlight = simple_panel_set_backlight, }; static const struct udevice_id simple_panel_ids[] = { diff --git a/drivers/video/tegra124/sor.c b/drivers/video/tegra124/sor.c index 91e61b5..172bb14 100644 --- a/drivers/video/tegra124/sor.c +++ b/drivers/video/tegra124/sor.c @@ -533,7 +533,8 @@ static int tegra_dc_sor_power_up(struct udevice *dev, int is_lvds) #if DEBUG_SOR static void dump_sor_reg(struct tegra_dc_sor_data *sor) { -#define DUMP_REG(a) printk(BIOS_INFO, "%-32s %03x %08x\n", \ +#define DUMP_REG(a) printk(BIOS_INFO, \ + "%-32s %03x %08x\n", \ #a, a, tegra_sor_readl(sor, a)); DUMP_REG(SUPER_STATE0); diff --git a/drivers/video/vidconsole-uclass.c b/drivers/video/vidconsole-uclass.c index 7f95e9c..1874887 100644 --- a/drivers/video/vidconsole-uclass.c +++ b/drivers/video/vidconsole-uclass.c @@ -86,7 +86,7 @@ static int vidconsole_back(struct udevice *dev) if (priv->ycur < 0) priv->ycur = 0; } - video_sync(dev->parent); + video_sync(dev->parent, false); return 0; } @@ -113,7 +113,7 @@ static void vidconsole_newline(struct udevice *dev) } priv->last_ch = 0; - video_sync(dev->parent); + video_sync(dev->parent, false); } static const struct vid_rgb colors[VID_COLOR_COUNT] = { @@ -293,7 +293,7 @@ static void vidconsole_escape_char(struct udevice *dev, char ch) if (mode == 2) { video_clear(dev->parent); - video_sync(dev->parent); + video_sync(dev->parent, false); priv->ycur = 0; priv->xcur_frac = priv->xstart_frac; } else { @@ -449,7 +449,7 @@ static void vidconsole_putc(struct stdio_dev *sdev, const char ch) struct udevice *dev = sdev->priv; vidconsole_put_char(dev, ch); - video_sync(dev->parent); + video_sync(dev->parent, false); } static void vidconsole_puts(struct stdio_dev *sdev, const char *s) @@ -458,7 +458,7 @@ static void vidconsole_puts(struct stdio_dev *sdev, const char *s) while (*s) vidconsole_put_char(dev, *s++); - video_sync(dev->parent); + video_sync(dev->parent, false); } /* Set up the number of rows and colours (rotated drivers override this) */ @@ -511,6 +511,8 @@ void vidconsole_position_cursor(struct udevice *dev, unsigned col, unsigned row) struct udevice *vid_dev = dev->parent; struct video_priv *vid_priv = dev_get_uclass_priv(vid_dev); + col *= priv->x_charsize; + row *= priv->y_charsize; priv->xcur_frac = VID_TO_POS(min_t(short, col, vid_priv->xsize - 1)); priv->ycur = min_t(short, row, vid_priv->ysize - 1); } @@ -547,7 +549,7 @@ static int do_video_puts(cmd_tbl_t *cmdtp, int flag, int argc, for (s = argv[1]; *s; s++) vidconsole_put_char(dev, *s); - video_sync(dev->parent); + video_sync(dev->parent, false); return 0; } diff --git a/drivers/video/video-uclass.c b/drivers/video/video-uclass.c index dd08737..44dfa71 100644 --- a/drivers/video/video-uclass.c +++ b/drivers/video/video-uclass.c @@ -86,7 +86,7 @@ int video_reserve(ulong *addrp) return 0; } -void video_clear(struct udevice *dev) +int video_clear(struct udevice *dev) { struct video_priv *priv = dev_get_uclass_priv(dev); @@ -111,6 +111,8 @@ void video_clear(struct udevice *dev) memset(priv->fb, priv->colour_bg, priv->fb_size); break; } + + return 0; } void video_set_default_colors(struct video_priv *priv) @@ -128,7 +130,7 @@ void video_set_default_colors(struct video_priv *priv) } /* Flush video activity to the caches */ -void video_sync(struct udevice *vid) +void video_sync(struct udevice *vid, bool force) { /* * flush_dcache_range() is declared in common.h but it seems that some @@ -147,7 +149,7 @@ void video_sync(struct udevice *vid) struct video_priv *priv = dev_get_uclass_priv(vid); static ulong last_sync; - if (get_timer(last_sync) > 10) { + if (force || get_timer(last_sync) > 10) { sandbox_sdl_sync(priv->fb); last_sync = get_timer(0); } @@ -162,7 +164,7 @@ void video_sync_all(void) dev; uclass_find_next_device(&dev)) { if (device_active(dev)) - video_sync(dev); + video_sync(dev, true); } } diff --git a/drivers/video/video_bmp.c b/drivers/video/video_bmp.c index aeff656..1377e19 100644 --- a/drivers/video/video_bmp.c +++ b/drivers/video/video_bmp.c @@ -345,7 +345,7 @@ int video_bmp_display(struct udevice *dev, ulong bmp_image, int x, int y, break; }; - video_sync(dev); + video_sync(dev, false); return 0; } diff --git a/include/backlight.h b/include/backlight.h index a304c36..ac59eb2 100644 --- a/include/backlight.h +++ b/include/backlight.h @@ -7,6 +7,13 @@ #ifndef _BACKLIGHT_H #define _BACKLIGHT_H +enum { + BACKLIGHT_MAX = 100, + BACKLIGHT_MIN = 0, + BACKLIGHT_OFF = -1, + BACKLIGHT_DEFAULT = -2, +}; + struct backlight_ops { /** * enable() - Enable a backlight @@ -15,6 +22,15 @@ struct backlight_ops { * @return 0 if OK, -ve on error */ int (*enable)(struct udevice *dev); + + /** + * set_brightness - Set brightness + * + * @dev: Backlight device to update + * @percent: Brightness value (0 to 100, or BACKLIGHT_... value) + * @return 0 if OK, -ve on error + */ + int (*set_brightness)(struct udevice *dev, int percent); }; #define backlight_get_ops(dev) ((struct backlight_ops *)(dev)->driver->ops) @@ -27,4 +43,13 @@ struct backlight_ops { */ int backlight_enable(struct udevice *dev); +/** + * backlight_set_brightness - Set brightness + * + * @dev: Backlight device to update + * @percent: Brightness value (0 to 100, or BACKLIGHT_... value) + * @return 0 if OK, -ve on error + */ +int backlight_set_brightness(struct udevice *dev, int percent); + #endif diff --git a/include/configs/edison.h b/include/configs/edison.h index 476f5e3..86c584d 100644 --- a/include/configs/edison.h +++ b/include/configs/edison.h @@ -48,6 +48,5 @@ /* RTC */ #define CONFIG_SYS_ISA_IO_BASE_ADDRESS 0 -#define CONFIG_RTC_MC146818 #endif diff --git a/include/configs/malta.h b/include/configs/malta.h index ba3639d..520b987 100644 --- a/include/configs/malta.h +++ b/include/configs/malta.h @@ -19,7 +19,6 @@ #define CONFIG_PCNET_79C973 #define PCNET_HAS_PROM -#define CONFIG_RTC_MC146818 #define CONFIG_SYS_ISA_IO_BASE_ADDRESS 0 /* diff --git a/include/cros_ec.h b/include/cros_ec.h index 60ecefb..4771e6b 100644 --- a/include/cros_ec.h +++ b/include/cros_ec.h @@ -69,7 +69,7 @@ struct fdt_cros_ec { * @param maxlen Maximum length of the ID field * @return 0 if ok, -1 on error */ -int cros_ec_read_id(struct cros_ec_dev *dev, char *id, int maxlen); +int cros_ec_read_id(struct udevice *dev, char *id, int maxlen); /** * Read a keyboard scan from the CROS-EC device @@ -89,18 +89,19 @@ int cros_ec_scan_keyboard(struct udevice *dev, struct mbkp_keyscan *scan); * @param image Destination for image identifier * @return 0 if ok, <0 on error */ -int cros_ec_read_current_image(struct cros_ec_dev *dev, - enum ec_current_image *image); +int cros_ec_read_current_image(struct udevice *dev, + enum ec_current_image *image); /** * Read the hash of the CROS-EC device firmware. * * @param dev CROS-EC device + * @param hash_offset Offset in flash to read from * @param hash Destination for hash information * @return 0 if ok, <0 on error */ -int cros_ec_read_hash(struct cros_ec_dev *dev, - struct ec_response_vboot_hash *hash); +int cros_ec_read_hash(struct udevice *dev, uint hash_offset, + struct ec_response_vboot_hash *hash); /** * Send a reboot command to the CROS-EC device. @@ -112,8 +113,7 @@ int cros_ec_read_hash(struct cros_ec_dev *dev, * @param flags Flags for reboot command (EC_REBOOT_FLAG_*) * @return 0 if ok, <0 on error */ -int cros_ec_reboot(struct cros_ec_dev *dev, enum ec_reboot_cmd cmd, - uint8_t flags); +int cros_ec_reboot(struct udevice *dev, enum ec_reboot_cmd cmd, uint8_t flags); /** * Check if the CROS-EC device has an interrupt pending. @@ -144,7 +144,7 @@ enum { * expected), -ve if we should have an cros_ec device but failed to find * one, or init failed (-CROS_EC_ERR_...). */ -int cros_ec_init(const void *blob, struct cros_ec_dev **cros_ecp); +int cros_ec_init(const void *blob, struct udevice**cros_ecp); /** * Read information about the keyboard matrix @@ -152,8 +152,7 @@ int cros_ec_init(const void *blob, struct cros_ec_dev **cros_ecp); * @param dev CROS-EC device * @param info Place to put the info structure */ -int cros_ec_info(struct cros_ec_dev *dev, - struct ec_response_mkbp_info *info); +int cros_ec_info(struct udevice *dev, struct ec_response_mkbp_info *info); /** * Read the host event flags @@ -162,7 +161,7 @@ int cros_ec_info(struct cros_ec_dev *dev, * @param events_ptr Destination for event flags. Not changed on error. * @return 0 if ok, <0 on error */ -int cros_ec_get_host_events(struct cros_ec_dev *dev, uint32_t *events_ptr); +int cros_ec_get_host_events(struct udevice *dev, uint32_t *events_ptr); /** * Clear the specified host event flags @@ -171,7 +170,7 @@ int cros_ec_get_host_events(struct cros_ec_dev *dev, uint32_t *events_ptr); * @param events Event flags to clear * @return 0 if ok, <0 on error */ -int cros_ec_clear_host_events(struct cros_ec_dev *dev, uint32_t events); +int cros_ec_clear_host_events(struct udevice *dev, uint32_t events); /** * Get/set flash protection @@ -184,9 +183,9 @@ int cros_ec_clear_host_events(struct cros_ec_dev *dev, uint32_t events); * @param prot Destination for updated protection state from EC. * @return 0 if ok, <0 on error */ -int cros_ec_flash_protect(struct cros_ec_dev *dev, - uint32_t set_mask, uint32_t set_flags, - struct ec_response_flash_protect *resp); +int cros_ec_flash_protect(struct udevice *dev, uint32_t set_mask, + uint32_t set_flags, + struct ec_response_flash_protect *resp); /** @@ -195,7 +194,7 @@ int cros_ec_flash_protect(struct cros_ec_dev *dev, * @param dev CROS-EC device * @return 0 if ok, <0 if the test failed */ -int cros_ec_test(struct cros_ec_dev *dev); +int cros_ec_test(struct udevice *dev); /** * Update the EC RW copy. @@ -205,17 +204,15 @@ int cros_ec_test(struct cros_ec_dev *dev); * @param imafge_size content length * @return 0 if ok, <0 if the test failed */ -int cros_ec_flash_update_rw(struct cros_ec_dev *dev, - const uint8_t *image, int image_size); +int cros_ec_flash_update_rw(struct udevice *dev, const uint8_t *image, + int image_size); /** * Return a pointer to the board's CROS-EC device * - * This should be implemented by board files. - * * @return pointer to CROS-EC device, or NULL if none is available */ -struct cros_ec_dev *board_get_cros_ec_dev(void); +struct udevice *board_get_cros_ec_dev(void); struct dm_cros_ec_ops { int (*check_version)(struct udevice *dev); @@ -249,8 +246,7 @@ void cros_ec_dump_data(const char *name, int cmd, const uint8_t *data, int len); */ int cros_ec_calc_checksum(const uint8_t *data, int size); -int cros_ec_flash_erase(struct cros_ec_dev *dev, uint32_t offset, - uint32_t size); +int cros_ec_flash_erase(struct udevice *dev, uint32_t offset, uint32_t size); /** * Read data from the flash @@ -267,8 +263,8 @@ int cros_ec_flash_erase(struct cros_ec_dev *dev, uint32_t offset, * @param size Number of bytes to read * @return 0 if ok, -1 on error */ -int cros_ec_flash_read(struct cros_ec_dev *dev, uint8_t *data, uint32_t offset, - uint32_t size); +int cros_ec_flash_read(struct udevice *dev, uint8_t *data, uint32_t offset, + uint32_t size); /** * Read back flash parameters @@ -278,8 +274,8 @@ int cros_ec_flash_read(struct cros_ec_dev *dev, uint8_t *data, uint32_t offset, * @param dev Pointer to device * @param info Pointer to output flash info struct */ -int cros_ec_read_flashinfo(struct cros_ec_dev *dev, - struct ec_response_flash_info *info); +int cros_ec_read_flashinfo(struct udevice *dev, + struct ec_response_flash_info *info); /** * Write data to the flash @@ -299,8 +295,8 @@ int cros_ec_read_flashinfo(struct cros_ec_dev *dev, * @param size Number of bytes to write * @return 0 if ok, -1 on error */ -int cros_ec_flash_write(struct cros_ec_dev *dev, const uint8_t *data, - uint32_t offset, uint32_t size); +int cros_ec_flash_write(struct udevice *dev, const uint8_t *data, + uint32_t offset, uint32_t size); /** * Obtain position and size of a flash region @@ -311,18 +307,18 @@ int cros_ec_flash_write(struct cros_ec_dev *dev, const uint8_t *data, * @param size Returns size of flash region * @return 0 if ok, -1 on error */ -int cros_ec_flash_offset(struct cros_ec_dev *dev, enum ec_flash_region region, - uint32_t *offset, uint32_t *size); +int cros_ec_flash_offset(struct udevice *dev, enum ec_flash_region region, + uint32_t *offset, uint32_t *size); /** - * Read/write VbNvContext from/to a CROS-EC device. + * Read/write non-volatile data from/to a CROS-EC device. * * @param dev CROS-EC device * @param block Buffer of VbNvContext to be read/write * @return 0 if ok, -1 on error */ -int cros_ec_read_vbnvcontext(struct cros_ec_dev *dev, uint8_t *block); -int cros_ec_write_vbnvcontext(struct cros_ec_dev *dev, const uint8_t *block); +int cros_ec_read_nvdata(struct udevice *dev, uint8_t *block, int size); +int cros_ec_write_nvdata(struct udevice *dev, const uint8_t *block, int size); /** * Read the version information for the EC images @@ -331,8 +327,8 @@ int cros_ec_write_vbnvcontext(struct cros_ec_dev *dev, const uint8_t *block); * @param versionp This is set to point to the version information * @return 0 if ok, -1 on error */ -int cros_ec_read_version(struct cros_ec_dev *dev, - struct ec_response_get_version **versionp); +int cros_ec_read_version(struct udevice *dev, + struct ec_response_get_version **versionp); /** * Read the build information for the EC @@ -341,7 +337,7 @@ int cros_ec_read_version(struct cros_ec_dev *dev, * @param versionp This is set to point to the build string * @return 0 if ok, -1 on error */ -int cros_ec_read_build_info(struct cros_ec_dev *dev, char **strp); +int cros_ec_read_build_info(struct udevice *dev, char **strp); /** * Switch on/off a LDO / FET. @@ -387,7 +383,7 @@ int cros_ec_decode_ec_flash(struct udevice *dev, struct fdt_cros_ec *config); * * @param ec CROS-EC device */ -void cros_ec_check_keyboard(struct cros_ec_dev *dev); +void cros_ec_check_keyboard(struct udevice *dev); struct i2c_msg; /* diff --git a/include/dm/device.h b/include/dm/device.h index 9812d86..8479344 100644 --- a/include/dm/device.h +++ b/include/dm/device.h @@ -270,7 +270,7 @@ struct driver { * @dev Device to check * @return platform data, or NULL if none */ -void *dev_get_platdata(struct udevice *dev); +void *dev_get_platdata(const struct udevice *dev); /** * dev_get_parent_platdata() - Get the parent platform data for a device @@ -280,7 +280,7 @@ void *dev_get_platdata(struct udevice *dev); * @dev Device to check * @return parent's platform data, or NULL if none */ -void *dev_get_parent_platdata(struct udevice *dev); +void *dev_get_parent_platdata(const struct udevice *dev); /** * dev_get_uclass_platdata() - Get the uclass platform data for a device @@ -290,7 +290,7 @@ void *dev_get_parent_platdata(struct udevice *dev); * @dev Device to check * @return uclass's platform data, or NULL if none */ -void *dev_get_uclass_platdata(struct udevice *dev); +void *dev_get_uclass_platdata(const struct udevice *dev); /** * dev_get_priv() - Get the private data for a device @@ -300,7 +300,7 @@ void *dev_get_uclass_platdata(struct udevice *dev); * @dev Device to check * @return private data, or NULL if none */ -void *dev_get_priv(struct udevice *dev); +void *dev_get_priv(const struct udevice *dev); /** * dev_get_parent_priv() - Get the parent private data for a device @@ -314,7 +314,7 @@ void *dev_get_priv(struct udevice *dev); * @dev Device to check * @return parent data, or NULL if none */ -void *dev_get_parent_priv(struct udevice *dev); +void *dev_get_parent_priv(const struct udevice *dev); /** * dev_get_uclass_priv() - Get the private uclass data for a device @@ -324,7 +324,7 @@ void *dev_get_parent_priv(struct udevice *dev); * @dev Device to check * @return private uclass data for this device, or NULL if none */ -void *dev_get_uclass_priv(struct udevice *dev); +void *dev_get_uclass_priv(const struct udevice *dev); /** * struct dev_get_parent() - Get the parent of a device @@ -332,7 +332,7 @@ void *dev_get_uclass_priv(struct udevice *dev); * @child: Child to check * @return parent of child, or NULL if this is the root device */ -struct udevice *dev_get_parent(struct udevice *child); +struct udevice *dev_get_parent(const struct udevice *child); /** * dev_get_driver_data() - get the driver data used to bind a device @@ -359,7 +359,7 @@ struct udevice *dev_get_parent(struct udevice *child); * @dev: Device to check * @return driver data (0 if none is provided) */ -ulong dev_get_driver_data(struct udevice *dev); +ulong dev_get_driver_data(const struct udevice *dev); /** * dev_get_driver_ops() - get the device's driver's operations @@ -370,7 +370,7 @@ ulong dev_get_driver_data(struct udevice *dev); * @dev: Device to check * @return void pointer to driver's operations or NULL for NULL-dev or NULL-ops */ -const void *dev_get_driver_ops(struct udevice *dev); +const void *dev_get_driver_ops(const struct udevice *dev); /** * device_get_uclass_id() - return the uclass ID of a device @@ -378,7 +378,7 @@ const void *dev_get_driver_ops(struct udevice *dev); * @dev: Device to check * @return uclass ID for the device */ -enum uclass_id device_get_uclass_id(struct udevice *dev); +enum uclass_id device_get_uclass_id(const struct udevice *dev); /** * dev_get_uclass_name() - return the uclass name of a device @@ -388,7 +388,7 @@ enum uclass_id device_get_uclass_id(struct udevice *dev); * @dev: Device to check * @return pointer to the uclass name for the device */ -const char *dev_get_uclass_name(struct udevice *dev); +const char *dev_get_uclass_name(const struct udevice *dev); /** * device_get_child() - Get the child of a device by index @@ -520,12 +520,27 @@ int device_find_first_child(struct udevice *parent, struct udevice **devp); int device_find_next_child(struct udevice **devp); /** + * device_find_first_inactive_child() - Find the first inactive child + * + * This is used to locate an existing child of a device which is of a given + * uclass. + * + * @parent: Parent device to search + * @uclass_id: Uclass to look for + * @devp: Returns device found, if any + * @return 0 if found, else -ENODEV + */ +int device_find_first_inactive_child(struct udevice *parent, + enum uclass_id uclass_id, + struct udevice **devp); + +/** * device_has_children() - check if a device has any children * * @dev: Device to check * @return true if the device has one or more children */ -bool device_has_children(struct udevice *dev); +bool device_has_children(const struct udevice *dev); /** * device_has_active_children() - check if a device has any active children diff --git a/include/dm/of_extra.h b/include/dm/of_extra.h index 97988b6..ca15df2 100644 --- a/include/dm/of_extra.h +++ b/include/dm/of_extra.h @@ -11,7 +11,7 @@ enum fmap_compress_t { FMAP_COMPRESS_NONE, - FMAP_COMPRESS_LZO, + FMAP_COMPRESS_LZ4, }; enum fmap_hash_t { @@ -26,6 +26,7 @@ struct fmap_entry { uint32_t length; uint32_t used; /* Number of bytes used in region */ enum fmap_compress_t compress_algo; /* Compression type */ + uint32_t unc_length; /* Uncompressed length */ enum fmap_hash_t hash_algo; /* Hash algorithm */ const uint8_t *hash; /* Hash value */ int hash_size; /* Hash size */ diff --git a/include/dm/uclass.h b/include/dm/uclass.h index 6e7c1cd..eebf2d5 100644 --- a/include/dm/uclass.h +++ b/include/dm/uclass.h @@ -44,6 +44,9 @@ struct udevice; /* Members of this uclass sequence themselves with aliases */ #define DM_UC_FLAG_SEQ_ALIAS (1 << 0) +/* Same as DM_FLAG_ALLOC_PRIV_DMA */ +#define DM_UC_FLAG_ALLOC_PRIV_DMA (1 << 5) + /** * struct uclass_driver - Driver for the uclass * diff --git a/include/ec_commands.h b/include/ec_commands.h index 7605066..392c1f1 100644 --- a/include/ec_commands.h +++ b/include/ec_commands.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2013 The Chromium OS Authors. All rights reserved. +/* Copyright (c) 2018 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. */ @@ -27,7 +27,13 @@ * On I2C, all bytes are sent serially in the same message. */ -/* Current version of this protocol */ +/* + * Current version of this protocol + * + * TODO(crosbug.com/p/11223): This is effectively useless; protocol is + * determined in other ways. Remove this once the kernel code no longer + * depends on it. + */ #define EC_PROTO_VERSION 0x00000002 /* Command version mask */ @@ -70,18 +76,22 @@ #define EC_MEMMAP_TEXT_MAX 8 /* Size of a string in the memory map */ /* The offset address of each type of data in mapped memory. */ -#define EC_MEMMAP_TEMP_SENSOR 0x00 /* Temp sensors */ -#define EC_MEMMAP_FAN 0x10 /* Fan speeds */ -#define EC_MEMMAP_TEMP_SENSOR_B 0x18 /* Temp sensors (second set) */ -#define EC_MEMMAP_ID 0x20 /* 'E' 'C' */ +#define EC_MEMMAP_TEMP_SENSOR 0x00 /* Temp sensors 0x00 - 0x0f */ +#define EC_MEMMAP_FAN 0x10 /* Fan speeds 0x10 - 0x17 */ +#define EC_MEMMAP_TEMP_SENSOR_B 0x18 /* More temp sensors 0x18 - 0x1f */ +#define EC_MEMMAP_ID 0x20 /* 0x20 == 'E', 0x21 == 'C' */ #define EC_MEMMAP_ID_VERSION 0x22 /* Version of data in 0x20 - 0x2f */ #define EC_MEMMAP_THERMAL_VERSION 0x23 /* Version of data in 0x00 - 0x1f */ #define EC_MEMMAP_BATTERY_VERSION 0x24 /* Version of data in 0x40 - 0x7f */ #define EC_MEMMAP_SWITCHES_VERSION 0x25 /* Version of data in 0x30 - 0x33 */ #define EC_MEMMAP_EVENTS_VERSION 0x26 /* Version of data in 0x34 - 0x3f */ -#define EC_MEMMAP_HOST_CMD_FLAGS 0x27 /* Host command interface flags */ -#define EC_MEMMAP_SWITCHES 0x30 -#define EC_MEMMAP_HOST_EVENTS 0x34 +#define EC_MEMMAP_HOST_CMD_FLAGS 0x27 /* Host cmd interface flags (8 bits) */ +/* Unused 0x28 - 0x2f */ +#define EC_MEMMAP_SWITCHES 0x30 /* 8 bits */ +/* Unused 0x31 - 0x33 */ +#define EC_MEMMAP_HOST_EVENTS 0x34 /* 32 bits */ +/* Reserve 0x38 - 0x3f for additional host event-related stuff */ +/* Battery values are all 32 bits */ #define EC_MEMMAP_BATT_VOLT 0x40 /* Battery Present Voltage */ #define EC_MEMMAP_BATT_RATE 0x44 /* Battery Present Rate */ #define EC_MEMMAP_BATT_CAP 0x48 /* Battery Remaining Capacity */ @@ -90,10 +100,33 @@ #define EC_MEMMAP_BATT_DVLT 0x54 /* Battery Design Voltage */ #define EC_MEMMAP_BATT_LFCC 0x58 /* Battery Last Full Charge Capacity */ #define EC_MEMMAP_BATT_CCNT 0x5c /* Battery Cycle Count */ +/* Strings are all 8 bytes (EC_MEMMAP_TEXT_MAX) */ #define EC_MEMMAP_BATT_MFGR 0x60 /* Battery Manufacturer String */ #define EC_MEMMAP_BATT_MODEL 0x68 /* Battery Model Number String */ #define EC_MEMMAP_BATT_SERIAL 0x70 /* Battery Serial Number String */ #define EC_MEMMAP_BATT_TYPE 0x78 /* Battery Type String */ +#define EC_MEMMAP_ALS 0x80 /* ALS readings in lux (2 X 16 bits) */ +/* Unused 0x84 - 0x8f */ +#define EC_MEMMAP_ACC_STATUS 0x90 /* Accelerometer status (8 bits )*/ +/* Unused 0x91 */ +#define EC_MEMMAP_ACC_DATA 0x92 /* Accelerometers data 0x92 - 0x9f */ +/* 0x92: Lid Angle if available, LID_ANGLE_UNRELIABLE otherwise */ +/* 0x94 - 0x99: 1st Accelerometer */ +/* 0x9a - 0x9f: 2nd Accelerometer */ +#define EC_MEMMAP_GYRO_DATA 0xa0 /* Gyroscope data 0xa0 - 0xa5 */ +/* Unused 0xa6 - 0xdf */ + +/* + * ACPI is unable to access memory mapped data at or above this offset due to + * limitations of the ACPI protocol. Do not place data in the range 0xe0 - 0xfe + * which might be needed by ACPI. + */ +#define EC_MEMMAP_NO_ACPI 0xe0 + +/* Define the format of the accelerometer mapped memory status byte. */ +#define EC_MEMMAP_ACC_STATUS_SAMPLE_ID_MASK 0x0f +#define EC_MEMMAP_ACC_STATUS_BUSY_BIT (1 << 4) +#define EC_MEMMAP_ACC_STATUS_PRESENCE_BIT (1 << 7) /* Number of temp sensors at EC_MEMMAP_TEMP_SENSOR */ #define EC_TEMP_SENSOR_ENTRIES 16 @@ -103,6 +136,8 @@ * Valid only if EC_MEMMAP_THERMAL_VERSION returns >= 2. */ #define EC_TEMP_SENSOR_B_ENTRIES 8 + +/* Special values for mapped temperature sensors */ #define EC_TEMP_SENSOR_NOT_PRESENT 0xff #define EC_TEMP_SENSOR_ERROR 0xfe #define EC_TEMP_SENSOR_NOT_POWERED 0xfd @@ -113,6 +148,18 @@ */ #define EC_TEMP_SENSOR_OFFSET 200 +/* + * Number of ALS readings at EC_MEMMAP_ALS + */ +#define EC_ALS_ENTRIES 2 + +/* + * The default value a temperature sensor will return when it is present but + * has not been read this boot. This is a reasonable number to avoid + * triggering alarms on the host. + */ +#define EC_TEMP_SENSOR_DEFAULT (296 - EC_TEMP_SENSOR_OFFSET) + #define EC_FAN_SPEED_ENTRIES 4 /* Number of fans at EC_MEMMAP_FAN */ #define EC_FAN_SPEED_NOT_PRESENT 0xffff /* Entry not present */ #define EC_FAN_SPEED_STALLED 0xfffe /* Fan stalled */ @@ -142,9 +189,158 @@ #define EC_HOST_CMD_FLAG_VERSION_3 0x02 /* Wireless switch flags */ -#define EC_WIRELESS_SWITCH_WLAN 0x01 -#define EC_WIRELESS_SWITCH_BLUETOOTH 0x02 -#define EC_WIRELESS_SWITCH_WWAN 0x04 +#define EC_WIRELESS_SWITCH_ALL ~0x00 /* All flags */ +#define EC_WIRELESS_SWITCH_WLAN 0x01 /* WLAN radio */ +#define EC_WIRELESS_SWITCH_BLUETOOTH 0x02 /* Bluetooth radio */ +#define EC_WIRELESS_SWITCH_WWAN 0x04 /* WWAN power */ +#define EC_WIRELESS_SWITCH_WLAN_POWER 0x08 /* WLAN power */ + +/*****************************************************************************/ +/* + * ACPI commands + * + * These are valid ONLY on the ACPI command/data port. + */ + +/* + * ACPI Read Embedded Controller + * + * This reads from ACPI memory space on the EC (EC_ACPI_MEM_*). + * + * Use the following sequence: + * + * - Write EC_CMD_ACPI_READ to EC_LPC_ADDR_ACPI_CMD + * - Wait for EC_LPC_CMDR_PENDING bit to clear + * - Write address to EC_LPC_ADDR_ACPI_DATA + * - Wait for EC_LPC_CMDR_DATA bit to set + * - Read value from EC_LPC_ADDR_ACPI_DATA + */ +#define EC_CMD_ACPI_READ 0x0080 + +/* + * ACPI Write Embedded Controller + * + * This reads from ACPI memory space on the EC (EC_ACPI_MEM_*). + * + * Use the following sequence: + * + * - Write EC_CMD_ACPI_WRITE to EC_LPC_ADDR_ACPI_CMD + * - Wait for EC_LPC_CMDR_PENDING bit to clear + * - Write address to EC_LPC_ADDR_ACPI_DATA + * - Wait for EC_LPC_CMDR_PENDING bit to clear + * - Write value to EC_LPC_ADDR_ACPI_DATA + */ +#define EC_CMD_ACPI_WRITE 0x0081 + +/* + * ACPI Burst Enable Embedded Controller + * + * This enables burst mode on the EC to allow the host to issue several + * commands back-to-back. While in this mode, writes to mapped multi-byte + * data are locked out to ensure data consistency. + */ +#define EC_CMD_ACPI_BURST_ENABLE 0x0082 + +/* + * ACPI Burst Disable Embedded Controller + * + * This disables burst mode on the EC and stops preventing EC writes to mapped + * multi-byte data. + */ +#define EC_CMD_ACPI_BURST_DISABLE 0x0083 + +/* + * ACPI Query Embedded Controller + * + * This clears the lowest-order bit in the currently pending host events, and + * sets the result code to the 1-based index of the bit (event 0x00000001 = 1, + * event 0x80000000 = 32), or 0 if no event was pending. + */ +#define EC_CMD_ACPI_QUERY_EVENT 0x0084 + +/* Valid addresses in ACPI memory space, for read/write commands */ + +/* Memory space version; set to EC_ACPI_MEM_VERSION_CURRENT */ +#define EC_ACPI_MEM_VERSION 0x00 +/* + * Test location; writing value here updates test compliment byte to (0xff - + * value). + */ +#define EC_ACPI_MEM_TEST 0x01 +/* Test compliment; writes here are ignored. */ +#define EC_ACPI_MEM_TEST_COMPLIMENT 0x02 + +/* Keyboard backlight brightness percent (0 - 100) */ +#define EC_ACPI_MEM_KEYBOARD_BACKLIGHT 0x03 +/* DPTF Target Fan Duty (0-100, 0xff for auto/none) */ +#define EC_ACPI_MEM_FAN_DUTY 0x04 + +/* + * DPTF temp thresholds. Any of the EC's temp sensors can have up to two + * independent thresholds attached to them. The current value of the ID + * register determines which sensor is affected by the THRESHOLD and COMMIT + * registers. The THRESHOLD register uses the same EC_TEMP_SENSOR_OFFSET scheme + * as the memory-mapped sensors. The COMMIT register applies those settings. + * + * The spec does not mandate any way to read back the threshold settings + * themselves, but when a threshold is crossed the AP needs a way to determine + * which sensor(s) are responsible. Each reading of the ID register clears and + * returns one sensor ID that has crossed one of its threshold (in either + * direction) since the last read. A value of 0xFF means "no new thresholds + * have tripped". Setting or enabling the thresholds for a sensor will clear + * the unread event count for that sensor. + */ +#define EC_ACPI_MEM_TEMP_ID 0x05 +#define EC_ACPI_MEM_TEMP_THRESHOLD 0x06 +#define EC_ACPI_MEM_TEMP_COMMIT 0x07 +/* + * Here are the bits for the COMMIT register: + * bit 0 selects the threshold index for the chosen sensor (0/1) + * bit 1 enables/disables the selected threshold (0 = off, 1 = on) + * Each write to the commit register affects one threshold. + */ +#define EC_ACPI_MEM_TEMP_COMMIT_SELECT_MASK (1 << 0) +#define EC_ACPI_MEM_TEMP_COMMIT_ENABLE_MASK (1 << 1) +/* + * Example: + * + * Set the thresholds for sensor 2 to 50 C and 60 C: + * write 2 to [0x05] -- select temp sensor 2 + * write 0x7b to [0x06] -- C_TO_K(50) - EC_TEMP_SENSOR_OFFSET + * write 0x2 to [0x07] -- enable threshold 0 with this value + * write 0x85 to [0x06] -- C_TO_K(60) - EC_TEMP_SENSOR_OFFSET + * write 0x3 to [0x07] -- enable threshold 1 with this value + * + * Disable the 60 C threshold, leaving the 50 C threshold unchanged: + * write 2 to [0x05] -- select temp sensor 2 + * write 0x1 to [0x07] -- disable threshold 1 + */ + +/* DPTF battery charging current limit */ +#define EC_ACPI_MEM_CHARGING_LIMIT 0x08 + +/* Charging limit is specified in 64 mA steps */ +#define EC_ACPI_MEM_CHARGING_LIMIT_STEP_MA 64 +/* Value to disable DPTF battery charging limit */ +#define EC_ACPI_MEM_CHARGING_LIMIT_DISABLED 0xff + +/* + * Report device orientation + * bit 0 device is tablet mode + */ +#define EC_ACPI_MEM_DEVICE_ORIENTATION 0x09 +#define EC_ACPI_MEM_DEVICE_TABLET_MODE 0x01 + +/* + * ACPI addresses 0x20 - 0xff map to EC_MEMMAP offset 0x00 - 0xdf. This data + * is read-only from the AP. Added in EC_ACPI_MEM_VERSION 2. + */ +#define EC_ACPI_MEM_MAPPED_BEGIN 0x20 +#define EC_ACPI_MEM_MAPPED_SIZE 0xe0 + +/* Current version of ACPI memory address space */ +#define EC_ACPI_MEM_VERSION_CURRENT 2 + /* * This header file is used in coreboot both in C and ACPI code. The ACPI code @@ -161,6 +357,92 @@ #define __packed __attribute__((packed)) #endif +#ifndef __aligned +#define __aligned(x) __attribute__((aligned(x))) +#endif + +/* + * Attributes for EC request and response packets. Just defining __packed + * results in inefficient assembly code on ARM, if the structure is actually + * 32-bit aligned, as it should be for all buffers. + * + * Be very careful when adding these to existing structures. They will round + * up the structure size to the specified boundary. + * + * Also be very careful to make that if a structure is included in some other + * parent structure that the alignment will still be true given the packing of + * the parent structure. This is particularly important if the sub-structure + * will be passed as a pointer to another function, since that function will + * not know about the misaligment caused by the parent structure's packing. + * + * Also be very careful using __packed - particularly when nesting non-packed + * structures inside packed ones. In fact, DO NOT use __packed directly; + * always use one of these attributes. + * + * Once everything is annotated properly, the following search strings should + * not return ANY matches in this file other than right here: + * + * "__packed" - generates inefficient code; all sub-structs must also be packed + * + * "struct [^_]" - all structs should be annotated, except for structs that are + * members of other structs/unions (and their original declarations should be + * annotated). + */ +#ifdef CONFIG_HOSTCMD_ALIGNED + +/* + * Packed structures where offset and size are always aligned to 1, 2, or 4 + * byte boundary. + */ +#define __ec_align1 __packed +#define __ec_align2 __packed __aligned(2) +#define __ec_align4 __packed __aligned(4) + +/* + * Packed structure which must be under-aligned, because its size is not a + * 4-byte multiple. This is sub-optimal because it forces byte-wise access + * of all multi-byte fields in it, even though they are themselves aligned. + * + * In theory, we could duplicate the structure with __aligned(4) for accessing + * its members, but use the __packed version for sizeof(). + */ +#define __ec_align_size1 __packed + +/* + * Packed structure which must be under-aligned, because its offset inside a + * parent structure is not a 4-byte multiple. + */ +#define __ec_align_offset1 __packed +#define __ec_align_offset2 __packed __aligned(2) + +/* + * Structures which are complicated enough that I'm skipping them on the first + * pass. They are effectively unchanged from their previous definitions. + * + * TODO(rspangler): Figure out what to do with these. It's likely necessary + * to work out the size and offset of each member and add explicit padding to + * maintain those. + */ +#define __ec_todo_packed __packed +#define __ec_todo_unpacked + +#else /* !CONFIG_HOSTCMD_ALIGNED */ + +/* + * Packed structures make no assumption about alignment, so they do inefficient + * byte-wise reads. + */ +#define __ec_align1 __packed +#define __ec_align2 __packed +#define __ec_align4 __packed +#define __ec_align_size1 __packed +#define __ec_align_offset1 __packed +#define __ec_align_offset2 __packed +#define __ec_todo_packed __packed +#define __ec_todo_unpacked + +#endif /* !CONFIG_HOSTCMD_ALIGNED */ + /* LPC command status byte masks */ /* EC has written a byte in the data register and host hasn't read it yet */ #define EC_LPC_STATUS_TO_HOST 0x01 @@ -170,7 +452,7 @@ #define EC_LPC_STATUS_PROCESSING 0x04 /* Last write to EC was a command, not data */ #define EC_LPC_STATUS_LAST_CMD 0x08 -/* EC is in burst mode. Unsupported by Chrome EC, so this bit is never set */ +/* EC is in burst mode */ #define EC_LPC_STATUS_BURST_MODE 0x10 /* SCI event is pending (requesting SCI query) */ #define EC_LPC_STATUS_SCI_PENDING 0x20 @@ -186,7 +468,9 @@ #define EC_LPC_STATUS_BUSY_MASK \ (EC_LPC_STATUS_FROM_HOST | EC_LPC_STATUS_PROCESSING) -/* Host command response codes */ +/* Host command response codes (16-bit). Note that response codes should be + * stored in a uint16_t rather than directly in a value of this type. + */ enum ec_status { EC_RES_SUCCESS = 0, EC_RES_INVALID_COMMAND = 1, @@ -202,7 +486,9 @@ enum ec_status { EC_RES_OVERFLOW = 11, /* Table / data overflow */ EC_RES_INVALID_HEADER = 12, /* Header contains invalid data */ EC_RES_REQUEST_TRUNCATED = 13, /* Didn't get the entire request */ - EC_RES_RESPONSE_TOO_BIG = 14 /* Response was too big to handle */ + EC_RES_RESPONSE_TOO_BIG = 14, /* Response was too big to handle */ + EC_RES_BUS_ERROR = 15, /* Communications bus error */ + EC_RES_BUSY = 16 /* Up but too busy. Should retry */ }; /* @@ -222,7 +508,8 @@ enum host_event_code { EC_HOST_EVENT_BATTERY_CRITICAL = 7, EC_HOST_EVENT_BATTERY = 8, EC_HOST_EVENT_THERMAL_THRESHOLD = 9, - EC_HOST_EVENT_THERMAL_OVERLOAD = 10, + /* Event generated by a device attached to the EC */ + EC_HOST_EVENT_DEVICE = 10, EC_HOST_EVENT_THERMAL = 11, EC_HOST_EVENT_USB_CHARGER = 12, EC_HOST_EVENT_KEY_PRESSED = 13, @@ -240,6 +527,49 @@ enum host_event_code { /* Shutdown due to battery level too low */ EC_HOST_EVENT_BATTERY_SHUTDOWN = 17, + /* Suggest that the AP throttle itself */ + EC_HOST_EVENT_THROTTLE_START = 18, + /* Suggest that the AP resume normal speed */ + EC_HOST_EVENT_THROTTLE_STOP = 19, + + /* Hang detect logic detected a hang and host event timeout expired */ + EC_HOST_EVENT_HANG_DETECT = 20, + /* Hang detect logic detected a hang and warm rebooted the AP */ + EC_HOST_EVENT_HANG_REBOOT = 21, + + /* PD MCU triggering host event */ + EC_HOST_EVENT_PD_MCU = 22, + + /* Battery Status flags have changed */ + EC_HOST_EVENT_BATTERY_STATUS = 23, + + /* EC encountered a panic, triggering a reset */ + EC_HOST_EVENT_PANIC = 24, + + /* Keyboard fastboot combo has been pressed */ + EC_HOST_EVENT_KEYBOARD_FASTBOOT = 25, + + /* EC RTC event occurred */ + EC_HOST_EVENT_RTC = 26, + + /* Emulate MKBP event */ + EC_HOST_EVENT_MKBP = 27, + + /* EC desires to change state of host-controlled USB mux */ + EC_HOST_EVENT_USB_MUX = 28, + + /* TABLET/LAPTOP mode event*/ + EC_HOST_EVENT_MODE_CHANGE = 29, + + /* Keyboard recovery combo with hardware reinitialization */ + EC_HOST_EVENT_KEYBOARD_RECOVERY_HW_REINIT = 30, + + /* + * Reserve this last bit to indicate that at least one bit in a + * secondary host event word is set. See crbug.com/633646. + */ + EC_HOST_EVENT_EXTENDED = 31, + /* * The high bit of the event mask is not used as a host event code. If * it reads back as set, then the entire event mask should be @@ -250,10 +580,10 @@ enum host_event_code { EC_HOST_EVENT_INVALID = 32 }; /* Host event mask */ -#define EC_HOST_EVENT_MASK(event_code) (1UL << ((event_code) - 1)) +#define EC_HOST_EVENT_MASK(event_code) (1ULL << ((event_code) - 1)) /* Arguments at EC_LPC_ADDR_HOST_ARGS */ -struct ec_lpc_host_args { +struct __ec_align4 ec_lpc_host_args { uint8_t flags; uint8_t command_version; uint8_t data_size; @@ -262,7 +592,7 @@ struct ec_lpc_host_args { * all params/response data bytes. */ uint8_t checksum; -} __packed; +}; /* Flags for ec_lpc_host_args.flags */ /* @@ -272,7 +602,7 @@ struct ec_lpc_host_args { * If EC gets a command and this flag is not set, this is an old-style command. * Command version is 0 and params from host are at EC_LPC_ADDR_OLD_PARAM with * unknown length. EC must respond with an old-style response (that is, - * withouth setting EC_HOST_ARGS_FLAG_TO_HOST). + * without setting EC_HOST_ARGS_FLAG_TO_HOST). */ #define EC_HOST_ARGS_FLAG_FROM_HOST 0x01 /* @@ -285,6 +615,89 @@ struct ec_lpc_host_args { #define EC_HOST_ARGS_FLAG_TO_HOST 0x02 /*****************************************************************************/ +/* + * Byte codes returned by EC over SPI interface. + * + * These can be used by the AP to debug the EC interface, and to determine + * when the EC is not in a state where it will ever get around to responding + * to the AP. + * + * Example of sequence of bytes read from EC for a current good transfer: + * 1. - - AP asserts chip select (CS#) + * 2. EC_SPI_OLD_READY - AP sends first byte(s) of request + * 3. - - EC starts handling CS# interrupt + * 4. EC_SPI_RECEIVING - AP sends remaining byte(s) of request + * 5. EC_SPI_PROCESSING - EC starts processing request; AP is clocking in + * bytes looking for EC_SPI_FRAME_START + * 6. - - EC finishes processing and sets up response + * 7. EC_SPI_FRAME_START - AP reads frame byte + * 8. (response packet) - AP reads response packet + * 9. EC_SPI_PAST_END - Any additional bytes read by AP + * 10 - - AP deasserts chip select + * 11 - - EC processes CS# interrupt and sets up DMA for + * next request + * + * If the AP is waiting for EC_SPI_FRAME_START and sees any value other than + * the following byte values: + * EC_SPI_OLD_READY + * EC_SPI_RX_READY + * EC_SPI_RECEIVING + * EC_SPI_PROCESSING + * + * Then the EC found an error in the request, or was not ready for the request + * and lost data. The AP should give up waiting for EC_SPI_FRAME_START, + * because the EC is unable to tell when the AP is done sending its request. + */ + +/* + * Framing byte which precedes a response packet from the EC. After sending a + * request, the AP will clock in bytes until it sees the framing byte, then + * clock in the response packet. + */ +#define EC_SPI_FRAME_START 0xec + +/* + * Padding bytes which are clocked out after the end of a response packet. + */ +#define EC_SPI_PAST_END 0xed + +/* + * EC is ready to receive, and has ignored the byte sent by the AP. EC expects + * that the AP will send a valid packet header (starting with + * EC_COMMAND_PROTOCOL_3) in the next 32 bytes. + */ +#define EC_SPI_RX_READY 0xf8 + +/* + * EC has started receiving the request from the AP, but hasn't started + * processing it yet. + */ +#define EC_SPI_RECEIVING 0xf9 + +/* EC has received the entire request from the AP and is processing it. */ +#define EC_SPI_PROCESSING 0xfa + +/* + * EC received bad data from the AP, such as a packet header with an invalid + * length. EC will ignore all data until chip select deasserts. + */ +#define EC_SPI_RX_BAD_DATA 0xfb + +/* + * EC received data from the AP before it was ready. That is, the AP asserted + * chip select and started clocking data before the EC was ready to receive it. + * EC will ignore all data until chip select deasserts. + */ +#define EC_SPI_NOT_READY 0xfc + +/* + * EC was ready to receive a request from the AP. EC has treated the byte sent + * by the AP as part of a request packet, or (for old-style ECs) is processing + * a fully received packet but is not ready to respond yet. + */ +#define EC_SPI_OLD_READY 0xfd + +/*****************************************************************************/ /* * Protocol version 2 for I2C and SPI send a request this way: @@ -332,8 +745,8 @@ struct ec_lpc_host_args { #define EC_HOST_REQUEST_VERSION 3 /* Version 3 request from host */ -struct ec_host_request { - /* Struct version (=3) +struct __ec_align4 ec_host_request { + /* Structure version (=3) * * EC will return EC_RES_INVALID_HEADER if it receives a header with a * version it doesn't know how to parse. @@ -357,13 +770,13 @@ struct ec_host_request { /* Length of data which follows this header */ uint16_t data_len; -} __packed; +}; #define EC_HOST_RESPONSE_VERSION 3 /* Version 3 response from EC */ -struct ec_host_response { - /* Struct version (=3) */ +struct __ec_align4 ec_host_response { + /* Structure version (=3) */ uint8_t struct_version; /* @@ -380,18 +793,21 @@ struct ec_host_response { /* Unused bytes in current protocol version; set to 0 */ uint16_t reserved; -} __packed; +}; /*****************************************************************************/ /* * Notes on commands: * - * Each command is an 8-byte command value. Commands which take params or - * return response data specify structs for that data. If no struct is + * Each command is an 16-bit command value. Commands which take params or + * return response data specify structures for that data. If no structure is * specified, the command does not input or output data, respectively. * Parameter/response length is implicit in the structs. Some underlying * communication protocols (I2C, SPI) may add length or checksum headers, but * those are implementation-dependent and not defined here. + * + * All commands MUST be #defined to be 4-digit UPPER CASE hex values + * (e.g., 0x00AB, not 0xab) for CONFIG_HOSTCMD_SECTION_SORTED to work. */ /*****************************************************************************/ @@ -401,28 +817,28 @@ struct ec_host_response { * Get protocol version, used to deal with non-backward compatible protocol * changes. */ -#define EC_CMD_PROTO_VERSION 0x00 +#define EC_CMD_PROTO_VERSION 0x0000 -struct ec_response_proto_version { +struct __ec_align4 ec_response_proto_version { uint32_t version; -} __packed; +}; /* * Hello. This is a simple command to test the EC is responsive to * commands. */ -#define EC_CMD_HELLO 0x01 +#define EC_CMD_HELLO 0x0001 -struct ec_params_hello { +struct __ec_align4 ec_params_hello { uint32_t in_data; /* Pass anything here */ -} __packed; +}; -struct ec_response_hello { +struct __ec_align4 ec_response_hello { uint32_t out_data; /* Output will be in_data + 0x01020304 */ -} __packed; +}; /* Get version number */ -#define EC_CMD_GET_VERSION 0x02 +#define EC_CMD_GET_VERSION 0x0002 enum ec_current_image { EC_IMAGE_UNKNOWN = 0, @@ -430,49 +846,49 @@ enum ec_current_image { EC_IMAGE_RW }; -struct ec_response_get_version { +struct __ec_align4 ec_response_get_version { /* Null-terminated version strings for RO, RW */ char version_string_ro[32]; char version_string_rw[32]; char reserved[32]; /* Was previously RW-B string */ uint32_t current_image; /* One of ec_current_image */ -} __packed; +}; /* Read test */ -#define EC_CMD_READ_TEST 0x03 +#define EC_CMD_READ_TEST 0x0003 -struct ec_params_read_test { +struct __ec_align4 ec_params_read_test { uint32_t offset; /* Starting value for read buffer */ uint32_t size; /* Size to read in bytes */ -} __packed; +}; -struct ec_response_read_test { +struct __ec_align4 ec_response_read_test { uint32_t data[32]; -} __packed; +}; /* * Get build information * * Response is null-terminated string. */ -#define EC_CMD_GET_BUILD_INFO 0x04 +#define EC_CMD_GET_BUILD_INFO 0x0004 /* Get chip info */ -#define EC_CMD_GET_CHIP_INFO 0x05 +#define EC_CMD_GET_CHIP_INFO 0x0005 -struct ec_response_get_chip_info { +struct __ec_align4 ec_response_get_chip_info { /* Null-terminated strings */ char vendor[32]; char name[32]; char revision[32]; /* Mask version */ -} __packed; +}; /* Get board HW version */ -#define EC_CMD_GET_BOARD_VERSION 0x06 +#define EC_CMD_GET_BOARD_VERSION 0x0006 -struct ec_response_board_version { +struct __ec_align2 ec_response_board_version { uint16_t board_version; /* A monotonously incrementing number. */ -} __packed; +}; /* * Read memory-mapped data. @@ -482,72 +898,73 @@ struct ec_response_board_version { * * Response is params.size bytes of data. */ -#define EC_CMD_READ_MEMMAP 0x07 +#define EC_CMD_READ_MEMMAP 0x0007 -struct ec_params_read_memmap { +struct __ec_align1 ec_params_read_memmap { uint8_t offset; /* Offset in memmap (EC_MEMMAP_*) */ uint8_t size; /* Size to read in bytes */ -} __packed; +}; /* Read versions supported for a command */ -#define EC_CMD_GET_CMD_VERSIONS 0x08 +#define EC_CMD_GET_CMD_VERSIONS 0x0008 -struct ec_params_get_cmd_versions { +struct __ec_align1 ec_params_get_cmd_versions { uint8_t cmd; /* Command to check */ -} __packed; +}; + +struct __ec_align2 ec_params_get_cmd_versions_v1 { + uint16_t cmd; /* Command to check */ +}; -struct ec_response_get_cmd_versions { +struct __ec_align4 ec_response_get_cmd_versions { /* * Mask of supported versions; use EC_VER_MASK() to compare with a * desired version. */ uint32_t version_mask; -} __packed; +}; /* - * Check EC communcations status (busy). This is needed on i2c/spi but not + * Check EC communications status (busy). This is needed on i2c/spi but not * on lpc since it has its own out-of-band busy indicator. * * lpc must read the status from the command register. Attempting this on * lpc will overwrite the args/parameter space and corrupt its data. */ -#define EC_CMD_GET_COMMS_STATUS 0x09 +#define EC_CMD_GET_COMMS_STATUS 0x0009 /* Avoid using ec_status which is for return values */ enum ec_comms_status { EC_COMMS_STATUS_PROCESSING = 1 << 0, /* Processing cmd */ }; -struct ec_response_get_comms_status { +struct __ec_align4 ec_response_get_comms_status { uint32_t flags; /* Mask of enum ec_comms_status */ -} __packed; +}; -/* - * Fake a variety of responses, purely for testing purposes. - * FIXME: Would be nice to force checksum errors. - */ -#define EC_CMD_TEST_PROTOCOL 0x0a +/* Fake a variety of responses, purely for testing purposes. */ +#define EC_CMD_TEST_PROTOCOL 0x000A /* Tell the EC what to send back to us. */ -struct ec_params_test_protocol { +struct __ec_align4 ec_params_test_protocol { uint32_t ec_result; uint32_t ret_len; uint8_t buf[32]; -} __packed; +}; /* Here it comes... */ -struct ec_response_test_protocol { +struct __ec_align4 ec_response_test_protocol { uint8_t buf[32]; -} __packed; +}; -/* Get prococol information */ -#define EC_CMD_GET_PROTOCOL_INFO 0x0b +/* Get protocol information */ +#define EC_CMD_GET_PROTOCOL_INFO 0x000B /* Flags for ec_response_get_protocol_info.flags */ /* EC_RES_IN_PROGRESS may be returned if a command is slow */ #define EC_PROTOCOL_INFO_IN_PROGRESS_SUPPORTED (1 << 0) -struct ec_response_get_protocol_info { +struct __ec_align4 ec_response_get_protocol_info { /* Fields which exist if at least protocol version 3 supported */ /* Bitmask of protocol versions supported (1 << n means version n)*/ @@ -561,15 +978,153 @@ struct ec_response_get_protocol_info { /* Flags; see EC_PROTOCOL_INFO_* */ uint32_t flags; -} __packed; +}; + + +/*****************************************************************************/ +/* Get/Set miscellaneous values */ + +/* The upper byte of .flags tells what to do (nothing means "get") */ +#define EC_GSV_SET 0x80000000 + +/* The lower three bytes of .flags identifies the parameter, if that has + meaning for an individual command. */ +#define EC_GSV_PARAM_MASK 0x00ffffff + +struct __ec_align4 ec_params_get_set_value { + uint32_t flags; + uint32_t value; +}; + +struct __ec_align4 ec_response_get_set_value { + uint32_t flags; + uint32_t value; +}; + +/* More than one command can use these structs to get/set parameters. */ +#define EC_CMD_GSV_PAUSE_IN_S5 0x000C + +/*****************************************************************************/ +/* List the features supported by the firmware */ +#define EC_CMD_GET_FEATURES 0x000D + +/* Supported features */ +enum ec_feature_code { + /* + * This image contains a limited set of features. Another image + * in RW partition may support more features. + */ + EC_FEATURE_LIMITED = 0, + /* + * Commands for probing/reading/writing/erasing the flash in the + * EC are present. + */ + EC_FEATURE_FLASH = 1, + /* + * Can control the fan speed directly. + */ + EC_FEATURE_PWM_FAN = 2, + /* + * Can control the intensity of the keyboard backlight. + */ + EC_FEATURE_PWM_KEYB = 3, + /* + * Support Google lightbar, introduced on Pixel. + */ + EC_FEATURE_LIGHTBAR = 4, + /* Control of LEDs */ + EC_FEATURE_LED = 5, + /* Exposes an interface to control gyro and sensors. + * The host goes through the EC to access these sensors. + * In addition, the EC may provide composite sensors, like lid angle. + */ + EC_FEATURE_MOTION_SENSE = 6, + /* The keyboard is controlled by the EC */ + EC_FEATURE_KEYB = 7, + /* The AP can use part of the EC flash as persistent storage. */ + EC_FEATURE_PSTORE = 8, + /* The EC monitors BIOS port 80h, and can return POST codes. */ + EC_FEATURE_PORT80 = 9, + /* + * Thermal management: include TMP specific commands. + * Higher level than direct fan control. + */ + EC_FEATURE_THERMAL = 10, + /* Can switch the screen backlight on/off */ + EC_FEATURE_BKLIGHT_SWITCH = 11, + /* Can switch the wifi module on/off */ + EC_FEATURE_WIFI_SWITCH = 12, + /* Monitor host events, through for example SMI or SCI */ + EC_FEATURE_HOST_EVENTS = 13, + /* The EC exposes GPIO commands to control/monitor connected devices. */ + EC_FEATURE_GPIO = 14, + /* The EC can send i2c messages to downstream devices. */ + EC_FEATURE_I2C = 15, + /* Command to control charger are included */ + EC_FEATURE_CHARGER = 16, + /* Simple battery support. */ + EC_FEATURE_BATTERY = 17, + /* + * Support Smart battery protocol + * (Common Smart Battery System Interface Specification) + */ + EC_FEATURE_SMART_BATTERY = 18, + /* EC can detect when the host hangs. */ + EC_FEATURE_HANG_DETECT = 19, + /* Report power information, for pit only */ + EC_FEATURE_PMU = 20, + /* Another Cros EC device is present downstream of this one */ + EC_FEATURE_SUB_MCU = 21, + /* Support USB Power delivery (PD) commands */ + EC_FEATURE_USB_PD = 22, + /* Control USB multiplexer, for audio through USB port for instance. */ + EC_FEATURE_USB_MUX = 23, + /* Motion Sensor code has an internal software FIFO */ + EC_FEATURE_MOTION_SENSE_FIFO = 24, + /* Support temporary secure vstore */ + EC_FEATURE_VSTORE = 25, + /* EC decides on USB-C SS mux state, muxes configured by host */ + EC_FEATURE_USBC_SS_MUX_VIRTUAL = 26, + /* EC has RTC feature that can be controlled by host commands */ + EC_FEATURE_RTC = 27, + /* The MCU exposes a Fingerprint sensor */ + EC_FEATURE_FINGERPRINT = 28, + /* The MCU exposes a Touchpad */ + EC_FEATURE_TOUCHPAD = 29, + /* The MCU has RWSIG task enabled */ + EC_FEATURE_RWSIG = 30, + /* EC has device events support */ + EC_FEATURE_DEVICE_EVENT = 31, + /* EC supports the unified wake masks for LPC/eSPI systems */ + EC_FEATURE_UNIFIED_WAKE_MASKS = 32, +}; + +#define EC_FEATURE_MASK_0(event_code) (1UL << (event_code % 32)) +#define EC_FEATURE_MASK_1(event_code) (1UL << (event_code - 32)) +struct __ec_align4 ec_response_get_features { + uint32_t flags[2]; +}; + +/*****************************************************************************/ +/* Get the board's SKU ID from EC */ +#define EC_CMD_GET_SKU_ID 0x000E + +/* Set SKU ID from AP */ +#define EC_CMD_SET_SKU_ID 0x000F + +struct __ec_align4 ec_sku_id_info { + uint32_t sku_id; +}; /*****************************************************************************/ /* Flash commands */ /* Get flash info */ -#define EC_CMD_FLASH_INFO 0x10 +#define EC_CMD_FLASH_INFO 0x0010 +#define EC_VER_FLASH_INFO 2 -struct ec_response_flash_info { +/* Version 0 returns these fields */ +struct __ec_align4 ec_response_flash_info { /* Usable flash size, in bytes */ uint32_t flash_size; /* @@ -587,40 +1142,157 @@ struct ec_response_flash_info { * multiple of this. */ uint32_t protect_block_size; -} __packed; +}; + +/* Flags for version 1+ flash info command */ +/* EC flash erases bits to 0 instead of 1 */ +#define EC_FLASH_INFO_ERASE_TO_0 (1 << 0) + +/* Flash must be selected for read/write/erase operations to succeed. This may + * be necessary on a chip where write/erase can be corrupted by other board + * activity, or where the chip needs to enable some sort of programming voltage, + * or where the read/write/erase operations require cleanly suspending other + * chip functionality. */ +#define EC_FLASH_INFO_SELECT_REQUIRED (1 << 1) /* - * Read flash + * Version 1 returns the same initial fields as version 0, with additional + * fields following. * - * Response is params.size bytes of data. + * gcc anonymous structs don't seem to get along with the __packed directive; + * if they did we'd define the version 0 structure as a sub-structure of this + * one. + * + * Version 2 supports flash banks of different sizes: + * The caller specified the number of banks it has preallocated + * (num_banks_desc) + * The EC returns the number of banks describing the flash memory. + * It adds banks descriptions up to num_banks_desc. */ -#define EC_CMD_FLASH_READ 0x11 +struct __ec_align4 ec_response_flash_info_1 { + /* Version 0 fields; see above for description */ + uint32_t flash_size; + uint32_t write_block_size; + uint32_t erase_block_size; + uint32_t protect_block_size; -struct ec_params_flash_read { - uint32_t offset; /* Byte offset to read */ - uint32_t size; /* Size to read in bytes */ -} __packed; + /* Version 1 adds these fields: */ + /* + * Ideal write size in bytes. Writes will be fastest if size is + * exactly this and offset is a multiple of this. For example, an EC + * may have a write buffer which can do half-page operations if data is + * aligned, and a slower word-at-a-time write mode. + */ + uint32_t write_ideal_size; -/* Write flash */ -#define EC_CMD_FLASH_WRITE 0x12 -#define EC_VER_FLASH_WRITE 1 + /* Flags; see EC_FLASH_INFO_* */ + uint32_t flags; +}; -/* Version 0 of the flash command supported only 64 bytes of data */ +struct __ec_align4 ec_params_flash_info_2 { + /* Number of banks to describe */ + uint16_t num_banks_desc; + /* Reserved; set 0; ignore on read */ + uint8_t reserved[2]; +}; + +struct ec_flash_bank { + /* Number of sector is in this bank. */ + uint16_t count; + /* Size in power of 2 of each sector (8 --> 256 bytes) */ + uint8_t size_exp; + /* Minimal write size for the sectors in this bank */ + uint8_t write_size_exp; + /* Erase size for the sectors in this bank */ + uint8_t erase_size_exp; + /* Size for write protection, usually identical to erase size. */ + uint8_t protect_size_exp; + /* Reserved; set 0; ignore on read */ + uint8_t reserved[2]; +}; + +struct __ec_align4 ec_response_flash_info_2 { + /* Total flash in the EC. */ + uint32_t flash_size; + /* Flags; see EC_FLASH_INFO_* */ + uint32_t flags; + /* Maximum size to use to send data to write to the EC. */ + uint32_t write_ideal_size; + /* Number of banks present in the EC. */ + uint16_t num_banks_total; + /* Number of banks described in banks array. */ + uint16_t num_banks_desc; + struct ec_flash_bank banks[0]; +}; + +/* + * Read flash + * + * Response is params.size bytes of data. + */ +#define EC_CMD_FLASH_READ 0x0011 + +struct __ec_align4 ec_params_flash_read { + uint32_t offset; /* Byte offset to read */ + uint32_t size; /* Size to read in bytes */ +}; + +/* Write flash */ +#define EC_CMD_FLASH_WRITE 0x0012 +#define EC_VER_FLASH_WRITE 1 + +/* Version 0 of the flash command supported only 64 bytes of data */ #define EC_FLASH_WRITE_VER0_SIZE 64 -struct ec_params_flash_write { +struct __ec_align4 ec_params_flash_write { uint32_t offset; /* Byte offset to write */ uint32_t size; /* Size to write in bytes */ /* Followed by data to write */ -} __packed; +}; /* Erase flash */ -#define EC_CMD_FLASH_ERASE 0x13 +#define EC_CMD_FLASH_ERASE 0x0013 -struct ec_params_flash_erase { +/* v0 */ +struct __ec_align4 ec_params_flash_erase { uint32_t offset; /* Byte offset to erase */ uint32_t size; /* Size to erase in bytes */ -} __packed; +}; + + +#define EC_VER_FLASH_WRITE 1 +/* v1 add async erase: + * subcommands can returns: + * EC_RES_SUCCESS : erased (see ERASE_SECTOR_ASYNC case below). + * EC_RES_INVALID_PARAM : offset/size are not aligned on a erase boundary. + * EC_RES_ERROR : other errors. + * EC_RES_BUSY : an existing erase operation is in progress. + * EC_RES_ACCESS_DENIED: Trying to erase running image. + * + * When ERASE_SECTOR_ASYNC returns EC_RES_SUCCESS, the operation is just + * properly queued. The user must call ERASE_GET_RESULT subcommand to get + * the proper result. + * When ERASE_GET_RESULT returns EC_RES_BUSY, the caller must wait and send + * ERASE_GET_RESULT again to get the result of ERASE_SECTOR_ASYNC. + * ERASE_GET_RESULT command may timeout on EC where flash access is not + * permitted while erasing. (For instance, STM32F4). + */ +enum ec_flash_erase_cmd { + FLASH_ERASE_SECTOR, /* Erase and wait for result */ + FLASH_ERASE_SECTOR_ASYNC, /* Erase and return immediately. */ + FLASH_ERASE_GET_RESULT, /* Ask for last erase result */ +}; + +struct __ec_align4 ec_params_flash_erase_v1 { + /* One of ec_flash_erase_cmd. */ + uint8_t cmd; + /* Pad byte; currently always contains 0 */ + uint8_t reserved; + /* No flags defined yet; set to 0 */ + uint16_t flag; + /* Same as v0 parameters. */ + struct ec_params_flash_erase params; +}; /* * Get/set flash protection. @@ -632,7 +1304,7 @@ struct ec_params_flash_erase { * * If mask=0, simply returns the current flags state. */ -#define EC_CMD_FLASH_PROTECT 0x15 +#define EC_CMD_FLASH_PROTECT 0x0015 #define EC_VER_FLASH_PROTECT 1 /* Command version 1 */ /* Flags for flash protection */ @@ -655,15 +1327,23 @@ struct ec_params_flash_erase { * re-requesting the desired flags, or by a hard reset if that fails. */ #define EC_FLASH_PROTECT_ERROR_INCONSISTENT (1 << 5) -/* Entile flash code protected when the EC boots */ +/* Entire flash code protected when the EC boots */ #define EC_FLASH_PROTECT_ALL_AT_BOOT (1 << 6) - -struct ec_params_flash_protect { +/* RW flash code protected when the EC boots */ +#define EC_FLASH_PROTECT_RW_AT_BOOT (1 << 7) +/* RW flash code protected now. */ +#define EC_FLASH_PROTECT_RW_NOW (1 << 8) +/* Rollback information flash region protected when the EC boots */ +#define EC_FLASH_PROTECT_ROLLBACK_AT_BOOT (1 << 9) +/* Rollback information flash region protected now */ +#define EC_FLASH_PROTECT_ROLLBACK_NOW (1 << 10) + +struct __ec_align4 ec_params_flash_protect { uint32_t mask; /* Bits in flags to apply */ uint32_t flags; /* New flags to apply */ -} __packed; +}; -struct ec_response_flash_protect { +struct __ec_align4 ec_response_flash_protect { /* Current value of flash protect flags */ uint32_t flags; /* @@ -674,7 +1354,7 @@ struct ec_response_flash_protect { uint32_t valid_flags; /* Flags which can be changed given the current protection state */ uint32_t writable_flags; -} __packed; +}; /* * Note: commands 0x14 - 0x19 version 0 were old commands to get/set flash @@ -682,89 +1362,166 @@ struct ec_response_flash_protect { */ /* Get the region offset/size */ -#define EC_CMD_FLASH_REGION_INFO 0x16 +#define EC_CMD_FLASH_REGION_INFO 0x0016 #define EC_VER_FLASH_REGION_INFO 1 enum ec_flash_region { /* Region which holds read-only EC image */ EC_FLASH_REGION_RO = 0, - /* Region which holds rewritable EC image */ - EC_FLASH_REGION_RW, + /* Region which holds active rewritable EC image */ + EC_FLASH_REGION_ACTIVE, /* * Region which should be write-protected in the factory (a superset of * EC_FLASH_REGION_RO) */ EC_FLASH_REGION_WP_RO, + /* Region which holds updatable image */ + EC_FLASH_REGION_UPDATE, /* Number of regions */ EC_FLASH_REGION_COUNT, }; -struct ec_params_flash_region_info { +struct __ec_align4 ec_params_flash_region_info { uint32_t region; /* enum ec_flash_region */ -} __packed; +}; -struct ec_response_flash_region_info { +struct __ec_align4 ec_response_flash_region_info { uint32_t offset; uint32_t size; -} __packed; +}; /* Read/write VbNvContext */ -#define EC_CMD_VBNV_CONTEXT 0x17 +#define EC_CMD_VBNV_CONTEXT 0x0017 #define EC_VER_VBNV_CONTEXT 1 #define EC_VBNV_BLOCK_SIZE 16 +#define EC_VBNV_BLOCK_SIZE_V2 64 enum ec_vbnvcontext_op { EC_VBNV_CONTEXT_OP_READ, EC_VBNV_CONTEXT_OP_WRITE, }; -struct ec_params_vbnvcontext { +struct __ec_align4 ec_params_vbnvcontext { uint32_t op; - uint8_t block[EC_VBNV_BLOCK_SIZE]; -} __packed; + uint8_t block[EC_VBNV_BLOCK_SIZE_V2]; +}; + +struct __ec_align4 ec_response_vbnvcontext { + uint8_t block[EC_VBNV_BLOCK_SIZE_V2]; +}; + + +/* Get SPI flash information */ +#define EC_CMD_FLASH_SPI_INFO 0x0018 + +struct __ec_align1 ec_response_flash_spi_info { + /* JEDEC info from command 0x9F (manufacturer, memory type, size) */ + uint8_t jedec[3]; + + /* Pad byte; currently always contains 0 */ + uint8_t reserved0; + + /* Manufacturer / device ID from command 0x90 */ + uint8_t mfr_dev_id[2]; + + /* Status registers from command 0x05 and 0x35 */ + uint8_t sr1, sr2; +}; + -struct ec_response_vbnvcontext { - uint8_t block[EC_VBNV_BLOCK_SIZE]; -} __packed; +/* Select flash during flash operations */ +#define EC_CMD_FLASH_SELECT 0x0019 + +struct __ec_align4 ec_params_flash_select { + /* 1 to select flash, 0 to deselect flash */ + uint8_t select; +}; /*****************************************************************************/ /* PWM commands */ /* Get fan target RPM */ -#define EC_CMD_PWM_GET_FAN_TARGET_RPM 0x20 +#define EC_CMD_PWM_GET_FAN_TARGET_RPM 0x0020 -struct ec_response_pwm_get_fan_rpm { +struct __ec_align4 ec_response_pwm_get_fan_rpm { uint32_t rpm; -} __packed; +}; /* Set target fan RPM */ -#define EC_CMD_PWM_SET_FAN_TARGET_RPM 0x21 +#define EC_CMD_PWM_SET_FAN_TARGET_RPM 0x0021 + +/* Version 0 of input params */ +struct __ec_align4 ec_params_pwm_set_fan_target_rpm_v0 { + uint32_t rpm; +}; -struct ec_params_pwm_set_fan_target_rpm { +/* Version 1 of input params */ +struct __ec_align_size1 ec_params_pwm_set_fan_target_rpm_v1 { uint32_t rpm; -} __packed; + uint8_t fan_idx; +}; /* Get keyboard backlight */ -#define EC_CMD_PWM_GET_KEYBOARD_BACKLIGHT 0x22 +/* OBSOLETE - Use EC_CMD_PWM_SET_DUTY */ +#define EC_CMD_PWM_GET_KEYBOARD_BACKLIGHT 0x0022 -struct ec_response_pwm_get_keyboard_backlight { +struct __ec_align1 ec_response_pwm_get_keyboard_backlight { uint8_t percent; uint8_t enabled; -} __packed; +}; /* Set keyboard backlight */ -#define EC_CMD_PWM_SET_KEYBOARD_BACKLIGHT 0x23 +/* OBSOLETE - Use EC_CMD_PWM_SET_DUTY */ +#define EC_CMD_PWM_SET_KEYBOARD_BACKLIGHT 0x0023 -struct ec_params_pwm_set_keyboard_backlight { +struct __ec_align1 ec_params_pwm_set_keyboard_backlight { uint8_t percent; -} __packed; +}; /* Set target fan PWM duty cycle */ -#define EC_CMD_PWM_SET_FAN_DUTY 0x24 +#define EC_CMD_PWM_SET_FAN_DUTY 0x0024 + +/* Version 0 of input params */ +struct __ec_align4 ec_params_pwm_set_fan_duty_v0 { + uint32_t percent; +}; -struct ec_params_pwm_set_fan_duty { +/* Version 1 of input params */ +struct __ec_align_size1 ec_params_pwm_set_fan_duty_v1 { uint32_t percent; -} __packed; + uint8_t fan_idx; +}; + +#define EC_CMD_PWM_SET_DUTY 0x0025 +/* 16 bit duty cycle, 0xffff = 100% */ +#define EC_PWM_MAX_DUTY 0xffff + +enum ec_pwm_type { + /* All types, indexed by board-specific enum pwm_channel */ + EC_PWM_TYPE_GENERIC = 0, + /* Keyboard backlight */ + EC_PWM_TYPE_KB_LIGHT, + /* Display backlight */ + EC_PWM_TYPE_DISPLAY_LIGHT, + EC_PWM_TYPE_COUNT, +}; + +struct __ec_align4 ec_params_pwm_set_duty { + uint16_t duty; /* Duty cycle, EC_PWM_MAX_DUTY = 100% */ + uint8_t pwm_type; /* ec_pwm_type */ + uint8_t index; /* Type-specific index, or 0 if unique */ +}; + +#define EC_CMD_PWM_GET_DUTY 0x0026 + +struct __ec_align1 ec_params_pwm_get_duty { + uint8_t pwm_type; /* ec_pwm_type */ + uint8_t index; /* Type-specific index, or 0 if unique */ +}; + +struct __ec_align2 ec_response_pwm_get_duty { + uint16_t duty; /* Duty cycle, EC_PWM_MAX_DUTY = 100% */ +}; /*****************************************************************************/ /* @@ -773,9 +1530,9 @@ struct ec_params_pwm_set_fan_duty { * into a subcommand. We'll make separate structs for subcommands with * different input args, so that we know how much to expect. */ -#define EC_CMD_LIGHTBAR_CMD 0x28 +#define EC_CMD_LIGHTBAR_CMD 0x0028 -struct rgb_s { +struct __ec_todo_unpacked rgb_s { uint8_t r, g, b; }; @@ -783,17 +1540,17 @@ struct rgb_s { /* List of tweakable parameters. NOTE: It's __packed so it can be sent in a * host command, but the alignment is the same regardless. Keep it that way. */ -struct lightbar_params { +struct __ec_todo_packed lightbar_params_v0 { /* Timing */ - int google_ramp_up; - int google_ramp_down; - int s3s0_ramp_up; - int s0_tick_delay[2]; /* AC=0/1 */ - int s0a_tick_delay[2]; /* AC=0/1 */ - int s0s3_ramp_down; - int s3_sleep_for; - int s3_ramp_up; - int s3_ramp_down; + int32_t google_ramp_up; + int32_t google_ramp_down; + int32_t s3s0_ramp_up; + int32_t s0_tick_delay[2]; /* AC=0/1 */ + int32_t s0a_tick_delay[2]; /* AC=0/1 */ + int32_t s0s3_ramp_down; + int32_t s3_sleep_for; + int32_t s3_ramp_up; + int32_t s3_ramp_down; /* Oscillation */ uint8_t new_s0; @@ -815,52 +1572,221 @@ struct lightbar_params { /* Color palette */ struct rgb_s color[8]; /* 0-3 are Google colors */ -} __packed; +}; + +struct __ec_todo_packed lightbar_params_v1 { + /* Timing */ + int32_t google_ramp_up; + int32_t google_ramp_down; + int32_t s3s0_ramp_up; + int32_t s0_tick_delay[2]; /* AC=0/1 */ + int32_t s0a_tick_delay[2]; /* AC=0/1 */ + int32_t s0s3_ramp_down; + int32_t s3_sleep_for; + int32_t s3_ramp_up; + int32_t s3_ramp_down; + int32_t s5_ramp_up; + int32_t s5_ramp_down; + int32_t tap_tick_delay; + int32_t tap_gate_delay; + int32_t tap_display_time; + + /* Tap-for-battery params */ + uint8_t tap_pct_red; + uint8_t tap_pct_green; + uint8_t tap_seg_min_on; + uint8_t tap_seg_max_on; + uint8_t tap_seg_osc; + uint8_t tap_idx[3]; + + /* Oscillation */ + uint8_t osc_min[2]; /* AC=0/1 */ + uint8_t osc_max[2]; /* AC=0/1 */ + uint8_t w_ofs[2]; /* AC=0/1 */ + + /* Brightness limits based on the backlight and AC. */ + uint8_t bright_bl_off_fixed[2]; /* AC=0/1 */ + uint8_t bright_bl_on_min[2]; /* AC=0/1 */ + uint8_t bright_bl_on_max[2]; /* AC=0/1 */ + + /* Battery level thresholds */ + uint8_t battery_threshold[LB_BATTERY_LEVELS - 1]; + + /* Map [AC][battery_level] to color index */ + uint8_t s0_idx[2][LB_BATTERY_LEVELS]; /* AP is running */ + uint8_t s3_idx[2][LB_BATTERY_LEVELS]; /* AP is sleeping */ + + /* s5: single color pulse on inhibited power-up */ + uint8_t s5_idx; + + /* Color palette */ + struct rgb_s color[8]; /* 0-3 are Google colors */ +}; + +/* Lightbar command params v2 + * crbug.com/467716 + * + * lightbar_parms_v1 was too big for i2c, therefore in v2, we split them up by + * logical groups to make it more manageable ( < 120 bytes). + * + * NOTE: Each of these groups must be less than 120 bytes. + */ + +struct __ec_todo_packed lightbar_params_v2_timing { + /* Timing */ + int32_t google_ramp_up; + int32_t google_ramp_down; + int32_t s3s0_ramp_up; + int32_t s0_tick_delay[2]; /* AC=0/1 */ + int32_t s0a_tick_delay[2]; /* AC=0/1 */ + int32_t s0s3_ramp_down; + int32_t s3_sleep_for; + int32_t s3_ramp_up; + int32_t s3_ramp_down; + int32_t s5_ramp_up; + int32_t s5_ramp_down; + int32_t tap_tick_delay; + int32_t tap_gate_delay; + int32_t tap_display_time; +}; + +struct __ec_todo_packed lightbar_params_v2_tap { + /* Tap-for-battery params */ + uint8_t tap_pct_red; + uint8_t tap_pct_green; + uint8_t tap_seg_min_on; + uint8_t tap_seg_max_on; + uint8_t tap_seg_osc; + uint8_t tap_idx[3]; +}; + +struct __ec_todo_packed lightbar_params_v2_oscillation { + /* Oscillation */ + uint8_t osc_min[2]; /* AC=0/1 */ + uint8_t osc_max[2]; /* AC=0/1 */ + uint8_t w_ofs[2]; /* AC=0/1 */ +}; + +struct __ec_todo_packed lightbar_params_v2_brightness { + /* Brightness limits based on the backlight and AC. */ + uint8_t bright_bl_off_fixed[2]; /* AC=0/1 */ + uint8_t bright_bl_on_min[2]; /* AC=0/1 */ + uint8_t bright_bl_on_max[2]; /* AC=0/1 */ +}; + +struct __ec_todo_packed lightbar_params_v2_thresholds { + /* Battery level thresholds */ + uint8_t battery_threshold[LB_BATTERY_LEVELS - 1]; +}; + +struct __ec_todo_packed lightbar_params_v2_colors { + /* Map [AC][battery_level] to color index */ + uint8_t s0_idx[2][LB_BATTERY_LEVELS]; /* AP is running */ + uint8_t s3_idx[2][LB_BATTERY_LEVELS]; /* AP is sleeping */ + + /* s5: single color pulse on inhibited power-up */ + uint8_t s5_idx; + + /* Color palette */ + struct rgb_s color[8]; /* 0-3 are Google colors */ +}; + +/* Lightbyte program. */ +#define EC_LB_PROG_LEN 192 +struct __ec_todo_unpacked lightbar_program { + uint8_t size; + uint8_t data[EC_LB_PROG_LEN]; +}; -struct ec_params_lightbar { +struct __ec_todo_packed ec_params_lightbar { uint8_t cmd; /* Command (see enum lightbar_command) */ union { - struct { + struct __ec_todo_unpacked { /* no args */ - } dump, off, on, init, get_seq, get_params; + } dump, off, on, init, get_seq, get_params_v0, get_params_v1, + version, get_brightness, get_demo, suspend, resume, + get_params_v2_timing, get_params_v2_tap, + get_params_v2_osc, get_params_v2_bright, + get_params_v2_thlds, get_params_v2_colors; - struct num { + struct __ec_todo_unpacked { uint8_t num; - } brightness, seq, demo; + } set_brightness, seq, demo; - struct reg { + struct __ec_todo_unpacked { uint8_t ctrl, reg, value; } reg; - struct rgb { + struct __ec_todo_unpacked { uint8_t led, red, green, blue; - } rgb; + } set_rgb; + + struct __ec_todo_unpacked { + uint8_t led; + } get_rgb; - struct lightbar_params set_params; + struct __ec_todo_unpacked { + uint8_t enable; + } manual_suspend_ctrl; + + struct lightbar_params_v0 set_params_v0; + struct lightbar_params_v1 set_params_v1; + + struct lightbar_params_v2_timing set_v2par_timing; + struct lightbar_params_v2_tap set_v2par_tap; + struct lightbar_params_v2_oscillation set_v2par_osc; + struct lightbar_params_v2_brightness set_v2par_bright; + struct lightbar_params_v2_thresholds set_v2par_thlds; + struct lightbar_params_v2_colors set_v2par_colors; + + struct lightbar_program set_program; }; -} __packed; +}; -struct ec_response_lightbar { +struct __ec_todo_packed ec_response_lightbar { union { - struct dump { - struct { + struct __ec_todo_unpacked { + struct __ec_todo_unpacked { uint8_t reg; uint8_t ic0; uint8_t ic1; } vals[23]; } dump; - struct get_seq { + struct __ec_todo_unpacked { uint8_t num; - } get_seq; + } get_seq, get_brightness, get_demo; - struct lightbar_params get_params; + struct lightbar_params_v0 get_params_v0; + struct lightbar_params_v1 get_params_v1; - struct { + + struct lightbar_params_v2_timing get_params_v2_timing; + struct lightbar_params_v2_tap get_params_v2_tap; + struct lightbar_params_v2_oscillation get_params_v2_osc; + struct lightbar_params_v2_brightness get_params_v2_bright; + struct lightbar_params_v2_thresholds get_params_v2_thlds; + struct lightbar_params_v2_colors get_params_v2_colors; + + struct __ec_todo_unpacked { + uint32_t num; + uint32_t flags; + } version; + + struct __ec_todo_unpacked { + uint8_t red, green, blue; + } get_rgb; + + struct __ec_todo_unpacked { /* no return params */ - } off, on, init, brightness, seq, reg, rgb, demo, set_params; + } off, on, init, set_brightness, seq, reg, set_rgb, + demo, set_params_v0, set_params_v1, + set_program, manual_suspend_ctrl, suspend, resume, + set_v2par_timing, set_v2par_tap, + set_v2par_osc, set_v2par_bright, set_v2par_thlds, + set_v2par_colors; }; -} __packed; +}; /* Lightbar commands */ enum lightbar_command { @@ -868,26 +1794,64 @@ enum lightbar_command { LIGHTBAR_CMD_OFF = 1, LIGHTBAR_CMD_ON = 2, LIGHTBAR_CMD_INIT = 3, - LIGHTBAR_CMD_BRIGHTNESS = 4, + LIGHTBAR_CMD_SET_BRIGHTNESS = 4, LIGHTBAR_CMD_SEQ = 5, LIGHTBAR_CMD_REG = 6, - LIGHTBAR_CMD_RGB = 7, + LIGHTBAR_CMD_SET_RGB = 7, LIGHTBAR_CMD_GET_SEQ = 8, LIGHTBAR_CMD_DEMO = 9, - LIGHTBAR_CMD_GET_PARAMS = 10, - LIGHTBAR_CMD_SET_PARAMS = 11, + LIGHTBAR_CMD_GET_PARAMS_V0 = 10, + LIGHTBAR_CMD_SET_PARAMS_V0 = 11, + LIGHTBAR_CMD_VERSION = 12, + LIGHTBAR_CMD_GET_BRIGHTNESS = 13, + LIGHTBAR_CMD_GET_RGB = 14, + LIGHTBAR_CMD_GET_DEMO = 15, + LIGHTBAR_CMD_GET_PARAMS_V1 = 16, + LIGHTBAR_CMD_SET_PARAMS_V1 = 17, + LIGHTBAR_CMD_SET_PROGRAM = 18, + LIGHTBAR_CMD_MANUAL_SUSPEND_CTRL = 19, + LIGHTBAR_CMD_SUSPEND = 20, + LIGHTBAR_CMD_RESUME = 21, + LIGHTBAR_CMD_GET_PARAMS_V2_TIMING = 22, + LIGHTBAR_CMD_SET_PARAMS_V2_TIMING = 23, + LIGHTBAR_CMD_GET_PARAMS_V2_TAP = 24, + LIGHTBAR_CMD_SET_PARAMS_V2_TAP = 25, + LIGHTBAR_CMD_GET_PARAMS_V2_OSCILLATION = 26, + LIGHTBAR_CMD_SET_PARAMS_V2_OSCILLATION = 27, + LIGHTBAR_CMD_GET_PARAMS_V2_BRIGHTNESS = 28, + LIGHTBAR_CMD_SET_PARAMS_V2_BRIGHTNESS = 29, + LIGHTBAR_CMD_GET_PARAMS_V2_THRESHOLDS = 30, + LIGHTBAR_CMD_SET_PARAMS_V2_THRESHOLDS = 31, + LIGHTBAR_CMD_GET_PARAMS_V2_COLORS = 32, + LIGHTBAR_CMD_SET_PARAMS_V2_COLORS = 33, LIGHTBAR_NUM_CMDS }; /*****************************************************************************/ /* LED control commands */ -#define EC_CMD_LED_CONTROL 0x29 +#define EC_CMD_LED_CONTROL 0x0029 enum ec_led_id { + /* LED to indicate battery state of charge */ EC_LED_ID_BATTERY_LED = 0, - EC_LED_ID_POWER_BUTTON_LED, + /* + * LED to indicate system power state (on or in suspend). + * May be on power button or on C-panel. + */ + EC_LED_ID_POWER_LED, + /* LED on power adapter or its plug */ EC_LED_ID_ADAPTER_LED, + /* LED to indicate left side */ + EC_LED_ID_LEFT_LED, + /* LED to indicate right side */ + EC_LED_ID_RIGHT_LED, + /* LED to indicate recovery mode with HW_REINIT */ + EC_LED_ID_RECOVERY_HW_REINIT_LED, + /* LED to indicate sysrq debug mode. */ + EC_LED_ID_SYSRQ_DEBUG_LED, + + EC_LED_ID_COUNT }; /* LED control flags */ @@ -900,18 +1864,19 @@ enum ec_led_colors { EC_LED_COLOR_BLUE, EC_LED_COLOR_YELLOW, EC_LED_COLOR_WHITE, + EC_LED_COLOR_AMBER, EC_LED_COLOR_COUNT }; -struct ec_params_led_control { +struct __ec_align1 ec_params_led_control { uint8_t led_id; /* Which LED to control */ uint8_t flags; /* Control flags */ uint8_t brightness[EC_LED_COLOR_COUNT]; -} __packed; +}; -struct ec_response_led_control { +struct __ec_align1 ec_response_led_control { /* * Available brightness value range. * @@ -920,7 +1885,7 @@ struct ec_response_led_control { * Other values means the LED is control by PWM. */ uint8_t brightness_range[EC_LED_COLOR_COUNT]; -} __packed; +}; /*****************************************************************************/ /* Verified boot commands */ @@ -931,9 +1896,9 @@ struct ec_response_led_control { */ /* Verified boot hash command */ -#define EC_CMD_VBOOT_HASH 0x2A +#define EC_CMD_VBOOT_HASH 0x002A -struct ec_params_vboot_hash { +struct __ec_align4 ec_params_vboot_hash { uint8_t cmd; /* enum ec_vboot_hash_cmd */ uint8_t hash_type; /* enum ec_vboot_hash_type */ uint8_t nonce_size; /* Nonce size; may be 0 */ @@ -941,9 +1906,9 @@ struct ec_params_vboot_hash { uint32_t offset; /* Offset in flash to hash */ uint32_t size; /* Number of bytes to hash */ uint8_t nonce_data[64]; /* Nonce data; ignored if nonce_size=0 */ -} __packed; +}; -struct ec_response_vboot_hash { +struct __ec_align4 ec_response_vboot_hash { uint8_t status; /* enum ec_vboot_hash_status */ uint8_t hash_type; /* enum ec_vboot_hash_type */ uint8_t digest_size; /* Size of hash digest in bytes */ @@ -951,7 +1916,7 @@ struct ec_response_vboot_hash { uint32_t offset; /* Offset in flash which was hashed */ uint32_t size; /* Number of bytes hashed */ uint8_t hash_digest[64]; /* Hash digest data */ -} __packed; +}; enum ec_vboot_hash_cmd { EC_VBOOT_HASH_GET = 0, /* Get current hash status */ @@ -975,741 +1940,2662 @@ enum ec_vboot_hash_status { * If one of these is specified, the EC will automatically update offset and * size to the correct values for the specified image (RO or RW). */ -#define EC_VBOOT_HASH_OFFSET_RO 0xfffffffe -#define EC_VBOOT_HASH_OFFSET_RW 0xfffffffd +#define EC_VBOOT_HASH_OFFSET_RO 0xfffffffe +#define EC_VBOOT_HASH_OFFSET_ACTIVE 0xfffffffd +#define EC_VBOOT_HASH_OFFSET_UPDATE 0xfffffffc /*****************************************************************************/ -/* USB charging control commands */ +/* + * Motion sense commands. We'll make separate structs for sub-commands with + * different input args, so that we know how much to expect. + */ +#define EC_CMD_MOTION_SENSE_CMD 0x002B -/* Set USB port charging mode */ -#define EC_CMD_USB_CHARGE_SET_MODE 0x30 +/* Motion sense commands */ +enum motionsense_command { + /* + * Dump command returns all motion sensor data including motion sense + * module flags and individual sensor flags. + */ + MOTIONSENSE_CMD_DUMP = 0, -struct ec_params_usb_charge_set_mode { - uint8_t usb_port_id; - uint8_t mode; -} __packed; + /* + * Info command returns data describing the details of a given sensor, + * including enum motionsensor_type, enum motionsensor_location, and + * enum motionsensor_chip. + */ + MOTIONSENSE_CMD_INFO = 1, -/*****************************************************************************/ -/* Persistent storage for host */ + /* + * EC Rate command is a setter/getter command for the EC sampling rate + * in milliseconds. + * It is per sensor, the EC run sample task at the minimum of all + * sensors EC_RATE. + * For sensors without hardware FIFO, EC_RATE should be equals to 1/ODR + * to collect all the sensor samples. + * For sensor with hardware FIFO, EC_RATE is used as the maximal delay + * to process of all motion sensors in milliseconds. + */ + MOTIONSENSE_CMD_EC_RATE = 2, -/* Maximum bytes that can be read/written in a single command */ -#define EC_PSTORE_SIZE_MAX 64 + /* + * Sensor ODR command is a setter/getter command for the output data + * rate of a specific motion sensor in millihertz. + */ + MOTIONSENSE_CMD_SENSOR_ODR = 3, -/* Get persistent storage info */ -#define EC_CMD_PSTORE_INFO 0x40 + /* + * Sensor range command is a setter/getter command for the range of + * a specified motion sensor in +/-G's or +/- deg/s. + */ + MOTIONSENSE_CMD_SENSOR_RANGE = 4, -struct ec_response_pstore_info { - /* Persistent storage size, in bytes */ - uint32_t pstore_size; - /* Access size; read/write offset and size must be a multiple of this */ - uint32_t access_size; -} __packed; + /* + * Setter/getter command for the keyboard wake angle. When the lid + * angle is greater than this value, keyboard wake is disabled in S3, + * and when the lid angle goes less than this value, keyboard wake is + * enabled. Note, the lid angle measurement is an approximate, + * un-calibrated value, hence the wake angle isn't exact. + */ + MOTIONSENSE_CMD_KB_WAKE_ANGLE = 5, -/* - * Read persistent storage - * - * Response is params.size bytes of data. - */ -#define EC_CMD_PSTORE_READ 0x41 + /* + * Returns a single sensor data. + */ + MOTIONSENSE_CMD_DATA = 6, -struct ec_params_pstore_read { - uint32_t offset; /* Byte offset to read */ - uint32_t size; /* Size to read in bytes */ -} __packed; + /* + * Return sensor fifo info. + */ + MOTIONSENSE_CMD_FIFO_INFO = 7, -/* Write persistent storage */ -#define EC_CMD_PSTORE_WRITE 0x42 + /* + * Insert a flush element in the fifo and return sensor fifo info. + * The host can use that element to synchronize its operation. + */ + MOTIONSENSE_CMD_FIFO_FLUSH = 8, -struct ec_params_pstore_write { - uint32_t offset; /* Byte offset to write */ - uint32_t size; /* Size to write in bytes */ - uint8_t data[EC_PSTORE_SIZE_MAX]; -} __packed; + /* + * Return a portion of the fifo. + */ + MOTIONSENSE_CMD_FIFO_READ = 9, -/*****************************************************************************/ -/* Real-time clock */ + /* + * Perform low level calibration. + * On sensors that support it, ask to do offset calibration. + */ + MOTIONSENSE_CMD_PERFORM_CALIB = 10, -/* RTC params and response structures */ -struct ec_params_rtc { - uint32_t time; -} __packed; + /* + * Sensor Offset command is a setter/getter command for the offset + * used for calibration. + * The offsets can be calculated by the host, or via + * PERFORM_CALIB command. + */ + MOTIONSENSE_CMD_SENSOR_OFFSET = 11, -struct ec_response_rtc { - uint32_t time; -} __packed; + /* + * List available activities for a MOTION sensor. + * Indicates if they are enabled or disabled. + */ + MOTIONSENSE_CMD_LIST_ACTIVITIES = 12, -/* These use ec_response_rtc */ -#define EC_CMD_RTC_GET_VALUE 0x44 -#define EC_CMD_RTC_GET_ALARM 0x45 + /* + * Activity management + * Enable/Disable activity recognition. + */ + MOTIONSENSE_CMD_SET_ACTIVITY = 13, -/* These all use ec_params_rtc */ -#define EC_CMD_RTC_SET_VALUE 0x46 -#define EC_CMD_RTC_SET_ALARM 0x47 + /* + * Lid Angle + */ + MOTIONSENSE_CMD_LID_ANGLE = 14, -/*****************************************************************************/ -/* Port80 log access */ + /* + * Allow the FIFO to trigger interrupt via MKBP events. + * By default the FIFO does not send interrupt to process the FIFO + * until the AP is ready or it is coming from a wakeup sensor. + */ + MOTIONSENSE_CMD_FIFO_INT_ENABLE = 15, -/* Get last port80 code from previous boot */ -#define EC_CMD_PORT80_LAST_BOOT 0x48 + /* + * Spoof the readings of the sensors. The spoofed readings can be set + * to arbitrary values, or will lock to the last read actual values. + */ + MOTIONSENSE_CMD_SPOOF = 16, -struct ec_response_port80_last_boot { - uint16_t code; -} __packed; + /* Number of motionsense sub-commands. */ + MOTIONSENSE_NUM_CMDS +}; -/*****************************************************************************/ -/* Thermal engine commands */ +/* List of motion sensor types. */ +enum motionsensor_type { + MOTIONSENSE_TYPE_ACCEL = 0, + MOTIONSENSE_TYPE_GYRO = 1, + MOTIONSENSE_TYPE_MAG = 2, + MOTIONSENSE_TYPE_PROX = 3, + MOTIONSENSE_TYPE_LIGHT = 4, + MOTIONSENSE_TYPE_ACTIVITY = 5, + MOTIONSENSE_TYPE_BARO = 6, + MOTIONSENSE_TYPE_MAX, +}; -/* Set thershold value */ -#define EC_CMD_THERMAL_SET_THRESHOLD 0x50 +/* List of motion sensor locations. */ +enum motionsensor_location { + MOTIONSENSE_LOC_BASE = 0, + MOTIONSENSE_LOC_LID = 1, + MOTIONSENSE_LOC_MAX, +}; -struct ec_params_thermal_set_threshold { - uint8_t sensor_type; - uint8_t threshold_id; - uint16_t value; -} __packed; +/* List of motion sensor chips. */ +enum motionsensor_chip { + MOTIONSENSE_CHIP_KXCJ9 = 0, + MOTIONSENSE_CHIP_LSM6DS0 = 1, + MOTIONSENSE_CHIP_BMI160 = 2, + MOTIONSENSE_CHIP_SI1141 = 3, + MOTIONSENSE_CHIP_SI1142 = 4, + MOTIONSENSE_CHIP_SI1143 = 5, + MOTIONSENSE_CHIP_KX022 = 6, + MOTIONSENSE_CHIP_L3GD20H = 7, + MOTIONSENSE_CHIP_BMA255 = 8, + MOTIONSENSE_CHIP_BMP280 = 9, + MOTIONSENSE_CHIP_OPT3001 = 10, +}; -/* Get threshold value */ -#define EC_CMD_THERMAL_GET_THRESHOLD 0x51 +struct __ec_todo_packed ec_response_motion_sensor_data { + /* Flags for each sensor. */ + uint8_t flags; + /* sensor number the data comes from */ + uint8_t sensor_num; + /* Each sensor is up to 3-axis. */ + union { + int16_t data[3]; + struct __ec_todo_packed { + uint16_t reserved; + uint32_t timestamp; + }; + struct __ec_todo_unpacked { + uint8_t activity; /* motionsensor_activity */ + uint8_t state; + int16_t add_info[2]; + }; + }; +}; -struct ec_params_thermal_get_threshold { - uint8_t sensor_type; - uint8_t threshold_id; -} __packed; +/* Note: used in ec_response_get_next_data */ +struct __ec_todo_packed ec_response_motion_sense_fifo_info { + /* Size of the fifo */ + uint16_t size; + /* Amount of space used in the fifo */ + uint16_t count; + /* Timestamp recorded in us */ + uint32_t timestamp; + /* Total amount of vector lost */ + uint16_t total_lost; + /* Lost events since the last fifo_info, per sensors */ + uint16_t lost[0]; +}; -struct ec_response_thermal_get_threshold { - uint16_t value; -} __packed; +struct __ec_todo_packed ec_response_motion_sense_fifo_data { + uint32_t number_data; + struct ec_response_motion_sensor_data data[0]; +}; -/* Toggle automatic fan control */ -#define EC_CMD_THERMAL_AUTO_FAN_CTRL 0x52 +/* List supported activity recognition */ +enum motionsensor_activity { + MOTIONSENSE_ACTIVITY_RESERVED = 0, + MOTIONSENSE_ACTIVITY_SIG_MOTION = 1, + MOTIONSENSE_ACTIVITY_DOUBLE_TAP = 2, +}; -/* Get TMP006 calibration data */ -#define EC_CMD_TMP006_GET_CALIBRATION 0x53 +struct __ec_todo_unpacked ec_motion_sense_activity { + uint8_t sensor_num; + uint8_t activity; /* one of enum motionsensor_activity */ + uint8_t enable; /* 1: enable, 0: disable */ + uint8_t reserved; + uint16_t parameters[3]; /* activity dependent parameters */ +}; -struct ec_params_tmp006_get_calibration { - uint8_t index; -} __packed; +/* Module flag masks used for the dump sub-command. */ +#define MOTIONSENSE_MODULE_FLAG_ACTIVE (1<<0) -struct ec_response_tmp006_get_calibration { - float s0; - float b0; - float b1; - float b2; -} __packed; +/* Sensor flag masks used for the dump sub-command. */ +#define MOTIONSENSE_SENSOR_FLAG_PRESENT (1<<0) -/* Set TMP006 calibration data */ -#define EC_CMD_TMP006_SET_CALIBRATION 0x54 +/* + * Flush entry for synchronization. + * data contains time stamp + */ +#define MOTIONSENSE_SENSOR_FLAG_FLUSH (1<<0) +#define MOTIONSENSE_SENSOR_FLAG_TIMESTAMP (1<<1) +#define MOTIONSENSE_SENSOR_FLAG_WAKEUP (1<<2) +#define MOTIONSENSE_SENSOR_FLAG_TABLET_MODE (1<<3) -struct ec_params_tmp006_set_calibration { - uint8_t index; - uint8_t reserved[3]; /* Reserved; set 0 */ - float s0; - float b0; - float b1; - float b2; -} __packed; +/* + * Send this value for the data element to only perform a read. If you + * send any other value, the EC will interpret it as data to set and will + * return the actual value set. + */ +#define EC_MOTION_SENSE_NO_VALUE -1 -/*****************************************************************************/ -/* MKBP - Matrix KeyBoard Protocol */ +#define EC_MOTION_SENSE_INVALID_CALIB_TEMP 0x8000 + +/* MOTIONSENSE_CMD_SENSOR_OFFSET subcommand flag */ +/* Set Calibration information */ +#define MOTION_SENSE_SET_OFFSET 1 + +#define LID_ANGLE_UNRELIABLE 500 + +enum motionsense_spoof_mode { + /* Disable spoof mode. */ + MOTIONSENSE_SPOOF_MODE_DISABLE = 0, + + /* Enable spoof mode, but use provided component values. */ + MOTIONSENSE_SPOOF_MODE_CUSTOM, + + /* Enable spoof mode, but use the current sensor values. */ + MOTIONSENSE_SPOOF_MODE_LOCK_CURRENT, + + /* Query the current spoof mode status for the sensor. */ + MOTIONSENSE_SPOOF_MODE_QUERY, +}; + +struct __ec_todo_packed ec_params_motion_sense { + uint8_t cmd; + union { + /* Used for MOTIONSENSE_CMD_DUMP */ + struct __ec_todo_unpacked { + /* + * Maximal number of sensor the host is expecting. + * 0 means the host is only interested in the number + * of sensors controlled by the EC. + */ + uint8_t max_sensor_count; + } dump; + + /* + * Used for MOTIONSENSE_CMD_KB_WAKE_ANGLE. + */ + struct __ec_todo_unpacked { + /* Data to set or EC_MOTION_SENSE_NO_VALUE to read. + * kb_wake_angle: angle to wakup AP. + */ + int16_t data; + } kb_wake_angle; + + /* Used for MOTIONSENSE_CMD_INFO, MOTIONSENSE_CMD_DATA + * and MOTIONSENSE_CMD_PERFORM_CALIB. */ + struct __ec_todo_unpacked { + uint8_t sensor_num; + } info, info_3, data, fifo_flush, perform_calib, + list_activities; + + /* + * Used for MOTIONSENSE_CMD_EC_RATE, MOTIONSENSE_CMD_SENSOR_ODR + * and MOTIONSENSE_CMD_SENSOR_RANGE. + */ + struct __ec_todo_unpacked { + uint8_t sensor_num; + + /* Rounding flag, true for round-up, false for down. */ + uint8_t roundup; + + uint16_t reserved; + + /* Data to set or EC_MOTION_SENSE_NO_VALUE to read. */ + int32_t data; + } ec_rate, sensor_odr, sensor_range; + + /* Used for MOTIONSENSE_CMD_SENSOR_OFFSET */ + struct __ec_todo_packed { + uint8_t sensor_num; + + /* + * bit 0: If set (MOTION_SENSE_SET_OFFSET), set + * the calibration information in the EC. + * If unset, just retrieve calibration information. + */ + uint16_t flags; + + /* + * Temperature at calibration, in units of 0.01 C + * 0x8000: invalid / unknown. + * 0x0: 0C + * 0x7fff: +327.67C + */ + int16_t temp; + + /* + * Offset for calibration. + * Unit: + * Accelerometer: 1/1024 g + * Gyro: 1/1024 deg/s + * Compass: 1/16 uT + */ + int16_t offset[3]; + } sensor_offset; + + /* Used for MOTIONSENSE_CMD_FIFO_INFO */ + struct __ec_todo_unpacked { + } fifo_info; + + /* Used for MOTIONSENSE_CMD_FIFO_READ */ + struct __ec_todo_unpacked { + /* + * Number of expected vector to return. + * EC may return less or 0 if none available. + */ + uint32_t max_data_vector; + } fifo_read; + + struct ec_motion_sense_activity set_activity; + + /* Used for MOTIONSENSE_CMD_LID_ANGLE */ + struct __ec_todo_unpacked { + } lid_angle; + + /* Used for MOTIONSENSE_CMD_FIFO_INT_ENABLE */ + struct __ec_todo_unpacked { + /* + * 1: enable, 0 disable fifo, + * EC_MOTION_SENSE_NO_VALUE return value. + */ + int8_t enable; + } fifo_int_enable; + + /* Used for MOTIONSENSE_CMD_SPOOF */ + struct __ec_todo_packed { + uint8_t sensor_id; + + /* See enum motionsense_spoof_mode. */ + uint8_t spoof_enable; + + /* Ignored, used for alignment. */ + uint8_t reserved; + + /* Individual component values to spoof. */ + int16_t components[3]; + } spoof; + }; +}; + +struct __ec_todo_packed ec_response_motion_sense { + union { + /* Used for MOTIONSENSE_CMD_DUMP */ + struct __ec_todo_unpacked { + /* Flags representing the motion sensor module. */ + uint8_t module_flags; + + /* Number of sensors managed directly by the EC */ + uint8_t sensor_count; + + /* + * sensor data is truncated if response_max is too small + * for holding all the data. + */ + struct ec_response_motion_sensor_data sensor[0]; + } dump; + + /* Used for MOTIONSENSE_CMD_INFO. */ + struct __ec_todo_unpacked { + /* Should be element of enum motionsensor_type. */ + uint8_t type; + + /* Should be element of enum motionsensor_location. */ + uint8_t location; + + /* Should be element of enum motionsensor_chip. */ + uint8_t chip; + } info; + + /* Used for MOTIONSENSE_CMD_INFO version 3 */ + struct __ec_todo_unpacked { + /* Should be element of enum motionsensor_type. */ + uint8_t type; + + /* Should be element of enum motionsensor_location. */ + uint8_t location; + + /* Should be element of enum motionsensor_chip. */ + uint8_t chip; + + /* Minimum sensor sampling frequency */ + uint32_t min_frequency; + + /* Maximum sensor sampling frequency */ + uint32_t max_frequency; + + /* Max number of sensor events that could be in fifo */ + uint32_t fifo_max_event_count; + } info_3; + + /* Used for MOTIONSENSE_CMD_DATA */ + struct ec_response_motion_sensor_data data; + + /* + * Used for MOTIONSENSE_CMD_EC_RATE, MOTIONSENSE_CMD_SENSOR_ODR, + * MOTIONSENSE_CMD_SENSOR_RANGE, + * MOTIONSENSE_CMD_KB_WAKE_ANGLE, + * MOTIONSENSE_CMD_FIFO_INT_ENABLE and + * MOTIONSENSE_CMD_SPOOF. + */ + struct __ec_todo_unpacked { + /* Current value of the parameter queried. */ + int32_t ret; + } ec_rate, sensor_odr, sensor_range, kb_wake_angle, + fifo_int_enable, spoof; + + /* Used for MOTIONSENSE_CMD_SENSOR_OFFSET */ + struct __ec_todo_unpacked { + int16_t temp; + int16_t offset[3]; + } sensor_offset, perform_calib; + + struct ec_response_motion_sense_fifo_info fifo_info, fifo_flush; + + struct ec_response_motion_sense_fifo_data fifo_read; + + struct __ec_todo_packed { + uint16_t reserved; + uint32_t enabled; + uint32_t disabled; + } list_activities; + + struct __ec_todo_unpacked { + } set_activity; + + /* Used for MOTIONSENSE_CMD_LID_ANGLE */ + struct __ec_todo_unpacked { + /* + * Angle between 0 and 360 degree if available, + * LID_ANGLE_UNRELIABLE otherwise. + */ + uint16_t value; + } lid_angle; + }; +}; + +/*****************************************************************************/ +/* Force lid open command */ + +/* Make lid event always open */ +#define EC_CMD_FORCE_LID_OPEN 0x002C + +struct __ec_align1 ec_params_force_lid_open { + uint8_t enabled; +}; + +/*****************************************************************************/ +/* Configure the behavior of the power button */ +#define EC_CMD_CONFIG_POWER_BUTTON 0x002D + +enum ec_config_power_button_flags { + /* Enable/Disable power button pulses for x86 devices */ + EC_POWER_BUTTON_ENABLE_PULSE = (1 << 0), +}; + +struct __ec_align1 ec_params_config_power_button { + /* See enum ec_config_power_button_flags */ + uint8_t flags; +}; + +/*****************************************************************************/ +/* USB charging control commands */ + +/* Set USB port charging mode */ +#define EC_CMD_USB_CHARGE_SET_MODE 0x0030 + +struct __ec_align1 ec_params_usb_charge_set_mode { + uint8_t usb_port_id; + uint8_t mode; +}; + +/*****************************************************************************/ +/* Persistent storage for host */ + +/* Maximum bytes that can be read/written in a single command */ +#define EC_PSTORE_SIZE_MAX 64 + +/* Get persistent storage info */ +#define EC_CMD_PSTORE_INFO 0x0040 + +struct __ec_align4 ec_response_pstore_info { + /* Persistent storage size, in bytes */ + uint32_t pstore_size; + /* Access size; read/write offset and size must be a multiple of this */ + uint32_t access_size; +}; + +/* + * Read persistent storage + * + * Response is params.size bytes of data. + */ +#define EC_CMD_PSTORE_READ 0x0041 + +struct __ec_align4 ec_params_pstore_read { + uint32_t offset; /* Byte offset to read */ + uint32_t size; /* Size to read in bytes */ +}; + +/* Write persistent storage */ +#define EC_CMD_PSTORE_WRITE 0x0042 + +struct __ec_align4 ec_params_pstore_write { + uint32_t offset; /* Byte offset to write */ + uint32_t size; /* Size to write in bytes */ + uint8_t data[EC_PSTORE_SIZE_MAX]; +}; + +/*****************************************************************************/ +/* Real-time clock */ + +/* RTC params and response structures */ +struct __ec_align4 ec_params_rtc { + uint32_t time; +}; + +struct __ec_align4 ec_response_rtc { + uint32_t time; +}; + +/* These use ec_response_rtc */ +#define EC_CMD_RTC_GET_VALUE 0x0044 +#define EC_CMD_RTC_GET_ALARM 0x0045 + +/* These all use ec_params_rtc */ +#define EC_CMD_RTC_SET_VALUE 0x0046 +#define EC_CMD_RTC_SET_ALARM 0x0047 + +/* Pass as time param to SET_ALARM to clear the current alarm */ +#define EC_RTC_ALARM_CLEAR 0 + +/*****************************************************************************/ +/* Port80 log access */ + +/* Maximum entries that can be read/written in a single command */ +#define EC_PORT80_SIZE_MAX 32 + +/* Get last port80 code from previous boot */ +#define EC_CMD_PORT80_LAST_BOOT 0x0048 +#define EC_CMD_PORT80_READ 0x0048 + +enum ec_port80_subcmd { + EC_PORT80_GET_INFO = 0, + EC_PORT80_READ_BUFFER, +}; + +struct __ec_todo_packed ec_params_port80_read { + uint16_t subcmd; + union { + struct __ec_todo_unpacked { + uint32_t offset; + uint32_t num_entries; + } read_buffer; + }; +}; + +struct __ec_todo_packed ec_response_port80_read { + union { + struct __ec_todo_unpacked { + uint32_t writes; + uint32_t history_size; + uint32_t last_boot; + } get_info; + struct __ec_todo_unpacked { + uint16_t codes[EC_PORT80_SIZE_MAX]; + } data; + }; +}; + +struct __ec_align2 ec_response_port80_last_boot { + uint16_t code; +}; + +/*****************************************************************************/ +/* Temporary secure storage for host verified boot use */ + +/* Number of bytes in a vstore slot */ +#define EC_VSTORE_SLOT_SIZE 64 + +/* Maximum number of vstore slots */ +#define EC_VSTORE_SLOT_MAX 32 + +/* Get persistent storage info */ +#define EC_CMD_VSTORE_INFO 0x0049 +struct __ec_align_size1 ec_response_vstore_info { + /* Indicates which slots are locked */ + uint32_t slot_locked; + /* Total number of slots available */ + uint8_t slot_count; +}; + +/* + * Read temporary secure storage + * + * Response is EC_VSTORE_SLOT_SIZE bytes of data. + */ +#define EC_CMD_VSTORE_READ 0x004A + +struct __ec_align1 ec_params_vstore_read { + uint8_t slot; /* Slot to read from */ +}; + +struct __ec_align1 ec_response_vstore_read { + uint8_t data[EC_VSTORE_SLOT_SIZE]; +}; + +/* + * Write temporary secure storage and lock it. + */ +#define EC_CMD_VSTORE_WRITE 0x004B + +struct __ec_align1 ec_params_vstore_write { + uint8_t slot; /* Slot to write to */ + uint8_t data[EC_VSTORE_SLOT_SIZE]; +}; + +/*****************************************************************************/ +/* Thermal engine commands. Note that there are two implementations. We'll + * reuse the command number, but the data and behavior is incompatible. + * Version 0 is what originally shipped on Link. + * Version 1 separates the CPU thermal limits from the fan control. + */ + +#define EC_CMD_THERMAL_SET_THRESHOLD 0x0050 +#define EC_CMD_THERMAL_GET_THRESHOLD 0x0051 + +/* The version 0 structs are opaque. You have to know what they are for + * the get/set commands to make any sense. + */ + +/* Version 0 - set */ +struct __ec_align2 ec_params_thermal_set_threshold { + uint8_t sensor_type; + uint8_t threshold_id; + uint16_t value; +}; + +/* Version 0 - get */ +struct __ec_align1 ec_params_thermal_get_threshold { + uint8_t sensor_type; + uint8_t threshold_id; +}; + +struct __ec_align2 ec_response_thermal_get_threshold { + uint16_t value; +}; + + +/* The version 1 structs are visible. */ +enum ec_temp_thresholds { + EC_TEMP_THRESH_WARN = 0, + EC_TEMP_THRESH_HIGH, + EC_TEMP_THRESH_HALT, + + EC_TEMP_THRESH_COUNT +}; + +/* + * Thermal configuration for one temperature sensor. Temps are in degrees K. + * Zero values will be silently ignored by the thermal task. + * + * Note that this structure is a sub-structure of + * ec_params_thermal_set_threshold_v1, but maintains its alignment there. + */ +struct __ec_align4 ec_thermal_config { + uint32_t temp_host[EC_TEMP_THRESH_COUNT]; /* levels of hotness */ + uint32_t temp_fan_off; /* no active cooling needed */ + uint32_t temp_fan_max; /* max active cooling needed */ +}; + +/* Version 1 - get config for one sensor. */ +struct __ec_align4 ec_params_thermal_get_threshold_v1 { + uint32_t sensor_num; +}; +/* This returns a struct ec_thermal_config */ + +/* Version 1 - set config for one sensor. + * Use read-modify-write for best results! */ +struct __ec_align4 ec_params_thermal_set_threshold_v1 { + uint32_t sensor_num; + struct ec_thermal_config cfg; +}; +/* This returns no data */ + +/****************************************************************************/ + +/* Toggle automatic fan control */ +#define EC_CMD_THERMAL_AUTO_FAN_CTRL 0x0052 + +/* Version 1 of input params */ +struct __ec_align1 ec_params_auto_fan_ctrl_v1 { + uint8_t fan_idx; +}; + +/* Get/Set TMP006 calibration data */ +#define EC_CMD_TMP006_GET_CALIBRATION 0x0053 +#define EC_CMD_TMP006_SET_CALIBRATION 0x0054 + +/* + * The original TMP006 calibration only needed four params, but now we need + * more. Since the algorithm is nothing but magic numbers anyway, we'll leave + * the params opaque. The v1 "get" response will include the algorithm number + * and how many params it requires. That way we can change the EC code without + * needing to update this file. We can also use a different algorithm on each + * sensor. + */ + +/* This is the same struct for both v0 and v1. */ +struct __ec_align1 ec_params_tmp006_get_calibration { + uint8_t index; +}; + +/* Version 0 */ +struct __ec_align4 ec_response_tmp006_get_calibration_v0 { + float s0; + float b0; + float b1; + float b2; +}; + +struct __ec_align4 ec_params_tmp006_set_calibration_v0 { + uint8_t index; + uint8_t reserved[3]; + float s0; + float b0; + float b1; + float b2; +}; + +/* Version 1 */ +struct __ec_align4 ec_response_tmp006_get_calibration_v1 { + uint8_t algorithm; + uint8_t num_params; + uint8_t reserved[2]; + float val[0]; +}; + +struct __ec_align4 ec_params_tmp006_set_calibration_v1 { + uint8_t index; + uint8_t algorithm; + uint8_t num_params; + uint8_t reserved; + float val[0]; +}; + + +/* Read raw TMP006 data */ +#define EC_CMD_TMP006_GET_RAW 0x0055 + +struct __ec_align1 ec_params_tmp006_get_raw { + uint8_t index; +}; + +struct __ec_align4 ec_response_tmp006_get_raw { + int32_t t; /* In 1/100 K */ + int32_t v; /* In nV */ +}; + +/*****************************************************************************/ +/* MKBP - Matrix KeyBoard Protocol */ /* * Read key state * * Returns raw data for keyboard cols; see ec_response_mkbp_info.cols for * expected response size. + * + * NOTE: This has been superseded by EC_CMD_MKBP_GET_NEXT_EVENT. If you wish + * to obtain the instantaneous state, use EC_CMD_MKBP_INFO with the type + * EC_MKBP_INFO_CURRENT and event EC_MKBP_EVENT_KEY_MATRIX. */ -#define EC_CMD_MKBP_STATE 0x60 +#define EC_CMD_MKBP_STATE 0x0060 + +/* + * Provide information about various MKBP things. See enum ec_mkbp_info_type. + */ +#define EC_CMD_MKBP_INFO 0x0061 + +struct __ec_align_size1 ec_response_mkbp_info { + uint32_t rows; + uint32_t cols; + /* Formerly "switches", which was 0. */ + uint8_t reserved; +}; + +struct __ec_align1 ec_params_mkbp_info { + uint8_t info_type; + uint8_t event_type; +}; + +enum ec_mkbp_info_type { + /* + * Info about the keyboard matrix: number of rows and columns. + * + * Returns struct ec_response_mkbp_info. + */ + EC_MKBP_INFO_KBD = 0, + + /* + * For buttons and switches, info about which specifically are + * supported. event_type must be set to one of the values in enum + * ec_mkbp_event. + * + * For EC_MKBP_EVENT_BUTTON and EC_MKBP_EVENT_SWITCH, returns a 4 byte + * bitmask indicating which buttons or switches are present. See the + * bit inidices below. + */ + EC_MKBP_INFO_SUPPORTED = 1, + + /* + * Instantaneous state of buttons and switches. + * + * event_type must be set to one of the values in enum ec_mkbp_event. + * + * For EC_MKBP_EVENT_KEY_MATRIX, returns uint8_t key_matrix[13] + * indicating the current state of the keyboard matrix. + * + * For EC_MKBP_EVENT_HOST_EVENT, return uint32_t host_event, the raw + * event state. + * + * For EC_MKBP_EVENT_BUTTON, returns uint32_t buttons, indicating the + * state of supported buttons. + * + * For EC_MKBP_EVENT_SWITCH, returns uint32_t switches, indicating the + * state of supported switches. + */ + EC_MKBP_INFO_CURRENT = 2, +}; + +/* Simulate key press */ +#define EC_CMD_MKBP_SIMULATE_KEY 0x0062 + +struct __ec_align1 ec_params_mkbp_simulate_key { + uint8_t col; + uint8_t row; + uint8_t pressed; +}; + +/* Configure keyboard scanning */ +#define EC_CMD_MKBP_SET_CONFIG 0x0064 +#define EC_CMD_MKBP_GET_CONFIG 0x0065 + +/* flags */ +enum mkbp_config_flags { + EC_MKBP_FLAGS_ENABLE = 1, /* Enable keyboard scanning */ +}; + +enum mkbp_config_valid { + EC_MKBP_VALID_SCAN_PERIOD = 1 << 0, + EC_MKBP_VALID_POLL_TIMEOUT = 1 << 1, + EC_MKBP_VALID_MIN_POST_SCAN_DELAY = 1 << 3, + EC_MKBP_VALID_OUTPUT_SETTLE = 1 << 4, + EC_MKBP_VALID_DEBOUNCE_DOWN = 1 << 5, + EC_MKBP_VALID_DEBOUNCE_UP = 1 << 6, + EC_MKBP_VALID_FIFO_MAX_DEPTH = 1 << 7, +}; + +/* + * Configuration for our key scanning algorithm. + * + * Note that this is used as a sub-structure of + * ec_{params/response}_mkbp_get_config. + */ +struct __ec_align_size1 ec_mkbp_config { + uint32_t valid_mask; /* valid fields */ + uint8_t flags; /* some flags (enum mkbp_config_flags) */ + uint8_t valid_flags; /* which flags are valid */ + uint16_t scan_period_us; /* period between start of scans */ + /* revert to interrupt mode after no activity for this long */ + uint32_t poll_timeout_us; + /* + * minimum post-scan relax time. Once we finish a scan we check + * the time until we are due to start the next one. If this time is + * shorter this field, we use this instead. + */ + uint16_t min_post_scan_delay_us; + /* delay between setting up output and waiting for it to settle */ + uint16_t output_settle_us; + uint16_t debounce_down_us; /* time for debounce on key down */ + uint16_t debounce_up_us; /* time for debounce on key up */ + /* maximum depth to allow for fifo (0 = no keyscan output) */ + uint8_t fifo_max_depth; +}; + +struct __ec_align_size1 ec_params_mkbp_set_config { + struct ec_mkbp_config config; +}; + +struct __ec_align_size1 ec_response_mkbp_get_config { + struct ec_mkbp_config config; +}; + +/* Run the key scan emulation */ +#define EC_CMD_KEYSCAN_SEQ_CTRL 0x0066 + +enum ec_keyscan_seq_cmd { + EC_KEYSCAN_SEQ_STATUS = 0, /* Get status information */ + EC_KEYSCAN_SEQ_CLEAR = 1, /* Clear sequence */ + EC_KEYSCAN_SEQ_ADD = 2, /* Add item to sequence */ + EC_KEYSCAN_SEQ_START = 3, /* Start running sequence */ + EC_KEYSCAN_SEQ_COLLECT = 4, /* Collect sequence summary data */ +}; + +enum ec_collect_flags { + /* + * Indicates this scan was processed by the EC. Due to timing, some + * scans may be skipped. + */ + EC_KEYSCAN_SEQ_FLAG_DONE = 1 << 0, +}; + +struct __ec_align1 ec_collect_item { + uint8_t flags; /* some flags (enum ec_collect_flags) */ +}; + +struct __ec_todo_packed ec_params_keyscan_seq_ctrl { + uint8_t cmd; /* Command to send (enum ec_keyscan_seq_cmd) */ + union { + struct __ec_align1 { + uint8_t active; /* still active */ + uint8_t num_items; /* number of items */ + /* Current item being presented */ + uint8_t cur_item; + } status; + struct __ec_todo_unpacked { + /* + * Absolute time for this scan, measured from the + * start of the sequence. + */ + uint32_t time_us; + uint8_t scan[0]; /* keyscan data */ + } add; + struct __ec_align1 { + uint8_t start_item; /* First item to return */ + uint8_t num_items; /* Number of items to return */ + } collect; + }; +}; + +struct __ec_todo_packed ec_result_keyscan_seq_ctrl { + union { + struct __ec_todo_unpacked { + uint8_t num_items; /* Number of items */ + /* Data for each item */ + struct ec_collect_item item[0]; + } collect; + }; +}; + +/* + * Get the next pending MKBP event. + * + * Returns EC_RES_UNAVAILABLE if there is no event pending. + */ +#define EC_CMD_GET_NEXT_EVENT 0x0067 + +enum ec_mkbp_event { + /* Keyboard matrix changed. The event data is the new matrix state. */ + EC_MKBP_EVENT_KEY_MATRIX = 0, + + /* New host event. The event data is 4 bytes of host event flags. */ + EC_MKBP_EVENT_HOST_EVENT = 1, + + /* New Sensor FIFO data. The event data is fifo_info structure. */ + EC_MKBP_EVENT_SENSOR_FIFO = 2, + + /* The state of the non-matrixed buttons have changed. */ + EC_MKBP_EVENT_BUTTON = 3, + + /* The state of the switches have changed. */ + EC_MKBP_EVENT_SWITCH = 4, + + /* New Fingerprint sensor event, the event data is fp_events bitmap. */ + EC_MKBP_EVENT_FINGERPRINT = 5, + + /* + * Sysrq event: send emulated sysrq. The event data is sysrq, + * corresponding to the key to be pressed. + */ + EC_MKBP_EVENT_SYSRQ = 6, + + /* Number of MKBP events */ + EC_MKBP_EVENT_COUNT, +}; + +union __ec_align_offset1 ec_response_get_next_data { + uint8_t key_matrix[13]; + + /* Unaligned */ + uint32_t host_event; + + struct __ec_todo_unpacked { + /* For aligning the fifo_info */ + uint8_t reserved[3]; + struct ec_response_motion_sense_fifo_info info; + } sensor_fifo; + + uint32_t buttons; + + uint32_t switches; + + uint32_t fp_events; + + uint32_t sysrq; +}; + +struct __ec_align1 ec_response_get_next_event { + uint8_t event_type; + /* Followed by event data if any */ + union ec_response_get_next_data data; +}; + +/* Bit indices for buttons and switches.*/ +/* Buttons */ +#define EC_MKBP_POWER_BUTTON 0 +#define EC_MKBP_VOL_UP 1 +#define EC_MKBP_VOL_DOWN 2 +#define EC_MKBP_RECOVERY 3 + +/* Switches */ +#define EC_MKBP_LID_OPEN 0 +#define EC_MKBP_TABLET_MODE 1 + +/* Run keyboard factory test scanning */ +#define EC_CMD_KEYBOARD_FACTORY_TEST 0x0068 + +struct __ec_align2 ec_response_keyboard_factory_test { + uint16_t shorted; /* Keyboard pins are shorted */ +}; + +/* Fingerprint events in 'fp_events' for EC_MKBP_EVENT_FINGERPRINT */ +#define EC_MKBP_FP_RAW_EVENT(fp_events) ((fp_events) & 0x00FFFFFF) +#define EC_MKBP_FP_FINGER_DOWN (1 << 29) +#define EC_MKBP_FP_FINGER_UP (1 << 30) +#define EC_MKBP_FP_IMAGE_READY (1 << 31) + +/*****************************************************************************/ +/* Temperature sensor commands */ + +/* Read temperature sensor info */ +#define EC_CMD_TEMP_SENSOR_GET_INFO 0x0070 + +struct __ec_align1 ec_params_temp_sensor_get_info { + uint8_t id; +}; + +struct __ec_align1 ec_response_temp_sensor_get_info { + char sensor_name[32]; + uint8_t sensor_type; +}; + +/*****************************************************************************/ + +/* + * Note: host commands 0x80 - 0x87 are reserved to avoid conflict with ACPI + * commands accidentally sent to the wrong interface. See the ACPI section + * below. + */ + +/*****************************************************************************/ +/* Host event commands */ + + +/* Obsolete. New implementation should use EC_CMD_PROGRAM_HOST_EVENT instead */ +/* + * Host event mask params and response structures, shared by all of the host + * event commands below. + */ +struct __ec_align4 ec_params_host_event_mask { + uint32_t mask; +}; + +struct __ec_align4 ec_response_host_event_mask { + uint32_t mask; +}; + +/* These all use ec_response_host_event_mask */ +#define EC_CMD_HOST_EVENT_GET_B 0x0087 +#define EC_CMD_HOST_EVENT_GET_SMI_MASK 0x0088 +#define EC_CMD_HOST_EVENT_GET_SCI_MASK 0x0089 +#define EC_CMD_HOST_EVENT_GET_WAKE_MASK 0x008D + +/* These all use ec_params_host_event_mask */ +#define EC_CMD_HOST_EVENT_SET_SMI_MASK 0x008A +#define EC_CMD_HOST_EVENT_SET_SCI_MASK 0x008B +#define EC_CMD_HOST_EVENT_CLEAR 0x008C +#define EC_CMD_HOST_EVENT_SET_WAKE_MASK 0x008E +#define EC_CMD_HOST_EVENT_CLEAR_B 0x008F + +/* + * Unified host event programming interface - Should be used by newer versions + * of BIOS/OS to program host events and masks + */ + +struct __ec_align4 ec_params_host_event { + + /* Action requested by host - one of enum ec_host_event_action. */ + uint8_t action; + + /* + * Mask type that the host requested the action on - one of + * enum ec_host_event_mask_type. + */ + uint8_t mask_type; + + /* Set to 0, ignore on read */ + uint16_t reserved; + + /* Value to be used in case of set operations. */ + uint64_t value; +}; + +/* + * Response structure returned by EC_CMD_HOST_EVENT. + * Update the value on a GET request. Set to 0 on GET/CLEAR + */ + +struct __ec_align4 ec_response_host_event { + + /* Mask value in case of get operation */ + uint64_t value; +}; + +enum ec_host_event_action { + /* + * params.value is ignored. Value of mask_type populated + * in response.value + */ + EC_HOST_EVENT_GET, + + /* Bits in params.value are set */ + EC_HOST_EVENT_SET, + + /* Bits in params.value are cleared */ + EC_HOST_EVENT_CLEAR, +}; + +enum ec_host_event_mask_type { + + /* Main host event copy */ + EC_HOST_EVENT_MAIN, + + /* Copy B of host events */ + EC_HOST_EVENT_B, + + /* SCI Mask */ + EC_HOST_EVENT_SCI_MASK, + + /* SMI Mask */ + EC_HOST_EVENT_SMI_MASK, + + /* Mask of events that should be always reported in hostevents */ + EC_HOST_EVENT_ALWAYS_REPORT_MASK, + + /* Active wake mask */ + EC_HOST_EVENT_ACTIVE_WAKE_MASK, + + /* Lazy wake mask for S0ix */ + EC_HOST_EVENT_LAZY_WAKE_MASK_S0IX, + + /* Lazy wake mask for S3 */ + EC_HOST_EVENT_LAZY_WAKE_MASK_S3, + + /* Lazy wake mask for S5 */ + EC_HOST_EVENT_LAZY_WAKE_MASK_S5, +}; + +#define EC_CMD_HOST_EVENT 0x00A4 + +/*****************************************************************************/ +/* Switch commands */ + +/* Enable/disable LCD backlight */ +#define EC_CMD_SWITCH_ENABLE_BKLIGHT 0x0090 + +struct __ec_align1 ec_params_switch_enable_backlight { + uint8_t enabled; +}; + +/* Enable/disable WLAN/Bluetooth */ +#define EC_CMD_SWITCH_ENABLE_WIRELESS 0x0091 +#define EC_VER_SWITCH_ENABLE_WIRELESS 1 + +/* Version 0 params; no response */ +struct __ec_align1 ec_params_switch_enable_wireless_v0 { + uint8_t enabled; +}; + +/* Version 1 params */ +struct __ec_align1 ec_params_switch_enable_wireless_v1 { + /* Flags to enable now */ + uint8_t now_flags; + + /* Which flags to copy from now_flags */ + uint8_t now_mask; + + /* + * Flags to leave enabled in S3, if they're on at the S0->S3 + * transition. (Other flags will be disabled by the S0->S3 + * transition.) + */ + uint8_t suspend_flags; + + /* Which flags to copy from suspend_flags */ + uint8_t suspend_mask; +}; + +/* Version 1 response */ +struct __ec_align1 ec_response_switch_enable_wireless_v1 { + /* Flags to enable now */ + uint8_t now_flags; + + /* Flags to leave enabled in S3 */ + uint8_t suspend_flags; +}; + +/*****************************************************************************/ +/* GPIO commands. Only available on EC if write protect has been disabled. */ + +/* Set GPIO output value */ +#define EC_CMD_GPIO_SET 0x0092 + +struct __ec_align1 ec_params_gpio_set { + char name[32]; + uint8_t val; +}; + +/* Get GPIO value */ +#define EC_CMD_GPIO_GET 0x0093 + +/* Version 0 of input params and response */ +struct __ec_align1 ec_params_gpio_get { + char name[32]; +}; + +struct __ec_align1 ec_response_gpio_get { + uint8_t val; +}; + +/* Version 1 of input params and response */ +struct __ec_align1 ec_params_gpio_get_v1 { + uint8_t subcmd; + union { + struct __ec_align1 { + char name[32]; + } get_value_by_name; + struct __ec_align1 { + uint8_t index; + } get_info; + }; +}; + +struct __ec_todo_packed ec_response_gpio_get_v1 { + union { + struct __ec_align1 { + uint8_t val; + } get_value_by_name, get_count; + struct __ec_todo_unpacked { + uint8_t val; + char name[32]; + uint32_t flags; + } get_info; + }; +}; + +enum gpio_get_subcmd { + EC_GPIO_GET_BY_NAME = 0, + EC_GPIO_GET_COUNT = 1, + EC_GPIO_GET_INFO = 2, +}; + +/*****************************************************************************/ +/* I2C commands. Only available when flash write protect is unlocked. */ + +/* + * CAUTION: These commands are deprecated, and are not supported anymore in EC + * builds >= 8398.0.0 (see crosbug.com/p/23570). + * + * Use EC_CMD_I2C_PASSTHRU instead. + */ + +/* Read I2C bus */ +#define EC_CMD_I2C_READ 0x0094 + +struct __ec_align_size1 ec_params_i2c_read { + uint16_t addr; /* 8-bit address (7-bit shifted << 1) */ + uint8_t read_size; /* Either 8 or 16. */ + uint8_t port; + uint8_t offset; +}; + +struct __ec_align2 ec_response_i2c_read { + uint16_t data; +}; + +/* Write I2C bus */ +#define EC_CMD_I2C_WRITE 0x0095 + +struct __ec_align_size1 ec_params_i2c_write { + uint16_t data; + uint16_t addr; /* 8-bit address (7-bit shifted << 1) */ + uint8_t write_size; /* Either 8 or 16. */ + uint8_t port; + uint8_t offset; +}; + +/*****************************************************************************/ +/* Charge state commands. Only available when flash write protect unlocked. */ + +/* Force charge state machine to stop charging the battery or force it to + * discharge the battery. + */ +#define EC_CMD_CHARGE_CONTROL 0x0096 +#define EC_VER_CHARGE_CONTROL 1 + +enum ec_charge_control_mode { + CHARGE_CONTROL_NORMAL = 0, + CHARGE_CONTROL_IDLE, + CHARGE_CONTROL_DISCHARGE, +}; + +struct __ec_align4 ec_params_charge_control { + uint32_t mode; /* enum charge_control_mode */ +}; + +/*****************************************************************************/ +/* Console commands. Only available when flash write protect is unlocked. */ + +/* Snapshot console output buffer for use by EC_CMD_CONSOLE_READ. */ +#define EC_CMD_CONSOLE_SNAPSHOT 0x0097 + +/* + * Read data from the saved snapshot. If the subcmd parameter is + * CONSOLE_READ_NEXT, this will return data starting from the beginning of + * the latest snapshot. If it is CONSOLE_READ_RECENT, it will start from the + * end of the previous snapshot. + * + * The params are only looked at in version >= 1 of this command. Prior + * versions will just default to CONSOLE_READ_NEXT behavior. + * + * Response is null-terminated string. Empty string, if there is no more + * remaining output. + */ +#define EC_CMD_CONSOLE_READ 0x0098 + +enum ec_console_read_subcmd { + CONSOLE_READ_NEXT = 0, + CONSOLE_READ_RECENT +}; + +struct __ec_align1 ec_params_console_read_v1 { + uint8_t subcmd; /* enum ec_console_read_subcmd */ +}; + +/*****************************************************************************/ + +/* + * Cut off battery power immediately or after the host has shut down. + * + * return EC_RES_INVALID_COMMAND if unsupported by a board/battery. + * EC_RES_SUCCESS if the command was successful. + * EC_RES_ERROR if the cut off command failed. + */ +#define EC_CMD_BATTERY_CUT_OFF 0x0099 + +#define EC_BATTERY_CUTOFF_FLAG_AT_SHUTDOWN (1 << 0) + +struct __ec_align1 ec_params_battery_cutoff { + uint8_t flags; +}; + +/*****************************************************************************/ +/* USB port mux control. */ + +/* + * Switch USB mux or return to automatic switching. + */ +#define EC_CMD_USB_MUX 0x009A + +struct __ec_align1 ec_params_usb_mux { + uint8_t mux; +}; + +/*****************************************************************************/ +/* LDOs / FETs control. */ + +enum ec_ldo_state { + EC_LDO_STATE_OFF = 0, /* the LDO / FET is shut down */ + EC_LDO_STATE_ON = 1, /* the LDO / FET is ON / providing power */ +}; + +/* + * Switch on/off a LDO. + */ +#define EC_CMD_LDO_SET 0x009B + +struct __ec_align1 ec_params_ldo_set { + uint8_t index; + uint8_t state; +}; + +/* + * Get LDO state. + */ +#define EC_CMD_LDO_GET 0x009C + +struct __ec_align1 ec_params_ldo_get { + uint8_t index; +}; + +struct __ec_align1 ec_response_ldo_get { + uint8_t state; +}; + +/*****************************************************************************/ +/* Power info. */ + +/* + * Get power info. + */ +#define EC_CMD_POWER_INFO 0x009D + +struct __ec_align4 ec_response_power_info { + uint32_t usb_dev_type; + uint16_t voltage_ac; + uint16_t voltage_system; + uint16_t current_system; + uint16_t usb_current_limit; +}; + +/*****************************************************************************/ +/* I2C passthru command */ + +#define EC_CMD_I2C_PASSTHRU 0x009E + +/* Read data; if not present, message is a write */ +#define EC_I2C_FLAG_READ (1 << 15) + +/* Mask for address */ +#define EC_I2C_ADDR_MASK 0x3ff + +#define EC_I2C_STATUS_NAK (1 << 0) /* Transfer was not acknowledged */ +#define EC_I2C_STATUS_TIMEOUT (1 << 1) /* Timeout during transfer */ + +/* Any error */ +#define EC_I2C_STATUS_ERROR (EC_I2C_STATUS_NAK | EC_I2C_STATUS_TIMEOUT) + +struct __ec_align2 ec_params_i2c_passthru_msg { + uint16_t addr_flags; /* I2C slave address (7 or 10 bits) and flags */ + uint16_t len; /* Number of bytes to read or write */ +}; + +struct __ec_align2 ec_params_i2c_passthru { + uint8_t port; /* I2C port number */ + uint8_t num_msgs; /* Number of messages */ + struct ec_params_i2c_passthru_msg msg[]; + /* Data to write for all messages is concatenated here */ +}; + +struct __ec_align1 ec_response_i2c_passthru { + uint8_t i2c_status; /* Status flags (EC_I2C_STATUS_...) */ + uint8_t num_msgs; /* Number of messages processed */ + uint8_t data[]; /* Data read by messages concatenated here */ +}; + +/*****************************************************************************/ +/* Power button hang detect */ + +#define EC_CMD_HANG_DETECT 0x009F + +/* Reasons to start hang detection timer */ +/* Power button pressed */ +#define EC_HANG_START_ON_POWER_PRESS (1 << 0) + +/* Lid closed */ +#define EC_HANG_START_ON_LID_CLOSE (1 << 1) + + /* Lid opened */ +#define EC_HANG_START_ON_LID_OPEN (1 << 2) + +/* Start of AP S3->S0 transition (booting or resuming from suspend) */ +#define EC_HANG_START_ON_RESUME (1 << 3) + +/* Reasons to cancel hang detection */ + +/* Power button released */ +#define EC_HANG_STOP_ON_POWER_RELEASE (1 << 8) + +/* Any host command from AP received */ +#define EC_HANG_STOP_ON_HOST_COMMAND (1 << 9) + +/* Stop on end of AP S0->S3 transition (suspending or shutting down) */ +#define EC_HANG_STOP_ON_SUSPEND (1 << 10) + +/* + * If this flag is set, all the other fields are ignored, and the hang detect + * timer is started. This provides the AP a way to start the hang timer + * without reconfiguring any of the other hang detect settings. Note that + * you must previously have configured the timeouts. + */ +#define EC_HANG_START_NOW (1 << 30) + +/* + * If this flag is set, all the other fields are ignored (including + * EC_HANG_START_NOW). This provides the AP a way to stop the hang timer + * without reconfiguring any of the other hang detect settings. + */ +#define EC_HANG_STOP_NOW (1 << 31) + +struct __ec_align4 ec_params_hang_detect { + /* Flags; see EC_HANG_* */ + uint32_t flags; + + /* Timeout in msec before generating host event, if enabled */ + uint16_t host_event_timeout_msec; + + /* Timeout in msec before generating warm reboot, if enabled */ + uint16_t warm_reboot_timeout_msec; +}; + +/*****************************************************************************/ +/* Commands for battery charging */ + +/* + * This is the single catch-all host command to exchange data regarding the + * charge state machine (v2 and up). + */ +#define EC_CMD_CHARGE_STATE 0x00A0 + +/* Subcommands for this host command */ +enum charge_state_command { + CHARGE_STATE_CMD_GET_STATE, + CHARGE_STATE_CMD_GET_PARAM, + CHARGE_STATE_CMD_SET_PARAM, + CHARGE_STATE_NUM_CMDS +}; + +/* + * Known param numbers are defined here. Ranges are reserved for board-specific + * params, which are handled by the particular implementations. + */ +enum charge_state_params { + CS_PARAM_CHG_VOLTAGE, /* charger voltage limit */ + CS_PARAM_CHG_CURRENT, /* charger current limit */ + CS_PARAM_CHG_INPUT_CURRENT, /* charger input current limit */ + CS_PARAM_CHG_STATUS, /* charger-specific status */ + CS_PARAM_CHG_OPTION, /* charger-specific options */ + CS_PARAM_LIMIT_POWER, /* + * Check if power is limited due to + * low battery and / or a weak external + * charger. READ ONLY. + */ + /* How many so far? */ + CS_NUM_BASE_PARAMS, + + /* Range for CONFIG_CHARGER_PROFILE_OVERRIDE params */ + CS_PARAM_CUSTOM_PROFILE_MIN = 0x10000, + CS_PARAM_CUSTOM_PROFILE_MAX = 0x1ffff, + + /* Other custom param ranges go here... */ +}; + +struct __ec_todo_packed ec_params_charge_state { + uint8_t cmd; /* enum charge_state_command */ + union { + struct __ec_align1 { + /* no args */ + } get_state; + + struct __ec_todo_unpacked { + uint32_t param; /* enum charge_state_param */ + } get_param; + + struct __ec_todo_unpacked { + uint32_t param; /* param to set */ + uint32_t value; /* value to set */ + } set_param; + }; +}; + +struct __ec_align4 ec_response_charge_state { + union { + struct __ec_align4 { + int ac; + int chg_voltage; + int chg_current; + int chg_input_current; + int batt_state_of_charge; + } get_state; + + struct __ec_align4 { + uint32_t value; + } get_param; + struct __ec_align4 { + /* no return values */ + } set_param; + }; +}; + + +/* + * Set maximum battery charging current. + */ +#define EC_CMD_CHARGE_CURRENT_LIMIT 0x00A1 + +struct __ec_align4 ec_params_current_limit { + uint32_t limit; /* in mA */ +}; + +/* + * Set maximum external voltage / current. + */ +#define EC_CMD_EXTERNAL_POWER_LIMIT 0x00A2 + +/* Command v0 is used only on Spring and is obsolete + unsupported */ +struct __ec_align2 ec_params_external_power_limit_v1 { + uint16_t current_lim; /* in mA, or EC_POWER_LIMIT_NONE to clear limit */ + uint16_t voltage_lim; /* in mV, or EC_POWER_LIMIT_NONE to clear limit */ +}; + +#define EC_POWER_LIMIT_NONE 0xffff + +/* + * Set maximum voltage & current of a dedicated charge port + */ +#define EC_CMD_OVERRIDE_DEDICATED_CHARGER_LIMIT 0x00A3 + +struct __ec_align2 ec_params_dedicated_charger_limit { + uint16_t current_lim; /* in mA */ + uint16_t voltage_lim; /* in mV */ +}; + +/*****************************************************************************/ +/* Hibernate/Deep Sleep Commands */ + +/* Set the delay before going into hibernation. */ +#define EC_CMD_HIBERNATION_DELAY 0x00A8 + +struct __ec_align4 ec_params_hibernation_delay { + /* + * Seconds to wait in G3 before hibernate. Pass in 0 to read the + * current settings without changing them. + */ + uint32_t seconds; +}; + +struct __ec_align4 ec_response_hibernation_delay { + /* + * The current time in seconds in which the system has been in the G3 + * state. This value is reset if the EC transitions out of G3. + */ + uint32_t time_g3; + + /* + * The current time remaining in seconds until the EC should hibernate. + * This value is also reset if the EC transitions out of G3. + */ + uint32_t time_remaining; + + /* + * The current time in seconds that the EC should wait in G3 before + * hibernating. + */ + uint32_t hibernate_delay; +}; + +/* Inform the EC when entering a sleep state */ +#define EC_CMD_HOST_SLEEP_EVENT 0x00A9 + +enum host_sleep_event { + HOST_SLEEP_EVENT_S3_SUSPEND = 1, + HOST_SLEEP_EVENT_S3_RESUME = 2, + HOST_SLEEP_EVENT_S0IX_SUSPEND = 3, + HOST_SLEEP_EVENT_S0IX_RESUME = 4 +}; + +struct __ec_align1 ec_params_host_sleep_event { + uint8_t sleep_event; +}; + +/*****************************************************************************/ +/* Device events */ +#define EC_CMD_DEVICE_EVENT 0x00AA + +enum ec_device_event { + EC_DEVICE_EVENT_TRACKPAD, + EC_DEVICE_EVENT_DSP, + EC_DEVICE_EVENT_WIFI, +}; + +enum ec_device_event_param { + /* Get and clear pending device events */ + EC_DEVICE_EVENT_PARAM_GET_CURRENT_EVENTS, + /* Get device event mask */ + EC_DEVICE_EVENT_PARAM_GET_ENABLED_EVENTS, + /* Set device event mask */ + EC_DEVICE_EVENT_PARAM_SET_ENABLED_EVENTS, +}; + +#define EC_DEVICE_EVENT_MASK(event_code) (1UL << (event_code % 32)) -/* Provide information about the matrix : number of rows and columns */ -#define EC_CMD_MKBP_INFO 0x61 +struct __ec_align_size1 ec_params_device_event { + uint32_t event_mask; + uint8_t param; +}; -struct ec_response_mkbp_info { - uint32_t rows; - uint32_t cols; - uint8_t switches; -} __packed; +struct __ec_align4 ec_response_device_event { + uint32_t event_mask; +}; -/* Simulate key press */ -#define EC_CMD_MKBP_SIMULATE_KEY 0x62 +/*****************************************************************************/ +/* Smart battery pass-through */ -struct ec_params_mkbp_simulate_key { - uint8_t col; - uint8_t row; - uint8_t pressed; -} __packed; +/* Get / Set 16-bit smart battery registers */ +#define EC_CMD_SB_READ_WORD 0x00B0 +#define EC_CMD_SB_WRITE_WORD 0x00B1 -/* Configure keyboard scanning */ -#define EC_CMD_MKBP_SET_CONFIG 0x64 -#define EC_CMD_MKBP_GET_CONFIG 0x65 +/* Get / Set string smart battery parameters + * formatted as SMBUS "block". + */ +#define EC_CMD_SB_READ_BLOCK 0x00B2 +#define EC_CMD_SB_WRITE_BLOCK 0x00B3 -/* flags */ -enum mkbp_config_flags { - EC_MKBP_FLAGS_ENABLE = 1, /* Enable keyboard scanning */ +struct __ec_align1 ec_params_sb_rd { + uint8_t reg; }; -enum mkbp_config_valid { - EC_MKBP_VALID_SCAN_PERIOD = 1 << 0, - EC_MKBP_VALID_POLL_TIMEOUT = 1 << 1, - EC_MKBP_VALID_MIN_POST_SCAN_DELAY = 1 << 3, - EC_MKBP_VALID_OUTPUT_SETTLE = 1 << 4, - EC_MKBP_VALID_DEBOUNCE_DOWN = 1 << 5, - EC_MKBP_VALID_DEBOUNCE_UP = 1 << 6, - EC_MKBP_VALID_FIFO_MAX_DEPTH = 1 << 7, +struct __ec_align2 ec_response_sb_rd_word { + uint16_t value; }; -/* Configuration for our key scanning algorithm */ -struct ec_mkbp_config { - uint32_t valid_mask; /* valid fields */ - uint8_t flags; /* some flags (enum mkbp_config_flags) */ - uint8_t valid_flags; /* which flags are valid */ - uint16_t scan_period_us; /* period between start of scans */ - /* revert to interrupt mode after no activity for this long */ - uint32_t poll_timeout_us; - /* - * minimum post-scan relax time. Once we finish a scan we check - * the time until we are due to start the next one. If this time is - * shorter this field, we use this instead. - */ - uint16_t min_post_scan_delay_us; - /* delay between setting up output and waiting for it to settle */ - uint16_t output_settle_us; - uint16_t debounce_down_us; /* time for debounce on key down */ - uint16_t debounce_up_us; /* time for debounce on key up */ - /* maximum depth to allow for fifo (0 = no keyscan output) */ - uint8_t fifo_max_depth; -} __packed; +struct __ec_align1 ec_params_sb_wr_word { + uint8_t reg; + uint16_t value; +}; -struct ec_params_mkbp_set_config { - struct ec_mkbp_config config; -} __packed; +struct __ec_align1 ec_response_sb_rd_block { + uint8_t data[32]; +}; -struct ec_response_mkbp_get_config { - struct ec_mkbp_config config; -} __packed; +struct __ec_align1 ec_params_sb_wr_block { + uint8_t reg; + uint16_t data[32]; +}; -/* Run the key scan emulation */ -#define EC_CMD_KEYSCAN_SEQ_CTRL 0x66 +/*****************************************************************************/ +/* Battery vendor parameters + * + * Get or set vendor-specific parameters in the battery. Implementations may + * differ between boards or batteries. On a set operation, the response + * contains the actual value set, which may be rounded or clipped from the + * requested value. + */ -enum ec_keyscan_seq_cmd { - EC_KEYSCAN_SEQ_STATUS = 0, /* Get status information */ - EC_KEYSCAN_SEQ_CLEAR = 1, /* Clear sequence */ - EC_KEYSCAN_SEQ_ADD = 2, /* Add item to sequence */ - EC_KEYSCAN_SEQ_START = 3, /* Start running sequence */ - EC_KEYSCAN_SEQ_COLLECT = 4, /* Collect sequence summary data */ +#define EC_CMD_BATTERY_VENDOR_PARAM 0x00B4 + +enum ec_battery_vendor_param_mode { + BATTERY_VENDOR_PARAM_MODE_GET = 0, + BATTERY_VENDOR_PARAM_MODE_SET, }; -enum ec_collect_flags { - /* - * Indicates this scan was processed by the EC. Due to timing, some - * scans may be skipped. - */ - EC_KEYSCAN_SEQ_FLAG_DONE = 1 << 0, +struct __ec_align_size1 ec_params_battery_vendor_param { + uint32_t param; + uint32_t value; + uint8_t mode; }; -struct ec_collect_item { - uint8_t flags; /* some flags (enum ec_collect_flags) */ +struct __ec_align4 ec_response_battery_vendor_param { + uint32_t value; }; -struct ec_params_keyscan_seq_ctrl { - uint8_t cmd; /* Command to send (enum ec_keyscan_seq_cmd) */ +/*****************************************************************************/ +/* + * Smart Battery Firmware Update Commands + */ +#define EC_CMD_SB_FW_UPDATE 0x00B5 + +enum ec_sb_fw_update_subcmd { + EC_SB_FW_UPDATE_PREPARE = 0x0, + EC_SB_FW_UPDATE_INFO = 0x1, /*query sb info */ + EC_SB_FW_UPDATE_BEGIN = 0x2, /*check if protected */ + EC_SB_FW_UPDATE_WRITE = 0x3, /*check if protected */ + EC_SB_FW_UPDATE_END = 0x4, + EC_SB_FW_UPDATE_STATUS = 0x5, + EC_SB_FW_UPDATE_PROTECT = 0x6, + EC_SB_FW_UPDATE_MAX = 0x7, +}; + +#define SB_FW_UPDATE_CMD_WRITE_BLOCK_SIZE 32 +#define SB_FW_UPDATE_CMD_STATUS_SIZE 2 +#define SB_FW_UPDATE_CMD_INFO_SIZE 8 + +struct __ec_align4 ec_sb_fw_update_header { + uint16_t subcmd; /* enum ec_sb_fw_update_subcmd */ + uint16_t fw_id; /* firmware id */ +}; + +struct __ec_align4 ec_params_sb_fw_update { + struct ec_sb_fw_update_header hdr; union { - struct { - uint8_t active; /* still active */ - uint8_t num_items; /* number of items */ - /* Current item being presented */ - uint8_t cur_item; - } status; - struct { - /* - * Absolute time for this scan, measured from the - * start of the sequence. - */ - uint32_t time_us; - uint8_t scan[0]; /* keyscan data */ - } add; - struct { - uint8_t start_item; /* First item to return */ - uint8_t num_items; /* Number of items to return */ - } collect; + /* EC_SB_FW_UPDATE_PREPARE = 0x0 */ + /* EC_SB_FW_UPDATE_INFO = 0x1 */ + /* EC_SB_FW_UPDATE_BEGIN = 0x2 */ + /* EC_SB_FW_UPDATE_END = 0x4 */ + /* EC_SB_FW_UPDATE_STATUS = 0x5 */ + /* EC_SB_FW_UPDATE_PROTECT = 0x6 */ + struct __ec_align4 { + /* no args */ + } dummy; + + /* EC_SB_FW_UPDATE_WRITE = 0x3 */ + struct __ec_align4 { + uint8_t data[SB_FW_UPDATE_CMD_WRITE_BLOCK_SIZE]; + } write; }; -} __packed; +}; -struct ec_result_keyscan_seq_ctrl { +struct __ec_align1 ec_response_sb_fw_update { union { - struct { - uint8_t num_items; /* Number of items */ - /* Data for each item */ - struct ec_collect_item item[0]; - } collect; + /* EC_SB_FW_UPDATE_INFO = 0x1 */ + struct __ec_align1 { + uint8_t data[SB_FW_UPDATE_CMD_INFO_SIZE]; + } info; + + /* EC_SB_FW_UPDATE_STATUS = 0x5 */ + struct __ec_align1 { + uint8_t data[SB_FW_UPDATE_CMD_STATUS_SIZE]; + } status; }; -} __packed; +}; + +/* + * Entering Verified Boot Mode Command + * Default mode is VBOOT_MODE_NORMAL if EC did not receive this command. + * Valid Modes are: normal, developer, and recovery. + */ +#define EC_CMD_ENTERING_MODE 0x00B6 + +struct __ec_align4 ec_params_entering_mode { + int vboot_mode; +}; + +#define VBOOT_MODE_NORMAL 0 +#define VBOOT_MODE_DEVELOPER 1 +#define VBOOT_MODE_RECOVERY 2 /*****************************************************************************/ -/* Temperature sensor commands */ +/* + * I2C passthru protection command: Protects I2C tunnels against access on + * certain addresses (board-specific). + */ +#define EC_CMD_I2C_PASSTHRU_PROTECT 0x00B7 -/* Read temperature sensor info */ -#define EC_CMD_TEMP_SENSOR_GET_INFO 0x70 +enum ec_i2c_passthru_protect_subcmd { + EC_CMD_I2C_PASSTHRU_PROTECT_STATUS = 0x0, + EC_CMD_I2C_PASSTHRU_PROTECT_ENABLE = 0x1, +}; -struct ec_params_temp_sensor_get_info { - uint8_t id; -} __packed; +struct __ec_align1 ec_params_i2c_passthru_protect { + uint8_t subcmd; + uint8_t port; /* I2C port number */ +}; -struct ec_response_temp_sensor_get_info { - char sensor_name[32]; - uint8_t sensor_type; -} __packed; +struct __ec_align1 ec_response_i2c_passthru_protect { + uint8_t status; /* Status flags (0: unlocked, 1: locked) */ +}; /*****************************************************************************/ +/* System commands */ /* - * Note: host commands 0x80 - 0x87 are reserved to avoid conflict with ACPI - * commands accidentally sent to the wrong interface. See the ACPI section - * below. + * TODO(crosbug.com/p/23747): This is a confusing name, since it doesn't + * necessarily reboot the EC. Rename to "image" or something similar? */ +#define EC_CMD_REBOOT_EC 0x00D2 -/*****************************************************************************/ -/* Host event commands */ +/* Command */ +enum ec_reboot_cmd { + EC_REBOOT_CANCEL = 0, /* Cancel a pending reboot */ + EC_REBOOT_JUMP_RO = 1, /* Jump to RO without rebooting */ + EC_REBOOT_JUMP_RW = 2, /* Jump to RW without rebooting */ + /* (command 3 was jump to RW-B) */ + EC_REBOOT_COLD = 4, /* Cold-reboot */ + EC_REBOOT_DISABLE_JUMP = 5, /* Disable jump until next reboot */ + EC_REBOOT_HIBERNATE = 6, /* Hibernate EC */ + EC_REBOOT_HIBERNATE_CLEAR_AP_OFF = 7, /* and clears AP_OFF flag */ +}; + +/* Flags for ec_params_reboot_ec.reboot_flags */ +#define EC_REBOOT_FLAG_RESERVED0 (1 << 0) /* Was recovery request */ +#define EC_REBOOT_FLAG_ON_AP_SHUTDOWN (1 << 1) /* Reboot after AP shutdown */ +#define EC_REBOOT_FLAG_SWITCH_RW_SLOT (1 << 2) /* Switch RW slot */ + +struct __ec_align1 ec_params_reboot_ec { + uint8_t cmd; /* enum ec_reboot_cmd */ + uint8_t flags; /* See EC_REBOOT_FLAG_* */ +}; /* - * Host event mask params and response structures, shared by all of the host - * event commands below. + * Get information on last EC panic. + * + * Returns variable-length platform-dependent panic information. See panic.h + * for details. */ -struct ec_params_host_event_mask { - uint32_t mask; -} __packed; +#define EC_CMD_GET_PANIC_INFO 0x00D3 -struct ec_response_host_event_mask { - uint32_t mask; -} __packed; +/*****************************************************************************/ +/* + * Special commands + * + * These do not follow the normal rules for commands. See each command for + * details. + */ -/* These all use ec_response_host_event_mask */ -#define EC_CMD_HOST_EVENT_GET_B 0x87 -#define EC_CMD_HOST_EVENT_GET_SMI_MASK 0x88 -#define EC_CMD_HOST_EVENT_GET_SCI_MASK 0x89 -#define EC_CMD_HOST_EVENT_GET_WAKE_MASK 0x8d +/* + * Reboot NOW + * + * This command will work even when the EC LPC interface is busy, because the + * reboot command is processed at interrupt level. Note that when the EC + * reboots, the host will reboot too, so there is no response to this command. + * + * Use EC_CMD_REBOOT_EC to reboot the EC more politely. + */ +#define EC_CMD_REBOOT 0x00D1 /* Think "die" */ -/* These all use ec_params_host_event_mask */ -#define EC_CMD_HOST_EVENT_SET_SMI_MASK 0x8a -#define EC_CMD_HOST_EVENT_SET_SCI_MASK 0x8b -#define EC_CMD_HOST_EVENT_CLEAR 0x8c -#define EC_CMD_HOST_EVENT_SET_WAKE_MASK 0x8e -#define EC_CMD_HOST_EVENT_CLEAR_B 0x8f +/* + * Resend last response (not supported on LPC). + * + * Returns EC_RES_UNAVAILABLE if there is no response available - for example, + * there was no previous command, or the previous command's response was too + * big to save. + */ +#define EC_CMD_RESEND_RESPONSE 0x00DB + +/* + * This header byte on a command indicate version 0. Any header byte less + * than this means that we are talking to an old EC which doesn't support + * versioning. In that case, we assume version 0. + * + * Header bytes greater than this indicate a later version. For example, + * EC_CMD_VERSION0 + 1 means we are using version 1. + * + * The old EC interface must not use commands 0xdc or higher. + */ +#define EC_CMD_VERSION0 0x00DC /*****************************************************************************/ -/* Switch commands */ +/* + * PD commands + * + * These commands are for PD MCU communication. + */ -/* Enable/disable LCD backlight */ -#define EC_CMD_SWITCH_ENABLE_BKLIGHT 0x90 +/* EC to PD MCU exchange status command */ +#define EC_CMD_PD_EXCHANGE_STATUS 0x0100 +#define EC_VER_PD_EXCHANGE_STATUS 2 -struct ec_params_switch_enable_backlight { - uint8_t enabled; -} __packed; +enum pd_charge_state { + PD_CHARGE_NO_CHANGE = 0, /* Don't change charge state */ + PD_CHARGE_NONE, /* No charging allowed */ + PD_CHARGE_5V, /* 5V charging only */ + PD_CHARGE_MAX /* Charge at max voltage */ +}; -/* Enable/disable WLAN/Bluetooth */ -#define EC_CMD_SWITCH_ENABLE_WIRELESS 0x91 +/* Status of EC being sent to PD */ +#define EC_STATUS_HIBERNATING (1 << 0) + +struct __ec_align1 ec_params_pd_status { + uint8_t status; /* EC status */ + int8_t batt_soc; /* battery state of charge */ + uint8_t charge_state; /* charging state (from enum pd_charge_state) */ +}; + +/* Status of PD being sent back to EC */ +#define PD_STATUS_HOST_EVENT (1 << 0) /* Forward host event to AP */ +#define PD_STATUS_IN_RW (1 << 1) /* Running RW image */ +#define PD_STATUS_JUMPED_TO_IMAGE (1 << 2) /* Current image was jumped to */ +#define PD_STATUS_TCPC_ALERT_0 (1 << 3) /* Alert active in port 0 TCPC */ +#define PD_STATUS_TCPC_ALERT_1 (1 << 4) /* Alert active in port 1 TCPC */ +#define PD_STATUS_TCPC_ALERT_2 (1 << 5) /* Alert active in port 2 TCPC */ +#define PD_STATUS_TCPC_ALERT_3 (1 << 6) /* Alert active in port 3 TCPC */ +#define PD_STATUS_EC_INT_ACTIVE (PD_STATUS_TCPC_ALERT_0 | \ + PD_STATUS_TCPC_ALERT_1 | \ + PD_STATUS_HOST_EVENT) +struct __ec_align_size1 ec_response_pd_status { + uint32_t curr_lim_ma; /* input current limit */ + uint16_t status; /* PD MCU status */ + int8_t active_charge_port; /* active charging port */ +}; + +/* AP to PD MCU host event status command, cleared on read */ +#define EC_CMD_PD_HOST_EVENT_STATUS 0x0104 + +/* PD MCU host event status bits */ +#define PD_EVENT_UPDATE_DEVICE (1 << 0) +#define PD_EVENT_POWER_CHANGE (1 << 1) +#define PD_EVENT_IDENTITY_RECEIVED (1 << 2) +#define PD_EVENT_DATA_SWAP (1 << 3) +struct __ec_align4 ec_response_host_event_status { + uint32_t status; /* PD MCU host event status */ +}; + +/* Set USB type-C port role and muxes */ +#define EC_CMD_USB_PD_CONTROL 0x0101 + +enum usb_pd_control_role { + USB_PD_CTRL_ROLE_NO_CHANGE = 0, + USB_PD_CTRL_ROLE_TOGGLE_ON = 1, /* == AUTO */ + USB_PD_CTRL_ROLE_TOGGLE_OFF = 2, + USB_PD_CTRL_ROLE_FORCE_SINK = 3, + USB_PD_CTRL_ROLE_FORCE_SOURCE = 4, + USB_PD_CTRL_ROLE_COUNT +}; + +enum usb_pd_control_mux { + USB_PD_CTRL_MUX_NO_CHANGE = 0, + USB_PD_CTRL_MUX_NONE = 1, + USB_PD_CTRL_MUX_USB = 2, + USB_PD_CTRL_MUX_DP = 3, + USB_PD_CTRL_MUX_DOCK = 4, + USB_PD_CTRL_MUX_AUTO = 5, + USB_PD_CTRL_MUX_COUNT +}; + +enum usb_pd_control_swap { + USB_PD_CTRL_SWAP_NONE = 0, + USB_PD_CTRL_SWAP_DATA = 1, + USB_PD_CTRL_SWAP_POWER = 2, + USB_PD_CTRL_SWAP_VCONN = 3, + USB_PD_CTRL_SWAP_COUNT +}; + +struct __ec_align1 ec_params_usb_pd_control { + uint8_t port; + uint8_t role; + uint8_t mux; + uint8_t swap; +}; -struct ec_params_switch_enable_wireless { +#define PD_CTRL_RESP_ENABLED_COMMS (1 << 0) /* Communication enabled */ +#define PD_CTRL_RESP_ENABLED_CONNECTED (1 << 1) /* Device connected */ +#define PD_CTRL_RESP_ENABLED_PD_CAPABLE (1 << 2) /* Partner is PD capable */ + +#define PD_CTRL_RESP_ROLE_POWER (1 << 0) /* 0=SNK/1=SRC */ +#define PD_CTRL_RESP_ROLE_DATA (1 << 1) /* 0=UFP/1=DFP */ +#define PD_CTRL_RESP_ROLE_VCONN (1 << 2) /* Vconn status */ +#define PD_CTRL_RESP_ROLE_DR_POWER (1 << 3) /* Partner is dualrole power */ +#define PD_CTRL_RESP_ROLE_DR_DATA (1 << 4) /* Partner is dualrole data */ +#define PD_CTRL_RESP_ROLE_USB_COMM (1 << 5) /* Partner USB comm capable */ +#define PD_CTRL_RESP_ROLE_EXT_POWERED (1 << 6) /* Partner externally powerd */ + +struct __ec_align1 ec_response_usb_pd_control { uint8_t enabled; -} __packed; + uint8_t role; + uint8_t polarity; + uint8_t state; +}; -/*****************************************************************************/ -/* GPIO commands. Only available on EC if write protect has been disabled. */ +struct __ec_align1 ec_response_usb_pd_control_v1 { + uint8_t enabled; + uint8_t role; + uint8_t polarity; + char state[32]; +}; -/* Set GPIO output value */ -#define EC_CMD_GPIO_SET 0x92 +#define EC_CMD_USB_PD_PORTS 0x0102 -struct ec_params_gpio_set { - char name[32]; - uint8_t val; -} __packed; +/* Maximum number of PD ports on a device, num_ports will be <= this */ +#define EC_USB_PD_MAX_PORTS 8 -/* Get GPIO value */ -#define EC_CMD_GPIO_GET 0x93 +struct __ec_align1 ec_response_usb_pd_ports { + uint8_t num_ports; +}; -struct ec_params_gpio_get { - char name[32]; -} __packed; -struct ec_response_gpio_get { - uint8_t val; -} __packed; +#define EC_CMD_USB_PD_POWER_INFO 0x0103 + +#define PD_POWER_CHARGING_PORT 0xff +struct __ec_align1 ec_params_usb_pd_power_info { + uint8_t port; +}; + +enum usb_chg_type { + USB_CHG_TYPE_NONE, + USB_CHG_TYPE_PD, + USB_CHG_TYPE_C, + USB_CHG_TYPE_PROPRIETARY, + USB_CHG_TYPE_BC12_DCP, + USB_CHG_TYPE_BC12_CDP, + USB_CHG_TYPE_BC12_SDP, + USB_CHG_TYPE_OTHER, + USB_CHG_TYPE_VBUS, + USB_CHG_TYPE_UNKNOWN, +}; +enum usb_power_roles { + USB_PD_PORT_POWER_DISCONNECTED, + USB_PD_PORT_POWER_SOURCE, + USB_PD_PORT_POWER_SINK, + USB_PD_PORT_POWER_SINK_NOT_CHARGING, +}; + +struct __ec_align2 usb_chg_measures { + uint16_t voltage_max; + uint16_t voltage_now; + uint16_t current_max; + uint16_t current_lim; +}; + +struct __ec_align4 ec_response_usb_pd_power_info { + uint8_t role; + uint8_t type; + uint8_t dualrole; + uint8_t reserved1; + struct usb_chg_measures meas; + uint32_t max_power; +}; + +/* Write USB-PD device FW */ +#define EC_CMD_USB_PD_FW_UPDATE 0x0110 + +enum usb_pd_fw_update_cmds { + USB_PD_FW_REBOOT, + USB_PD_FW_FLASH_ERASE, + USB_PD_FW_FLASH_WRITE, + USB_PD_FW_ERASE_SIG, +}; + +struct __ec_align4 ec_params_usb_pd_fw_update { + uint16_t dev_id; + uint8_t cmd; + uint8_t port; + uint32_t size; /* Size to write in bytes */ + /* Followed by data to write */ +}; -/*****************************************************************************/ -/* I2C commands. Only available when flash write protect is unlocked. */ +/* Write USB-PD Accessory RW_HASH table entry */ +#define EC_CMD_USB_PD_RW_HASH_ENTRY 0x0111 +/* RW hash is first 20 bytes of SHA-256 of RW section */ +#define PD_RW_HASH_SIZE 20 +struct __ec_align1 ec_params_usb_pd_rw_hash_entry { + uint16_t dev_id; + uint8_t dev_rw_hash[PD_RW_HASH_SIZE]; + uint8_t reserved; /* For alignment of current_image + * TODO(rspangler) but it's not aligned! + * Should have been reserved[2]. */ + uint32_t current_image; /* One of ec_current_image */ +}; -/* Read I2C bus */ -#define EC_CMD_I2C_READ 0x94 +/* Read USB-PD Accessory info */ +#define EC_CMD_USB_PD_DEV_INFO 0x0112 -struct ec_params_i2c_read { - uint16_t addr; /* 8-bit address (7-bit shifted << 1) */ - uint8_t read_size; /* Either 8 or 16. */ +struct __ec_align1 ec_params_usb_pd_info_request { uint8_t port; - uint8_t offset; -} __packed; -struct ec_response_i2c_read { - uint16_t data; -} __packed; +}; -/* Write I2C bus */ -#define EC_CMD_I2C_WRITE 0x95 +/* Read USB-PD Device discovery info */ +#define EC_CMD_USB_PD_DISCOVERY 0x0113 +struct __ec_align_size1 ec_params_usb_pd_discovery_entry { + uint16_t vid; /* USB-IF VID */ + uint16_t pid; /* USB-IF PID */ + uint8_t ptype; /* product type (hub,periph,cable,ama) */ +}; -struct ec_params_i2c_write { - uint16_t data; - uint16_t addr; /* 8-bit address (7-bit shifted << 1) */ - uint8_t write_size; /* Either 8 or 16. */ - uint8_t port; - uint8_t offset; -} __packed; +/* Override default charge behavior */ +#define EC_CMD_PD_CHARGE_PORT_OVERRIDE 0x0114 -/*****************************************************************************/ -/* Charge state commands. Only available when flash write protect unlocked. */ +/* Negative port parameters have special meaning */ +enum usb_pd_override_ports { + OVERRIDE_DONT_CHARGE = -2, + OVERRIDE_OFF = -1, + /* [0, CONFIG_USB_PD_PORT_COUNT): Port# */ +}; -/* Force charge state machine to stop in idle mode */ -#define EC_CMD_CHARGE_FORCE_IDLE 0x96 +struct __ec_align2 ec_params_charge_port_override { + int16_t override_port; /* Override port# */ +}; -struct ec_params_force_idle { - uint8_t enabled; -} __packed; +/* Read (and delete) one entry of PD event log */ +#define EC_CMD_PD_GET_LOG_ENTRY 0x0115 -/*****************************************************************************/ -/* Console commands. Only available when flash write protect is unlocked. */ +struct __ec_align4 ec_response_pd_log { + uint32_t timestamp; /* relative timestamp in milliseconds */ + uint8_t type; /* event type : see PD_EVENT_xx below */ + uint8_t size_port; /* [7:5] port number [4:0] payload size in bytes */ + uint16_t data; /* type-defined data payload */ + uint8_t payload[0]; /* optional additional data payload: 0..16 bytes */ +}; -/* Snapshot console output buffer for use by EC_CMD_CONSOLE_READ. */ -#define EC_CMD_CONSOLE_SNAPSHOT 0x97 + +/* The timestamp is the microsecond counter shifted to get about a ms. */ +#define PD_LOG_TIMESTAMP_SHIFT 10 /* 1 LSB = 1024us */ + +#define PD_LOG_SIZE_MASK 0x1f +#define PD_LOG_PORT_MASK 0xe0 +#define PD_LOG_PORT_SHIFT 5 +#define PD_LOG_PORT_SIZE(port, size) (((port) << PD_LOG_PORT_SHIFT) | \ + ((size) & PD_LOG_SIZE_MASK)) +#define PD_LOG_PORT(size_port) ((size_port) >> PD_LOG_PORT_SHIFT) +#define PD_LOG_SIZE(size_port) ((size_port) & PD_LOG_SIZE_MASK) + +/* PD event log : entry types */ +/* PD MCU events */ +#define PD_EVENT_MCU_BASE 0x00 +#define PD_EVENT_MCU_CHARGE (PD_EVENT_MCU_BASE+0) +#define PD_EVENT_MCU_CONNECT (PD_EVENT_MCU_BASE+1) +/* Reserved for custom board event */ +#define PD_EVENT_MCU_BOARD_CUSTOM (PD_EVENT_MCU_BASE+2) +/* PD generic accessory events */ +#define PD_EVENT_ACC_BASE 0x20 +#define PD_EVENT_ACC_RW_FAIL (PD_EVENT_ACC_BASE+0) +#define PD_EVENT_ACC_RW_ERASE (PD_EVENT_ACC_BASE+1) +/* PD power supply events */ +#define PD_EVENT_PS_BASE 0x40 +#define PD_EVENT_PS_FAULT (PD_EVENT_PS_BASE+0) +/* PD video dongles events */ +#define PD_EVENT_VIDEO_BASE 0x60 +#define PD_EVENT_VIDEO_DP_MODE (PD_EVENT_VIDEO_BASE+0) +#define PD_EVENT_VIDEO_CODEC (PD_EVENT_VIDEO_BASE+1) +/* Returned in the "type" field, when there is no entry available */ +#define PD_EVENT_NO_ENTRY 0xff /* - * Read next chunk of data from saved snapshot. - * - * Response is null-terminated string. Empty string, if there is no more - * remaining output. + * PD_EVENT_MCU_CHARGE event definition : + * the payload is "struct usb_chg_measures" + * the data field contains the port state flags as defined below : */ -#define EC_CMD_CONSOLE_READ 0x98 - -/*****************************************************************************/ +/* Port partner is a dual role device */ +#define CHARGE_FLAGS_DUAL_ROLE (1 << 15) +/* Port is the pending override port */ +#define CHARGE_FLAGS_DELAYED_OVERRIDE (1 << 14) +/* Port is the override port */ +#define CHARGE_FLAGS_OVERRIDE (1 << 13) +/* Charger type */ +#define CHARGE_FLAGS_TYPE_SHIFT 3 +#define CHARGE_FLAGS_TYPE_MASK (0xf << CHARGE_FLAGS_TYPE_SHIFT) +/* Power delivery role */ +#define CHARGE_FLAGS_ROLE_MASK (7 << 0) /* - * Cut off battery power output if the battery supports. - * - * For unsupported battery, just don't implement this command and lets EC - * return EC_RES_INVALID_COMMAND. + * PD_EVENT_PS_FAULT data field flags definition : */ -#define EC_CMD_BATTERY_CUT_OFF 0x99 - -/*****************************************************************************/ -/* USB port mux control. */ +#define PS_FAULT_OCP 1 +#define PS_FAULT_FAST_OCP 2 +#define PS_FAULT_OVP 3 +#define PS_FAULT_DISCH 4 /* - * Switch USB mux or return to automatic switching. + * PD_EVENT_VIDEO_CODEC payload is "struct mcdp_info". */ -#define EC_CMD_USB_MUX 0x9a +struct __ec_align4 mcdp_version { + uint8_t major; + uint8_t minor; + uint16_t build; +}; -struct ec_params_usb_mux { - uint8_t mux; -} __packed; +struct __ec_align4 mcdp_info { + uint8_t family[2]; + uint8_t chipid[2]; + struct mcdp_version irom; + struct mcdp_version fw; +}; -/*****************************************************************************/ -/* LDOs / FETs control. */ +/* struct mcdp_info field decoding */ +#define MCDP_CHIPID(chipid) ((chipid[0] << 8) | chipid[1]) +#define MCDP_FAMILY(family) ((family[0] << 8) | family[1]) -enum ec_ldo_state { - EC_LDO_STATE_OFF = 0, /* the LDO / FET is shut down */ - EC_LDO_STATE_ON = 1, /* the LDO / FET is ON / providing power */ +/* Get/Set USB-PD Alternate mode info */ +#define EC_CMD_USB_PD_GET_AMODE 0x0116 +struct __ec_align_size1 ec_params_usb_pd_get_mode_request { + uint16_t svid_idx; /* SVID index to get */ + uint8_t port; /* port */ }; -/* - * Switch on/off a LDO. - */ -#define EC_CMD_LDO_SET 0x9b +struct __ec_align4 ec_params_usb_pd_get_mode_response { + uint16_t svid; /* SVID */ + uint16_t opos; /* Object Position */ + uint32_t vdo[6]; /* Mode VDOs */ +}; -struct ec_params_ldo_set { - uint8_t index; - uint8_t state; -} __packed; +#define EC_CMD_USB_PD_SET_AMODE 0x0117 -/* - * Get LDO state. - */ -#define EC_CMD_LDO_GET 0x9c +enum pd_mode_cmd { + PD_EXIT_MODE = 0, + PD_ENTER_MODE = 1, + /* Not a command. Do NOT remove. */ + PD_MODE_CMD_COUNT, +}; -struct ec_params_ldo_get { - uint8_t index; -} __packed; +struct __ec_align4 ec_params_usb_pd_set_mode_request { + uint32_t cmd; /* enum pd_mode_cmd */ + uint16_t svid; /* SVID to set */ + uint8_t opos; /* Object Position */ + uint8_t port; /* port */ +}; -struct ec_response_ldo_get { - uint8_t state; -} __packed; +/* Ask the PD MCU to record a log of a requested type */ +#define EC_CMD_PD_WRITE_LOG_ENTRY 0x0118 -/*****************************************************************************/ -/* Power info. */ +struct __ec_align1 ec_params_pd_write_log_entry { + uint8_t type; /* event type : see PD_EVENT_xx above */ + uint8_t port; /* port#, or 0 for events unrelated to a given port */ +}; -/* - * Get power info. - */ -#define EC_CMD_POWER_INFO 0x9d -struct ec_response_power_info { - uint32_t usb_dev_type; - uint16_t voltage_ac; - uint16_t voltage_system; - uint16_t current_system; - uint16_t usb_current_limit; -} __packed; +/* Control USB-PD chip */ +#define EC_CMD_PD_CONTROL 0x0119 -/*****************************************************************************/ -/* I2C passthru command */ +enum ec_pd_control_cmd { + PD_SUSPEND = 0, /* Suspend the PD chip (EC: stop talking to PD) */ + PD_RESUME, /* Resume the PD chip (EC: start talking to PD) */ + PD_RESET, /* Force reset the PD chip */ + PD_CONTROL_DISABLE /* Disable further calls to this command */ +}; -#define EC_CMD_I2C_PASSTHRU 0x9e +struct __ec_align1 ec_params_pd_control { + uint8_t chip; /* chip id (should be 0) */ + uint8_t subcmd; +}; -/* Slave address is 10 (not 7) bit */ -#define EC_I2C_FLAG_10BIT (1 << 16) +/* Get info about USB-C SS muxes */ +#define EC_CMD_USB_PD_MUX_INFO 0x011A -/* Read data; if not present, message is a write */ -#define EC_I2C_FLAG_READ (1 << 15) +struct __ec_align1 ec_params_usb_pd_mux_info { + uint8_t port; /* USB-C port number */ +}; -/* Mask for address */ -#define EC_I2C_ADDR_MASK 0x3ff +/* Flags representing mux state */ +#define USB_PD_MUX_USB_ENABLED (1 << 0) +#define USB_PD_MUX_DP_ENABLED (1 << 1) +#define USB_PD_MUX_POLARITY_INVERTED (1 << 2) +#define USB_PD_MUX_HPD_IRQ (1 << 3) -#define EC_I2C_STATUS_NAK (1 << 0) /* Transfer was not acknowledged */ -#define EC_I2C_STATUS_TIMEOUT (1 << 1) /* Timeout during transfer */ +struct __ec_align1 ec_response_usb_pd_mux_info { + uint8_t flags; /* USB_PD_MUX_*-encoded USB mux state */ +}; -/* Any error */ -#define EC_I2C_STATUS_ERROR (EC_I2C_STATUS_NAK | EC_I2C_STATUS_TIMEOUT) +#define EC_CMD_PD_CHIP_INFO 0x011B -struct ec_params_i2c_passthru_msg { - uint16_t addr_flags; /* I2C slave address (7 or 10 bits) and flags */ - uint16_t len; /* Number of bytes to read or write */ -} __packed; +struct __ec_align1 ec_params_pd_chip_info { + uint8_t port; /* USB-C port number */ + uint8_t renew; /* Force renewal */ +}; -struct ec_params_i2c_passthru { - uint8_t port; /* I2C port number */ - uint8_t num_msgs; /* Number of messages */ - struct ec_params_i2c_passthru_msg msg[]; - /* Data to write for all messages is concatenated here */ -} __packed; +struct __ec_align2 ec_response_pd_chip_info { + uint16_t vendor_id; + uint16_t product_id; + uint16_t device_id; + union { + uint8_t fw_version_string[8]; + uint64_t fw_version_number; + }; +}; -struct ec_response_i2c_passthru { - uint8_t i2c_status; /* Status flags (EC_I2C_STATUS_...) */ - uint8_t num_msgs; /* Number of messages processed */ - uint8_t data[]; /* Data read by messages concatenated here */ -} __packed; +/* Run RW signature verification and get status */ +#define EC_CMD_RWSIG_CHECK_STATUS 0x011C + +struct __ec_align4 ec_response_rwsig_check_status { + uint32_t status; +}; +/* For controlling RWSIG task */ +#define EC_CMD_RWSIG_ACTION 0x011D -/*****************************************************************************/ -/* Temporary debug commands. TODO: remove this crosbug.com/p/13849 */ +enum rwsig_action { + RWSIG_ACTION_ABORT = 0, /* Abort RWSIG and prevent jumping */ + RWSIG_ACTION_CONTINUE = 1, /* Jump to RW immediately */ +}; + +struct __ec_align4 ec_params_rwsig_action { + uint32_t action; +}; + +/* Run verification on a slot */ +#define EC_CMD_EFS_VERIFY 0x011E + +struct __ec_align1 ec_params_efs_verify { + uint8_t region; /* enum ec_flash_region */ +}; /* - * Dump charge state machine context. - * - * Response is a binary dump of charge state machine context. + * Retrieve info from Cros Board Info store. Response is based on the data + * type. Integers return a uint32. Strings return a string, using the response + * size to determine how big it is. + */ +#define EC_CMD_GET_CROS_BOARD_INFO 0x011F +/* + * Write info into Cros Board Info on EEPROM. Write fails if the board has + * hardware write-protect enabled. */ -#define EC_CMD_CHARGE_DUMP 0xa0 +#define EC_CMD_SET_CROS_BOARD_INFO 0x0120 + +enum cbi_data_tag { + CBI_TAG_BOARD_VERSION = 0, /* uint16_t or uint8_t[] = {minor,major} */ + CBI_TAG_OEM_ID = 1, /* uint8_t */ + CBI_TAG_SKU_ID = 2, /* uint8_t */ + CBI_TAG_COUNT, +}; /* - * Set maximum battery charging current. + * Flags to control read operation + * + * RELOAD: Invalidate cache and read data from EEPROM. Useful to verify + * write was successful without reboot. */ -#define EC_CMD_CHARGE_CURRENT_LIMIT 0xa1 +#define CBI_GET_RELOAD (1 << 0) -struct ec_params_current_limit { - uint32_t limit; /* in mA */ -} __packed; +struct __ec_align4 ec_params_get_cbi { + uint32_t type; /* enum cbi_data_tag */ + uint32_t flag; /* CBI_GET_* */ +}; /* - * Set maximum external power current. + * Flags to control write behavior. + * + * NO_SYNC: Makes EC update data in RAM but skip writing to EEPROM. It's + * useful when writing multiple fields in a row. + * INIT: Needs to be set when creating a new CBI from scratch. All fields + * will be initialized to zero first. */ -#define EC_CMD_EXT_POWER_CURRENT_LIMIT 0xa2 +#define CBI_SET_NO_SYNC (1 << 0) +#define CBI_SET_INIT (1 << 1) + +struct __ec_align1 ec_params_set_cbi { + uint32_t tag; /* enum cbi_data_tag */ + uint32_t flag; /* CBI_SET_* */ + uint32_t size; /* Data size */ + uint8_t data[]; /* For string and raw data */ +}; -struct ec_params_ext_power_current_limit { - uint32_t limit; /* in mA */ -} __packed; +/*****************************************************************************/ +/* The command range 0x200-0x2FF is reserved for Rotor. */ /*****************************************************************************/ -/* Smart battery pass-through */ +/* + * Reserve a range of host commands for the CR51 firmware. + */ +#define EC_CMD_CR51_BASE 0x0300 +#define EC_CMD_CR51_LAST 0x03FF -/* Get / Set 16-bit smart battery registers */ -#define EC_CMD_SB_READ_WORD 0xb0 -#define EC_CMD_SB_WRITE_WORD 0xb1 +/*****************************************************************************/ +/* Fingerprint MCU commands: range 0x0400-0x040x */ -/* Get / Set string smart battery parameters - * formatted as SMBUS "block". - */ -#define EC_CMD_SB_READ_BLOCK 0xb2 -#define EC_CMD_SB_WRITE_BLOCK 0xb3 +/* Fingerprint SPI sensor passthru command: prototyping ONLY */ +#define EC_CMD_FP_PASSTHRU 0x0400 -struct ec_params_sb_rd { - uint8_t reg; -} __packed; +#define EC_FP_FLAG_NOT_COMPLETE 0x1 -struct ec_response_sb_rd_word { - uint16_t value; -} __packed; +struct __ec_align2 ec_params_fp_passthru { + uint16_t len; /* Number of bytes to write then read */ + uint16_t flags; /* EC_FP_FLAG_xxx */ + uint8_t data[]; /* Data to send */ +}; -struct ec_params_sb_wr_word { - uint8_t reg; - uint16_t value; -} __packed; +/* Fingerprint sensor configuration command: prototyping ONLY */ +#define EC_CMD_FP_SENSOR_CONFIG 0x0401 -struct ec_response_sb_rd_block { - uint8_t data[32]; -} __packed; +#define EC_FP_SENSOR_CONFIG_MAX_REGS 16 -struct ec_params_sb_wr_block { - uint8_t reg; - uint16_t data[32]; -} __packed; +struct __ec_align2 ec_params_fp_sensor_config { + uint8_t count; /* Number of setup registers */ + /* + * the value to send to each of the 'count' setup registers + * is stored in the 'data' array for 'len' bytes just after + * the previous one. + */ + uint8_t len[EC_FP_SENSOR_CONFIG_MAX_REGS]; + uint8_t data[]; +}; -/* - * Entering Verified Boot Mode Command - * Default mode is VBOOT_MODE_NORMAL if EC did not receive this command. - * Valid Modes are: normal, developer, and recovery. - */ -#define EC_CMD_ENTERING_MODE 0xb6 +/* Configure the Fingerprint MCU behavior */ +#define EC_CMD_FP_MODE 0x0402 + +/* Put the sensor in its lowest power mode */ +#define FP_MODE_DEEPSLEEP (1<<0) +/* Wait to see a finger on the sensor */ +#define FP_MODE_FINGER_DOWN (1<<1) +/* Poll until the finger has left the sensor */ +#define FP_MODE_FINGER_UP (1<<2) +/* Capture the current finger image */ +#define FP_MODE_CAPTURE (1<<3) +/* special value: don't change anything just read back current mode */ +#define FP_MODE_DONT_CHANGE (1<<31) + +struct __ec_align4 ec_params_fp_mode { + uint32_t mode; /* as defined by FP_MODE_ constants */ + /* TBD */ +}; -struct ec_params_entering_mode { - int vboot_mode; -} __packed; +struct __ec_align4 ec_response_fp_mode { + uint32_t mode; /* as defined by FP_MODE_ constants */ + /* TBD */ +}; -#define VBOOT_MODE_NORMAL 0 -#define VBOOT_MODE_DEVELOPER 1 -#define VBOOT_MODE_RECOVERY 2 +/* Retrieve Fingerprint sensor information */ +#define EC_CMD_FP_INFO 0x0403 + +struct __ec_align2 ec_response_fp_info { + /* Sensor identification */ + uint32_t vendor_id; + uint32_t product_id; + uint32_t model_id; + uint32_t version; + /* Image frame characteristics */ + uint32_t frame_size; + uint32_t pixel_format; /* using V4L2_PIX_FMT_ */ + uint16_t width; + uint16_t height; + uint16_t bpp; +}; + +/* Get the last captured finger frame: TODO: will be AES-encrypted */ +#define EC_CMD_FP_FRAME 0x0404 + +struct __ec_align4 ec_params_fp_frame { + uint32_t offset; + uint32_t size; +}; /*****************************************************************************/ -/* System commands */ +/* Touchpad MCU commands: range 0x0500-0x05FF */ -/* - * TODO: this is a confusing name, since it doesn't necessarily reboot the EC. - * Rename to "set image" or something similar. - */ -#define EC_CMD_REBOOT_EC 0xd2 +/* Perform touchpad self test */ +#define EC_CMD_TP_SELF_TEST 0x0500 -/* Command */ -enum ec_reboot_cmd { - EC_REBOOT_CANCEL = 0, /* Cancel a pending reboot */ - EC_REBOOT_JUMP_RO = 1, /* Jump to RO without rebooting */ - EC_REBOOT_JUMP_RW = 2, /* Jump to RW without rebooting */ - /* (command 3 was jump to RW-B) */ - EC_REBOOT_COLD = 4, /* Cold-reboot */ - EC_REBOOT_DISABLE_JUMP = 5, /* Disable jump until next reboot */ - EC_REBOOT_HIBERNATE = 6 /* Hibernate EC */ +/* Get number of frame types, and the size of each type */ +#define EC_CMD_TP_FRAME_INFO 0x0501 + +struct __ec_align4 ec_response_tp_frame_info { + uint32_t n_frames; + uint32_t frame_sizes[0]; }; -/* Flags for ec_params_reboot_ec.reboot_flags */ -#define EC_REBOOT_FLAG_RESERVED0 (1 << 0) /* Was recovery request */ -#define EC_REBOOT_FLAG_ON_AP_SHUTDOWN (1 << 1) /* Reboot after AP shutdown */ +/* Create a snapshot of current frame readings */ +#define EC_CMD_TP_FRAME_SNAPSHOT 0x0502 -struct ec_params_reboot_ec { - uint8_t cmd; /* enum ec_reboot_cmd */ - uint8_t flags; /* See EC_REBOOT_FLAG_* */ -} __packed; +/* Read the frame */ +#define EC_CMD_TP_FRAME_GET 0x0503 -/* - * Get information on last EC panic. - * - * Returns variable-length platform-dependent panic information. See panic.h - * for details. - */ -#define EC_CMD_GET_PANIC_INFO 0xd3 +struct __ec_align4 ec_params_tp_frame_get { + uint32_t frame_index; + uint32_t offset; + uint32_t size; +}; /*****************************************************************************/ /* - * ACPI commands - * - * These are valid ONLY on the ACPI command/data port. - */ - -/* - * ACPI Read Embedded Controller + * Reserve a range of host commands for board-specific, experimental, or + * special purpose features. These can be (re)used without updating this file. * - * This reads from ACPI memory space on the EC (EC_ACPI_MEM_*). + * CAUTION: Don't go nuts with this. Shipping products should document ALL + * their EC commands for easier development, testing, debugging, and support. * - * Use the following sequence: + * All commands MUST be #defined to be 4-digit UPPER CASE hex values + * (e.g., 0x00AB, not 0xab) for CONFIG_HOSTCMD_SECTION_SORTED to work. * - * - Write EC_CMD_ACPI_READ to EC_LPC_ADDR_ACPI_CMD - * - Wait for EC_LPC_CMDR_PENDING bit to clear - * - Write address to EC_LPC_ADDR_ACPI_DATA - * - Wait for EC_LPC_CMDR_DATA bit to set - * - Read value from EC_LPC_ADDR_ACPI_DATA - */ -#define EC_CMD_ACPI_READ 0x80 - -/* - * ACPI Write Embedded Controller + * In your experimental code, you may want to do something like this: * - * This reads from ACPI memory space on the EC (EC_ACPI_MEM_*). + * #define EC_CMD_MAGIC_FOO 0x0000 + * #define EC_CMD_MAGIC_BAR 0x0001 + * #define EC_CMD_MAGIC_HEY 0x0002 * - * Use the following sequence: + * DECLARE_PRIVATE_HOST_COMMAND(EC_CMD_MAGIC_FOO, magic_foo_handler, + * EC_VER_MASK(0); * - * - Write EC_CMD_ACPI_WRITE to EC_LPC_ADDR_ACPI_CMD - * - Wait for EC_LPC_CMDR_PENDING bit to clear - * - Write address to EC_LPC_ADDR_ACPI_DATA - * - Wait for EC_LPC_CMDR_PENDING bit to clear - * - Write value to EC_LPC_ADDR_ACPI_DATA - */ -#define EC_CMD_ACPI_WRITE 0x81 - -/* - * ACPI Query Embedded Controller + * DECLARE_PRIVATE_HOST_COMMAND(EC_CMD_MAGIC_BAR, magic_bar_handler, + * EC_VER_MASK(0); * - * This clears the lowest-order bit in the currently pending host events, and - * sets the result code to the 1-based index of the bit (event 0x00000001 = 1, - * event 0x80000000 = 32), or 0 if no event was pending. + * DECLARE_PRIVATE_HOST_COMMAND(EC_CMD_MAGIC_HEY, magic_hey_handler, + * EC_VER_MASK(0); */ -#define EC_CMD_ACPI_QUERY_EVENT 0x84 +#define EC_CMD_BOARD_SPECIFIC_BASE 0x3E00 +#define EC_CMD_BOARD_SPECIFIC_LAST 0x3FFF -/* Valid addresses in ACPI memory space, for read/write commands */ -/* Memory space version; set to EC_ACPI_MEM_VERSION_CURRENT */ -#define EC_ACPI_MEM_VERSION 0x00 /* - * Test location; writing value here updates test compliment byte to (0xff - - * value). + * Given the private host command offset, calculate the true private host + * command value. */ -#define EC_ACPI_MEM_TEST 0x01 -/* Test compliment; writes here are ignored. */ -#define EC_ACPI_MEM_TEST_COMPLIMENT 0x02 -/* Keyboard backlight brightness percent (0 - 100) */ -#define EC_ACPI_MEM_KEYBOARD_BACKLIGHT 0x03 - -/* Current version of ACPI memory address space */ -#define EC_ACPI_MEM_VERSION_CURRENT 1 - +#define EC_PRIVATE_HOST_COMMAND_VALUE(command) \ + (EC_CMD_BOARD_SPECIFIC_BASE + (command)) /*****************************************************************************/ /* - * Special commands + * Passthru commands * - * These do not follow the normal rules for commands. See each command for - * details. - */ - -/* - * Reboot NOW + * Some platforms have sub-processors chained to each other. For example. * - * This command will work even when the EC LPC interface is busy, because the - * reboot command is processed at interrupt level. Note that when the EC - * reboots, the host will reboot too, so there is no response to this command. + * AP <--> EC <--> PD MCU * - * Use EC_CMD_REBOOT_EC to reboot the EC more politely. - */ -#define EC_CMD_REBOOT 0xd1 /* Think "die" */ - -/* - * Resend last response (not supported on LPC). + * The top 2 bits of the command number are used to indicate which device the + * command is intended for. Device 0 is always the device receiving the + * command; other device mapping is board-specific. * - * Returns EC_RES_UNAVAILABLE if there is no response available - for example, - * there was no previous command, or the previous command's response was too - * big to save. + * When a device receives a command to be passed to a sub-processor, it passes + * it on with the device number set back to 0. This allows the sub-processor + * to remain blissfully unaware of whether the command originated on the next + * device up the chain, or was passed through from the AP. + * + * In the above example, if the AP wants to send command 0x0002 to the PD MCU, + * AP sends command 0x4002 to the EC + * EC sends command 0x0002 to the PD MCU + * EC forwards PD MCU response back to the AP */ -#define EC_CMD_RESEND_RESPONSE 0xdb +/* Offset and max command number for sub-device n */ +#define EC_CMD_PASSTHRU_OFFSET(n) (0x4000 * (n)) +#define EC_CMD_PASSTHRU_MAX(n) (EC_CMD_PASSTHRU_OFFSET(n) + 0x3fff) + +/*****************************************************************************/ /* - * This header byte on a command indicate version 0. Any header byte less - * than this means that we are talking to an old EC which doesn't support - * versioning. In that case, we assume version 0. - * - * Header bytes greater than this indicate a later version. For example, - * EC_CMD_VERSION0 + 1 means we are using version 1. - * - * The old EC interface must not use commands 0dc or higher. + * Deprecated constants. These constants have been renamed for clarity. The + * meaning and size has not changed. Programs that use the old names should + * switch to the new names soon, as the old names may not be carried forward + * forever. */ -#define EC_CMD_VERSION0 0xdc +#define EC_HOST_PARAM_SIZE EC_PROTO2_MAX_PARAM_SIZE +#define EC_LPC_ADDR_OLD_PARAM EC_HOST_CMD_REGION1 +#define EC_OLD_PARAM_SIZE EC_HOST_CMD_REGION_SIZE -#endif /* !__ACPI__ */ +#endif /* !__ACPI__ && !__KERNEL__ */ #endif /* __CROS_EC_COMMANDS_H */ diff --git a/include/fdtdec.h b/include/fdtdec.h index 83be064..c26df50 100644 --- a/include/fdtdec.h +++ b/include/fdtdec.h @@ -803,23 +803,6 @@ const u8 *fdtdec_locate_byte_array(const void *blob, int node, const char *prop_name, int count); /** - * Look up a property in a node which contains a memory region address and - * size. Then return a pointer to this address. - * - * The property must hold one address with a length. This is only tested on - * 32-bit machines. - * - * @param blob FDT blob - * @param node node to examine - * @param prop_name name of property to find - * @param basep Returns base address of region - * @param size Returns size of region - * @return 0 if ok, -1 on error (property not found) - */ -int fdtdec_decode_region(const void *blob, int node, const char *prop_name, - fdt_addr_t *basep, fdt_size_t *sizep); - -/** * Obtain an indexed resource from a device property. * * @param fdt FDT blob @@ -849,34 +832,6 @@ int fdt_get_named_resource(const void *fdt, int node, const char *property, const char *prop_names, const char *name, struct fdt_resource *res); -/** - * Decode a named region within a memory bank of a given type. - * - * This function handles selection of a memory region. The region is - * specified as an offset/size within a particular type of memory. - * - * The properties used are: - * - * -memory for the name of the memory bank - * -offset for the offset in that bank - * - * The property value must have an offset and a size. The function checks - * that the region is entirely within the memory bank.5 - * - * @param blob FDT blob - * @param node Node containing the properties (-1 for /config) - * @param mem_type Type of memory to use, which is a name, such as - * "u-boot" or "kernel". - * @param suffix String to append to the memory/offset - * property names - * @param basep Returns base of region - * @param sizep Returns size of region - * @return 0 if OK, -ive on error - */ -int fdtdec_decode_memory_region(const void *blob, int node, - const char *mem_type, const char *suffix, - fdt_addr_t *basep, fdt_size_t *sizep); - /* Display timings from linux include/video/display_timing.h */ enum display_flags { DISPLAY_FLAGS_HSYNC_LOW = 1 << 0, diff --git a/include/linux/compiler-gcc.h b/include/linux/compiler-gcc.h index 22ab246..8d9e079 100644 --- a/include/linux/compiler-gcc.h +++ b/include/linux/compiler-gcc.h @@ -12,7 +12,8 @@ /* Optimization barrier */ /* The "volatile" is due to gcc bugs */ -#define barrier() __asm__ __volatile__("": : :"memory") +#define barrier() \ + __asm__ __volatile__("": : :"memory") /* * This version is i.e. to prevent dead stores elimination on @ptr * where gcc and llvm may behave differently when otherwise using @@ -26,7 +27,8 @@ * the compiler that the inline asm absolutely may see the contents * of @ptr. See also: https://llvm.org/bugs/show_bug.cgi?id=15495 */ -#define barrier_data(ptr) __asm__ __volatile__("": :"r"(ptr) :"memory") +#define barrier_data(ptr) \ + __asm__ __volatile__("": :"r"(ptr) :"memory") /* * This macro obfuscates arithmetic on a variable address so that gcc diff --git a/include/log.h b/include/log.h index 653fb8d..a872fc6 100644 --- a/include/log.h +++ b/include/log.h @@ -39,16 +39,17 @@ enum log_level_t { enum log_category_t { LOGC_FIRST = 0, /* First part mirrors UCLASS_... */ - LOGC_NONE = UCLASS_COUNT, - LOGC_ARCH, - LOGC_BOARD, - LOGC_CORE, + LOGC_NONE = UCLASS_COUNT, /* First number is after all uclasses */ + LOGC_ARCH, /* Related to arch-specific code */ + LOGC_BOARD, /* Related to board-specific code */ + LOGC_CORE, /* Related to core features (non-driver-model) */ LOGC_DM, /* Core driver-model */ LOGC_DT, /* Device-tree */ LOGC_EFI, /* EFI implementation */ + LOGC_ALLOC, /* Memory allocation */ - LOGC_COUNT, - LOGC_END, + LOGC_COUNT, /* Number of log categories */ + LOGC_END, /* Sentinel value for a list of log categories */ }; /* Helper to cast a uclass ID to a log category */ @@ -88,8 +89,22 @@ int _log(enum log_category_t cat, enum log_level_t level, const char *file, */ #if CONFIG_IS_ENABLED(LOG) #define _LOG_MAX_LEVEL CONFIG_VAL(LOG_MAX_LEVEL) +#define log_err(_fmt...) log(LOG_CATEGORY, LOGL_ERR, ##_fmt) +#define log_warning(_fmt...) log(LOG_CATEGORY, LOGL_WARNING, ##_fmt) +#define log_notice(_fmt...) log(LOG_CATEGORY, LOGL_NOTICE, ##_fmt) +#define log_info(_fmt...) log(LOG_CATEGORY, LOGL_INFO, ##_fmt) +#define log_debug(_fmt...) log(LOG_CATEGORY, LOGL_DEBUG, ##_fmt) +#define log_content(_fmt...) log(LOG_CATEGORY, LOGL_DEBUG_CONTENT, ##_fmt) +#define log_io(_fmt...) log(LOG_CATEGORY, LOGL_DEBUG_IO, ##_fmt) #else #define _LOG_MAX_LEVEL LOGL_INFO +#define log_err(_fmt...) +#define log_warning(_fmt...) +#define log_notice(_fmt...) +#define log_info(_fmt...) +#define log_debug(_fmt...) +#define log_content(_fmt...) +#define log_io(_fmt...) #endif /* Emit a log record if the level is less that the maximum */ @@ -175,7 +190,7 @@ void __assert_fail(const char *assertion, const char *file, unsigned int line, }) #else #define log_ret(_ret) (_ret) -#define log_msg_ret(_ret) (_ret) +#define log_msg_ret(_msg, _ret) (_ret) #endif /** diff --git a/include/os.h b/include/os.h index 5c79721..28eb625 100644 --- a/include/os.h +++ b/include/os.h @@ -27,16 +27,6 @@ struct sandbox_state; ssize_t os_read(int fd, void *buf, size_t count); /** - * Access to the OS read() system call with non-blocking access - * - * \param fd File descriptor as returned by os_open() - * \param buf Buffer to place data - * \param count Number of bytes to read - * \return number of bytes read, or -1 on error - */ -ssize_t os_read_no_block(int fd, void *buf, size_t count); - -/** * Access to the OS write() system call * * \param fd File descriptor as returned by os_open() @@ -75,6 +65,7 @@ int os_open(const char *pathname, int flags); #define OS_O_RDWR 2 #define OS_O_MASK 3 /* Mask for read/write flags */ #define OS_O_CREAT 0100 +#define OS_O_TRUNC 01000 /** * Access to the OS close() system call @@ -334,4 +325,29 @@ void os_localtime(struct rtc_time *rt); * os_abort() - Raise SIGABRT to exit sandbox (e.g. to debugger) */ void os_abort(void); + +/** + * os_mprotect_allow() - Remove write-protection on a region of memory + * + * The start and length will be page-aligned before use. + * + * @start: Region start + * @len: Region length in bytes + * @return 0 if OK, -1 on error from mprotect() + */ +int os_mprotect_allow(void *start, size_t len); + +/** + * os_write_file() - Write a file to the host filesystem + * + * This can be useful when debugging for writing data out of sandbox for + * inspection by external tools. + * + * @name: File path to write to + * @buf: Data to write + * @size: Size of data to write + * @return 0 if OK, -ve on error + */ +int os_write_file(const char *name, const void *buf, int size); + #endif diff --git a/include/panel.h b/include/panel.h index 6237d32..cd596d4 100644 --- a/include/panel.h +++ b/include/panel.h @@ -15,6 +15,16 @@ struct panel_ops { * @return 0 if OK, -ve on error */ int (*enable_backlight)(struct udevice *dev); + + /** + * set_backlight - Set panel backlight brightness + * + * @dev: Panel device containing the backlight to update + * @percent: Brightness value (0 to 100, or BACKLIGHT_... value) + * @return 0 if OK, -ve on error + */ + int (*set_backlight)(struct udevice *dev, int percent); + /** * get_timings() - Get display timings from panel. * @@ -29,14 +39,24 @@ struct panel_ops { #define panel_get_ops(dev) ((struct panel_ops *)(dev)->driver->ops) /** - * panel_enable_backlight() - Enable the panel backlight + * panel_enable_backlight() - Enable/disable the panel backlight * * @dev: Panel device containing the backlight to enable + * @enable: true to enable the backlight, false to dis * @return 0 if OK, -ve on error */ int panel_enable_backlight(struct udevice *dev); /** + * panel_set_backlight - Set brightness for the panel backlight + * + * @dev: Panel device containing the backlight to update + * @percent: Brightness value (0 to 100, or BACKLIGHT_... value) + * @return 0 if OK, -ve on error + */ +int panel_set_backlight(struct udevice *dev, int percent); + +/** * panel_get_display_timing() - Get display timings from panel. * * @dev: Panel device containing the display timings diff --git a/include/part_efi.h b/include/part_efi.h index 8525770..7170b61 100644 --- a/include/part_efi.h +++ b/include/part_efi.h @@ -24,7 +24,7 @@ #define EFI_PMBR_OSTYPE_EFI 0xEF #define EFI_PMBR_OSTYPE_EFI_GPT 0xEE -#define GPT_HEADER_SIGNATURE 0x5452415020494645ULL +#define GPT_HEADER_SIGNATURE_UBOOT 0x5452415020494645ULL #define GPT_HEADER_REVISION_V1 0x00010000 #define GPT_PRIMARY_PARTITION_TABLE_LBA 1ULL #define GPT_ENTRY_NUMBERS CONFIG_EFI_PARTITION_ENTRIES_NUMBERS diff --git a/include/string.h b/include/string.h new file mode 100644 index 0000000..38134dc --- /dev/null +++ b/include/string.h @@ -0,0 +1 @@ +#include diff --git a/include/sysreset.h b/include/sysreset.h index a5c0b74..61295e3 100644 --- a/include/sysreset.h +++ b/include/sysreset.h @@ -11,6 +11,7 @@ enum sysreset_t { SYSRESET_WARM, /* Reset CPU, keep GPIOs active */ SYSRESET_COLD, /* Reset CPU and GPIOs */ SYSRESET_POWER, /* Reset PMIC (remove and restore power) */ + SYSRESET_POWER_OFF, /* Turn off power */ SYSRESET_COUNT, }; @@ -31,11 +32,20 @@ struct sysreset_ops { /** * get_status() - get printable reset status information * + * @dev: Device to check * @buf: Buffer to receive the textual reset information * @size: Size of the passed buffer * @return 0 if OK, -ve on error */ int (*get_status)(struct udevice *dev, char *buf, int size); + + /** + * get_last() - get information on the last reset + * + * @dev: Device to check + * @return last reset state (enum sysreset_t) or -ve error + */ + int (*get_last)(struct udevice *dev); }; #define sysreset_get_ops(dev) ((struct sysreset_ops *)(dev)->driver->ops) @@ -49,8 +59,9 @@ struct sysreset_ops { int sysreset_request(struct udevice *dev, enum sysreset_t type); /** - * get_status() - get printable reset status information + * sysreset_get_status() - get printable reset status information * + * @dev: Device to check * @buf: Buffer to receive the textual reset information * @size: Size of the passed buffer * @return 0 if OK, -ve on error @@ -58,6 +69,14 @@ int sysreset_request(struct udevice *dev, enum sysreset_t type); int sysreset_get_status(struct udevice *dev, char *buf, int size); /** + * sysreset_get_last() - get information on the last reset + * + * @dev: Device to check + * @return last reset state (enum sysreset_t) or -ve error + */ +int sysreset_get_last(struct udevice *dev); + +/** * sysreset_walk() - cause a system reset * * This works through the available sysreset devices until it finds one that can @@ -72,6 +91,19 @@ int sysreset_get_status(struct udevice *dev, char *buf, int size); int sysreset_walk(enum sysreset_t type); /** + * sysreset_get_last_walk() - get information on the last reset + * + * This works through the available sysreset devices until it finds one that can + * perform a reset. If the provided sysreset type is not available, the next one + * will be tried. + * + * If no device prives the information, this function returns -ENOENT + * + * @return last reset state (enum sysreset_t) or -ve error + */ +int sysreset_get_last_walk(void); + +/** * sysreset_walk_halt() - try to reset, otherwise halt * * This calls sysreset_walk(). If it returns, indicating that reset is not diff --git a/include/tpm-v1.h b/include/tpm-v1.h index 6b4941e..be2eca9 100644 --- a/include/tpm-v1.h +++ b/include/tpm-v1.h @@ -81,6 +81,12 @@ enum tpm_capability_areas { TPM_CAP_VERSION_VAL = 0x0000001A, }; +enum tmp_cap_flag { + TPM_CAP_FLAG_PERMANENT = 0x108, +}; + +#define TPM_TAG_PERMANENT_FLAGS 0x001f + #define TPM_NV_PER_GLOBALLOCK BIT(15) #define TPM_NV_PER_PPREAD BIT(16) #define TPM_NV_PER_PPWRITE BIT(0) @@ -93,6 +99,14 @@ enum { TPM_PUBEK_SIZE = 256, }; +enum { + TPM_CMD_EXTEND = 0x14, + TPM_CMD_GET_CAPABILITY = 0x65, + TPM_CMD_NV_DEFINE_SPACE = 0xcc, + TPM_CMD_NV_WRITE_VALUE = 0xcd, + TPM_CMD_NV_READ_VALUE = 0xcf, +}; + /** * TPM return codes as defined in the TCG Main specification * (TPM Main Part 2 Structures; Specification version 1.2) @@ -231,6 +245,40 @@ struct tpm_permanent_flags { u8 disable_full_da_logic_info; } __packed; +#define TPM_SHA1_160_HASH_LEN 0x14 + +struct __packed tpm_composite_hash { + u8 digest[TPM_SHA1_160_HASH_LEN]; +}; + +struct __packed tpm_pcr_selection { + __be16 size_of_select; + u8 pcr_select[3]; /* matches vboot's struct */ +}; + +struct __packed tpm_pcr_info_short { + struct tpm_pcr_selection pcr_selection; + u8 locality_at_release; + struct tpm_composite_hash digest_at_release; +}; + +struct __packed tpm_nv_attributes { + __be16 tag; + __be32 attributes; +}; + +struct __packed tpm_nv_data_public { + __be16 tag; + __be32 nv_index; + struct tpm_pcr_info_short pcr_info_read; + struct tpm_pcr_info_short pcr_info_write; + struct tpm_nv_attributes permission; + u8 read_st_clear; + u8 write_st_clear; + u8 write_define; + __be32 data_size; +}; + /** * Issue a TPM_Startup command. * @@ -477,4 +525,32 @@ u32 tpm_find_key_sha1(const u8 auth[20], const u8 pubkey_digest[20], */ u32 tpm_get_random(void *data, u32 count); +/** + * tpm_finalise_physical_presence() - Finalise physical presence + * + * @return return code of the operation (0 = success) + */ +u32 tpm_finalise_physical_presence(void); + +/** + * tpm_nv_set_locked() - lock the non-volatile space + * + * @return return code of the operation (0 = success) + */ +u32 tpm_nv_set_locked(void); + +/** + * tpm_set_global_lock() - set the global lock + * + * @return return code of the operation (0 = success) + */ +u32 tpm_set_global_lock(void); + +/** + * tpm_resume() - start up the TPM from resume (after suspend) + * + * @return return code of the operation (0 = success) + */ +u32 tpm_resume(void); + #endif /* __TPM_V1_H */ diff --git a/include/tpm-v2.h b/include/tpm-v2.h index 780e061..c77b416 100644 --- a/include/tpm-v2.h +++ b/include/tpm-v2.h @@ -83,6 +83,7 @@ enum tpm2_command_codes { TPM2_CC_PCR_SETAUTHPOL = 0x012C, TPM2_CC_DAM_RESET = 0x0139, TPM2_CC_DAM_PARAMETERS = 0x013A, + TPM2_CC_NV_READ = 0x014E, TPM2_CC_GET_CAPABILITY = 0x017A, TPM2_CC_PCR_READ = 0x017E, TPM2_CC_PCR_EXTEND = 0x0182, diff --git a/include/video.h b/include/video.h index e7fc5c9..75200f0 100644 --- a/include/video.h +++ b/include/video.h @@ -55,7 +55,7 @@ enum video_log2_bpp { * @xsize: Number of pixel columns (e.g. 1366) * @ysize: Number of pixels rows (e.g.. 768) * @rot: Display rotation (0=none, 1=90 degrees clockwise, etc.) - * @bpix: Encoded bits per pixel + * @bpix: Encoded bits per pixel (enum video_log2_bpp) * @vidconsole_drv_name: Driver to use for the text console, NULL to * select automatically * @font_size: Font size in pixels (0 to use a default value) @@ -120,8 +120,9 @@ int video_reserve(ulong *addrp); * video_clear() - Clear a device's frame buffer to background color. * * @dev: Device to clear + * @return 0 */ -void video_clear(struct udevice *dev); +int video_clear(struct udevice *dev); /** * video_sync() - Sync a device's frame buffer with its hardware @@ -131,8 +132,10 @@ void video_clear(struct udevice *dev); * buffer are displayed to the user. * * @dev: Device to sync + * @force: True to force a sync even if there was one recently (this is + * very expensive on sandbox) */ -void video_sync(struct udevice *vid); +void video_sync(struct udevice *vid, bool force); /** * video_sync_all() - Sync all devices' frame buffers with there hardware @@ -266,6 +269,6 @@ int lg4573_spi_startup(unsigned int bus, unsigned int cs, */ void video_get_info_str(int line_number, char *info); -#endif /* CONFIG_DM_VIDEO */ +#endif /* !CONFIG_DM_VIDEO */ #endif diff --git a/lib/Kconfig b/lib/Kconfig index 622f3c2..ccab426 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -185,6 +185,28 @@ config TPM for the low-level TPM interface, but only one TPM is supported at a time by the TPM library. +config SPL_TPM + bool "Trusted Platform Module (TPM) Support in SPL" + depends on SPL_DM + help + This enables support for TPMs which can be used to provide security + features for your board. The TPM can be connected via LPC or I2C + and a sandbox TPM is provided for testing purposes. Use the 'tpm' + command to interactive the TPM. Driver model support is provided + for the low-level TPM interface, but only one TPM is supported at + a time by the TPM library. + +config TPL_TPM + bool "Trusted Platform Module (TPM) Support in TPL" + depends on TPL_DM + help + This enables support for TPMs which can be used to provide security + features for your board. The TPM can be connected via LPC or I2C + and a sandbox TPM is provided for testing purposes. Use the 'tpm' + command to interactive the TPM. Driver model support is provided + for the low-level TPM interface, but only one TPM is supported at + a time by the TPM library. + endmenu menu "Android Verified Boot" @@ -331,6 +353,16 @@ config SPL_OF_LIBFDT particular compatible nodes. The library operates on a flattened version of the device tree. +config TPL_OF_LIBFDT + bool "Enable the FDT library for TPL" + default y if TPL_OF_CONTROL + help + This enables the FDT library (libfdt). It provides functions for + accessing binary device tree images in memory, such as adding and + removing nodes and properties, scanning through the tree and finding + particular compatible nodes. The library operates on a flattened + version of the device tree. + config FDT_FIXUP_PARTITIONS bool "overwrite MTD partitions in DTS through defined in 'mtdparts'" depends on OF_LIBFDT diff --git a/lib/Makefile b/lib/Makefile index f169644..fb69441 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -45,14 +45,18 @@ obj-$(CONFIG_PHYSMEM) += physmem.o obj-y += qsort.o obj-y += rc4.o obj-$(CONFIG_SUPPORT_EMMC_RPMB) += sha256.o -obj-$(CONFIG_TPM) += tpm-common.o -obj-$(CONFIG_TPM_V1) += tpm-v1.o -obj-$(CONFIG_TPM_V2) += tpm-v2.o obj-$(CONFIG_RBTREE) += rbtree.o obj-$(CONFIG_BITREVERSE) += bitrev.o obj-y += list_sort.o endif +obj-$(CONFIG_$(SPL_TPL_)TPM) += tpm-common.o +ifeq ($(CONFIG_$(SPL_TPL_)TPM),y) +obj-y += crc8.o +obj-$(CONFIG_TPM_V1) += tpm-v1.o +obj-$(CONFIG_TPM_V2) += tpm-v2.o +endif + obj-$(CONFIG_RSA) += rsa/ obj-$(CONFIG_SHA1) += sha1.o obj-$(CONFIG_SHA256) += sha256.o diff --git a/lib/fdtdec.c b/lib/fdtdec.c index 74196ce..b1b3925 100644 --- a/lib/fdtdec.c +++ b/lib/fdtdec.c @@ -922,28 +922,6 @@ char *fdtdec_get_config_string(const void *blob, const char *prop_name) return (char *)nodep; } -int fdtdec_decode_region(const void *blob, int node, const char *prop_name, - fdt_addr_t *basep, fdt_size_t *sizep) -{ - const fdt_addr_t *cell; - int len; - - debug("%s: %s: %s\n", __func__, fdt_get_name(blob, node, NULL), - prop_name); - cell = fdt_getprop(blob, node, prop_name, &len); - if (!cell || (len < sizeof(fdt_addr_t) * 2)) { - debug("cell=%p, len=%d\n", cell, len); - return -1; - } - - *basep = fdt_addr_to_cpu(*cell); - *sizep = fdt_size_to_cpu(cell[1]); - debug("%s: base=%08lx, size=%lx\n", __func__, (ulong)*basep, - (ulong)*sizep); - - return 0; -} - u64 fdtdec_get_number(const fdt32_t *ptr, unsigned int cells) { u64 number = 0; @@ -1002,67 +980,6 @@ int fdt_get_named_resource(const void *fdt, int node, const char *property, return fdt_get_resource(fdt, node, property, index, res); } -int fdtdec_decode_memory_region(const void *blob, int config_node, - const char *mem_type, const char *suffix, - fdt_addr_t *basep, fdt_size_t *sizep) -{ - char prop_name[50]; - const char *mem; - fdt_size_t size, offset_size; - fdt_addr_t base, offset; - int node; - - if (config_node == -1) { - config_node = fdt_path_offset(blob, "/config"); - if (config_node < 0) { - debug("%s: Cannot find /config node\n", __func__); - return -ENOENT; - } - } - if (!suffix) - suffix = ""; - - snprintf(prop_name, sizeof(prop_name), "%s-memory%s", mem_type, - suffix); - mem = fdt_getprop(blob, config_node, prop_name, NULL); - if (!mem) { - debug("%s: No memory type for '%s', using /memory\n", __func__, - prop_name); - mem = "/memory"; - } - - node = fdt_path_offset(blob, mem); - if (node < 0) { - debug("%s: Failed to find node '%s': %s\n", __func__, mem, - fdt_strerror(node)); - return -ENOENT; - } - - /* - * Not strictly correct - the memory may have multiple banks. We just - * use the first - */ - if (fdtdec_decode_region(blob, node, "reg", &base, &size)) { - debug("%s: Failed to decode memory region %s\n", __func__, - mem); - return -EINVAL; - } - - snprintf(prop_name, sizeof(prop_name), "%s-offset%s", mem_type, - suffix); - if (fdtdec_decode_region(blob, config_node, prop_name, &offset, - &offset_size)) { - debug("%s: Failed to decode memory region '%s'\n", __func__, - prop_name); - return -EINVAL; - } - - *basep = base + offset; - *sizep = offset_size; - - return 0; -} - static int decode_timing_property(const void *blob, int node, const char *name, struct timing_entry *result) { diff --git a/lib/hang.c b/lib/hang.c index bf56f4c..c5a7869 100644 --- a/lib/hang.c +++ b/lib/hang.c @@ -20,8 +20,9 @@ */ void hang(void) { -#if !defined(CONFIG_SPL_BUILD) || (defined(CONFIG_SPL_LIBCOMMON_SUPPORT) && \ - defined(CONFIG_SPL_SERIAL_SUPPORT)) +#if !defined(CONFIG_SPL_BUILD) || \ + (CONFIG_IS_ENABLED(LIBCOMMON_SUPPORT) && \ + CONFIG_IS_ENABLED(SERIAL_SUPPORT)) puts("### ERROR ### Please RESET the board ###\n"); #endif bootstage_error(BOOTSTAGE_ID_NEED_RESET); diff --git a/lib/tpm-common.c b/lib/tpm-common.c index 43b5308..a440639 100644 --- a/lib/tpm-common.c +++ b/lib/tpm-common.c @@ -4,6 +4,8 @@ * Coypright (c) 2013 Guntermann & Drunck GmbH */ +#define LOG_CATEGORY UCLASS_TPM + #include #include #include @@ -110,6 +112,8 @@ int unpack_byte_string(const u8 *str, size_t size, const char *format, ...) if (offset + length > size) { va_end(args); + log_err("Failed to read: size=%d, offset=%x, len=%x\n", + size, offset, length); return -1; } @@ -176,10 +180,10 @@ u32 tpm_sendrecv_command(const void *command, void *response, size_t *size_ptr) ret = tpm_return_code(response); - log(LOGC_NONE, LOGL_DEBUG, "TPM response [ret:%d]: ", ret); + log_debug("TPM response [ret:%d]: ", ret); for (i = 0; i < response_length; i++) - log(LOGC_NONE, LOGL_DEBUG, "%02x ", ((u8 *)response)[i]); - log(LOGC_NONE, LOGL_DEBUG, "\n"); + log_debug("%02x ", ((u8 *)response)[i]); + log_debug("\n"); return ret; } diff --git a/lib/tpm-v1.c b/lib/tpm-v1.c index 7aecb24..9d45c3d 100644 --- a/lib/tpm-v1.c +++ b/lib/tpm-v1.c @@ -4,6 +4,8 @@ * Coypright (c) 2013 Guntermann & Drunck GmbH */ +#define LOG_CATEGORY UCLASS_TPM + #include #include #include @@ -45,6 +47,11 @@ u32 tpm_startup(enum tpm_startup_type mode) return tpm_sendrecv_command(buf, NULL, NULL); } +u32 tpm_resume(void) +{ + return tpm_startup(TPM_ST_STATE); +} + u32 tpm_self_test_full(void) { const u8 command[10] = { @@ -61,6 +68,34 @@ u32 tpm_continue_self_test(void) return tpm_sendrecv_command(command, NULL, NULL); } +u32 tpm_clear_and_reenable(void) +{ + u32 ret; + + log_info("TPM: Clear and re-enable\n"); + ret = tpm_force_clear(); + if (ret != TPM_SUCCESS) { + log_err("Can't initiate a force clear\n"); + return ret; + } + +#if IS_ENABLED(CONFIG_TPM_V1) + ret = tpm_physical_enable(); + if (ret != TPM_SUCCESS) { + log_err("TPM: Can't set enabled state\n"); + return ret; + } + + ret = tpm_physical_set_deactivated(0); + if (ret != TPM_SUCCESS) { + log_err("TPM: Can't set deactivated state\n"); + return ret; + } +#endif + + return TPM_SUCCESS; +} + u32 tpm_nv_define_space(u32 index, u32 perm, u32 size) { const u8 command[101] = { @@ -104,6 +139,11 @@ u32 tpm_nv_define_space(u32 index, u32 perm, u32 size) return tpm_sendrecv_command(buf, NULL, NULL); } +u32 tpm_nv_set_locked(void) +{ + return tpm_nv_define_space(TPM_NV_INDEX_LOCK, 0, 0); +} + u32 tpm_nv_read_value(u32 index, void *data, u32 count) { const u8 command[22] = { @@ -168,6 +208,13 @@ u32 tpm_nv_write_value(u32 index, const void *data, u32 length) return 0; } +uint32_t tpm_set_global_lock(void) +{ + u32 x; + + return tpm_nv_write_value(TPM_NV_INDEX_0, (uint8_t *)&x, 0); +} + u32 tpm_extend(u32 index, const void *in_digest, void *out_digest) { const u8 command[34] = { @@ -243,6 +290,15 @@ u32 tpm_tsc_physical_presence(u16 presence) return tpm_sendrecv_command(buf, NULL, NULL); } +u32 tpm_finalise_physical_presence(void) +{ + const u8 command[12] = { + 0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x40, 0x0, 0x0, 0xa, 0x2, 0xa0, + }; + + return tpm_sendrecv_command(command, NULL, NULL); +} + u32 tpm_read_pubek(void *data, size_t count) { const u8 command[30] = { @@ -377,13 +433,19 @@ u32 tpm_get_permanent_flags(struct tpm_permanent_flags *pflags) if (err) return err; if (unpack_byte_string(response, response_length, "d", - data_size_offset, &data_size)) + data_size_offset, &data_size)) { + log_err("Cannot unpack data size\n"); return TPM_LIB_ERROR; - if (data_size < sizeof(*pflags)) + } + if (data_size < sizeof(*pflags)) { + log_err("Data size too small\n"); return TPM_LIB_ERROR; + } if (unpack_byte_string(response, response_length, "s", - data_offset, pflags, sizeof(*pflags))) + data_offset, pflags, sizeof(*pflags))) { + log_err("Cannot unpack pflags\n"); return TPM_LIB_ERROR; + } return 0; } diff --git a/scripts/Makefile.spl b/scripts/Makefile.spl index e494d18..7416abe 100644 --- a/scripts/Makefile.spl +++ b/scripts/Makefile.spl @@ -45,6 +45,13 @@ SPL_ := SPL_TPL_ := endif +ifeq ($(obj)$(CONFIG_SUPPORT_SPL),spl) +$(error You cannot build SPL without enabling CONFIG_SUPPORT_SPL) +endif +ifeq ($(obj)$(CONFIG_SUPPORT_TPL),tpl) +$(error You cannot build TPL without enabling CONFIG_SUPPORT_TPL) +endif + include $(srctree)/config.mk include $(srctree)/arch/$(ARCH)/Makefile @@ -364,7 +371,7 @@ $(u-boot-spl-dirs): $(u-boot-spl-platdata) quiet_cmd_cpp_lds = LDS $@ cmd_cpp_lds = $(CPP) -Wp,-MD,$(depfile) $(cpp_flags) $(LDPPFLAGS) -ansi \ - -D__ASSEMBLY__ -x assembler-with-cpp -P -o $@ $< + -D__ASSEMBLY__ -x assembler-with-cpp -std=c99 -P -o $@ $< $(obj)/u-boot-spl.lds: $(LDSCRIPT) FORCE $(call if_changed_dep,cpp_lds) diff --git a/scripts/config_whitelist.txt b/scripts/config_whitelist.txt index e805b1e..b85c35b 100644 --- a/scripts/config_whitelist.txt +++ b/scripts/config_whitelist.txt @@ -1673,7 +1673,6 @@ CONFIG_RTC_IMXDI CONFIG_RTC_M41T11 CONFIG_RTC_M41T62 CONFIG_RTC_MC13XXX -CONFIG_RTC_MC146818 CONFIG_RTC_MCFRRTC CONFIG_RTC_MCP79411 CONFIG_RTC_MXS diff --git a/test/dm/Makefile b/test/dm/Makefile index 57c7dfb..b490cf2 100644 --- a/test/dm/Makefile +++ b/test/dm/Makefile @@ -25,6 +25,7 @@ obj-$(CONFIG_DM_MAILBOX) += mailbox.o obj-$(CONFIG_DM_MMC) += mmc.o obj-y += ofnode.o obj-$(CONFIG_OSD) += osd.o +obj-$(CONFIG_DM_VIDEO) += panel.o obj-$(CONFIG_DM_PCI) += pci.o obj-$(CONFIG_PHY) += phy.o obj-$(CONFIG_POWER_DOMAIN) += power-domain.o diff --git a/test/dm/bus.c b/test/dm/bus.c index e9a4028..08137a2 100644 --- a/test/dm/bus.c +++ b/test/dm/bus.c @@ -4,6 +4,9 @@ */ #include +#ifdef CONFIG_SANDBOX +#include +#endif #include #include #include @@ -297,6 +300,11 @@ static int dm_test_bus_parent_data_uclass(struct unit_test_state *uts) ut_assertok(uclass_find_device(UCLASS_TEST_BUS, 0, &bus)); drv = (struct driver *)bus->driver; size = drv->per_child_auto_alloc_size; + +#ifdef CONFIG_SANDBOX + os_mprotect_allow(bus->uclass->uc_drv, sizeof(*bus->uclass->uc_drv)); + os_mprotect_allow(drv, sizeof(*drv)); +#endif bus->uclass->uc_drv->per_child_auto_alloc_size = size; drv->per_child_auto_alloc_size = 0; ret = test_bus_parent_data(uts); @@ -440,6 +448,10 @@ static int dm_test_bus_parent_platdata_uclass(struct unit_test_state *uts) ut_assertok(uclass_find_device(UCLASS_TEST_BUS, 0, &bus)); drv = (struct driver *)bus->driver; size = drv->per_child_platdata_auto_alloc_size; +#ifdef CONFIG_SANDBOX + os_mprotect_allow(bus->uclass->uc_drv, sizeof(*bus->uclass->uc_drv)); + os_mprotect_allow(drv, sizeof(*drv)); +#endif bus->uclass->uc_drv->per_child_platdata_auto_alloc_size = size; drv->per_child_platdata_auto_alloc_size = 0; ret = test_bus_parent_platdata(uts); diff --git a/test/dm/core.c b/test/dm/core.c index c15a840..260f649 100644 --- a/test/dm/core.c +++ b/test/dm/core.c @@ -870,3 +870,34 @@ static int dm_test_uclass_names(struct unit_test_state *uts) return 0; } DM_TEST(dm_test_uclass_names, DM_TESTF_SCAN_PDATA); + +static int dm_test_inactive_child(struct unit_test_state *uts) +{ + struct dm_test_state *dms = uts->priv; + struct udevice *parent, *dev1, *dev2; + + /* Skip the behaviour in test_post_probe() */ + dms->skip_post_probe = 1; + + ut_assertok(uclass_first_device_err(UCLASS_TEST, &parent)); + + /* + * Create a child but do not activate it. Calling the function again + * should return the same child. + */ + ut_asserteq(-ENODEV, device_find_first_inactive_child(parent, + UCLASS_TEST, &dev1)); + ut_assertok(device_bind_ofnode(parent, DM_GET_DRIVER(test_drv), + "test_child", 0, ofnode_null(), &dev1)); + + ut_assertok(device_find_first_inactive_child(parent, UCLASS_TEST, + &dev2)); + ut_asserteq_ptr(dev1, dev2); + + ut_assertok(device_probe(dev1)); + ut_asserteq(-ENODEV, device_find_first_inactive_child(parent, + UCLASS_TEST, &dev2)); + + return 0; +} +DM_TEST(dm_test_inactive_child, DM_TESTF_SCAN_PDATA); diff --git a/test/dm/ofnode.c b/test/dm/ofnode.c index 907d1dd..745de50 100644 --- a/test/dm/ofnode.c +++ b/test/dm/ofnode.c @@ -2,6 +2,7 @@ #include #include +#include #include #include @@ -42,3 +43,18 @@ static int dm_test_ofnode_by_prop_value(struct unit_test_state *uts) return 0; } DM_TEST(dm_test_ofnode_by_prop_value, DM_TESTF_SCAN_FDT); + +static int dm_test_ofnode_fmap(struct unit_test_state *uts) +{ + struct fmap_entry entry; + ofnode node; + + node = ofnode_path("/cros-ec/flash"); + ut_assert(ofnode_valid(node)); + ut_assertok(ofnode_read_fmap_entry(node, &entry)); + ut_asserteq(0x08000000, entry.offset); + ut_asserteq(0x20000, entry.length); + + return 0; +} +DM_TEST(dm_test_ofnode_fmap, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); diff --git a/test/dm/panel.c b/test/dm/panel.c new file mode 100644 index 0000000..7e4ebd6 --- /dev/null +++ b/test/dm/panel.c @@ -0,0 +1,79 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Test for panel uclass + * + * Copyright (c) 2018 Google, Inc + * Written by Simon Glass + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Basic test of the panel uclass */ +static int dm_test_panel(struct unit_test_state *uts) +{ + struct udevice *dev, *pwm, *gpio, *reg; + uint period_ns; + uint duty_ns; + bool enable; + bool polarity; + + ut_assertok(uclass_first_device_err(UCLASS_PANEL, &dev)); + ut_assertok(uclass_first_device_err(UCLASS_PWM, &pwm)); + ut_assertok(uclass_get_device(UCLASS_GPIO, 1, &gpio)); + ut_assertok(regulator_get_by_platname("VDD_EMMC_1.8V", ®)); + ut_assertok(sandbox_pwm_get_config(pwm, 0, &period_ns, &duty_ns, + &enable, &polarity)); + ut_asserteq(false, enable); + ut_asserteq(false, regulator_get_enable(reg)); + + ut_assertok(panel_enable_backlight(dev)); + ut_assertok(sandbox_pwm_get_config(pwm, 0, &period_ns, &duty_ns, + &enable, &polarity)); + ut_asserteq(1000, period_ns); + ut_asserteq(170 * 1000 / 256, duty_ns); + ut_asserteq(true, enable); + ut_asserteq(false, polarity); + ut_asserteq(1, sandbox_gpio_get_value(gpio, 1)); + ut_asserteq(true, regulator_get_enable(reg)); + + ut_assertok(panel_set_backlight(dev, 40)); + ut_assertok(sandbox_pwm_get_config(pwm, 0, &period_ns, &duty_ns, + &enable, &polarity)); + ut_asserteq(64 * 1000 / 256, duty_ns); + + ut_assertok(panel_set_backlight(dev, BACKLIGHT_MAX)); + ut_assertok(sandbox_pwm_get_config(pwm, 0, &period_ns, &duty_ns, + &enable, &polarity)); + ut_asserteq(255 * 1000 / 256, duty_ns); + + ut_assertok(panel_set_backlight(dev, BACKLIGHT_MIN)); + ut_assertok(sandbox_pwm_get_config(pwm, 0, &period_ns, &duty_ns, + &enable, &polarity)); + ut_asserteq(0 * 1000 / 256, duty_ns); + ut_asserteq(1, sandbox_gpio_get_value(gpio, 1)); + + ut_assertok(panel_set_backlight(dev, BACKLIGHT_DEFAULT)); + ut_assertok(sandbox_pwm_get_config(pwm, 0, &period_ns, &duty_ns, + &enable, &polarity)); + ut_asserteq(true, enable); + ut_asserteq(170 * 1000 / 256, duty_ns); + + ut_assertok(panel_set_backlight(dev, BACKLIGHT_OFF)); + ut_assertok(sandbox_pwm_get_config(pwm, 0, &period_ns, &duty_ns, + &enable, &polarity)); + ut_asserteq(0 * 1000 / 256, duty_ns); + ut_asserteq(0, sandbox_gpio_get_value(gpio, 1)); + ut_asserteq(false, regulator_get_enable(reg)); + + return 0; +} +DM_TEST(dm_test_panel, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); diff --git a/test/dm/sysreset.c b/test/dm/sysreset.c index 04d4621..e1b7bf5 100644 --- a/test/dm/sysreset.c +++ b/test/dm/sysreset.c @@ -62,7 +62,6 @@ static int dm_test_sysreset_get_status(struct unit_test_state *uts) return 0; } - DM_TEST(dm_test_sysreset_get_status, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); /* Test that we can walk through the sysreset devices */ @@ -72,6 +71,7 @@ static int dm_test_sysreset_walk(struct unit_test_state *uts) /* If we generate a power sysreset, we will exit sandbox! */ state->sysreset_allowed[SYSRESET_POWER] = false; + state->sysreset_allowed[SYSRESET_POWER_OFF] = false; ut_asserteq(-EACCES, sysreset_walk(SYSRESET_WARM)); ut_asserteq(-EACCES, sysreset_walk(SYSRESET_COLD)); ut_asserteq(-EACCES, sysreset_walk(SYSRESET_POWER)); @@ -91,3 +91,22 @@ static int dm_test_sysreset_walk(struct unit_test_state *uts) return 0; } DM_TEST(dm_test_sysreset_walk, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); + +static int dm_test_sysreset_get_last(struct unit_test_state *uts) +{ + struct udevice *dev; + + /* Device 1 is the warm sysreset device */ + ut_assertok(uclass_get_device(UCLASS_SYSRESET, 1, &dev)); + ut_asserteq(SYSRESET_WARM, sysreset_get_last(dev)); + + /* Device 2 is the cold sysreset device */ + ut_assertok(uclass_get_device(UCLASS_SYSRESET, 2, &dev)); + ut_asserteq(SYSRESET_COLD, sysreset_get_last(dev)); + + /* This is device 0, the non-DT one */ + ut_asserteq(SYSRESET_COLD, sysreset_get_last_walk()); + + return 0; +} +DM_TEST(dm_test_sysreset_get_last, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); diff --git a/test/dm/video.c b/test/dm/video.c index ef74c2d..7def338 100644 --- a/test/dm/video.c +++ b/test/dm/video.c @@ -169,7 +169,7 @@ static int dm_test_video_ansi(struct unit_test_state *uts) /* reference clear: */ video_clear(con->parent); - video_sync(con->parent); + video_sync(con->parent, false); ut_asserteq(46, compress_frame_buffer(dev)); /* test clear escape sequence: [2J */ diff --git a/test/log/log_test.c b/test/log/log_test.c index de431b0..febc2c1 100644 --- a/test/log/log_test.c +++ b/test/log/log_test.c @@ -181,6 +181,19 @@ static int log_test(int testnum) return ret; break; } + case 10: { + log_err("level %d\n", LOGL_EMERG); + log_err("level %d\n", LOGL_ALERT); + log_err("level %d\n", LOGL_CRIT); + log_err("level %d\n", LOGL_ERR); + log_warning("level %d\n", LOGL_WARNING); + log_notice("level %d\n", LOGL_NOTICE); + log_info("level %d\n", LOGL_INFO); + log_debug("level %d\n", LOGL_DEBUG); + log_content("level %d\n", LOGL_DEBUG_CONTENT); + log_io("level %d\n", LOGL_DEBUG_IO); + break; + } } return 0; diff --git a/test/py/README.md b/test/py/README.md index aed2fd0..4d9d2b8 100644 --- a/test/py/README.md +++ b/test/py/README.md @@ -29,6 +29,7 @@ tests. Similar package names should exist in other distributions. | -------------- | ----------------------------- | | python | 2.7.5-5ubuntu3 | | python-pytest | 2.5.1-1 | +| python-subunit | - | | gdisk | 0.8.8-1ubuntu0.1 | | dfu-util | 0.5-1 | | dtc | 1.4.0+dfsg-1 | diff --git a/test/py/multiplexed_log.py b/test/py/multiplexed_log.py index f23d5de..637a3bd 100644 --- a/test/py/multiplexed_log.py +++ b/test/py/multiplexed_log.py @@ -314,8 +314,9 @@ $(document).ready(function () { # The set of characters that should be represented as hexadecimal codes in # the log file. - _nonprint = ('%' + ''.join(chr(c) for c in range(0, 32) if c not in (9, 10)) + - ''.join(chr(c) for c in range(127, 256))) + _nonprint = {ord('%')} + _nonprint.update({c for c in range(0, 32) if c not in (9, 10)}) + _nonprint.update({c for c in range(127, 256)}) def _escape(self, data): """Render data format suitable for inclusion in an HTML document. @@ -331,7 +332,7 @@ $(document).ready(function () { """ data = data.replace(chr(13), '') - data = ''.join((c in self._nonprint) and ('%%%02x' % ord(c)) or + data = ''.join((ord(c) in self._nonprint) and ('%%%02x' % ord(c)) or c for c in data) data = cgi.escape(data) return data diff --git a/test/py/tests/test_log.py b/test/py/tests/test_log.py index 605275b..cb18344 100644 --- a/test/py/tests/test_log.py +++ b/test/py/tests/test_log.py @@ -85,6 +85,11 @@ def test_log(u_boot_console): lines = run_test(9) check_log_entries(lines, 3) + def test10(): + lines = run_test(10) + for i in range(7): + assert 'log_test() level %d' % i == lines.next() + # TODO(sjg@chromium.org): Consider structuring this as separate tests cons = u_boot_console test0() @@ -97,6 +102,7 @@ def test_log(u_boot_console): test7() test8() test9() + test10() @pytest.mark.buildconfigspec('cmd_log') def test_log_format(u_boot_console): diff --git a/test/run b/test/run index d77a1c3..fb8ff5d 100755 --- a/test/run +++ b/test/run @@ -1,40 +1,53 @@ #!/bin/bash +# Script to run all U-Boot tests that use sandbox. + +# Runs a test and checks the exit code to decide if it passed +# $1: Test name +# $2 onwards: command line to run run_test() { - $@ - [ $? -ne 0 ] && result=$((result+1)) + echo -n "$1: " + shift + "$@" + [ $? -ne 0 ] && failures=$((failures+1)) } -result=0 +failures=0 # Run all tests that the standard sandbox build can support -run_test ./test/py/test.py --bd sandbox --build +run_test "sandbox" ./test/py/test.py --bd sandbox --build # Run tests which require sandbox_spl -run_test ./test/py/test.py --bd sandbox_spl --build -k test_ofplatdata.py - -# Run tests for the flat DT version of sandbox -./test/py/test.py --bd sandbox_flattree --build - +run_test "sandbox_spl" ./test/py/test.py --bd sandbox_spl --build \ + -k test_ofplatdata.py + +# Run tests for the flat-device-tree version of sandbox. This is a special +# build which does not enable CONFIG_OF_LIVE for the live device tree, so we can +# check that functionality is the same. The standard sandbox build (above) uses +# CONFIG_OF_LIVE. +run_test "sandbox_flattree" ./test/py/test.py --bd sandbox_flattree --build \ + -k test_ut + +# Set up a path to dtc (device-tree compiler) and libfdt.py, a library it +# provides and which is built by the sandbox_spl config. DTC_DIR=build-sandbox_spl/scripts/dtc +export PYTHONPATH=${DTC_DIR}/pylibfdt +export DTC=${DTC_DIR}/dtc -PYTHONPATH=${DTC_DIR}/pylibfdt DTC=${DTC_DIR}/dtc run_test \ - ./tools/binman/binman -t -run_test ./tools/patman/patman --test -run_test ./tools/buildman/buildman -t -PYTHONPATH=${DTC_DIR}/pylibfdt DTC=${DTC_DIR}/dtc run_test ./tools/dtoc/dtoc -t +run_test "binman" ./tools/binman/binman -t +run_test "patman" ./tools/patman/patman --test +run_test "buildman" ./tools/buildman/buildman -t +run_test "fdt" ./tools/dtoc/test_fdt -t +run_test "dtoc" ./tools/dtoc/dtoc -t # This needs you to set up Python test coverage tools. # To enable Python test coverage on Debian-type distributions (e.g. Ubuntu): # $ sudo apt-get install python-pytest python-coverage -PYTHONPATH=${DTC_DIR}/pylibfdt DTC=${DTC_DIR}/dtc run_test \ - ./tools/binman/binman -T -PYTHONPATH=${DTC_DIR}/pylibfdt DTC=${DTC_DIR}/dtc run_test \ - ./tools/dtoc/dtoc -T -PYTHONPATH=${DTC_DIR}/pylibfdt DTC=${DTC_DIR}/dtc run_test \ - ./tools/dtoc/test_fdt -T - -if [ $result == 0 ]; then +run_test "binman code coverage" ./tools/binman/binman -T +run_test "dtoc code coverage" ./tools/dtoc/dtoc -T +run_test "fdt code coverage" ./tools/dtoc/test_fdt -T + +if [ $failures == 0 ]; then echo "Tests passed!" else echo "Tests FAILED" diff --git a/tools/binman/binman.py b/tools/binman/binman.py index 1536e95..439908e 100755 --- a/tools/binman/binman.py +++ b/tools/binman/binman.py @@ -10,6 +10,7 @@ """See README for more information""" import glob +import multiprocessing import os import sys import traceback @@ -17,24 +18,32 @@ import unittest # Bring in the patman and dtoc libraries our_path = os.path.dirname(os.path.realpath(__file__)) -for dirname in ['../patman', '../dtoc', '..']: +for dirname in ['../patman', '../dtoc', '..', '../concurrencytest']: sys.path.insert(0, os.path.join(our_path, dirname)) # Bring in the libfdt module sys.path.insert(0, 'scripts/dtc/pylibfdt') +sys.path.insert(0, os.path.join(our_path, + '../../build-sandbox_spl/scripts/dtc/pylibfdt')) import cmdline import command +use_concurrent = True +try: + from concurrencytest import ConcurrentTestSuite, fork_for_tests +except: + use_concurrent = False import control import test_util -def RunTests(debug, args): +def RunTests(debug, processes, args): """Run the functional tests and any embedded doctests Args: debug: True to enable debugging, which shows a full stack trace on error args: List of positional args provided to binman. This can hold a test name to execute (as in 'binman -t testSections', for example) + processes: Number of processes to use to run tests (None=same as #CPUs) """ import elf_test import entry_test @@ -52,19 +61,28 @@ def RunTests(debug, args): sys.argv = [sys.argv[0]] if debug: sys.argv.append('-D') + if debug: + sys.argv.append('-D') # Run the entry tests first ,since these need to be the first to import the # 'entry' module. test_name = args and args[0] or None + suite = unittest.TestSuite() + loader = unittest.TestLoader() for module in (entry_test.TestEntry, ftest.TestFunctional, fdt_test.TestFdt, elf_test.TestElf, image_test.TestImage): if test_name: try: - suite = unittest.TestLoader().loadTestsFromName(test_name, module) + suite.addTests(loader.loadTestsFromName(test_name, module)) except AttributeError: continue else: - suite = unittest.TestLoader().loadTestsFromTestCase(module) + suite.addTests(loader.loadTestsFromTestCase(module)) + if use_concurrent and processes != 1: + concurrent_suite = ConcurrentTestSuite(suite, + fork_for_tests(processes or multiprocessing.cpu_count())) + concurrent_suite.run(result) + else: suite.run(result) print result @@ -113,7 +131,7 @@ def RunBinman(options, args): sys.tracebacklimit = 0 if options.test: - ret_code = RunTests(options.debug, args[1:]) + ret_code = RunTests(options.debug, options.processes, args[1:]) elif options.test_coverage: RunTestCoverage() diff --git a/tools/binman/cmdline.py b/tools/binman/cmdline.py index f8caa7d..3886d52 100644 --- a/tools/binman/cmdline.py +++ b/tools/binman/cmdline.py @@ -46,6 +46,8 @@ def ParseArgs(argv): parser.add_option('-p', '--preserve', action='store_true',\ help='Preserve temporary output directory even if option -O is not ' 'given') + parser.add_option('-P', '--processes', type=int, + help='set number of processes to use for running tests') parser.add_option('-t', '--test', action='store_true', default=False, help='run tests') parser.add_option('-T', '--test-coverage', action='store_true', diff --git a/tools/binman/elf_test.py b/tools/binman/elf_test.py index c16f714..b68530c 100644 --- a/tools/binman/elf_test.py +++ b/tools/binman/elf_test.py @@ -10,6 +10,7 @@ import unittest import elf import test_util +import tools binman_dir = os.path.dirname(os.path.realpath(sys.argv[0])) @@ -46,6 +47,10 @@ class FakeSection: class TestElf(unittest.TestCase): + @classmethod + def setUpClass(self): + tools.SetInputDirs(['.']) + def testAllSymbols(self): """Test that we can obtain a symbol from the ELF file""" fname = os.path.join(binman_dir, 'test', 'u_boot_ucode_ptr') diff --git a/tools/binman/entry_test.py b/tools/binman/entry_test.py index 69d85b4..1f7ff5b 100644 --- a/tools/binman/entry_test.py +++ b/tools/binman/entry_test.py @@ -13,12 +13,19 @@ import fdt import fdt_util import tools +entry = None + class TestEntry(unittest.TestCase): + def setUp(self): + tools.PrepareOutputDir(None) + + def tearDown(self): + tools.FinaliseOutputDir() + def GetNode(self): binman_dir = os.path.dirname(os.path.realpath(sys.argv[0])) - tools.PrepareOutputDir(None) fname = fdt_util.EnsureCompiled( - os.path.join(binman_dir,('test/05_simple.dts'))) + os.path.join(binman_dir,('test/005_simple.dts'))) dtb = fdt.FdtScan(fname) return dtb.GetNode('/binman/u-boot') @@ -33,9 +40,11 @@ class TestEntry(unittest.TestCase): def test2EntryImportLib(self): del sys.modules['importlib'] global entry - reload(entry) + if entry: + reload(entry) + else: + import entry entry.Entry.Create(None, self.GetNode(), 'u-boot-spl') - tools._RemoveOutputDir() del entry def testEntryContents(self): diff --git a/tools/binman/fdt_test.py b/tools/binman/fdt_test.py index 8ea098f..ac6f910 100644 --- a/tools/binman/fdt_test.py +++ b/tools/binman/fdt_test.py @@ -21,6 +21,10 @@ class TestFdt(unittest.TestCase): self._indir = tempfile.mkdtemp(prefix='binmant.') tools.PrepareOutputDir(self._indir, True) + @classmethod + def tearDownClass(self): + tools._FinaliseForTest() + def TestFile(self, fname): return os.path.join(self._binman_dir, 'test', fname) @@ -32,12 +36,12 @@ class TestFdt(unittest.TestCase): node.DeleteProp('data') def testFdtNormal(self): - fname = self.GetCompiled('34_x86_ucode.dts') + fname = self.GetCompiled('034_x86_ucode.dts') dt = FdtScan(fname) self._DeleteProp(dt) def testFdtNormalProp(self): - fname = self.GetCompiled('45_prop_test.dts') + fname = self.GetCompiled('045_prop_test.dts') dt = FdtScan(fname) node = dt.GetNode('/binman/intel-me') self.assertEquals('intel-me', node.name) diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py index 57725c9..167f56d 100644 --- a/tools/binman/ftest.py +++ b/tools/binman/ftest.py @@ -115,7 +115,6 @@ class TestFunctional(unittest.TestCase): TestFunctional._MakeInputFile('ecrw.bin', CROS_EC_RW_DATA) TestFunctional._MakeInputDir('devkeys') TestFunctional._MakeInputFile('bmpblk.bin', BMPBLK_DATA) - self._output_setup = False # ELF file with a '_dt_ucode_base_size' symbol with open(self.TestFile('u_boot_ucode_ptr')) as fd: @@ -190,7 +189,7 @@ class TestFunctional(unittest.TestCase): """Run binman with a given test file Args: - fname: Device-tree source filename to use (e.g. 05_simple.dts) + fname: Device-tree source filename to use (e.g. 005_simple.dts) debug: True to enable debugging output map: True to output map files for the images update_dtb: Update the offset and size of each entry in the device @@ -230,14 +229,13 @@ class TestFunctional(unittest.TestCase): Returns: Contents of device-tree binary """ - if not self._output_setup: - tools.PrepareOutputDir(self._indir, True) - self._output_setup = True + tools.PrepareOutputDir(None) dtb = fdt_util.EnsureCompiled(self.TestFile(fname)) with open(dtb) as fd: data = fd.read() TestFunctional._MakeInputFile(outfile, data) - return data + tools.FinaliseOutputDir() + return data def _GetDtbContentsForSplTpl(self, dtb_data, name): """Create a version of the main DTB for SPL or SPL @@ -268,7 +266,7 @@ class TestFunctional(unittest.TestCase): Raises an assertion failure if binman returns a non-zero exit code. Args: - fname: Device-tree source filename to use (e.g. 05_simple.dts) + fname: Device-tree source filename to use (e.g. 005_simple.dts) use_real_dtb: True to use the test file as the contents of the u-boot-dtb entry. Normally this is not needed and the test contents (the U_BOOT_DTB_DATA string) can be used. @@ -325,7 +323,7 @@ class TestFunctional(unittest.TestCase): """Helper function which discards the device-tree binary Args: - fname: Device-tree source filename to use (e.g. 05_simple.dts) + fname: Device-tree source filename to use (e.g. 005_simple.dts) use_real_dtb: True to use the test file as the contents of the u-boot-dtb entry. Normally this is not needed and the test contents (the U_BOOT_DTB_DATA string) can be used. @@ -370,6 +368,16 @@ class TestFunctional(unittest.TestCase): return pathname @classmethod + def _SetupSplElf(self, src_fname='bss_data'): + """Set up an ELF file with a '_dt_ucode_base_size' symbol + + Args: + Filename of ELF file to use as SPL + """ + with open(self.TestFile(src_fname)) as fd: + TestFunctional._MakeInputFile('spl/u-boot-spl', fd.read()) + + @classmethod def TestFile(self, fname): return os.path.join(self._binman_dir, 'test', fname) @@ -456,7 +464,7 @@ class TestFunctional(unittest.TestCase): def testBoard(self): """Test that we can run it with a specific board""" - self._SetupDtb('05_simple.dts', 'sandbox/u-boot.dtb') + self._SetupDtb('005_simple.dts', 'sandbox/u-boot.dtb') TestFunctional._MakeInputFile('sandbox/u-boot.bin', U_BOOT_DATA) result = self._DoBinman('-b', 'sandbox') self.assertEqual(0, result) @@ -483,19 +491,19 @@ class TestFunctional(unittest.TestCase): will come from the device-tree compiler (dtc). """ with self.assertRaises(Exception) as e: - self._RunBinman('-d', self.TestFile('01_invalid.dts')) + self._RunBinman('-d', self.TestFile('001_invalid.dts')) self.assertIn("FATAL ERROR: Unable to parse input tree", str(e.exception)) def testMissingNode(self): """Test that a device tree without a 'binman' node generates an error""" with self.assertRaises(Exception) as e: - self._DoBinman('-d', self.TestFile('02_missing_node.dts')) + self._DoBinman('-d', self.TestFile('002_missing_node.dts')) self.assertIn("does not have a 'binman' node", str(e.exception)) def testEmpty(self): """Test that an empty binman node works OK (i.e. does nothing)""" - result = self._RunBinman('-d', self.TestFile('03_empty.dts')) + result = self._RunBinman('-d', self.TestFile('003_empty.dts')) self.assertEqual(0, len(result.stderr)) self.assertEqual(0, result.return_code) @@ -503,25 +511,25 @@ class TestFunctional(unittest.TestCase): """Test that an invalid entry is flagged""" with self.assertRaises(Exception) as e: result = self._RunBinman('-d', - self.TestFile('04_invalid_entry.dts')) + self.TestFile('004_invalid_entry.dts')) self.assertIn("Unknown entry type 'not-a-valid-type' in node " "'/binman/not-a-valid-type'", str(e.exception)) def testSimple(self): """Test a simple binman with a single file""" - data = self._DoReadFile('05_simple.dts') + data = self._DoReadFile('005_simple.dts') self.assertEqual(U_BOOT_DATA, data) def testSimpleDebug(self): """Test a simple binman run with debugging enabled""" - data = self._DoTestFile('05_simple.dts', debug=True) + data = self._DoTestFile('005_simple.dts', debug=True) def testDual(self): """Test that we can handle creating two images This also tests image padding. """ - retcode = self._DoTestFile('06_dual_image.dts') + retcode = self._DoTestFile('006_dual_image.dts') self.assertEqual(0, retcode) image = control.images['image1'] @@ -545,13 +553,13 @@ class TestFunctional(unittest.TestCase): def testBadAlign(self): """Test that an invalid alignment value is detected""" with self.assertRaises(ValueError) as e: - self._DoTestFile('07_bad_align.dts') + self._DoTestFile('007_bad_align.dts') self.assertIn("Node '/binman/u-boot': Alignment 23 must be a power " "of two", str(e.exception)) def testPackSimple(self): """Test that packing works as expected""" - retcode = self._DoTestFile('08_pack.dts') + retcode = self._DoTestFile('008_pack.dts') self.assertEqual(0, retcode) self.assertIn('image', control.images) image = control.images['image'] @@ -593,7 +601,7 @@ class TestFunctional(unittest.TestCase): def testPackExtra(self): """Test that extra packing feature works as expected""" - retcode = self._DoTestFile('09_pack_extra.dts') + retcode = self._DoTestFile('009_pack_extra.dts') self.assertEqual(0, retcode) self.assertIn('image', control.images) @@ -638,35 +646,35 @@ class TestFunctional(unittest.TestCase): def testPackAlignPowerOf2(self): """Test that invalid entry alignment is detected""" with self.assertRaises(ValueError) as e: - self._DoTestFile('10_pack_align_power2.dts') + self._DoTestFile('010_pack_align_power2.dts') self.assertIn("Node '/binman/u-boot': Alignment 5 must be a power " "of two", str(e.exception)) def testPackAlignSizePowerOf2(self): """Test that invalid entry size alignment is detected""" with self.assertRaises(ValueError) as e: - self._DoTestFile('11_pack_align_size_power2.dts') + self._DoTestFile('011_pack_align_size_power2.dts') self.assertIn("Node '/binman/u-boot': Alignment size 55 must be a " "power of two", str(e.exception)) def testPackInvalidAlign(self): """Test detection of an offset that does not match its alignment""" with self.assertRaises(ValueError) as e: - self._DoTestFile('12_pack_inv_align.dts') + self._DoTestFile('012_pack_inv_align.dts') self.assertIn("Node '/binman/u-boot': Offset 0x5 (5) does not match " "align 0x4 (4)", str(e.exception)) def testPackInvalidSizeAlign(self): """Test that invalid entry size alignment is detected""" with self.assertRaises(ValueError) as e: - self._DoTestFile('13_pack_inv_size_align.dts') + self._DoTestFile('013_pack_inv_size_align.dts') self.assertIn("Node '/binman/u-boot': Size 0x5 (5) does not match " "align-size 0x4 (4)", str(e.exception)) def testPackOverlap(self): """Test that overlapping regions are detected""" with self.assertRaises(ValueError) as e: - self._DoTestFile('14_pack_overlap.dts') + self._DoTestFile('014_pack_overlap.dts') self.assertIn("Node '/binman/u-boot-align': Offset 0x3 (3) overlaps " "with previous entry '/binman/u-boot' ending at 0x4 (4)", str(e.exception)) @@ -674,20 +682,20 @@ class TestFunctional(unittest.TestCase): def testPackEntryOverflow(self): """Test that entries that overflow their size are detected""" with self.assertRaises(ValueError) as e: - self._DoTestFile('15_pack_overflow.dts') + self._DoTestFile('015_pack_overflow.dts') self.assertIn("Node '/binman/u-boot': Entry contents size is 0x4 (4) " "but entry size is 0x3 (3)", str(e.exception)) def testPackImageOverflow(self): """Test that entries which overflow the image size are detected""" with self.assertRaises(ValueError) as e: - self._DoTestFile('16_pack_image_overflow.dts') + self._DoTestFile('016_pack_image_overflow.dts') self.assertIn("Section '/binman': contents size 0x4 (4) exceeds section " "size 0x3 (3)", str(e.exception)) def testPackImageSize(self): """Test that the image size can be set""" - retcode = self._DoTestFile('17_pack_image_size.dts') + retcode = self._DoTestFile('017_pack_image_size.dts') self.assertEqual(0, retcode) self.assertIn('image', control.images) image = control.images['image'] @@ -695,7 +703,7 @@ class TestFunctional(unittest.TestCase): def testPackImageSizeAlign(self): """Test that image size alignemnt works as expected""" - retcode = self._DoTestFile('18_pack_image_align.dts') + retcode = self._DoTestFile('018_pack_image_align.dts') self.assertEqual(0, retcode) self.assertIn('image', control.images) image = control.images['image'] @@ -704,27 +712,26 @@ class TestFunctional(unittest.TestCase): def testPackInvalidImageAlign(self): """Test that invalid image alignment is detected""" with self.assertRaises(ValueError) as e: - self._DoTestFile('19_pack_inv_image_align.dts') + self._DoTestFile('019_pack_inv_image_align.dts') self.assertIn("Section '/binman': Size 0x7 (7) does not match " "align-size 0x8 (8)", str(e.exception)) def testPackAlignPowerOf2(self): """Test that invalid image alignment is detected""" with self.assertRaises(ValueError) as e: - self._DoTestFile('20_pack_inv_image_align_power2.dts') + self._DoTestFile('020_pack_inv_image_align_power2.dts') self.assertIn("Section '/binman': Alignment size 131 must be a power of " "two", str(e.exception)) def testImagePadByte(self): """Test that the image pad byte can be specified""" - with open(self.TestFile('bss_data')) as fd: - TestFunctional._MakeInputFile('spl/u-boot-spl', fd.read()) - data = self._DoReadFile('21_image_pad.dts') + self._SetupSplElf() + data = self._DoReadFile('021_image_pad.dts') self.assertEqual(U_BOOT_SPL_DATA + (chr(0xff) * 1) + U_BOOT_DATA, data) def testImageName(self): """Test that image files can be named""" - retcode = self._DoTestFile('22_image_name.dts') + retcode = self._DoTestFile('022_image_name.dts') self.assertEqual(0, retcode) image = control.images['image1'] fname = tools.GetOutputFilename('test-name') @@ -736,32 +743,33 @@ class TestFunctional(unittest.TestCase): def testBlobFilename(self): """Test that generic blobs can be provided by filename""" - data = self._DoReadFile('23_blob.dts') + data = self._DoReadFile('023_blob.dts') self.assertEqual(BLOB_DATA, data) def testPackSorted(self): """Test that entries can be sorted""" - data = self._DoReadFile('24_sorted.dts') + self._SetupSplElf() + data = self._DoReadFile('024_sorted.dts') self.assertEqual(chr(0) * 1 + U_BOOT_SPL_DATA + chr(0) * 2 + U_BOOT_DATA, data) def testPackZeroOffset(self): """Test that an entry at offset 0 is not given a new offset""" with self.assertRaises(ValueError) as e: - self._DoTestFile('25_pack_zero_size.dts') + self._DoTestFile('025_pack_zero_size.dts') self.assertIn("Node '/binman/u-boot-spl': Offset 0x0 (0) overlaps " "with previous entry '/binman/u-boot' ending at 0x4 (4)", str(e.exception)) def testPackUbootDtb(self): """Test that a device tree can be added to U-Boot""" - data = self._DoReadFile('26_pack_u_boot_dtb.dts') + data = self._DoReadFile('026_pack_u_boot_dtb.dts') self.assertEqual(U_BOOT_NODTB_DATA + U_BOOT_DTB_DATA, data) def testPackX86RomNoSize(self): """Test that the end-at-4gb property requires a size property""" with self.assertRaises(ValueError) as e: - self._DoTestFile('27_pack_4gb_no_size.dts') + self._DoTestFile('027_pack_4gb_no_size.dts') self.assertIn("Section '/binman': Section size must be provided when " "using end-at-4gb", str(e.exception)) @@ -776,14 +784,15 @@ class TestFunctional(unittest.TestCase): def testPackX86RomOutside(self): """Test that the end-at-4gb property checks for offset boundaries""" with self.assertRaises(ValueError) as e: - self._DoTestFile('28_pack_4gb_outside.dts') + self._DoTestFile('028_pack_4gb_outside.dts') self.assertIn("Node '/binman/u-boot': Offset 0x0 (0) is outside " "the section starting at 0xffffffe0 (4294967264)", str(e.exception)) def testPackX86Rom(self): """Test that a basic x86 ROM can be created""" - data = self._DoReadFile('29_x86-rom.dts') + self._SetupSplElf() + data = self._DoReadFile('029_x86-rom.dts') self.assertEqual(U_BOOT_DATA + chr(0) * 7 + U_BOOT_SPL_DATA + chr(0) * 2, data) @@ -791,31 +800,31 @@ class TestFunctional(unittest.TestCase): """Test that an invalid Intel descriptor entry is detected""" TestFunctional._MakeInputFile('descriptor.bin', '') with self.assertRaises(ValueError) as e: - self._DoTestFile('31_x86-rom-me.dts') + self._DoTestFile('031_x86-rom-me.dts') self.assertIn("Node '/binman/intel-descriptor': Cannot find FD " "signature", str(e.exception)) def testPackX86RomBadDesc(self): """Test that the Intel requires a descriptor entry""" with self.assertRaises(ValueError) as e: - self._DoTestFile('30_x86-rom-me-no-desc.dts') + self._DoTestFile('030_x86-rom-me-no-desc.dts') self.assertIn("Node '/binman/intel-me': No offset set with " "offset-unset: should another entry provide this correct " "offset?", str(e.exception)) def testPackX86RomMe(self): """Test that an x86 ROM with an ME region can be created""" - data = self._DoReadFile('31_x86-rom-me.dts') + data = self._DoReadFile('031_x86-rom-me.dts') self.assertEqual(ME_DATA, data[0x1000:0x1000 + len(ME_DATA)]) def testPackVga(self): """Test that an image with a VGA binary can be created""" - data = self._DoReadFile('32_intel-vga.dts') + data = self._DoReadFile('032_intel-vga.dts') self.assertEqual(VGA_DATA, data[:len(VGA_DATA)]) def testPackStart16(self): """Test that an image with an x86 start16 region can be created""" - data = self._DoReadFile('33_x86-start16.dts') + data = self._DoReadFile('033_x86-start16.dts') self.assertEqual(X86_START16_DATA, data[:len(X86_START16_DATA)]) def testPackPowerpcMpc85xxBootpgResetvec(self): @@ -884,7 +893,7 @@ class TestFunctional(unittest.TestCase): u-boot.dtb with the microcode removed the microcode """ - first, pos_and_size = self._RunMicrocodeTest('34_x86_ucode.dts', + first, pos_and_size = self._RunMicrocodeTest('034_x86_ucode.dts', U_BOOT_NODTB_DATA) self.assertEqual('nodtb with microcode' + pos_and_size + ' somewhere in here', first) @@ -901,7 +910,7 @@ class TestFunctional(unittest.TestCase): # We need the libfdt library to run this test since only that allows # finding the offset of a property. This is required by # Entry_u_boot_dtb_with_ucode.ObtainContents(). - data = self._DoReadFile('35_x86_single_ucode.dts', True) + data = self._DoReadFile('035_x86_single_ucode.dts', True) second = data[len(U_BOOT_NODTB_DATA):] @@ -928,27 +937,27 @@ class TestFunctional(unittest.TestCase): def testUBootImg(self): """Test that u-boot.img can be put in a file""" - data = self._DoReadFile('36_u_boot_img.dts') + data = self._DoReadFile('036_u_boot_img.dts') self.assertEqual(U_BOOT_IMG_DATA, data) def testNoMicrocode(self): """Test that a missing microcode region is detected""" with self.assertRaises(ValueError) as e: - self._DoReadFile('37_x86_no_ucode.dts', True) + self._DoReadFile('037_x86_no_ucode.dts', True) self.assertIn("Node '/binman/u-boot-dtb-with-ucode': No /microcode " "node found in ", str(e.exception)) def testMicrocodeWithoutNode(self): """Test that a missing u-boot-dtb-with-ucode node is detected""" with self.assertRaises(ValueError) as e: - self._DoReadFile('38_x86_ucode_missing_node.dts', True) + self._DoReadFile('038_x86_ucode_missing_node.dts', True) self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Cannot find " "microcode region u-boot-dtb-with-ucode", str(e.exception)) def testMicrocodeWithoutNode2(self): """Test that a missing u-boot-ucode node is detected""" with self.assertRaises(ValueError) as e: - self._DoReadFile('39_x86_ucode_missing_node2.dts', True) + self._DoReadFile('039_x86_ucode_missing_node2.dts', True) self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Cannot find " "microcode region u-boot-ucode", str(e.exception)) @@ -972,7 +981,7 @@ class TestFunctional(unittest.TestCase): def testMicrocodeNotInImage(self): """Test that microcode must be placed within the image""" with self.assertRaises(ValueError) as e: - self._DoReadFile('40_x86_ucode_not_in_image.dts', True) + self._DoReadFile('040_x86_ucode_not_in_image.dts', True) self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Microcode " "pointer _dt_ucode_base_size at fffffe14 is outside the " "section ranging from 00000000 to 0000002e", str(e.exception)) @@ -981,7 +990,7 @@ class TestFunctional(unittest.TestCase): """Test that we can cope with an image without microcode (e.g. qemu)""" with open(self.TestFile('u_boot_no_ucode_ptr')) as fd: TestFunctional._MakeInputFile('u-boot', fd.read()) - data, dtb, _, _ = self._DoReadFileDtb('44_x86_optional_ucode.dts', True) + data, dtb, _, _ = self._DoReadFileDtb('044_x86_optional_ucode.dts', True) # Now check the device tree has no microcode self.assertEqual(U_BOOT_NODTB_DATA, data[:len(U_BOOT_NODTB_DATA)]) @@ -997,43 +1006,43 @@ class TestFunctional(unittest.TestCase): def testUnknownPosSize(self): """Test that microcode must be placed within the image""" with self.assertRaises(ValueError) as e: - self._DoReadFile('41_unknown_pos_size.dts', True) + self._DoReadFile('041_unknown_pos_size.dts', True) self.assertIn("Section '/binman': Unable to set offset/size for unknown " "entry 'invalid-entry'", str(e.exception)) def testPackFsp(self): """Test that an image with a FSP binary can be created""" - data = self._DoReadFile('42_intel-fsp.dts') + data = self._DoReadFile('042_intel-fsp.dts') self.assertEqual(FSP_DATA, data[:len(FSP_DATA)]) def testPackCmc(self): """Test that an image with a CMC binary can be created""" - data = self._DoReadFile('43_intel-cmc.dts') + data = self._DoReadFile('043_intel-cmc.dts') self.assertEqual(CMC_DATA, data[:len(CMC_DATA)]) def testPackVbt(self): """Test that an image with a VBT binary can be created""" - data = self._DoReadFile('46_intel-vbt.dts') + data = self._DoReadFile('046_intel-vbt.dts') self.assertEqual(VBT_DATA, data[:len(VBT_DATA)]) def testSplBssPad(self): """Test that we can pad SPL's BSS with zeros""" # ELF file with a '__bss_size' symbol - with open(self.TestFile('bss_data')) as fd: - TestFunctional._MakeInputFile('spl/u-boot-spl', fd.read()) - data = self._DoReadFile('47_spl_bss_pad.dts') + self._SetupSplElf() + data = self._DoReadFile('047_spl_bss_pad.dts') self.assertEqual(U_BOOT_SPL_DATA + (chr(0) * 10) + U_BOOT_DATA, data) - with open(self.TestFile('u_boot_ucode_ptr')) as fd: - TestFunctional._MakeInputFile('spl/u-boot-spl', fd.read()) + def testSplBssPadMissing(self): + """Test that a missing symbol is detected""" + self._SetupSplElf('u_boot_ucode_ptr') with self.assertRaises(ValueError) as e: - data = self._DoReadFile('47_spl_bss_pad.dts') + self._DoReadFile('047_spl_bss_pad.dts') self.assertIn('Expected __bss_size symbol in spl/u-boot-spl', str(e.exception)) def testPackStart16Spl(self): """Test that an image with an x86 start16 SPL region can be created""" - data = self._DoReadFile('48_x86-start16-spl.dts') + data = self._DoReadFile('048_x86-start16-spl.dts') self.assertEqual(X86_START16_SPL_DATA, data[:len(X86_START16_SPL_DATA)]) def _PackUbootSplMicrocode(self, dts, ucode_second=False): @@ -1050,9 +1059,7 @@ class TestFunctional(unittest.TestCase): ucode_second: True if the microsecond entry is second instead of third """ - # ELF file with a '_dt_ucode_base_size' symbol - with open(self.TestFile('u_boot_ucode_ptr')) as fd: - TestFunctional._MakeInputFile('spl/u-boot-spl', fd.read()) + self._SetupSplElf('u_boot_ucode_ptr') first, pos_and_size = self._RunMicrocodeTest(dts, U_BOOT_SPL_NODTB_DATA, ucode_second=ucode_second) self.assertEqual('splnodtb with microc' + pos_and_size + @@ -1060,7 +1067,7 @@ class TestFunctional(unittest.TestCase): def testPackUbootSplMicrocode(self): """Test that x86 microcode can be handled correctly in SPL""" - self._PackUbootSplMicrocode('49_x86_ucode_spl.dts') + self._PackUbootSplMicrocode('049_x86_ucode_spl.dts') def testPackUbootSplMicrocodeReorder(self): """Test that order doesn't matter for microcode entries @@ -1069,22 +1076,22 @@ class TestFunctional(unittest.TestCase): u-boot-ucode entry we have not yet seen the u-boot-dtb-with-ucode entry, so we reply on binman to try later. """ - self._PackUbootSplMicrocode('58_x86_ucode_spl_needs_retry.dts', + self._PackUbootSplMicrocode('058_x86_ucode_spl_needs_retry.dts', ucode_second=True) def testPackMrc(self): """Test that an image with an MRC binary can be created""" - data = self._DoReadFile('50_intel_mrc.dts') + data = self._DoReadFile('050_intel_mrc.dts') self.assertEqual(MRC_DATA, data[:len(MRC_DATA)]) def testSplDtb(self): """Test that an image with spl/u-boot-spl.dtb can be created""" - data = self._DoReadFile('51_u_boot_spl_dtb.dts') + data = self._DoReadFile('051_u_boot_spl_dtb.dts') self.assertEqual(U_BOOT_SPL_DTB_DATA, data[:len(U_BOOT_SPL_DTB_DATA)]) def testSplNoDtb(self): """Test that an image with spl/u-boot-spl-nodtb.bin can be created""" - data = self._DoReadFile('52_u_boot_spl_nodtb.dts') + data = self._DoReadFile('052_u_boot_spl_nodtb.dts') self.assertEqual(U_BOOT_SPL_NODTB_DATA, data[:len(U_BOOT_SPL_NODTB_DATA)]) def testSymbols(self): @@ -1094,9 +1101,8 @@ class TestFunctional(unittest.TestCase): addr = elf.GetSymbolAddress(elf_fname, '__image_copy_start') self.assertEqual(syms['_binman_u_boot_spl_prop_offset'].address, addr) - with open(self.TestFile('u_boot_binman_syms')) as fd: - TestFunctional._MakeInputFile('spl/u-boot-spl', fd.read()) - data = self._DoReadFile('53_symbols.dts') + self._SetupSplElf('u_boot_binman_syms') + data = self._DoReadFile('053_symbols.dts') sym_values = struct.pack('I', val); - self.value = val + self.value = self.bytes self.type = TYPE_INT self.dirty = True diff --git a/tools/dtoc/test_dtoc.py b/tools/dtoc/test_dtoc.py index 72bcb37..11bead1 100644 --- a/tools/dtoc/test_dtoc.py +++ b/tools/dtoc/test_dtoc.py @@ -385,7 +385,8 @@ U_BOOT_DEVICE(phandle_source2) = { def test_phandle_bad(self): """Test a node containing an invalid phandle fails""" - dtb_file = get_dtb_file('dtoc_test_phandle_bad.dts') + dtb_file = get_dtb_file('dtoc_test_phandle_bad.dts', + capture_stderr=True) output = tools.GetOutputFilename('output') with self.assertRaises(ValueError) as e: dtb_platdata.run_steps(['struct'], dtb_file, False, output) @@ -394,7 +395,8 @@ U_BOOT_DEVICE(phandle_source2) = { def test_phandle_bad2(self): """Test a phandle target missing its #*-cells property""" - dtb_file = get_dtb_file('dtoc_test_phandle_bad2.dts') + dtb_file = get_dtb_file('dtoc_test_phandle_bad2.dts', + capture_stderr=True) output = tools.GetOutputFilename('output') with self.assertRaises(ValueError) as e: dtb_platdata.run_steps(['struct'], dtb_file, False, output) diff --git a/tools/dtoc/test_fdt.py b/tools/dtoc/test_fdt.py index d259702..8d70dd2 100755 --- a/tools/dtoc/test_fdt.py +++ b/tools/dtoc/test_fdt.py @@ -60,7 +60,7 @@ class TestFdt(unittest.TestCase): @classmethod def tearDownClass(cls): - tools._FinaliseForTest() + tools.FinaliseOutputDir() def setUp(self): self.dtb = fdt.FdtScan('tools/dtoc/dtoc_test_simple.dts') @@ -128,7 +128,7 @@ class TestNode(unittest.TestCase): @classmethod def tearDownClass(cls): - tools._FinaliseForTest() + tools.FinaliseOutputDir() def setUp(self): self.dtb = fdt.FdtScan('tools/dtoc/dtoc_test_simple.dts') @@ -209,7 +209,7 @@ class TestProp(unittest.TestCase): @classmethod def tearDownClass(cls): - tools._FinaliseForTest() + tools.FinaliseOutputDir() def setUp(self): self.dtb = fdt.FdtScan('tools/dtoc/dtoc_test_simple.dts') @@ -427,6 +427,10 @@ class TestFdtUtil(unittest.TestCase): def setUpClass(cls): tools.PrepareOutputDir(None) + @classmethod + def tearDownClass(cls): + tools.FinaliseOutputDir() + def setUp(self): self.dtb = fdt.FdtScan('tools/dtoc/dtoc_test_simple.dts') self.node = self.dtb.GetNode('/spl-test') @@ -543,6 +547,8 @@ if __name__ != '__main__': parser = OptionParser() parser.add_option('-B', '--build-dir', type='string', default='b', help='Directory containing the build output') +parser.add_option('-P', '--processes', type=int, + help='set number of processes to use for running tests') parser.add_option('-t', '--test', action='store_true', dest='test', default=False, help='run tests') parser.add_option('-T', '--test-coverage', action='store_true', diff --git a/tools/patman/settings.py b/tools/patman/settings.py index ca43344..ea2bc74 100644 --- a/tools/patman/settings.py +++ b/tools/patman/settings.py @@ -58,25 +58,25 @@ class _ProjectConfigParser(ConfigParser.SafeConfigParser): >>> config = _ProjectConfigParser("zzz") >>> config.readfp(StringIO(sample_config)) >>> config.get("alias", "enemies") - 'Evil ' + u'Evil ' # Check to make sure that alias gets overridden by project. >>> config = _ProjectConfigParser("sm") >>> config.readfp(StringIO(sample_config)) >>> config.get("alias", "enemies") - 'Green G. ' + u'Green G. ' # Check to make sure that settings get merged with project. >>> config = _ProjectConfigParser("linux") >>> config.readfp(StringIO(sample_config)) >>> sorted(config.items("settings")) - [('am_hero', 'True'), ('process_tags', 'False')] + [(u'am_hero', u'True'), (u'process_tags', u'False')] # Check to make sure that settings works with unknown project. >>> config = _ProjectConfigParser("unknown") >>> config.readfp(StringIO(sample_config)) >>> sorted(config.items("settings")) - [('am_hero', 'True')] + [(u'am_hero', u'True')] """ def __init__(self, project_name): """Construct _ProjectConfigParser. @@ -99,6 +99,17 @@ class _ProjectConfigParser(ConfigParser.SafeConfigParser): for setting_name, setting_value in project_defaults.items(): self.set(project_settings, setting_name, setting_value) + def _to_unicode(self, val): + """Make sure a value is of type 'unicode' + + Args: + val: string or unicode object + + Returns: + unicode version of val + """ + return val if isinstance(val, unicode) else val.decode('utf-8') + def get(self, section, option, *args, **kwargs): """Extend SafeConfigParser to try project_section before section. @@ -108,14 +119,15 @@ class _ProjectConfigParser(ConfigParser.SafeConfigParser): See SafeConfigParser. """ try: - return ConfigParser.SafeConfigParser.get( + val = ConfigParser.SafeConfigParser.get( self, "%s_%s" % (self._project_name, section), option, *args, **kwargs ) except (ConfigParser.NoSectionError, ConfigParser.NoOptionError): - return ConfigParser.SafeConfigParser.get( + val = ConfigParser.SafeConfigParser.get( self, section, option, *args, **kwargs ) + return self._to_unicode(val) def items(self, section, *args, **kwargs): """Extend SafeConfigParser to add project_section to section. @@ -150,7 +162,8 @@ class _ProjectConfigParser(ConfigParser.SafeConfigParser): item_dict = dict(top_items) item_dict.update(project_items) - return item_dict.items() + return {(self._to_unicode(item), self._to_unicode(val)) + for item, val in item_dict.iteritems()} def ReadGitAliases(fname): """Read a git alias file. This is in the form used by git: diff --git a/tools/patman/test_util.py b/tools/patman/test_util.py index 0e79af8..687d407 100644 --- a/tools/patman/test_util.py +++ b/tools/patman/test_util.py @@ -43,7 +43,7 @@ def RunTestCoverage(prog, filter_fname, exclude_list, build_dir, required=None): glob_list += exclude_list glob_list += ['*libfdt.py', '*site-packages*'] cmd = ('PYTHONPATH=$PYTHONPATH:%s/sandbox_spl/tools python-coverage run ' - '--omit "%s" %s -t' % (build_dir, ','.join(glob_list), prog)) + '--omit "%s" %s -P1 -t' % (build_dir, ','.join(glob_list), prog)) os.system(cmd) stdout = command.Output('python-coverage', 'report') lines = stdout.splitlines() diff --git a/tools/patman/tools.py b/tools/patman/tools.py index 1c9bf4e..bf09979 100644 --- a/tools/patman/tools.py +++ b/tools/patman/tools.py @@ -28,6 +28,9 @@ packages = { 'lz4': 'liblz4-tool', } +# List of paths to use when looking for an input file +indir = [] + def PrepareOutputDir(dirname, preserve=False): """Select an output directory, ensuring it exists. diff --git a/tools/patman/tout.py b/tools/patman/tout.py index 4cd49e1..4957c7a 100644 --- a/tools/patman/tout.py +++ b/tools/patman/tout.py @@ -15,6 +15,8 @@ NOTICE = 2 INFO = 3 DEBUG = 4 +in_progress = False + """ This class handles output of progress and other useful information to the user. It provides for simple verbosity level control and can @@ -48,9 +50,11 @@ def UserIsPresent(): def ClearProgress(): """Clear any active progress message on the terminal.""" - if verbose > 0 and stdout_is_tty: + global in_progress + if verbose > 0 and stdout_is_tty and in_progress: _stdout.write('\r%s\r' % (" " * len (_progress))) _stdout.flush() + in_progress = False def Progress(msg, warning=False, trailer='...'): """Display progress information. @@ -58,6 +62,7 @@ def Progress(msg, warning=False, trailer='...'): Args: msg: Message to display. warning: True if this is a warning.""" + global in_progress ClearProgress() if verbose > 0: _progress = msg + trailer @@ -65,6 +70,7 @@ def Progress(msg, warning=False, trailer='...'): col = _color.YELLOW if warning else _color.GREEN _stdout.write('\r' + _color.Color(col, _progress)) _stdout.flush() + in_progress = True else: _stdout.write(_progress + '\n')