[U-Boot] [PATCH v5 2/4] usb: ehci: add weak-aliased functions to portsc & tdi

Kuo-Jung Su
2013-05-13T01:10:04Z

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