>>>
>>> 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. 
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.  

>>
>> 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

Thanks, 
Cheers,
Pawel

Reply via email to