summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--board/firefly/usb_pd_policy.c5
-rw-r--r--board/fruitpie/usb_pd_policy.c5
-rw-r--r--board/samus/board.c14
-rw-r--r--board/samus/board.h1
-rw-r--r--board/samus/ec.tasklist1
-rw-r--r--board/samus_pd/usb_pd_policy.c73
-rw-r--r--board/zinger/usb_pd_policy.c5
-rw-r--r--common/build.mk2
-rw-r--r--common/charge_state_v2.c2
-rw-r--r--common/host_command_pd.c52
-rw-r--r--common/usb_pd_protocol.c10
-rw-r--r--include/charge_state.h2
-rw-r--r--include/config.h14
-rw-r--r--include/ec_commands.h19
-rw-r--r--include/host_command.h6
-rw-r--r--include/usb_pd.h7
16 files changed, 209 insertions, 9 deletions
diff --git a/board/firefly/usb_pd_policy.c b/board/firefly/usb_pd_policy.c
index 0a57d34192..a526702b13 100644
--- a/board/firefly/usb_pd_policy.c
+++ b/board/firefly/usb_pd_policy.c
@@ -125,3 +125,8 @@ int pd_board_checks(void)
return EC_SUCCESS;
}
+
+int pd_power_negotiation_allowed(void)
+{
+ return 1;
+}
diff --git a/board/fruitpie/usb_pd_policy.c b/board/fruitpie/usb_pd_policy.c
index 9464b242be..6ebc04385b 100644
--- a/board/fruitpie/usb_pd_policy.c
+++ b/board/fruitpie/usb_pd_policy.c
@@ -123,3 +123,8 @@ int pd_board_checks(void)
{
return EC_SUCCESS;
}
+
+int pd_power_negotiation_allowed(void)
+{
+ return 1;
+}
diff --git a/board/samus/board.c b/board/samus/board.c
index 000c1f0db7..d5a9bead21 100644
--- a/board/samus/board.c
+++ b/board/samus/board.c
@@ -18,6 +18,7 @@
#include "extpower.h"
#include "fan.h"
#include "gpio.h"
+#include "hooks.h"
#include "host_command.h"
#include "i2c.h"
#include "jtag.h"
@@ -39,7 +40,8 @@
static void pd_mcu_interrupt(enum gpio_signal signal)
{
- ccprintf("PD interrupt!\n");
+ /* Exchange status with PD MCU. */
+ host_command_pd_send_status();
}
/* GPIO signal list. Must match order from enum gpio_signal. */
@@ -90,7 +92,8 @@ const struct gpio_info gpio_list[] = {
{"CAPSENSE_INT_L", LM4_GPIO_N, (1<<0), GPIO_INPUT, NULL},
#endif
{"PD_MCU_INT_L", LM4_GPIO_J, (1<<5), GPIO_PULL_UP|
- GPIO_INT_FALLING,
+ GPIO_INT_FALLING|
+ GPIO_INT_DSLEEP,
pd_mcu_interrupt},
/* Other inputs */
@@ -338,6 +341,13 @@ struct keyboard_scan_config keyscan_config = {
},
};
+/* Initialize board. */
+static void board_init(void)
+{
+ gpio_enable_interrupt(GPIO_PD_MCU_INT_L);
+}
+DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT);
+
#ifdef CONFIG_BATTERY_PRESENT_CUSTOM
/**
* Physical check of battery presence.
diff --git a/board/samus/board.h b/board/samus/board.h
index b914964e78..48b1a94be1 100644
--- a/board/samus/board.h
+++ b/board/samus/board.h
@@ -44,7 +44,6 @@
#define CONFIG_CHARGER_INPUT_CURRENT 2000
#define CONFIG_CHARGER_DISCHARGE_ON_AC
#define CONFIG_FANS 2
-#define CONFIG_HOST_CMD_MASTER
#define CONFIG_PECI_TJMAX 100
#define CONFIG_PWM
#define CONFIG_PWM_KBLIGHT
diff --git a/board/samus/ec.tasklist b/board/samus/ec.tasklist
index 2b8da9c77b..ab25faa872 100644
--- a/board/samus/ec.tasklist
+++ b/board/samus/ec.tasklist
@@ -23,6 +23,7 @@
TASK_ALWAYS(CHARGER, charger_task, NULL, TASK_STACK_SIZE) \
TASK_NOTEST(CHIPSET, chipset_task, NULL, TASK_STACK_SIZE) \
TASK_NOTEST(KEYPROTO, keyboard_protocol_task, NULL, 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, LARGER_TASK_STACK_SIZE) \
TASK_ALWAYS(POWERBTN, power_button_task, NULL, TASK_STACK_SIZE) \
diff --git a/board/samus_pd/usb_pd_policy.c b/board/samus_pd/usb_pd_policy.c
index ea5f2d1703..2e2a42d182 100644
--- a/board/samus_pd/usb_pd_policy.c
+++ b/board/samus_pd/usb_pd_policy.c
@@ -8,6 +8,7 @@
#include "console.h"
#include "gpio.h"
#include "hooks.h"
+#include "host_command.h"
#include "registers.h"
#include "task.h"
#include "timer.h"
@@ -33,6 +34,9 @@ const int pd_snk_pdo_cnt = ARRAY_SIZE(pd_snk_pdo);
/* Cap on the max voltage requested as a sink (in millivolts) */
static unsigned max_mv = -1; /* no cap */
+/* Flag for battery status */
+static int battery_ok;
+
int pd_choose_voltage(int cnt, uint32_t *src_caps, uint32_t *rdo)
{
int i;
@@ -40,6 +44,10 @@ int pd_choose_voltage(int cnt, uint32_t *src_caps, uint32_t *rdo)
int max_uw = 0;
int max_i = -1;
+ /* Don't negotiate power until battery ok signal is given */
+ if (!battery_ok)
+ return -EC_ERROR_UNKNOWN;
+
/* Get max power */
for (i = 0; i < cnt; i++) {
int uw;
@@ -119,7 +127,72 @@ void pd_power_supply_reset(void)
gpio_set_level(GPIO_USB_C0_5V_EN, 0);
}
+static void pd_send_ec_int(void)
+{
+ gpio_set_level(GPIO_EC_INT_L, 0);
+
+ /*
+ * Delay long enough to guarantee EC see's the change. Slowest
+ * EC clock speed is 250kHz in deep sleep -> 4us, and add 1us
+ * for buffer.
+ */
+ usleep(5);
+
+ gpio_set_level(GPIO_EC_INT_L, 1);
+}
+
int pd_board_checks(void)
{
+ static uint64_t last_time;
+
+ /*
+ * If battery is not yet ok, signal EC to send status. Avoid
+ * sending requests too frequently.
+ */
+ if (!battery_ok && (get_time().val - last_time >= SECOND)) {
+ last_time = get_time().val;
+ pd_send_ec_int();
+ }
+
return EC_SUCCESS;
}
+
+int pd_power_negotiation_allowed(void)
+{
+ return battery_ok;
+}
+
+static int command_ec_int(int argc, char **argv)
+{
+ pd_send_ec_int();
+
+ return EC_SUCCESS;
+}
+DECLARE_CONSOLE_COMMAND(ecint, command_ec_int,
+ "",
+ "Toggle EC interrupt line",
+ NULL);
+
+static int ec_status_host_cmd(struct host_cmd_handler_args *args)
+{
+ const struct ec_params_pd_status *p = args->params;
+ struct ec_response_pd_status *r = args->response;
+
+ if (p->batt_soc >= CONFIG_USB_PD_MIN_BATT_CHARGE) {
+ /*
+ * When battery is above minimum charge, we know
+ * that we have enough power remaining for us to
+ * negotiate power over PD.
+ */
+ CPRINTS("Battery is ok, safe to negotiate power");
+ battery_ok = 1;
+ } else {
+ battery_ok = 0;
+ }
+
+ args->response_size = sizeof(*r);
+
+ return EC_RES_SUCCESS;
+}
+DECLARE_HOST_COMMAND(EC_CMD_PD_EXCHANGE_STATUS, ec_status_host_cmd,
+ EC_VER_MASK(0));
diff --git a/board/zinger/usb_pd_policy.c b/board/zinger/usb_pd_policy.c
index 1b52d0876c..04b04fca6b 100644
--- a/board/zinger/usb_pd_policy.c
+++ b/board/zinger/usb_pd_policy.c
@@ -233,6 +233,11 @@ int pd_board_checks(void)
}
+int pd_power_negotiation_allowed(void)
+{
+ return 1;
+}
+
void IRQ_HANDLER(STM32_IRQ_ADC_COMP)(void)
{
/* cut the power output */
diff --git a/common/build.mk b/common/build.mk
index 18c1c47579..09bbfe2564 100644
--- a/common/build.mk
+++ b/common/build.mk
@@ -43,7 +43,6 @@ common-$(CONFIG_EXTPOWER_SPRING)+=extpower_spring.o
common-$(CONFIG_FANS)+=fan.o
common-$(CONFIG_FLASH)+=flash.o
common-$(CONFIG_FMAP)+=fmap.o
-common-$(CONFIG_HOST_CMD_MASTER)+=host_command_master.o
common-$(CONFIG_I2C)+=i2c.o
common-$(CONFIG_I2C_ARBITRATION)+=i2c_arbitration.o
common-$(CONFIG_KEYBOARD_PROTOCOL_8042)+=keyboard_8042.o
@@ -72,6 +71,7 @@ common-$(HAS_TASK_CHIPSET)+=chipset.o throttle_ap.o
common-$(HAS_TASK_CONSOLE)+=console.o console_output.o uart_buffering.o
common-$(HAS_TASK_CONSOLE)+=memory_commands.o
common-$(HAS_TASK_HOSTCMD)+=acpi.o host_command.o host_event_commands.o
+common-$(HAS_TASK_PDCMD)+=host_command_master.o host_command_pd.o
common-$(HAS_TASK_KEYSCAN)+=keyboard_scan.o
common-$(HAS_TASK_LIGHTBAR)+=lb_common.o lightbar.o
common-$(HAS_TASK_MOTIONSENSE)+=motion_sense.o math_util.o
diff --git a/common/charge_state_v2.c b/common/charge_state_v2.c
index 87ad28561b..6a6a93765d 100644
--- a/common/charge_state_v2.c
+++ b/common/charge_state_v2.c
@@ -744,6 +744,8 @@ uint32_t charge_get_flags(void)
flags |= CHARGE_FLAG_FORCE_IDLE;
if (curr.ac)
flags |= CHARGE_FLAG_EXTERNAL_POWER;
+ if (curr.batt.flags & BATT_FLAG_RESPONSIVE)
+ flags |= CHARGE_FLAG_BATT_RESPONSIVE;
return flags;
}
diff --git a/common/host_command_pd.c b/common/host_command_pd.c
new file mode 100644
index 0000000000..5d9a3adf6d
--- /dev/null
+++ b/common/host_command_pd.c
@@ -0,0 +1,52 @@
+/* Copyright (c) 2014 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.
+ */
+
+/* Host command module for PD MCU */
+
+#include "charge_state.h"
+#include "common.h"
+#include "host_command.h"
+#include "task.h"
+#include "timer.h"
+#include "util.h"
+
+#define TASK_EVENT_EXCHANGE_PD_STATUS TASK_EVENT_CUSTOM(1)
+
+void host_command_pd_send_status(void)
+{
+ task_set_event(TASK_ID_PDCMD, TASK_EVENT_EXCHANGE_PD_STATUS, 0);
+}
+
+static void pd_exchange_status(void)
+{
+ struct ec_params_pd_status ec_status;
+
+ /*
+ * TODO(crosbug.com/p/29499): Change sending state of charge to
+ * remaining capacity for finer grained control.
+ */
+ /* Send battery state of charge */
+ if (charge_get_flags() & CHARGE_FLAG_BATT_RESPONSIVE)
+ ec_status.batt_soc = charge_get_percent();
+ else
+ ec_status.batt_soc = -1;
+
+ pd_host_command(EC_CMD_PD_EXCHANGE_STATUS, 0, &ec_status,
+ sizeof(struct ec_params_pd_status), NULL, 0);
+}
+
+void pd_command_task(void)
+{
+
+ while (1) {
+ /* Wait for the next command event */
+ int evt = task_wait_event(-1);
+
+ /* Process event to send status to PD */
+ if (evt & TASK_EVENT_EXCHANGE_PD_STATUS)
+ pd_exchange_status();
+ }
+}
+
diff --git a/common/usb_pd_protocol.c b/common/usb_pd_protocol.c
index 214d5f15a0..34a6183cd2 100644
--- a/common/usb_pd_protocol.c
+++ b/common/usb_pd_protocol.c
@@ -495,6 +495,10 @@ static void handle_data_request(void *ctxt, uint16_t head, uint32_t *payload)
*/
pd_task_state = PD_STATE_SNK_REQUESTED;
}
+ /*
+ * TODO(crosbug.com/p/28332): if pd_choose_voltage
+ * returns an error, ignore failure for now.
+ */
}
break;
#endif /* CONFIG_USB_PD_DUAL_ROLE */
@@ -886,6 +890,12 @@ void pd_task(void)
break;
}
+ /* Don't continue if power negotiation is not allowed */
+ if (!pd_power_negotiation_allowed()) {
+ timeout = PD_T_GET_SOURCE_CAP;
+ break;
+ }
+
res = send_control(ctxt, PD_CTRL_GET_SOURCE_CAP);
/* packet was acked => PD capable device) */
if (res >= 0) {
diff --git a/include/charge_state.h b/include/charge_state.h
index 0da544422f..c23e70c260 100644
--- a/include/charge_state.h
+++ b/include/charge_state.h
@@ -50,6 +50,8 @@ enum charge_state {
#define CHARGE_FLAG_FORCE_IDLE (1 << 0)
/* External (AC) power is present */
#define CHARGE_FLAG_EXTERNAL_POWER (1 << 1)
+/* Battery is responsive */
+#define CHARGE_FLAG_BATT_RESPONSIVE (1 << 2)
/* Debugging constants, in the same order as enum charge_state. This string
* table was moved here to sync with enum above.
diff --git a/include/config.h b/include/config.h
index 464ad50953..43f7cfdbca 100644
--- a/include/config.h
+++ b/include/config.h
@@ -503,9 +503,6 @@
/*****************************************************************************/
-/* Support EC acting as host master for other MCUs. */
-#undef CONFIG_HOST_CMD_MASTER
-
/*
* Support the host asking the EC about the status of the most recent host
* command.
@@ -866,12 +863,19 @@
#undef CONFIG_UART_TX_DMA
/*****************************************************************************/
+/* USB PD config */
+
+/* USB PD MCU slave address for host commands */
+#define CONFIG_USB_PD_I2C_SLAVE_ADDR 0x3c
+
+/* TODO(crosbug.com/p/29499): Determine threshold for power negotiation */
+/* USB PD minimum battery charge to negotiate for more power */
+#define CONFIG_USB_PD_MIN_BATT_CHARGE 1
/* USB PD transmit uses SPI master */
#undef CONFIG_USB_PD_TX_USES_SPI_MASTER
-/* USB PD MCU slave address for host commands */
-#define CONFIG_USB_PD_I2C_SLAVE_ADDR 0x3c
+/*****************************************************************************/
/* Support simple control of power to the device's USB ports */
#undef CONFIG_USB_PORT_POWER_DUMB
diff --git a/include/ec_commands.h b/include/ec_commands.h
index 1526084986..5edd754df3 100644
--- a/include/ec_commands.h
+++ b/include/ec_commands.h
@@ -2478,6 +2478,25 @@ struct ec_params_reboot_ec {
/*****************************************************************************/
/*
+ * PD commands
+ *
+ * These commands are for PD MCU communication.
+ */
+
+/* EC to PD MCU exchange status command */
+#define EC_CMD_PD_EXCHANGE_STATUS 0x100
+
+/* Status of EC being sent to PD */
+struct ec_params_pd_status {
+ int8_t batt_soc; /* battery state of charge */
+} __packed;
+
+/* Status of PD being sent back to EC */
+struct ec_response_pd_status {
+} __packed;
+
+/*****************************************************************************/
+/*
* 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
diff --git a/include/host_command.h b/include/host_command.h
index 1fbf0b6554..231ef9a6b8 100644
--- a/include/host_command.h
+++ b/include/host_command.h
@@ -207,6 +207,12 @@ void host_packet_receive(struct host_packet *pkt);
*/
void host_throttle_cpu(int throttle);
+
+/**
+ * Signal host command task to send status to PD MCU.
+ */
+void host_command_pd_send_status(void);
+
/**
* Send host command to PD MCU.
*
diff --git a/include/usb_pd.h b/include/usb_pd.h
index 89229079a4..e8f9168aa7 100644
--- a/include/usb_pd.h
+++ b/include/usb_pd.h
@@ -185,6 +185,13 @@ void pd_request_source_voltage(int mv);
*/
int pd_board_checks(void);
+/**
+ * Query if power negotiation is allowed.
+ *
+ * @return true if negotation is allowed, false otherwise.
+ */
+int pd_power_negotiation_allowed(void);
+
/*
* Handle Vendor Defined Message with our vendor ID.
*