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:
|
* devices:
|
||||||
* tablet USB tablet mouse
|
* 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/cdefs.h>
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#include <sys/uio.h>
|
#include <sys/uio.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/queue.h>
|
#include <sys/queue.h>
|
||||||
|
#include <sys/fcntl.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
@ -216,6 +263,13 @@ struct pci_xhci_excap_ptr {
|
||||||
uint8_t cap_ptr;
|
uint8_t cap_ptr;
|
||||||
} __attribute__((packed));
|
} __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_prot {
|
||||||
struct pci_xhci_excap_ptr excap_ptr;
|
struct pci_xhci_excap_ptr excap_ptr;
|
||||||
uint8_t rev_min;
|
uint8_t rev_min;
|
||||||
|
@ -244,6 +298,25 @@ static DEFINE_EXCP_PROT(u3_prot,
|
||||||
1,
|
1,
|
||||||
XHCI_MAX_DEVS/2);
|
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
|
* default xhci extended capabilities
|
||||||
* excap start excap end register value
|
* excap start excap end register value
|
||||||
|
@ -302,6 +375,7 @@ struct pci_xhci_vdev {
|
||||||
int ndevices;
|
int ndevices;
|
||||||
|
|
||||||
void *excap_ptr;
|
void *excap_ptr;
|
||||||
|
int (*excap_write)(struct pci_xhci_vdev *, uint64_t, uint64_t);
|
||||||
int usb2_port_start;
|
int usb2_port_start;
|
||||||
int usb3_port_start;
|
int usb3_port_start;
|
||||||
uint8_t *native_assign_ports[USB_NATIVE_NUM_BUS];
|
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
|
static void
|
||||||
pci_xhci_excap_write(struct pci_xhci_vdev *xdev, uint64_t offset,
|
pci_xhci_excap_write(struct pci_xhci_vdev *xdev, uint64_t offset,
|
||||||
uint64_t value)
|
uint64_t value)
|
||||||
{
|
{
|
||||||
/* TODO: The default extended capabilities are readonly. Need implement
|
int rc = 0;
|
||||||
* related write operations once writable capabilities get supported in
|
|
||||||
* future.
|
assert(xdev);
|
||||||
*/
|
|
||||||
UPRINTF(LWRN, "write invalid offset 0x%lx\r\n", offset);
|
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 *
|
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->usb2_port_start = (XHCI_MAX_DEVS/2) + 1;
|
||||||
xdev->usb3_port_start = 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 */
|
/* discover devices */
|
||||||
error = pci_xhci_parse_opts(xdev, opts);
|
error = pci_xhci_parse_opts(xdev, opts);
|
||||||
|
|
|
@ -102,6 +102,18 @@ enum {
|
||||||
.reserve = 0x00 \
|
.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 {
|
struct xhci_slot_ctx {
|
||||||
volatile uint32_t dwSctx0;
|
volatile uint32_t dwSctx0;
|
||||||
#define XHCI_SCTX_0_ROUTE_SET(x) ((x) & 0xFFFFF)
|
#define XHCI_SCTX_0_ROUTE_SET(x) ((x) & 0xFFFFF)
|
||||||
|
|
|
@ -227,6 +227,7 @@
|
||||||
#define XHCI_ID_VIRTUALIZATION 0x0004
|
#define XHCI_ID_VIRTUALIZATION 0x0004
|
||||||
#define XHCI_ID_MSG_IRQ 0x0005
|
#define XHCI_ID_MSG_IRQ 0x0005
|
||||||
#define XHCI_ID_USB_LOCAL_MEM 0x0006
|
#define XHCI_ID_USB_LOCAL_MEM 0x0006
|
||||||
|
#define XHCI_ID_DRD_INTEL 0x00C0
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* xHCI extended capability pointer in HCCPARAMS1.
|
* xHCI extended capability pointer in HCCPARAMS1.
|
||||||
|
@ -239,6 +240,35 @@
|
||||||
#define EXCAP_GROUP_END 0xFFFF
|
#define EXCAP_GROUP_END 0xFFFF
|
||||||
#define EXCAP_GROUP_NULL NULL
|
#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 */
|
/* XHCI register R/W wrappers */
|
||||||
#define XREAD1(sc, what, a) \
|
#define XREAD1(sc, what, a) \
|
||||||
bus_space_read_1((sc)->sc_io_tag, (sc)->sc_io_hdl, \
|
bus_space_read_1((sc)->sc_io_tag, (sc)->sc_io_hdl, \
|
||||||
|
|
Loading…
Reference in New Issue