Commit Graph

18 Commits

Author SHA1 Message Date
Schspa Shi
3c938cc5ce gpio: use raw spinlock for gpio chip shadowed data
In case of PREEMPT_RT, there is a raw_spinlock -> spinlock dependency
as the lockdep report shows.

__irq_set_handler
  irq_get_desc_buslock
    __irq_get_desc_lock
      raw_spin_lock_irqsave(&desc->lock, *flags);  // raw spinlock get here
  __irq_do_set_handler
    mask_ack_irq
      dwapb_irq_ack
        spin_lock_irqsave(&gc->bgpio_lock, flags); // sleep able spinlock
  irq_put_desc_busunlock

Replace with a raw lock to avoid BUGs. This lock is only used to access
registers, and It's safe to replace with the raw lock without bad
influence.

[   15.090359][    T1] =============================
[   15.090365][    T1] [ BUG: Invalid wait context ]
[   15.090373][    T1] 5.10.59-rt52-00983-g186a6841c682-dirty #3 Not tainted
[   15.090386][    T1] -----------------------------
[   15.090392][    T1] swapper/0/1 is trying to lock:
[   15.090402][    T1] 70ff00018507c188 (&gc->bgpio_lock){....}-{3:3}, at: _raw_spin_lock_irqsave+0x1c/0x28
[   15.090470][    T1] other info that might help us debug this:
[   15.090477][    T1] context-{5:5}
[   15.090485][    T1] 3 locks held by swapper/0/1:
[   15.090497][    T1]  #0: c2ff0001816de1a0 (&dev->mutex){....}-{4:4}, at: __device_driver_lock+0x98/0x104
[   15.090553][    T1]  #1: ffff90001485b4b8 (irq_domain_mutex){+.+.}-{4:4}, at: irq_domain_associate+0xbc/0x6d4
[   15.090606][    T1]  #2: 4bff000185d7a8e0 (lock_class){....}-{2:2}, at: _raw_spin_lock_irqsave+0x1c/0x28
[   15.090654][    T1] stack backtrace:
[   15.090661][    T1] CPU: 4 PID: 1 Comm: swapper/0 Not tainted 5.10.59-rt52-00983-g186a6841c682-dirty #3
[   15.090682][    T1] Hardware name: Horizon Robotics Journey 5 DVB (DT)
[   15.090692][    T1] Call trace:
......
[   15.090811][    T1]  _raw_spin_lock_irqsave+0x1c/0x28
[   15.090828][    T1]  dwapb_irq_ack+0xb4/0x300
[   15.090846][    T1]  __irq_do_set_handler+0x494/0xb2c
[   15.090864][    T1]  __irq_set_handler+0x74/0x114
[   15.090881][    T1]  irq_set_chip_and_handler_name+0x44/0x58
[   15.090900][    T1]  gpiochip_irq_map+0x210/0x644

Signed-off-by: Schspa Shi <schspa@gmail.com>
Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Acked-by: Doug Berger <opendmb@gmail.com>
Acked-by: Serge Semin <fancer.lancer@gmail.com>
Signed-off-by: Bartosz Golaszewski <brgl@bgdev.pl>
2022-04-25 12:10:02 +02:00
Andy Shevchenko
761b5c30c2 gpio: mmio: replace open-coded for_each_set_bit()
Use for_each_set_bit() instead of open-coding it to simplify the code.

Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Link: https://lore.kernel.org/r/20200713154429.23662-1-andriy.shevchenko@linux.intel.com
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
2020-07-16 15:07:18 +02:00
Chuanhong Guo
d19d2de61f gpio: mmio: introduce BGPIOF_NO_SET_ON_INPUT
Some gpio controllers ignores pin value writing when that pin is
configured as input mode. As a result, bgpio_dir_out should set
pin to output before configuring pin values or gpio pin values
can't be set up properly.
Introduce two variants of bgpio_dir_out: bgpio_dir_out_val_first
and bgpio_dir_out_dir_first, and assign direction_output according
to a new flag: BGPIOF_NO_SET_ON_INPUT.

Signed-off-by: Chuanhong Guo <gch981213@gmail.com>
Tested-by: René van Dorst <opensource@vdorst.com>
Reviewed-by: Sergio Paracuellos <sergio.paracuellos@gmail.com>
Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
2020-03-25 09:50:45 +01:00
Matti Vaittinen
0f67f16a6e gpio: mmio: remove untrue leftover comment
The comment should have been removed when new GPIO direction
definitions were taken in use as the function logic was changed. It
is now perfectly valid and Ok to hit the return from the bottom of
the direction getting function.

Signed-off-by: Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>
Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
2019-11-13 13:49:42 +01:00
Matti Vaittinen
e42615ec23 gpio: Use new GPIO_LINE_DIRECTION
It's hard for occasional GPIO code reader/writer to know if values 0/1
equal to IN or OUT. Use defined GPIO_LINE_DIRECTION_IN and
GPIO_LINE_DIRECTION_OUT to help them out.

NOTE - for gpio-amd-fch and gpio-bd9571mwv:
This commit also changes the return value for direction get to equal 1
for direction INPUT. Prior this commit these drivers might have
returned some other positive value but 1 for INPUT.

Signed-off-by: Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>
Acked-by: Scott Branden <scott.branden@broadcom.com>
Reviewed-by: Grygorii Strashko <grygorii.strashko@ti.com>
Reviewed-by: Michal Simek <michal.simek@xilinx.com>
Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
Acked-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Acked-by: William Breathitt Gray <vilhelm.gray@gmail.com>
Acked-by: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
2019-11-07 09:27:48 +01:00
Linus Walleij
27157af663 gpio: mmio: Drop bgpio_dir_inverted
The direction inversion semantics are now handled by simply
using the registers for in/out available, no need to keep
track of inversion semantics exmplicitly anymore.

Reviewed-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
Reviewed-by: Jan Kotas <jank@cadence.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
2019-04-08 11:17:43 +02:00
Jan Kotas
4f2f95e9a8 gpio: mmio: Fix bgpio_get_set & bgpio_get_set_multiple
During my regression testing I noticed the cadence GPIO driver
fails on the latest gpio for-next tree.

I think the reason is this patch:
commit 96cd559817f2 ("Merge branch 'devel' into for-next")

Here is a part of the test log:

Loopback 8 -> 24
TESTING: gpio: 488: output direction PASSED
TESTING: gpio: 504: input direction PASSED
TESTING: gpio: 488: 0 PASSED
TESTING: gpio: 488 -> 504: 0 PASSED
TESTING: gpio: 488: 1 FAILED
TESTING: gpio: 488 -> 504: 1 FAILED
TESTING: gpio: 488: 0 PASSED
TESTING: gpio: 488 -> 504: 0 PASSED

It looks like the issue is that gc->bgpio_dir has changed its meaning.
It used to be set to the register value (so it was being inverted).

Now it's always set to 1 for output and 0 for input.
However the bgpio_get_set functions were not updated.
So they invert the bit again, which means a wrong register
is being accessed.

This patch fixes that by removing the unnecessary inversion.

Signed-off-by: Jan Kotas <jank@cadence.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
2019-04-05 00:04:28 +07:00
Linus Walleij
f69e00bd21 gpio: mmio: Support two direction registers
It turns out that one specific hardware has two direction
registers: one to set a GPIO line as input and another one
to set a GPIO line as output. So in theory a line can be
configured as input and output at the same time.

Make the MMIO GPIO helper deal with this: store both
registers in the state container, use both in the generic
code if present. Synchronize the input register to the
output register when we register a GPIO chip, with the
output settings taking precedence.

Keep the helper variable to detect inverted direction
semantics (only direction in register) but augment the
code to be more straight-forward for the generic case
when setting the registers.

Fix some flunky with unreadable direction registers at
the same time as we're touching this code.

Cc: David Woods <dwoods@mellanox.com>
Cc: Shravan Kumar Ramani <sramani@mellanox.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
2019-04-05 00:04:13 +07:00
Linus Walleij
dae5f0afcf gpio: Use SPDX header for core library
Use the SPDX headers and cut down on boilerplate to indicate the
license in the core gpiolib implementation.

Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
2018-09-25 09:08:48 +02:00
Linus Walleij
d799a4de0a gpio: mmio: Fix up inverted direction registers
The bgpio_init() takes one of two arguments to specify a register
to set the direction of the GPIO line: either dirout that
indicates that a 1 in the bit in that register sets the
corresponding line to output, or dirin which indicates that
a 1 in the bit in that register sets the corresponding line to
input. Conversely setting the bit to 0 on these will turn the
line into input and output respectively. One of these can
be defined but not both.

This means that a platform that sets a bit to 1 for output
only defines dirout and a platform that sets a bit to 0 for
output only defines dirin. In short this defines the polarity
of the direction register.

Both can also be left as NULL meaning the GPIO chip is either
input only or output only.

Tomer Maimon discovered that for get/set chips (those where the
get and set registers are defined but no separate clear register,
and specifying BGPIOF_READ_OUTPUT_REG_SET so that we say we
want to read the output value from the SET register)
we are unconditionally reading the value from the SET register
when the direction bit is 1 and from the DAT register when the
direction bit is 0, not taking the direction bit polarity into
account.

It would be expected that when the direction bit is inverted
(dirin is defined but not dirout) we read the current value from
the DAT register when the bit is 1 and from the SET register
when the bit is 0.

Currently only some versions of ATH79, brcmstb, some versions of
CLP711x, GE, IOP and Loongson use the dirin mode (a 1 in the
register means input). They are unaffected because
BGPIOF_READ_OUTPUT_REG_SET is not set on any of them. (They
do not read back the SET register to figure out the output
value.) So this is no regression with current drivers.

However the behaviour is wrong and does not work with Tomer's
new driver where he needs to use the BGIOF_READ_OUTPUT_REG_SET.
This fixes the above issue by:

- Instead of defining separate functions for the inverted case,
  set up a flag in the gpio_chip that indicates that the
  direction is inverted.
- Remove the special inverted functions for setting
  input/output and getting the direction, rely on the flag
  instead.
- Respect this flag in bgpio_get_set() and
  bgpio_get_set_multiple()

Reported-by: Tomer Maimon <tmaimon77@gmail.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
2018-08-10 23:19:17 +02:00
Linus Walleij
07c7b6a525 gpio: mmio: Also read bits that are zero
The code for .get_multiple() has bugs:

1. The simple .get_multiple() just reads a register, masks it
and sets the return value. This is not correct: we only want to
assign values (whether 0 or 1) to the bits that are set in the
mask. Fix this by using &= ~mask to clear all bits in the mask
and then |= val & mask to set the corresponding bits from the
read.

2. The bgpio_get_multiple_be() call has a similar problem: it
uses the |= operator to set the bits, so only the bits in the
mask are affected, but it misses to clear all returned bits
from the mask initially, so some bits will be returned
erroneously set to 1.

3. The bgpio_get_set_multiple() again fails to clear the bits
from the mask.

4. find_next_bit() wasn't handled correctly, use a totally
different approach for one function and change the other
function to follow the design pattern of assigning the first
bit to -1, then use bit + 1 in the for loop and < num_iterations
as break condition.

Fixes: 80057cb417 ("gpio-mmio: Use the new .get_multiple() callback")
Cc: Bartosz Golaszewski <brgl@bgdev.pl>
Reported-by: Clemens Gruber <clemens.gruber@pqgruber.com>
Tested-by: Clemens Gruber <clemens.gruber@pqgruber.com>
Reported-by: Lukas Wunner <lukas@wunner.de>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
2018-01-16 23:42:36 +01:00
Linus Walleij
80057cb417 gpio-mmio: Use the new .get_multiple() callback
It is possible to read all lines of a generic MMIO GPIO chip
with a single register read so support this if we are in
native endianness.

Add an especially quirky callback to read multiple lines for
the variants that require you to read values from the
output registers if and only if the line is set as output.
We managed to do that with a maximum of two register reads,
and just one read if the requested lines are all input or all
output.

Cc: Anton Vorontsov <anton@enomsg.org>
Cc: Lukas Wunner <lukas@wunner.de>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
2017-10-30 08:35:32 +01:00
Linus Walleij
24efd94bc3 gpio: mmio: Make pin2mask() a private business
The vtable call pin2mask() was introducing a vtable function call
in every gpiochip callback for a generic MMIO GPIO chip. This was
not exactly efficient. (Maybe link-time optimization could get rid of
it, I don't know.)

After removing all external calls into this API we can make it a
boolean flag in the struct gpio_chip call and sink the function into
the gpio-mmio driver yielding encapsulation and potential speedups.

Cc: Anton Vorontsov <anton@enomsg.org>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
2017-10-25 11:25:41 +02:00
Nathan Sullivan
b8c90199b5 gpio: mmio: add support for NI 169445 NAND GPIO
The GPIO-based NAND controller on National Instruments 169445 hardware
exposes a set of simple lines for the control signals.

Signed-off-by: Nathan Sullivan <nathan.sullivan@ni.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
2017-03-23 09:49:06 +01:00
Christian Lamparter
05cc995f4d gpio: mmio: add brcm,bcm6345 support
This patch adds support for the GPIO found in Broadcom's bcm63xx-gpio
chips.
This GPIO controller is used in the following Broadcom SoCs: BCM6338, BCM6345.
It can be used in newer SoCs, without the capability of pin multiplexing.

Signed-off-by: Christian Lamparter <chunkeey@googlemail.com>
Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
2016-08-11 16:17:05 +02:00
Christian Lamparter
c0d30ecfe2 gpio: mmio: add MyBook Live GPIO support
This patch adds support for the Western Digital's
MyBook Live memory-mapped GPIO controllers.

The GPIOs will be supported by the generic driver
for memory-mapped GPIO controllers.

Signed-off-by: Christian Lamparter <chunkeey@googlemail.com>
Acked-by: Alexandre Courbot <acourbot@nvidia.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
2016-06-08 11:16:50 +02:00
Álvaro Fernández Rojas
e698613ada gpio: mmio: add DT support for memory-mapped GPIOs
This patch adds support for defining memory-mapped GPIOs which
are compatible with the existing gpio-mmio interface. The generic
library provides support for many memory-mapped GPIO controllers
that are found in various on-board FPGA and ASIC solutions that
are used to control board's switches, LEDs, chip-selects,
Ethernet/USB PHY power, etc.

For setting GPIOs there are three configurations:
	1. single input/output register resource (named "dat"),
	2. set/clear pair (named "set" and "clr"),
	3. single output register resource and single input resource
	   ("set" and dat").

The configuration is detected by which resources are present.
For the single output register, this drives a 1 by setting a bit
and a zero by clearing a bit.  For the set clr pair, this drives
a 1 by setting a bit in the set register and clears it by setting
a bit in the clear register.

For setting the GPIO direction, there are three configurations:
	a. simple bidirectional GPIOs that requires no configuration.
	b. an output direction register (named "dirout")
	   where a 1 bit indicates the GPIO is an output.
	c. an input direction register (named "dirin")
	   where a 1 bit indicates the GPIO is an input.

Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Signed-off-by: Christian Lamparter <chunkeey@googlemail.com>
Acked-by: Alexandre Courbot <acourbot@nvidia.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
2016-06-08 11:15:11 +02:00
Christian Lamparter
e9f4d569fb gpio: rename gpio-generic.c into gpio-mmio.c
This patch renames the gpio-generic.c into gpio-mmio.c.
This is because currently the file only contains code
for a memory-mapped GPIO driver. There isn't any support
for ioports or other resource type.

Signed-off-by: Christian Lamparter <chunkeey@googlemail.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
2016-04-29 16:14:32 +02:00