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
This commit is contained in:
Rong Chang
2015-03-23 20:12:56 +08:00
committed by ChromeOS Commit Bot
parent 937cc8a64e
commit 552c17543f
18 changed files with 876 additions and 47 deletions

View File

@@ -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 */

61
board/oak/battery.c Normal file
View File

@@ -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();
}

141
board/oak/board.c Normal file
View File

@@ -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

107
board/oak/board.h Normal file
View File

@@ -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 */

13
board/oak/build.mk Normal file
View File

@@ -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

26
board/oak/ec.tasklist Normal file
View File

@@ -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)

51
board/oak/extpower.c Normal file
View File

@@ -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);

86
board/oak/gpio.inc Normal file
View File

@@ -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 */

137
board/oak/led.c Normal file
View File

@@ -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);

View File

@@ -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;

View File

@@ -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);

View File

@@ -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

View File

@@ -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"

View File

@@ -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... */

View File

@@ -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

78
driver/pi3usb30532.h Normal file
View File

@@ -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 */

View File

@@ -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);

View File

@@ -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.
* Set the system power 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.
*
* @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");