On 26/11/18 12:09, Pawel Laszczak wrote:
>>>>
>>>> Pawel,
>>>>
>>>> On 26/11/18 09:23, Pawel Laszczak wrote:
>>>>> Hi Roger,
>>>>>
>>>>>> On 18/11/18 12:09, Pawel Laszczak wrote:
>>>>>>> Patch adds supports for detecting Host/Device mode.
>>>>>>> Controller has additional OTG register that allow
>>>>>>> implement even whole OTG functionality.
>>>>>>> At this moment patch adds support only for detecting
>>>>>>> the appropriate mode based on strap pins and ID pin.
>>>>>>>
>>>>>>> Signed-off-by: Pawel Laszczak <paw...@cadence.com>
>>>>>>> ---
>>>>>>>  drivers/usb/cdns3/Makefile |   2 +-
>>>>>>>  drivers/usb/cdns3/core.c   |  27 +++--
>>>>>>>  drivers/usb/cdns3/drd.c    | 229 +++++++++++++++++++++++++++++++++++++
>>>>>>>  drivers/usb/cdns3/drd.h    | 122 ++++++++++++++++++++
>>>>>>>  4 files changed, 372 insertions(+), 8 deletions(-)
>>>>>>>  create mode 100644 drivers/usb/cdns3/drd.c
>>>>>>>  create mode 100644 drivers/usb/cdns3/drd.h
>>>>>>>
>>>>>>> diff --git a/drivers/usb/cdns3/Makefile b/drivers/usb/cdns3/Makefile
>>>>>>> index 02d25b23c5d3..e779b2a2f8eb 100644
>>>>>>> --- a/drivers/usb/cdns3/Makefile
>>>>>>> +++ b/drivers/usb/cdns3/Makefile
>>>>>>> @@ -1,5 +1,5 @@
>>>>>>>  obj-$(CONFIG_USB_CDNS3)                        += cdns3.o
>>>>>>>  obj-$(CONFIG_USB_CDNS3_PCI_WRAP)       += cdns3-pci.o
>>>>>>>
>>>>>>> -cdns3-y                                        := core.o
>>>>>>> +cdns3-y                                        := core.o drd.o
>>>>>>>  cdns3-pci-y                            := cdns3-pci-wrap.o
>>>>>>> diff --git a/drivers/usb/cdns3/core.c b/drivers/usb/cdns3/core.c
>>>>>>> index f9055d4da67f..dbee4325da7f 100644
>>>>>>> --- a/drivers/usb/cdns3/core.c
>>>>>>> +++ b/drivers/usb/cdns3/core.c
>>>>>>> @@ -17,6 +17,7 @@
>>>>>>>
>>>>>>>  #include "gadget.h"
>>>>>>>  #include "core.h"
>>>>>>> +#include "drd.h"
>>>>>>>
>>>>>>>  static inline struct cdns3_role_driver 
>>>>>>> *cdns3_get_current_role_driver(struct cdns3 *cdns)
>>>>>>>  {
>>>>>>> @@ -57,8 +58,10 @@ static inline void cdns3_role_stop(struct cdns3 
>>>>>>> *cdns)
>>>>>>>  static enum cdns3_roles cdns3_get_role(struct cdns3 *cdns)
>>>>>>>  {
>>>>>>>         if (cdns->roles[CDNS3_ROLE_HOST] && 
>>>>>>> cdns->roles[CDNS3_ROLE_GADGET]) {
>>>>>>> -               //TODO: implements selecting device/host mode
>>>>>>> -               return CDNS3_ROLE_HOST;
>>>>>>> +               if (cdns3_is_host(cdns))
>>>>>>> +                       return CDNS3_ROLE_HOST;
>>>>>>> +               if (cdns3_is_device(cdns))
>>>>>>> +                       return CDNS3_ROLE_GADGET;
>>>>>>>         }
>>>>>>>         return cdns->roles[CDNS3_ROLE_HOST]
>>>>>>>                 ? CDNS3_ROLE_HOST
>>>>>>> @@ -124,6 +127,12 @@ static irqreturn_t cdns3_irq(int irq, void *data)
>>>>>>>         struct cdns3 *cdns = data;
>>>>>>>         irqreturn_t ret = IRQ_NONE;
>>>>>>>
>>>>>>> +       if (cdns->dr_mode == USB_DR_MODE_OTG) {
>>>>>>> +               ret = cdns3_drd_irq(cdns);
>>>>>>> +               if (ret == IRQ_HANDLED)
>>>>>>> +                       return ret;
>>>>>>> +       }
>>>>>>
>>>>>> The kernel's shared IRQ model takes care of sharing the same interrupt
>>>>>> between different devices and their drivers. You don't need to manually
>>>>>> handle it here. Just let all 3 drivers do a request_irq() and have
>>>>>> handlers check if the IRQ was theirs or not and return IRQ_HANDLED or
>>>>>> IRQ_NONE accordingly.
>>>>>>
>>>>>> Looks like you can do away with irq member of the role driver struct.
>>>>>
>>>>> Ok, I will split it into 3 separate part, but in this case, I 
>>>>> additionally have to check the current
>>>>> role in ISR function. Driver can't read host side registers when 
>>>>> controller works in device role
>>>>> and vice versa. One part of controller is kept in reset. Only DRD 
>>>>> registers are common and are all accessible.
>>>>>
>>>>
>>>> In which ISR do you need to check current role?
>>>>
>>>> I'm not sure if we are on the same page.
>>>> Core (drd) driver shouldn't read host/device side registers. All 3 drivers,
>>>> i.e. DRD(core), Host (xhci) and device (cdns3) should do a request_irq()
>>>> and process their respective IRQ events.
>>>
>>> Yes, I understand.
>>> I need to check this in cdns3_irq_handler_thread and cdns3_host_irq.
>>>
>>> Core (drd) has register that are always accessible.
>>> Core (device)  - registers are available also in device mode
>>> Core (host)  - registers  are available only in host mode
>>>
>>> So we can use separate request_irq  for drd, device and host side, but
>>> we need ensure that in host side driver will not touch the device register.
>>
>> That should never happen as host side doesn't have visibility to device 
>> registers.
> 
> I meant the following scenario:
> Assume that controller work in Device role and it raise interrupt for Device 
> part. 
> Now host is kept in reset. 
> 1. System receive interrupt 
> 2.  Kernel call drd_irq but this function return IRQ_NONE
> 3.  Kernel call cdns3_host_irq and driver has to read some interrupt register 
> to check if 
>      this event is addressed to him. In this moment we can have unknown 
> behavior. 

This is the problem. If device is not able to figure out its interrupt event 
then
it must unregister the ISR.

> 4.  Kernel call cdns3_irq_handler  (device). This point probably will not 
> happen because 
>     It could have stuck at point 3. 
> 
> Ok, I think I understood. After changing role, the driver unregisters the 
> interrupt function
> used by previous role so point 3 never happen. 
> 
> I will try to check how it works.  
> 

Cool! Thanks.

>>>
>>> We doesn't know the order in which  the system will call interrupts 
>>> function related to
>>>  the shared interrupt line.
>>
>> Order shouldn't matter. Each user will check its own events return IRQ_NONE 
>> if they
>> didn't cause the IRQ.
>>>
>>
>> <snip>
>>

cheers,
-roger
-- 
Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki.
Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki

Reply via email to