mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2026-01-09 17:11:42 +00:00
pd: VDM Alternate mode support.
Successfully communicate SVDM for discovery (identity, svids, modes)
and enter mode.
Still need to:
- Add same functionality on when power role is sink too.
- determine what connected events would require exit mode.
- do proper cleanup on disconnect.
- implement real display port 'enter' mode for samus_pd
- test & cleanup
Additionally the USB Billboard class functionality needs to be added
but will likely do that in a separate CL.
BRANCH=none
BUG=chrome-os-partner:28342
TEST=manual,
From fruitpie,
[Image: RO, fruitpie_v1.1.2263-d79140d-dirty 2014-09-29 17:44:15 tbroch@brisket.mtv.corp.google.com]
[0.000383 Inits done]
C0 st2
Console is enabled; type HELP for help.
> [0.250551 USB PD initialized]
pd dualrole source
C0 st8
> [8.366335 PD TMOUT RX 1/1]
RX ERR (-1)
[8.478308 PD TMOUT RX 1/1]
RX ERR (-1)
[8.590280 PD TMOUT RX 1/1]
RX ERR (-1)
C0 st9
Switch to 5000 V 3000 mA (for 3000/3000 mA)
C0 st10
C0 st11
C0 st12
8.867593] SVDM/4 [1] ff008081 340018d1 00000000 17000008
8.867906] DONE
8.871006] SVDM/2 [2] ff008082 ff010000
8.871224] DONE
8.875092] SVDM/7 [3] ff018083 00100081 00000000 00000000 00000000 00000000 00000000
Entering mode w/ vdo = 00100081
8.875492] DONE
8.878435] SVDM/1 [4] ff018144
8.878612] DONE
> pe 0 dump
SVID[0]: ff01 [0] 00100081 [1] 00000000 [2] 00000000 [3] 00000000 [4] 00000000 [5] 00000000
MODE[0]: svid:ff01 mode:1 caps:00100081
From hoho,
[Image: RO, hoho_v1.1.2263-d79140d-dirty 2014-09-29 17:54:59 tbroch@brisket.mtv.corp.google.com]
[0.000375 Inits done]
C0 st2
Console is enabled; type HELP for help.
> [0.250542 USB PD initialized]
C0 st3
[0.264637 PD TMOUT RX 1/1]
RX ERR (-1)
Request [1] 5V 3000mA
C0 st4
C0 st5
C0 st6
0.487451] SVDM/1 [1] ff008001
0.487628] DONE
0.491190] SVDM/1 [2] ff008002
0.491346] DONE
0.494510] SVDM/1 [3] ff018003
0.494667] DONE
0.498777] SVDM/1 [4] ff018104
0.498934] DONE
Change-Id: I5e2b7802c66b8aaad97e5120dca7a02820086bc1
Signed-off-by: Todd Broch <tbroch@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/219513
Reviewed-by: Alec Berg <alecaberg@chromium.org>
This commit is contained in:
committed by
chrome-internal-fetch
parent
0938563284
commit
a194bede19
@@ -22,6 +22,8 @@
|
||||
#define CONFIG_USB_MS_BUFFER_SIZE SPI_FLASH_MAX_WRITE_SIZE
|
||||
#define CONFIG_USB_POWER_DELIVERY
|
||||
#define CONFIG_USB_PD_CUSTOM_VDM
|
||||
#define CONFIG_USB_PD_ALT_MODE
|
||||
#define CONFIG_USB_PD_ALT_MODE_DFP
|
||||
#define CONFIG_USB_PD_DUAL_ROLE
|
||||
#define CONFIG_USB_PD_INTERNAL_COMP
|
||||
#define CONFIG_USBC_SS_MUX
|
||||
|
||||
@@ -136,7 +136,14 @@ int pd_board_checks(void)
|
||||
}
|
||||
|
||||
/* ----------------- Vendor Defined Messages ------------------ */
|
||||
int pd_custom_vdm(int port, int cnt, uint32_t *payload, uint32_t **rpayload)
|
||||
const struct svdm_response svdm_rsp = {
|
||||
.identity = NULL,
|
||||
.svids = NULL,
|
||||
.modes = NULL,
|
||||
};
|
||||
|
||||
static 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;
|
||||
@@ -171,3 +178,50 @@ int pd_custom_vdm(int port, int cnt, uint32_t *payload, uint32_t **rpayload)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pd_vdm(int port, int cnt, uint32_t *payload, uint32_t **rpayload)
|
||||
{
|
||||
if (PD_VDO_SVDM(payload[0]))
|
||||
return pd_svdm(port, cnt, payload, rpayload);
|
||||
else
|
||||
return pd_custom_vdm(port, cnt, payload, rpayload);
|
||||
}
|
||||
|
||||
static void svdm_enter_dp_mode(uint32_t mode_caps)
|
||||
{
|
||||
ccprintf("Entering mode w/ vdo = %08x\n", mode_caps);
|
||||
}
|
||||
|
||||
static void svdm_exit_dp_mode(void)
|
||||
{
|
||||
ccprintf("Exiting mode\n");
|
||||
/* return to safe config */
|
||||
}
|
||||
|
||||
static struct svdm_amode_data supported_modes[] = {
|
||||
{
|
||||
.svid = 0xff01,
|
||||
.enter = &svdm_enter_dp_mode,
|
||||
.exit = &svdm_exit_dp_mode,
|
||||
},
|
||||
};
|
||||
|
||||
void pd_dfp_choose_modes(struct pd_policy *pe)
|
||||
{
|
||||
int i, j;
|
||||
struct svdm_amode_data *modep;
|
||||
pe->amode_cnt = sizeof(supported_modes) / sizeof(struct
|
||||
svdm_amode_data);
|
||||
pe->amodes = modep = supported_modes;
|
||||
for (i = 0; i < pe->amode_cnt; i++) {
|
||||
for (j = 0; j < pe->svid_cnt; j++) {
|
||||
if (pe->svids[j].svid == modep->svid) {
|
||||
/* TODO(tbroch) need more elaborate mode
|
||||
resolution */
|
||||
modep->mode_caps = &pe->svids[j].mode_vdo[0];
|
||||
modep->amode = dfp_amode1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
modep++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,8 +26,12 @@
|
||||
#define CONFIG_SPI_MASTER_PORT 2
|
||||
#define CONFIG_SPI_CS_GPIO GPIO_PD_MCDP_SPI_CS_L
|
||||
#define CONFIG_USB_POWER_DELIVERY
|
||||
#define CONFIG_USB_PD_ALT_MODE
|
||||
#define CONFIG_USB_PD_DUAL_ROLE
|
||||
#define CONFIG_USB_PD_CUSTOM_VDM
|
||||
#define CONFIG_USB_PD_INTERNAL_COMP
|
||||
#define CONFIG_USB_PD_IDENTITY_HW_VERS 1
|
||||
#define CONFIG_USB_PD_IDENTITY_SW_VERS 1
|
||||
#undef CONFIG_WATCHDOG_HELP
|
||||
#undef CONFIG_LID_SWITCH
|
||||
#undef CONFIG_TASK_PROFILING
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include "timer.h"
|
||||
#include "util.h"
|
||||
#include "usb_pd.h"
|
||||
#include "version.h"
|
||||
|
||||
#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args)
|
||||
|
||||
@@ -23,7 +24,7 @@ const int pd_src_pdo_cnt = ARRAY_SIZE(pd_src_pdo);
|
||||
|
||||
/* Fake PDOs : we just want our pre-defined voltages */
|
||||
const uint32_t pd_snk_pdo[] = {
|
||||
PDO_FIXED(5000, 500, 0),
|
||||
PDO_FIXED(5000, 500, 0),
|
||||
};
|
||||
const int pd_snk_pdo_cnt = ARRAY_SIZE(pd_snk_pdo);
|
||||
|
||||
@@ -88,3 +89,119 @@ int pd_board_checks(void)
|
||||
return EC_SUCCESS;
|
||||
}
|
||||
|
||||
/* ----------------- Vendor Defined Messages ------------------ */
|
||||
const uint32_t vdo_idh = VDO_IDH(0, /* data caps as USB host */
|
||||
0, /* data caps as USB device */
|
||||
IDH_PTYPE_AMA, /* Alternate mode */
|
||||
1, /* supports alt modes */
|
||||
USB_VID_GOOGLE);
|
||||
|
||||
const uint32_t vdo_ama = VDO_AMA(CONFIG_USB_PD_IDENTITY_HW_VERS,
|
||||
CONFIG_USB_PD_IDENTITY_SW_VERS,
|
||||
0, 0, 0, 0, /* SS[TR][12] */
|
||||
0, /* Vconn power */
|
||||
0, /* Vconn power required */
|
||||
1, /* Vbus power required */
|
||||
0 /* USB SS support */);
|
||||
|
||||
static int svdm_response_identity(int port, uint32_t *payload)
|
||||
{
|
||||
payload[VDO_I(IDH)] = vdo_idh;
|
||||
/* TODO(tbroch): Do we plan to obtain TID (test ID) for hoho */
|
||||
payload[VDO_I(CSTAT)] = VDO_CSTAT(0);
|
||||
payload[VDO_I(AMA)] = vdo_ama;
|
||||
return 4;
|
||||
}
|
||||
|
||||
static int svdm_response_svids(int port, uint32_t *payload)
|
||||
{
|
||||
payload[1] = VDO_SVID(USB_SID_DISPLAYPORT, 0);
|
||||
return 2;
|
||||
}
|
||||
|
||||
const uint32_t vdo_dp_mode[1] = {
|
||||
VDO_MODE_DP(MODE_DP_PIN_E, /* sink pin cfg */
|
||||
0, /* no src pin cfg */
|
||||
1, /* no usb2.0 signalling in AMode */
|
||||
CABLE_PLUG, /* its a plug */
|
||||
0, /* no GEN2 usb */
|
||||
0, /* no dp 1.3 support */
|
||||
MODE_DP_SNK) /* Its a sink only */
|
||||
};
|
||||
|
||||
static int svdm_response_modes(int port, uint32_t *payload)
|
||||
{
|
||||
if (PD_VDO_VID(payload[0]) != USB_SID_DISPLAYPORT) {
|
||||
/* TODO(tbroch) USB billboard enabled here then */
|
||||
return 1; /* will generate a NAK */
|
||||
}
|
||||
memset(payload + 1, 0, sizeof(uint32_t) * PDO_MODES);
|
||||
payload[1] = vdo_dp_mode[0];
|
||||
/* TODO(tbroch) does spec have mechanism for identifying valid modes
|
||||
* returned for svid? */
|
||||
return PDO_MAX_OBJECTS;
|
||||
}
|
||||
|
||||
static int svdm_enter_mode(int port, uint32_t *payload)
|
||||
{
|
||||
/* SID & mode request is valid */
|
||||
if ((PD_VDO_VID(payload[0]) != USB_SID_DISPLAYPORT) ||
|
||||
(PD_VDO_OPOS(payload[0]) != 1))
|
||||
return 1; /* will generate a NAK */
|
||||
|
||||
gpio_set_level(GPIO_PD_SBU_ENABLE, 1);
|
||||
payload[1] = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int svdm_exit_mode(int port, uint32_t *payload)
|
||||
{
|
||||
/* SID & mode request is valid */
|
||||
if ((PD_VDO_VID(payload[0]) != USB_SID_DISPLAYPORT) ||
|
||||
(PD_VDO_OPOS(payload[0]) != 1))
|
||||
return 1; /* will generate a NAK */
|
||||
|
||||
gpio_set_level(GPIO_PD_SBU_ENABLE, 0);
|
||||
payload[1] = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
const struct svdm_response svdm_rsp = {
|
||||
.identity = &svdm_response_identity,
|
||||
.svids = &svdm_response_svids,
|
||||
.modes = &svdm_response_modes,
|
||||
.enter_mode = &svdm_enter_mode,
|
||||
.exit_mode = &svdm_exit_mode,
|
||||
};
|
||||
|
||||
static int pd_custom_vdm(int port, int cnt, uint32_t *payload,
|
||||
uint32_t **rpayload)
|
||||
{
|
||||
int cmd = PD_VDO_CMD(payload[0]);
|
||||
int rsize = 1;
|
||||
ccprintf("%T] VDM/%d [%d] %08x\n", cnt, cmd, payload[0]);
|
||||
|
||||
*rpayload = payload;
|
||||
switch (cmd) {
|
||||
case VDO_CMD_VERSION:
|
||||
memcpy(payload + 1, &version_data.version, 24);
|
||||
rsize = 7;
|
||||
break;
|
||||
default:
|
||||
/* Unknown : do not answer */
|
||||
return 0;
|
||||
}
|
||||
ccprintf("%T] DONE\n");
|
||||
/* respond (positively) to the request */
|
||||
payload[0] |= VDO_SRC_RESPONDER;
|
||||
|
||||
return rsize;
|
||||
}
|
||||
|
||||
int pd_vdm(int port, int cnt, uint32_t *payload, uint32_t **rpayload)
|
||||
{
|
||||
if (PD_VDO_SVDM(payload[0]))
|
||||
return pd_svdm(port, cnt, payload, rpayload);
|
||||
else
|
||||
return pd_custom_vdm(port, cnt, payload, rpayload);
|
||||
}
|
||||
|
||||
@@ -158,7 +158,8 @@ static void pd_send_host_event(void)
|
||||
}
|
||||
|
||||
/* ----------------- Vendor Defined Messages ------------------ */
|
||||
int pd_custom_vdm(int port, int cnt, uint32_t *payload, uint32_t **rpayload)
|
||||
static 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;
|
||||
@@ -199,6 +200,14 @@ int pd_custom_vdm(int port, int cnt, uint32_t *payload, uint32_t **rpayload)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pd_vdm(int port, int cnt, uint32_t *payload, uint32_t **rpayload)
|
||||
{
|
||||
if (PD_VDO_SVDM(payload[0]))
|
||||
return pd_svdm(port, cnt, payload, rpayload);
|
||||
else
|
||||
return pd_custom_vdm(port, cnt, payload, rpayload);
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
/* Console commands */
|
||||
static int command_ec_int(int argc, char **argv)
|
||||
|
||||
@@ -396,7 +396,8 @@ uint32_t *pd_get_info(void)
|
||||
return info_data;
|
||||
}
|
||||
|
||||
int pd_custom_vdm(int port, int cnt, uint32_t *payload, uint32_t **rpayload)
|
||||
static int pd_custom_vdm(int port, int cnt, uint32_t *payload,
|
||||
uint32_t **rpayload)
|
||||
{
|
||||
static int flash_offset;
|
||||
int cmd = PD_VDO_CMD(payload[0]);
|
||||
@@ -463,3 +464,11 @@ int pd_custom_vdm(int port, int cnt, uint32_t *payload, uint32_t **rpayload)
|
||||
|
||||
return rsize;
|
||||
}
|
||||
|
||||
int pd_vdm(int port, int cnt, uint32_t *payload, uint32_t **rpayload)
|
||||
{
|
||||
if (PD_VDO_SVDM(payload[0]))
|
||||
return pd_svdm(port, cnt, payload, rpayload);
|
||||
else
|
||||
return pd_custom_vdm(port, cnt, payload, rpayload);
|
||||
}
|
||||
|
||||
@@ -71,7 +71,7 @@ common-$(CONFIG_SW_CRC)+=crc.o
|
||||
common-$(CONFIG_TEMP_SENSOR)+=temp_sensor.o thermal.o throttle_ap.o
|
||||
common-$(CONFIG_USB_PORT_POWER_DUMB)+=usb_port_power_dumb.o
|
||||
common-$(CONFIG_USB_PORT_POWER_SMART)+=usb_port_power_smart.o
|
||||
common-$(CONFIG_USB_POWER_DELIVERY)+=usb_pd_protocol.o
|
||||
common-$(CONFIG_USB_POWER_DELIVERY)+=usb_pd_protocol.o usb_pd_policy.o
|
||||
common-$(CONFIG_VBOOT_HASH)+=sha256.o vboot_hash.o
|
||||
common-$(CONFIG_WIRELESS)+=wireless.o
|
||||
common-$(HAS_TASK_CHIPSET)+=chipset.o
|
||||
|
||||
294
common/usb_pd_policy.c
Normal file
294
common/usb_pd_policy.c
Normal file
@@ -0,0 +1,294 @@
|
||||
/* 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.
|
||||
*/
|
||||
#include "adc.h"
|
||||
#include "atomic.h"
|
||||
#include "common.h"
|
||||
#include "console.h"
|
||||
#include "gpio.h"
|
||||
#include "host_command.h"
|
||||
#include "registers.h"
|
||||
#include "task.h"
|
||||
#include "timer.h"
|
||||
#include "util.h"
|
||||
#include "usb_pd.h"
|
||||
#include "usb_pd_config.h"
|
||||
#include "version.h"
|
||||
|
||||
#ifdef CONFIG_USB_PD_ALT_MODE
|
||||
|
||||
#ifdef CONFIG_USB_PD_ALT_MODE_DFP
|
||||
|
||||
struct pd_policy pe[PD_PORT_COUNT];
|
||||
|
||||
static void pe_init(int port)
|
||||
{
|
||||
memset(pe, 0, sizeof(struct pd_policy) * PD_PORT_COUNT);
|
||||
}
|
||||
|
||||
static void dfp_consume_identity(int port, uint32_t *payload)
|
||||
{
|
||||
int ptype = PD_IDH_PTYPE(payload[VDO_I(IDH)]);
|
||||
pe_init(port);
|
||||
switch (ptype) {
|
||||
case IDH_PTYPE_AMA:
|
||||
/* TODO(tbroch) do I disable VBUS here if power contract
|
||||
* requested it
|
||||
*/
|
||||
if (!PD_VDO_AMA_VBUS_REQ(payload[VDO_I(AMA)]))
|
||||
pd_power_supply_reset(port);
|
||||
break;
|
||||
/* TODO(crosbug.com/p/30645) provide vconn support here */
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int dfp_discover_svids(int port, uint32_t *payload)
|
||||
{
|
||||
payload[0] = VDO(USB_SID_PD, 1, CMD_DISCOVER_SVID);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void dfp_consume_svids(int port, uint32_t *payload)
|
||||
{
|
||||
int i;
|
||||
uint32_t *ptr = payload + 1;
|
||||
uint16_t svid0, svid1;
|
||||
|
||||
for (i = pe[port].svid_cnt; i < pe[port].svid_cnt + 12; i += 2) {
|
||||
if (i == SVID_DISCOVERY_MAX) {
|
||||
ccprintf("ERR: too many svids discovered\n");
|
||||
break;
|
||||
}
|
||||
|
||||
svid0 = PD_VDO_SVID_SVID0(*ptr);
|
||||
if (!svid0)
|
||||
break;
|
||||
pe[port].svids[i].svid = svid0;
|
||||
pe[port].svid_cnt++;
|
||||
|
||||
svid1 = PD_VDO_SVID_SVID1(*ptr);
|
||||
if (!svid1)
|
||||
break;
|
||||
pe[port].svids[i + 1].svid = svid1;
|
||||
pe[port].svid_cnt++;
|
||||
ptr++;
|
||||
}
|
||||
/* TODO(tbroch) need to re-issue discover svids if > 12 */
|
||||
if (i && ((i % 12) == 0))
|
||||
ccprintf("TODO: need to re-issue discover svids > 12\n");
|
||||
}
|
||||
|
||||
static int dfp_discover_modes(int port, uint32_t *payload)
|
||||
{
|
||||
uint16_t svid = pe[port].svids[pe[port].svid_idx].svid;
|
||||
payload[0] = VDO(svid, 1, CMD_DISCOVER_MODES);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int dfp_consume_modes(int port, uint32_t *payload)
|
||||
{
|
||||
memcpy(pe[port].svids[pe[port].svid_idx].mode_vdo, &payload[1],
|
||||
sizeof(uint32_t) * PDO_MODES);
|
||||
pe[port].svid_idx++;
|
||||
return (pe[port].svid_idx < pe[port].svid_cnt);
|
||||
}
|
||||
|
||||
static int dfp_enter_modes(int port, uint32_t *payload)
|
||||
{
|
||||
struct svdm_amode_data *modep;
|
||||
if (pe[port].amodes == NULL)
|
||||
pd_dfp_choose_modes(&pe[port]);
|
||||
|
||||
modep = &pe[port].amodes[pe[port].amode_idx];
|
||||
if (modep->amode == dfp_amode_none)
|
||||
return 0;
|
||||
|
||||
modep->enter(*modep->mode_caps);
|
||||
payload[0] = VDO(modep->svid, 1,
|
||||
CMD_ENTER_MODE |
|
||||
VDO_OPOS(modep->amode));
|
||||
pe[port].amode_idx++;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int pd_exit_modes(int port, uint32_t *payload)
|
||||
{
|
||||
struct svdm_amode_data *modep;
|
||||
if (pe[port].amodes == NULL)
|
||||
return 0;
|
||||
|
||||
modep = &pe[port].amodes[pe[port].amode_idx];
|
||||
if (modep->amode == dfp_amode_none)
|
||||
return 1;
|
||||
|
||||
modep->exit();
|
||||
payload[0] = VDO(modep->svid, 1,
|
||||
CMD_EXIT_MODE |
|
||||
VDO_OPOS(modep->amode));
|
||||
pe[port].amode_idx++;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void dump_pe(int port)
|
||||
{
|
||||
int i, j;
|
||||
struct svdm_amode_data *modep = pe[port].amodes;
|
||||
|
||||
for (i = 0; i < pe[port].svid_cnt; i++) {
|
||||
ccprintf("SVID[%d]: %04x", i, pe[port].svids[i].svid);
|
||||
for (j = 0; j < (PDO_MAX_OBJECTS - 1); j++)
|
||||
ccprintf(" [%d] %08x", j,
|
||||
pe[port].svids[i].mode_vdo[j]);
|
||||
ccprintf("\n");
|
||||
}
|
||||
for (i = 0; i < pe[port].amode_cnt; i++) {
|
||||
ccprintf("MODE[%d]: svid:%04x mode:%d caps:%08x\n", i,
|
||||
modep->svid, modep->amode, *modep->mode_caps);
|
||||
modep++;
|
||||
}
|
||||
}
|
||||
|
||||
static int command_pe(int argc, char **argv)
|
||||
{
|
||||
int port;
|
||||
char *e;
|
||||
if (argc < 3)
|
||||
return EC_ERROR_PARAM_COUNT;
|
||||
/* command: pe <port> <subcmd> <args> */
|
||||
port = strtoi(argv[1], &e, 10);
|
||||
if (*e || port >= PD_PORT_COUNT)
|
||||
return EC_ERROR_PARAM2;
|
||||
if (!strncasecmp(argv[2], "dump", 4))
|
||||
dump_pe(port);
|
||||
|
||||
return EC_SUCCESS;
|
||||
}
|
||||
|
||||
DECLARE_CONSOLE_COMMAND(pe, command_pe,
|
||||
"<port> dump",
|
||||
"USB PE",
|
||||
NULL);
|
||||
|
||||
#endif /* CONFIG_USB_PD_ALT_MODE_DFP */
|
||||
|
||||
int pd_svdm(int port, int cnt, uint32_t *payload, uint32_t **rpayload)
|
||||
{
|
||||
int i;
|
||||
int cmd = PD_VDO_CMD(payload[0]);
|
||||
int cmd_type = PD_VDO_CMDT(payload[0]);
|
||||
|
||||
int rsize = 1; /* VDM header at a minimum */
|
||||
ccprintf("%T] SVDM/%d [%d] %08x", cnt, cmd, payload[0]);
|
||||
for (i = 1; i < cnt; i++)
|
||||
ccprintf(" %08x", payload[i]);
|
||||
ccprintf("\n");
|
||||
|
||||
payload[0] &= ~VDO_CMDT_MASK;
|
||||
*rpayload = payload;
|
||||
|
||||
if (cmd_type == CMDT_INIT) {
|
||||
switch (cmd) {
|
||||
case CMD_DISCOVER_IDENT:
|
||||
rsize = svdm_rsp.identity(port, payload);
|
||||
break;
|
||||
case CMD_DISCOVER_SVID:
|
||||
rsize = svdm_rsp.svids(port, payload);
|
||||
break;
|
||||
case CMD_DISCOVER_MODES:
|
||||
rsize = svdm_rsp.modes(port, payload);
|
||||
break;
|
||||
case CMD_ENTER_MODE:
|
||||
rsize = svdm_rsp.enter_mode(port, payload);
|
||||
break;
|
||||
case CMD_EXIT_MODE:
|
||||
rsize = svdm_rsp.exit_mode(port, payload);
|
||||
break;
|
||||
}
|
||||
if (rsize > 1)
|
||||
payload[0] |= VDO_CMDT(CMDT_RSP_ACK);
|
||||
else if (rsize == 1)
|
||||
payload[0] |= VDO_CMDT(CMDT_RSP_NAK);
|
||||
else {
|
||||
payload[0] |= VDO_CMDT(CMDT_RSP_BUSY);
|
||||
rsize = 1;
|
||||
}
|
||||
#ifdef CONFIG_USB_PD_ALT_MODE_DFP
|
||||
} else if (cmd_type == CMDT_RSP_ACK) {
|
||||
switch (cmd) {
|
||||
case CMD_DISCOVER_IDENT:
|
||||
dfp_consume_identity(port, payload);
|
||||
rsize = dfp_discover_svids(port, payload);
|
||||
break;
|
||||
case CMD_DISCOVER_SVID:
|
||||
dfp_consume_svids(port, payload);
|
||||
rsize = dfp_discover_modes(port, payload);
|
||||
break;
|
||||
case CMD_DISCOVER_MODES:
|
||||
if (dfp_consume_modes(port, payload))
|
||||
rsize = dfp_discover_modes(port, payload);
|
||||
else
|
||||
rsize = dfp_enter_modes(port, payload);
|
||||
break;
|
||||
case CMD_ENTER_MODE:
|
||||
rsize = dfp_enter_modes(port, payload);
|
||||
case CMD_EXIT_MODE:
|
||||
rsize = pd_exit_modes(port, payload);
|
||||
break;
|
||||
}
|
||||
payload[0] &= ~VDO_CMDT(0);
|
||||
payload[0] |= VDO_CMDT(CMDT_INIT);
|
||||
} else if (cmd_type == CMDT_RSP_BUSY) {
|
||||
switch (cmd) {
|
||||
case CMD_DISCOVER_IDENT:
|
||||
case CMD_DISCOVER_SVID:
|
||||
case CMD_DISCOVER_MODES:
|
||||
/* resend if its discovery */
|
||||
payload[0] &= ~VDO_CMDT(0);
|
||||
payload[0] |= VDO_CMDT(CMDT_INIT);
|
||||
rsize = 1;
|
||||
break;
|
||||
case CMD_ENTER_MODE:
|
||||
/* Error */
|
||||
ccprintf("PE ERR: received BUSY for Enter mode\n");
|
||||
rsize = 0;
|
||||
break;
|
||||
case CMD_EXIT_MODE:
|
||||
rsize = 0;
|
||||
break;
|
||||
}
|
||||
} else if (cmd_type == CMDT_RSP_NAK) {
|
||||
/* nothing to do */
|
||||
rsize = 0;
|
||||
#endif /* CONFIG_USB_PD_ALT_MODE_DFP */
|
||||
} else {
|
||||
ccprintf("PE ERR: unknown cmd type %d\n", cmd);
|
||||
}
|
||||
ccprintf("%T] DONE\n");
|
||||
return rsize;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
int pd_svdm(int port, int cnt, uint32_t *payload, uint32_t **rpayload)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_USB_PD_ALT_MODE */
|
||||
|
||||
#ifndef CONFIG_USB_PD_CUSTOM_VDM
|
||||
int pd_vdm(int port, int cnt, uint32_t *payload, uint32_t **rpayload)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif /* !CONFIG_USB_PD_CUSTOM_VDM */
|
||||
|
||||
#ifndef CONFIG_USB_PD_ALT_MODE_DFP
|
||||
int pd_exit_modes(int port, uint32_t *payload)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif /* !CONFIG_USB_PD_ALT_MODE_DFP */
|
||||
@@ -151,6 +151,7 @@ static const uint8_t dec4b5b[] = {
|
||||
#define CC_RA(cc) (cc < PD_SRC_RD_THRESHOLD)
|
||||
#define CC_RD(cc) ((cc > PD_SRC_RD_THRESHOLD) && (cc < PD_SRC_VNC))
|
||||
#define GET_POLARITY(cc1, cc2) (CC_RD(cc2) || CC_RA(cc1))
|
||||
#define IS_CABLE(cc1, cc2) (CC_RD(cc1) || CC_RD(cc2))
|
||||
|
||||
/* PD counter definitions */
|
||||
#define PD_MESSAGE_ID_COUNT 7
|
||||
@@ -619,29 +620,23 @@ static void bist_mode_2_rx(int port)
|
||||
|
||||
static void handle_vdm_request(int port, int cnt, uint32_t *payload)
|
||||
{
|
||||
uint16_t vid = PD_VDO_VID(payload[0]);
|
||||
#ifdef CONFIG_USB_PD_CUSTOM_VDM
|
||||
int rlen;
|
||||
int rlen = 0;
|
||||
uint32_t *rdata;
|
||||
#endif
|
||||
|
||||
if (vid == USB_VID_GOOGLE) {
|
||||
if (pd[port].vdm_state == VDM_STATE_BUSY)
|
||||
pd[port].vdm_state = VDM_STATE_DONE;
|
||||
#ifdef CONFIG_USB_PD_CUSTOM_VDM
|
||||
rlen = pd_custom_vdm(port, cnt, payload, &rdata);
|
||||
if (rlen > 0) {
|
||||
uint16_t header = PD_HEADER(PD_DATA_VENDOR_DEF,
|
||||
pd[port].role, pd[port].msg_id,
|
||||
rlen);
|
||||
send_validate_message(port, header, rlen, rdata);
|
||||
}
|
||||
#endif
|
||||
if (pd[port].vdm_state == VDM_STATE_BUSY)
|
||||
pd[port].vdm_state = VDM_STATE_DONE;
|
||||
|
||||
rlen = pd_vdm(port, cnt, payload, &rdata);
|
||||
if (rlen > 0) {
|
||||
uint16_t header = PD_HEADER(PD_DATA_VENDOR_DEF,
|
||||
pd[port].role, pd[port].msg_id,
|
||||
rlen);
|
||||
send_validate_message(port, header, rlen, rdata);
|
||||
return;
|
||||
}
|
||||
if (debug_level >= 1)
|
||||
CPRINTF("Unhandled VDM VID %04x CMD %04x\n",
|
||||
vid, payload[0] & 0xFFFF);
|
||||
PD_VDO_VID(payload[0]), payload[0] & 0xFFFF);
|
||||
}
|
||||
|
||||
static void execute_hard_reset(int port)
|
||||
@@ -1027,7 +1022,7 @@ void pd_send_vdm(int port, uint32_t vid, int cmd, const uint32_t *data,
|
||||
return;
|
||||
}
|
||||
|
||||
pd[port].vdo_data[0] = VDO(vid, cmd);
|
||||
pd[port].vdo_data[0] = VDO(vid, (vid == USB_SID_PD) ? 1 : 0, cmd);
|
||||
pd[port].vdo_count = count + 1;
|
||||
for (i = 1; i < count + 1; i++)
|
||||
pd[port].vdo_data[i] = data[i-1];
|
||||
@@ -1319,20 +1314,23 @@ void pd_task(void)
|
||||
}
|
||||
break;
|
||||
case PD_STATE_SRC_READY:
|
||||
#ifdef CONFIG_USB_PD_SIMPLE_DFP
|
||||
/*
|
||||
* For simple devices that don't support alternate
|
||||
* mode and are only sources (ie power adapters),
|
||||
* send custom VDM with info about this device
|
||||
* once power contract has been negotiated.
|
||||
*/
|
||||
if (pd[port].last_state != pd[port].task_state) {
|
||||
/* Send google VDM to read info */
|
||||
#ifdef CONFIG_USB_PD_SIMPLE_DFP
|
||||
/*
|
||||
* For simple devices that don't support
|
||||
* alternate mode and are only sources (ie power
|
||||
* adapters), send custom VDM with info about
|
||||
* this device once power contract has been
|
||||
* negotiated.
|
||||
*/
|
||||
pd_send_vdm(port, USB_VID_GOOGLE,
|
||||
VDO_CMD_SEND_INFO,
|
||||
pd_get_info(), 6);
|
||||
}
|
||||
#else
|
||||
pd_send_vdm(port, USB_SID_PD,
|
||||
CMD_DISCOVER_IDENT, NULL, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!pd[port].ping_enabled) {
|
||||
timeout = PD_T_SOURCE_ACTIVITY;
|
||||
@@ -1443,6 +1441,7 @@ void pd_task(void)
|
||||
PD_STATE_HARD_RESET);
|
||||
break;
|
||||
case PD_STATE_HARD_RESET:
|
||||
pd_exit_modes(port, payload);
|
||||
send_hard_reset(port);
|
||||
/* reset our own state machine */
|
||||
execute_hard_reset(port);
|
||||
@@ -1797,8 +1796,10 @@ static int command_pd(int argc, char **argv)
|
||||
} else if (!strncasecmp(argv[2], "state", 5)) {
|
||||
const char * const state_names[] = {
|
||||
"DISABLED", "SUSPENDED",
|
||||
#ifdef CONFIG_USB_PD_DUAL_ROLE
|
||||
"SNK_DISCONNECTED", "SNK_DISCOVERY", "SNK_REQUESTED",
|
||||
"SNK_TRANSITION", "SNK_READY",
|
||||
#endif /* CONFIG_USB_PD_DUAL_ROLE */
|
||||
"SRC_DISCONNECTED", "SRC_DISCOVERY", "SRC_NEGOCIATE",
|
||||
"SRC_ACCEPTED", "SRC_TRANSITION", "SRC_READY",
|
||||
"SOFT_RESET", "HARD_RESET", "BIST",
|
||||
|
||||
@@ -1001,6 +1001,12 @@
|
||||
/* Default state of PD communication enabled flag */
|
||||
#define CONFIG_USB_PD_COMM_ENABLED 1
|
||||
|
||||
/* Support for USB PD alternate mode */
|
||||
#undef CONFIG_USB_PD_ALT_MODE
|
||||
|
||||
/* Support for USB PD alternate mode of Downward Facing Port */
|
||||
#undef CONFIG_USB_PD_ALT_MODE_DFP
|
||||
|
||||
/* Respond to custom vendor-defined messages over PD */
|
||||
#undef CONFIG_USB_PD_CUSTOM_VDM
|
||||
|
||||
@@ -1013,6 +1019,10 @@
|
||||
/* Check whether PD is the sole power source before flash erase operation */
|
||||
#undef CONFIG_USB_PD_FLASH_ERASE_CHECK
|
||||
|
||||
/* HW & SW version for alternate mode discover identity response (4bits each) */
|
||||
#undef CONFIG_USB_PD_IDENTITY_HW_ID
|
||||
#undef CONFIG_USB_PD_IDENTITY_SW_ID
|
||||
|
||||
/* USB PD MCU slave address for host commands */
|
||||
#define CONFIG_USB_PD_I2C_SLAVE_ADDR 0x3c
|
||||
|
||||
|
||||
299
include/usb_pd.h
299
include/usb_pd.h
@@ -22,6 +22,7 @@ enum pd_errors {
|
||||
|
||||
/* --- PD data message helpers --- */
|
||||
#define PDO_MAX_OBJECTS 7
|
||||
#define PDO_MODES (PDO_MAX_OBJECTS - 1)
|
||||
|
||||
/* PDO : Power Data Object */
|
||||
/*
|
||||
@@ -102,22 +103,106 @@ enum pd_errors {
|
||||
|
||||
#define BDO(mode, cnt) ((mode) | ((cnt) & 0xFFFF))
|
||||
|
||||
/* VDO : Vendor Defined Message Object */
|
||||
#define VDO(vid, custom) (((vid) << 16) | ((custom) & 0xFFFF))
|
||||
/* TODO(tbroch) is there a finite number for these in the spec */
|
||||
#define SVID_DISCOVERY_MAX 16
|
||||
|
||||
/* function table for alternate mode capable responders */
|
||||
struct svdm_response {
|
||||
int (*identity)(int port, uint32_t *payload);
|
||||
int (*svids)(int port, uint32_t *payload);
|
||||
int (*modes)(int port, uint32_t *payload);
|
||||
int (*enter_mode)(int port, uint32_t *payload);
|
||||
int (*exit_mode)(int port, uint32_t *payload);
|
||||
};
|
||||
|
||||
/* defined in <board>/usb_pd_policy.c */
|
||||
extern const struct svdm_response svdm_rsp;
|
||||
|
||||
/* Each SVID is allowed to have 6 modes */
|
||||
enum dfp_amode {
|
||||
dfp_amode_none = 0,
|
||||
dfp_amode1,
|
||||
dfp_amode2,
|
||||
dfp_amode3,
|
||||
dfp_amode4,
|
||||
dfp_amode5,
|
||||
dfp_amode6,
|
||||
};
|
||||
|
||||
struct svdm_svid_data {
|
||||
uint16_t svid;
|
||||
uint32_t mode_vdo[PDO_MODES];
|
||||
};
|
||||
|
||||
struct svdm_amode_data {
|
||||
uint16_t svid;
|
||||
enum dfp_amode amode;
|
||||
uint32_t *mode_caps;
|
||||
void (*enter)(uint32_t mode_caps);
|
||||
void (*exit)(void);
|
||||
};
|
||||
|
||||
/* Policy structure for driving alternate mode */
|
||||
struct pd_policy {
|
||||
/* index of svid currently being operated on */
|
||||
int svid_idx;
|
||||
/* count of svids discovered */
|
||||
int svid_cnt;
|
||||
/* supported svids & corresponding vdo mode data */
|
||||
struct svdm_svid_data svids[SVID_DISCOVERY_MAX];
|
||||
/* index of amode currently being operated on */
|
||||
int amode_idx;
|
||||
/* count of amodes discovered */
|
||||
int amode_cnt;
|
||||
/* supported amodes */
|
||||
struct svdm_amode_data *amodes;
|
||||
};
|
||||
|
||||
/*
|
||||
* VDO : Vendor Defined Message Object
|
||||
* VDM object is minimum of VDM header + 6 additional data objects.
|
||||
*/
|
||||
|
||||
/*
|
||||
* VDM header
|
||||
* ----------
|
||||
* <31:16> :: SVID
|
||||
* <15> :: VDM type ( 1b == structured, 0b == unstructured )
|
||||
* <14:13> :: Structured VDM version
|
||||
* <12:11> :: reserved
|
||||
* <10:8> :: object position (1-7 valid ... used for enter/exit mode only)
|
||||
* <7:6> :: command type (SVDM only?)
|
||||
* <5> :: reserved (SVDM), command type (UVDM)
|
||||
* <4:0> :: command
|
||||
*/
|
||||
#define VDO_MAX_SIZE 7
|
||||
#define VDO(vid, type, custom) \
|
||||
(((vid) << 16) | \
|
||||
((type) << 15) | \
|
||||
((custom) & 0x7FFF))
|
||||
|
||||
#define VDO_ACK (0 << 6)
|
||||
#define VDO_NAK (1 << 6)
|
||||
#define VDO_PENDING (2 << 6)
|
||||
#define VDO_SVDM_TYPE (1 << 15)
|
||||
#define VDO_SVDM_VERS(x) (x << 13)
|
||||
#define VDO_OPOS(x) (x << 8)
|
||||
#define VDO_CMDT(x) (x << 6)
|
||||
#define VDO_CMDT_MASK VDO_CMDT(0x3)
|
||||
|
||||
#define CMDT_INIT 0
|
||||
#define CMDT_RSP_NAK 1
|
||||
#define CMDT_RSP_ACK 2
|
||||
#define CMDT_RSP_BUSY 3
|
||||
|
||||
|
||||
/* reserved for SVDM ... for Google UVDM */
|
||||
#define VDO_SRC_INITIATOR (0 << 5)
|
||||
#define VDO_SRC_RESPONDER (1 << 5)
|
||||
|
||||
#define VDO_CMD_DISCOVER_VID (1 << 0)
|
||||
#define VDO_CMD_DISCOVER_ALT (2 << 0)
|
||||
#define VDO_CMD_AUTHENTICATE (3 << 0)
|
||||
#define VDO_CMD_ENTER_ALT (4 << 0)
|
||||
#define VDO_CMD_EXIT_ALT (5 << 0)
|
||||
#define CMD_DISCOVER_IDENT 1
|
||||
#define CMD_DISCOVER_SVID 2
|
||||
#define CMD_DISCOVER_MODES 3
|
||||
#define CMD_ENTER_MODE 4
|
||||
#define CMD_EXIT_MODE 5
|
||||
#define CMD_ATTENTION 6
|
||||
#define VDO_CMD_VENDOR(x) (((10 + (x)) & 0x1f))
|
||||
|
||||
/* ChromeOS specific commands */
|
||||
@@ -131,8 +216,164 @@ enum pd_errors {
|
||||
#define VDO_CMD_PING_ENABLE VDO_CMD_VENDOR(10)
|
||||
#define VDO_CMD_CURRENT VDO_CMD_VENDOR(11)
|
||||
|
||||
#define PD_VDO_VID(vdo) ((vdo) >> 16)
|
||||
#define PD_VDO_CMD(vdo) ((vdo) & 0x1f)
|
||||
#define PD_VDO_VID(vdo) ((vdo) >> 16)
|
||||
#define PD_VDO_SVDM(vdo) (((vdo) >> 15) & 1)
|
||||
#define PD_VDO_OPOS(vdo) (((vdo) >> 8) & 0x7)
|
||||
#define PD_VDO_CMD(vdo) ((vdo) & 0x1f)
|
||||
#define PD_VDO_CMDT(vdo) (((vdo) >> 6) & 0x3)
|
||||
|
||||
/*
|
||||
* SVDM Identity request -> response
|
||||
*
|
||||
* Request is simply properly formatted SVDM header
|
||||
*
|
||||
* Response is 4 data objects:
|
||||
* [0] :: SVDM header
|
||||
* [1] :: Identitiy header
|
||||
* [2] :: Cert Stat VDO
|
||||
* [3] :: (Product | Cable | AMA) VDO
|
||||
*
|
||||
*/
|
||||
#define VDO_INDEX_HDR 0
|
||||
#define VDO_INDEX_IDH 1
|
||||
#define VDO_INDEX_CSTAT 2
|
||||
#define VDO_INDEX_CABLE 3
|
||||
#define VDO_INDEX_AMA 3
|
||||
#define VDO_I(name) VDO_INDEX_##name
|
||||
|
||||
/*
|
||||
* SVDM Identity Header
|
||||
* --------------------
|
||||
* <31> :: data capable as a USB host
|
||||
* <30> :: data capable as a USB device
|
||||
* <29:27> :: product type
|
||||
* <26> :: modal operation supported (1b == yes)
|
||||
* <25:16> :: SBZ
|
||||
* <15:0> :: USB-IF assigned VID for this cable vendor
|
||||
*/
|
||||
#define IDH_PTYPE_UNDEF 0
|
||||
#define IDH_PTYPE_HUB 1
|
||||
#define IDH_PTYPE_PERIPH 2
|
||||
#define IDH_PTYPE_ACABLE 4
|
||||
#define IDH_PTYPE_PCABLE 5
|
||||
#define IDH_PTYPE_AMA 6
|
||||
|
||||
#define VDO_IDH(usbh, usbd, ptype, is_modal, vid) \
|
||||
((usbh) << 31 | (usbd) << 30 | ((ptype) & 0x7) << 27 \
|
||||
| (is_modal) << 26 | ((vid) & 0xffff))
|
||||
|
||||
#define PD_IDH_PTYPE(vdo) (((vdo) >> 27) & 0x7)
|
||||
#define PD_IDH_VID(vdo) ((vdo) & 0xffff)
|
||||
|
||||
/*
|
||||
* Cert Stat VDO
|
||||
* -------------
|
||||
* <31:20> : SBZ
|
||||
* <19:0> : USB-IF assigned TID for this cable
|
||||
*/
|
||||
#define VDO_CSTAT(tid) ((tid) & 0xfffff)
|
||||
#define PD_CSTAT_TID(vdo) ((vdo) & 0xfffff)
|
||||
|
||||
/*
|
||||
* Cable VDO
|
||||
* ---------
|
||||
* <31:28> :: Cable HW version
|
||||
* <27:24> :: Cable FW version
|
||||
* <23:20> :: SBZ
|
||||
* <19:18> :: type-C to Type-A/B/C (00b == A, 01 == B, 10 == C)
|
||||
* <17> :: Type-C to Plug/Receptacle (0b == plug, 1b == receptacle)
|
||||
* <16:13> :: cable latency (0001 == <10ns(~1m length))
|
||||
* <12:11> :: cable termination type (11b == both ends active VCONN req)
|
||||
* <10> :: SSTX1 Directionality support (0b == fixed, 1b == cfgable)
|
||||
* <9> :: SSTX2 Directionality support
|
||||
* <8> :: SSRX1 Directionality support
|
||||
* <7> :: SSRX2 Directionality support
|
||||
* <6:5> :: Vbus current handling capability
|
||||
* <4> :: Vbus through cable (0b == no, 1b == yes)
|
||||
* <3> :: SOP" controller present? (0b == no, 1b == yes)
|
||||
* <2:0> :: USB SS Signaling support
|
||||
*/
|
||||
#define CABLE_ATYPE 0
|
||||
#define CABLE_BTYPE 1
|
||||
#define CABLE_CTYPE 2
|
||||
#define CABLE_PLUG 0
|
||||
#define CABLE_RECEPTACLE 1
|
||||
#define VDO_CABLE(hw, fw, cbl, gdr, lat, term, tx1d, tx2d, rx1d, rx2d, cur, vps, sopp, usbss) \
|
||||
(((hw) & 0x7) << 28 | ((fw) & 0x7) << 24 | ((cbl) & 0x3) << 18 \
|
||||
| (gdr) << 17 | ((lat) & 0x7) << 13 | ((term) & 0x3) << 11 \
|
||||
| (tx1d) << 10 | (tx2d) << 9 | (rx1d) << 8 | (rx2d) << 7 \
|
||||
| ((cur) & 0x3) << 5 | (vps) << 4 | (sopp) << 3 \
|
||||
| ((usbss) & 0x7))
|
||||
|
||||
/*
|
||||
* AMA VDO
|
||||
* ---------
|
||||
* <31:28> :: Cable HW version
|
||||
* <27:24> :: Cable FW version
|
||||
* <23:12> :: SBZ
|
||||
* <11> :: SSTX1 Directionality support (0b == fixed, 1b == cfgable)
|
||||
* <10> :: SSTX2 Directionality support
|
||||
* <9> :: SSRX1 Directionality support
|
||||
* <8> :: SSRX2 Directionality support
|
||||
* <7:5> :: Vconn power
|
||||
* <4> :: Vconn power required
|
||||
* <3> :: Vbus power required
|
||||
* <2:0> :: USB SS Signaling support
|
||||
*/
|
||||
#define VDO_AMA(hw, fw, tx1d, tx2d, rx1d, rx2d, vcpwr, vcr, vbr, usbss) \
|
||||
(((hw) & 0x7) << 28 | ((fw) & 0x7) << 24 \
|
||||
| (tx1d) << 11 | (tx2d) << 10 | (rx1d) << 9 | (rx2d) << 8 \
|
||||
| ((vcpwr) & 0x3) << 5 | (vcr) << 4 | (vbr) << 3 \
|
||||
| ((usbss) & 0x7))
|
||||
|
||||
#define PD_VDO_AMA_VCONN_REQ(vdo) (((vdo) >> 4) & 1)
|
||||
#define PD_VDO_AMA_VBUS_REQ(vdo) (((vdo) >> 3) & 1)
|
||||
|
||||
/*
|
||||
* SVDM Discover SVIDs request -> response
|
||||
*
|
||||
* Request is properly formatted VDM Header with discover SVIDs command.
|
||||
* Response is a set of SVIDs of all all supported SVIDs with all zero's to
|
||||
* mark the end of SVIDs. If more than 12 SVIDs are supported command SHOULD be
|
||||
* repeated.
|
||||
*/
|
||||
#define VDO_SVID(svid0, svid1) (((svid0) & 0xffff) << 16 | ((svid1) & 0xffff))
|
||||
#define PD_VDO_SVID_SVID0(vdo) ((vdo) >> 16)
|
||||
#define PD_VDO_SVID_SVID1(vdo) ((vdo) & 0xffff)
|
||||
|
||||
/*
|
||||
* Mode Capabilities
|
||||
*
|
||||
* Number of VDOs supplied is SID dependent (but <= 6 VDOS?)
|
||||
*/
|
||||
#define VDO_MODE_CNT_DISPLAYPORT 1
|
||||
|
||||
/*
|
||||
* DisplayPort modes capabilities
|
||||
* -------------------------------
|
||||
* <31:24> : SBZ
|
||||
* <23:16> : sink pin assignment supported
|
||||
* <15:8> : source pin assignment supported
|
||||
* <7> : USB 2.0 signaling (0b=yes, 1b=no)
|
||||
* <6> : Plug | Receptacle (0b == plug, 1b == receptacle)
|
||||
* <5:3> : USB Gen 2 signaling for DP (000b=no, 001b=yes, rest=rsv)
|
||||
* <2> : supports dp1.3
|
||||
* <1:0> : signal direction ( 00b=rsv, 01b=sink, 10b=src 11b=both )
|
||||
*/
|
||||
#define VDO_MODE_DP(snkp, srcp, usb, gdr, usbdp, dp3, sdir) \
|
||||
(((snkp) & 0xff) << 16 | ((srcp) & 0xff) << 8 \
|
||||
| ((usb) & 1) << 7 | ((gdr) & 1) << 6 | ((usbdp) & 0x7) << 3 \
|
||||
| ((dp3) & 1) << 2 | ((sdir) & 0x3))
|
||||
|
||||
#define MODE_DP_PIN_A 0x01
|
||||
#define MODE_DP_PIN_B 0x02
|
||||
#define MODE_DP_PIN_C 0x04
|
||||
#define MODE_DP_PIN_D 0x08
|
||||
#define MODE_DP_PIN_E 0x10
|
||||
|
||||
#define MODE_DP_SNK 0x1
|
||||
#define MODE_DP_SRC 0x2
|
||||
#define MODE_DP_BOTH 0x3
|
||||
|
||||
/*
|
||||
* ChromeOS specific PD device Hardware IDs. Used to identify unique
|
||||
@@ -158,6 +399,9 @@ enum pd_errors {
|
||||
#define VDO_INFO_SW_DBG_VER(x) (((x) >> 1) & 0x7fff)
|
||||
#define VDO_INFO_IS_RW(x) ((x) & 1)
|
||||
|
||||
/* USB-IF SIDs */
|
||||
#define USB_SID_PD 0xff00 /* power delivery */
|
||||
#define USB_SID_DISPLAYPORT 0xff01
|
||||
/* USB Vendor ID assigned to Google Inc. */
|
||||
#define USB_VID_GOOGLE 0x18d1
|
||||
|
||||
@@ -337,7 +581,7 @@ int pd_board_checks(void);
|
||||
uint32_t *pd_get_info(void);
|
||||
|
||||
/**
|
||||
* Handle Vendor Defined Message with our vendor ID.
|
||||
* Handle Vendor Defined Messages
|
||||
*
|
||||
* @param port USB-C port number
|
||||
* @param cnt number of data objects in the payload.
|
||||
@@ -345,7 +589,34 @@ uint32_t *pd_get_info(void);
|
||||
* @param rpayload pointer to the data to send back.
|
||||
* @return if >0, number of VDOs to send back.
|
||||
*/
|
||||
int pd_custom_vdm(int port, int cnt, uint32_t *payload, uint32_t **rpayload);
|
||||
int pd_vdm(int port, int cnt, uint32_t *payload, uint32_t **rpayload);
|
||||
|
||||
/**
|
||||
* Handle Structured Vendor Defined Messages
|
||||
*
|
||||
* @param port USB-C port number
|
||||
* @param cnt number of data objects in the payload.
|
||||
* @param payload payload data.
|
||||
* @param rpayload pointer to the data to send back.
|
||||
* @return if >0, number of VDOs to send back.
|
||||
*/
|
||||
int pd_svdm(int port, int cnt, uint32_t *payload, uint32_t **rpayload);
|
||||
|
||||
/**
|
||||
* Choose appropriate alternate modes.
|
||||
*
|
||||
* @param pe pd_policy data structure
|
||||
*/
|
||||
void pd_dfp_choose_modes(struct pd_policy *pe);
|
||||
|
||||
/**
|
||||
* Exit alternate mode
|
||||
*
|
||||
* @param port USB-C port number
|
||||
* @param payload payload data.
|
||||
* @return if >0, number of VDOs to send back.
|
||||
*/
|
||||
int pd_exit_modes(int port, uint32_t *payload);
|
||||
|
||||
/**
|
||||
* Store Device ID & RW hash of device
|
||||
|
||||
@@ -49,6 +49,11 @@ void pd_select_polarity(int port, int polarity)
|
||||
pd_port[port].polarity = polarity;
|
||||
}
|
||||
|
||||
int pd_vdm(int port, int cnt, uint32_t *payload, uint32_t **rpayload)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Tests */
|
||||
|
||||
void inc_tx_id(int port)
|
||||
|
||||
Reference in New Issue
Block a user