diff options
author | Rong Chang <rongchang@chromium.org> | 2015-03-23 20:12:56 +0800 |
---|---|---|
committer | ChromeOS Commit Bot <chromeos-commit-bot@chromium.org> | 2015-05-27 05:04:14 +0000 |
commit | 552c17543fb1e85e2143025a2dc9fdd560da5abb (patch) | |
tree | 53f41adc588d00d0adfb6d2b4ff60533a3b119b7 | |
parent | 937cc8a64e5971def21303e7a19a4ad9553e0ace (diff) | |
download | chrome-ec-552c17543fb1e85e2143025a2dc9fdd560da5abb.tar.gz |
oak: add initial support for oak board rev1
Add initial support for Oak rev1 board. This is just the
EC and includes battery charging but does not include
USB PD.
BUG=none
BRANCH=none
TEST=load on oak board and get console
Signed-off-by: Rong Chang <rongchang@chromium.org>
Signed-off-by: Alec Berg <alecaberg@chromium.org>
Change-Id: I626f3921025fbc39ba22b04eeb6dd1084cd70777
Reviewed-on: https://chromium-review.googlesource.com/261678
-rw-r--r-- | board/llama/gpio.inc | 1 | ||||
-rw-r--r-- | board/oak/battery.c | 61 | ||||
-rw-r--r-- | board/oak/board.c | 141 | ||||
-rw-r--r-- | board/oak/board.h | 107 | ||||
-rw-r--r-- | board/oak/build.mk | 13 | ||||
-rw-r--r-- | board/oak/ec.tasklist | 26 | ||||
-rw-r--r-- | board/oak/extpower.c | 51 | ||||
-rw-r--r-- | board/oak/gpio.inc | 86 | ||||
-rw-r--r-- | board/oak/led.c | 137 | ||||
-rw-r--r-- | board/samus/board.c | 10 | ||||
-rw-r--r-- | board/samus/board.h | 3 | ||||
-rw-r--r-- | chip/stm32/config-stm32f09x.h | 20 | ||||
-rw-r--r-- | chip/stm32/config_chip.h | 3 | ||||
-rw-r--r-- | common/system.c | 4 | ||||
-rw-r--r-- | driver/build.mk | 1 | ||||
-rw-r--r-- | driver/pi3usb30532.h | 78 | ||||
-rw-r--r-- | driver/usb_switch_pi3usb30532.c | 85 | ||||
-rw-r--r-- | power/mediatek.c | 96 |
18 files changed, 876 insertions, 47 deletions
diff --git a/board/llama/gpio.inc b/board/llama/gpio.inc index 253780ab9a..7b44460eab 100644 --- a/board/llama/gpio.inc +++ b/board/llama/gpio.inc @@ -65,6 +65,7 @@ GPIO(MASTER_I2C_SDA, PIN(B, 7), GPIO_INPUT) UNIMPLEMENTED(WP_L) UNIMPLEMENTED(BOARD_VERSION2) UNIMPLEMENTED(BOARD_VERSION3) +UNIMPLEMENTED(5V_POWER_GOOD) ALTERNATE(PIN_MASK(A, 0x0600), 1, MODULE_UART, 0) /* USART1: PA9/PA10 */ ALTERNATE(PIN_MASK(B, 0x00c0), 1, MODULE_I2C, 0) /* I2C MASTER:PB6/7 */ diff --git a/board/oak/battery.c b/board/oak/battery.c new file mode 100644 index 0000000000..2b92619557 --- /dev/null +++ b/board/oak/battery.c @@ -0,0 +1,61 @@ +/* Copyright 2015 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. + * + * Battery pack vendor provided charging profile + */ + +#include "battery.h" +#include "battery_smart.h" +#include "i2c.h" +#include "util.h" + +/* Shutdown mode parameter to write to manufacturer access register */ +#define PARAM_CUT_OFF_LOW 0x10 +#define PARAM_CUT_OFF_HIGH 0x00 + +static const struct battery_info info = { + .voltage_max = 8700, + .voltage_normal = 7600, + .voltage_min = 6000, + + /* Pre-charge values. */ + .precharge_current = 256, /* mA */ + + .start_charging_min_c = 0, + .start_charging_max_c = 45, + .charging_min_c = 0, + .charging_max_c = 45, + .discharging_min_c = -10, + .discharging_max_c = 60, +}; + +const struct battery_info *battery_get_info(void) +{ + return &info; +} + +static int cutoff(void) +{ + int rv; + uint8_t buf[3]; + + /* Ship mode command must be sent twice to take effect */ + buf[0] = SB_MANUFACTURER_ACCESS & 0xff; + buf[1] = PARAM_CUT_OFF_LOW; + buf[2] = PARAM_CUT_OFF_HIGH; + + i2c_lock(I2C_PORT_BATTERY, 1); + rv = i2c_xfer(I2C_PORT_BATTERY, BATTERY_ADDR, buf, 3, NULL, 0, + I2C_XFER_SINGLE); + rv |= i2c_xfer(I2C_PORT_BATTERY, BATTERY_ADDR, buf, 3, NULL, 0, + I2C_XFER_SINGLE); + i2c_lock(I2C_PORT_BATTERY, 0); + + return rv; +} + +int board_cut_off_battery(void) +{ + return cutoff(); +} diff --git a/board/oak/board.c b/board/oak/board.c new file mode 100644 index 0000000000..abbc1add0c --- /dev/null +++ b/board/oak/board.c @@ -0,0 +1,141 @@ +/* Copyright 2015 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. + */ + +/* Oak board configuration */ + +#include "battery.h" +#include "charger.h" +#include "chipset.h" +#include "common.h" +#include "console.h" +#include "extpower.h" +#include "gpio.h" +#include "hooks.h" +#include "host_command.h" +#include "i2c.h" +#include "keyboard_raw.h" +#include "lid_switch.h" +#include "power.h" +#include "power_button.h" +#include "registers.h" +#include "spi.h" +#include "switch.h" +#include "task.h" +#include "timer.h" +#include "util.h" + +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ## args) + +#define GPIO_KB_INPUT (GPIO_INPUT | GPIO_PULL_UP | GPIO_INT_BOTH) +#define GPIO_KB_OUTPUT GPIO_ODR_HIGH + +static void ap_reset_deferred(void) +{ + /* Warm reset AP */ + chipset_reset(0); +} +DECLARE_DEFERRED(ap_reset_deferred); + +void ap_reset_interrupt(enum gpio_signal signal) +{ + if (gpio_get_level(GPIO_AP_RESET_L) == 0) + hook_call_deferred(ap_reset_deferred, 0); +} + +void vbus_wake_interrupt(enum gpio_signal signal) +{ + CPRINTF("VBUS %d\n", gpio_get_level(signal)); +} + +void pd_mcu_interrupt(enum gpio_signal signal) +{ + CPRINTF("PD INT\n"); +} + +#include "gpio_list.h" + +/* power signal list. Must match order of enum power_signal. */ +const struct power_signal_info power_signal_list[] = { + {GPIO_SOC_POWER_GOOD, 1, "POWER_GOOD"}, /* Active high */ + {GPIO_SUSPEND_L, 0, "SUSPEND#_ASSERTED"}, /* Active low */ +}; + +BUILD_ASSERT(ARRAY_SIZE(power_signal_list) == POWER_SIGNAL_COUNT); + +/* I2C ports */ +const struct i2c_port_t i2c_ports[] = { + {"battery", I2C_PORT_BATTERY, 100, GPIO_I2C0_SCL, GPIO_I2C0_SDA}, + {"pd", I2C_PORT_PD_MCU, 1000, GPIO_I2C1_SCL, GPIO_I2C1_SDA} +}; + +const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); + +static int discharging_on_ac; + +/** + * Discharge battery when on AC power for factory test. + */ +int board_discharge_on_ac(int enable) +{ + int rv = charger_discharge_on_ac(enable); + + if (rv == EC_SUCCESS) + discharging_on_ac = enable; + + return rv; +} + +/** + * Reset PD MCU + */ +void board_reset_pd_mcu(void) +{ + gpio_set_level(GPIO_USB_PD_RST_L, 0); + usleep(100); + gpio_set_level(GPIO_USB_PD_RST_L, 1); +} + +void __board_i2c_set_timeout(int port, uint32_t timeout) +{ +} + +void i2c_set_timeout(int port, uint32_t timeout) + __attribute__((weak, alias("__board_i2c_set_timeout"))); + +/* Initialize board. */ +static void board_init(void) +{ + /* Enable rev1 testing GPIOs */ + gpio_set_level(GPIO_SYSTEM_POWER_H, 1); + /* Enable PD MCU interrupt */ + gpio_enable_interrupt(GPIO_PD_MCU_INT); + /* Enable VBUS interrupt */ + gpio_enable_interrupt(GPIO_VBUS_WAKE_L); +#ifdef CONFIG_AP_WARM_RESET_INTERRUPT + gpio_enable_interrupt(GPIO_AP_RESET_L); +#endif +} +DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); + +#ifndef CONFIG_AP_WARM_RESET_INTERRUPT +/* Using this hook if system doesn't have enough external line. */ +static void check_ap_reset_second(void) +{ + /* Check the warm reset signal from servo board */ + static int warm_reset, last; + + warm_reset = !gpio_get_level(GPIO_AP_RESET_L); + + if (last == warm_reset) + return; + + if (warm_reset) + chipset_reset(0); /* Warm reset AP */ + + last = warm_reset; +} +DECLARE_HOOK(HOOK_SECOND, check_ap_reset_second, HOOK_PRIO_DEFAULT); +#endif diff --git a/board/oak/board.h b/board/oak/board.h new file mode 100644 index 0000000000..90d88653c0 --- /dev/null +++ b/board/oak/board.h @@ -0,0 +1,107 @@ +/* Copyright 2015 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. + */ + +/* oak board configuration */ + +#ifndef __BOARD_H +#define __BOARD_H + +/* Add for AC adaptor, charger, battery */ +#define CONFIG_BATTERY_CUT_OFF +#define CONFIG_BATTERY_SMART +#define CONFIG_CHARGER +#define CONFIG_CHARGER_BQ24773 +#define CONFIG_CHARGER_DISCHARGE_ON_AC +#define CONFIG_CHARGER_INPUT_CURRENT 2150 +#define CONFIG_CHARGER_SENSE_RESISTOR 10 +#define CONFIG_CHARGER_SENSE_RESISTOR_AC 10 +#define CONFIG_CHARGER_V2 +#define CONFIG_CHIPSET_MEDIATEK +#define CONFIG_FORCE_CONSOLE_RESUME +#undef CONFIG_HIBERNATE +#define CONFIG_HOST_COMMAND_STATUS +#define CONFIG_I2C +#define CONFIG_KEYBOARD_COL2_INVERTED +#define CONFIG_KEYBOARD_PROTOCOL_MKBP +#define CONFIG_LED_COMMON +#define CONFIG_LOW_POWER_IDLE +#define CONFIG_FORCE_CONSOLE_RESUME +#define CONFIG_PMIC_FW_LONG_PRESS_TIMER +#define CONFIG_POWER_BUTTON +#define CONFIG_POWER_COMMON +#define CONFIG_SPI +#define CONFIG_STM_HWTIMER32 +#define CONFIG_VBOOT_HASH +#undef CONFIG_WATCHDOG_HELP +#define CONFIG_LID_SWITCH +#define CONFIG_SWITCH +#define CONFIG_BOARD_VERSION +#undef CONFIG_UART_CONSOLE +#define CONFIG_UART_CONSOLE 1 + +/* UART DMA */ +#undef CONFIG_UART_TX_DMA +#undef CONFIG_UART_RX_DMA + +/* + * Allow dangerous commands. + * TODO: Remove this config before production. + */ +#define CONFIG_SYSTEM_UNLOCKED + +/* Optional features */ +#define CONFIG_CMD_HOSTCMD + +/* Drivers */ +#define CONFIG_USB_SWITCH_PI3USB30532 +/* + * 8-bit USB type-C switch I2C addresses: + * port 0: 0x54 << 1 + * port 1: 0x55 << 1 + */ +#define CONFIG_USB_SWITCH_I2C_ADDRS {0x54 << 1, 0x55 << 1} + +#ifndef __ASSEMBLER__ + +/* 48 MHz SYSCLK clock frequency */ +#define CPU_CLOCK 48000000 + +/* Keyboard output port list */ +#define KB_OUT_PORT_LIST GPIO_A, GPIO_B, GPIO_C, GPIO_D + +/* 2 I2C master ports, connect to battery, charger, pd and USB switches */ +#define I2C_PORT_BATTERY 0 +#define I2C_PORT_CHARGER 0 +#define I2C_PORT_PD_MCU 1 +#define I2C_PORT_USB_SWITCH 1 + +/* Timer selection */ +#define TIM_CLOCK32 2 +#define TIM_WATCHDOG 4 + +#include "gpio_signal.h" + +enum power_signal { + MTK_POWER_GOOD = 0, + MTK_SUSPEND_ASSERTED, + /* Number of power signals */ + POWER_SIGNAL_COUNT +}; + +enum pwm_channel { + PWM_CH_POWER_LED = 0, + /* Number of PWM channels */ + PWM_CH_COUNT +}; + +/* Discharge battery when on AC power for factory test. */ +int board_discharge_on_ac(int enable); + +/* Reset PD MCU */ +void board_reset_pd_mcu(void); + +#endif /* !__ASSEMBLER__ */ + +#endif /* __BOARD_H */ diff --git a/board/oak/build.mk b/board/oak/build.mk new file mode 100644 index 0000000000..6beb2374ba --- /dev/null +++ b/board/oak/build.mk @@ -0,0 +1,13 @@ +#-*- makefile -*- +# Copyright 2015 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. +# +# Board specific files build + +# STmicro STM32F091VC +CHIP := stm32 +CHIP_FAMILY := stm32f0 +CHIP_VARIANT:= stm32f09x + +board-y = board.o battery.o extpower.o led.o diff --git a/board/oak/ec.tasklist b/board/oak/ec.tasklist new file mode 100644 index 0000000000..20cac3c317 --- /dev/null +++ b/board/oak/ec.tasklist @@ -0,0 +1,26 @@ +/* Copyright 2015 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. + */ + +/** + * List of enabled tasks in the priority order + * + * The first one has the lowest priority. + * + * For each task, use the macro TASK_ALWAYS(n, r, d, s) for base tasks and + * TASK_NOTEST(n, r, d, s) for tasks that can be excluded in test binaries, + * where : + * 'n' in the name of the task + * 'r' in the main routine of the task + * 'd' in an opaque parameter passed to the routine at startup + * 's' is the stack size in bytes; must be a multiple of 8 + */ +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CHARGER, charger_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_NOTEST(CHIPSET, chipset_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_NOTEST(PDCMD, pd_command_task, NULL, TASK_STACK_SIZE) \ + TASK_ALWAYS(HOSTCMD, host_command_task, NULL, TASK_STACK_SIZE) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, TASK_STACK_SIZE) \ + TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, TASK_STACK_SIZE) diff --git a/board/oak/extpower.c b/board/oak/extpower.c new file mode 100644 index 0000000000..c9efa4c0fa --- /dev/null +++ b/board/oak/extpower.c @@ -0,0 +1,51 @@ +/* Copyright 2015 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. + */ + +/* + * Pure GPIO-based external power detection, buffered to PCH. + * Drive high in S5-S0 when AC_PRESENT is high, otherwise drive low. + */ + +#include "chipset.h" +#include "common.h" +#include "gpio.h" +#include "hooks.h" +#include "system.h" +#include "util.h" + +int extpower_is_present(void) +{ + return gpio_get_level(GPIO_AC_PRESENT); +} + +static void extpower_buffer_to_soc(void) +{ + /* Drive high when AP is off */ + gpio_set_level(GPIO_LEVEL_SHIFT_EN_L, + chipset_in_state(CHIPSET_STATE_HARD_OFF) ? 1 : 0); +} +DECLARE_HOOK(HOOK_CHIPSET_PRE_INIT, extpower_buffer_to_soc, HOOK_PRIO_DEFAULT); + +static void extpower_shutdown(void) +{ + /* Disable level shift to SoC when shutting down */ + gpio_set_level(GPIO_LEVEL_SHIFT_EN_L, 1); +} +DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, extpower_shutdown, HOOK_PRIO_DEFAULT); + +void extpower_interrupt(enum gpio_signal signal) +{ + /* Trigger notification of external power change */ + extpower_buffer_to_soc(); +} + +static void extpower_init(void) +{ + extpower_buffer_to_soc(); + + /* Enable interrupts, now that we've initialized */ + gpio_enable_interrupt(GPIO_AC_PRESENT); +} +DECLARE_HOOK(HOOK_INIT, extpower_init, HOOK_PRIO_DEFAULT); diff --git a/board/oak/gpio.inc b/board/oak/gpio.inc new file mode 100644 index 0000000000..f8b822456c --- /dev/null +++ b/board/oak/gpio.inc @@ -0,0 +1,86 @@ +/* -*- mode:c -*- + * + * Copyright 2015 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. + */ + +/* Inputs with interrupt handlers are first for efficiency */ +GPIO_INT(AC_PRESENT, C, 6, GPIO_INT_BOTH, extpower_interrupt) +GPIO_INT(POWER_BUTTON_L, B, 5, GPIO_INT_BOTH | GPIO_PULL_UP, power_button_interrupt) +GPIO_INT(SOC_POWER_GOOD, A, 3, GPIO_INT_BOTH | GPIO_PULL_DOWN, power_signal_interrupt) +GPIO_INT(LID_OPEN, C, 13, GPIO_INT_BOTH, lid_interrupt) /* LID switch detection */ +GPIO_INT(SUSPEND_L, C, 7, GPIO_INT_BOTH, power_signal_interrupt) /* AP suspend/resume state */ +GPIO_INT(VBUS_WAKE_L, E, 1, GPIO_INT_BOTH, vbus_wake_interrupt) /* VBUS wake: PE 1 */ +GPIO_INT(PD_MCU_INT, E, 0, GPIO_INT_FALLING | GPIO_INT_DSLEEP,pd_mcu_interrupt) /* Interrupt from PD MCU, external pull-up */ +GPIO_INT(SPI1_NSS, A, 4, GPIO_INT_BOTH | GPIO_PULL_UP, spi_event) /* SPI Chip Select */ +GPIO_INT(AP_RESET_L, C, 3, GPIO_INT_BOTH | GPIO_PULL_UP, ap_reset_interrupt) /* AP reset signal from servo board */ + +/* Keyboard inputs */ +GPIO_INT(KB_IN00, C, 8, GPIO_KB_INPUT, keyboard_raw_gpio_interrupt) +GPIO_INT(KB_IN01, C, 9, GPIO_KB_INPUT, keyboard_raw_gpio_interrupt) +GPIO_INT(KB_IN02, C, 10, GPIO_KB_INPUT, keyboard_raw_gpio_interrupt) +GPIO_INT(KB_IN03, C, 11, GPIO_KB_INPUT, keyboard_raw_gpio_interrupt) +GPIO_INT(KB_IN04, C, 12, GPIO_KB_INPUT, keyboard_raw_gpio_interrupt) +GPIO_INT(KB_IN05, C, 14, GPIO_KB_INPUT, keyboard_raw_gpio_interrupt) +GPIO_INT(KB_IN06, C, 15, GPIO_KB_INPUT, keyboard_raw_gpio_interrupt) +GPIO_INT(KB_IN07, D, 2, GPIO_KB_INPUT, keyboard_raw_gpio_interrupt) + +/* Inputs without interrupt handlers */ +GPIO(5V_POWER_GOOD, A, 1, GPIO_INPUT) +GPIO(EC_WAKE, A, 0, GPIO_INPUT|GPIO_PULL_DOWN) +GPIO(WP_L, B, 4, GPIO_INPUT) /* Write protect input */ + +/* Board version */ +GPIO(BOARD_VERSION1, E, 10, GPIO_INPUT|GPIO_PULL_UP) /* Board ID 0 */ +GPIO(BOARD_VERSION2, E, 9, GPIO_INPUT|GPIO_PULL_UP) /* Board ID 1 */ +GPIO(BOARD_VERSION3, E, 12, GPIO_INPUT|GPIO_PULL_UP) /* Board ID 2 */ +GPIO(BOARD_VERSION4, E, 11, GPIO_INPUT|GPIO_PULL_UP) /* Board ID 3 */ + +/* Outputs */ +GPIO(BAT_LED0, B, 11, GPIO_OUT_LOW) /* LED_GREEN */ +GPIO(BAT_LED1, A, 11, GPIO_OUT_LOW) /* LED_ORANGE */ +GPIO(EC_BL_OVERRIDE, F, 1, GPIO_OUT_LOW) +GPIO(EC_INT, B, 9, GPIO_OUT_HIGH) +GPIO(ENTERING_RW, F, 0, GPIO_OUT_LOW) +GPIO(KB_OUT00, B, 0, GPIO_KB_OUTPUT) +GPIO(KB_OUT01, B, 8, GPIO_KB_OUTPUT) +GPIO(KB_OUT02, B, 12, GPIO_OUT_LOW) /* KSO2 is inverted */ +GPIO(KB_OUT03, B, 2, GPIO_KB_OUTPUT) +GPIO(KB_OUT04, A, 8, GPIO_KB_OUTPUT) +GPIO(KB_OUT05, D, 4, GPIO_KB_OUTPUT) +GPIO(KB_OUT06, D, 0, GPIO_KB_OUTPUT) +GPIO(KB_OUT07, D, 1, GPIO_KB_OUTPUT) +GPIO(KB_OUT08, C, 2, GPIO_KB_OUTPUT) +GPIO(KB_OUT09, B, 1, GPIO_KB_OUTPUT) +GPIO(KB_OUT10, C, 5, GPIO_KB_OUTPUT) +GPIO(KB_OUT11, C, 4, GPIO_KB_OUTPUT) +GPIO(KB_OUT12, A, 13, GPIO_KB_OUTPUT) +GPIO(SYSTEM_POWER_H, B, 10, GPIO_OUT_LOW) +GPIO(PMIC_PWRON_H, A, 12, GPIO_OUT_LOW) +GPIO(PMIC_WARM_RESET_H, B, 3, GPIO_OUT_LOW) +GPIO(LEVEL_SHIFT_EN_L, D, 3, GPIO_OUT_LOW) /* LID/AC level shift */ +GPIO(USB_PD_RST_L, A, 15, GPIO_OUT_HIGH) /* PD reset */ +GPIO(USB_C0_5V_OUT, D, 8, GPIO_OUT_LOW) /* USBC port 0 5V */ +GPIO(USB_C0_CHARGE_L, D, 9, GPIO_OUT_LOW) /* USBC port 0 charge */ +GPIO(USB_C1_5V_OUT, D, 10, GPIO_OUT_LOW) /* USBC port 1 5V */ +GPIO(USB_C1_CHARGE_L, D, 11, GPIO_OUT_HIGH) /* USBC port 1 charge */ +GPIO(USB_PD_VBUS_WAKE, B, 15, GPIO_OUT_LOW) /* PD VBUS wake */ +GPIO(USB_DP_HPD, F, 3, GPIO_OUT_LOW) + +/* + * I2C pins should be configured as inputs until I2C module is + * initialized. This will avoid driving the lines unintentionally. + */ +GPIO(I2C0_SCL, B, 6, GPIO_INPUT) /* EC I2C */ +GPIO(I2C0_SDA, B, 7, GPIO_INPUT) +GPIO(I2C1_SCL, B, 13, GPIO_INPUT) /* PD I2C */ +GPIO(I2C1_SDA, B, 14, GPIO_INPUT) + +/* Unimplemented signals which we need to emulate for now */ +UNIMPLEMENTED(NONE) + +ALTERNATE(A, 0x0600, 1, MODULE_UART, 0) /* USART1: PA9/PA10 */ +ALTERNATE(B, 0x00c0, 1, MODULE_I2C, 0) /* I2C MASTER:PB6/7 */ +ALTERNATE(B, 0x6000, 5, MODULE_I2C, 0) /* I2C MASTER:PB13/14 */ +ALTERNATE(A, 0x00f0, 0, MODULE_SPI, 0) /* SPI SLAVE:PA4/5/6/7 */ diff --git a/board/oak/led.c b/board/oak/led.c new file mode 100644 index 0000000000..7c11ff2155 --- /dev/null +++ b/board/oak/led.c @@ -0,0 +1,137 @@ +/* Copyright 2015 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. + * + * Battery LED and Power LED control for LLAMA Board. + */ + +#include "battery.h" +#include "charge_state.h" +#include "chipset.h" +#include "gpio.h" +#include "hooks.h" +#include "led_common.h" +#include "util.h" + +const enum ec_led_id supported_led_ids[] = { + EC_LED_ID_BATTERY_LED +}; + +const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); + +enum led_color { + LED_GREEN = 0, + LED_ORANGE, + LED_COLOR_COUNT /* Number of colors, not a color itself */ +}; + +static int bat_led_set(enum led_color color, int on) +{ + switch (color) { + case LED_GREEN: + gpio_set_level(GPIO_BAT_LED0, on ? 0 : 1); + break; + case LED_ORANGE: + gpio_set_level(GPIO_BAT_LED1, on ? 0 : 1); + break; + default: + return EC_ERROR_UNKNOWN; + } + return EC_SUCCESS; +} + +void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) +{ + /* Ignoring led_id as both leds support the same colors */ + brightness_range[EC_LED_COLOR_GREEN] = 1; + brightness_range[EC_LED_COLOR_YELLOW] = 1; +} + +int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) +{ + if (EC_LED_ID_BATTERY_LED == led_id) { + if (brightness[EC_LED_COLOR_GREEN] != 0) { + bat_led_set(LED_GREEN, 1); + bat_led_set(LED_ORANGE, 0); + } else if (brightness[EC_LED_COLOR_YELLOW] != 0) { + bat_led_set(LED_GREEN, 1); + bat_led_set(LED_ORANGE, 1); + } else { + bat_led_set(LED_GREEN, 0); + bat_led_set(LED_ORANGE, 0); + } + return EC_SUCCESS; + } else { + return EC_ERROR_UNKNOWN; + } +} + +static void oak_led_set_power(void) +{ + static int power_second; + + power_second++; + + /* PWR LED behavior: + * Power on: Green + * Suspend: Green in breeze mode ( 1 sec on/ 3 sec off) + * Power off: OFF + */ + if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) + bat_led_set(LED_GREEN, 0); + else if (chipset_in_state(CHIPSET_STATE_ON)) + bat_led_set(LED_GREEN, 1); + else if (chipset_in_state(CHIPSET_STATE_SUSPEND)) + bat_led_set(LED_GREEN, (power_second & 3) ? 0 : 1); +} + +static void oak_led_set_battery(void) +{ + static int battery_second; + + battery_second++; + + /* BAT LED behavior: + * Fully charged / idle: Off + * Under charging: Orange + * Battery low (10%): Orange in breeze mode (1 sec on, 3 sec off) + * Battery critical low (less than 3%) or abnormal battery + * situation: Orange in blinking mode (1 sec on, 1 sec off) + * Using battery or not connected to AC power: OFF + */ + switch (charge_get_state()) { + case PWR_STATE_CHARGE: + bat_led_set(LED_ORANGE, 1); + break; + case PWR_STATE_CHARGE_NEAR_FULL: + bat_led_set(LED_ORANGE, 1); + break; + case PWR_STATE_DISCHARGE: + if (charge_get_percent() < 3) + bat_led_set(LED_ORANGE, (battery_second & 1) ? 0 : 1); + else if (charge_get_percent() < 10) + bat_led_set(LED_ORANGE, (battery_second & 3) ? 0 : 1); + else + bat_led_set(LED_ORANGE, 0); + break; + case PWR_STATE_ERROR: + bat_led_set(LED_ORANGE, (battery_second & 1) ? 0 : 1); + break; + case PWR_STATE_IDLE: /* External power connected in IDLE. */ + bat_led_set(LED_ORANGE, 0); + break; + default: + /* Other states don't alter LED behavior */ + break; + } +} + +/** * Called by hook task every 1 sec */ +static void led_second(void) +{ + if (led_auto_control_is_enabled(EC_LED_ID_POWER_LED)) + oak_led_set_power(); + if (led_auto_control_is_enabled(EC_LED_ID_BATTERY_LED)) + oak_led_set_battery(); +} +DECLARE_HOOK(HOOK_SECOND, led_second, HOOK_PRIO_DEFAULT); diff --git a/board/samus/board.c b/board/samus/board.c index 909ba7eca3..2272f1acfe 100644 --- a/board/samus/board.c +++ b/board/samus/board.c @@ -252,6 +252,16 @@ int board_is_discharging_on_ac(void) return discharging_on_ac; } +/** + * Reset PD MCU + */ +void board_reset_pd_mcu(void) +{ + gpio_set_level(GPIO_USB_MCU_RST, 1); + usleep(100); + gpio_set_level(GPIO_USB_MCU_RST, 0); +} + /* Base Sensor mutex */ static struct mutex g_base_mutex; diff --git a/board/samus/board.h b/board/samus/board.h index 30af544baf..8d78c03cef 100644 --- a/board/samus/board.h +++ b/board/samus/board.h @@ -183,6 +183,9 @@ enum als_id { int board_discharge_on_ac(int enable); int board_is_discharging_on_ac(void); +/* Reset PD MCU */ +void board_reset_pd_mcu(void); + /* Backboost detected interrupt */ void bkboost_det_interrupt(enum gpio_signal signal); diff --git a/chip/stm32/config-stm32f09x.h b/chip/stm32/config-stm32f09x.h new file mode 100644 index 0000000000..fe73db195f --- /dev/null +++ b/chip/stm32/config-stm32f09x.h @@ -0,0 +1,20 @@ +/* Copyright 2015 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. + */ + +/* Memory mapping */ +#define CONFIG_FLASH_BASE 0x08000000 +#define CONFIG_FLASH_PHYSICAL_SIZE 0x00040000 +#define CONFIG_FLASH_BANK_SIZE 0x2000 +#define CONFIG_FLASH_ERASE_SIZE 0x0800 /* erase bank size */ +#define CONFIG_FLASH_WRITE_SIZE 0x0002 /* minimum write size */ + +/* No page mode on STM32F, so no benefit to larger write sizes */ +#define CONFIG_FLASH_WRITE_IDEAL_SIZE 0x0002 + +#define CONFIG_RAM_BASE 0x20000000 +#define CONFIG_RAM_SIZE 0x00008000 + +/* Number of IRQ vectors on the NVIC */ +#define CONFIG_IRQ_COUNT 32 diff --git a/chip/stm32/config_chip.h b/chip/stm32/config_chip.h index 2454b216ed..88c080dc59 100644 --- a/chip/stm32/config_chip.h +++ b/chip/stm32/config_chip.h @@ -30,6 +30,9 @@ #elif defined(CHIP_VARIANT_STM32F10X) /* STM32F101xx, STM32F102xx, STM32F103xx, STM32F105xx, and STM32F107xx */ #include "config-stm32f10x.h" +#elif defined(CHIP_VARIANT_STM32F09X) +/* STM32F09xx */ +#include "config-stm32f09x.h" #elif defined(CHIP_VARIANT_STM32F07X) /* STM32F07xx */ #include "config-stm32f07x.h" diff --git a/common/system.c b/common/system.c index a144935c4b..803784d6cd 100644 --- a/common/system.c +++ b/common/system.c @@ -668,9 +668,7 @@ static int handle_pending_reboot(enum ec_reboot_cmd cmd) case EC_REBOOT_COLD: #ifdef HAS_TASK_PDCMD /* Reboot the PD chip as well */ - gpio_set_level(GPIO_USB_MCU_RST, 1); - usleep(100); - gpio_set_level(GPIO_USB_MCU_RST, 0); + board_reset_pd_mcu(); #endif system_reset(SYSTEM_RESET_HARD); /* That shouldn't return... */ diff --git a/driver/build.mk b/driver/build.mk index f45b293dc7..997726fe24 100644 --- a/driver/build.mk +++ b/driver/build.mk @@ -56,6 +56,7 @@ driver-$(CONFIG_TEMP_SENSOR_TMP432)+=temp_sensor/tmp432.o # USB switches driver-$(CONFIG_USB_SWITCH_PI3USB9281)+=usb_switch_pi3usb9281.o +driver-$(CONFIG_USB_SWITCH_PI3USB30532)+=usb_switch_pi3usb30532.o driver-$(CONFIG_USB_SWITCH_TSU6721)+=usb_switch_tsu6721.o # Firmware Update diff --git a/driver/pi3usb30532.h b/driver/pi3usb30532.h new file mode 100644 index 0000000000..f99c9561bb --- /dev/null +++ b/driver/pi3usb30532.h @@ -0,0 +1,78 @@ +/* Copyright 2015 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. + * + * Pericom PI3USB30532 USB port switch driver. + */ + +#ifndef PI3USB30532_H +#define PI3USB30532_H + +#include <inttypes.h> + +/* USB switch registers */ +#define PI3USB30532_REG_ADDR 0x00 +#define PI3USB30532_REG_VENDOR 0x01 +#define PI3USB30532_REG_CONTROL 0x02 +/* Control register field */ +#define PI3USB30532_CTRL_MASK 0x7 +#define PI3USB30532_CTRL_RSVD 0 +/* Switch vendor ID */ +#define PI3USB30532_VENDOR_ID 0 + +/* PI3USB30532 control flags */ +#define PI3USB30532_BIT_SWAP (1 << 0) +#define PI3USB30532_BIT_DP (1 << 1) +#define PI3USB30532_BIT_USB (1 << 2) + +/* PI3USB30532 modes */ +/* Power down, switch open */ +#define PI3USB30532_MODE_POWERDOWN 0 +/* Keep power on, switch open */ +#define PI3USB30532_MODE_POWERON 1 +/* 4-lane DP 1.2 + * dp0~3 : rx2, tx2, tx1, rx1 + * hpd+/-: rfu1, rfu2 + */ +#define PI3USB30532_MODE_DP PI3USB30532_BIT_DP +/* 4-lane DP 1.2 swap + * dp0~3 : rx1, tx1, tx2, rx2 + * hpd+/-: rfu2, rfu1 + */ +#define PI3USB30532_MODE_DP_SWAP (PI3USB30532_MODE_DP | PI3USB30532_BIT_SWAP) +/* USB3 + * tx/rx : tx1, rx1 + */ +#define PI3USB30532_MODE_USB PI3USB30532_BIT_USB +/* USB3 swap + * tx/rx : tx2, rx2 + */ +#define PI3USB30532_MODE_USB_SWAP (PI3USB30532_MODE_USB | PI3USB30532_BIT_SWAP) +/* 2-lane DP 1.2 + USB3 + * tx/rx : tx1, rx1 + * dp0~1 : rx2, tx2 + * hpd+/-: rfu1, rfu2 + */ +#define PI3USB30532_MODE_DP_USB (PI3USB30532_BIT_DP | PI3USB30532_BIT_USB) +/* 2-lane DP 1.2 + USB3, swap + * tx/rx : tx2, rx2 + * dp0-1 : rx1, tx1 + * hpd+/-: rfu2, rfu1 + */ +#define PI3USB30532_MODE_DP_USB_SWAP (PI3USB30532_MODE_DP_USB | \ + PI3USB30532_BIT_SWAP) + + +/* Reads PI3USB30532 register */ +int pi3usb30532_read(uint8_t chip_idx, uint8_t reg); + +/* Writes PI3USB30532 register */ +int pi3usb30532_write(uint8_t chip_idx, uint8_t reg, uint8_t val); + +/* Writes PI3USB30532 control register */ +int pi3usb30532_set_switch(uint8_t chip_idx, uint8_t mode); + +/* Resets PI3USB30532 to power on default value */ +int pi3usb30532_reset(uint8_t chip_idx); + +#endif /* PI3USB30532_H */ diff --git a/driver/usb_switch_pi3usb30532.c b/driver/usb_switch_pi3usb30532.c new file mode 100644 index 0000000000..1688278ae6 --- /dev/null +++ b/driver/usb_switch_pi3usb30532.c @@ -0,0 +1,85 @@ +/* Copyright 2015 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. + * + * Pericom PI3USB30532 USB port switch driver. + */ + +#include "common.h" +#include "console.h" +#include "gpio.h" +#include "hooks.h" +#include "i2c.h" +#include "task.h" +#include "timer.h" +#include "pi3usb30532.h" +#include "util.h" + +/* Console output macros */ +#define CPUTS(outstr) cputs(CC_USBCHARGE, outstr) +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args) + +#define INTERNAL_READ_ERROR(code) (EC_ERROR_INTERNAL_FIRST + code) +#define IS_READ_ERROR(code) ((code) > EC_ERROR_INTERNAL_FIRST) + +/* 8-bit I2C address */ +static const int pi3usb30532_addrs[] = CONFIG_USB_SWITCH_I2C_ADDRS; + +int pi3usb30532_read(uint8_t chip_idx, uint8_t reg) +{ + int res, val; + int addr = pi3usb30532_addrs[chip_idx]; + + res = i2c_read8(I2C_PORT_USB_SWITCH, addr, reg, &val); + if (res) + return INTERNAL_READ_ERROR(res); + + return val; +} + +int pi3usb30532_write(uint8_t chip_idx, uint8_t reg, uint8_t val) +{ + int res; + int addr = pi3usb30532_addrs[chip_idx]; + + res = i2c_write8(I2C_PORT_USB_SWITCH, addr, reg, val); + if (res) + CPUTS("PI3USB30532 I2C write failed"); + + return res; +} + +/* Writes control register to set switch mode */ +int pi3usb30532_set_switch(uint8_t chip_idx, uint8_t mode) +{ + return pi3usb30532_write(chip_idx, PI3USB30532_REG_CONTROL, + (mode & PI3USB30532_CTRL_MASK) | + PI3USB30532_CTRL_RSVD); +} + +int pi3usb30532_reset(uint8_t chip_idx) +{ + return pi3usb30532_set_switch(chip_idx, PI3USB30532_MODE_POWERDOWN); +} + +static void pi3usb30532_init(void) +{ + int i, res, val; + + for (i = 0; i < ARRAY_SIZE(pi3usb30532_addrs); i++) { + res = pi3usb30532_reset(i); + if (res) + CPRINTS("PI3USB30532 [%d] init failed", i); + + val = pi3usb30532_read(i, PI3USB30532_REG_VENDOR); + if (IS_READ_ERROR(val)) { + CPRINTS("PI3USB30532 [%d] read failed", i); + continue; + } + + if (val != PI3USB30532_VENDOR_ID) + CPRINTS("PI3USB30532 [%d] invalid ID 0x%02x", i, val); + + } +} +DECLARE_HOOK(HOOK_INIT, pi3usb30532_init, HOOK_PRIO_LAST); diff --git a/power/mediatek.c b/power/mediatek.c index e4b54c59d9..3aa1c1c564 100644 --- a/power/mediatek.c +++ b/power/mediatek.c @@ -79,10 +79,15 @@ #define DELAY_SHUTDOWN_ON_POWER_HOLD (11000 * MSEC) /* 11 seconds */ /* - * The hold time for pulling down the PMIC_WARM_RESET_L pin so that + * The hold time for pulling down the PMIC_WARM_RESET_H pin so that * the AP can entery the recovery mode (flash SPI flash from USB). */ -#define PMIC_WARM_RESET_L_HOLD_TIME (4 * MSEC) +#define PMIC_WARM_RESET_H_HOLD_TIME (4 * MSEC) + +/* + * The hold time for pulling down the SYSTEM_POWER_H pin. + */ +#define PMIC_COLD_RESET_L_HOLD_TIME (50 * MSEC) /* * The first time the PMIC sees power (AC or battery) it needs 200ms (+/-12% @@ -90,6 +95,9 @@ * time of approx. 0.5msec until V2_5 regulator starts up. */ #define PMIC_RTC_STARTUP (225 * MSEC) +/* Wait for 5V power source stable */ +#define PMIC_WAIT_FOR_5V_POWER_GOOD (1 * MSEC) + /* TODO(crosbug.com/p/25047): move to HOOK_POWER_BUTTON_CHANGE */ /* 1 if the power button was pressed last time we checked */ static char power_button_was_pressed; @@ -154,21 +162,14 @@ enum blacklight_override_t { static void chipset_turn_off_power_rails(void); /** - * Set the AP RESET signal. - * - * This function is for backward-compatible. - * - * AP_RESET_H (PB3) is stuffed before rev <= 2.0 and connected to PMIC RESET. - * After rev >= 2.2, this is removed. This should not effected the new board. + * Set the system power signal. * - * @param asserted Assert (=1) or deassert (=0) the signal. This is the - * logical level of the pin, not the physical level. + * @param asserted off (=0) or on (=1) */ -static void set_ap_reset(int asserted) +static void set_system_power(int asserted) { - /* Signal is active-high */ - CPRINTS("set_ap_reset(%d)", asserted); - gpio_set_level(GPIO_AP_RESET_H, asserted); + CPRINTS("set_system_power(%d)", asserted); + gpio_set_level(GPIO_SYSTEM_POWER_H, asserted); } /** @@ -181,8 +182,25 @@ static void set_ap_reset(int asserted) */ static void set_pmic_pwron(int asserted) { + timestamp_t poll_deadline; /* Signal is active-high */ CPRINTS("set_pmic_pwron(%d)", asserted); + /* Oak rev1 power-on sequence: + * raise GPIO_SYSTEM_POWER_H + * wait for 5V power good, timeout 1 second + */ + /* if (system_get_board_version() > 1) { */ + if (asserted) { + set_system_power(asserted); + poll_deadline = get_time(); + poll_deadline.val += SECOND; + while (asserted && !gpio_get_level(GPIO_5V_POWER_GOOD) && + get_time().val < poll_deadline.val) + usleep(PMIC_WAIT_FOR_5V_POWER_GOOD); + if (gpio_get_level(GPIO_5V_POWER_GOOD)) + CPRINTS("5V power not ready"); + } + gpio_set_level(GPIO_PMIC_PWRON_H, asserted); } @@ -264,10 +282,6 @@ static int check_for_power_off_event(void) power_button_was_pressed = pressed; - /* POWER_GOOD released by AP : shutdown immediately */ - if (!power_has_signals(IN_POWER_GOOD)) - return POWER_OFF_BY_POWER_GOOD_LOST; - return POWER_OFF_CANCEL; } @@ -360,16 +374,9 @@ static void chipset_turn_off_power_rails(void) { /* Release the power on pin, if it was asserted */ set_pmic_pwron(0); - /* Close the pmic power source immediately */ - /* set_pmic_source(0); */ - usleep(PMIC_THERM_HOLD_TIME); - - /* Keep AP and PMIC in reset the whole time */ - set_pmic_warm_reset(1); - - /* Hold the reset pin so that the AP stays in off mode (rev <= 2.0) */ - set_ap_reset(1); + /* system power off */ + set_system_power(0); } void chipset_force_shutdown(void) @@ -435,6 +442,13 @@ static int check_for_power_on_event(void) return POWER_OFF_CANCEL; } +void release_pmic_pwron_deferred(void) +{ + /* Release PMIC power button */ + set_pmic_pwron(0); +} +DECLARE_DEFERRED(release_pmic_pwron_deferred); + /** * Power on the AP */ @@ -442,14 +456,12 @@ static void power_on(void) { uint64_t t; - CPRINTS("power_on AP"); - /* Set pull-up and enable interrupt */ gpio_set_flags(power_signal_list[MTK_SUSPEND_ASSERTED].gpio, GPIO_INPUT | GPIO_PULL_UP | GPIO_INT_BOTH); - /* Make sure we de-assert and AP_RESET_L pin. */ - set_ap_reset(0); + /* Make sure we de-assert and GPIO_PMIC_WARM_RESET_H pin. */ + set_pmic_warm_reset(0); /* * Before we push PMIC power button, wait for the PMI RTC ready, which @@ -471,10 +483,7 @@ static void power_on(void) /* Push the power button */ set_pmic_pwron(1); - usleep(PMIC_PWRON_PRESS_TIME); - - /* Wait till the AP has SPI ready */ - /* usleep(PMIC_SPI_READY_TIME); */ + hook_call_deferred(release_pmic_pwron_deferred, PMIC_PWRON_PRESS_TIME); /* enable interrupt */ gpio_set_flags(GPIO_SUSPEND_L, INT_BOTH_PULL_UP); @@ -547,17 +556,17 @@ void chipset_reset(int is_cold) { if (is_cold) { CPRINTS("EC triggered cold reboot"); - power_off(); - /* After POWER_GOOD is dropped off, - * the system will be on again - */ - power_request = POWER_REQ_ON; + set_system_power(0); + usleep(PMIC_COLD_RESET_L_HOLD_TIME); + /* Press the PMIC power button */ + set_pmic_pwron(1); + usleep(PMIC_PWRON_PRESS_TIME); + set_pmic_pwron(0); } else { CPRINTS("EC triggered warm reboot"); - CPRINTS("assert GPIO_PMIC_WARM_RESET_H for %d ms", - PMIC_WARM_RESET_L_HOLD_TIME / MSEC); set_pmic_warm_reset(1); - usleep(PMIC_WARM_RESET_L_HOLD_TIME); + usleep(PMIC_WARM_RESET_H_HOLD_TIME); + /* deassert the reset signals */ set_pmic_warm_reset(0); } } @@ -597,7 +606,6 @@ enum power_state power_handle_state(enum power_state state) CPRINTS("POWER_GOOD seen"); if (wait_for_power_button_release (DELAY_SHUTDOWN_ON_POWER_HOLD) == EC_SUCCESS) { - set_pmic_pwron(0); return POWER_S3; } else { CPRINTS("long-press button, shutdown"); |