sdio wifi oob irq support for sunxi
Subsystems (5)
cover sdio wifi oob irq support for sunxi
Hi All,
Here is a patch series adding support for oob irqs for the ap6210 sdio wifi modules found on various Allwinner A20 boards.
A lot of it is ground work which should be useful for adding oob irq support to other sdio wifi models too.
The first 5 patches are sunxi pinctrl patches and should go upstream through the pinctrl tree.
Patch 6 adds generic support for having per sdio function child nodes in devicetree and should go upstream through the mmc tree.
Patch 7 and 8 add oob irq support to the brcmfmac driver. Patch 9 pokes some magic bits needed to enable the oob irq, this was taken from an android code dump and good do with a good review from someone from Broadcom, Arend ?
Patch 10 and 11 add the necessary dts bits to actually enable the sdio irq and should go upstream through Maxime's dt tree.
Please review / merge.
Thanks & Regards,
Hans
PATCH 1/11 pinctrl: sunxi: create irq/pin mapping during init
From: Chen-Yu Tsai <[email protected]>
The irq/pin mapping is used to lookup the pin to mux to the irq function when the irq is enabled. It is created when gpio_to_irq is called. Creating the mapping during init allows us to map the interrupts directly from the device tree.
--- drivers/pinctrl/sunxi/pinctrl-sunxi.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/pinctrl/sunxi/pinctrl-sunxi.c +3 -2
@@ -529,8 +529,6 @@ static int sunxi_pinctrl_gpio_to_irq(struct gpio_chip *chip, unsigned offset)if (!desc)return -EINVAL ; - pctl->irq_array[desc->irqnum] = offset; -dev_dbg (chip->dev,"%s: request IRQ for GPIO %d, return %d\n" , chip->label, offset + chip->base, desc->irqnum);
@@ -731,6 +729,9 @@ static int sunxi_pinctrl_build_state(struct platform_device *pdev)struct sunxi_desc_function *func = pin->functions;while (func->name) { +/* Create interrupt mapping while we're at it */ +if (!strcmp (func->name,"irq" )) + pctl->irq_array[func->irqnum] = pin->pin.number;sunxi_pinctrl_add_function (pctl, func->name); func++; }
Signature · 1 line
1.9.3
PATCH 1/11 pinctrl: sunxi: create irq/pin mapping during init
Hi,
Quoted 6 lines · Hans de Goede
From: Chen-Yu Tsai <[email protected]>
The irq/pin mapping is used to lookup the pin to mux to the irq function when the irq is enabled. It is created when
gpio_to_irqis called. Creating the mapping during init allows us to map the interrupts directly from the device tree.
Can you be a bit more precise on this?
What is the issue that this patch fix?
Maxime
Signature · 10 lines
Maxime Ripard, Free Electrons Embedded Linux, Kernel and Android engineering http://free-electrons.com -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140527/b9e1c07b/attachment.sig>
[linux-sunxi] Re: [PATCH 01/11] pinctrl: sunxi: create irq/pin mapping during init
Quoted 5 lines · Maxime Ripard
Hi,
Quoted 2 lines · Hans de Goede
From: Chen-Yu Tsai <[email protected]>
Quoted 8 lines
Quoted 4 lines
The irq/pin mapping is used to lookup the pin to mux to the irq function when the irq is enabled. It is created when
gpio_to_irqis called. Creating the mapping during init allows us to map the interrupts directly from the device tree.Can you be a bit more precise on this?
What is the issue that this patch fix?
IIRC, originally the IRQ to pin mapping was created when gpio_to_irq was called with a GPIO handle. The mapping in turn is used to mux the pin into EINT mode.
If the mapping is created during gpio_to_irq, we can't use the interrupts directly, i.e. through the DT with "interrupts = <&pio A 4>".
Instead we'd have to use "gpios = <&pio A B>", then pass the gpio through to gpio_to_irq.
ChenYu
PATCH 1/11 pinctrl: sunxi: create irq/pin mapping during init
In reply to Hans de GoedeQuoted 9 lines · Hans de Goede
From: Chen-Yu Tsai <[email protected]>
The irq/pin mapping is used to lookup the pin to mux to the irq function when the irq is enabled. It is created when
gpio_to_irqis called. Creating the mapping during init allows us to map the interrupts directly from the device tree.Signed-off-by Chen-Yu Tsai <[email protected]>Signed-off-by Hans de Goede <[email protected]>
This is exactly correct. Patch applied.
I tried to hack the sunxi driver to even use the gpiolib irqchip helpers but exactly this complex map thing in ->irq_array[] git me stuck. If any of you guys could be so nice to take a stab at this (compare to other commits converting drivers to use gpiolibs irqchip helpers) then I'd be very happy.
Yours,
Linus Walleij
[linux-sunxi] Re: [PATCH 01/11] pinctrl: sunxi: create irq/pin mapping during init
Quoted 9 lines · Linus Walleij
Quoted 7 lines · Hans de Goede
From: Chen-Yu Tsai <[email protected]>
The irq/pin mapping is used to lookup the pin to mux to the irq function when the irq is enabled. It is created when
gpio_to_irqis called. Creating the mapping during init allows us to map the interrupts directly from the device tree.
Quoted 4 lines
Quoted 2 lines
Signed-off-by Chen-Yu Tsai <[email protected]>Signed-off-by Hans de Goede <[email protected]>This is exactly correct. Patch applied.
Thanks.
Quoted 6 lines
I tried to hack the sunxi driver to even use the gpiolib irqchip helpers but exactly this complex map thing in ->irq_array[] git me stuck. If any of you guys could be so nice to take a stab at this (compare to other commits converting drivers to use gpiolibs irqchip helpers) then I'd be very happy.
We still need to rework the whole irqchip stuff for sun6i/sun8i, which have 1 parent interrupt per EINT capable pin bank.
Earlier discussions with Maxime (on IRC IIRC) suggested moving this over to gpiolib irqchip helpers might be more work than using our own irqchip implementation, requiring 1 gpiochip per pin group? (not sure)
ChenYu
[linux-sunxi] Re: [PATCH 01/11] pinctrl: sunxi: create irq/pin mapping during init
Quoted 9 lines · Chen-Yu Tsai
On Tue, May 27, 2014 at 10:11 PM, Linus Walleij
Quoted 6 lines
I tried to hack the sunxi driver to even use the gpiolib irqchip helpers but exactly this complex map thing in ->irq_array[] git me stuck. If any of you guys could be so nice to take a stab at this (compare to other commits converting drivers to use gpiolibs irqchip helpers) then I'd be very happy.
Quoted 6 lines
We still need to rework the whole irqchip stuff for sun6i/sun8i, which have 1 parent interrupt per EINT capable pin bank.
Earlier discussions with Maxime (on IRC IIRC) suggested moving this over to gpiolib irqchip helpers might be more work than using our own irqchip implementation, requiring 1 gpiochip per pin group? (not sure)
OK then keep your current code. I do not intend to cover all cases in the world with these helpers, just the simple cases. Complex hardware merits complex code.
Yours,
Linus Walleij
PATCH 2/11 pinctrl: sunxi: add IRQCHIP_SKIP_SET_WAKE flag for pinctrl irq chip
In reply to Hans de GoedeFrom: Chen-Yu Tsai <[email protected]>
The sunxi pinctrl irq chip driver does not support wakeup at the moment. Adding IRQCHIP_SKIP_SET_WAKE lets the irqs work with drivers using wakeup.
Also add a name to the irq chip.
--- drivers/pinctrl/sunxi/pinctrl-sunxi.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/pinctrl/sunxi/pinctrl-sunxi.c +2 -0
@@ -646,6 +646,8 @@ static struct irq_chip sunxi_pinctrl_irq_chip = { .irq_mask_ack = sunxi_pinctrl_irq_mask_ack, .irq_unmask = sunxi_pinctrl_irq_unmask, .irq_set_type = sunxi_pinctrl_irq_set_type, + .name = "sunxi-pio", + .flags = IRQCHIP_SKIP_SET_WAKE, };static void sunxi_pinctrl_irq_handler (unsigned irq,struct irq_desc *desc)
Signature · 1 line
1.9.3
PATCH 2/11 pinctrl: sunxi: add IRQCHIP_SKIP_SET_WAKE flag for pinctrl irq chip
Quoted 19 lines · Hans de Goede
From: Chen-Yu Tsai <[email protected]>
The sunxi pinctrl irq chip driver does not support wakeup at the moment. Adding
IRQCHIP_SKIP_SET_WAKElets the irqs work with drivers using wakeup.Also add a name to the irq chip.
Signed-off-by Chen-Yu Tsai <[email protected]>Signed-off-by Hans de Goede <[email protected]>--- drivers/pinctrl/sunxi/pinctrl-sunxi.c | 2 ++ 1 file changed, 2 insertions(+)drivers/pinctrl/sunxi/pinctrl-sunxi.c +0
-0
drivers/pinctrl/sunxi/pinctrl-sunxi.c static struct irq_chip sunxi_pinctrl_irq_chip = { · line 650
Quoted 5 lines
drivers/pinctrl/sunxi/pinctrl-sunxi.c +2
-0@@ -646,6 +646,8 @@ static struct irq_chip sunxi_pinctrl_irq_chip = { .irq_mask_ack = sunxi_pinctrl_irq_mask_ack, .irq_unmask = sunxi_pinctrl_irq_unmask, .irq_set_type = sunxi_pinctrl_irq_set_type, + .name = "sunxi-pio", + .flags = IRQCHIP_SKIP_SET_WAKE,
I'd rather see the name set to dev_name() or something like that. This will not work that great with multiple pin controller supporting interrupts.
Maxime
Signature · 10 lines
Maxime Ripard, Free Electrons Embedded Linux, Kernel and Android engineering http://free-electrons.com -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140527/bd65fcd8/attachment.sig>
PATCH 2/11 pinctrl: sunxi: add IRQCHIP_SKIP_SET_WAKE flag for pinctrl irq chip
Hi,
Quoted 15 lines · Maxime Ripard
Quoted 14 lines · Hans de Goede
From: Chen-Yu Tsai <[email protected]>
The sunxi pinctrl irq chip driver does not support wakeup at the moment. Adding
IRQCHIP_SKIP_SET_WAKElets the irqs work with drivers using wakeup.Also add a name to the irq chip.
Signed-off-by Chen-Yu Tsai <[email protected]>Signed-off-by Hans de Goede <[email protected]>--- drivers/pinctrl/sunxi/pinctrl-sunxi.c | 2 ++ 1 file changed, 2 insertions(+)
Quoted 14 lines
drivers/pinctrl/sunxi/pinctrl-sunxi.c static struct irq_chip sunxi_pinctrl_irq_chip = { · line 650
Quoted 10 lines
drivers/pinctrl/sunxi/pinctrl-sunxi.c +2
-0@@ -646,6 +646,8 @@ static struct irq_chip sunxi_pinctrl_irq_chip = { .irq_mask_ack = sunxi_pinctrl_irq_mask_ack, .irq_unmask = sunxi_pinctrl_irq_unmask, .irq_set_type = sunxi_pinctrl_irq_set_type, + .name = "sunxi-pio", + .flags = IRQCHIP_SKIP_SET_WAKE,I'd rather see the name set to
dev_name()or something like that. This will not work that great with multiple pin controller supporting interrupts.
That would require moving the irq_chip struct to become a member of the sunxi_pinctrl struct. Not undoable, but that seems like something which should be done in a separate patch. So shall I just drop the .name part of this patch for now ?
Regards,
Hans
PATCH 2/11 pinctrl: sunxi: add IRQCHIP_SKIP_SET_WAKE flag for pinctrl irq chip
Quoted 33 lines · Hans de Goede
Hi,
Quoted 15 lines · Maxime Ripard
Quoted 14 lines · Hans de Goede
From: Chen-Yu Tsai <[email protected]>
The sunxi pinctrl irq chip driver does not support wakeup at the moment. Adding
IRQCHIP_SKIP_SET_WAKElets the irqs work with drivers using wakeup.Also add a name to the irq chip.
Signed-off-by Chen-Yu Tsai <[email protected]>Signed-off-by Hans de Goede <[email protected]>--- drivers/pinctrl/sunxi/pinctrl-sunxi.c | 2 ++ 1 file changed, 2 insertions(+)Quoted 14 lines
drivers/pinctrl/sunxi/pinctrl-sunxi.c static struct irq_chip sunxi_pinctrl_irq_chip = { · line 650
Quoted 10 lines
drivers/pinctrl/sunxi/pinctrl-sunxi.c +2
-0@@ -646,6 +646,8 @@ static struct irq_chip sunxi_pinctrl_irq_chip = { .irq_mask_ack = sunxi_pinctrl_irq_mask_ack, .irq_unmask = sunxi_pinctrl_irq_unmask, .irq_set_type = sunxi_pinctrl_irq_set_type, + .name = "sunxi-pio", + .flags = IRQCHIP_SKIP_SET_WAKE,I'd rather see the name set to
dev_name()or something like that. This will not work that great with multiple pin controller supporting interrupts.
Quoted 4 lines
That would require moving the
irq_chipstruct to become a member of thesunxi_pinctrlstruct. Not undoable, but that seems like something which should be done in a separate patch. So shall I just drop the .name part of this patch for now ?
Please do. AFAIK, .name is only used for the debugfs representation. This change was only meant for cosmetic purposes.
ChenYu
PATCH 2/11 pinctrl: sunxi: add IRQCHIP_SKIP_SET_WAKE flag for pinctrl irq chip
In reply to Maxime RipardQuoted 14 lines · Maxime Ripard
Quoted 13 lines · Hans de Goede
From: Chen-Yu Tsai <[email protected]>
The sunxi pinctrl irq chip driver does not support wakeup at the moment. Adding
IRQCHIP_SKIP_SET_WAKElets the irqs work with drivers using wakeup.Also add a name to the irq chip.
Signed-off-by Chen-Yu Tsai <[email protected]> Signed-off-by: Hansde Goede <[email protected]> ---
drivers/pinctrl/sunxi/pinctrl-sunxi.c| 2 ++ 1 file changed, 2 insertions(+)
Quoted 13 lines
Quoted 9 lines
(quoted diff) +0
-0
b/drivers/pinctrl/sunxi/pinctrl-sunxi.cindex db9ccd6..ec60c2e 100644 ---a/drivers/pinctrl/sunxi/pinctrl-sunxi.c+++b/drivers/pinctrl/sunxi/pinctrl-sunxi.c@@ -646,6 +646,8 @@
static structirq_chipsunxi_pinctrl_irq_chip= { .irq_mask_ack =sunxi_pinctrl_irq_mask_ack, .irq_unmask =sunxi_pinctrl_irq_unmask, .irq_set_type =sunxi_pinctrl_irq_set_type, + .name = "sunxi-pio", + .flags =IRQCHIP_SKIP_SET_WAKE,I'd rather see the name set to
dev_name()or something like that. This will not work that great with multiple pin controller supporting interrupts.
Correct me if I'm wrong, but I've always thought that struct irq_chip describes a class of IRQ controllers, not particular instances.
Best regards,
Tomasz
PATCH 2/11 pinctrl: sunxi: add IRQCHIP_SKIP_SET_WAKE flag for pinctrl irq chip
Quoted 29 lines · Tomasz Figa
Quoted 14 lines · Maxime Ripard
Quoted 13 lines · Hans de Goede
From: Chen-Yu Tsai <[email protected]>
The sunxi pinctrl irq chip driver does not support wakeup at the moment. Adding
IRQCHIP_SKIP_SET_WAKElets the irqs work with drivers using wakeup.Also add a name to the irq chip.
Signed-off-by Chen-Yu Tsai <[email protected]> Signed-off-by: Hansde Goede <[email protected]> ---
drivers/pinctrl/sunxi/pinctrl-sunxi.c| 2 ++ 1 file changed, 2 insertions(+)Quoted 13 lines
Quoted 9 lines
(quoted diff) +0
-0
b/drivers/pinctrl/sunxi/pinctrl-sunxi.cindex db9ccd6..ec60c2e 100644 ---a/drivers/pinctrl/sunxi/pinctrl-sunxi.c+++b/drivers/pinctrl/sunxi/pinctrl-sunxi.c@@ -646,6 +646,8 @@
static structirq_chipsunxi_pinctrl_irq_chip= { .irq_mask_ack =sunxi_pinctrl_irq_mask_ack, .irq_unmask =sunxi_pinctrl_irq_unmask, .irq_set_type =sunxi_pinctrl_irq_set_type, + .name = "sunxi-pio", + .flags =IRQCHIP_SKIP_SET_WAKE,I'd rather see the name set to
dev_name()or something like that. This will not work that great with multiple pin controller supporting interrupts.
Quoted 2 lines
Correct me if I'm wrong, but I've always thought that struct
irq_chipdescribes a class of IRQ controllers, not particular instances.
It's not said as such in <linux/irq.h>, but maybe..
Maxime
Signature · 10 lines
Maxime Ripard, Free Electrons Embedded Linux, Kernel and Android engineering http://free-electrons.com -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140528/50f075cd/attachment.sig>
PATCH 2/11 pinctrl: sunxi: add IRQCHIP_SKIP_SET_WAKE flag for pinctrl irq chip
Quoted 31 lines · Maxime Ripard
Quoted 30 lines · Tomasz Figa
Quoted 28 lines · Maxime Ripard
Quoted 14 lines · Hans de Goede
From: Chen-Yu Tsai <[email protected]>
The sunxi pinctrl irq chip driver does not support wakeup at the moment. Adding
IRQCHIP_SKIP_SET_WAKElets the irqs work with drivers using wakeup.Also add a name to the irq chip.
Signed-off-by Chen-Yu Tsai <[email protected]> Signed-off-by:Hans de Goede <[email protected]> ---
drivers/pinctrl/sunxi/pinctrl-sunxi.c| 2 ++ 1 file changed, 2 insertions(+)(quoted diff) +0
-0Quoted 9 lines
b/drivers/pinctrl/sunxi/pinctrl-sunxi.cindex db9ccd6..ec60c2e 100644 ---a/drivers/pinctrl/sunxi/pinctrl-sunxi.c+++b/drivers/pinctrl/sunxi/pinctrl-sunxi.c@@ -646,6 +646,8 @@ static structirq_chipsunxi_pinctrl_irq_chip= {
.irq_mask_ack =sunxi_pinctrl_irq_mask_ack, .irq_unmask =sunxi_pinctrl_irq_unmask, .irq_set_type =sunxi_pinctrl_irq_set_type, + .name = "sunxi-pio", + .flags
=IRQCHIP_SKIP_SET_WAKE,I'd rather see the name set to
dev_name()or something like that. This will not work that great with multiple pin controller supporting interrupts.
Quoted 5 lines
Quoted 3 lines
Correct me if I'm wrong, but I've always thought that struct
irq_chipdescribes a class of IRQ controllers, not particular instances.It's not said as such in <
linux/irq.h>, but maybe..
It is not said the otherwise as well, so hopefully someone could clarify this. Thomas?
My conclusion about the purpose of this struct is based on its contents - name, flags and a number of callbacks, nothing that could be per-instance of identical chips. Moreover there is per interrupt chip_data, which is usually used to store per-instance data by irqchip drivers.
Best regards,
Tomasz
PATCH 3/11 pinctrl: sunxi: Move setting of mux to irq type from unmask to set_type
In reply to Hans de GoedeWith level triggered interrupt mask / unmask will get called for each interrupt, doing the somewhat expensive mux setting on each unmask thus is not a good idea. Instead move it to the set_type callback, which is typically done only once for each irq.
--- drivers/pinctrl/sunxi/pinctrl-sunxi.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-)
drivers/pinctrl/sunxi/pinctrl-sunxi.c +7 -8
@@ -542,6 +542,7 @@ static int sunxi_pinctrl_irq_set_type(struct irq_data *d,struct sunxi_pinctrl *pctl =irq_data_get_irq_chip_data (d);u32 reg =sunxi_irq_cfg_reg (d->hwirq);u8 index =sunxi_irq_cfg_offset (d->hwirq); +struct sunxi_desc_function *func;unsigned long flags;u32 regval;u8 mode;
@@ -574,6 +575,12 @@ static int sunxi_pinctrl_irq_set_type(struct irq_data *d,spin_unlock_irqrestore (&pctl->lock, flags); + func =sunxi_pinctrl_desc_find_function_by_pin (pctl, + pctl->irq_array[d->hwirq],"irq" ); + +/* Change muxing to INT mode */ +sunxi_pmx_set (pctl->pctl_dev, pctl->irq_array[d->hwirq], func->muxval); +return 0 ; }
@@ -619,19 +626,11 @@ static void sunxi_pinctrl_irq_mask(struct irq_data *d)static void sunxi_pinctrl_irq_unmask (struct irq_data *d) {struct sunxi_pinctrl *pctl =irq_data_get_irq_chip_data (d); -struct sunxi_desc_function *func;u32 reg =sunxi_irq_ctrl_reg (d->hwirq);u8 idx =sunxi_irq_ctrl_offset (d->hwirq);unsigned long flags;u32 val; - func =sunxi_pinctrl_desc_find_function_by_pin (pctl, - pctl->irq_array[d->hwirq], -"irq" ); - -/* Change muxing to INT mode */ -sunxi_pmx_set (pctl->pctl_dev, pctl->irq_array[d->hwirq], func->muxval); -spin_lock_irqsave (&pctl->lock, flags);/* Unmask the IRQ */
Signature · 1 line
1.9.3
PATCH 3/11 pinctrl: sunxi: Move setting of mux to irq type from unmask to set_type
Quoted 4 lines · Hans de Goede
With level triggered interrupt mask / unmask will get called for each interrupt, doing the somewhat expensive mux setting on each unmask thus is not a good idea. Instead move it to the
set_typecallback, which is typically done only once for each irq.
*This* is the bad idea. Nothing prevents you from calling gpio_get_value whenever you just got your interrupt, that will change the muxing, and never change it back, effectively breaking the interrupts.
Maxime
Signature · 10 lines
Maxime Ripard, Free Electrons Embedded Linux, Kernel and Android engineering http://free-electrons.com -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140527/89e7eb9c/attachment.sig>
PATCH 3/11 pinctrl: sunxi: Move setting of mux to irq type from unmask to set_type
Hi,
Quoted 10 lines · Maxime Ripard
Quoted 4 lines · Hans de Goede
With level triggered interrupt mask / unmask will get called for each interrupt, doing the somewhat expensive mux setting on each unmask thus is not a good idea. Instead move it to the
set_typecallback, which is typically done only once for each irq.*This* is the bad idea. Nothing prevents you from calling
gpio_get_valuewhenever you just got your interrupt, that will change the muxing, and never change it back, effectively breaking the interrupts.
Hmm, interesting point, but your assuming 2 things which are both not true:
1) That calling gpiod_get_value changes the muxing, which is not true, all gpiod_get_value variants end up in drivers/gpio/gpiolib.c _gpiod_get_raw_value() which does no such thing
2) That unmask will always get called after the gpio_get_value to restore the mux setting for us, which is not guaranteed at all. Before this patch set pinctrl-sunxi.c was using handle_simple_irq which does not mask / unmask at all.
And even with an irq-handler which masks / unmasks, what if the irq wakes up a thread and that thread then does the gpio_get_value ?
Note this is *exactly* what e.g. the mmc gpio card-detect code does, it uses a thread to read the gpio for debouncing.
Luckily 2. is not a problem, since 1. means that the mux won't get changed at all so we don't need to change it back.
Regards,
Hans
PATCH 3/11 pinctrl: sunxi: Move setting of mux to irq type from unmask to set_type
Quoted 14 lines · Hans de Goede
Hi,
Quoted 10 lines · Maxime Ripard
Quoted 4 lines · Hans de Goede
With level triggered interrupt mask / unmask will get called for each interrupt, doing the somewhat expensive mux setting on each unmask thus is not a good idea. Instead move it to the
set_typecallback, which is typically done only once for each irq.*This* is the bad idea. Nothing prevents you from calling
gpio_get_valuewhenever you just got your interrupt, that will change the muxing, and never change it back, effectively breaking the interrupts.
Quoted 5 lines
Hmm, interesting point, but your assuming 2 things which are both not true:
1) That calling
gpiod_get_valuechanges the muxing, which is not true, allgpiod_get_valuevariants end up indrivers/gpio/gpiolib.c_gpiod_get_raw_value()which does no such thing
Somehow I was convinced it was the case, but yeah, it doesn't really make much sense, especially since you can get the value of an output, without wanting to change it to input.
Quoted 5 lines
2) That unmask will always get called after the
gpio_get_valueto restore the mux setting for us, which is not guaranteed at all. Before this patch setpinctrl-sunxi.cwas usinghandle_simple_irqwhich does not mask / unmask at all.
Quoted 8 lines
And even with an irq-handler which masks / unmasks, what if the irq wakes up a thread and that thread then does the
gpio_get_value?Note this is *exactly* what e.g. the mmc gpio card-detect code does, it uses a thread to read the gpio for debouncing.
Luckily 2. is not a problem, since 1. means that the mux won't get changed at all so we don't need to change it back.
Ok.
Maxime
Signature · 10 lines
Maxime Ripard, Free Electrons Embedded Linux, Kernel and Android engineering http://free-electrons.com -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140528/f07876e3/attachment.sig>
PATCH 3/11 pinctrl: sunxi: Move setting of mux to irq type from unmask to set_type
In reply to Hans de GoedeQuoted 6 lines · Hans de Goede
With level triggered interrupt mask / unmask will get called for each interrupt, doing the somewhat expensive mux setting on each unmask thus is not a good idea. Instead move it to the
set_typecallback, which is typically done only once for each irq.Signed-off-by Hans de Goede <[email protected]>
Yes move it out of mask/unmask but no, not into set_type().
Can you not use the irqchip startup()/shutdown() callbacks instead?
And how come we have no clean separation between gpiochip and the pinmux parts here, why cant we just call pinctrl_request_gpio() and pinctrl_free_gpio() here instead? Or maybe pinctrl_gpio_direction_input() and have that set up the muxing in the pinctrl driver side?
It looks slightly convoluted.
Yours,
Linus Walleij
PATCH 3/11 pinctrl: sunxi: Move setting of mux to irq type from unmask to set_type
Quoted 7 lines · Linus Walleij
Quoted 5 lines · Hans de Goede
With level triggered interrupt mask / unmask will get called for each interrupt, doing the somewhat expensive mux setting on each unmask thus is not a good idea. Instead move it to the
set_typecallback, which is typically done only once for each irq.
Quoted 6 lines
Quoted 1 line
Signed-off-by Hans de Goede <[email protected]>Yes move it out of mask/unmask but no, not into
set_type().Can you not use the irqchip startup()/shutdown() callbacks instead?
I think we can use irq_request_resources then
https://lkml.org/lkml/2014/3/12/307
We could even merge the gpio_to_irq code into it.
It's called in __setup_irq, so it's guaranteed to be called, and it will bail out early without doing anything, since it's one of the first thing __setup_irq does.
Quoted 5 lines
And how come we have no clean separation between gpiochip and the pinmux parts here, why cant we just call
pinctrl_request_gpio()andpinctrl_free_gpio()here instead? Or maybepinctrl_gpio_direction_input()and have that set up the muxing in the pinctrl driver side?
Because the function it has to be muxed to is neither gpio_in or gpio_out, and it's not even considered a gpio. It really is just another muxing function, like i2c or mmc.
Maxime
Signature · 10 lines
Maxime Ripard, Free Electrons Embedded Linux, Kernel and Android engineering http://free-electrons.com -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140528/e08db759/attachment.sig>
PATCH 3/11 pinctrl: sunxi: Move setting of mux to irq type from unmask to set_type
Hi,
Quoted 10 lines · Maxime Ripard
Quoted 9 lines · Linus Walleij
Quoted 6 lines · Hans de Goede
With level triggered interrupt mask / unmask will get called for each interrupt, doing the somewhat expensive mux setting on each unmask thus is not a good idea. Instead move it to the
set_typecallback, which is typically done only once for each irq.Signed-off-by Hans de Goede <[email protected]>
Quoted 7 lines
Quoted 4 lines
Yes move it out of mask/unmask but no, not into
set_type().Can you not use the irqchip startup()/shutdown() callbacks instead?
I think we can use
irq_request_resourcesthen
https://lkml.org/lkml/2014/3/12/307
Sounds good, I'll modify the patch to move it here before posting a v2 of this series. Note v2 likely won't happen till this weekend, -ENOTIME.
Quoted 1 line
We could even merge the
gpio_to_irqcode into it.
Erm, no we need that as a separate function for the gpio_chip's to_irq callback.
Quoted 3 lines
It's called in
__setup_irq, so it's guaranteed to be called, and it will bail out early without doing anything, since it's one of the first thing__setup_irqdoes.
Right, as I said above, this sounds good.
Regards,
Hans
PATCH 3/11 pinctrl: sunxi: Move setting of mux to irq type from unmask to set_type
Quoted 21 lines · Hans de Goede
Hi,
Quoted 10 lines · Maxime Ripard
Quoted 9 lines · Linus Walleij
Quoted 6 lines · Hans de Goede
With level triggered interrupt mask / unmask will get called for each interrupt, doing the somewhat expensive mux setting on each unmask thus is not a good idea. Instead move it to the
set_typecallback, which is typically done only once for each irq.Signed-off-by Hans de Goede <[email protected]>Quoted 7 lines
Quoted 4 lines
Yes move it out of mask/unmask but no, not into
set_type().Can you not use the irqchip startup()/shutdown() callbacks instead?
I think we can use
irq_request_resourcesthen
https://lkml.org/lkml/2014/3/12/307
Quoted 7 lines
Sounds good, I'll modify the patch to move it here before posting a v2 of this series. Note v2 likely won't happen till this weekend,
-ENOTIME.Quoted 1 line
We could even merge the
gpio_to_irqcode into it.Erm, no we need that as a separate function for the gpio_chip's
to_irqcallback.
Linus sent a patch stating otherwise a few weeks ago, and was suggesting moving it to irq_startup.
https://lkml.org/lkml/2014/5/9/50
Maxime
Signature · 10 lines
Maxime Ripard, Free Electrons Embedded Linux, Kernel and Android engineering http://free-electrons.com -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140528/4f0e6e7a/attachment.sig>
PATCH 3/11 pinctrl: sunxi: Move setting of mux to irq type from unmask to set_type
Hi,
Quoted 27 lines · Maxime Ripard
Quoted 26 lines · Hans de Goede
Hi,
Quoted 10 lines · Maxime Ripard
Quoted 9 lines · Linus Walleij
Quoted 6 lines · Hans de Goede
With level triggered interrupt mask / unmask will get called for each interrupt, doing the somewhat expensive mux setting on each unmask thus is not a good idea. Instead move it to the
set_typecallback, which is typically done only once for each irq.Signed-off-by Hans de Goede <[email protected]>Quoted 7 lines
Quoted 4 lines
Yes move it out of mask/unmask but no, not into
set_type().Can you not use the irqchip startup()/shutdown() callbacks instead?
I think we can use
irq_request_resourcesthen
https://lkml.org/lkml/2014/3/12/307Sounds good, I'll modify the patch to move it here before posting a v2 of this series. Note v2 likely won't happen till this weekend,
-ENOTIME.Quoted 1 line
We could even merge the
gpio_to_irqcode into it.
Quoted 7 lines
Quoted 2 lines
Erm, no we need that as a separate function for the gpio_chip's
to_irqcallback.Linus sent a patch stating otherwise a few weeks ago, and was suggesting moving it to
irq_startup.
That is not going to work, that patch uses gpiochip_irqchip_add, which in turn uses gpiochip_to_irq as to_irq handler, which assumes that gpio offset == irq offset, which is not true for sunxi-pinctrl.
Specifically gpio_chio_to_irq does:
static int gpiochip_to_irq(struct gpio_chip *chip, unsigned offset)
{
return irq_find_mapping(chip->irqdomain, offset);
}Where as the sunxi code does (simplified):
static int sunxi_pinctrl_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
{
struct sunxi_desc_function *desc = sunxi_pinctrl_desc_find_function_by_pin(pctl, offset, "irq");
return irq_find_mapping(pctl->domain, desc->irqnum);\
}Note the extra level of indirection.
Regards,
Hans
PATCH 3/11 pinctrl: sunxi: Move setting of mux to irq type from unmask to set_type
Quoted 50 lines · Hans de Goede
Hi,
Quoted 27 lines · Maxime Ripard
Quoted 26 lines · Hans de Goede
Hi,
Quoted 10 lines · Maxime Ripard
Quoted 9 lines · Linus Walleij
Quoted 6 lines · Hans de Goede
With level triggered interrupt mask / unmask will get called for each interrupt, doing the somewhat expensive mux setting on each unmask thus is not a good idea. Instead move it to the
set_typecallback, which is typically done only once for each irq.Signed-off-by Hans de Goede <[email protected]>Quoted 7 lines
Quoted 4 lines
Yes move it out of mask/unmask but no, not into
set_type().Can you not use the irqchip startup()/shutdown() callbacks instead?
I think we can use
irq_request_resourcesthen
https://lkml.org/lkml/2014/3/12/307Sounds good, I'll modify the patch to move it here before posting a v2 of this series. Note v2 likely won't happen till this weekend,
-ENOTIME.Quoted 1 line
We could even merge the
gpio_to_irqcode into it.Quoted 7 lines
Quoted 2 lines
Erm, no we need that as a separate function for the gpio_chip's
to_irqcallback.Linus sent a patch stating otherwise a few weeks ago, and was suggesting moving it to
irq_startup.That is not going to work, that patch uses
gpiochip_irqchip_add, which in turn usesgpiochip_to_irqasto_irqhandler, which assumes that gpio offset == irq offset, which is not true for sunxi-pinctrl.Specifically
gpio_chio_to_irqdoes:static int
gpiochip_to_irq(struct gpio_chip *chip, unsigned offset){ return irq_find_mapping(chip->irqdomain, offset); }
Quoted 7 lines
Where as the sunxi code does (simplified):
static int
sunxi_pinctrl_gpio_to_irq(struct gpio_chip *chip, unsigned offset){ struct sunxi_desc_function *desc = sunxi_pinctrl_desc_find_function_by_pin(pctl, offset, "irq"); return irq_find_mapping(pctl->domain, desc->irqnum);\ }
Yes, I know it's not going to work, but my point was that gpio_to_irq might not be called by the drivers, and it's still valid not to do it. So we might end up with a driver requesting an interrupt that won't be muxed to it.
But thinking more about it, it would be wrong to remove the .to_irq callback completely either, since drivers might need a "secondary" interrupt (like the card detect one for an MMC driver), and a lot of these use an additional gpio property to do so. So we need to keep it.
Nevermind then.
Maxime
Signature · 10 lines
Maxime Ripard, Free Electrons Embedded Linux, Kernel and Android engineering http://free-electrons.com -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140602/25fca981/attachment.sig>
PATCH 4/11 pinctrl: sunxi: Properly handle level triggered gpio interrupts
In reply to Hans de GoedeFor level triggered gpio interrupts we need to use handle_fasteoi_irq, like we do with the irq-sunxi-nmi driver. This is necessary to give threaded interrupt handlers a chance to actuall clear the source of the interrupt (which may involve sleeping waitnig for i2c / spi / mmc transfers), before acknowledging the interrupt.
--- drivers/pinctrl/sunxi/pinctrl-sunxi.c | 71 +++++++++++++++++++++++++++-------- 1 file changed, 56 insertions(+), 15 deletions(-)
drivers/pinctrl/sunxi/pinctrl-sunxi.c +56 -15
@@ -31,6 +31,12 @@#include "../core.h" #include "pinctrl-sunxi.h" +static int sunxi_pinctrl_irq_set_type (struct irq_data *d,unsigned int type); +static void sunxi_pinctrl_irq_mask_ack (struct irq_data *d); +static void sunxi_pinctrl_irq_mask (struct irq_data *d); +static void sunxi_pinctrl_irq_unmask (struct irq_data *d); +static void sunxi_pinctrl_irq_ack (struct irq_data *d); +static struct sunxi_pinctrl_group *sunxi_pinctrl_find_group_by_name (struct sunxi_pinctrl *pctl,const char *group) {
@@ -535,11 +541,31 @@ static int sunxi_pinctrl_gpio_to_irq(struct gpio_chip *chip, unsigned offset)return irq_find_mapping (pctl->domain, desc->irqnum); } +static struct irq_chip sunxi_pinctrl_edge_irq_chip = { + .irq_mask = sunxi_pinctrl_irq_mask, + .irq_mask_ack = sunxi_pinctrl_irq_mask_ack, + .irq_unmask = sunxi_pinctrl_irq_unmask, + .irq_ack = sunxi_pinctrl_irq_ack, + .irq_set_type = sunxi_pinctrl_irq_set_type, + .name ="sunxi-pio" , + .flags =IRQCHIP_SKIP_SET_WAKE , +}; + +static struct irq_chip sunxi_pinctrl_level_irq_chip = { + .irq_mask = sunxi_pinctrl_irq_mask, + .irq_mask_ack = sunxi_pinctrl_irq_mask_ack, + .irq_unmask = sunxi_pinctrl_irq_unmask, + .irq_eoi = sunxi_pinctrl_irq_ack, + .irq_set_type = sunxi_pinctrl_irq_set_type, + .name ="sunxi-pio" , + .flags =IRQCHIP_SKIP_SET_WAKE |IRQCHIP_EOI_THREADED | +IRQCHIP_EOI_IF_HANDLED , +}; -static int sunxi_pinctrl_irq_set_type (struct irq_data *d, -unsigned int type) +static int sunxi_pinctrl_irq_set_type (struct irq_data *d,unsigned int type) {struct sunxi_pinctrl *pctl =irq_data_get_irq_chip_data (d); + struct irq_desc *desc = container_of(d, struct irq_desc, irq_data);u32 reg =sunxi_irq_cfg_reg (d->hwirq);u8 index =sunxi_irq_cfg_offset (d->hwirq);struct sunxi_desc_function *func;
@@ -567,6 +593,14 @@ static int sunxi_pinctrl_irq_set_type(struct irq_data *d,return -EINVAL ; } +if (type &IRQ_TYPE_LEVEL_MASK ) { + d->chip = &sunxi_pinctrl_level_irq_chip; + desc->handle_irq = handle_fasteoi_irq; + }else { + d->chip = &sunxi_pinctrl_edge_irq_chip; + desc->handle_irq = handle_edge_irq; + } +spin_lock_irqsave (&pctl->lock, flags); regval =readl (pctl->membase + reg);
@@ -640,14 +674,20 @@ static void sunxi_pinctrl_irq_unmask(struct irq_data *d)spin_unlock_irqrestore (&pctl->lock, flags); } -static struct irq_chip sunxi_pinctrl_irq_chip = { - .irq_mask = sunxi_pinctrl_irq_mask, - .irq_mask_ack = sunxi_pinctrl_irq_mask_ack, - .irq_unmask = sunxi_pinctrl_irq_unmask, - .irq_set_type = sunxi_pinctrl_irq_set_type, - .name ="sunxi-pio" , - .flags =IRQCHIP_SKIP_SET_WAKE , -}; +static void sunxi_pinctrl_irq_ack (struct irq_data *d) +{ +struct sunxi_pinctrl *pctl =irq_data_get_irq_chip_data (d); +u32 status_reg =sunxi_irq_status_reg (d->hwirq); +u8 status_idx =sunxi_irq_status_offset (d->hwirq); +unsigned long flags; + +spin_lock_irqsave (&pctl->lock, flags); + +/* Clear the IRQ */ +writel (1 << status_idx, pctl->membase + status_reg); + +spin_unlock_irqrestore (&pctl->lock, flags); +}static void sunxi_pinctrl_irq_handler (unsigned irq,struct irq_desc *desc) {
@@ -655,9 +695,6 @@ static void sunxi_pinctrl_irq_handler(unsigned irq, struct irq_desc *desc)struct sunxi_pinctrl *pctl =irq_get_handler_data (irq);const unsigned long reg =readl (pctl->membase +IRQ_STATUS_REG ); -/* Clear all interrupts */ -writel (reg, pctl->membase +IRQ_STATUS_REG ); -if (reg) {int irqoffset;
@@ -892,11 +929,15 @@ int sunxi_pinctrl_init(struct platform_device *pdev,for (i =0 ; i <SUNXI_IRQ_NUMBER ; i++) {int irqno =irq_create_mapping (pctl->domain, i); -irq_set_chip_and_handler (irqno, &sunxi_pinctrl_irq_chip, - handle_simple_irq); +irq_set_chip_and_handler (irqno, &sunxi_pinctrl_edge_irq_chip, + handle_edge_irq);irq_set_chip_data (irqno, pctl); }; +/* Mask and clear all IRQs before registering a handler */ +writel (0 , pctl->membase +IRQ_CTRL_REG ); +writel (0xffffffff , pctl->membase +IRQ_STATUS_REG ); +irq_set_chained_handler (pctl->irq, sunxi_pinctrl_irq_handler);irq_set_handler_data (pctl->irq, pctl);
Signature · 1 line
1.9.3
PATCH 4/11 pinctrl: sunxi: Properly handle level triggered gpio interrupts
Quoted 7 lines · Hans de Goede
For level triggered gpio interrupts we need to use
handle_fasteoi_irq, like we do with the irq-sunxi-nmi driver. This is necessary to give threaded interrupt handlers a chance to actuall clear the source of the interrupt (which may involve sleeping waitnig for i2c / spi / mmc transfers), before acknowledging the interrupt.Signed-off-by Hans de Goede <[email protected]>
I haven't seen any feedback on the pin controller patches in this series from Maxime, I might have missed it due to being tied to some other patch in the series.
Anyway, this needs to be rebased and reposted anyway, I just merged some base patches from Maxime for external interrupts that will go in after the merge window, I need some help to figure out what and how to merge here.
Yours,
Linus Walleij
PATCH 4/11 pinctrl: sunxi: Properly handle level triggered gpio interrupts
Hi Linus,
Quoted 10 lines · Linus Walleij
Quoted 7 lines · Hans de Goede
For level triggered gpio interrupts we need to use
handle_fasteoi_irq, like we do with the irq-sunxi-nmi driver. This is necessary to give threaded interrupt handlers a chance to actuall clear the source of the interrupt (which may involve sleeping waitnig for i2c / spi / mmc transfers), before acknowledging the interrupt.Signed-off-by Hans de Goede <[email protected]>
Quoted 8 lines
I haven't seen any feedback on the pin controller patches in this series from Maxime, I might have missed it due to being tied to some other patch in the series.
Anyway, this needs to be rebased and reposted anyway, I just merged some base patches from Maxime for external interrupts that will go in after the merge window, I need some help to figure out what and how to merge here.
No problem I plan to do a rebased v2 of the pinctrl bits in this series (and only the pinctrl bits) with some remarks from Maxime fixed soon.
Regards,
Hans
PATCH 5/11 pinctrl: sunxi: Define enable / disable irq callbacks for level triggered irqs
In reply to Hans de GoedeSome drivers use disable_irq / enable_irq and do the work clearing the source in another thread instead of using a threaded interrupt handler.
The irqchip used not having irq_disable and irq_enable callbacks in this case, will lead to unnecessary spurious interrupts:
On a disable_irq in a chip without a handller for this, the irq core will remember the disable, but not actually call into the irqchip. With a level triggered interrupt (where the source has not been cleared) this will lead to an immediate retrigger, at which point the irq-core will mask the irq. So having an irq_disable callback in the irqchip will save us the interrupt firing a 2nd time for nothing.
Drivers using disable / enable_irq like this, will call enable_irq when they finally have cleared the interrupt source, without an enable_irq callback, this will turn into an unmask, at which point the irq will trigger immediately because when it was originally acked the level was still high, so the ack was a nop.
--- drivers/pinctrl/sunxi/pinctrl-sunxi.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+)
drivers/pinctrl/sunxi/pinctrl-sunxi.c +27 -0
@@ -36,6 +36,7 @@ static void sunxi_pinctrl_irq_mask_ack(struct irq_data *d);static void sunxi_pinctrl_irq_mask (struct irq_data *d);static void sunxi_pinctrl_irq_unmask (struct irq_data *d);static void sunxi_pinctrl_irq_ack (struct irq_data *d); +static void sunxi_pinctrl_irq_ack_unmask (struct irq_data *d);static struct sunxi_pinctrl_group *sunxi_pinctrl_find_group_by_name (struct sunxi_pinctrl *pctl,const char *group)
@@ -556,6 +557,10 @@ static struct irq_chip sunxi_pinctrl_level_irq_chip = { .irq_mask_ack = sunxi_pinctrl_irq_mask_ack, .irq_unmask = sunxi_pinctrl_irq_unmask, .irq_eoi = sunxi_pinctrl_irq_ack, +/* Define irq_enable / disable to avoid spurious irqs for drivers +* using these to suppress irqs while they clear the irq source */ + .irq_enable = sunxi_pinctrl_irq_ack_unmask, + .irq_disable = sunxi_pinctrl_irq_mask, .irq_set_type = sunxi_pinctrl_irq_set_type, .name = "sunxi-pio", .flags = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_EOI_THREADED |
@@ -689,6 +694,28 @@ static void sunxi_pinctrl_irq_ack(struct irq_data *d)spin_unlock_irqrestore (&pctl->lock, flags); } +static void sunxi_pinctrl_irq_ack_unmask (struct irq_data *d) +{ +struct sunxi_pinctrl *pctl =irq_data_get_irq_chip_data (d); +u32 ctrl_reg =sunxi_irq_ctrl_reg (d->hwirq); +u8 ctrl_idx =sunxi_irq_ctrl_offset (d->hwirq); +u32 status_reg =sunxi_irq_status_reg (d->hwirq); +u8 status_idx =sunxi_irq_status_offset (d->hwirq); +unsigned long flags; +u32 val; + +spin_lock_irqsave (&pctl->lock, flags); + +/* Clear the IRQ */ +writel (1 << status_idx, pctl->membase + status_reg); + +/* Unmask the IRQ */ + val =readl (pctl->membase + ctrl_reg); +writel (val | (1 << ctrl_idx), pctl->membase + ctrl_reg); + +spin_unlock_irqrestore (&pctl->lock, flags); +} +static void sunxi_pinctrl_irq_handler (unsigned irq,struct irq_desc *desc) {struct irq_chip *chip =irq_get_chip (irq);
Signature · 1 line
1.9.3
PATCH 6/11 mmc: Add SDIO function devicetree subnode parsing
In reply to Hans de GoedeFrom: Sascha Hauer <[email protected]>
This adds SDIO devicetree subnode parsing to the mmc core. While SDIO devices are runtime probable they sometimes need nonprobable additional information on embedded systems, like an additional gpio interrupt or a clock. This patch makes it possible to supply this information from the devicetree. SDIO drivers will find a pointer to the devicenode in their devices of_node pointer.
--- Documentation/devicetree/bindings/mmc/mmc.txt | 30 +++++++++++++++++++++++++++ drivers/mmc/core/bus.c | 14 +++++++++++++ drivers/mmc/core/core.c | 25 ++++++++++++++++++++++ drivers/mmc/core/core.h | 3 +++ drivers/mmc/core/sdio_bus.c | 16 ++++++++++++++ 5 files changed, 88 insertions(+)
Documentation/devicetree/bindings/mmc/mmc.txt +30 -0
@@ -60,6 +60,15 @@ Optional SDIO properties: - keep-power-in-suspend: Preserves card power during a suspend/resume cycle - enable-sdio-wakeup: Enables wake up of host system on SDIO IRQ assertion +Function subnodes: +On embedded systems the cards connected to a host may need additional properties. +These can be specified in subnodes to the host controller node. The subnodes are +identified by the standard 'reg' property. +Required properties: +- reg: Must contain the SDIO function number of the function this subnode describes. + A value of 0 denotes the memory SD function, values from 1 to 7 denote the + SDIO functions. + Example: sdhci at ab000000 {
@@ -74,3 +83,24 @@ sdhci at ab000000 { keep-power-in-suspend; enable-sdio-wakeup; } + +Example with SDIO subnode: + +sdhci at ab000000 { + compatible = "sdhci"; + reg = <0xab000000 0x200>; + interrupts = <23>; + bus-width = <4>; + cd-gpios = <&gpio 69 0>; + cd-inverted; + wp-gpios = <&gpio 70 0>; + max-frequency = <50000000>; + keep-power-in-suspend; + enable-sdio-wakeup; + + func at 2 { + reg = <2>; + reset-gpios = <&gpio 69 0>; + clock-frequency = <26000000>; + }; +}
drivers/mmc/core/bus.c +14 -0
@@ -16,6 +16,7 @@#include <linux/err.h> #include <linux/slab.h> #include <linux/stat.h> +#include <linux/of.h> #include <linux/pm_runtime.h> #include <linux/mmc/card.h>
@@ -289,6 +290,16 @@ struct mmc_card *mmc_alloc_card(struct mmc_host *host, struct device_type *type)return card; } +static void mmc_set_of_node (struct mmc_card *card) +{ +struct mmc_host *host = card->host; + +if (!host->parent->of_node) +return ; + + card->dev.of_node =mmc_of_find_child_device (host->parent->of_node,0 ); +} +/* * Register a new MMC card with the driver model. */
@@ -359,6 +370,8 @@ int mmc_add_card(struct mmc_card *card)#endif mmc_init_context_info (card->host); +mmc_set_of_node (card); + ret =device_add (&card->dev);if (ret)return ret;
@@ -387,6 +400,7 @@ void mmc_remove_card(struct mmc_card *card) mmc_hostname(card->host), card->rca); }device_del (&card->dev); +of_node_put (card->dev.of_node); }put_device (&card->dev);
drivers/mmc/core/core.c +25 -0
@@ -1201,6 +1201,31 @@ EXPORT_SYMBOL(mmc_of_parse_voltage);#endif /* CONFIG_OF */ +static int mmc_of_get_func_num (struct device_node *node) +{ +u32 reg; +int ret; + + ret =of_property_read_u32 (node,"reg" , ®); +if (ret <0 ) +return ret; + +return reg; +} + +struct device_node *mmc_of_find_child_device (struct device_node *parent, +unsigned func_num) +{ +struct device_node *node; + +for_each_child_of_node (parent, node) { +if (mmc_of_get_func_num (node) == func_num) +return node; + } + +return NULL ; +} +#ifdef CONFIG_REGULATOR /**
drivers/mmc/core/core.h +3 -0
@@ -32,6 +32,9 @@ struct mmc_bus_ops {void mmc_attach_bus (struct mmc_host *host,const struct mmc_bus_ops *ops);void mmc_detach_bus (struct mmc_host *host); +struct device_node *mmc_of_find_child_device (struct device_node *parent, +unsigned func_num); +void mmc_init_erase (struct mmc_card *card);void mmc_set_chip_select (struct mmc_host *host,int mode);
drivers/mmc/core/sdio_bus.c +16 -0
@@ -22,6 +22,7 @@#include <linux/mmc/host.h> #include <linux/mmc/sdio_func.h> +#include "core.h" #include "sdio_cis.h" #include "sdio_bus.h"
@@ -314,6 +315,19 @@ static void sdio_acpi_set_handle(struct sdio_func *func)static inline void sdio_acpi_set_handle (struct sdio_func *func) {}#endif +#include <linux/of.h> + +void sdio_set_of_node (struct sdio_func *func) +{ +struct mmc_host *host = func->card->host; + +if (!host->parent->of_node) +return ; + + func->dev.of_node =mmc_of_find_child_device (host->parent->of_node, + func->num); +} +/* * Register a new SDIO function with the driver model. */
@@ -323,6 +337,7 @@ int sdio_add_func(struct sdio_func *func)dev_set_name (&func->dev,"%s:%d" ,mmc_card_id (func->card), func->num); +sdio_set_of_node (func);sdio_acpi_set_handle (func); ret =device_add (&func->dev);if (ret ==0 ) {
@@ -346,6 +361,7 @@ void sdio_remove_func(struct sdio_func *func)acpi_dev_pm_detach (&func->dev, false);device_del (&func->dev); +of_node_put (func->dev.of_node);put_device (&func->dev); }
Signature · 1 line
1.9.3
PATCH 7/11 dt: bindings: add bindings for Broadcom bcm43xx sdio devices
In reply to Hans de GoedeFrom: Arend van Spriel <[email protected]>
The Broadcom bcm43xx sdio devices are fullmac devices that may be integrated in ARM platforms. Currently, the brcmfmac driver for these devices support use of platform data. This patch specifies the bindings that allow this platform data to be expressed in the devicetree.
[hdegoede at redhat.com: drop clk / reg_on gpio handling, as there is no consensus
on how to handle this yet]
--- .../bindings/net/wireless/brcm,bcm43xx-fmac.txt | 29 ++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 Documentation/devicetree/bindings/net/wireless/brcm,bcm43xx-fmac.txt
Documentation/devicetree/bindings/net/wireless/brcm,bcm43xx-fmac.txt new file +29 -0
@@ -0,0 +1,29 @@ +Broadcom BCM43xx Fullmac wireless SDIO devices + +This node provides properties for controlling the Broadcom wireless device. The +node is expected to be specified as a child node to the SDIO controller that +connects the device to the system. + +Required properties: + + - compatible : Should be "brcm,bcm43xx-fmac". + +Optional properties: + - brcm,drive-strength : drive strength used for SDIO pins on device. + (default = 6mA). + - interrupt-parent : the phandle for the interrupt controller to which the + device interrupts are connected. + - interrupts : specifies attributes for the out-of-band interrupt (host-wake). + When not specified the device will use in-band SDIO interrupts. + - interrupt-names : name of the out-of-band interrupt, which must be set + to "host-wake". + +Example: + +bcm4335 { + compatible = "brcm,bcm43xx-fmac"; + brcm,drive-strength = <4>; + interrupt-parent = <&gpx2>; + interrupts = <5 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "host-wake"; +};
Signature · 1 line
1.9.3
PATCH 8/11 brcmfmac: add device tree support for SDIO devices
In reply to Hans de GoedeFrom: Chen-Yu Tsai <[email protected]>
brcmfmac devices can use an out-of-band interrupt on a GPIO line. Currently this is specified using platform data. Add support for specifying out-of-band interrupt via device tree.
[hdegoede at redhat.com: drop clk / reg_on gpio handling, as there is no consensus
on how to handle this yet]
--- drivers/net/wireless/brcm80211/brcmfmac/Makefile | 2 + drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c | 4 ++ drivers/net/wireless/brcm80211/brcmfmac/of.c | 56 ++++++++++++++++++++++++ drivers/net/wireless/brcm80211/brcmfmac/of.h | 22 ++++++++++ 4 files changed, 84 insertions(+) create mode 100644 drivers/net/wireless/brcm80211/brcmfmac/of.c create mode 100644 drivers/net/wireless/brcm80211/brcmfmac/of.h
drivers/net/wireless/brcm80211/brcmfmac/Makefile +2 -0
@@ -44,3 +44,5 @@ brcmfmac-$(CONFIG_BRCMDBG) += \ dhd_dbg.o brcmfmac-$(CONFIG_BRCM_TRACING) += \ tracepoint.o +brcmfmac-$(CONFIG_OF) += \ + of.o
drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c +4 -0
@@ -43,6 +43,7 @@#include "dhd_bus.h" #include "dhd_dbg.h" #include "sdio_host.h" +#include "of.h" #define SDIOH_API_ACCESS_RETRY_LIMIT 2
@@ -1043,6 +1044,9 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func, sdiodev->dev = &sdiodev->func[1 ]->dev; sdiodev->pdata = brcmfmac_sdio_pdata; +if (!sdiodev->pdata) +brcmf_of_probe (sdiodev); +atomic_set (&sdiodev->suspend, false);init_waitqueue_head (&sdiodev->request_word_wait);init_waitqueue_head (&sdiodev->request_buffer_wait);
drivers/net/wireless/brcm80211/brcmfmac/of.c new file +56 -0
56 lines not on this page · raw message
drivers/net/wireless/brcm80211/brcmfmac/of.h new file +22 -0
@@ -0,0 +1,22 @@ +/* +* Copyright (c) 2014 Broadcom Corporation +* +* Permission to use, copy, modify, and/or distribute this software for any +* purpose with or without fee is hereby granted, provided that the above +* copyright notice and this permission notice appear in all copies. +* +* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION +* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +#ifdef CONFIG_OF +void brcmf_of_probe (struct brcmf_sdio_dev *sdiodev); +#else +static void brcmf_of_probe (struct brcmf_sdio_dev *sdiodev) +{ +} +#endif /* CONFIG_OF */
Signature · 1 line
1.9.3
PATCH 9/11 brcmfmac: Fix OOB interrupt not working for BCM43362
In reply to Hans de GoedeIt has taken me a long long time to get the OOB interrupt working on the AP6210 sdio wifi/bt module found on various Allwinner A20 boards. In the end I found these magic register pokes in the cubietruck kernel tree:
https://github.com/cubieboard2/linux-sunxi/commit/7f08ba395617d17e7a711507503d89a50406fe7a
I'm not entirely sure if this specific to the AP6210 module, or if this should be done for all BCM43362 sdio devices.
--- drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+)
drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c +18 -0
@@ -39,7 +39,9 @@#include <brcm_hw_ids.h> #include <brcmu_utils.h> #include <brcmu_wifi.h> +#include <chipcommon.h> #include <soc.h> +#include "chip.h" #include "dhd_bus.h" #include "dhd_dbg.h" #include "sdio_host.h"
@@ -119,6 +121,7 @@ int brcmf_sdiod_intr_register(struct brcmf_sdio_dev *sdiodev) {int ret =0 ;u8 data; +u32 addr, gpiocontrol;unsigned long flags;if ((sdiodev->pdata) && (sdiodev->pdata->oob_irq_supported)) {
@@ -148,6 +151,21 @@ int brcmf_sdiod_intr_register(struct brcmf_sdio_dev *sdiodev)sdio_claim_host (sdiodev->func[1 ]); +if (sdiodev->bus_if->chip ==BCM43362_CHIP_ID ) { + addr =CORE_CC_REG (SI_ENUM_BASE , gpiocontrol); + gpiocontrol =brcmf_sdiod_regrl (sdiodev, addr, &ret); + gpiocontrol |=0x2 ; +brcmf_sdiod_regwl (sdiodev, addr, gpiocontrol, &ret); + +/* SPROM_ADDR_HIGH ? perhaps the defines name is off */ +brcmf_sdiod_regwb (sdiodev,SBSDIO_SPROM_ADDR_HIGH ,0xf , + &ret); +brcmf_sdiod_regwb (sdiodev,SBSDIO_CHIP_CTRL_DATA ,0 , + &ret); +brcmf_sdiod_regwb (sdiodev,SBSDIO_CHIP_CTRL_EN ,0x2 , + &ret); + } +/* must configure SDIO_CCCR_IENx to enable irq */ data =brcmf_sdiod_regrb (sdiodev, SDIO_CCCR_IENx, &ret); data |=1 <<SDIO_FUNC_1 |1 <<SDIO_FUNC_2 |1 ;
Signature · 1 line
1.9.3
PATCH 9/11 brcmfmac: Fix OOB interrupt not working for BCM43362
Quoted 7 lines · Hans de Goede
It has taken me a long long time to get the OOB interrupt working on the AP6210 sdio wifi/bt module found on various Allwinner A20 boards. In the end I found these magic register pokes in the cubietruck kernel tree:
https://github.com/cubieboard2/linux-sunxi/commit/7f08ba395617d17e7a711507503d89a50406fe7aI'm not entirely sure if this specific to the AP6210 module, or if this should be done for all BCM43362 sdio devices.
This magic is not in our host drivers so my guess is that it is board specific. This means the nvram file provided to the firmware should have this specified. Can you send me yours?
Regards,
Arend
Quoted 49 lines
Signed-off-by Hans de Goede<[email protected]>--- drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+)drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c +18
-0@@ -39,7 +39,9 @@#include <brcm_hw_ids.h> #include <brcmu_utils.h> #include <brcmu_wifi.h> +#include <chipcommon.h> #include <soc.h> +#include "chip.h" #include "dhd_bus.h" #include "dhd_dbg.h" #include "sdio_host.h" @@ -119,6 +121,7 @@ int brcmf_sdiod_intr_register(struct brcmf_sdio_dev *sdiodev) {int ret =0 ;u8 data; +u32 addr, gpiocontrol;unsigned long flags;if ((sdiodev->pdata)&& (sdiodev->pdata->oob_irq_supported)) {@@ -148,6 +151,21 @@ int brcmf_sdiod_intr_register(struct brcmf_sdio_dev *sdiodev)sdio_claim_host (sdiodev->func[1 ]); +if (sdiodev->bus_if->chip ==BCM43362_CHIP_ID ) { + addr =CORE_CC_REG (SI_ENUM_BASE , gpiocontrol); + gpiocontrol =brcmf_sdiod_regrl (sdiodev, addr,&ret); + gpiocontrol |=0x2 ; +brcmf_sdiod_regwl (sdiodev, addr, gpiocontrol,&ret); + +/* SPROM_ADDR_HIGH ? perhaps the defines name is off */ +brcmf_sdiod_regwb (sdiodev,SBSDIO_SPROM_ADDR_HIGH ,0xf , + &ret); +brcmf_sdiod_regwb (sdiodev,SBSDIO_CHIP_CTRL_DATA ,0 , + &ret); +brcmf_sdiod_regwb (sdiodev,SBSDIO_CHIP_CTRL_EN ,0x2 , + &ret); + } +/* must configure SDIO_CCCR_IENx to enable irq */ data =brcmf_sdiod_regrb (sdiodev, SDIO_CCCR_IENx,&ret); data |=1 <<SDIO_FUNC_1 |1 <<SDIO_FUNC_2 |1 ;
PATCH 9/11 brcmfmac: Fix OOB interrupt not working for BCM43362
In reply to Hans de GoedeQuoted 7 lines · Hans de Goede
It has taken me a long long time to get the OOB interrupt working on the AP6210 sdio wifi/bt module found on various Allwinner A20 boards. In the end I found these magic register pokes in the cubietruck kernel tree:
https://github.com/cubieboard2/linux-sunxi/commit/7f08ba395617d17e7a711507503d89a50406fe7aI'm not entirely sure if this specific to the AP6210 module, or if this should be done for all BCM43362 sdio devices.
Let keep it as this for now. I added some remarks below.
Regards,
Arend
Quoted 28 lines
Signed-off-by Hans de Goede<[email protected]>--- drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+)drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c +3
-0@@ -39,7 +39,9 @@#include <brcm_hw_ids.h> #include <brcmu_utils.h> #include <brcmu_wifi.h> +#include <chipcommon.h> #include <soc.h> +#include "chip.h" #include "dhd_bus.h" #include "dhd_dbg.h" #include "sdio_host.h" @@ -119,6 +121,7 @@ int brcmf_sdiod_intr_register(struct brcmf_sdio_dev *sdiodev) {int ret =0 ;u8 data; +u32 addr, gpiocontrol;unsigned long flags;if ((sdiodev->pdata)&& (sdiodev->pdata->oob_irq_supported)) {
drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c int brcmf_sdiod_intr_register(struct brcmf_sdio_dev *sdiodev) · line 154
Quoted 4 lines
drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c +1
-0@@ -148,6 +151,21 @@ int brcmf_sdiod_intr_register(struct brcmf_sdio_dev *sdiodev)sdio_claim_host (sdiodev->func[1 ]); +if (sdiodev->bus_if->chip ==BCM43362_CHIP_ID ) {
+ /* assign GPIO to SDIO core */
drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c int brcmf_sdiod_intr_register(struct brcmf_sdio_dev *sdiodev) · line 160
Quoted 6 lines
drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c +6
-0+ addr =CORE_CC_REG (SI_ENUM_BASE , gpiocontrol); + gpiocontrol =brcmf_sdiod_regrl (sdiodev, addr,&ret); + gpiocontrol |=0x2 ; +brcmf_sdiod_regwl (sdiodev, addr, gpiocontrol,&ret); + +/* SPROM_ADDR_HIGH ? perhaps the defines name is off */
These names are all off. These should be:SBSDIO_SPROM_ADDR_HIGH = SBSDIO_GPIO_SELECTSBSDIO_CHIP_CTRL_DATA = SBSDIO_GPIO_OUTSBSDIO_CHIP_CTRL_EN = SBSDIO_GPIO_EN
Quoted 11 lines
drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c +8
-0+brcmf_sdiod_regwb (sdiodev,SBSDIO_SPROM_ADDR_HIGH ,0xf , + &ret); +brcmf_sdiod_regwb (sdiodev,SBSDIO_CHIP_CTRL_DATA ,0 , + &ret); +brcmf_sdiod_regwb (sdiodev,SBSDIO_CHIP_CTRL_EN ,0x2 , + &ret); + } +/* must configure SDIO_CCCR_IENx to enable irq */ data =brcmf_sdiod_regrb (sdiodev, SDIO_CCCR_IENx,&ret); data |=1 <<SDIO_FUNC_1 |1 <<SDIO_FUNC_2 |1 ;
PATCH 9/11 brcmfmac: Fix OOB interrupt not working for BCM43362
Hi,
Quoted 54 lines · Arend van Spriel
Quoted 7 lines · Hans de Goede
It has taken me a long long time to get the OOB interrupt working on the AP6210 sdio wifi/bt module found on various Allwinner A20 boards. In the end I found these magic register pokes in the cubietruck kernel tree:
https://github.com/cubieboard2/linux-sunxi/commit/7f08ba395617d17e7a711507503d89a50406fe7aI'm not entirely sure if this specific to the AP6210 module, or if this should be done for all BCM43362 sdio devices.
Let keep it as this for now. I added some remarks below.
Regards,
ArendQuoted 28 lines
Signed-off-by Hans de Goede<[email protected]>--- drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+)drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c +3
-0@@ -39,7 +39,9 @@#include <brcm_hw_ids.h> #include <brcmu_utils.h> #include <brcmu_wifi.h> +#include <chipcommon.h> #include <soc.h> +#include "chip.h" #include "dhd_bus.h" #include "dhd_dbg.h" #include "sdio_host.h" @@ -119,6 +121,7 @@ int brcmf_sdiod_intr_register(struct brcmf_sdio_dev *sdiodev) {int ret =0 ;u8 data; +u32 addr, gpiocontrol;unsigned long flags;if ((sdiodev->pdata)&& (sdiodev->pdata->oob_irq_supported)) {drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c int brcmf_sdiod_intr_register(struct brcmf_sdio_dev *sdiodev) · line 154
Quoted 4 lines
drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c +1
-0@@ -148,6 +151,21 @@ int brcmf_sdiod_intr_register(struct brcmf_sdio_dev *sdiodev)sdio_claim_host (sdiodev->func[1 ]); +if (sdiodev->bus_if->chip ==BCM43362_CHIP_ID ) {+ /* assign GPIO to SDIO core */
drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c int brcmf_sdiod_intr_register(struct brcmf_sdio_dev *sdiodev) · line 160
Quoted 6 lines
drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c +6
-0+ addr =CORE_CC_REG (SI_ENUM_BASE , gpiocontrol); + gpiocontrol =brcmf_sdiod_regrl (sdiodev, addr,&ret); + gpiocontrol |=0x2 ; +brcmf_sdiod_regwl (sdiodev, addr, gpiocontrol,&ret); + +/* SPROM_ADDR_HIGH ? perhaps the defines name is off */
Quoted 4 lines
These names are all off. These should be:
SBSDIO_SPROM_ADDR_HIGH=SBSDIO_GPIO_SELECTSBSDIO_CHIP_CTRL_DATA=SBSDIO_GPIO_OUTSBSDIO_CHIP_CTRL_EN=SBSDIO_GPIO_EN
Ok, so I guess I should do a pre-patch adding defines for these, should these replace the existing defines for these addresses in:drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h
Or should the pre-patch add defines with the new names and keep the old ones ?
Regards,
Hans
PATCH 9/11 brcmfmac: Fix OOB interrupt not working for BCM43362
Quoted 66 lines · Hans de Goede
Hi,
Quoted 58 lines · Arend van Spriel
Quoted 8 lines · Hans de Goede
It has taken me a long long time to get the OOB interrupt working on the AP6210 sdio wifi/bt module found on various Allwinner A20 boards. In the end I found these magic register pokes in the cubietruck kernel tree:
https://github.com/cubieboard2/linux-sunxi/commit/7f08ba395617d17e7a711507503d89a50406fe7aI'm not entirely sure if this specific to the AP6210 module, or if this should be done for all BCM43362 sdio devices.
Let keep it as this for now. I added some remarks below.
Regards,
ArendQuoted 30 lines
Signed-off-by Hans de Goede<[email protected]>---
drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c| 18 ++++++++++++++++++1 file changed, 18 insertions(+)drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c +3
-0@@ -39,7 +39,9 @@#include <brcm_hw_ids.h> #include <brcmu_utils.h> #include <brcmu_wifi.h> +#include <chipcommon.h> #include <soc.h> +#include "chip.h" #include "dhd_bus.h" #include "dhd_dbg.h" #include "sdio_host.h" @@ -119,6 +121,7 @@ int brcmf_sdiod_intr_register(struct brcmf_sdio_dev *sdiodev) {int ret =0 ;u8 data; +u32 addr, gpiocontrol;unsigned long flags;if ((sdiodev->pdata)&& (
sdiodev->pdata->oob_irq_supported)) {drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c int brcmf_sdiod_intr_register(struct · line 155
Quoted 5 lines
drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c +1
-0@@ -148,6 +151,21 @@ int brcmf_sdiod_intr_register(struct brcmf_sdio_dev *sdiodev) sdio_claim_host(sdiodev->func[1]); +if (sdiodev->bus_if->chip ==BCM43362_CHIP_ID ) {+ /* assign GPIO to SDIO core */
drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c int brcmf_sdiod_intr_register(struct brcmf_sdio_dev *sdiodev) · line 160
Quoted 6 lines
drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c +6
-0+ addr =CORE_CC_REG (SI_ENUM_BASE , gpiocontrol); + gpiocontrol =brcmf_sdiod_regrl (sdiodev, addr,&ret); + gpiocontrol |=0x2 ; +brcmf_sdiod_regwl (sdiodev, addr, gpiocontrol,&ret); + +/* SPROM_ADDR_HIGH ? perhaps the defines name is off */ Quoted 4 lines
These names are all off. These should be:
SBSDIO_SPROM_ADDR_HIGH=SBSDIO_GPIO_SELECTSBSDIO_CHIP_CTRL_DATA=SBSDIO_GPIO_OUTSBSDIO_CHIP_CTRL_EN=SBSDIO_GPIO_EN
Quoted 6 lines
Ok, so I guess I should do a pre-patch adding defines for these, should these replace the existing defines for these addresses in:
drivers/net/wireless/brcm80211/brcmfmac/sdio_host.hOr should the pre-patch add defines with the new names and keep the old ones ?
These defines are not used in the code so go ahead and replace them. It needs some more cleanup, but I can do a subsequent patch for that.
Gr. AvS
PATCH 10/11 ARM: dts: sun7i: Add #interrupt-cells to pinctrl node
In reply to Hans de GoedeFrom: Chen-Yu Tsai <[email protected]>
The pinctrl device is also an interrupt controller for external interrupts. Add the missing #interrupt-cells property.
Also remove the unused #address-cells property.
--- arch/arm/boot/dts/sun7i-a20.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/arm/boot/dts/sun7i-a20.dtsi +1 -1
@@ -594,7 +594,7 @@ clocks = <&apb0_gates 5>; gpio-controller; interrupt-controller; - #address-cells = <1>; + #interrupt-cells = <2>; #size-cells = <0>; #gpio-cells = <3>;
Signature · 1 line
1.9.3
PATCH 11/11 ARM: dts: sun7i: Add OOB irq support to boards with broadcom sdio wifi
In reply to Hans de Goede--- arch/arm/boot/dts/sun7i-a20-cubietruck.dts | 12 ++++++++++++ arch/arm/boot/dts/sun7i-a20-i12-tvbox.dts | 12 ++++++++++++ 2 files changed, 24 insertions(+)
arch/arm/boot/dts/sun7i-a20-cubietruck.dts +12 -0
@@ -31,12 +31,24 @@ }; mmc3: mmc at 01c12000 { + #address-cells = <1>; + #size-cells = <0>; + pinctrl-names = "default"; pinctrl-0 = <&mmc3_pins_a>; vmmc-supply = <®_vmmc3>; bus-width = <4>; non-removable; status = "okay"; + + brcmf: bcrmf at 1 { + reg = <1>; + compatible = "brcm,bcm43xx-fmac"; + interrupt-parent = <&pio>; + interrupts = <10 8>; /* PH10 / EINT10 */ + interrupt-names = "host-wake"; + status = "okay"; + }; }; usbphy: phy at 01c13400 {
arch/arm/boot/dts/sun7i-a20-i12-tvbox.dts +12 -0
@@ -29,12 +29,24 @@ }; mmc3: mmc at 01c12000 { + #address-cells = <1>; + #size-cells = <0>; + pinctrl-names = "default"; pinctrl-0 = <&mmc3_pins_a>; vmmc-supply = <®_vmmc3>; bus-width = <4>; non-removable; status = "okay"; + + brcmf: bcrmf at 1 { + reg = <1>; + compatible = "brcm,bcm43xx-fmac"; + interrupt-parent = <&pio>; + interrupts = <10 8>; /* PH10 / EINT10 */ + interrupt-names = "host-wake"; + status = "okay"; + }; }; usbphy: phy at 01c13400 {
Signature · 1 line
1.9.3
cover sdio wifi oob irq support for sunxi
In reply to Hans de GoedeQuoted 11 lines · Hans de Goede
Hi All,
Here is a patch series adding support for oob irqs for the ap6210 sdio wifi modules found on various Allwinner A20 boards.
A lot of it is ground work which should be useful for adding oob irq support to other sdio wifi models too.
The first 5 patches are sunxi pinctrl patches and should go upstream through the pinctrl tree.
Quoted 6 lines
Patch 6 adds generic support for having per sdio function child nodes in devicetree and should go upstream through the mmc tree.
Patch 7 and 8 add oob irq support to the brcmfmac driver. Patch 9 pokes some magic bits needed to enable the oob irq, this was taken from an android code dump and good do with a good review from someone from Broadcom, Arend ?
If Arend approves, I'm fine with these going through another appropriate tree.
Quoted 9 lines
Patch 10 and 11 add the necessary dts bits to actually enable the sdio irq and should go upstream through Maxime's dt tree.
Please review / merge.
Thanks & Regards,
Hans
Signature · 2 lines
John W. Linville Someday the world will need a hero, and you linville at tuxdriver.com might be all we have. Be ready.
cover sdio wifi oob irq support for sunxi
Quoted 12 lines · John W. Linville
Quoted 11 lines · Hans de Goede
Hi All,
Here is a patch series adding support for oob irqs for the ap6210 sdio wifi modules found on various Allwinner A20 boards.
A lot of it is ground work which should be useful for adding oob irq support to other sdio wifi models too.
The first 5 patches are sunxi pinctrl patches and should go upstream through the pinctrl tree.
Quoted 8 lines
Quoted 6 lines
Patch 6 adds generic support for having per sdio function child nodes in devicetree and should go upstream through the mmc tree.
Patch 7 and 8 add oob irq support to the brcmfmac driver. Patch 9 pokes some magic bits needed to enable the oob irq, this was taken from an android code dump and good do with a good review from someone from Broadcom, Arend ?
If Arend approves, I'm fine with these going through another appropriate tree.
Not sure in what tree these patches were created (assume some sunxi tree), but if it conflicts with wireless-next I am pretty sure Stephen will find that. I am fine with any tree. Patch 9 indeed has some magic bits that need some clarification, but I will sort that out with Hans.
Regards,
Arend
Quoted 10 lines
Quoted 9 lines
Patch 10 and 11 add the necessary dts bits to actually enable the sdio irq and should go upstream through Maxime's dt tree.
Please review / merge.
Thanks& Regards,
Hans