diff mbox

[PATCHv6,4/5] USB: gadget: atmel_usba_udc: Prepare for IRQ single edge support

Message ID 1421945805-31129-5-git-send-email-sylvain.rochet@finsecur.com (mailing list archive)
State New, archived
Headers show

Commit Message

Sylvain Rochet Jan. 22, 2015, 4:56 p.m. UTC
Renamed struct usba_udc_errata to struct usba_udc_caps, we are adding a
new property which is not about errata, this way the struct is not
misnamed.

New struct usba_udc_caps property: irq_single_edge_support, boolean,
set to true if the board supports IRQ_TYPE_EDGE_FALLING and
IRQ_TYPE_EDGE_RISING, otherwise set to false.

Signed-off-by: Sylvain Rochet <sylvain.rochet@finsecur.com>
---
 drivers/usb/gadget/udc/atmel_usba_udc.c | 25 +++++++++++++++----------
 drivers/usb/gadget/udc/atmel_usba_udc.h |  5 +++--
 2 files changed, 18 insertions(+), 12 deletions(-)

Comments

Boris BREZILLON Jan. 22, 2015, 5:14 p.m. UTC | #1
On Thu, 22 Jan 2015 17:56:44 +0100
Sylvain Rochet <sylvain.rochet@finsecur.com> wrote:

> Renamed struct usba_udc_errata to struct usba_udc_caps, we are adding a
> new property which is not about errata, this way the struct is not
> misnamed.
> 
> New struct usba_udc_caps property: irq_single_edge_support, boolean,
> set to true if the board supports IRQ_TYPE_EDGE_FALLING and
> IRQ_TYPE_EDGE_RISING, otherwise set to false.
> 
> Signed-off-by: Sylvain Rochet <sylvain.rochet@finsecur.com>

Acked-by: Boris Brezillon <boris.brezillon@free-electrons.com>

> ---
>  drivers/usb/gadget/udc/atmel_usba_udc.c | 25 +++++++++++++++----------
>  drivers/usb/gadget/udc/atmel_usba_udc.h |  5 +++--
>  2 files changed, 18 insertions(+), 12 deletions(-)
> 
> diff --git a/drivers/usb/gadget/udc/atmel_usba_udc.c b/drivers/usb/gadget/udc/atmel_usba_udc.c
> index d554106..361f740 100644
> --- a/drivers/usb/gadget/udc/atmel_usba_udc.c
> +++ b/drivers/usb/gadget/udc/atmel_usba_udc.c
> @@ -338,8 +338,8 @@ static int vbus_is_present(struct usba_udc *udc)
>  
>  static void toggle_bias(struct usba_udc *udc, int is_on)
>  {
> -	if (udc->errata && udc->errata->toggle_bias)
> -		udc->errata->toggle_bias(udc, is_on);
> +	if (udc->caps && udc->caps->toggle_bias)
> +		udc->caps->toggle_bias(udc, is_on);
>  }
>  
>  static void generate_bias_pulse(struct usba_udc *udc)
> @@ -347,8 +347,8 @@ static void generate_bias_pulse(struct usba_udc *udc)
>  	if (!udc->bias_pulse_needed)
>  		return;
>  
> -	if (udc->errata && udc->errata->pulse_bias)
> -		udc->errata->pulse_bias(udc);
> +	if (udc->caps && udc->caps->pulse_bias)
> +		udc->caps->pulse_bias(udc);
>  
>  	udc->bias_pulse_needed = false;
>  }
> @@ -1901,18 +1901,23 @@ static void at91sam9g45_pulse_bias(struct usba_udc *udc)
>  	at91_pmc_write(AT91_CKGR_UCKR, uckr | AT91_PMC_BIASEN);
>  }
>  
> -static const struct usba_udc_errata at91sam9rl_errata = {
> +static const struct usba_udc_caps at91sam9rl_caps = {
>  	.toggle_bias = at91sam9rl_toggle_bias,
>  };
>  
> -static const struct usba_udc_errata at91sam9g45_errata = {
> +static const struct usba_udc_caps at91sam9g45_caps = {
>  	.pulse_bias = at91sam9g45_pulse_bias,
> +	.irq_single_edge_support = true,
> +};
> +
> +static const struct usba_udc_caps sama5d3_caps = {
> +	.irq_single_edge_support = true,
>  };
>  
>  static const struct of_device_id atmel_udc_dt_ids[] = {
> -	{ .compatible = "atmel,at91sam9rl-udc", .data = &at91sam9rl_errata },
> -	{ .compatible = "atmel,at91sam9g45-udc", .data = &at91sam9g45_errata },
> -	{ .compatible = "atmel,sama5d3-udc" },
> +	{ .compatible = "atmel,at91sam9rl-udc", .data = &at91sam9rl_caps },
> +	{ .compatible = "atmel,at91sam9g45-udc", .data = &at91sam9g45_caps },
> +	{ .compatible = "atmel,sama5d3-udc", .data = &sama5d3_caps },
>  	{ /* sentinel */ }
>  };
>  
> @@ -1934,7 +1939,7 @@ static struct usba_ep * atmel_udc_of_init(struct platform_device *pdev,
>  	if (!match)
>  		return ERR_PTR(-EINVAL);
>  
> -	udc->errata = match->data;
> +	udc->caps = match->data;
>  
>  	udc->num_ep = 0;
>  
> diff --git a/drivers/usb/gadget/udc/atmel_usba_udc.h b/drivers/usb/gadget/udc/atmel_usba_udc.h
> index 085749a..4fe4c87 100644
> --- a/drivers/usb/gadget/udc/atmel_usba_udc.h
> +++ b/drivers/usb/gadget/udc/atmel_usba_udc.h
> @@ -304,9 +304,10 @@ struct usba_request {
>  	unsigned int				mapped:1;
>  };
>  
> -struct usba_udc_errata {
> +struct usba_udc_caps {
>  	void (*toggle_bias)(struct usba_udc *udc, int is_on);
>  	void (*pulse_bias)(struct usba_udc *udc);
> +	bool irq_single_edge_support;
>  };
>  
>  struct usba_udc {
> @@ -322,7 +323,7 @@ struct usba_udc {
>  	struct usb_gadget gadget;
>  	struct usb_gadget_driver *driver;
>  	struct platform_device *pdev;
> -	const struct usba_udc_errata *errata;
> +	const struct usba_udc_caps *caps;
>  	int irq;
>  	int vbus_pin;
>  	int vbus_pin_inverted;
Nicolas Ferre Feb. 5, 2015, 5:19 p.m. UTC | #2
Le 22/01/2015 18:14, Boris Brezillon a écrit :
> On Thu, 22 Jan 2015 17:56:44 +0100
> Sylvain Rochet <sylvain.rochet@finsecur.com> wrote:
> 
>> Renamed struct usba_udc_errata to struct usba_udc_caps, we are adding a
>> new property which is not about errata, this way the struct is not
>> misnamed.
>>
>> New struct usba_udc_caps property: irq_single_edge_support, boolean,
>> set to true if the board supports IRQ_TYPE_EDGE_FALLING and
>> IRQ_TYPE_EDGE_RISING, otherwise set to false.
>>
>> Signed-off-by: Sylvain Rochet <sylvain.rochet@finsecur.com>
> 
> Acked-by: Boris Brezillon <boris.brezillon@free-electrons.com>

Some comments:

>> ---
>>  drivers/usb/gadget/udc/atmel_usba_udc.c | 25 +++++++++++++++----------
>>  drivers/usb/gadget/udc/atmel_usba_udc.h |  5 +++--
>>  2 files changed, 18 insertions(+), 12 deletions(-)
>>
>> diff --git a/drivers/usb/gadget/udc/atmel_usba_udc.c b/drivers/usb/gadget/udc/atmel_usba_udc.c
>> index d554106..361f740 100644
>> --- a/drivers/usb/gadget/udc/atmel_usba_udc.c
>> +++ b/drivers/usb/gadget/udc/atmel_usba_udc.c
>> @@ -338,8 +338,8 @@ static int vbus_is_present(struct usba_udc *udc)
>>  
>>  static void toggle_bias(struct usba_udc *udc, int is_on)
>>  {
>> -	if (udc->errata && udc->errata->toggle_bias)
>> -		udc->errata->toggle_bias(udc, is_on);
>> +	if (udc->caps && udc->caps->toggle_bias)
>> +		udc->caps->toggle_bias(udc, is_on);
>>  }
>>  
>>  static void generate_bias_pulse(struct usba_udc *udc)
>> @@ -347,8 +347,8 @@ static void generate_bias_pulse(struct usba_udc *udc)
>>  	if (!udc->bias_pulse_needed)
>>  		return;
>>  
>> -	if (udc->errata && udc->errata->pulse_bias)
>> -		udc->errata->pulse_bias(udc);
>> +	if (udc->caps && udc->caps->pulse_bias)
>> +		udc->caps->pulse_bias(udc);
>>  
>>  	udc->bias_pulse_needed = false;
>>  }
>> @@ -1901,18 +1901,23 @@ static void at91sam9g45_pulse_bias(struct usba_udc *udc)
>>  	at91_pmc_write(AT91_CKGR_UCKR, uckr | AT91_PMC_BIASEN);
>>  }
>>  
>> -static const struct usba_udc_errata at91sam9rl_errata = {
>> +static const struct usba_udc_caps at91sam9rl_caps = {
>>  	.toggle_bias = at91sam9rl_toggle_bias,
>>  };
>>  
>> -static const struct usba_udc_errata at91sam9g45_errata = {
>> +static const struct usba_udc_caps at91sam9g45_caps = {
>>  	.pulse_bias = at91sam9g45_pulse_bias,
>> +	.irq_single_edge_support = true,

Nope! at91sam9g45 doesn't have this property. You'll have to create
another compatible string and capabilities structure
("atmel,at91sam9x5-udc")

But still, I don't know if it's the proper approach. The possibility tro
trigger an IRQ on both edges or a single edge is a capacity of the gpio
controller, not the USBA IP. So, it's a little bit strange to have this
capability here.

I don't know if it's actually feasible but trying to configure the IRQ
on a single edge, testing if it's accepted by the GPIO irq controller
and if not, falling back to a "both edge" pattern. Doesn't it look like
a way to workaround this issue nicely? Can you give it a try?

Bye,

>> +};
>> +
>> +static const struct usba_udc_caps sama5d3_caps = {
>> +	.irq_single_edge_support = true,
>>  };
>>  
>>  static const struct of_device_id atmel_udc_dt_ids[] = {
>> -	{ .compatible = "atmel,at91sam9rl-udc", .data = &at91sam9rl_errata },
>> -	{ .compatible = "atmel,at91sam9g45-udc", .data = &at91sam9g45_errata },
>> -	{ .compatible = "atmel,sama5d3-udc" },
>> +	{ .compatible = "atmel,at91sam9rl-udc", .data = &at91sam9rl_caps },
>> +	{ .compatible = "atmel,at91sam9g45-udc", .data = &at91sam9g45_caps },
>> +	{ .compatible = "atmel,sama5d3-udc", .data = &sama5d3_caps },
>>  	{ /* sentinel */ }
>>  };
>>  
>> @@ -1934,7 +1939,7 @@ static struct usba_ep * atmel_udc_of_init(struct platform_device *pdev,
>>  	if (!match)
>>  		return ERR_PTR(-EINVAL);
>>  
>> -	udc->errata = match->data;
>> +	udc->caps = match->data;
>>  
>>  	udc->num_ep = 0;
>>  
>> diff --git a/drivers/usb/gadget/udc/atmel_usba_udc.h b/drivers/usb/gadget/udc/atmel_usba_udc.h
>> index 085749a..4fe4c87 100644
>> --- a/drivers/usb/gadget/udc/atmel_usba_udc.h
>> +++ b/drivers/usb/gadget/udc/atmel_usba_udc.h
>> @@ -304,9 +304,10 @@ struct usba_request {
>>  	unsigned int				mapped:1;
>>  };
>>  
>> -struct usba_udc_errata {
>> +struct usba_udc_caps {
>>  	void (*toggle_bias)(struct usba_udc *udc, int is_on);
>>  	void (*pulse_bias)(struct usba_udc *udc);
>> +	bool irq_single_edge_support;
>>  };
>>  
>>  struct usba_udc {
>> @@ -322,7 +323,7 @@ struct usba_udc {
>>  	struct usb_gadget gadget;
>>  	struct usb_gadget_driver *driver;
>>  	struct platform_device *pdev;
>> -	const struct usba_udc_errata *errata;
>> +	const struct usba_udc_caps *caps;
>>  	int irq;
>>  	int vbus_pin;
>>  	int vbus_pin_inverted;
> 
> 
>
Sylvain Rochet Feb. 7, 2015, 7:37 p.m. UTC | #3
Hello Nicolas,


On Thu, Feb 05, 2015 at 06:19:55PM +0100, Nicolas Ferre wrote:
> Le 22/01/2015 18:14, Boris Brezillon a écrit :
> > On Thu, 22 Jan 2015 17:56:44 +0100
> > Sylvain Rochet <sylvain.rochet@finsecur.com> wrote:
> > 
> > > -static const struct usba_udc_errata at91sam9g45_errata = {
> > > +static const struct usba_udc_caps at91sam9g45_caps = {
> > >  	.pulse_bias = at91sam9g45_pulse_bias,
> > > +	.irq_single_edge_support = true,
> 
> Nope! at91sam9g45 doesn't have this property. You'll have to create
> another compatible string and capabilities structure
> ("atmel,at91sam9x5-udc")

Oops.


> But still, I don't know if it's the proper approach. The possibility to
> trigger an IRQ on both edges or a single edge is a capacity of the gpio
> controller, not the USBA IP. So, it's a little bit strange to have this
> capability here.

I agree.


> I don't know if it's actually feasible but trying to configure the IRQ
> on a single edge, testing if it's accepted by the GPIO irq controller
> and if not, falling back to a "both edge" pattern. Doesn't it look like
> a way to workaround this issue nicely? Can you give it a try?

Tried, it works, but it displays the following message from 
__irq_set_trigger() [1] during devm_request_threaded_irq(…, 
IRQF_TRIGGER_RISING, …) on boards which does not support single-edge 
IRQ:

genirq: Setting trigger mode 1 for irq 176 failed (gpio_irq_type+0x0/0x34)

Is it acceptable ?
If not, is udc->caps->irq_single_edge_support boolean acceptable ?
If not, I am ok to drop the feature, this is only a bonus.


Sylvain


[1] http://lxr.free-electrons.com/source/kernel/irq/manage.c#L619
Boris BREZILLON Feb. 8, 2015, 9:24 a.m. UTC | #4
On Sat, 7 Feb 2015 20:37:23 +0100
Sylvain Rochet <sylvain.rochet@finsecur.com> wrote:

> Hello Nicolas,
> 
> 
> On Thu, Feb 05, 2015 at 06:19:55PM +0100, Nicolas Ferre wrote:
> > Le 22/01/2015 18:14, Boris Brezillon a écrit :
> > > On Thu, 22 Jan 2015 17:56:44 +0100
> > > Sylvain Rochet <sylvain.rochet@finsecur.com> wrote:
> > > 
> > > > -static const struct usba_udc_errata at91sam9g45_errata = {
> > > > +static const struct usba_udc_caps at91sam9g45_caps = {
> > > >  	.pulse_bias = at91sam9g45_pulse_bias,
> > > > +	.irq_single_edge_support = true,
> > 
> > Nope! at91sam9g45 doesn't have this property. You'll have to create
> > another compatible string and capabilities structure
> > ("atmel,at91sam9x5-udc")
> 
> Oops.
> 
> 
> > But still, I don't know if it's the proper approach. The possibility to
> > trigger an IRQ on both edges or a single edge is a capacity of the gpio
> > controller, not the USBA IP. So, it's a little bit strange to have this
> > capability here.
> 
> I agree.

Me too (even if I'm the one who proposed this approach in the first
place ;-)).

> 
> 
> > I don't know if it's actually feasible but trying to configure the IRQ
> > on a single edge, testing if it's accepted by the GPIO irq controller
> > and if not, falling back to a "both edge" pattern. Doesn't it look like
> > a way to workaround this issue nicely? Can you give it a try?
> 
> Tried, it works, but it displays the following message from 
> __irq_set_trigger() [1] during devm_request_threaded_irq(…, 
> IRQF_TRIGGER_RISING, …) on boards which does not support single-edge 
> IRQ:
> 
> genirq: Setting trigger mode 1 for irq 176 failed (gpio_irq_type+0x0/0x34)
> 
> Is it acceptable ?

IMHO it's not.

> If not, is udc->caps->irq_single_edge_support boolean acceptable ?

Do you mean keeping the current approach ?
If you do, then maybe you can rework a bit the way you detect the GPIO
controller you depends on: instead of linking this information to the
usba compatible string you could link it to the gpio controller
compatible string.

You can find the gpio controller node thanks to your "vbus-gpio"
property: use the phandle defined in this property to find the gpio
controller node, and once you have the device_node referencing the gpio
controller you can match it with your internal device_id table
(containing 2 entries: one for the at91rm9200 IP and the other for the
at91sam9x5 IP).

Another solution would be to add an irq_try_set_irq_type function that
would not complain when it fails to set the requested trigger.

Thomas, I know you did not follow the whole thread, but would you mind
adding this irq_try_set_irq_type function (here is a reference
implementation [1]), to prevent this error trace from happening when
we're just trying a configuration ?

> If not, I am ok to drop the feature, this is only a bonus.

That could be a short term solution, to get this series accepted. We
could then find a proper way to support that optimization.


Best Regards,

Boris

[1]http://code.bulix.org/z4bu9k-87846
Sylvain Rochet Feb. 12, 2015, 6 p.m. UTC | #5
Hello Boris,

On Sun, Feb 08, 2015 at 10:24:39AM +0100, Boris Brezillon wrote:
> On Sat, 7 Feb 2015 20:37:23 +0100
> Sylvain Rochet <sylvain.rochet@finsecur.com> wrote:
> 
> > If not, is udc->caps->irq_single_edge_support boolean acceptable ?
> 
> Do you mean keeping the current approach ?

Yes!


> If you do, then maybe you can rework a bit the way you detect the GPIO
> controller you depends on: instead of linking this information to the
> usba compatible string you could link it to the gpio controller
> compatible string.
> 
> You can find the gpio controller node thanks to your "vbus-gpio"
> property: use the phandle defined in this property to find the gpio
> controller node, and once you have the device_node referencing the gpio
> controller you can match it with your internal device_id table
> (containing 2 entries: one for the at91rm9200 IP and the other for the
> at91sam9x5 IP).

I have a working PoC for that if this is the chosen solution.


> Another solution would be to add an irq_try_set_irq_type function that
> would not complain when it fails to set the requested trigger.
> 
> Thomas, I know you did not follow the whole thread, but would you mind
> adding this irq_try_set_irq_type function (here is a reference
> implementation [1]), to prevent this error trace from happening when
> we're just trying a configuration ?

This would be great :-)


> > If not, I am ok to drop the feature, this is only a bonus.
> 
> That could be a short term solution, to get this series accepted. We
> could then find a proper way to support that optimization.

I agree, I have the feeling your proposed core change may takes a long 
time, I just sent a v7 without IRQ single edge support.


Sylvain
diff mbox

Patch

diff --git a/drivers/usb/gadget/udc/atmel_usba_udc.c b/drivers/usb/gadget/udc/atmel_usba_udc.c
index d554106..361f740 100644
--- a/drivers/usb/gadget/udc/atmel_usba_udc.c
+++ b/drivers/usb/gadget/udc/atmel_usba_udc.c
@@ -338,8 +338,8 @@  static int vbus_is_present(struct usba_udc *udc)
 
 static void toggle_bias(struct usba_udc *udc, int is_on)
 {
-	if (udc->errata && udc->errata->toggle_bias)
-		udc->errata->toggle_bias(udc, is_on);
+	if (udc->caps && udc->caps->toggle_bias)
+		udc->caps->toggle_bias(udc, is_on);
 }
 
 static void generate_bias_pulse(struct usba_udc *udc)
@@ -347,8 +347,8 @@  static void generate_bias_pulse(struct usba_udc *udc)
 	if (!udc->bias_pulse_needed)
 		return;
 
-	if (udc->errata && udc->errata->pulse_bias)
-		udc->errata->pulse_bias(udc);
+	if (udc->caps && udc->caps->pulse_bias)
+		udc->caps->pulse_bias(udc);
 
 	udc->bias_pulse_needed = false;
 }
@@ -1901,18 +1901,23 @@  static void at91sam9g45_pulse_bias(struct usba_udc *udc)
 	at91_pmc_write(AT91_CKGR_UCKR, uckr | AT91_PMC_BIASEN);
 }
 
-static const struct usba_udc_errata at91sam9rl_errata = {
+static const struct usba_udc_caps at91sam9rl_caps = {
 	.toggle_bias = at91sam9rl_toggle_bias,
 };
 
-static const struct usba_udc_errata at91sam9g45_errata = {
+static const struct usba_udc_caps at91sam9g45_caps = {
 	.pulse_bias = at91sam9g45_pulse_bias,
+	.irq_single_edge_support = true,
+};
+
+static const struct usba_udc_caps sama5d3_caps = {
+	.irq_single_edge_support = true,
 };
 
 static const struct of_device_id atmel_udc_dt_ids[] = {
-	{ .compatible = "atmel,at91sam9rl-udc", .data = &at91sam9rl_errata },
-	{ .compatible = "atmel,at91sam9g45-udc", .data = &at91sam9g45_errata },
-	{ .compatible = "atmel,sama5d3-udc" },
+	{ .compatible = "atmel,at91sam9rl-udc", .data = &at91sam9rl_caps },
+	{ .compatible = "atmel,at91sam9g45-udc", .data = &at91sam9g45_caps },
+	{ .compatible = "atmel,sama5d3-udc", .data = &sama5d3_caps },
 	{ /* sentinel */ }
 };
 
@@ -1934,7 +1939,7 @@  static struct usba_ep * atmel_udc_of_init(struct platform_device *pdev,
 	if (!match)
 		return ERR_PTR(-EINVAL);
 
-	udc->errata = match->data;
+	udc->caps = match->data;
 
 	udc->num_ep = 0;
 
diff --git a/drivers/usb/gadget/udc/atmel_usba_udc.h b/drivers/usb/gadget/udc/atmel_usba_udc.h
index 085749a..4fe4c87 100644
--- a/drivers/usb/gadget/udc/atmel_usba_udc.h
+++ b/drivers/usb/gadget/udc/atmel_usba_udc.h
@@ -304,9 +304,10 @@  struct usba_request {
 	unsigned int				mapped:1;
 };
 
-struct usba_udc_errata {
+struct usba_udc_caps {
 	void (*toggle_bias)(struct usba_udc *udc, int is_on);
 	void (*pulse_bias)(struct usba_udc *udc);
+	bool irq_single_edge_support;
 };
 
 struct usba_udc {
@@ -322,7 +323,7 @@  struct usba_udc {
 	struct usb_gadget gadget;
 	struct usb_gadget_driver *driver;
 	struct platform_device *pdev;
-	const struct usba_udc_errata *errata;
+	const struct usba_udc_caps *caps;
 	int irq;
 	int vbus_pin;
 	int vbus_pin_inverted;