DM USB: xHCI: Support APL extended capability for DRD.
This patch implements Intel ApolloLake xHCI extended capabilities. It includes two dual role switch registers for switching shared USB2&USB3 phys between xHCI and xDCI. Change-Id: I2533537d8a4224da3cf9b2e7475aab9f65347a4a Signed-off-by: Liang Yang <liang3.yang@intel.com> Reviewed-by: Xiaoguang Wu <xiaoguang.wu@intel.com> Reviewed-by: Yu Wang <yu1.wang@intel.com> Reviewed-by: Kevin Tian <kevin.tian@intel.com>
This commit is contained in:
parent
1687765371
commit
0679a81972
|
@ -30,11 +30,58 @@
|
|||
* devices:
|
||||
* tablet USB tablet mouse
|
||||
*/
|
||||
|
||||
/*
|
||||
* xHCI DRD control flow digram.
|
||||
* +---------------------------+
|
||||
* | ACRN DM |
|
||||
* | +---------------------+ |
|
||||
* | | xhci emulator | |
|
||||
* | | | |
|
||||
* | | +---------------+ | |
|
||||
* | | | drd emulator |<----------+ +----------------------+
|
||||
* | | +---------------+ | | | | app |
|
||||
* | +---------|-----------+ | | +----------------------+
|
||||
* +------------|--------------+ | echo H or D |
|
||||
* | SOS USER SPACE | | UOS USER SPACE
|
||||
* -------------|--------------------|-------------|-----------------
|
||||
* v SOS KERNEL SPACE | v UOS KERNEL SPACE
|
||||
* +------------------------------+ | +--------------------------+
|
||||
* | native drd sysfs interface | | |native drd sysfs interface|
|
||||
* +------------------------------+ | +--------------------------+
|
||||
* | | |
|
||||
* v | v
|
||||
* +------------------------+ | +----------------------+
|
||||
* | natvie drd driver | +----| native drd driver |
|
||||
* +------------------------+ +----------------------+
|
||||
* |
|
||||
* -------------|---------------------------------------------------
|
||||
* HARDWARE |
|
||||
* +------------|----------+
|
||||
* |xHCI v | +-----------+
|
||||
* | +----------------+ | | xDCI |
|
||||
* | | switch control | | +-----------+
|
||||
* | +-------+--------+ | |
|
||||
* +-----------+-----------+ |
|
||||
* | | |
|
||||
* | +----+---------+
|
||||
* | |
|
||||
* | +------+------+
|
||||
* +-----| PHY MUX |
|
||||
* +---+-----+---+
|
||||
* | |
|
||||
* +---+ +---+
|
||||
* +---+----+ +----+---+
|
||||
* |USB2 PHY| |USB3 PHY|
|
||||
* +--------+ +--------+
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/uio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/queue.h>
|
||||
#include <sys/fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
@ -216,6 +263,13 @@ struct pci_xhci_excap_ptr {
|
|||
uint8_t cap_ptr;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct pci_xhci_excap_drd_apl {
|
||||
struct pci_xhci_excap_ptr excap_ptr;
|
||||
uint8_t padding[102]; /* Followed native xHCI MMIO layout */
|
||||
uint32_t drdcfg0;
|
||||
uint32_t drdcfg1;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct pci_xhci_excap_prot {
|
||||
struct pci_xhci_excap_ptr excap_ptr;
|
||||
uint8_t rev_min;
|
||||
|
@ -244,6 +298,25 @@ static DEFINE_EXCP_PROT(u3_prot,
|
|||
1,
|
||||
XHCI_MAX_DEVS/2);
|
||||
|
||||
static DEFINE_EXCP_VENDOR_DRD(XHCI_ID_DRD_INTEL,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00);
|
||||
|
||||
/*
|
||||
* Extended capabilities layout of APL platform.
|
||||
* excap start excap end register value
|
||||
* 0x8000 0x8010 0x02000802
|
||||
* 0x8020 0x8030 0x03001402
|
||||
* 0x8070 0x80E0 0x000000C0
|
||||
*/
|
||||
struct pci_xhci_excap excap_group_apl[] = {
|
||||
{0x8000, 0x8010, &excap_u2_prot},
|
||||
{0x8020, 0x8030, &excap_u3_prot},
|
||||
{0x8070, 0x80E0, &excap_drd_apl},
|
||||
{EXCAP_GROUP_END, EXCAP_GROUP_END, EXCAP_GROUP_NULL}
|
||||
};
|
||||
|
||||
/*
|
||||
* default xhci extended capabilities
|
||||
* excap start excap end register value
|
||||
|
@ -302,6 +375,7 @@ struct pci_xhci_vdev {
|
|||
int ndevices;
|
||||
|
||||
void *excap_ptr;
|
||||
int (*excap_write)(struct pci_xhci_vdev *, uint64_t, uint64_t);
|
||||
int usb2_port_start;
|
||||
int usb3_port_start;
|
||||
uint8_t *native_assign_ports[USB_NATIVE_NUM_BUS];
|
||||
|
@ -958,15 +1032,88 @@ pci_xhci_portregs_write(struct pci_xhci_vdev *xdev,
|
|||
}
|
||||
}
|
||||
|
||||
static int
|
||||
pci_xhci_apl_drdregs_write(struct pci_xhci_vdev *xdev, uint64_t offset,
|
||||
uint64_t value)
|
||||
{
|
||||
int rc = 0, fd;
|
||||
uint32_t drdcfg0 = 0, drdcfg1 = 0;
|
||||
struct pci_xhci_excap *excap;
|
||||
struct pci_xhci_excap_drd_apl *excap_drd;
|
||||
|
||||
assert(xdev);
|
||||
|
||||
excap = xdev->excap_ptr;
|
||||
|
||||
while (excap && excap->start != XHCI_APL_DRDCAP_BASE)
|
||||
excap++;
|
||||
|
||||
if (!excap || !excap->data || excap->start != XHCI_APL_DRDCAP_BASE) {
|
||||
UPRINTF(LWRN, "drd extended capability can't be found\r\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
excap_drd = excap->data;
|
||||
|
||||
offset -= XHCI_APL_DRDREGS_BASE;
|
||||
if (offset == XHCI_DRD_MUX_CFG0) {
|
||||
fd = open(XHCI_NATIVE_DRD_SWITCH_PATH, O_WRONLY);
|
||||
if (fd == -1) {
|
||||
UPRINTF(LWRN, "drd native interface open failed\r\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (value & XHCI_DRD_CFG0_HOST_MODE)
|
||||
rc = write(fd, XHCI_NATIVE_DRD_HOST_MODE,
|
||||
XHCI_NATIVE_DRD_WRITE_SZ);
|
||||
else if (value & XHCI_DRD_CFG0_DEV_MODE)
|
||||
rc = write(fd, XHCI_NATIVE_DRD_DEV_MODE,
|
||||
XHCI_NATIVE_DRD_WRITE_SZ);
|
||||
|
||||
if (rc == XHCI_NATIVE_DRD_WRITE_SZ) {
|
||||
if (value & XHCI_DRD_CFG0_HOST_MODE) {
|
||||
drdcfg1 |= XHCI_DRD_CFG1_HOST_MODE;
|
||||
drdcfg0 &= ~XHCI_DRD_CFG0_IDPIN;
|
||||
drdcfg0 &= ~XHCI_DRD_CFG0_VBUS_VALID;
|
||||
} else if (value & XHCI_DRD_CFG0_DEV_MODE) {
|
||||
drdcfg1 &= ~XHCI_DRD_CFG1_HOST_MODE;
|
||||
drdcfg0 |= XHCI_DRD_CFG0_IDPIN;
|
||||
drdcfg0 |= XHCI_DRD_CFG0_VBUS_VALID;
|
||||
}
|
||||
drdcfg0 |= XHCI_DRD_CFG0_IDPIN_EN;
|
||||
excap_drd->drdcfg0 = drdcfg0;
|
||||
excap_drd->drdcfg1 = drdcfg1;
|
||||
} else {
|
||||
UPRINTF(LWRN, "drd native inferface write failed, "
|
||||
"returned %d.\r\n", rc);
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
} else if (offset == XHCI_DRD_MUX_CFG1) {
|
||||
UPRINTF(LWRN, "write to RO register, offset 0x%lx\r\n", offset);
|
||||
return -1;
|
||||
} else
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
pci_xhci_excap_write(struct pci_xhci_vdev *xdev, uint64_t offset,
|
||||
uint64_t value)
|
||||
{
|
||||
/* TODO: The default extended capabilities are readonly. Need implement
|
||||
* related write operations once writable capabilities get supported in
|
||||
* future.
|
||||
*/
|
||||
UPRINTF(LWRN, "write invalid offset 0x%lx\r\n", offset);
|
||||
int rc = 0;
|
||||
|
||||
assert(xdev);
|
||||
|
||||
if (xdev->excap_ptr && xdev->excap_write)
|
||||
rc = xdev->excap_write(xdev, offset, value);
|
||||
else
|
||||
rc = -1;
|
||||
|
||||
if (rc)
|
||||
UPRINTF(LWRN, "write invalid offset 0x%lx\r\n", offset);
|
||||
|
||||
}
|
||||
|
||||
struct xhci_dev_ctx *
|
||||
|
@ -3394,7 +3541,8 @@ pci_xhci_init(struct vmctx *ctx, struct pci_vdev *dev, char *opts)
|
|||
xdev->usb2_port_start = (XHCI_MAX_DEVS/2) + 1;
|
||||
xdev->usb3_port_start = 1;
|
||||
|
||||
xdev->excap_ptr = excap_group_dft;
|
||||
xdev->excap_ptr = excap_group_apl;
|
||||
xdev->excap_write = pci_xhci_apl_drdregs_write;
|
||||
|
||||
/* discover devices */
|
||||
error = pci_xhci_parse_opts(xdev, opts);
|
||||
|
|
|
@ -102,6 +102,18 @@ enum {
|
|||
.reserve = 0x00 \
|
||||
}
|
||||
|
||||
/* Intel ApolloLake xHCI extended capability for DRD. */
|
||||
#define DEFINE_EXCP_VENDOR_DRD(capid, next_ptr, reg0, reg1) \
|
||||
struct pci_xhci_excap_drd_apl excap_drd_apl = { \
|
||||
{ \
|
||||
.cap_id = capid, \
|
||||
.cap_ptr = next_ptr \
|
||||
}, \
|
||||
.padding = {0}, \
|
||||
.drdcfg0 = reg0, \
|
||||
.drdcfg1 = reg1 \
|
||||
}
|
||||
|
||||
struct xhci_slot_ctx {
|
||||
volatile uint32_t dwSctx0;
|
||||
#define XHCI_SCTX_0_ROUTE_SET(x) ((x) & 0xFFFFF)
|
||||
|
|
|
@ -227,6 +227,7 @@
|
|||
#define XHCI_ID_VIRTUALIZATION 0x0004
|
||||
#define XHCI_ID_MSG_IRQ 0x0005
|
||||
#define XHCI_ID_USB_LOCAL_MEM 0x0006
|
||||
#define XHCI_ID_DRD_INTEL 0x00C0
|
||||
|
||||
/*
|
||||
* xHCI extended capability pointer in HCCPARAMS1.
|
||||
|
@ -239,6 +240,35 @@
|
|||
#define EXCAP_GROUP_END 0xFFFF
|
||||
#define EXCAP_GROUP_NULL NULL
|
||||
|
||||
/* Intel APL xHCI DRD Configuration registers */
|
||||
#define XHCI_DRD_MUX_CFG0 0x0000
|
||||
#define XHCI_DRD_MUX_CFG1 0x0004
|
||||
#define XCHI_DRD_CFG0_MODE_MASK 0x0003
|
||||
#define XHCI_DRD_CFG0_DYN 0
|
||||
#define XHCI_DRD_CFG0_HOST_MODE 1
|
||||
#define XHCI_DRD_CFG0_DEV_MODE 2
|
||||
#define XHCI_DRD_CFG0_SYNC (1 << 2)
|
||||
#define XHCI_DRD_CFG0_SWITCH_EN (1 << 16)
|
||||
#define XHCI_DRD_CFG0_IDPIN (1 << 20)
|
||||
#define XHCI_DRD_CFG0_IDPIN_EN (1 << 21)
|
||||
#define XHCI_DRD_CFG0_VBUS_VALID (1 << 24)
|
||||
#define XHCI_DRD_CFG1_HOST_MODE (1 << 29)
|
||||
|
||||
/* Intel APL xHCI DRD register related bases */
|
||||
#define XHCI_APL_DRDCAP_BASE 0x8070
|
||||
#define XHCI_APL_DRDREGS_BASE 0x80D8
|
||||
|
||||
/* setting drd for host mode */
|
||||
#define XHCI_NATIVE_DRD_DEV_MODE "D"
|
||||
|
||||
/* setting drd for device mode */
|
||||
#define XHCI_NATIVE_DRD_HOST_MODE "H"
|
||||
#define XHCI_NATIVE_DRD_SWITCH_PATH \
|
||||
"/sys/devices/platform/intel_usb_dr_phy.0/mux_state"
|
||||
|
||||
/* return value after setting drd device node */
|
||||
#define XHCI_NATIVE_DRD_WRITE_SZ 2
|
||||
|
||||
/* XHCI register R/W wrappers */
|
||||
#define XREAD1(sc, what, a) \
|
||||
bus_space_read_1((sc)->sc_io_tag, (sc)->sc_io_hdl, \
|
||||
|
|
Loading…
Reference in New Issue