提交 5e6a5845 编写于 作者: L Linus Torvalds

Merge tag 'gpio-updates-for-v5.15' of git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux

Pull gpio updates from Bartosz Golaszewski:
 "We mostly have various improvements and refactoring all over the place
  but also some interesting new features - like the virtio GPIO driver
  that allows guest VMs to use host's GPIOs. We also have a new/old GPIO
  driver for rockchip - this one has been split out of the pinctrl
  driver.

  Summary:

   - new driver: gpio-virtio allowing a guest VM running linux to access
     GPIO lines provided by the host

   - split the GPIO driver out of the rockchip pin control driver

   - add support for a new model to gpio-aspeed-sgpio, refactor the
     driver and use generic device property interfaces, improve property
     sanitization

   - add ACPI support to gpio-tegra186

   - improve the code setting the line names to support multiple GPIO
     banks per device

   - constify a bunch of OF functions in the core GPIO code and make the
     declaration for one of the core OF functions we use consistent
     within its header

   - use software nodes in intel_quark_i2c_gpio

   - add support for the gpio-line-names property in gpio-mt7621

   - use the standard GPIO function for setting the GPIO names in
     gpio-brcmstb

   - fix a bunch of leaks and other bugs in gpio-mpc8xxx

   - use generic pm callbacks in gpio-ml-ioh

   - improve resource management and PM handling in gpio-mlxbf2

   - modernize and improve the gpio-dwapb driver

   - coding style improvements in gpio-rcar

   - documentation fixes and improvements

   - update the MAINTAINERS entry for gpio-zynq

   - minor tweaks in several drivers"

* tag 'gpio-updates-for-v5.15' of git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux: (35 commits)
  gpio: mpc8xxx: Use 'devm_gpiochip_add_data()' to simplify the code and avoid a leak
  gpio: mpc8xxx: Fix a potential double iounmap call in 'mpc8xxx_probe()'
  gpio: mpc8xxx: Fix a resources leak in the error handling path of 'mpc8xxx_probe()'
  gpio: viperboard: remove platform_set_drvdata() call in probe
  gpio: virtio: Add missing mailings lists in MAINTAINERS entry
  gpio: virtio: Fix sparse warnings
  gpio: remove the obsolete MX35 3DS BOARD MC9S08DZ60 GPIO functions
  gpio: max730x: Use the right include
  gpio: Add virtio-gpio driver
  gpio: mlxbf2: Use DEFINE_RES_MEM_NAMED() helper macro
  gpio: mlxbf2: Use devm_platform_ioremap_resource()
  gpio: mlxbf2: Drop wrong use of ACPI_PTR()
  gpio: mlxbf2: Convert to device PM ops
  gpio: dwapb: Get rid of legacy platform data
  mfd: intel_quark_i2c_gpio: Convert GPIO to use software nodes
  gpio: dwapb: Read GPIO base from gpio-base property
  gpio: dwapb: Unify ACPI enumeration checks in get_irq() and configure_irqs()
  gpiolib: Deduplicate forward declaration in the consumer.h header
  MAINTAINERS: update gpio-zynq.yaml reference
  gpio: tegra186: Add ACPI support
  ...
...@@ -72,6 +72,10 @@ for the GPIO. Values can be: ...@@ -72,6 +72,10 @@ for the GPIO. Values can be:
* GPIOD_OUT_HIGH_OPEN_DRAIN same as GPIOD_OUT_HIGH but also enforce the line * GPIOD_OUT_HIGH_OPEN_DRAIN same as GPIOD_OUT_HIGH but also enforce the line
to be electrically used with open drain. to be electrically used with open drain.
Note that the initial value is *logical* and the physical line level depends on
whether the line is configured active high or active low (see
:ref:`active_low_semantics`).
The two last flags are used for use cases where open drain is mandatory, such The two last flags are used for use cases where open drain is mandatory, such
as I2C: if the line is not already configured as open drain in the mappings as I2C: if the line is not already configured as open drain in the mappings
(see board.txt), then open drain will be enforced anyway and a warning will be (see board.txt), then open drain will be enforced anyway and a warning will be
...@@ -252,6 +256,8 @@ that can't be accessed from hardIRQ handlers, these calls act the same as the ...@@ -252,6 +256,8 @@ that can't be accessed from hardIRQ handlers, these calls act the same as the
spinlock-safe calls. spinlock-safe calls.
.. _active_low_semantics:
The active low and open drain semantics The active low and open drain semantics
--------------------------------------- ---------------------------------------
As a consumer should not have to care about the physical line level, all of the As a consumer should not have to care about the physical line level, all of the
...@@ -309,9 +315,11 @@ work on the raw line value:: ...@@ -309,9 +315,11 @@ work on the raw line value::
void gpiod_set_raw_value_cansleep(struct gpio_desc *desc, int value) void gpiod_set_raw_value_cansleep(struct gpio_desc *desc, int value)
int gpiod_direction_output_raw(struct gpio_desc *desc, int value) int gpiod_direction_output_raw(struct gpio_desc *desc, int value)
The active low state of a GPIO can also be queried using the following call:: The active low state of a GPIO can also be queried and toggled using the
following calls::
int gpiod_is_active_low(const struct gpio_desc *desc) int gpiod_is_active_low(const struct gpio_desc *desc)
void gpiod_toggle_active_low(struct gpio_desc *desc)
Note that these functions should only be used with great moderation; a driver Note that these functions should only be used with great moderation; a driver
should not have to care about the physical line level or open drain semantics. should not have to care about the physical line level or open drain semantics.
......
...@@ -547,13 +547,10 @@ To use the helpers please keep the following in mind: ...@@ -547,13 +547,10 @@ To use the helpers please keep the following in mind:
the irqchip can initialize. E.g. .dev and .can_sleep shall be set up the irqchip can initialize. E.g. .dev and .can_sleep shall be set up
properly. properly.
- Nominally set all handlers to handle_bad_irq() in the setup call and pass - Nominally set gpio_irq_chip.handler to handle_bad_irq. Then, if your irqchip
handle_bad_irq() as flow handler parameter in gpiochip_irqchip_add() if it is is cascaded, set the handler to handle_level_irq() and/or handle_edge_irq()
expected for GPIO driver that irqchip .set_type() callback will be called in the irqchip .set_type() callback depending on what your controller
before using/enabling each GPIO IRQ. Then set the handler to supports and what is requested by the consumer.
handle_level_irq() and/or handle_edge_irq() in the irqchip .set_type()
callback depending on what your controller supports and what is requested
by the consumer.
Locking IRQ usage Locking IRQ usage
......
...@@ -19852,6 +19852,15 @@ F: Documentation/filesystems/virtiofs.rst ...@@ -19852,6 +19852,15 @@ F: Documentation/filesystems/virtiofs.rst
F: fs/fuse/virtio_fs.c F: fs/fuse/virtio_fs.c
F: include/uapi/linux/virtio_fs.h F: include/uapi/linux/virtio_fs.h
VIRTIO GPIO DRIVER
M: Enrico Weigelt, metux IT consult <info@metux.net>
M: Viresh Kumar <vireshk@kernel.org>
L: linux-gpio@vger.kernel.org
L: virtualization@lists.linux-foundation.org
S: Maintained
F: drivers/gpio/gpio-virtio.c
F: include/uapi/linux/virtio_gpio.h
VIRTIO GPU DRIVER VIRTIO GPU DRIVER
M: David Airlie <airlied@linux.ie> M: David Airlie <airlied@linux.ie>
M: Gerd Hoffmann <kraxel@redhat.com> M: Gerd Hoffmann <kraxel@redhat.com>
...@@ -20546,7 +20555,7 @@ R: Srinivas Neeli <srinivas.neeli@xilinx.com> ...@@ -20546,7 +20555,7 @@ R: Srinivas Neeli <srinivas.neeli@xilinx.com>
R: Michal Simek <michal.simek@xilinx.com> R: Michal Simek <michal.simek@xilinx.com>
S: Maintained S: Maintained
F: Documentation/devicetree/bindings/gpio/gpio-xilinx.txt F: Documentation/devicetree/bindings/gpio/gpio-xilinx.txt
F: Documentation/devicetree/bindings/gpio/gpio-zynq.txt F: Documentation/devicetree/bindings/gpio/gpio-zynq.yaml
F: drivers/gpio/gpio-xilinx.c F: drivers/gpio/gpio-xilinx.c
F: drivers/gpio/gpio-zynq.c F: drivers/gpio/gpio-zynq.c
......
...@@ -1018,12 +1018,6 @@ config GPIO_MAX732X_IRQ ...@@ -1018,12 +1018,6 @@ config GPIO_MAX732X_IRQ
Say yes here to enable the max732x to be used as an interrupt Say yes here to enable the max732x to be used as an interrupt
controller. It requires the driver to be built in the kernel. controller. It requires the driver to be built in the kernel.
config GPIO_MC9S08DZ60
bool "MX35 3DS BOARD MC9S08DZ60 GPIO functions"
depends on I2C=y && MACH_MX35_3DS
help
Select this to enable the MC9S08DZ60 GPIO driver
config GPIO_PCA953X config GPIO_PCA953X
tristate "PCA95[357]x, PCA9698, TCA64xx, and MAX7310 I/O ports" tristate "PCA95[357]x, PCA9698, TCA64xx, and MAX7310 I/O ports"
select REGMAP_I2C select REGMAP_I2C
...@@ -1677,6 +1671,15 @@ config GPIO_MOCKUP ...@@ -1677,6 +1671,15 @@ config GPIO_MOCKUP
tools/testing/selftests/gpio/gpio-mockup.sh. Reference the usage in tools/testing/selftests/gpio/gpio-mockup.sh. Reference the usage in
it. it.
config GPIO_VIRTIO
tristate "VirtIO GPIO support"
depends on VIRTIO
help
Say Y here to enable guest support for virtio-based GPIO controllers.
These virtual GPIOs can be routed to real GPIOs or attached to
simulators on the host (like QEMU).
endmenu endmenu
endif endif
...@@ -92,7 +92,6 @@ obj-$(CONFIG_GPIO_MAX77620) += gpio-max77620.o ...@@ -92,7 +92,6 @@ obj-$(CONFIG_GPIO_MAX77620) += gpio-max77620.o
obj-$(CONFIG_GPIO_MAX77650) += gpio-max77650.o obj-$(CONFIG_GPIO_MAX77650) += gpio-max77650.o
obj-$(CONFIG_GPIO_MB86S7X) += gpio-mb86s7x.o obj-$(CONFIG_GPIO_MB86S7X) += gpio-mb86s7x.o
obj-$(CONFIG_GPIO_MC33880) += gpio-mc33880.o obj-$(CONFIG_GPIO_MC33880) += gpio-mc33880.o
obj-$(CONFIG_GPIO_MC9S08DZ60) += gpio-mc9s08dz60.o
obj-$(CONFIG_GPIO_MENZ127) += gpio-menz127.o obj-$(CONFIG_GPIO_MENZ127) += gpio-menz127.o
obj-$(CONFIG_GPIO_MERRIFIELD) += gpio-merrifield.o obj-$(CONFIG_GPIO_MERRIFIELD) += gpio-merrifield.o
obj-$(CONFIG_GPIO_ML_IOH) += gpio-ml-ioh.o obj-$(CONFIG_GPIO_ML_IOH) += gpio-ml-ioh.o
...@@ -166,6 +165,7 @@ obj-$(CONFIG_GPIO_UCB1400) += gpio-ucb1400.o ...@@ -166,6 +165,7 @@ obj-$(CONFIG_GPIO_UCB1400) += gpio-ucb1400.o
obj-$(CONFIG_GPIO_UNIPHIER) += gpio-uniphier.o obj-$(CONFIG_GPIO_UNIPHIER) += gpio-uniphier.o
obj-$(CONFIG_GPIO_VF610) += gpio-vf610.o obj-$(CONFIG_GPIO_VF610) += gpio-vf610.o
obj-$(CONFIG_GPIO_VIPERBOARD) += gpio-viperboard.o obj-$(CONFIG_GPIO_VIPERBOARD) += gpio-viperboard.o
obj-$(CONFIG_GPIO_VIRTIO) += gpio-virtio.o
obj-$(CONFIG_GPIO_VISCONTI) += gpio-visconti.o obj-$(CONFIG_GPIO_VISCONTI) += gpio-visconti.o
obj-$(CONFIG_GPIO_VR41XX) += gpio-vr41xx.o obj-$(CONFIG_GPIO_VR41XX) += gpio-vr41xx.o
obj-$(CONFIG_GPIO_VX855) += gpio-vx855.o obj-$(CONFIG_GPIO_VX855) += gpio-vx855.o
......
...@@ -17,37 +17,30 @@ ...@@ -17,37 +17,30 @@
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/string.h> #include <linux/string.h>
/*
* MAX_NR_HW_GPIO represents the number of actual hardware-supported GPIOs (ie,
* slots within the clocked serial GPIO data). Since each HW GPIO is both an
* input and an output, we provide MAX_NR_HW_GPIO * 2 lines on our gpiochip
* device.
*
* We use SGPIO_OUTPUT_OFFSET to define the split between the inputs and
* outputs; the inputs start at line 0, the outputs start at OUTPUT_OFFSET.
*/
#define MAX_NR_HW_SGPIO 80
#define SGPIO_OUTPUT_OFFSET MAX_NR_HW_SGPIO
#define ASPEED_SGPIO_CTRL 0x54 #define ASPEED_SGPIO_CTRL 0x54
#define ASPEED_SGPIO_PINS_MASK GENMASK(9, 6)
#define ASPEED_SGPIO_CLK_DIV_MASK GENMASK(31, 16) #define ASPEED_SGPIO_CLK_DIV_MASK GENMASK(31, 16)
#define ASPEED_SGPIO_ENABLE BIT(0) #define ASPEED_SGPIO_ENABLE BIT(0)
#define ASPEED_SGPIO_PINS_SHIFT 6
struct aspeed_sgpio_pdata {
const u32 pin_mask;
};
struct aspeed_sgpio { struct aspeed_sgpio {
struct gpio_chip chip; struct gpio_chip chip;
struct irq_chip intc;
struct clk *pclk; struct clk *pclk;
spinlock_t lock; spinlock_t lock;
void __iomem *base; void __iomem *base;
int irq; int irq;
int n_sgpio;
}; };
struct aspeed_sgpio_bank { struct aspeed_sgpio_bank {
uint16_t val_regs; u16 val_regs;
uint16_t rdata_reg; u16 rdata_reg;
uint16_t irq_regs; u16 irq_regs;
u16 tolerance_regs;
const char names[4][3]; const char names[4][3];
}; };
...@@ -63,19 +56,29 @@ static const struct aspeed_sgpio_bank aspeed_sgpio_banks[] = { ...@@ -63,19 +56,29 @@ static const struct aspeed_sgpio_bank aspeed_sgpio_banks[] = {
.val_regs = 0x0000, .val_regs = 0x0000,
.rdata_reg = 0x0070, .rdata_reg = 0x0070,
.irq_regs = 0x0004, .irq_regs = 0x0004,
.tolerance_regs = 0x0018,
.names = { "A", "B", "C", "D" }, .names = { "A", "B", "C", "D" },
}, },
{ {
.val_regs = 0x001C, .val_regs = 0x001C,
.rdata_reg = 0x0074, .rdata_reg = 0x0074,
.irq_regs = 0x0020, .irq_regs = 0x0020,
.tolerance_regs = 0x0034,
.names = { "E", "F", "G", "H" }, .names = { "E", "F", "G", "H" },
}, },
{ {
.val_regs = 0x0038, .val_regs = 0x0038,
.rdata_reg = 0x0078, .rdata_reg = 0x0078,
.irq_regs = 0x003C, .irq_regs = 0x003C,
.names = { "I", "J" }, .tolerance_regs = 0x0050,
.names = { "I", "J", "K", "L" },
},
{
.val_regs = 0x0090,
.rdata_reg = 0x007C,
.irq_regs = 0x0094,
.tolerance_regs = 0x00A8,
.names = { "M", "N", "O", "P" },
}, },
}; };
...@@ -87,6 +90,7 @@ enum aspeed_sgpio_reg { ...@@ -87,6 +90,7 @@ enum aspeed_sgpio_reg {
reg_irq_type1, reg_irq_type1,
reg_irq_type2, reg_irq_type2,
reg_irq_status, reg_irq_status,
reg_tolerance,
}; };
#define GPIO_VAL_VALUE 0x00 #define GPIO_VAL_VALUE 0x00
...@@ -115,15 +119,17 @@ static void __iomem *bank_reg(struct aspeed_sgpio *gpio, ...@@ -115,15 +119,17 @@ static void __iomem *bank_reg(struct aspeed_sgpio *gpio,
return gpio->base + bank->irq_regs + GPIO_IRQ_TYPE2; return gpio->base + bank->irq_regs + GPIO_IRQ_TYPE2;
case reg_irq_status: case reg_irq_status:
return gpio->base + bank->irq_regs + GPIO_IRQ_STATUS; return gpio->base + bank->irq_regs + GPIO_IRQ_STATUS;
case reg_tolerance:
return gpio->base + bank->tolerance_regs;
default: default:
/* acturally if code runs to here, it's an error case */ /* acturally if code runs to here, it's an error case */
BUG(); BUG();
} }
} }
#define GPIO_BANK(x) ((x % SGPIO_OUTPUT_OFFSET) >> 5) #define GPIO_BANK(x) ((x) >> 6)
#define GPIO_OFFSET(x) ((x % SGPIO_OUTPUT_OFFSET) & 0x1f) #define GPIO_OFFSET(x) ((x) & GENMASK(5, 0))
#define GPIO_BIT(x) BIT(GPIO_OFFSET(x)) #define GPIO_BIT(x) BIT(GPIO_OFFSET(x) >> 1)
static const struct aspeed_sgpio_bank *to_bank(unsigned int offset) static const struct aspeed_sgpio_bank *to_bank(unsigned int offset)
{ {
...@@ -138,39 +144,25 @@ static const struct aspeed_sgpio_bank *to_bank(unsigned int offset) ...@@ -138,39 +144,25 @@ static const struct aspeed_sgpio_bank *to_bank(unsigned int offset)
static int aspeed_sgpio_init_valid_mask(struct gpio_chip *gc, static int aspeed_sgpio_init_valid_mask(struct gpio_chip *gc,
unsigned long *valid_mask, unsigned int ngpios) unsigned long *valid_mask, unsigned int ngpios)
{ {
struct aspeed_sgpio *sgpio = gpiochip_get_data(gc); bitmap_set(valid_mask, 0, ngpios);
int n = sgpio->n_sgpio;
int c = SGPIO_OUTPUT_OFFSET - n;
WARN_ON(ngpios < MAX_NR_HW_SGPIO * 2);
/* input GPIOs in the lower range */
bitmap_set(valid_mask, 0, n);
bitmap_clear(valid_mask, n, c);
/* output GPIOS above SGPIO_OUTPUT_OFFSET */
bitmap_set(valid_mask, SGPIO_OUTPUT_OFFSET, n);
bitmap_clear(valid_mask, SGPIO_OUTPUT_OFFSET + n, c);
return 0; return 0;
} }
static void aspeed_sgpio_irq_init_valid_mask(struct gpio_chip *gc, static void aspeed_sgpio_irq_init_valid_mask(struct gpio_chip *gc,
unsigned long *valid_mask, unsigned int ngpios) unsigned long *valid_mask, unsigned int ngpios)
{ {
struct aspeed_sgpio *sgpio = gpiochip_get_data(gc); unsigned int i;
int n = sgpio->n_sgpio;
WARN_ON(ngpios < MAX_NR_HW_SGPIO * 2); /* input GPIOs are even bits */
for (i = 0; i < ngpios; i++) {
/* input GPIOs in the lower range */ if (i % 2)
bitmap_set(valid_mask, 0, n); clear_bit(i, valid_mask);
bitmap_clear(valid_mask, n, ngpios - n); }
} }
static bool aspeed_sgpio_is_input(unsigned int offset) static bool aspeed_sgpio_is_input(unsigned int offset)
{ {
return offset < SGPIO_OUTPUT_OFFSET; return !(offset % 2);
} }
static int aspeed_sgpio_get(struct gpio_chip *gc, unsigned int offset) static int aspeed_sgpio_get(struct gpio_chip *gc, unsigned int offset)
...@@ -409,14 +401,6 @@ static void aspeed_sgpio_irq_handler(struct irq_desc *desc) ...@@ -409,14 +401,6 @@ static void aspeed_sgpio_irq_handler(struct irq_desc *desc)
chained_irq_exit(ic, desc); chained_irq_exit(ic, desc);
} }
static struct irq_chip aspeed_sgpio_irqchip = {
.name = "aspeed-sgpio",
.irq_ack = aspeed_sgpio_irq_ack,
.irq_mask = aspeed_sgpio_irq_mask,
.irq_unmask = aspeed_sgpio_irq_unmask,
.irq_set_type = aspeed_sgpio_set_type,
};
static int aspeed_sgpio_setup_irqs(struct aspeed_sgpio *gpio, static int aspeed_sgpio_setup_irqs(struct aspeed_sgpio *gpio,
struct platform_device *pdev) struct platform_device *pdev)
{ {
...@@ -439,8 +423,14 @@ static int aspeed_sgpio_setup_irqs(struct aspeed_sgpio *gpio, ...@@ -439,8 +423,14 @@ static int aspeed_sgpio_setup_irqs(struct aspeed_sgpio *gpio,
iowrite32(0xffffffff, bank_reg(gpio, bank, reg_irq_status)); iowrite32(0xffffffff, bank_reg(gpio, bank, reg_irq_status));
} }
gpio->intc.name = dev_name(&pdev->dev);
gpio->intc.irq_ack = aspeed_sgpio_irq_ack;
gpio->intc.irq_mask = aspeed_sgpio_irq_mask;
gpio->intc.irq_unmask = aspeed_sgpio_irq_unmask;
gpio->intc.irq_set_type = aspeed_sgpio_set_type;
irq = &gpio->chip.irq; irq = &gpio->chip.irq;
irq->chip = &aspeed_sgpio_irqchip; irq->chip = &gpio->intc;
irq->init_valid_mask = aspeed_sgpio_irq_init_valid_mask; irq->init_valid_mask = aspeed_sgpio_irq_init_valid_mask;
irq->handler = handle_bad_irq; irq->handler = handle_bad_irq;
irq->default_type = IRQ_TYPE_NONE; irq->default_type = IRQ_TYPE_NONE;
...@@ -463,9 +453,56 @@ static int aspeed_sgpio_setup_irqs(struct aspeed_sgpio *gpio, ...@@ -463,9 +453,56 @@ static int aspeed_sgpio_setup_irqs(struct aspeed_sgpio *gpio,
return 0; return 0;
} }
static const struct aspeed_sgpio_pdata ast2400_sgpio_pdata = {
.pin_mask = GENMASK(9, 6),
};
static int aspeed_sgpio_reset_tolerance(struct gpio_chip *chip,
unsigned int offset, bool enable)
{
struct aspeed_sgpio *gpio = gpiochip_get_data(chip);
unsigned long flags;
void __iomem *reg;
u32 val;
reg = bank_reg(gpio, to_bank(offset), reg_tolerance);
spin_lock_irqsave(&gpio->lock, flags);
val = readl(reg);
if (enable)
val |= GPIO_BIT(offset);
else
val &= ~GPIO_BIT(offset);
writel(val, reg);
spin_unlock_irqrestore(&gpio->lock, flags);
return 0;
}
static int aspeed_sgpio_set_config(struct gpio_chip *chip, unsigned int offset,
unsigned long config)
{
unsigned long param = pinconf_to_config_param(config);
u32 arg = pinconf_to_config_argument(config);
if (param == PIN_CONFIG_PERSIST_STATE)
return aspeed_sgpio_reset_tolerance(chip, offset, arg);
return -ENOTSUPP;
}
static const struct aspeed_sgpio_pdata ast2600_sgpiom_pdata = {
.pin_mask = GENMASK(10, 6),
};
static const struct of_device_id aspeed_sgpio_of_table[] = { static const struct of_device_id aspeed_sgpio_of_table[] = {
{ .compatible = "aspeed,ast2400-sgpio" }, { .compatible = "aspeed,ast2400-sgpio", .data = &ast2400_sgpio_pdata, },
{ .compatible = "aspeed,ast2500-sgpio" }, { .compatible = "aspeed,ast2500-sgpio", .data = &ast2400_sgpio_pdata, },
{ .compatible = "aspeed,ast2600-sgpiom", .data = &ast2600_sgpiom_pdata, },
{} {}
}; };
...@@ -473,10 +510,11 @@ MODULE_DEVICE_TABLE(of, aspeed_sgpio_of_table); ...@@ -473,10 +510,11 @@ MODULE_DEVICE_TABLE(of, aspeed_sgpio_of_table);
static int __init aspeed_sgpio_probe(struct platform_device *pdev) static int __init aspeed_sgpio_probe(struct platform_device *pdev)
{ {
u32 nr_gpios, sgpio_freq, sgpio_clk_div, gpio_cnt_regval, pin_mask;
const struct aspeed_sgpio_pdata *pdata;
struct aspeed_sgpio *gpio; struct aspeed_sgpio *gpio;
u32 nr_gpios, sgpio_freq, sgpio_clk_div;
int rc;
unsigned long apb_freq; unsigned long apb_freq;
int rc;
gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL); gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL);
if (!gpio) if (!gpio)
...@@ -486,18 +524,23 @@ static int __init aspeed_sgpio_probe(struct platform_device *pdev) ...@@ -486,18 +524,23 @@ static int __init aspeed_sgpio_probe(struct platform_device *pdev)
if (IS_ERR(gpio->base)) if (IS_ERR(gpio->base))
return PTR_ERR(gpio->base); return PTR_ERR(gpio->base);
rc = of_property_read_u32(pdev->dev.of_node, "ngpios", &nr_gpios); pdata = device_get_match_data(&pdev->dev);
if (!pdata)
return -EINVAL;
pin_mask = pdata->pin_mask;
rc = device_property_read_u32(&pdev->dev, "ngpios", &nr_gpios);
if (rc < 0) { if (rc < 0) {
dev_err(&pdev->dev, "Could not read ngpios property\n"); dev_err(&pdev->dev, "Could not read ngpios property\n");
return -EINVAL; return -EINVAL;
} else if (nr_gpios > MAX_NR_HW_SGPIO) { } else if (nr_gpios % 8) {
dev_err(&pdev->dev, "Number of GPIOs exceeds the maximum of %d: %d\n", dev_err(&pdev->dev, "Number of GPIOs not multiple of 8: %d\n",
MAX_NR_HW_SGPIO, nr_gpios); nr_gpios);
return -EINVAL; return -EINVAL;
} }
gpio->n_sgpio = nr_gpios;
rc = of_property_read_u32(pdev->dev.of_node, "bus-frequency", &sgpio_freq); rc = device_property_read_u32(&pdev->dev, "bus-frequency", &sgpio_freq);
if (rc < 0) { if (rc < 0) {
dev_err(&pdev->dev, "Could not read bus-frequency property\n"); dev_err(&pdev->dev, "Could not read bus-frequency property\n");
return -EINVAL; return -EINVAL;
...@@ -528,15 +571,14 @@ static int __init aspeed_sgpio_probe(struct platform_device *pdev) ...@@ -528,15 +571,14 @@ static int __init aspeed_sgpio_probe(struct platform_device *pdev)
if (sgpio_clk_div > (1 << 16) - 1) if (sgpio_clk_div > (1 << 16) - 1)
return -EINVAL; return -EINVAL;
iowrite32(FIELD_PREP(ASPEED_SGPIO_CLK_DIV_MASK, sgpio_clk_div) | gpio_cnt_regval = ((nr_gpios / 8) << ASPEED_SGPIO_PINS_SHIFT) & pin_mask;
FIELD_PREP(ASPEED_SGPIO_PINS_MASK, (nr_gpios / 8)) | iowrite32(FIELD_PREP(ASPEED_SGPIO_CLK_DIV_MASK, sgpio_clk_div) | gpio_cnt_regval |
ASPEED_SGPIO_ENABLE, ASPEED_SGPIO_ENABLE, gpio->base + ASPEED_SGPIO_CTRL);
gpio->base + ASPEED_SGPIO_CTRL);
spin_lock_init(&gpio->lock); spin_lock_init(&gpio->lock);
gpio->chip.parent = &pdev->dev; gpio->chip.parent = &pdev->dev;
gpio->chip.ngpio = MAX_NR_HW_SGPIO * 2; gpio->chip.ngpio = nr_gpios * 2;
gpio->chip.init_valid_mask = aspeed_sgpio_init_valid_mask; gpio->chip.init_valid_mask = aspeed_sgpio_init_valid_mask;
gpio->chip.direction_input = aspeed_sgpio_dir_in; gpio->chip.direction_input = aspeed_sgpio_dir_in;
gpio->chip.direction_output = aspeed_sgpio_dir_out; gpio->chip.direction_output = aspeed_sgpio_dir_out;
...@@ -545,7 +587,7 @@ static int __init aspeed_sgpio_probe(struct platform_device *pdev) ...@@ -545,7 +587,7 @@ static int __init aspeed_sgpio_probe(struct platform_device *pdev)
gpio->chip.free = NULL; gpio->chip.free = NULL;
gpio->chip.get = aspeed_sgpio_get; gpio->chip.get = aspeed_sgpio_get;
gpio->chip.set = aspeed_sgpio_set; gpio->chip.set = aspeed_sgpio_set;
gpio->chip.set_config = NULL; gpio->chip.set_config = aspeed_sgpio_set_config;
gpio->chip.label = dev_name(&pdev->dev); gpio->chip.label = dev_name(&pdev->dev);
gpio->chip.base = -1; gpio->chip.base = -1;
......
...@@ -602,49 +602,6 @@ static const struct dev_pm_ops brcmstb_gpio_pm_ops = { ...@@ -602,49 +602,6 @@ static const struct dev_pm_ops brcmstb_gpio_pm_ops = {
.resume_noirq = brcmstb_gpio_resume, .resume_noirq = brcmstb_gpio_resume,
}; };
static void brcmstb_gpio_set_names(struct device *dev,
struct brcmstb_gpio_bank *bank)
{
struct device_node *np = dev->of_node;
const char **names;
int nstrings, base;
unsigned int i;
base = bank->id * MAX_GPIO_PER_BANK;
nstrings = of_property_count_strings(np, "gpio-line-names");
if (nstrings <= base)
/* Line names not present */
return;
names = devm_kcalloc(dev, MAX_GPIO_PER_BANK, sizeof(*names),
GFP_KERNEL);
if (!names)
return;
/*
* Make sure to not index beyond the end of the number of descriptors
* of the GPIO device.
*/
for (i = 0; i < bank->width; i++) {
const char *name;
int ret;
ret = of_property_read_string_index(np, "gpio-line-names",
base + i, &name);
if (ret) {
if (ret != -ENODATA)
dev_err(dev, "unable to name line %d: %d\n",
base + i, ret);
break;
}
if (*name)
names[i] = name;
}
bank->gc.names = names;
}
static int brcmstb_gpio_probe(struct platform_device *pdev) static int brcmstb_gpio_probe(struct platform_device *pdev)
{ {
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
...@@ -758,6 +715,7 @@ static int brcmstb_gpio_probe(struct platform_device *pdev) ...@@ -758,6 +715,7 @@ static int brcmstb_gpio_probe(struct platform_device *pdev)
gc->of_xlate = brcmstb_gpio_of_xlate; gc->of_xlate = brcmstb_gpio_of_xlate;
/* not all ngpio lines are valid, will use bank width later */ /* not all ngpio lines are valid, will use bank width later */
gc->ngpio = MAX_GPIO_PER_BANK; gc->ngpio = MAX_GPIO_PER_BANK;
gc->offset = bank->id * MAX_GPIO_PER_BANK;
if (priv->parent_irq > 0) if (priv->parent_irq > 0)
gc->to_irq = brcmstb_gpio_to_irq; gc->to_irq = brcmstb_gpio_to_irq;
...@@ -768,7 +726,6 @@ static int brcmstb_gpio_probe(struct platform_device *pdev) ...@@ -768,7 +726,6 @@ static int brcmstb_gpio_probe(struct platform_device *pdev)
need_wakeup_event |= !!__brcmstb_gpio_get_active_irqs(bank); need_wakeup_event |= !!__brcmstb_gpio_get_active_irqs(bank);
gc->write_reg(reg_base + GIO_MASK(bank->id), 0); gc->write_reg(reg_base + GIO_MASK(bank->id), 0);
brcmstb_gpio_set_names(dev, bank);
err = gpiochip_add_data(gc, bank); err = gpiochip_add_data(gc, bank);
if (err) { if (err) {
dev_err(dev, "Could not add gpiochip for bank %d\n", dev_err(dev, "Could not add gpiochip for bank %d\n",
......
...@@ -16,7 +16,6 @@ ...@@ -16,7 +16,6 @@
#include <linux/mod_devicetable.h> #include <linux/mod_devicetable.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/platform_data/gpio-dwapb.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/property.h> #include <linux/property.h>
#include <linux/reset.h> #include <linux/reset.h>
...@@ -48,6 +47,7 @@ ...@@ -48,6 +47,7 @@
#define DWAPB_DRIVER_NAME "gpio-dwapb" #define DWAPB_DRIVER_NAME "gpio-dwapb"
#define DWAPB_MAX_PORTS 4 #define DWAPB_MAX_PORTS 4
#define DWAPB_MAX_GPIOS 32
#define GPIO_EXT_PORT_STRIDE 0x04 /* register stride 32 bits */ #define GPIO_EXT_PORT_STRIDE 0x04 /* register stride 32 bits */
#define GPIO_SWPORT_DR_STRIDE 0x0c /* register stride 3*32 bits */ #define GPIO_SWPORT_DR_STRIDE 0x0c /* register stride 3*32 bits */
...@@ -65,6 +65,19 @@ ...@@ -65,6 +65,19 @@
struct dwapb_gpio; struct dwapb_gpio;
struct dwapb_port_property {
struct fwnode_handle *fwnode;
unsigned int idx;
unsigned int ngpio;
unsigned int gpio_base;
int irq[DWAPB_MAX_GPIOS];
};
struct dwapb_platform_data {
struct dwapb_port_property *properties;
unsigned int nports;
};
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM_SLEEP
/* Store GPIO context across system-wide suspend/resume transitions */ /* Store GPIO context across system-wide suspend/resume transitions */
struct dwapb_context { struct dwapb_context {
...@@ -436,21 +449,17 @@ static void dwapb_configure_irqs(struct dwapb_gpio *gpio, ...@@ -436,21 +449,17 @@ static void dwapb_configure_irqs(struct dwapb_gpio *gpio,
pirq->irqchip.irq_set_wake = dwapb_irq_set_wake; pirq->irqchip.irq_set_wake = dwapb_irq_set_wake;
#endif #endif
if (!pp->irq_shared) { /*
girq->num_parents = pirq->nr_irqs; * Intel ACPI-based platforms mostly have the DesignWare APB GPIO
girq->parents = pirq->irq; * IRQ lane shared between several devices. In that case the parental
girq->parent_handler_data = gpio; * IRQ has to be handled in the shared way so to be properly delivered
girq->parent_handler = dwapb_irq_handler; * to all the connected devices.
} else { */
/* This will let us handle the parent IRQ in the driver */ if (has_acpi_companion(gpio->dev)) {
girq->num_parents = 0; girq->num_parents = 0;
girq->parents = NULL; girq->parents = NULL;
girq->parent_handler = NULL; girq->parent_handler = NULL;
/*
* Request a shared IRQ since where MFD would have devices
* using the same irq pin
*/
err = devm_request_irq(gpio->dev, pp->irq[0], err = devm_request_irq(gpio->dev, pp->irq[0],
dwapb_irq_handler_mfd, dwapb_irq_handler_mfd,
IRQF_SHARED, DWAPB_DRIVER_NAME, gpio); IRQF_SHARED, DWAPB_DRIVER_NAME, gpio);
...@@ -458,6 +467,11 @@ static void dwapb_configure_irqs(struct dwapb_gpio *gpio, ...@@ -458,6 +467,11 @@ static void dwapb_configure_irqs(struct dwapb_gpio *gpio,
dev_err(gpio->dev, "error requesting IRQ\n"); dev_err(gpio->dev, "error requesting IRQ\n");
goto err_kfree_pirq; goto err_kfree_pirq;
} }
} else {
girq->num_parents = pirq->nr_irqs;
girq->parents = pirq->irq;
girq->parent_handler_data = gpio;
girq->parent_handler = dwapb_irq_handler;
} }
girq->chip = &pirq->irqchip; girq->chip = &pirq->irqchip;
...@@ -581,9 +595,12 @@ static struct dwapb_platform_data *dwapb_gpio_get_pdata(struct device *dev) ...@@ -581,9 +595,12 @@ static struct dwapb_platform_data *dwapb_gpio_get_pdata(struct device *dev)
pp->ngpio = DWAPB_MAX_GPIOS; pp->ngpio = DWAPB_MAX_GPIOS;
} }
pp->irq_shared = false;
pp->gpio_base = -1; pp->gpio_base = -1;
/* For internal use only, new platforms mustn't exercise this */
if (is_software_node(fwnode))
fwnode_property_read_u32(fwnode, "gpio-base", &pp->gpio_base);
/* /*
* Only port A can provide interrupts in all configurations of * Only port A can provide interrupts in all configurations of
* the IP. * the IP.
...@@ -670,17 +687,12 @@ static int dwapb_gpio_probe(struct platform_device *pdev) ...@@ -670,17 +687,12 @@ static int dwapb_gpio_probe(struct platform_device *pdev)
unsigned int i; unsigned int i;
struct dwapb_gpio *gpio; struct dwapb_gpio *gpio;
int err; int err;
struct dwapb_platform_data *pdata;
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct dwapb_platform_data *pdata = dev_get_platdata(dev);
if (!pdata) {
pdata = dwapb_gpio_get_pdata(dev);
if (IS_ERR(pdata))
return PTR_ERR(pdata);
}
if (!pdata->nports) pdata = dwapb_gpio_get_pdata(dev);
return -ENODEV; if (IS_ERR(pdata))
return PTR_ERR(pdata);
gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL); gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL);
if (!gpio) if (!gpio)
......
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright 2009-2012 Freescale Semiconductor, Inc. All Rights Reserved.
*
* Author: Wu Guoxing <b39297@freescale.com>
*/
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/i2c.h>
#include <linux/gpio/driver.h>
#define GPIO_GROUP_NUM 2
#define GPIO_NUM_PER_GROUP 8
#define GPIO_NUM (GPIO_GROUP_NUM*GPIO_NUM_PER_GROUP)
struct mc9s08dz60 {
struct i2c_client *client;
struct gpio_chip chip;
};
static void mc9s_gpio_to_reg_and_bit(int offset, u8 *reg, u8 *bit)
{
*reg = 0x20 + offset / GPIO_NUM_PER_GROUP;
*bit = offset % GPIO_NUM_PER_GROUP;
}
static int mc9s08dz60_get_value(struct gpio_chip *gc, unsigned offset)
{
u8 reg, bit;
s32 value;
struct mc9s08dz60 *mc9s = gpiochip_get_data(gc);
mc9s_gpio_to_reg_and_bit(offset, &reg, &bit);
value = i2c_smbus_read_byte_data(mc9s->client, reg);
return (value >= 0) ? (value >> bit) & 0x1 : 0;
}
static int mc9s08dz60_set(struct mc9s08dz60 *mc9s, unsigned offset, int val)
{
u8 reg, bit;
s32 value;
mc9s_gpio_to_reg_and_bit(offset, &reg, &bit);
value = i2c_smbus_read_byte_data(mc9s->client, reg);
if (value >= 0) {
if (val)
value |= 1 << bit;
else
value &= ~(1 << bit);
return i2c_smbus_write_byte_data(mc9s->client, reg, value);
} else
return value;
}
static void mc9s08dz60_set_value(struct gpio_chip *gc, unsigned offset, int val)
{
struct mc9s08dz60 *mc9s = gpiochip_get_data(gc);
mc9s08dz60_set(mc9s, offset, val);
}
static int mc9s08dz60_direction_output(struct gpio_chip *gc,
unsigned offset, int val)
{
struct mc9s08dz60 *mc9s = gpiochip_get_data(gc);
return mc9s08dz60_set(mc9s, offset, val);
}
static int mc9s08dz60_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct mc9s08dz60 *mc9s;
mc9s = devm_kzalloc(&client->dev, sizeof(*mc9s), GFP_KERNEL);
if (!mc9s)
return -ENOMEM;
mc9s->chip.label = client->name;
mc9s->chip.base = -1;
mc9s->chip.parent = &client->dev;
mc9s->chip.owner = THIS_MODULE;
mc9s->chip.ngpio = GPIO_NUM;
mc9s->chip.can_sleep = true;
mc9s->chip.get = mc9s08dz60_get_value;
mc9s->chip.set = mc9s08dz60_set_value;
mc9s->chip.direction_output = mc9s08dz60_direction_output;
mc9s->client = client;
i2c_set_clientdata(client, mc9s);
return devm_gpiochip_add_data(&client->dev, &mc9s->chip, mc9s);
}
static const struct i2c_device_id mc9s08dz60_id[] = {
{"mc9s08dz60", 0},
{},
};
static struct i2c_driver mc9s08dz60_i2c_driver = {
.driver = {
.name = "mc9s08dz60",
},
.probe = mc9s08dz60_probe,
.id_table = mc9s08dz60_id,
};
builtin_i2c_driver(mc9s08dz60_i2c_driver);
...@@ -155,11 +155,10 @@ static int ioh_gpio_direction_input(struct gpio_chip *gpio, unsigned nr) ...@@ -155,11 +155,10 @@ static int ioh_gpio_direction_input(struct gpio_chip *gpio, unsigned nr)
return 0; return 0;
} }
#ifdef CONFIG_PM
/* /*
* Save register configuration and disable interrupts. * Save register configuration and disable interrupts.
*/ */
static void ioh_gpio_save_reg_conf(struct ioh_gpio *chip) static void __maybe_unused ioh_gpio_save_reg_conf(struct ioh_gpio *chip)
{ {
int i; int i;
...@@ -185,7 +184,7 @@ static void ioh_gpio_save_reg_conf(struct ioh_gpio *chip) ...@@ -185,7 +184,7 @@ static void ioh_gpio_save_reg_conf(struct ioh_gpio *chip)
/* /*
* This function restores the register configuration of the GPIO device. * This function restores the register configuration of the GPIO device.
*/ */
static void ioh_gpio_restore_reg_conf(struct ioh_gpio *chip) static void __maybe_unused ioh_gpio_restore_reg_conf(struct ioh_gpio *chip)
{ {
int i; int i;
...@@ -207,7 +206,6 @@ static void ioh_gpio_restore_reg_conf(struct ioh_gpio *chip) ...@@ -207,7 +206,6 @@ static void ioh_gpio_restore_reg_conf(struct ioh_gpio *chip)
&chip->reg->ioh_sel_reg[i]); &chip->reg->ioh_sel_reg[i]);
} }
} }
#endif
static int ioh_gpio_to_irq(struct gpio_chip *gpio, unsigned offset) static int ioh_gpio_to_irq(struct gpio_chip *gpio, unsigned offset)
{ {
...@@ -522,47 +520,23 @@ static void ioh_gpio_remove(struct pci_dev *pdev) ...@@ -522,47 +520,23 @@ static void ioh_gpio_remove(struct pci_dev *pdev)
kfree(chip); kfree(chip);
} }
#ifdef CONFIG_PM static int __maybe_unused ioh_gpio_suspend(struct device *dev)
static int ioh_gpio_suspend(struct pci_dev *pdev, pm_message_t state)
{ {
s32 ret; struct ioh_gpio *chip = dev_get_drvdata(dev);
struct ioh_gpio *chip = pci_get_drvdata(pdev);
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&chip->spinlock, flags); spin_lock_irqsave(&chip->spinlock, flags);
ioh_gpio_save_reg_conf(chip); ioh_gpio_save_reg_conf(chip);
spin_unlock_irqrestore(&chip->spinlock, flags); spin_unlock_irqrestore(&chip->spinlock, flags);
ret = pci_save_state(pdev);
if (ret) {
dev_err(&pdev->dev, "pci_save_state Failed-%d\n", ret);
return ret;
}
pci_disable_device(pdev);
pci_set_power_state(pdev, PCI_D0);
ret = pci_enable_wake(pdev, PCI_D0, 1);
if (ret)
dev_err(&pdev->dev, "pci_enable_wake Failed -%d\n", ret);
return 0; return 0;
} }
static int ioh_gpio_resume(struct pci_dev *pdev) static int __maybe_unused ioh_gpio_resume(struct device *dev)
{ {
s32 ret; struct ioh_gpio *chip = dev_get_drvdata(dev);
struct ioh_gpio *chip = pci_get_drvdata(pdev);
unsigned long flags; unsigned long flags;
ret = pci_enable_wake(pdev, PCI_D0, 0);
pci_set_power_state(pdev, PCI_D0);
ret = pci_enable_device(pdev);
if (ret) {
dev_err(&pdev->dev, "pci_enable_device Failed-%d ", ret);
return ret;
}
pci_restore_state(pdev);
spin_lock_irqsave(&chip->spinlock, flags); spin_lock_irqsave(&chip->spinlock, flags);
iowrite32(0x01, &chip->reg->srst); iowrite32(0x01, &chip->reg->srst);
iowrite32(0x00, &chip->reg->srst); iowrite32(0x00, &chip->reg->srst);
...@@ -571,10 +545,8 @@ static int ioh_gpio_resume(struct pci_dev *pdev) ...@@ -571,10 +545,8 @@ static int ioh_gpio_resume(struct pci_dev *pdev)
return 0; return 0;
} }
#else
#define ioh_gpio_suspend NULL static SIMPLE_DEV_PM_OPS(ioh_gpio_pm_ops, ioh_gpio_suspend, ioh_gpio_resume);
#define ioh_gpio_resume NULL
#endif
static const struct pci_device_id ioh_gpio_pcidev_id[] = { static const struct pci_device_id ioh_gpio_pcidev_id[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x802E) }, { PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x802E) },
...@@ -587,8 +559,9 @@ static struct pci_driver ioh_gpio_driver = { ...@@ -587,8 +559,9 @@ static struct pci_driver ioh_gpio_driver = {
.id_table = ioh_gpio_pcidev_id, .id_table = ioh_gpio_pcidev_id,
.probe = ioh_gpio_probe, .probe = ioh_gpio_probe,
.remove = ioh_gpio_remove, .remove = ioh_gpio_remove,
.suspend = ioh_gpio_suspend, .driver = {
.resume = ioh_gpio_resume .pm = &ioh_gpio_pm_ops,
},
}; };
module_pci_driver(ioh_gpio_driver); module_pci_driver(ioh_gpio_driver);
......
// SPDX-License-Identifier: GPL-2.0 // SPDX-License-Identifier: GPL-2.0
#include <linux/acpi.h>
#include <linux/bitfield.h> #include <linux/bitfield.h>
#include <linux/bitops.h> #include <linux/bitops.h>
#include <linux/device.h> #include <linux/device.h>
...@@ -8,6 +7,7 @@ ...@@ -8,6 +7,7 @@
#include <linux/io.h> #include <linux/io.h>
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/pm.h> #include <linux/pm.h>
...@@ -47,12 +47,10 @@ ...@@ -47,12 +47,10 @@
#define YU_GPIO_MODE0_SET 0x54 #define YU_GPIO_MODE0_SET 0x54
#define YU_GPIO_MODE0_CLEAR 0x58 #define YU_GPIO_MODE0_CLEAR 0x58
#ifdef CONFIG_PM
struct mlxbf2_gpio_context_save_regs { struct mlxbf2_gpio_context_save_regs {
u32 gpio_mode0; u32 gpio_mode0;
u32 gpio_mode1; u32 gpio_mode1;
}; };
#endif
/* BlueField-2 gpio block context structure. */ /* BlueField-2 gpio block context structure. */
struct mlxbf2_gpio_context { struct mlxbf2_gpio_context {
...@@ -61,9 +59,7 @@ struct mlxbf2_gpio_context { ...@@ -61,9 +59,7 @@ struct mlxbf2_gpio_context {
/* YU GPIO blocks address */ /* YU GPIO blocks address */
void __iomem *gpio_io; void __iomem *gpio_io;
#ifdef CONFIG_PM
struct mlxbf2_gpio_context_save_regs *csave_regs; struct mlxbf2_gpio_context_save_regs *csave_regs;
#endif
}; };
/* BlueField-2 gpio shared structure. */ /* BlueField-2 gpio shared structure. */
...@@ -73,11 +69,8 @@ struct mlxbf2_gpio_param { ...@@ -73,11 +69,8 @@ struct mlxbf2_gpio_param {
struct mutex *lock; struct mutex *lock;
}; };
static struct resource yu_arm_gpio_lock_res = { static struct resource yu_arm_gpio_lock_res =
.start = YU_ARM_GPIO_LOCK_ADDR, DEFINE_RES_MEM_NAMED(YU_ARM_GPIO_LOCK_ADDR, YU_ARM_GPIO_LOCK_SIZE, "YU_ARM_GPIO_LOCK");
.end = YU_ARM_GPIO_LOCK_ADDR + YU_ARM_GPIO_LOCK_SIZE - 1,
.name = "YU_ARM_GPIO_LOCK",
};
static DEFINE_MUTEX(yu_arm_gpio_lock_mutex); static DEFINE_MUTEX(yu_arm_gpio_lock_mutex);
...@@ -232,7 +225,6 @@ mlxbf2_gpio_probe(struct platform_device *pdev) ...@@ -232,7 +225,6 @@ mlxbf2_gpio_probe(struct platform_device *pdev)
struct mlxbf2_gpio_context *gs; struct mlxbf2_gpio_context *gs;
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct gpio_chip *gc; struct gpio_chip *gc;
struct resource *res;
unsigned int npins; unsigned int npins;
int ret; int ret;
...@@ -241,13 +233,9 @@ mlxbf2_gpio_probe(struct platform_device *pdev) ...@@ -241,13 +233,9 @@ mlxbf2_gpio_probe(struct platform_device *pdev)
return -ENOMEM; return -ENOMEM;
/* YU GPIO block address */ /* YU GPIO block address */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); gs->gpio_io = devm_platform_ioremap_resource(pdev, 0);
if (!res) if (IS_ERR(gs->gpio_io))
return -ENODEV; return PTR_ERR(gs->gpio_io);
gs->gpio_io = devm_ioremap(dev, res->start, resource_size(res));
if (!gs->gpio_io)
return -ENOMEM;
ret = mlxbf2_gpio_get_lock_res(pdev); ret = mlxbf2_gpio_get_lock_res(pdev);
if (ret) { if (ret) {
...@@ -284,11 +272,9 @@ mlxbf2_gpio_probe(struct platform_device *pdev) ...@@ -284,11 +272,9 @@ mlxbf2_gpio_probe(struct platform_device *pdev)
return 0; return 0;
} }
#ifdef CONFIG_PM static int __maybe_unused mlxbf2_gpio_suspend(struct device *dev)
static int mlxbf2_gpio_suspend(struct platform_device *pdev,
pm_message_t state)
{ {
struct mlxbf2_gpio_context *gs = platform_get_drvdata(pdev); struct mlxbf2_gpio_context *gs = dev_get_drvdata(dev);
gs->csave_regs->gpio_mode0 = readl(gs->gpio_io + gs->csave_regs->gpio_mode0 = readl(gs->gpio_io +
YU_GPIO_MODE0); YU_GPIO_MODE0);
...@@ -298,9 +284,9 @@ static int mlxbf2_gpio_suspend(struct platform_device *pdev, ...@@ -298,9 +284,9 @@ static int mlxbf2_gpio_suspend(struct platform_device *pdev,
return 0; return 0;
} }
static int mlxbf2_gpio_resume(struct platform_device *pdev) static int __maybe_unused mlxbf2_gpio_resume(struct device *dev)
{ {
struct mlxbf2_gpio_context *gs = platform_get_drvdata(pdev); struct mlxbf2_gpio_context *gs = dev_get_drvdata(dev);
writel(gs->csave_regs->gpio_mode0, gs->gpio_io + writel(gs->csave_regs->gpio_mode0, gs->gpio_io +
YU_GPIO_MODE0); YU_GPIO_MODE0);
...@@ -309,7 +295,7 @@ static int mlxbf2_gpio_resume(struct platform_device *pdev) ...@@ -309,7 +295,7 @@ static int mlxbf2_gpio_resume(struct platform_device *pdev)
return 0; return 0;
} }
#endif static SIMPLE_DEV_PM_OPS(mlxbf2_pm_ops, mlxbf2_gpio_suspend, mlxbf2_gpio_resume);
static const struct acpi_device_id __maybe_unused mlxbf2_gpio_acpi_match[] = { static const struct acpi_device_id __maybe_unused mlxbf2_gpio_acpi_match[] = {
{ "MLNXBF22", 0 }, { "MLNXBF22", 0 },
...@@ -320,13 +306,10 @@ MODULE_DEVICE_TABLE(acpi, mlxbf2_gpio_acpi_match); ...@@ -320,13 +306,10 @@ MODULE_DEVICE_TABLE(acpi, mlxbf2_gpio_acpi_match);
static struct platform_driver mlxbf2_gpio_driver = { static struct platform_driver mlxbf2_gpio_driver = {
.driver = { .driver = {
.name = "mlxbf2_gpio", .name = "mlxbf2_gpio",
.acpi_match_table = ACPI_PTR(mlxbf2_gpio_acpi_match), .acpi_match_table = mlxbf2_gpio_acpi_match,
.pm = &mlxbf2_pm_ops,
}, },
.probe = mlxbf2_gpio_probe, .probe = mlxbf2_gpio_probe,
#ifdef CONFIG_PM
.suspend = mlxbf2_gpio_suspend,
.resume = mlxbf2_gpio_resume,
#endif
}; };
module_platform_driver(mlxbf2_gpio_driver); module_platform_driver(mlxbf2_gpio_driver);
......
...@@ -332,7 +332,7 @@ static int mpc8xxx_probe(struct platform_device *pdev) ...@@ -332,7 +332,7 @@ static int mpc8xxx_probe(struct platform_device *pdev)
mpc8xxx_gc->regs + GPIO_DIR, NULL, mpc8xxx_gc->regs + GPIO_DIR, NULL,
BGPIOF_BIG_ENDIAN); BGPIOF_BIG_ENDIAN);
if (ret) if (ret)
goto err; return ret;
dev_dbg(&pdev->dev, "GPIO registers are LITTLE endian\n"); dev_dbg(&pdev->dev, "GPIO registers are LITTLE endian\n");
} else { } else {
ret = bgpio_init(gc, &pdev->dev, 4, ret = bgpio_init(gc, &pdev->dev, 4,
...@@ -342,7 +342,7 @@ static int mpc8xxx_probe(struct platform_device *pdev) ...@@ -342,7 +342,7 @@ static int mpc8xxx_probe(struct platform_device *pdev)
BGPIOF_BIG_ENDIAN BGPIOF_BIG_ENDIAN
| BGPIOF_BIG_ENDIAN_BYTE_ORDER); | BGPIOF_BIG_ENDIAN_BYTE_ORDER);
if (ret) if (ret)
goto err; return ret;
dev_dbg(&pdev->dev, "GPIO registers are BIG endian\n"); dev_dbg(&pdev->dev, "GPIO registers are BIG endian\n");
} }
...@@ -380,11 +380,11 @@ static int mpc8xxx_probe(struct platform_device *pdev) ...@@ -380,11 +380,11 @@ static int mpc8xxx_probe(struct platform_device *pdev)
is_acpi_node(fwnode)) is_acpi_node(fwnode))
gc->write_reg(mpc8xxx_gc->regs + GPIO_IBE, 0xffffffff); gc->write_reg(mpc8xxx_gc->regs + GPIO_IBE, 0xffffffff);
ret = gpiochip_add_data(gc, mpc8xxx_gc); ret = devm_gpiochip_add_data(&pdev->dev, gc, mpc8xxx_gc);
if (ret) { if (ret) {
dev_err(&pdev->dev, dev_err(&pdev->dev,
"GPIO chip registration failed with status %d\n", ret); "GPIO chip registration failed with status %d\n", ret);
goto err; return ret;
} }
mpc8xxx_gc->irqn = platform_get_irq(pdev, 0); mpc8xxx_gc->irqn = platform_get_irq(pdev, 0);
...@@ -416,7 +416,7 @@ static int mpc8xxx_probe(struct platform_device *pdev) ...@@ -416,7 +416,7 @@ static int mpc8xxx_probe(struct platform_device *pdev)
return 0; return 0;
err: err:
iounmap(mpc8xxx_gc->regs); irq_domain_remove(mpc8xxx_gc->irq);
return ret; return ret;
} }
...@@ -429,9 +429,6 @@ static int mpc8xxx_remove(struct platform_device *pdev) ...@@ -429,9 +429,6 @@ static int mpc8xxx_remove(struct platform_device *pdev)
irq_domain_remove(mpc8xxx_gc->irq); irq_domain_remove(mpc8xxx_gc->irq);
} }
gpiochip_remove(&mpc8xxx_gc->gc);
iounmap(mpc8xxx_gc->regs);
return 0; return 0;
} }
......
...@@ -239,6 +239,7 @@ mediatek_gpio_bank_probe(struct device *dev, ...@@ -239,6 +239,7 @@ mediatek_gpio_bank_probe(struct device *dev,
if (!rg->chip.label) if (!rg->chip.label)
return -ENOMEM; return -ENOMEM;
rg->chip.offset = bank * MTK_BANK_WIDTH;
rg->irq_chip.name = dev_name(dev); rg->irq_chip.name = dev_name(dev);
rg->irq_chip.parent_device = dev; rg->irq_chip.parent_device = dev;
rg->irq_chip.irq_unmask = mediatek_gpio_irq_unmask; rg->irq_chip.irq_unmask = mediatek_gpio_irq_unmask;
......
...@@ -564,9 +564,9 @@ static int gpio_rcar_probe(struct platform_device *pdev) ...@@ -564,9 +564,9 @@ static int gpio_rcar_probe(struct platform_device *pdev)
} }
if (p->info.has_inen) { if (p->info.has_inen) {
pm_runtime_get_sync(p->dev); pm_runtime_get_sync(dev);
gpio_rcar_enable_inputs(p); gpio_rcar_enable_inputs(p);
pm_runtime_put(p->dev); pm_runtime_put(dev);
} }
dev_info(dev, "driving %d GPIOs\n", npins); dev_info(dev, "driving %d GPIOs\n", npins);
......
...@@ -607,15 +607,21 @@ static int tegra186_gpio_probe(struct platform_device *pdev) ...@@ -607,15 +607,21 @@ static int tegra186_gpio_probe(struct platform_device *pdev)
if (!gpio) if (!gpio)
return -ENOMEM; return -ENOMEM;
gpio->soc = of_device_get_match_data(&pdev->dev); gpio->soc = device_get_match_data(&pdev->dev);
gpio->secure = devm_platform_ioremap_resource_byname(pdev, "security"); gpio->secure = devm_platform_ioremap_resource_byname(pdev, "security");
if (IS_ERR(gpio->secure)) if (IS_ERR(gpio->secure)) {
return PTR_ERR(gpio->secure); gpio->secure = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(gpio->secure))
return PTR_ERR(gpio->secure);
}
gpio->base = devm_platform_ioremap_resource_byname(pdev, "gpio"); gpio->base = devm_platform_ioremap_resource_byname(pdev, "gpio");
if (IS_ERR(gpio->base)) if (IS_ERR(gpio->base)) {
return PTR_ERR(gpio->base); gpio->base = devm_platform_ioremap_resource(pdev, 1);
if (IS_ERR(gpio->base))
return PTR_ERR(gpio->base);
}
err = platform_irq_count(pdev); err = platform_irq_count(pdev);
if (err < 0) if (err < 0)
...@@ -677,11 +683,13 @@ static int tegra186_gpio_probe(struct platform_device *pdev) ...@@ -677,11 +683,13 @@ static int tegra186_gpio_probe(struct platform_device *pdev)
gpio->gpio.names = (const char * const *)names; gpio->gpio.names = (const char * const *)names;
#if defined(CONFIG_OF_GPIO)
gpio->gpio.of_node = pdev->dev.of_node; gpio->gpio.of_node = pdev->dev.of_node;
gpio->gpio.of_gpio_n_cells = 2; gpio->gpio.of_gpio_n_cells = 2;
gpio->gpio.of_xlate = tegra186_gpio_of_xlate; gpio->gpio.of_xlate = tegra186_gpio_of_xlate;
#endif /* CONFIG_OF_GPIO */
gpio->intc.name = pdev->dev.of_node->name; gpio->intc.name = dev_name(&pdev->dev);
gpio->intc.irq_ack = tegra186_irq_ack; gpio->intc.irq_ack = tegra186_irq_ack;
gpio->intc.irq_mask = tegra186_irq_mask; gpio->intc.irq_mask = tegra186_irq_mask;
gpio->intc.irq_unmask = tegra186_irq_unmask; gpio->intc.irq_unmask = tegra186_irq_unmask;
...@@ -893,10 +901,20 @@ static const struct of_device_id tegra186_gpio_of_match[] = { ...@@ -893,10 +901,20 @@ static const struct of_device_id tegra186_gpio_of_match[] = {
}; };
MODULE_DEVICE_TABLE(of, tegra186_gpio_of_match); MODULE_DEVICE_TABLE(of, tegra186_gpio_of_match);
static const struct acpi_device_id tegra186_gpio_acpi_match[] = {
{ .id = "NVDA0108", .driver_data = (kernel_ulong_t)&tegra186_main_soc },
{ .id = "NVDA0208", .driver_data = (kernel_ulong_t)&tegra186_aon_soc },
{ .id = "NVDA0308", .driver_data = (kernel_ulong_t)&tegra194_main_soc },
{ .id = "NVDA0408", .driver_data = (kernel_ulong_t)&tegra194_aon_soc },
{}
};
MODULE_DEVICE_TABLE(acpi, tegra186_gpio_acpi_match);
static struct platform_driver tegra186_gpio_driver = { static struct platform_driver tegra186_gpio_driver = {
.driver = { .driver = {
.name = "tegra186-gpio", .name = "tegra186-gpio",
.of_match_table = tegra186_gpio_of_match, .of_match_table = tegra186_gpio_of_match,
.acpi_match_table = tegra186_gpio_acpi_match,
}, },
.probe = tegra186_gpio_probe, .probe = tegra186_gpio_probe,
}; };
......
...@@ -404,11 +404,10 @@ static int vprbrd_gpio_probe(struct platform_device *pdev) ...@@ -404,11 +404,10 @@ static int vprbrd_gpio_probe(struct platform_device *pdev)
vb_gpio->gpioa.get = vprbrd_gpioa_get; vb_gpio->gpioa.get = vprbrd_gpioa_get;
vb_gpio->gpioa.direction_input = vprbrd_gpioa_direction_input; vb_gpio->gpioa.direction_input = vprbrd_gpioa_direction_input;
vb_gpio->gpioa.direction_output = vprbrd_gpioa_direction_output; vb_gpio->gpioa.direction_output = vprbrd_gpioa_direction_output;
ret = devm_gpiochip_add_data(&pdev->dev, &vb_gpio->gpioa, vb_gpio); ret = devm_gpiochip_add_data(&pdev->dev, &vb_gpio->gpioa, vb_gpio);
if (ret < 0) { if (ret < 0)
dev_err(vb_gpio->gpioa.parent, "could not add gpio a");
return ret; return ret;
}
/* registering gpio b */ /* registering gpio b */
vb_gpio->gpiob.label = "viperboard gpio b"; vb_gpio->gpiob.label = "viperboard gpio b";
...@@ -421,15 +420,8 @@ static int vprbrd_gpio_probe(struct platform_device *pdev) ...@@ -421,15 +420,8 @@ static int vprbrd_gpio_probe(struct platform_device *pdev)
vb_gpio->gpiob.get = vprbrd_gpiob_get; vb_gpio->gpiob.get = vprbrd_gpiob_get;
vb_gpio->gpiob.direction_input = vprbrd_gpiob_direction_input; vb_gpio->gpiob.direction_input = vprbrd_gpiob_direction_input;
vb_gpio->gpiob.direction_output = vprbrd_gpiob_direction_output; vb_gpio->gpiob.direction_output = vprbrd_gpiob_direction_output;
ret = devm_gpiochip_add_data(&pdev->dev, &vb_gpio->gpiob, vb_gpio);
if (ret < 0) {
dev_err(vb_gpio->gpiob.parent, "could not add gpio b");
return ret;
}
platform_set_drvdata(pdev, vb_gpio);
return ret; return devm_gpiochip_add_data(&pdev->dev, &vb_gpio->gpiob, vb_gpio);
} }
static struct platform_driver vprbrd_gpio_driver = { static struct platform_driver vprbrd_gpio_driver = {
......
// SPDX-License-Identifier: GPL-2.0+
/*
* GPIO driver for virtio-based virtual GPIO controllers
*
* Copyright (C) 2021 metux IT consult
* Enrico Weigelt, metux IT consult <info@metux.net>
*
* Copyright (C) 2021 Linaro.
* Viresh Kumar <viresh.kumar@linaro.org>
*/
#include <linux/completion.h>
#include <linux/err.h>
#include <linux/gpio/driver.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/virtio_config.h>
#include <uapi/linux/virtio_gpio.h>
#include <uapi/linux/virtio_ids.h>
struct virtio_gpio_line {
struct mutex lock; /* Protects line operation */
struct completion completion;
struct virtio_gpio_request req ____cacheline_aligned;
struct virtio_gpio_response res ____cacheline_aligned;
unsigned int rxlen;
};
struct virtio_gpio {
struct virtio_device *vdev;
struct mutex lock; /* Protects virtqueue operation */
struct gpio_chip gc;
struct virtio_gpio_line *lines;
struct virtqueue *request_vq;
};
static int _virtio_gpio_req(struct virtio_gpio *vgpio, u16 type, u16 gpio,
u8 txvalue, u8 *rxvalue, void *response, u32 rxlen)
{
struct virtio_gpio_line *line = &vgpio->lines[gpio];
struct virtio_gpio_request *req = &line->req;
struct virtio_gpio_response *res = response;
struct scatterlist *sgs[2], req_sg, res_sg;
struct device *dev = &vgpio->vdev->dev;
int ret;
/*
* Prevent concurrent requests for the same line since we have
* pre-allocated request/response buffers for each GPIO line. Moreover
* Linux always accesses a GPIO line sequentially, so this locking shall
* always go through without any delays.
*/
mutex_lock(&line->lock);
req->type = cpu_to_le16(type);
req->gpio = cpu_to_le16(gpio);
req->value = cpu_to_le32(txvalue);
sg_init_one(&req_sg, req, sizeof(*req));
sg_init_one(&res_sg, res, rxlen);
sgs[0] = &req_sg;
sgs[1] = &res_sg;
line->rxlen = 0;
reinit_completion(&line->completion);
/*
* Virtqueue callers need to ensure they don't call its APIs with other
* virtqueue operations at the same time.
*/
mutex_lock(&vgpio->lock);
ret = virtqueue_add_sgs(vgpio->request_vq, sgs, 1, 1, line, GFP_KERNEL);
if (ret) {
dev_err(dev, "failed to add request to vq\n");
mutex_unlock(&vgpio->lock);
goto out;
}
virtqueue_kick(vgpio->request_vq);
mutex_unlock(&vgpio->lock);
if (!wait_for_completion_timeout(&line->completion, HZ)) {
dev_err(dev, "GPIO operation timed out\n");
ret = -ETIMEDOUT;
goto out;
}
if (unlikely(res->status != VIRTIO_GPIO_STATUS_OK)) {
dev_err(dev, "GPIO request failed: %d\n", gpio);
ret = -EINVAL;
goto out;
}
if (unlikely(line->rxlen != rxlen)) {
dev_err(dev, "GPIO operation returned incorrect len (%u : %u)\n",
rxlen, line->rxlen);
ret = -EINVAL;
goto out;
}
if (rxvalue)
*rxvalue = res->value;
out:
mutex_unlock(&line->lock);
return ret;
}
static int virtio_gpio_req(struct virtio_gpio *vgpio, u16 type, u16 gpio,
u8 txvalue, u8 *rxvalue)
{
struct virtio_gpio_line *line = &vgpio->lines[gpio];
struct virtio_gpio_response *res = &line->res;
return _virtio_gpio_req(vgpio, type, gpio, txvalue, rxvalue, res,
sizeof(*res));
}
static void virtio_gpio_free(struct gpio_chip *gc, unsigned int gpio)
{
struct virtio_gpio *vgpio = gpiochip_get_data(gc);
virtio_gpio_req(vgpio, VIRTIO_GPIO_MSG_SET_DIRECTION, gpio,
VIRTIO_GPIO_DIRECTION_NONE, NULL);
}
static int virtio_gpio_get_direction(struct gpio_chip *gc, unsigned int gpio)
{
struct virtio_gpio *vgpio = gpiochip_get_data(gc);
u8 direction;
int ret;
ret = virtio_gpio_req(vgpio, VIRTIO_GPIO_MSG_GET_DIRECTION, gpio, 0,
&direction);
if (ret)
return ret;
switch (direction) {
case VIRTIO_GPIO_DIRECTION_IN:
return GPIO_LINE_DIRECTION_IN;
case VIRTIO_GPIO_DIRECTION_OUT:
return GPIO_LINE_DIRECTION_OUT;
default:
return -EINVAL;
}
}
static int virtio_gpio_direction_input(struct gpio_chip *gc, unsigned int gpio)
{
struct virtio_gpio *vgpio = gpiochip_get_data(gc);
return virtio_gpio_req(vgpio, VIRTIO_GPIO_MSG_SET_DIRECTION, gpio,
VIRTIO_GPIO_DIRECTION_IN, NULL);
}
static int virtio_gpio_direction_output(struct gpio_chip *gc, unsigned int gpio,
int value)
{
struct virtio_gpio *vgpio = gpiochip_get_data(gc);
int ret;
ret = virtio_gpio_req(vgpio, VIRTIO_GPIO_MSG_SET_VALUE, gpio, value, NULL);
if (ret)
return ret;
return virtio_gpio_req(vgpio, VIRTIO_GPIO_MSG_SET_DIRECTION, gpio,
VIRTIO_GPIO_DIRECTION_OUT, NULL);
}
static int virtio_gpio_get(struct gpio_chip *gc, unsigned int gpio)
{
struct virtio_gpio *vgpio = gpiochip_get_data(gc);
u8 value;
int ret;
ret = virtio_gpio_req(vgpio, VIRTIO_GPIO_MSG_GET_VALUE, gpio, 0, &value);
return ret ? ret : value;
}
static void virtio_gpio_set(struct gpio_chip *gc, unsigned int gpio, int value)
{
struct virtio_gpio *vgpio = gpiochip_get_data(gc);
virtio_gpio_req(vgpio, VIRTIO_GPIO_MSG_SET_VALUE, gpio, value, NULL);
}
static void virtio_gpio_request_vq(struct virtqueue *vq)
{
struct virtio_gpio_line *line;
unsigned int len;
do {
line = virtqueue_get_buf(vq, &len);
if (!line)
return;
line->rxlen = len;
complete(&line->completion);
} while (1);
}
static void virtio_gpio_free_vqs(struct virtio_device *vdev)
{
vdev->config->reset(vdev);
vdev->config->del_vqs(vdev);
}
static int virtio_gpio_alloc_vqs(struct virtio_gpio *vgpio,
struct virtio_device *vdev)
{
const char * const names[] = { "requestq" };
vq_callback_t *cbs[] = {
virtio_gpio_request_vq,
};
struct virtqueue *vqs[1] = { NULL };
int ret;
ret = virtio_find_vqs(vdev, 1, vqs, cbs, names, NULL);
if (ret) {
dev_err(&vdev->dev, "failed to find vqs: %d\n", ret);
return ret;
}
if (!vqs[0]) {
dev_err(&vdev->dev, "failed to find requestq vq\n");
return -ENODEV;
}
vgpio->request_vq = vqs[0];
return 0;
}
static const char **virtio_gpio_get_names(struct virtio_gpio *vgpio,
u32 gpio_names_size, u16 ngpio)
{
struct virtio_gpio_response_get_names *res;
struct device *dev = &vgpio->vdev->dev;
u8 *gpio_names, *str;
const char **names;
int i, ret, len;
if (!gpio_names_size)
return NULL;
len = sizeof(*res) + gpio_names_size;
res = devm_kzalloc(dev, len, GFP_KERNEL);
if (!res)
return NULL;
gpio_names = res->value;
ret = _virtio_gpio_req(vgpio, VIRTIO_GPIO_MSG_GET_NAMES, 0, 0, NULL,
res, len);
if (ret) {
dev_err(dev, "Failed to get GPIO names: %d\n", ret);
return NULL;
}
names = devm_kcalloc(dev, ngpio, sizeof(*names), GFP_KERNEL);
if (!names)
return NULL;
/* NULL terminate the string instead of checking it */
gpio_names[gpio_names_size - 1] = '\0';
for (i = 0, str = gpio_names; i < ngpio; i++) {
names[i] = str;
str += strlen(str) + 1; /* zero-length strings are allowed */
if (str > gpio_names + gpio_names_size) {
dev_err(dev, "gpio_names block is too short (%d)\n", i);
return NULL;
}
}
return names;
}
static int virtio_gpio_probe(struct virtio_device *vdev)
{
struct virtio_gpio_config config;
struct device *dev = &vdev->dev;
struct virtio_gpio *vgpio;
u32 gpio_names_size;
u16 ngpio;
int ret, i;
vgpio = devm_kzalloc(dev, sizeof(*vgpio), GFP_KERNEL);
if (!vgpio)
return -ENOMEM;
/* Read configuration */
virtio_cread_bytes(vdev, 0, &config, sizeof(config));
gpio_names_size = le32_to_cpu(config.gpio_names_size);
ngpio = le16_to_cpu(config.ngpio);
if (!ngpio) {
dev_err(dev, "Number of GPIOs can't be zero\n");
return -EINVAL;
}
vgpio->lines = devm_kcalloc(dev, ngpio, sizeof(*vgpio->lines), GFP_KERNEL);
if (!vgpio->lines)
return -ENOMEM;
for (i = 0; i < ngpio; i++) {
mutex_init(&vgpio->lines[i].lock);
init_completion(&vgpio->lines[i].completion);
}
mutex_init(&vgpio->lock);
vdev->priv = vgpio;
vgpio->vdev = vdev;
vgpio->gc.free = virtio_gpio_free;
vgpio->gc.get_direction = virtio_gpio_get_direction;
vgpio->gc.direction_input = virtio_gpio_direction_input;
vgpio->gc.direction_output = virtio_gpio_direction_output;
vgpio->gc.get = virtio_gpio_get;
vgpio->gc.set = virtio_gpio_set;
vgpio->gc.ngpio = ngpio;
vgpio->gc.base = -1; /* Allocate base dynamically */
vgpio->gc.label = dev_name(dev);
vgpio->gc.parent = dev;
vgpio->gc.owner = THIS_MODULE;
vgpio->gc.can_sleep = true;
ret = virtio_gpio_alloc_vqs(vgpio, vdev);
if (ret)
return ret;
/* Mark the device ready to perform operations from within probe() */
virtio_device_ready(vdev);
vgpio->gc.names = virtio_gpio_get_names(vgpio, gpio_names_size, ngpio);
ret = gpiochip_add_data(&vgpio->gc, vgpio);
if (ret) {
virtio_gpio_free_vqs(vdev);
dev_err(dev, "Failed to add virtio-gpio controller\n");
}
return ret;
}
static void virtio_gpio_remove(struct virtio_device *vdev)
{
struct virtio_gpio *vgpio = vdev->priv;
gpiochip_remove(&vgpio->gc);
virtio_gpio_free_vqs(vdev);
}
static const struct virtio_device_id id_table[] = {
{ VIRTIO_ID_GPIO, VIRTIO_DEV_ANY_ID },
{},
};
MODULE_DEVICE_TABLE(virtio, id_table);
static struct virtio_driver virtio_gpio_driver = {
.id_table = id_table,
.probe = virtio_gpio_probe,
.remove = virtio_gpio_remove,
.driver = {
.name = KBUILD_MODNAME,
.owner = THIS_MODULE,
},
};
module_virtio_driver(virtio_gpio_driver);
MODULE_AUTHOR("Enrico Weigelt, metux IT consult <info@metux.net>");
MODULE_AUTHOR("Viresh Kumar <viresh.kumar@linaro.org>");
MODULE_DESCRIPTION("VirtIO GPIO driver");
MODULE_LICENSE("GPL");
...@@ -145,7 +145,7 @@ EXPORT_SYMBOL_GPL(devm_gpiod_get_index); ...@@ -145,7 +145,7 @@ EXPORT_SYMBOL_GPL(devm_gpiod_get_index);
* In case of error an ERR_PTR() is returned. * In case of error an ERR_PTR() is returned.
*/ */
struct gpio_desc *devm_gpiod_get_from_of_node(struct device *dev, struct gpio_desc *devm_gpiod_get_from_of_node(struct device *dev,
struct device_node *node, const struct device_node *node,
const char *propname, int index, const char *propname, int index,
enum gpiod_flags dflags, enum gpiod_flags dflags,
const char *label) const char *label)
......
...@@ -122,7 +122,7 @@ static struct gpio_desc *of_xlate_and_get_gpiod_flags(struct gpio_chip *chip, ...@@ -122,7 +122,7 @@ static struct gpio_desc *of_xlate_and_get_gpiod_flags(struct gpio_chip *chip,
bool of_gpio_need_valid_mask(const struct gpio_chip *gc) bool of_gpio_need_valid_mask(const struct gpio_chip *gc)
{ {
int size; int size;
struct device_node *np = gc->of_node; const struct device_node *np = gc->of_node;
size = of_property_count_u32_elems(np, "gpio-reserved-ranges"); size = of_property_count_u32_elems(np, "gpio-reserved-ranges");
if (size > 0 && size % 2 == 0) if (size > 0 && size % 2 == 0)
...@@ -130,7 +130,7 @@ bool of_gpio_need_valid_mask(const struct gpio_chip *gc) ...@@ -130,7 +130,7 @@ bool of_gpio_need_valid_mask(const struct gpio_chip *gc)
return false; return false;
} }
static void of_gpio_flags_quirks(struct device_node *np, static void of_gpio_flags_quirks(const struct device_node *np,
const char *propname, const char *propname,
enum of_gpio_flags *flags, enum of_gpio_flags *flags,
int index) int index)
...@@ -236,7 +236,7 @@ static void of_gpio_flags_quirks(struct device_node *np, ...@@ -236,7 +236,7 @@ static void of_gpio_flags_quirks(struct device_node *np,
* value on the error condition. If @flags is not NULL the function also fills * value on the error condition. If @flags is not NULL the function also fills
* in flags for the GPIO. * in flags for the GPIO.
*/ */
static struct gpio_desc *of_get_named_gpiod_flags(struct device_node *np, static struct gpio_desc *of_get_named_gpiod_flags(const struct device_node *np,
const char *propname, int index, enum of_gpio_flags *flags) const char *propname, int index, enum of_gpio_flags *flags)
{ {
struct of_phandle_args gpiospec; struct of_phandle_args gpiospec;
...@@ -275,7 +275,7 @@ static struct gpio_desc *of_get_named_gpiod_flags(struct device_node *np, ...@@ -275,7 +275,7 @@ static struct gpio_desc *of_get_named_gpiod_flags(struct device_node *np,
return desc; return desc;
} }
int of_get_named_gpio_flags(struct device_node *np, const char *list_name, int of_get_named_gpio_flags(const struct device_node *np, const char *list_name,
int index, enum of_gpio_flags *flags) int index, enum of_gpio_flags *flags)
{ {
struct gpio_desc *desc; struct gpio_desc *desc;
...@@ -303,7 +303,7 @@ EXPORT_SYMBOL_GPL(of_get_named_gpio_flags); ...@@ -303,7 +303,7 @@ EXPORT_SYMBOL_GPL(of_get_named_gpio_flags);
* *
* In case of error an ERR_PTR() is returned. * In case of error an ERR_PTR() is returned.
*/ */
struct gpio_desc *gpiod_get_from_of_node(struct device_node *node, struct gpio_desc *gpiod_get_from_of_node(const struct device_node *node,
const char *propname, int index, const char *propname, int index,
enum gpiod_flags dflags, enum gpiod_flags dflags,
const char *label) const char *label)
...@@ -373,7 +373,7 @@ static struct gpio_desc *of_find_spi_gpio(struct device *dev, const char *con_id ...@@ -373,7 +373,7 @@ static struct gpio_desc *of_find_spi_gpio(struct device *dev, const char *con_id
enum of_gpio_flags *of_flags) enum of_gpio_flags *of_flags)
{ {
char prop_name[32]; /* 32 is max size of property name */ char prop_name[32]; /* 32 is max size of property name */
struct device_node *np = dev->of_node; const struct device_node *np = dev->of_node;
struct gpio_desc *desc; struct gpio_desc *desc;
/* /*
...@@ -404,7 +404,7 @@ static struct gpio_desc *of_find_spi_cs_gpio(struct device *dev, ...@@ -404,7 +404,7 @@ static struct gpio_desc *of_find_spi_cs_gpio(struct device *dev,
unsigned int idx, unsigned int idx,
unsigned long *flags) unsigned long *flags)
{ {
struct device_node *np = dev->of_node; const struct device_node *np = dev->of_node;
if (!IS_ENABLED(CONFIG_SPI_MASTER)) if (!IS_ENABLED(CONFIG_SPI_MASTER))
return ERR_PTR(-ENOENT); return ERR_PTR(-ENOENT);
...@@ -440,7 +440,7 @@ static struct gpio_desc *of_find_regulator_gpio(struct device *dev, const char * ...@@ -440,7 +440,7 @@ static struct gpio_desc *of_find_regulator_gpio(struct device *dev, const char *
"wlf,ldo1ena", /* WM8994 */ "wlf,ldo1ena", /* WM8994 */
"wlf,ldo2ena", /* WM8994 */ "wlf,ldo2ena", /* WM8994 */
}; };
struct device_node *np = dev->of_node; const struct device_node *np = dev->of_node;
struct gpio_desc *desc; struct gpio_desc *desc;
int i; int i;
......
...@@ -382,10 +382,18 @@ static int devprop_gpiochip_set_names(struct gpio_chip *chip) ...@@ -382,10 +382,18 @@ static int devprop_gpiochip_set_names(struct gpio_chip *chip)
if (count < 0) if (count < 0)
return 0; return 0;
if (count > gdev->ngpio) { /*
dev_warn(&gdev->dev, "gpio-line-names is length %d but should be at most length %d", * When offset is set in the driver side we assume the driver internally
count, gdev->ngpio); * is using more than one gpiochip per the same device. We have to stop
count = gdev->ngpio; * setting friendly names if the specified ones with 'gpio-line-names'
* are less than the offset in the device itself. This means all the
* lines are not present for every single pin within all the internal
* gpiochips.
*/
if (count <= chip->offset) {
dev_warn(&gdev->dev, "gpio-line-names too short (length %d), cannot map names for the gpiochip at offset %u\n",
count, chip->offset);
return 0;
} }
names = kcalloc(count, sizeof(*names), GFP_KERNEL); names = kcalloc(count, sizeof(*names), GFP_KERNEL);
...@@ -400,8 +408,22 @@ static int devprop_gpiochip_set_names(struct gpio_chip *chip) ...@@ -400,8 +408,22 @@ static int devprop_gpiochip_set_names(struct gpio_chip *chip)
return ret; return ret;
} }
/*
* When more that one gpiochip per device is used, 'count' can
* contain at most number gpiochips x chip->ngpio. We have to
* correctly distribute all defined lines taking into account
* chip->offset as starting point from where we will assign
* the names to pins from the 'names' array. Since property
* 'gpio-line-names' cannot contains gaps, we have to be sure
* we only assign those pins that really exists since chip->ngpio
* can be different of the chip->offset.
*/
count = (count > chip->offset) ? count - chip->offset : count;
if (count > chip->ngpio)
count = chip->ngpio;
for (i = 0; i < count; i++) for (i = 0; i < count; i++)
gdev->descs[i].name = names[i]; gdev->descs[i].name = names[chip->offset + i];
kfree(names); kfree(names);
......
...@@ -17,7 +17,6 @@ ...@@ -17,7 +17,6 @@
#include <linux/clk-provider.h> #include <linux/clk-provider.h>
#include <linux/dmi.h> #include <linux/dmi.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/platform_data/gpio-dwapb.h>
#include <linux/property.h> #include <linux/property.h>
/* PCI BAR for register base address */ /* PCI BAR for register base address */
...@@ -28,15 +27,6 @@ ...@@ -28,15 +27,6 @@
#define MFD_ACPI_MATCH_GPIO 0ULL #define MFD_ACPI_MATCH_GPIO 0ULL
#define MFD_ACPI_MATCH_I2C 1ULL #define MFD_ACPI_MATCH_I2C 1ULL
/* The base GPIO number under GPIOLIB framework */
#define INTEL_QUARK_MFD_GPIO_BASE 8
/* The default number of South-Cluster GPIO on Quark. */
#define INTEL_QUARK_MFD_NGPIO 8
/* The DesignWare GPIO ports on Quark. */
#define INTEL_QUARK_GPIO_NPORTS 1
#define INTEL_QUARK_IORES_MEM 0 #define INTEL_QUARK_IORES_MEM 0
#define INTEL_QUARK_IORES_IRQ 1 #define INTEL_QUARK_IORES_IRQ 1
...@@ -111,12 +101,38 @@ static struct resource intel_quark_gpio_res[] = { ...@@ -111,12 +101,38 @@ static struct resource intel_quark_gpio_res[] = {
[INTEL_QUARK_IORES_MEM] = { [INTEL_QUARK_IORES_MEM] = {
.flags = IORESOURCE_MEM, .flags = IORESOURCE_MEM,
}, },
[INTEL_QUARK_IORES_IRQ] = {
.flags = IORESOURCE_IRQ,
},
}; };
static struct mfd_cell_acpi_match intel_quark_acpi_match_gpio = { static struct mfd_cell_acpi_match intel_quark_acpi_match_gpio = {
.adr = MFD_ACPI_MATCH_GPIO, .adr = MFD_ACPI_MATCH_GPIO,
}; };
static const struct software_node intel_quark_gpio_controller_node = {
.name = "intel-quark-gpio-controller",
};
static const struct property_entry intel_quark_gpio_portA_properties[] = {
PROPERTY_ENTRY_U32("reg", 0),
PROPERTY_ENTRY_U32("snps,nr-gpios", 8),
PROPERTY_ENTRY_U32("gpio-base", 8),
{ }
};
static const struct software_node intel_quark_gpio_portA_node = {
.name = "portA",
.parent = &intel_quark_gpio_controller_node,
.properties = intel_quark_gpio_portA_properties,
};
static const struct software_node *intel_quark_gpio_node_group[] = {
&intel_quark_gpio_controller_node,
&intel_quark_gpio_portA_node,
NULL
};
static struct mfd_cell intel_quark_mfd_cells[] = { static struct mfd_cell intel_quark_mfd_cells[] = {
[MFD_I2C_BAR] = { [MFD_I2C_BAR] = {
.id = MFD_I2C_BAR, .id = MFD_I2C_BAR,
...@@ -203,35 +219,19 @@ static int intel_quark_gpio_setup(struct pci_dev *pdev) ...@@ -203,35 +219,19 @@ static int intel_quark_gpio_setup(struct pci_dev *pdev)
{ {
struct mfd_cell *cell = &intel_quark_mfd_cells[MFD_GPIO_BAR]; struct mfd_cell *cell = &intel_quark_mfd_cells[MFD_GPIO_BAR];
struct resource *res = intel_quark_gpio_res; struct resource *res = intel_quark_gpio_res;
struct dwapb_platform_data *pdata; int ret;
struct device *dev = &pdev->dev;
res[INTEL_QUARK_IORES_MEM].start = pci_resource_start(pdev, MFD_GPIO_BAR); res[INTEL_QUARK_IORES_MEM].start = pci_resource_start(pdev, MFD_GPIO_BAR);
res[INTEL_QUARK_IORES_MEM].end = pci_resource_end(pdev, MFD_GPIO_BAR); res[INTEL_QUARK_IORES_MEM].end = pci_resource_end(pdev, MFD_GPIO_BAR);
pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); res[INTEL_QUARK_IORES_IRQ].start = pci_irq_vector(pdev, 0);
if (!pdata) res[INTEL_QUARK_IORES_IRQ].end = pci_irq_vector(pdev, 0);
return -ENOMEM;
/* For intel quark x1000, it has only one port: portA */
pdata->nports = INTEL_QUARK_GPIO_NPORTS;
pdata->properties = devm_kcalloc(dev, pdata->nports,
sizeof(*pdata->properties),
GFP_KERNEL);
if (!pdata->properties)
return -ENOMEM;
/* Set the properties for portA */
pdata->properties->fwnode = NULL;
pdata->properties->idx = 0;
pdata->properties->ngpio = INTEL_QUARK_MFD_NGPIO;
pdata->properties->gpio_base = INTEL_QUARK_MFD_GPIO_BASE;
pdata->properties->irq[0] = pci_irq_vector(pdev, 0);
pdata->properties->irq_shared = true;
cell->platform_data = pdata; ret = software_node_register_node_group(intel_quark_gpio_node_group);
cell->pdata_size = sizeof(*pdata); if (ret)
return ret;
cell->swnode = &intel_quark_gpio_controller_node;
return 0; return 0;
} }
...@@ -274,10 +274,12 @@ static int intel_quark_mfd_probe(struct pci_dev *pdev, ...@@ -274,10 +274,12 @@ static int intel_quark_mfd_probe(struct pci_dev *pdev,
ARRAY_SIZE(intel_quark_mfd_cells), NULL, 0, ARRAY_SIZE(intel_quark_mfd_cells), NULL, 0,
NULL); NULL);
if (ret) if (ret)
goto err_free_irq_vectors; goto err_unregister_gpio_node_group;
return 0; return 0;
err_unregister_gpio_node_group:
software_node_unregister_node_group(intel_quark_gpio_node_group);
err_free_irq_vectors: err_free_irq_vectors:
pci_free_irq_vectors(pdev); pci_free_irq_vectors(pdev);
err_unregister_i2c_clk: err_unregister_i2c_clk:
...@@ -288,6 +290,7 @@ static int intel_quark_mfd_probe(struct pci_dev *pdev, ...@@ -288,6 +290,7 @@ static int intel_quark_mfd_probe(struct pci_dev *pdev,
static void intel_quark_mfd_remove(struct pci_dev *pdev) static void intel_quark_mfd_remove(struct pci_dev *pdev)
{ {
mfd_remove_devices(&pdev->dev); mfd_remove_devices(&pdev->dev);
software_node_unregister_node_group(intel_quark_gpio_node_group);
pci_free_irq_vectors(pdev); pci_free_irq_vectors(pdev);
intel_quark_unregister_i2c_clk(&pdev->dev); intel_quark_unregister_i2c_clk(&pdev->dev);
} }
......
...@@ -609,7 +609,7 @@ struct gpio_desc *devm_fwnode_get_gpiod_from_child(struct device *dev, ...@@ -609,7 +609,7 @@ struct gpio_desc *devm_fwnode_get_gpiod_from_child(struct device *dev,
#if IS_ENABLED(CONFIG_GPIOLIB) && IS_ENABLED(CONFIG_OF_GPIO) #if IS_ENABLED(CONFIG_GPIOLIB) && IS_ENABLED(CONFIG_OF_GPIO)
struct device_node; struct device_node;
struct gpio_desc *gpiod_get_from_of_node(struct device_node *node, struct gpio_desc *gpiod_get_from_of_node(const struct device_node *node,
const char *propname, int index, const char *propname, int index,
enum gpiod_flags dflags, enum gpiod_flags dflags,
const char *label); const char *label);
...@@ -619,7 +619,7 @@ struct gpio_desc *gpiod_get_from_of_node(struct device_node *node, ...@@ -619,7 +619,7 @@ struct gpio_desc *gpiod_get_from_of_node(struct device_node *node,
struct device_node; struct device_node;
static inline static inline
struct gpio_desc *gpiod_get_from_of_node(struct device_node *node, struct gpio_desc *gpiod_get_from_of_node(const struct device_node *node,
const char *propname, int index, const char *propname, int index,
enum gpiod_flags dflags, enum gpiod_flags dflags,
const char *label) const char *label)
...@@ -633,7 +633,7 @@ struct gpio_desc *gpiod_get_from_of_node(struct device_node *node, ...@@ -633,7 +633,7 @@ struct gpio_desc *gpiod_get_from_of_node(struct device_node *node,
struct device_node; struct device_node;
struct gpio_desc *devm_gpiod_get_from_of_node(struct device *dev, struct gpio_desc *devm_gpiod_get_from_of_node(struct device *dev,
struct device_node *node, const struct device_node *node,
const char *propname, int index, const char *propname, int index,
enum gpiod_flags dflags, enum gpiod_flags dflags,
const char *label); const char *label);
...@@ -644,7 +644,7 @@ struct device_node; ...@@ -644,7 +644,7 @@ struct device_node;
static inline static inline
struct gpio_desc *devm_gpiod_get_from_of_node(struct device *dev, struct gpio_desc *devm_gpiod_get_from_of_node(struct device *dev,
struct device_node *node, const struct device_node *node,
const char *propname, int index, const char *propname, int index,
enum gpiod_flags dflags, enum gpiod_flags dflags,
const char *label) const char *label)
...@@ -680,10 +680,10 @@ struct acpi_gpio_mapping { ...@@ -680,10 +680,10 @@ struct acpi_gpio_mapping {
unsigned int quirks; unsigned int quirks;
}; };
#if IS_ENABLED(CONFIG_GPIOLIB) && IS_ENABLED(CONFIG_ACPI)
struct acpi_device; struct acpi_device;
#if IS_ENABLED(CONFIG_GPIOLIB) && IS_ENABLED(CONFIG_ACPI)
int acpi_dev_add_driver_gpios(struct acpi_device *adev, int acpi_dev_add_driver_gpios(struct acpi_device *adev,
const struct acpi_gpio_mapping *gpios); const struct acpi_gpio_mapping *gpios);
void acpi_dev_remove_driver_gpios(struct acpi_device *adev); void acpi_dev_remove_driver_gpios(struct acpi_device *adev);
...@@ -696,8 +696,6 @@ struct gpio_desc *acpi_get_and_request_gpiod(char *path, int pin, char *label); ...@@ -696,8 +696,6 @@ struct gpio_desc *acpi_get_and_request_gpiod(char *path, int pin, char *label);
#else /* CONFIG_GPIOLIB && CONFIG_ACPI */ #else /* CONFIG_GPIOLIB && CONFIG_ACPI */
struct acpi_device;
static inline int acpi_dev_add_driver_gpios(struct acpi_device *adev, static inline int acpi_dev_add_driver_gpios(struct acpi_device *adev,
const struct acpi_gpio_mapping *gpios) const struct acpi_gpio_mapping *gpios)
{ {
......
...@@ -312,6 +312,9 @@ struct gpio_irq_chip { ...@@ -312,6 +312,9 @@ struct gpio_irq_chip {
* get rid of the static GPIO number space in the long run. * get rid of the static GPIO number space in the long run.
* @ngpio: the number of GPIOs handled by this controller; the last GPIO * @ngpio: the number of GPIOs handled by this controller; the last GPIO
* handled is (base + ngpio - 1). * handled is (base + ngpio - 1).
* @offset: when multiple gpio chips belong to the same device this
* can be used as offset within the device so friendly names can
* be properly assigned.
* @names: if set, must be an array of strings to use as alternative * @names: if set, must be an array of strings to use as alternative
* names for the GPIOs in this chip. Any entry in the array * names for the GPIOs in this chip. Any entry in the array
* may be NULL if there is no alias for the GPIO, however the * may be NULL if there is no alias for the GPIO, however the
...@@ -398,6 +401,7 @@ struct gpio_chip { ...@@ -398,6 +401,7 @@ struct gpio_chip {
int base; int base;
u16 ngpio; u16 ngpio;
u16 offset;
const char *const *names; const char *const *names;
bool can_sleep; bool can_sleep;
......
...@@ -896,7 +896,7 @@ static inline int of_parse_phandle_with_fixed_args(const struct device_node *np, ...@@ -896,7 +896,7 @@ static inline int of_parse_phandle_with_fixed_args(const struct device_node *np,
return -ENOSYS; return -ENOSYS;
} }
static inline int of_count_phandle_with_args(struct device_node *np, static inline int of_count_phandle_with_args(const struct device_node *np,
const char *list_name, const char *list_name,
const char *cells_name) const char *cells_name)
{ {
......
...@@ -49,7 +49,7 @@ static inline struct of_mm_gpio_chip *to_of_mm_gpio_chip(struct gpio_chip *gc) ...@@ -49,7 +49,7 @@ static inline struct of_mm_gpio_chip *to_of_mm_gpio_chip(struct gpio_chip *gc)
return container_of(gc, struct of_mm_gpio_chip, gc); return container_of(gc, struct of_mm_gpio_chip, gc);
} }
extern int of_get_named_gpio_flags(struct device_node *np, extern int of_get_named_gpio_flags(const struct device_node *np,
const char *list_name, int index, enum of_gpio_flags *flags); const char *list_name, int index, enum of_gpio_flags *flags);
extern int of_mm_gpiochip_add_data(struct device_node *np, extern int of_mm_gpiochip_add_data(struct device_node *np,
...@@ -67,7 +67,7 @@ extern void of_mm_gpiochip_remove(struct of_mm_gpio_chip *mm_gc); ...@@ -67,7 +67,7 @@ extern void of_mm_gpiochip_remove(struct of_mm_gpio_chip *mm_gc);
#include <linux/errno.h> #include <linux/errno.h>
/* Drivers may not strictly depend on the GPIO support, so let them link. */ /* Drivers may not strictly depend on the GPIO support, so let them link. */
static inline int of_get_named_gpio_flags(struct device_node *np, static inline int of_get_named_gpio_flags(const struct device_node *np,
const char *list_name, int index, enum of_gpio_flags *flags) const char *list_name, int index, enum of_gpio_flags *flags)
{ {
if (flags) if (flags)
...@@ -98,7 +98,8 @@ static inline int of_get_named_gpio_flags(struct device_node *np, ...@@ -98,7 +98,8 @@ static inline int of_get_named_gpio_flags(struct device_node *np,
* The above example defines four GPIOs, two of which are not specified. * The above example defines four GPIOs, two of which are not specified.
* This function will return '4' * This function will return '4'
*/ */
static inline int of_gpio_named_count(struct device_node *np, const char* propname) static inline int of_gpio_named_count(const struct device_node *np,
const char *propname)
{ {
return of_count_phandle_with_args(np, propname, "#gpio-cells"); return of_count_phandle_with_args(np, propname, "#gpio-cells");
} }
...@@ -109,12 +110,12 @@ static inline int of_gpio_named_count(struct device_node *np, const char* propna ...@@ -109,12 +110,12 @@ static inline int of_gpio_named_count(struct device_node *np, const char* propna
* *
* Same as of_gpio_named_count, but hard coded to use the 'gpios' property * Same as of_gpio_named_count, but hard coded to use the 'gpios' property
*/ */
static inline int of_gpio_count(struct device_node *np) static inline int of_gpio_count(const struct device_node *np)
{ {
return of_gpio_named_count(np, "gpios"); return of_gpio_named_count(np, "gpios");
} }
static inline int of_get_gpio_flags(struct device_node *np, int index, static inline int of_get_gpio_flags(const struct device_node *np, int index,
enum of_gpio_flags *flags) enum of_gpio_flags *flags)
{ {
return of_get_named_gpio_flags(np, "gpios", index, flags); return of_get_named_gpio_flags(np, "gpios", index, flags);
...@@ -129,7 +130,7 @@ static inline int of_get_gpio_flags(struct device_node *np, int index, ...@@ -129,7 +130,7 @@ static inline int of_get_gpio_flags(struct device_node *np, int index,
* Returns GPIO number to use with Linux generic GPIO API, or one of the errno * Returns GPIO number to use with Linux generic GPIO API, or one of the errno
* value on the error condition. * value on the error condition.
*/ */
static inline int of_get_named_gpio(struct device_node *np, static inline int of_get_named_gpio(const struct device_node *np,
const char *propname, int index) const char *propname, int index)
{ {
return of_get_named_gpio_flags(np, propname, index, NULL); return of_get_named_gpio_flags(np, propname, index, NULL);
...@@ -143,7 +144,7 @@ static inline int of_get_named_gpio(struct device_node *np, ...@@ -143,7 +144,7 @@ static inline int of_get_named_gpio(struct device_node *np,
* Returns GPIO number to use with Linux generic GPIO API, or one of the errno * Returns GPIO number to use with Linux generic GPIO API, or one of the errno
* value on the error condition. * value on the error condition.
*/ */
static inline int of_get_gpio(struct device_node *np, int index) static inline int of_get_gpio(const struct device_node *np, int index)
{ {
return of_get_gpio_flags(np, index, NULL); return of_get_gpio_flags(np, index, NULL);
} }
......
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright(c) 2014 Intel Corporation.
*/
#ifndef GPIO_DW_APB_H
#define GPIO_DW_APB_H
#define DWAPB_MAX_GPIOS 32
struct dwapb_port_property {
struct fwnode_handle *fwnode;
unsigned int idx;
unsigned int ngpio;
unsigned int gpio_base;
int irq[DWAPB_MAX_GPIOS];
bool irq_shared;
};
struct dwapb_platform_data {
struct dwapb_port_property *properties;
unsigned int nports;
};
#endif
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
#ifndef LINUX_SPI_MAX7301_H #ifndef LINUX_SPI_MAX7301_H
#define LINUX_SPI_MAX7301_H #define LINUX_SPI_MAX7301_H
#include <linux/gpio.h> #include <linux/gpio/driver.h>
/* /*
* Some registers must be read back to modify. * Some registers must be read back to modify.
......
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
#ifndef _LINUX_VIRTIO_GPIO_H
#define _LINUX_VIRTIO_GPIO_H
#include <linux/types.h>
/* Virtio GPIO request types */
#define VIRTIO_GPIO_MSG_GET_NAMES 0x0001
#define VIRTIO_GPIO_MSG_GET_DIRECTION 0x0002
#define VIRTIO_GPIO_MSG_SET_DIRECTION 0x0003
#define VIRTIO_GPIO_MSG_GET_VALUE 0x0004
#define VIRTIO_GPIO_MSG_SET_VALUE 0x0005
/* Possible values of the status field */
#define VIRTIO_GPIO_STATUS_OK 0x0
#define VIRTIO_GPIO_STATUS_ERR 0x1
/* Direction types */
#define VIRTIO_GPIO_DIRECTION_NONE 0x00
#define VIRTIO_GPIO_DIRECTION_OUT 0x01
#define VIRTIO_GPIO_DIRECTION_IN 0x02
struct virtio_gpio_config {
__le16 ngpio;
__u8 padding[2];
__le32 gpio_names_size;
} __packed;
/* Virtio GPIO Request / Response */
struct virtio_gpio_request {
__le16 type;
__le16 gpio;
__le32 value;
};
struct virtio_gpio_response {
__u8 status;
__u8 value;
};
struct virtio_gpio_response_get_names {
__u8 status;
__u8 value[];
};
#endif /* _LINUX_VIRTIO_GPIO_H */
...@@ -58,6 +58,7 @@ ...@@ -58,6 +58,7 @@
#define VIRTIO_ID_SCMI 32 /* virtio SCMI */ #define VIRTIO_ID_SCMI 32 /* virtio SCMI */
#define VIRTIO_ID_I2C_ADAPTER 34 /* virtio i2c adapter */ #define VIRTIO_ID_I2C_ADAPTER 34 /* virtio i2c adapter */
#define VIRTIO_ID_BT 40 /* virtio bluetooth */ #define VIRTIO_ID_BT 40 /* virtio bluetooth */
#define VIRTIO_ID_GPIO 41 /* virtio gpio */
/* /*
* Virtio Transitional IDs * Virtio Transitional IDs
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册