Some USB controllers have quirks that require additional handling when enabling a port. One example is the Chipidea USB host found on various i.MX SoCs, which must be forced to HS mode for HSIC interfaces.
Signed-off-by: Nora Schiffer <[email protected]> --- drivers/usb/host/ehci-hcd.c | 15 +++++++++++---- drivers/usb/host/ehci.h | 2 ++ 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 7d5519c65a9..2de2a5578a1 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -139,6 +139,13 @@ static void ehci_set_usbmode(struct ehci_ctrl *ctrl) ehci_writel(reg_ptr, tmp); } +static void ehci_enable_port_power(struct ehci_ctrl *ctrl, uint32_t *status_reg, + uint32_t reg) +{ + if (HCS_PPC(ehci_readl(&ctrl->hccr->cr_hcsparams))) + ehci_writel(status_reg, reg | EHCI_PS_PP); +} + static void ehci_powerup_fixup(struct ehci_ctrl *ctrl, uint32_t *status_reg, uint32_t *reg) { @@ -874,10 +881,7 @@ static int ehci_submit_root(struct usb_device *dev, unsigned long pipe, ehci_writel(status_reg, reg); break; case USB_PORT_FEAT_POWER: - if (HCS_PPC(ehci_readl(&ctrl->hccr->cr_hcsparams))) { - reg |= EHCI_PS_PP; - ehci_writel(status_reg, reg); - } + ctrl->ops.enable_port_power(ctrl, status_reg, reg); break; case USB_PORT_FEAT_RESET: if ((reg & (EHCI_PS_PE | EHCI_PS_CS)) == EHCI_PS_CS && @@ -1005,6 +1009,7 @@ unknown: static const struct ehci_ops default_ehci_ops = { .set_usb_mode = ehci_set_usbmode, .get_port_speed = ehci_get_port_speed, + .enable_port_power = ehci_enable_port_power, .powerup_fixup = ehci_powerup_fixup, .get_portsc_register = ehci_get_portsc_register, }; @@ -1019,6 +1024,8 @@ static void ehci_setup_ops(struct ehci_ctrl *ctrl, const struct ehci_ops *ops) ctrl->ops.set_usb_mode = ehci_set_usbmode; if (!ctrl->ops.get_port_speed) ctrl->ops.get_port_speed = ehci_get_port_speed; + if (!ctrl->ops.enable_port_power) + ctrl->ops.enable_port_power = ehci_enable_port_power; if (!ctrl->ops.powerup_fixup) ctrl->ops.powerup_fixup = ehci_powerup_fixup; if (!ctrl->ops.get_portsc_register) diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index 5770d35b464..78da0bc0d17 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -238,6 +238,8 @@ struct ehci_ctrl; struct ehci_ops { void (*set_usb_mode)(struct ehci_ctrl *ctrl); int (*get_port_speed)(struct ehci_ctrl *ctrl, uint32_t reg); + void (*enable_port_power)(struct ehci_ctrl *ctrl, uint32_t *status_reg, + uint32_t reg); void (*powerup_fixup)(struct ehci_ctrl *ctrl, uint32_t *status_reg, uint32_t *reg); uint32_t *(*get_portsc_register)(struct ehci_ctrl *ctrl, int port); -- 2.55.0
