summaryrefslogtreecommitdiff
path: root/board/honeybuns/usb_pd_policy.c
diff options
context:
space:
mode:
Diffstat (limited to 'board/honeybuns/usb_pd_policy.c')
-rw-r--r--board/honeybuns/usb_pd_policy.c243
1 files changed, 243 insertions, 0 deletions
diff --git a/board/honeybuns/usb_pd_policy.c b/board/honeybuns/usb_pd_policy.c
new file mode 100644
index 0000000000..7e45a0cc87
--- /dev/null
+++ b/board/honeybuns/usb_pd_policy.c
@@ -0,0 +1,243 @@
+/* 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.
+ */
+
+#include "charger.h"
+#include "common.h"
+#include "console.h"
+#include "gpio.h"
+#include "hooks.h"
+#include "registers.h"
+#include "system.h"
+#include "task.h"
+#include "timer.h"
+#include "util.h"
+#include "usb_pd.h"
+
+
+#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args)
+#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args)
+
+#define PDO_FIXED_FLAGS (PDO_FIXED_EXTERNAL | PDO_FIXED_DUAL_ROLE | \
+ PDO_FIXED_DATA_SWAP)
+
+const uint32_t pd_src_pdo[] = {
+ PDO_FIXED(5000, 3000, PDO_FIXED_FLAGS),
+ PDO_FIXED(12000, 3000, PDO_FIXED_FLAGS),
+ PDO_FIXED(20000, 3000, PDO_FIXED_FLAGS),
+};
+const int pd_src_pdo_cnt = ARRAY_SIZE(pd_src_pdo);
+
+const uint32_t pd_snk_pdo[] = {
+ PDO_FIXED(5000, 500, PDO_FIXED_FLAGS),
+};
+const int pd_snk_pdo_cnt = ARRAY_SIZE(pd_snk_pdo);
+
+/* Holds valid object position (opos) for entered mode */
+static int alt_mode[PD_AMODE_COUNT];
+
+void pd_set_input_current_limit(int port, uint32_t max_ma,
+ uint32_t supply_voltage)
+{
+
+}
+
+
+int pd_is_valid_input_voltage(int mv)
+{
+ /* Any voltage less than the max is allowed */
+ return 1;
+}
+
+int pd_check_requested_voltage(uint32_t rdo)
+{
+ int max_ma = rdo & 0x3FF;
+ int op_ma = (rdo >> 10) & 0x3FF;
+ int idx = rdo >> 28;
+ uint32_t pdo;
+ uint32_t pdo_ma;
+
+ if (!idx || idx > pd_src_pdo_cnt)
+ return EC_ERROR_INVAL; /* Invalid index */
+
+ /* check current ... */
+ pdo = pd_src_pdo[idx - 1];
+ pdo_ma = (pdo & 0x3ff);
+ if (op_ma > pdo_ma)
+ return EC_ERROR_INVAL; /* too much op current */
+ if (max_ma > pdo_ma)
+ return EC_ERROR_INVAL; /* too much max current */
+
+ CPRINTF("Requested %d V %d mA (for %d/%d mA)\n",
+ ((pdo >> 10) & 0x3ff) * 50, (pdo & 0x3ff) * 10,
+ ((rdo >> 10) & 0x3ff) * 10, (rdo & 0x3ff) * 10);
+
+ return EC_SUCCESS;
+}
+
+void pd_transition_voltage(int idx)
+{
+ /* No-operation: we are always 5V */
+}
+
+int pd_set_power_supply_ready(int port)
+{
+ /* provide VBUS */
+ gpio_set_level(GPIO_PPVAR_VBUS_EN, 1);
+ return EC_SUCCESS; /* we are ready */
+}
+
+void pd_power_supply_reset(int port)
+{
+ /* Kill VBUS */
+ gpio_set_level(GPIO_PPVAR_VBUS_EN, 0);
+}
+
+int pd_board_checks(void)
+{
+ return EC_SUCCESS;
+}
+
+int pd_check_power_swap(int port)
+{
+ /* Always allow power swap */
+ return 1;
+}
+
+int pd_check_data_swap(int port, int data_role)
+{
+ /* Always allow data swap */
+ return 1;
+}
+
+void pd_execute_data_swap(int port, int data_role)
+{
+ /* Do nothing */
+}
+
+void pd_check_pr_role(int port, int pr_role, int partner_pr_swap)
+{
+}
+
+void pd_check_dr_role(int port, int dr_role, int partner_dr_swap)
+{
+}
+
+int pd_alt_mode(int port, uint16_t svid)
+{
+ if (svid == USB_SID_DISPLAYPORT)
+ return alt_mode[PD_AMODE_DISPLAYPORT];
+ else if (svid == USB_VID_GOOGLE)
+ return alt_mode[PD_AMODE_GOOGLE];
+ return 0;
+}
+
+
+/* ----------------- Vendor Defined Messages ------------------ */
+/* TODO () The VDM section needs to be updated for honeybuns */
+const struct svdm_response svdm_rsp = {
+ .identity = NULL,
+ .svids = NULL,
+ .modes = NULL,
+};
+
+int pd_custom_vdm(int port, int cnt, uint32_t *payload,
+ uint32_t **rpayload)
+{
+ int cmd = PD_VDO_CMD(payload[0]);
+ uint16_t dev_id = 0;
+
+ /* make sure we have some payload */
+ if (cnt == 0)
+ return 0;
+
+ switch (cmd) {
+ case VDO_CMD_VERSION:
+ /* guarantee last byte of payload is null character */
+ *(payload + cnt - 1) = 0;
+ CPRINTF("version: %s\n", (char *)(payload+1));
+ break;
+ case VDO_CMD_READ_INFO:
+ case VDO_CMD_SEND_INFO:
+ /* if last word is present, it contains lots of info */
+ if (cnt == 7) {
+ dev_id = VDO_INFO_HW_DEV_ID(payload[6]);
+ CPRINTF("DevId:%d.%d SW:%d RW:%d\n",
+ HW_DEV_ID_MAJ(dev_id),
+ HW_DEV_ID_MIN(dev_id),
+ VDO_INFO_SW_DBG_VER(payload[6]),
+ VDO_INFO_IS_RW(payload[6]));
+ }
+ /* copy hash */
+ if (cnt >= 6)
+ pd_dev_store_rw_hash(port, dev_id, payload + 1,
+ SYSTEM_IMAGE_UNKNOWN);
+
+ break;
+ }
+
+ return 0;
+}
+
+static int svdm_enter_dp_mode(int port, uint32_t mode_caps)
+{
+ /* Only enter mode if device is DFP_D capable */
+ if (mode_caps & MODE_DP_SNK) {
+ CPRINTF("Entering mode w/ vdo = %08x\n", mode_caps);
+ return 0;
+ }
+
+ return -1;
+}
+
+static int dp_on;
+
+static int svdm_dp_status(int port, uint32_t *payload)
+{
+ payload[0] = VDO(USB_SID_DISPLAYPORT, 1, CMD_DP_STATUS);
+ payload[1] = VDO_DP_STATUS(0, /* HPD IRQ ... not applicable */
+ 0, /* HPD level ... not applicable */
+ 0, /* exit DP? ... no */
+ 0, /* usb mode? ... no */
+ 0, /* multi-function ... no */
+ dp_on,
+ 0, /* power low? ... no */
+ dp_on);
+ return 2;
+};
+
+static int svdm_dp_config(int port, uint32_t *payload)
+{
+ board_set_usb_mux(port, TYPEC_MUX_DP, pd_get_polarity(port));
+ dp_on = 1;
+ payload[0] = VDO(USB_SID_DISPLAYPORT, 1, CMD_DP_CONFIG);
+ payload[1] = VDO_DP_CFG(MODE_DP_PIN_E, /* sink pins */
+ MODE_DP_PIN_E, /* src pins */
+ 1, /* DPv1.3 signaling */
+ 2); /* UFP connected */
+ return 2;
+};
+
+static int svdm_dp_attention(int port, uint32_t *payload)
+{
+ return 1; /* ack */
+}
+
+static void svdm_exit_dp_mode(int port)
+{
+ CPRINTF("Exiting mode\n");
+ /* return to safe config */
+}
+
+const struct svdm_amode_fx supported_modes[] = {
+ {
+ .svid = USB_SID_DISPLAYPORT,
+ .enter = &svdm_enter_dp_mode,
+ .status = &svdm_dp_status,
+ .config = &svdm_dp_config,
+ .attention = &svdm_dp_attention,
+ .exit = &svdm_exit_dp_mode,
+ },
+};
+const int supported_modes_cnt = ARRAY_SIZE(supported_modes);