Message ID | 1368069645-14582-3-git-send-email-dantesu@gmail.com |
---|---|
State | Superseded |
Delegated to: | Marek Vasut |
Headers | show |
Dear Kuo-Jung Su, > From: Kuo-Jung Su <dantesu@faraday-tech.com> > > There is at least one non-EHCI compliant controller (i.e. Faraday EHCI) > known to implement a non-standard TDI stuff. > Futhermore, it not only leave reserved and CONFIGFLAG registers > un-implemented but also has their address spaces removed. > > And thus, we need weak-aliased functions to both TDI stuff > and PORTSC registers for interface abstraction. > > Signed-off-by: Kuo-Jung Su <dantesu@faraday-tech.com> > CC: Marek Vasut <marex@denx.de> > --- > Changes for v5: > - Split up from Faraday EHCI patch > > Changes for v2 - v4: > - See 'usb: ehci: add Faraday USB 2.0 EHCI support' > > drivers/usb/host/ehci-hcd.c | 100 > +++++++++++++++++++++++++++---------------- 1 file changed, 64 > insertions(+), 36 deletions(-) > > diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c > index c816878..b334173 100644 > --- a/drivers/usb/host/ehci-hcd.c > +++ b/drivers/usb/host/ehci-hcd.c > @@ -117,10 +117,50 @@ static struct descriptor { > }; > > #if defined(CONFIG_EHCI_IS_TDI) > -#define ehci_is_TDI() (1) > -#else > -#define ehci_is_TDI() (0) > +# define ehci_is_TDI() (1) > + > +/* put TDI/ARC silicon into EHCI mode */ > +void __ehci_tdi_reset(struct ehci_hcor *hcor) > +{ > + uint32_t tmp, *reg_ptr; > + > + reg_ptr = (uint32_t *)((uint8_t *) + USBMODE); > + tmp = ehci_readl(reg_ptr); > + tmp |= USBMODE_CM_HC; > +#if defined(CONFIG_EHCI_MMIO_BIG_ENDIAN) > + tmp |= USBMODE_BE; > #endif > + ehci_writel(reg_ptr, tmp); > +} > + > +void ehci_tdi_reset(struct ehci_hcor *hcor) > + __attribute__((weak, alias("__ehci_tdi_reset"))); Just wrap this into simple __weak void ehci_tdi_reset(struct ehci_hcor *hcor) { ...body of __ehci_tdi_reset() above ... } it's the same thing as those two functions above, but without so much code ;-) if it doesn't work, include <linux/compiler.h>, same below. > +int __ehci_port_speed(struct ehci_hcor *hcor, unsigned int portsc) > +{ > + int ret = 0; > + > + switch (PORTSC_PSPD(portsc)) { > + case PORTSC_PSPD_FS: > + break; > + case PORTSC_PSPD_LS: > + ret = USB_PORT_STAT_LOW_SPEED; > + break; > + case PORTSC_PSPD_HS: > + default: > + ret = USB_PORT_STAT_HIGH_SPEED; > + break; > + } > + > + return ret; > +} > + > +int ehci_port_speed(struct ehci_hcor *hcor, unsigned int portsc) > + __attribute__((weak, alias("__ehci_port_speed"))); > + > +#else /* CONFIG_EHCI_IS_TDI */ > +# define ehci_is_TDI() (0) > +#endif /* CONFIG_EHCI_IS_TDI */ > > void __ehci_powerup_fixup(uint32_t *status_reg, uint32_t *reg) > { > @@ -149,8 +189,6 @@ static int handshake(uint32_t *ptr, uint32_t mask, > uint32_t done, int usec) static int ehci_reset(int index) > { > uint32_t cmd; > - uint32_t tmp; > - uint32_t *reg_ptr; > int ret = 0; > > cmd = ehci_readl(&ehcic[index].hcor->or_usbcmd); > @@ -163,15 +201,8 @@ static int ehci_reset(int index) > goto out; > } > > - if (ehci_is_TDI()) { > - reg_ptr = (uint32_t *)((u8 *)ehcic[index].hcor + USBMODE); > - tmp = ehci_readl(reg_ptr); > - tmp |= USBMODE_CM_HC; > -#if defined(CONFIG_EHCI_MMIO_BIG_ENDIAN) > - tmp |= USBMODE_BE; > -#endif > - ehci_writel(reg_ptr, tmp); > - } > + if (ehci_is_TDI()) > + ehci_tdi_reset(ehcic[index].hcor); > > #ifdef CONFIG_USB_EHCI_TXFIFO_THRESH > cmd = ehci_readl(&ehcic[index].hcor->or_txfilltuning); > @@ -597,6 +628,18 @@ static inline int min3(int a, int b, int c) > return a; > } > > +uint32_t *__ehci_get_portsc_register(struct ehci_hcor *hcor, int port) > +{ > + if (port >= CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS) { > + printf("The request port(%d) is not configured\n", port); > + return NULL; > + } > + > + return (uint32_t *)&hcor->or_portsc[port]; > +} > +uint32_t *ehci_get_portsc_register(struct ehci_hcor *hcor, int port) > + __attribute__((weak, alias("__ehci_get_portsc_register"))); > + > int > ehci_submit_root(struct usb_device *dev, unsigned long pipe, void *buffer, > int length, struct devrequest *req) > @@ -609,13 +652,10 @@ ehci_submit_root(struct usb_device *dev, unsigned > long pipe, void *buffer, uint32_t *status_reg; > struct ehci_ctrl *ctrl = dev->controller; > > - if (le16_to_cpu(req->index) > CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS) { > - printf("The request port(%d) is not configured\n", > - le16_to_cpu(req->index) - 1); > + status_reg = ehci_get_portsc_register(ctrl->hcor, > + le16_to_cpu(req->index) - 1); > + if (!status_reg) > return -1; > - } > - status_reg = (uint32_t *)&ctrl->hcor->or_portsc[ > - le16_to_cpu(req->index) - 1]; > srclen = 0; > > debug("req=%u (%#x), type=%u (%#x), value=%u, index=%u\n", > @@ -709,23 +749,10 @@ ehci_submit_root(struct usb_device *dev, unsigned > long pipe, void *buffer, tmpbuf[0] |= USB_PORT_STAT_RESET; > if (reg & EHCI_PS_PP) > tmpbuf[1] |= USB_PORT_STAT_POWER >> 8; > - > - if (ehci_is_TDI()) { > - switch (PORTSC_PSPD(reg)) { > - case PORTSC_PSPD_FS: > - break; > - case PORTSC_PSPD_LS: > - tmpbuf[1] |= USB_PORT_STAT_LOW_SPEED >> 8; > - break; > - case PORTSC_PSPD_HS: > - default: > - tmpbuf[1] |= USB_PORT_STAT_HIGH_SPEED >> 8; > - break; > - } > - } else { > + if (ehci_is_TDI()) > + tmpbuf[1] |= ehci_port_speed(ctrl->hcor, reg) >> 8; > + else > tmpbuf[1] |= USB_PORT_STAT_HIGH_SPEED >> 8; > - } > - > if (reg & EHCI_PS_CSC) > tmpbuf[2] |= USB_PORT_STAT_C_CONNECTION; > if (reg & EHCI_PS_PEC) > @@ -954,6 +981,7 @@ int usb_lowlevel_init(int index, void **controller) > cmd = ehci_readl(&ehcic[index].hcor->or_configflag); > cmd |= FLAG_CF; > ehci_writel(&ehcic[index].hcor->or_configflag, cmd); > + This is redundant ;-) > /* unblock posted write */ > cmd = ehci_readl(&ehcic[index].hcor->or_usbcmd); > mdelay(5); > -- > 1.7.9.5 Best regards, Marek Vasut
2013/5/10 Marek Vasut <marex@denx.de>: > Dear Kuo-Jung Su, > >> From: Kuo-Jung Su <dantesu@faraday-tech.com> >> >> There is at least one non-EHCI compliant controller (i.e. Faraday EHCI) >> known to implement a non-standard TDI stuff. >> Futhermore, it not only leave reserved and CONFIGFLAG registers >> un-implemented but also has their address spaces removed. >> >> And thus, we need weak-aliased functions to both TDI stuff >> and PORTSC registers for interface abstraction. >> >> Signed-off-by: Kuo-Jung Su <dantesu@faraday-tech.com> >> CC: Marek Vasut <marex@denx.de> >> --- >> Changes for v5: >> - Split up from Faraday EHCI patch >> >> Changes for v2 - v4: >> - See 'usb: ehci: add Faraday USB 2.0 EHCI support' >> >> drivers/usb/host/ehci-hcd.c | 100 >> +++++++++++++++++++++++++++---------------- 1 file changed, 64 >> insertions(+), 36 deletions(-) >> >> diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c >> index c816878..b334173 100644 >> --- a/drivers/usb/host/ehci-hcd.c >> +++ b/drivers/usb/host/ehci-hcd.c >> @@ -117,10 +117,50 @@ static struct descriptor { >> }; >> >> #if defined(CONFIG_EHCI_IS_TDI) >> -#define ehci_is_TDI() (1) >> -#else >> -#define ehci_is_TDI() (0) >> +# define ehci_is_TDI() (1) >> + >> +/* put TDI/ARC silicon into EHCI mode */ >> +void __ehci_tdi_reset(struct ehci_hcor *hcor) >> +{ >> + uint32_t tmp, *reg_ptr; >> + >> + reg_ptr = (uint32_t *)((uint8_t *) + USBMODE); >> + tmp = ehci_readl(reg_ptr); >> + tmp |= USBMODE_CM_HC; >> +#if defined(CONFIG_EHCI_MMIO_BIG_ENDIAN) >> + tmp |= USBMODE_BE; >> #endif >> + ehci_writel(reg_ptr, tmp); >> +} >> + >> +void ehci_tdi_reset(struct ehci_hcor *hcor) >> + __attribute__((weak, alias("__ehci_tdi_reset"))); > > Just wrap this into simple > > __weak void ehci_tdi_reset(struct ehci_hcor *hcor) > { > ...body of __ehci_tdi_reset() above ... > } > > it's the same thing as those two functions above, but without so much code ;-) > > if it doesn't work, include <linux/compiler.h>, same below. > Got it, thanks >> +int __ehci_port_speed(struct ehci_hcor *hcor, unsigned int portsc) >> +{ >> + int ret = 0; >> + >> + switch (PORTSC_PSPD(portsc)) { >> + case PORTSC_PSPD_FS: >> + break; >> + case PORTSC_PSPD_LS: >> + ret = USB_PORT_STAT_LOW_SPEED; >> + break; >> + case PORTSC_PSPD_HS: >> + default: >> + ret = USB_PORT_STAT_HIGH_SPEED; >> + break; >> + } >> + >> + return ret; >> +} >> + >> +int ehci_port_speed(struct ehci_hcor *hcor, unsigned int portsc) >> + __attribute__((weak, alias("__ehci_port_speed"))); >> + >> +#else /* CONFIG_EHCI_IS_TDI */ >> +# define ehci_is_TDI() (0) >> +#endif /* CONFIG_EHCI_IS_TDI */ >> >> void __ehci_powerup_fixup(uint32_t *status_reg, uint32_t *reg) >> { >> @@ -149,8 +189,6 @@ static int handshake(uint32_t *ptr, uint32_t mask, >> uint32_t done, int usec) static int ehci_reset(int index) >> { >> uint32_t cmd; >> - uint32_t tmp; >> - uint32_t *reg_ptr; >> int ret = 0; >> >> cmd = ehci_readl(&ehcic[index].hcor->or_usbcmd); >> @@ -163,15 +201,8 @@ static int ehci_reset(int index) >> goto out; >> } >> >> - if (ehci_is_TDI()) { >> - reg_ptr = (uint32_t *)((u8 *)ehcic[index].hcor + USBMODE); >> - tmp = ehci_readl(reg_ptr); >> - tmp |= USBMODE_CM_HC; >> -#if defined(CONFIG_EHCI_MMIO_BIG_ENDIAN) >> - tmp |= USBMODE_BE; >> -#endif >> - ehci_writel(reg_ptr, tmp); >> - } >> + if (ehci_is_TDI()) >> + ehci_tdi_reset(ehcic[index].hcor); >> >> #ifdef CONFIG_USB_EHCI_TXFIFO_THRESH >> cmd = ehci_readl(&ehcic[index].hcor->or_txfilltuning); >> @@ -597,6 +628,18 @@ static inline int min3(int a, int b, int c) >> return a; >> } >> >> +uint32_t *__ehci_get_portsc_register(struct ehci_hcor *hcor, int port) >> +{ >> + if (port >= CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS) { >> + printf("The request port(%d) is not configured\n", port); >> + return NULL; >> + } >> + >> + return (uint32_t *)&hcor->or_portsc[port]; >> +} >> +uint32_t *ehci_get_portsc_register(struct ehci_hcor *hcor, int port) >> + __attribute__((weak, alias("__ehci_get_portsc_register"))); >> + >> int >> ehci_submit_root(struct usb_device *dev, unsigned long pipe, void *buffer, >> int length, struct devrequest *req) >> @@ -609,13 +652,10 @@ ehci_submit_root(struct usb_device *dev, unsigned >> long pipe, void *buffer, uint32_t *status_reg; >> struct ehci_ctrl *ctrl = dev->controller; >> >> - if (le16_to_cpu(req->index) > CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS) { >> - printf("The request port(%d) is not configured\n", >> - le16_to_cpu(req->index) - 1); >> + status_reg = ehci_get_portsc_register(ctrl->hcor, >> + le16_to_cpu(req->index) - 1); >> + if (!status_reg) >> return -1; >> - } >> - status_reg = (uint32_t *)&ctrl->hcor->or_portsc[ >> - le16_to_cpu(req->index) - 1]; >> srclen = 0; >> >> debug("req=%u (%#x), type=%u (%#x), value=%u, index=%u\n", >> @@ -709,23 +749,10 @@ ehci_submit_root(struct usb_device *dev, unsigned >> long pipe, void *buffer, tmpbuf[0] |= USB_PORT_STAT_RESET; >> if (reg & EHCI_PS_PP) >> tmpbuf[1] |= USB_PORT_STAT_POWER >> 8; >> - >> - if (ehci_is_TDI()) { >> - switch (PORTSC_PSPD(reg)) { >> - case PORTSC_PSPD_FS: >> - break; >> - case PORTSC_PSPD_LS: >> - tmpbuf[1] |= USB_PORT_STAT_LOW_SPEED >> 8; >> - break; >> - case PORTSC_PSPD_HS: >> - default: >> - tmpbuf[1] |= USB_PORT_STAT_HIGH_SPEED >> 8; >> - break; >> - } >> - } else { >> + if (ehci_is_TDI()) >> + tmpbuf[1] |= ehci_port_speed(ctrl->hcor, reg) >> 8; >> + else >> tmpbuf[1] |= USB_PORT_STAT_HIGH_SPEED >> 8; >> - } >> - >> if (reg & EHCI_PS_CSC) >> tmpbuf[2] |= USB_PORT_STAT_C_CONNECTION; >> if (reg & EHCI_PS_PEC) >> @@ -954,6 +981,7 @@ int usb_lowlevel_init(int index, void **controller) >> cmd = ehci_readl(&ehcic[index].hcor->or_configflag); >> cmd |= FLAG_CF; >> ehci_writel(&ehcic[index].hcor->or_configflag, cmd); >> + > > This is redundant ;-) > Got it, thanks >> /* unblock posted write */ >> cmd = ehci_readl(&ehcic[index].hcor->or_usbcmd); >> mdelay(5); >> -- >> 1.7.9.5 > > Best regards, > Marek Vasut -- Best wishes, Kuo-Jung Su
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index c816878..b334173 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -117,10 +117,50 @@ static struct descriptor { }; #if defined(CONFIG_EHCI_IS_TDI) -#define ehci_is_TDI() (1) -#else -#define ehci_is_TDI() (0) +# define ehci_is_TDI() (1) + +/* put TDI/ARC silicon into EHCI mode */ +void __ehci_tdi_reset(struct ehci_hcor *hcor) +{ + uint32_t tmp, *reg_ptr; + + reg_ptr = (uint32_t *)((uint8_t *) + USBMODE); + tmp = ehci_readl(reg_ptr); + tmp |= USBMODE_CM_HC; +#if defined(CONFIG_EHCI_MMIO_BIG_ENDIAN) + tmp |= USBMODE_BE; #endif + ehci_writel(reg_ptr, tmp); +} + +void ehci_tdi_reset(struct ehci_hcor *hcor) + __attribute__((weak, alias("__ehci_tdi_reset"))); + +int __ehci_port_speed(struct ehci_hcor *hcor, unsigned int portsc) +{ + int ret = 0; + + switch (PORTSC_PSPD(portsc)) { + case PORTSC_PSPD_FS: + break; + case PORTSC_PSPD_LS: + ret = USB_PORT_STAT_LOW_SPEED; + break; + case PORTSC_PSPD_HS: + default: + ret = USB_PORT_STAT_HIGH_SPEED; + break; + } + + return ret; +} + +int ehci_port_speed(struct ehci_hcor *hcor, unsigned int portsc) + __attribute__((weak, alias("__ehci_port_speed"))); + +#else /* CONFIG_EHCI_IS_TDI */ +# define ehci_is_TDI() (0) +#endif /* CONFIG_EHCI_IS_TDI */ void __ehci_powerup_fixup(uint32_t *status_reg, uint32_t *reg) { @@ -149,8 +189,6 @@ static int handshake(uint32_t *ptr, uint32_t mask, uint32_t done, int usec) static int ehci_reset(int index) { uint32_t cmd; - uint32_t tmp; - uint32_t *reg_ptr; int ret = 0; cmd = ehci_readl(&ehcic[index].hcor->or_usbcmd); @@ -163,15 +201,8 @@ static int ehci_reset(int index) goto out; } - if (ehci_is_TDI()) { - reg_ptr = (uint32_t *)((u8 *)ehcic[index].hcor + USBMODE); - tmp = ehci_readl(reg_ptr); - tmp |= USBMODE_CM_HC; -#if defined(CONFIG_EHCI_MMIO_BIG_ENDIAN) - tmp |= USBMODE_BE; -#endif - ehci_writel(reg_ptr, tmp); - } + if (ehci_is_TDI()) + ehci_tdi_reset(ehcic[index].hcor); #ifdef CONFIG_USB_EHCI_TXFIFO_THRESH cmd = ehci_readl(&ehcic[index].hcor->or_txfilltuning); @@ -597,6 +628,18 @@ static inline int min3(int a, int b, int c) return a; } +uint32_t *__ehci_get_portsc_register(struct ehci_hcor *hcor, int port) +{ + if (port >= CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS) { + printf("The request port(%d) is not configured\n", port); + return NULL; + } + + return (uint32_t *)&hcor->or_portsc[port]; +} +uint32_t *ehci_get_portsc_register(struct ehci_hcor *hcor, int port) + __attribute__((weak, alias("__ehci_get_portsc_register"))); + int ehci_submit_root(struct usb_device *dev, unsigned long pipe, void *buffer, int length, struct devrequest *req) @@ -609,13 +652,10 @@ ehci_submit_root(struct usb_device *dev, unsigned long pipe, void *buffer, uint32_t *status_reg; struct ehci_ctrl *ctrl = dev->controller; - if (le16_to_cpu(req->index) > CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS) { - printf("The request port(%d) is not configured\n", - le16_to_cpu(req->index) - 1); + status_reg = ehci_get_portsc_register(ctrl->hcor, + le16_to_cpu(req->index) - 1); + if (!status_reg) return -1; - } - status_reg = (uint32_t *)&ctrl->hcor->or_portsc[ - le16_to_cpu(req->index) - 1]; srclen = 0; debug("req=%u (%#x), type=%u (%#x), value=%u, index=%u\n", @@ -709,23 +749,10 @@ ehci_submit_root(struct usb_device *dev, unsigned long pipe, void *buffer, tmpbuf[0] |= USB_PORT_STAT_RESET; if (reg & EHCI_PS_PP) tmpbuf[1] |= USB_PORT_STAT_POWER >> 8; - - if (ehci_is_TDI()) { - switch (PORTSC_PSPD(reg)) { - case PORTSC_PSPD_FS: - break; - case PORTSC_PSPD_LS: - tmpbuf[1] |= USB_PORT_STAT_LOW_SPEED >> 8; - break; - case PORTSC_PSPD_HS: - default: - tmpbuf[1] |= USB_PORT_STAT_HIGH_SPEED >> 8; - break; - } - } else { + if (ehci_is_TDI()) + tmpbuf[1] |= ehci_port_speed(ctrl->hcor, reg) >> 8; + else tmpbuf[1] |= USB_PORT_STAT_HIGH_SPEED >> 8; - } - if (reg & EHCI_PS_CSC) tmpbuf[2] |= USB_PORT_STAT_C_CONNECTION; if (reg & EHCI_PS_PEC) @@ -954,6 +981,7 @@ int usb_lowlevel_init(int index, void **controller) cmd = ehci_readl(&ehcic[index].hcor->or_configflag); cmd |= FLAG_CF; ehci_writel(&ehcic[index].hcor->or_configflag, cmd); + /* unblock posted write */ cmd = ehci_readl(&ehcic[index].hcor->or_usbcmd); mdelay(5);