mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-06-28 00:06:55 +00:00
DM USB: xHCI: introduce get/set function for PORTSC register
Port Status and Control (PORTSC) register is one of the most frequently accessed regiseter according the xHCI spec. This patch implement a pair of set/get function to access PORTS and it gives a clear code structure and help a lot for debugging work. Tracked-On: #2576 Signed-off-by: Conghui Chen <conghui.chen@intel.com> Signed-off-by: Xiaoguang Wu <xiaoguang.wu@intel.com> Acked-by: Yu Wang <yu1.wang@intel.com>
This commit is contained in:
parent
b7f5614387
commit
5f36580190
@ -508,6 +508,34 @@ static struct pci_xhci_option_elem xhci_option_table[] = {
|
|||||||
{"cap", pci_xhci_parse_extcap}
|
{"cap", pci_xhci_parse_extcap}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static inline uint32_t pci_xhci_access_portsc(struct pci_xhci_vdev *xdev,
|
||||||
|
uint32_t portnum, uint32_t value, int read)
|
||||||
|
{
|
||||||
|
if (!xdev || !xdev->portregs) {
|
||||||
|
UPRINTF(LDBG, "fail to set portsc (port %d)\r\n", portnum);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (read)
|
||||||
|
return xdev->portregs[portnum].portsc;
|
||||||
|
|
||||||
|
xdev->portregs[portnum].portsc = value;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pci_xhci_set_portsc(struct pci_xhci_vdev *xdev, uint32_t portnum,
|
||||||
|
uint32_t value)
|
||||||
|
{
|
||||||
|
UPRINTF(LDBG, "set portsc (port %d) %08x\r\n", portnum, value);
|
||||||
|
pci_xhci_access_portsc(xdev, portnum, value, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t pci_xhci_get_portsc(struct pci_xhci_vdev *xdev,
|
||||||
|
uint32_t portnum)
|
||||||
|
{
|
||||||
|
return pci_xhci_access_portsc(xdev, portnum, 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
pci_xhci_get_free_vport(struct pci_xhci_vdev *xdev,
|
pci_xhci_get_free_vport(struct pci_xhci_vdev *xdev,
|
||||||
struct usb_native_devinfo *di)
|
struct usb_native_devinfo *di)
|
||||||
@ -1113,19 +1141,21 @@ pci_xhci_change_port(struct pci_xhci_vdev *xdev, int port, int usb_speed,
|
|||||||
{
|
{
|
||||||
int speed, error;
|
int speed, error;
|
||||||
struct xhci_trb evtrb;
|
struct xhci_trb evtrb;
|
||||||
struct pci_xhci_portregs *reg;
|
uint32_t value;
|
||||||
|
|
||||||
assert(xdev != NULL);
|
assert(xdev != NULL);
|
||||||
|
|
||||||
reg = XHCI_PORTREG_PTR(xdev, port);
|
|
||||||
if (conn == 0) {
|
if (conn == 0) {
|
||||||
reg->portsc &= ~(XHCI_PS_CCS | XHCI_PS_PED);
|
value = pci_xhci_get_portsc(xdev, port);
|
||||||
reg->portsc |= (XHCI_PS_CSC |
|
value &= ~(XHCI_PS_CCS | XHCI_PS_PED);
|
||||||
XHCI_PS_PLS_SET(UPS_PORT_LS_RX_DET));
|
value |= (XHCI_PS_CSC | XHCI_PS_PLS_SET(UPS_PORT_LS_RX_DET));
|
||||||
|
pci_xhci_set_portsc(xdev, port, value);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
speed = pci_xhci_convert_speed(usb_speed);
|
speed = pci_xhci_convert_speed(usb_speed);
|
||||||
reg->portsc = XHCI_PS_CCS | XHCI_PS_PP | XHCI_PS_CSC;
|
value = XHCI_PS_CCS | XHCI_PS_PP | XHCI_PS_CSC;
|
||||||
reg->portsc |= XHCI_PS_SPEED_SET(speed);
|
value |= XHCI_PS_SPEED_SET(speed);
|
||||||
|
pci_xhci_set_portsc(xdev, port, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!need_intr)
|
if (!need_intr)
|
||||||
@ -1148,7 +1178,8 @@ pci_xhci_change_port(struct pci_xhci_vdev *xdev, int port, int usb_speed,
|
|||||||
if (error != XHCI_TRB_ERROR_SUCCESS)
|
if (error != XHCI_TRB_ERROR_SUCCESS)
|
||||||
UPRINTF(LWRN, "fail to report port change\r\n");
|
UPRINTF(LWRN, "fail to report port change\r\n");
|
||||||
|
|
||||||
UPRINTF(LDBG, "%s: port %d:%08X\r\n", __func__, port, reg->portsc);
|
UPRINTF(LDBG, "%s: portsc (port %d) to %08x\r\n", __func__, port,
|
||||||
|
pci_xhci_get_portsc(xdev, port));
|
||||||
return (error == XHCI_TRB_ERROR_SUCCESS) ? 0 : -1;
|
return (error == XHCI_TRB_ERROR_SUCCESS) ? 0 : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1258,6 +1289,7 @@ pci_xhci_portregs_write(struct pci_xhci_vdev *xdev,
|
|||||||
struct pci_xhci_portregs *p;
|
struct pci_xhci_portregs *p;
|
||||||
int port;
|
int port;
|
||||||
uint32_t oldpls, newpls;
|
uint32_t oldpls, newpls;
|
||||||
|
uint32_t portsc;
|
||||||
|
|
||||||
if (xdev->portregs == NULL)
|
if (xdev->portregs == NULL)
|
||||||
return;
|
return;
|
||||||
@ -1282,6 +1314,7 @@ pci_xhci_portregs_write(struct pci_xhci_vdev *xdev,
|
|||||||
}
|
}
|
||||||
|
|
||||||
p = XHCI_PORTREG_PTR(xdev, port);
|
p = XHCI_PORTREG_PTR(xdev, port);
|
||||||
|
portsc = pci_xhci_get_portsc(xdev, port);
|
||||||
switch (offset) {
|
switch (offset) {
|
||||||
case 0:
|
case 0:
|
||||||
/* port reset or warm reset */
|
/* port reset or warm reset */
|
||||||
@ -1290,23 +1323,23 @@ pci_xhci_portregs_write(struct pci_xhci_vdev *xdev,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((p->portsc & XHCI_PS_PP) == 0) {
|
if ((portsc & XHCI_PS_PP) == 0) {
|
||||||
UPRINTF(LWRN, "portregs_write to unpowered "
|
UPRINTF(LWRN, "portregs_write to unpowered "
|
||||||
"port %d\r\n", port);
|
"port %d\r\n", port);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Port status and control register */
|
/* Port status and control register */
|
||||||
oldpls = XHCI_PS_PLS_GET(p->portsc);
|
oldpls = XHCI_PS_PLS_GET(portsc);
|
||||||
newpls = XHCI_PS_PLS_GET(value);
|
newpls = XHCI_PS_PLS_GET(value);
|
||||||
|
|
||||||
p->portsc &= XHCI_PS_PED | XHCI_PS_PLS_MASK |
|
portsc &= XHCI_PS_PED | XHCI_PS_PLS_MASK |
|
||||||
XHCI_PS_SPEED_MASK | XHCI_PS_PIC_MASK;
|
XHCI_PS_SPEED_MASK | XHCI_PS_PIC_MASK;
|
||||||
|
|
||||||
if (XHCI_DEVINST_PTR(xdev, port))
|
if (XHCI_DEVINST_PTR(xdev, port))
|
||||||
p->portsc |= XHCI_PS_CCS;
|
p->portsc |= XHCI_PS_CCS;
|
||||||
|
|
||||||
p->portsc |= (value &
|
portsc |= (value &
|
||||||
~(XHCI_PS_OCA |
|
~(XHCI_PS_OCA |
|
||||||
XHCI_PS_PR |
|
XHCI_PS_PR |
|
||||||
XHCI_PS_PED |
|
XHCI_PS_PED |
|
||||||
@ -1316,7 +1349,7 @@ pci_xhci_portregs_write(struct pci_xhci_vdev *xdev,
|
|||||||
XHCI_PS_LWS | XHCI_PS_DR | XHCI_PS_WPR));
|
XHCI_PS_LWS | XHCI_PS_DR | XHCI_PS_WPR));
|
||||||
|
|
||||||
/* clear control bits */
|
/* clear control bits */
|
||||||
p->portsc &= ~(value &
|
portsc &= ~(value &
|
||||||
(XHCI_PS_CSC |
|
(XHCI_PS_CSC |
|
||||||
XHCI_PS_PEC |
|
XHCI_PS_PEC |
|
||||||
XHCI_PS_WRC |
|
XHCI_PS_WRC |
|
||||||
@ -1330,16 +1363,18 @@ pci_xhci_portregs_write(struct pci_xhci_vdev *xdev,
|
|||||||
if (value & XHCI_PS_PED)
|
if (value & XHCI_PS_PED)
|
||||||
UPRINTF(LDBG, "Disable port %d request\r\n", port);
|
UPRINTF(LDBG, "Disable port %d request\r\n", port);
|
||||||
|
|
||||||
if (!(value & XHCI_PS_LWS))
|
if (!(value & XHCI_PS_LWS)) {
|
||||||
|
pci_xhci_set_portsc(xdev, port, portsc);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
UPRINTF(LDBG, "Port new PLS: %d\r\n", newpls);
|
UPRINTF(LDBG, "Port new PLS: %d\r\n", newpls);
|
||||||
switch (newpls) {
|
switch (newpls) {
|
||||||
case 0: /* U0 */
|
case 0: /* U0 */
|
||||||
case 3: /* U3 */
|
case 3: /* U3 */
|
||||||
if (oldpls != newpls) {
|
if (oldpls != newpls) {
|
||||||
p->portsc &= ~XHCI_PS_PLS_MASK;
|
portsc &= ~XHCI_PS_PLS_MASK;
|
||||||
p->portsc |= XHCI_PS_PLS_SET(newpls);
|
portsc |= XHCI_PS_PLS_SET(newpls);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* TODO:
|
* TODO:
|
||||||
@ -1347,8 +1382,9 @@ pci_xhci_portregs_write(struct pci_xhci_vdev *xdev,
|
|||||||
* consistent with xHCI spec.
|
* consistent with xHCI spec.
|
||||||
*/
|
*/
|
||||||
if (newpls == 0)
|
if (newpls == 0)
|
||||||
p->portsc |= XHCI_PS_PLC;
|
portsc |= XHCI_PS_PLC;
|
||||||
|
|
||||||
|
pci_xhci_set_portsc(xdev, port, portsc);
|
||||||
if (oldpls != 0 && newpls == 0) {
|
if (oldpls != 0 && newpls == 0) {
|
||||||
pci_xhci_set_evtrb(&evtrb, port,
|
pci_xhci_set_evtrb(&evtrb, port,
|
||||||
XHCI_TRB_ERROR_SUCCESS,
|
XHCI_TRB_ERROR_SUCCESS,
|
||||||
@ -3610,17 +3646,16 @@ pci_xhci_read(struct vmctx *ctx,
|
|||||||
static void
|
static void
|
||||||
pci_xhci_reset_port(struct pci_xhci_vdev *xdev, int portn, int warm)
|
pci_xhci_reset_port(struct pci_xhci_vdev *xdev, int portn, int warm)
|
||||||
{
|
{
|
||||||
struct pci_xhci_portregs *port;
|
|
||||||
struct xhci_trb evtrb;
|
struct xhci_trb evtrb;
|
||||||
struct usb_native_devinfo *di;
|
struct usb_native_devinfo *di;
|
||||||
int speed, error;
|
int speed, error;
|
||||||
int index;
|
int index;
|
||||||
|
uint32_t portsc;
|
||||||
|
|
||||||
assert(portn <= XHCI_MAX_DEVS);
|
assert(portn <= XHCI_MAX_DEVS);
|
||||||
|
|
||||||
UPRINTF(LINF, "reset port %d\r\n", portn);
|
UPRINTF(LINF, "reset port %d\r\n", portn);
|
||||||
|
|
||||||
port = XHCI_PORTREG_PTR(xdev, portn);
|
|
||||||
index = pci_xhci_get_native_port_index_by_vport(xdev, portn);
|
index = pci_xhci_get_native_port_index_by_vport(xdev, portn);
|
||||||
if (index < 0) {
|
if (index < 0) {
|
||||||
UPRINTF(LWRN, "fail to reset port %d\r\n", portn);
|
UPRINTF(LWRN, "fail to reset port %d\r\n", portn);
|
||||||
@ -3628,15 +3663,17 @@ pci_xhci_reset_port(struct pci_xhci_vdev *xdev, int portn, int warm)
|
|||||||
}
|
}
|
||||||
di = &xdev->native_ports[index].info;
|
di = &xdev->native_ports[index].info;
|
||||||
|
|
||||||
|
portsc = pci_xhci_get_portsc(xdev, portn);
|
||||||
speed = pci_xhci_convert_speed(di->speed);
|
speed = pci_xhci_convert_speed(di->speed);
|
||||||
port->portsc &= ~(XHCI_PS_PLS_MASK | XHCI_PS_PR | XHCI_PS_PRC);
|
portsc &= ~(XHCI_PS_PLS_MASK | XHCI_PS_PR | XHCI_PS_PRC);
|
||||||
port->portsc |= XHCI_PS_PED | XHCI_PS_SPEED_SET(speed);
|
portsc |= XHCI_PS_PED | XHCI_PS_SPEED_SET(speed);
|
||||||
|
|
||||||
if (warm && di->bcd >= 0x300)
|
if (warm && di->bcd >= 0x300)
|
||||||
port->portsc |= XHCI_PS_WRC;
|
portsc |= XHCI_PS_WRC;
|
||||||
|
|
||||||
if ((port->portsc & XHCI_PS_PRC) == 0) {
|
if ((portsc & XHCI_PS_PRC) == 0) {
|
||||||
port->portsc |= XHCI_PS_PRC;
|
portsc |= XHCI_PS_PRC;
|
||||||
|
pci_xhci_set_portsc(xdev, portn, portsc);
|
||||||
|
|
||||||
pci_xhci_set_evtrb(&evtrb, portn,
|
pci_xhci_set_evtrb(&evtrb, portn,
|
||||||
XHCI_TRB_ERROR_SUCCESS,
|
XHCI_TRB_ERROR_SUCCESS,
|
||||||
@ -3645,14 +3682,15 @@ pci_xhci_reset_port(struct pci_xhci_vdev *xdev, int portn, int warm)
|
|||||||
if (error != XHCI_TRB_ERROR_SUCCESS)
|
if (error != XHCI_TRB_ERROR_SUCCESS)
|
||||||
UPRINTF(LWRN, "reset port insert event "
|
UPRINTF(LWRN, "reset port insert event "
|
||||||
"failed\n");
|
"failed\n");
|
||||||
}
|
} else
|
||||||
|
pci_xhci_set_portsc(xdev, portn, portsc);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
pci_xhci_init_port(struct pci_xhci_vdev *xdev, int portn)
|
pci_xhci_init_port(struct pci_xhci_vdev *xdev, int portn)
|
||||||
{
|
{
|
||||||
XHCI_PORTREG_PTR(xdev, portn)->portsc =
|
pci_xhci_set_portsc(xdev, portn, XHCI_PS_PLS_SET(UPS_PORT_LS_RX_DET)
|
||||||
XHCI_PS_PLS_SET(UPS_PORT_LS_RX_DET) | XHCI_PS_PP;
|
| XHCI_PS_PP);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -3662,11 +3700,11 @@ pci_xhci_dev_intr(struct usb_hci *hci, int epctx)
|
|||||||
struct xhci_dev_ctx *dev_ctx;
|
struct xhci_dev_ctx *dev_ctx;
|
||||||
struct xhci_trb evtrb;
|
struct xhci_trb evtrb;
|
||||||
struct pci_xhci_vdev *xdev;
|
struct pci_xhci_vdev *xdev;
|
||||||
struct pci_xhci_portregs *p;
|
|
||||||
struct xhci_endp_ctx *ep_ctx;
|
struct xhci_endp_ctx *ep_ctx;
|
||||||
int error = 0;
|
int error = 0;
|
||||||
int dir_in;
|
int dir_in;
|
||||||
int epid;
|
int epid;
|
||||||
|
uint32_t portsc;
|
||||||
|
|
||||||
dir_in = epctx & 0x80;
|
dir_in = epctx & 0x80;
|
||||||
epid = epctx & ~0x80;
|
epid = epctx & ~0x80;
|
||||||
@ -3685,16 +3723,19 @@ pci_xhci_dev_intr(struct usb_hci *hci, int epctx)
|
|||||||
dev->dev_ctx == NULL)
|
dev->dev_ctx == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
p = XHCI_PORTREG_PTR(xdev, hci->hci_port);
|
portsc = pci_xhci_get_portsc(xdev, hci->hci_port);
|
||||||
|
|
||||||
/* raise event if link U3 (suspended) state */
|
/* raise event if link U3 (suspended) state */
|
||||||
if (XHCI_PS_PLS_GET(p->portsc) == 3) {
|
if (XHCI_PS_PLS_GET(portsc) == 3) {
|
||||||
p->portsc &= ~XHCI_PS_PLS_MASK;
|
portsc &= ~XHCI_PS_PLS_MASK;
|
||||||
p->portsc |= XHCI_PS_PLS_SET(UPS_PORT_LS_RESUME);
|
portsc |= XHCI_PS_PLS_SET(UPS_PORT_LS_RESUME);
|
||||||
if ((p->portsc & XHCI_PS_PLC) != 0)
|
if ((portsc & XHCI_PS_PLC) != 0) {
|
||||||
|
pci_xhci_set_portsc(xdev, hci->hci_port, portsc);
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
p->portsc |= XHCI_PS_PLC;
|
portsc |= XHCI_PS_PLC;
|
||||||
|
pci_xhci_set_portsc(xdev, hci->hci_port, portsc);
|
||||||
|
|
||||||
pci_xhci_set_evtrb(&evtrb, hci->hci_port,
|
pci_xhci_set_evtrb(&evtrb, hci->hci_port,
|
||||||
XHCI_TRB_ERROR_SUCCESS,
|
XHCI_TRB_ERROR_SUCCESS,
|
||||||
|
Loading…
Reference in New Issue
Block a user