mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-07-22 02:17:36 -04:00
Merge tag 'gpio-fixes-for-v7.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux
Pull gpio fixes from Bartosz Golaszewski: - fix locking context with shared GPIOs in gpio-tegra - fix IRQ domain leak in error path in gpio-davinci - fix returning a potentially uninitialized integer in gpiochip_set_multiple() - use raw spinlock in gpio-eic-sprd and gpio-sch to address locking context issues - bail out of probe() if registering the GPIO chip fails in gpio-mlxbf3 - fix varible type for storing the "ngpios" property in gpio-pisosr - fix out-of-bounds pin access in GPIO ACPI - make GPIO ACPI core only trigger interrupts on boot that are marked as ActiveBoth - fix kerneldoc in gpio-tb10x - reference the real software node of the cs5535 GPIO controller in Geode board file * tag 'gpio-fixes-for-v7.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux: gpio: davinci: fix IRQ domain leak on devm_kzalloc failure gpio: tegra: do not call pinctrl for GPIO direction gpio: tb10x: fix struct tb10x_gpio kernel-doc gpiolib: initialize return value in gpiochip_set_multiple() x86/platform/geode: reference the real node of the cs5535 GPIO controller gpio: eic-sprd: use raw_spinlock_t in the irq startup path gpio: sch: use raw_spinlock_t in the irq startup path gpiolib: acpi: Prevent out-of-bounds pin access in OperationRegion handler gpiolib: acpi: Add robust bounds-checking for GPIO pin resources gpio: mlxbf3: fail probe if gpiochip registration fails gpio: pisosr: Read "ngpios" as u32 gpiolib: acpi: Only trigger ActiveBoth interrupts on boot
This commit is contained in:
@@ -3026,7 +3026,7 @@ config GEODE_COMMON
|
||||
|
||||
config ALIX
|
||||
bool "PCEngines ALIX System Support (LED setup)"
|
||||
select GPIOLIB
|
||||
depends on GPIO_CS5535=y
|
||||
select GEODE_COMMON
|
||||
help
|
||||
This option enables system support for the PCEngines ALIX.
|
||||
@@ -3034,21 +3034,21 @@ config ALIX
|
||||
ALIX2/3/6 boards. However, other system specific setup should
|
||||
get added here.
|
||||
|
||||
Note: You must still enable the drivers for GPIO and LED support
|
||||
(GPIO_CS5535 & LEDS_GPIO) to actually use the LEDs
|
||||
Note: You must still enable the drivers for LED support (LEDS_GPIO)
|
||||
to actually use the LEDs
|
||||
|
||||
Note: You have to set alix.force=1 for boards with Award BIOS.
|
||||
|
||||
config NET5501
|
||||
bool "Soekris Engineering net5501 System Support (LEDS, GPIO, etc)"
|
||||
select GPIOLIB
|
||||
depends on GPIO_CS5535=y
|
||||
select GEODE_COMMON
|
||||
help
|
||||
This option enables system support for the Soekris Engineering net5501.
|
||||
|
||||
config GEOS
|
||||
bool "Traverse Technologies GEOS System Support (LEDS, GPIO, etc)"
|
||||
select GPIOLIB
|
||||
depends on GPIO_CS5535=y
|
||||
select GEODE_COMMON
|
||||
depends on DMI
|
||||
help
|
||||
|
||||
@@ -9,15 +9,12 @@
|
||||
#include <linux/gpio/property.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/leds.h>
|
||||
#include <linux/mfd/cs5535.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include "geode-common.h"
|
||||
|
||||
static const struct software_node geode_gpiochip_node = {
|
||||
.name = "cs5535-gpio",
|
||||
};
|
||||
|
||||
static const struct property_entry geode_gpio_keys_props[] = {
|
||||
PROPERTY_ENTRY_U32("poll-interval", 20),
|
||||
{ }
|
||||
@@ -44,7 +41,6 @@ static const struct software_node geode_restart_key_node = {
|
||||
};
|
||||
|
||||
static const struct software_node *geode_gpio_keys_swnodes[] __initconst = {
|
||||
&geode_gpiochip_node,
|
||||
&geode_gpio_keys_node,
|
||||
&geode_restart_key_node,
|
||||
NULL
|
||||
@@ -66,7 +62,7 @@ int __init geode_create_restart_key(unsigned int pin)
|
||||
struct platform_device *pd;
|
||||
int err;
|
||||
|
||||
geode_restart_gpio_ref = SOFTWARE_NODE_REFERENCE(&geode_gpiochip_node,
|
||||
geode_restart_gpio_ref = SOFTWARE_NODE_REFERENCE(&cs5535_gpio_swnode,
|
||||
pin, GPIO_ACTIVE_LOW);
|
||||
|
||||
err = software_node_register_node_group(geode_gpio_keys_swnodes);
|
||||
@@ -143,7 +139,7 @@ int __init geode_create_leds(const char *label, const struct geode_led *leds,
|
||||
goto err_free_names;
|
||||
}
|
||||
|
||||
gpio_refs[i] = SOFTWARE_NODE_REFERENCE(&geode_gpiochip_node,
|
||||
gpio_refs[i] = SOFTWARE_NODE_REFERENCE(&cs5535_gpio_swnode,
|
||||
leds[i].pin,
|
||||
GPIO_ACTIVE_LOW);
|
||||
props[i * 3 + 0] =
|
||||
@@ -188,3 +184,5 @@ int __init geode_create_leds(const char *label, const struct geode_led *leds,
|
||||
kfree(swnodes);
|
||||
return err;
|
||||
}
|
||||
|
||||
MODULE_IMPORT_NS("CS5535");
|
||||
|
||||
@@ -568,8 +568,10 @@ static int davinci_gpio_irq_setup(struct platform_device *pdev)
|
||||
sizeof(struct
|
||||
davinci_gpio_irq_data),
|
||||
GFP_KERNEL);
|
||||
if (!irqdata)
|
||||
if (!irqdata) {
|
||||
irq_domain_remove(chips->irq_domain);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
irqdata->regs = g;
|
||||
irqdata->bank_num = bank;
|
||||
|
||||
@@ -95,7 +95,7 @@ struct sprd_eic {
|
||||
struct notifier_block irq_nb;
|
||||
void __iomem *base[SPRD_EIC_MAX_BANK];
|
||||
enum sprd_eic_type type;
|
||||
spinlock_t lock;
|
||||
raw_spinlock_t lock;
|
||||
int irq;
|
||||
};
|
||||
|
||||
@@ -149,7 +149,7 @@ static void sprd_eic_update(struct gpio_chip *chip, unsigned int offset,
|
||||
unsigned long flags;
|
||||
u32 tmp;
|
||||
|
||||
spin_lock_irqsave(&sprd_eic->lock, flags);
|
||||
raw_spin_lock_irqsave(&sprd_eic->lock, flags);
|
||||
tmp = readl_relaxed(base + reg);
|
||||
|
||||
if (val)
|
||||
@@ -158,7 +158,7 @@ static void sprd_eic_update(struct gpio_chip *chip, unsigned int offset,
|
||||
tmp &= ~BIT(SPRD_EIC_BIT(offset));
|
||||
|
||||
writel_relaxed(tmp, base + reg);
|
||||
spin_unlock_irqrestore(&sprd_eic->lock, flags);
|
||||
raw_spin_unlock_irqrestore(&sprd_eic->lock, flags);
|
||||
}
|
||||
|
||||
static int sprd_eic_read(struct gpio_chip *chip, unsigned int offset, u16 reg)
|
||||
@@ -628,7 +628,7 @@ static int sprd_eic_probe(struct platform_device *pdev)
|
||||
if (!sprd_eic)
|
||||
return -ENOMEM;
|
||||
|
||||
spin_lock_init(&sprd_eic->lock);
|
||||
raw_spin_lock_init(&sprd_eic->lock);
|
||||
sprd_eic->type = pdata->type;
|
||||
|
||||
sprd_eic->irq = platform_get_irq(pdev, 0);
|
||||
|
||||
@@ -255,7 +255,8 @@ static int mlxbf3_gpio_probe(struct platform_device *pdev)
|
||||
|
||||
ret = devm_gpiochip_add_data(dev, gc, gs);
|
||||
if (ret)
|
||||
dev_err_probe(dev, ret, "Failed adding memory mapped gpiochip\n");
|
||||
return dev_err_probe(dev, ret,
|
||||
"Failed adding memory mapped gpiochip\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -112,6 +112,7 @@ static int pisosr_gpio_probe(struct spi_device *spi)
|
||||
{
|
||||
struct device *dev = &spi->dev;
|
||||
struct pisosr_gpio *gpio;
|
||||
u32 ngpios;
|
||||
int ret;
|
||||
|
||||
gpio = devm_kzalloc(dev, sizeof(*gpio), GFP_KERNEL);
|
||||
@@ -120,7 +121,8 @@ static int pisosr_gpio_probe(struct spi_device *spi)
|
||||
|
||||
gpio->chip = template_chip;
|
||||
gpio->chip.parent = dev;
|
||||
of_property_read_u16(dev->of_node, "ngpios", &gpio->chip.ngpio);
|
||||
if (!of_property_read_u32(dev->of_node, "ngpios", &ngpios))
|
||||
gpio->chip.ngpio = ngpios;
|
||||
|
||||
gpio->spi = spi;
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
struct sch_gpio {
|
||||
struct gpio_chip chip;
|
||||
void __iomem *regs;
|
||||
spinlock_t lock;
|
||||
raw_spinlock_t lock;
|
||||
unsigned short resume_base;
|
||||
|
||||
/* GPE handling */
|
||||
@@ -104,9 +104,9 @@ static int sch_gpio_direction_in(struct gpio_chip *gc, unsigned int gpio_num)
|
||||
struct sch_gpio *sch = gpiochip_get_data(gc);
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&sch->lock, flags);
|
||||
raw_spin_lock_irqsave(&sch->lock, flags);
|
||||
sch_gpio_reg_set(sch, gpio_num, GIO, 1);
|
||||
spin_unlock_irqrestore(&sch->lock, flags);
|
||||
raw_spin_unlock_irqrestore(&sch->lock, flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -122,9 +122,9 @@ static int sch_gpio_set(struct gpio_chip *gc, unsigned int gpio_num, int val)
|
||||
struct sch_gpio *sch = gpiochip_get_data(gc);
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&sch->lock, flags);
|
||||
raw_spin_lock_irqsave(&sch->lock, flags);
|
||||
sch_gpio_reg_set(sch, gpio_num, GLV, val);
|
||||
spin_unlock_irqrestore(&sch->lock, flags);
|
||||
raw_spin_unlock_irqrestore(&sch->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -135,9 +135,9 @@ static int sch_gpio_direction_out(struct gpio_chip *gc, unsigned int gpio_num,
|
||||
struct sch_gpio *sch = gpiochip_get_data(gc);
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&sch->lock, flags);
|
||||
raw_spin_lock_irqsave(&sch->lock, flags);
|
||||
sch_gpio_reg_set(sch, gpio_num, GIO, 0);
|
||||
spin_unlock_irqrestore(&sch->lock, flags);
|
||||
raw_spin_unlock_irqrestore(&sch->lock, flags);
|
||||
|
||||
/*
|
||||
* according to the datasheet, writing to the level register has no
|
||||
@@ -196,14 +196,14 @@ static int sch_irq_type(struct irq_data *d, unsigned int type)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&sch->lock, flags);
|
||||
raw_spin_lock_irqsave(&sch->lock, flags);
|
||||
|
||||
sch_gpio_reg_set(sch, gpio_num, GTPE, rising);
|
||||
sch_gpio_reg_set(sch, gpio_num, GTNE, falling);
|
||||
|
||||
irq_set_handler_locked(d, handle_edge_irq);
|
||||
|
||||
spin_unlock_irqrestore(&sch->lock, flags);
|
||||
raw_spin_unlock_irqrestore(&sch->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -215,9 +215,9 @@ static void sch_irq_ack(struct irq_data *d)
|
||||
irq_hw_number_t gpio_num = irqd_to_hwirq(d);
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&sch->lock, flags);
|
||||
raw_spin_lock_irqsave(&sch->lock, flags);
|
||||
sch_gpio_reg_set(sch, gpio_num, GTS, 1);
|
||||
spin_unlock_irqrestore(&sch->lock, flags);
|
||||
raw_spin_unlock_irqrestore(&sch->lock, flags);
|
||||
}
|
||||
|
||||
static void sch_irq_mask_unmask(struct gpio_chip *gc, irq_hw_number_t gpio_num, int val)
|
||||
@@ -225,9 +225,9 @@ static void sch_irq_mask_unmask(struct gpio_chip *gc, irq_hw_number_t gpio_num,
|
||||
struct sch_gpio *sch = gpiochip_get_data(gc);
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&sch->lock, flags);
|
||||
raw_spin_lock_irqsave(&sch->lock, flags);
|
||||
sch_gpio_reg_set(sch, gpio_num, GGPE, val);
|
||||
spin_unlock_irqrestore(&sch->lock, flags);
|
||||
raw_spin_unlock_irqrestore(&sch->lock, flags);
|
||||
}
|
||||
|
||||
static void sch_irq_mask(struct irq_data *d)
|
||||
@@ -268,12 +268,12 @@ static u32 sch_gpio_gpe_handler(acpi_handle gpe_device, u32 gpe, void *context)
|
||||
int offset;
|
||||
u32 ret;
|
||||
|
||||
spin_lock_irqsave(&sch->lock, flags);
|
||||
raw_spin_lock_irqsave(&sch->lock, flags);
|
||||
|
||||
core_status = ioread32(sch->regs + CORE_BANK_OFFSET + GTS);
|
||||
resume_status = ioread32(sch->regs + RESUME_BANK_OFFSET + GTS);
|
||||
|
||||
spin_unlock_irqrestore(&sch->lock, flags);
|
||||
raw_spin_unlock_irqrestore(&sch->lock, flags);
|
||||
|
||||
pending = (resume_status << sch->resume_base) | core_status;
|
||||
for_each_set_bit(offset, &pending, sch->chip.ngpio)
|
||||
@@ -343,7 +343,7 @@ static int sch_gpio_probe(struct platform_device *pdev)
|
||||
|
||||
sch->regs = regs;
|
||||
|
||||
spin_lock_init(&sch->lock);
|
||||
raw_spin_lock_init(&sch->lock);
|
||||
sch->chip = sch_gpio_chip;
|
||||
sch->chip.label = dev_name(dev);
|
||||
sch->chip.parent = dev;
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
|
||||
|
||||
/**
|
||||
* struct tb10x_gpio - TB10x GPIO controller structure
|
||||
* @base: register base address
|
||||
* @domain: IRQ domain of GPIO generated interrupts managed by this controller
|
||||
* @irq: Interrupt line of parent interrupt controller
|
||||
|
||||
@@ -172,18 +172,11 @@ static int tegra_gpio_direction_input(struct gpio_chip *chip,
|
||||
unsigned int offset)
|
||||
{
|
||||
struct tegra_gpio_info *tgi = gpiochip_get_data(chip);
|
||||
int ret;
|
||||
|
||||
tegra_gpio_mask_write(tgi, GPIO_MSK_OE(tgi, offset), offset, 0);
|
||||
tegra_gpio_enable(tgi, offset);
|
||||
|
||||
ret = pinctrl_gpio_direction_input(chip, offset);
|
||||
if (ret < 0)
|
||||
dev_err(tgi->dev,
|
||||
"Failed to set pinctrl input direction of GPIO %d: %d",
|
||||
chip->base + offset, ret);
|
||||
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra_gpio_direction_output(struct gpio_chip *chip,
|
||||
@@ -191,19 +184,12 @@ static int tegra_gpio_direction_output(struct gpio_chip *chip,
|
||||
int value)
|
||||
{
|
||||
struct tegra_gpio_info *tgi = gpiochip_get_data(chip);
|
||||
int ret;
|
||||
|
||||
tegra_gpio_set(chip, offset, value);
|
||||
tegra_gpio_mask_write(tgi, GPIO_MSK_OE(tgi, offset), offset, 1);
|
||||
tegra_gpio_enable(tgi, offset);
|
||||
|
||||
ret = pinctrl_gpio_direction_output(chip, offset);
|
||||
if (ret < 0)
|
||||
dev_err(tgi->dev,
|
||||
"Failed to set pinctrl output direction of GPIO %d: %d",
|
||||
chip->base + offset, ret);
|
||||
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra_gpio_get_direction(struct gpio_chip *chip,
|
||||
|
||||
@@ -229,12 +229,23 @@ static void acpi_gpiochip_request_irq(struct acpi_gpio_chip *acpi_gpio,
|
||||
|
||||
event->irq_requested = true;
|
||||
|
||||
/* Make sure we trigger the initial state of edge-triggered IRQs */
|
||||
/*
|
||||
* Make sure we trigger the initial state of ActiveBoth IRQs.
|
||||
*
|
||||
* According to the Microsoft GPIO documentation, triggering GPIO
|
||||
* interrupts marked as ActiveBoth during initialization is correct
|
||||
* as long as the associated GPIO line is already "asserted"
|
||||
* (logic level low). We should not trigger edge-based GPIO
|
||||
* interrupts not marked as ActiveBoth.
|
||||
*
|
||||
* See: https://learn.microsoft.com/en-us/windows-hardware/drivers/bringup/general-purpose-i-o--gpio-
|
||||
* Section: "GPIO controllers and ActiveBoth interrupts"
|
||||
*/
|
||||
if (acpi_gpio_need_run_edge_events_on_boot() &&
|
||||
(event->irqflags & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING))) {
|
||||
((event->irqflags & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)) ==
|
||||
(IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING))) {
|
||||
value = gpiod_get_raw_value_cansleep(event->desc);
|
||||
if (((event->irqflags & IRQF_TRIGGER_RISING) && value == 1) ||
|
||||
((event->irqflags & IRQF_TRIGGER_FALLING) && value == 0))
|
||||
if (value == 0)
|
||||
event->handler(event->irq, event);
|
||||
}
|
||||
}
|
||||
@@ -305,10 +316,17 @@ static struct gpio_desc *acpi_request_own_gpiod(struct gpio_chip *chip,
|
||||
unsigned int index,
|
||||
const char *label)
|
||||
{
|
||||
int polarity = GPIO_ACTIVE_HIGH;
|
||||
enum gpiod_flags flags = acpi_gpio_to_gpiod_flags(agpio, polarity);
|
||||
unsigned int pin = agpio->pin_table[index];
|
||||
enum gpiod_flags flags;
|
||||
struct gpio_desc *desc;
|
||||
unsigned int pin;
|
||||
int polarity;
|
||||
|
||||
if (index >= agpio->pin_table_length)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
pin = agpio->pin_table[index];
|
||||
polarity = GPIO_ACTIVE_HIGH;
|
||||
flags = acpi_gpio_to_gpiod_flags(agpio, polarity);
|
||||
|
||||
desc = gpiochip_request_own_desc(chip, pin, label, polarity, flags);
|
||||
if (IS_ERR(desc))
|
||||
@@ -322,7 +340,12 @@ static struct gpio_desc *acpi_request_own_gpiod(struct gpio_chip *chip,
|
||||
static bool acpi_gpio_irq_is_wake(struct device *parent,
|
||||
const struct acpi_resource_gpio *agpio)
|
||||
{
|
||||
unsigned int pin = agpio->pin_table[0];
|
||||
unsigned int pin;
|
||||
|
||||
if (agpio->pin_table_length == 0)
|
||||
return false;
|
||||
|
||||
pin = agpio->pin_table[0];
|
||||
|
||||
if (agpio->wake_capable != ACPI_WAKE_CAPABLE)
|
||||
return false;
|
||||
@@ -352,6 +375,9 @@ static acpi_status acpi_gpiochip_alloc_event(struct acpi_resource *ares,
|
||||
if (!acpi_gpio_get_irq_resource(ares, &agpio))
|
||||
return AE_OK;
|
||||
|
||||
if (agpio->pin_table_length == 0)
|
||||
return AE_OK;
|
||||
|
||||
handle = ACPI_HANDLE(chip->parent);
|
||||
pin = agpio->pin_table[0];
|
||||
|
||||
@@ -1072,10 +1098,10 @@ acpi_gpio_adr_space_handler(u32 function, acpi_physical_address address,
|
||||
struct gpio_chip *chip = achip->chip;
|
||||
struct acpi_resource_gpio *agpio;
|
||||
struct acpi_resource *ares;
|
||||
u16 pin_index = address;
|
||||
unsigned int length;
|
||||
acpi_status status;
|
||||
int length;
|
||||
int i;
|
||||
unsigned int i;
|
||||
u16 pin_index;
|
||||
|
||||
status = acpi_buffer_to_resource(achip->conn_info.connection,
|
||||
achip->conn_info.length, &ares);
|
||||
@@ -1095,7 +1121,14 @@ acpi_gpio_adr_space_handler(u32 function, acpi_physical_address address,
|
||||
return AE_BAD_PARAMETER;
|
||||
}
|
||||
|
||||
length = min(agpio->pin_table_length, pin_index + bits);
|
||||
/* address represents GPIO pin index in connection table */
|
||||
if (address >= agpio->pin_table_length) {
|
||||
ACPI_FREE(ares);
|
||||
return AE_BAD_PARAMETER;
|
||||
}
|
||||
|
||||
pin_index = address;
|
||||
length = min_t(unsigned int, agpio->pin_table_length, pin_index + bits);
|
||||
for (i = pin_index; i < length; ++i) {
|
||||
unsigned int pin = agpio->pin_table[i];
|
||||
struct acpi_gpio_connection *conn;
|
||||
|
||||
@@ -3803,7 +3803,7 @@ static int gpiochip_set_multiple(struct gpio_chip *gc,
|
||||
unsigned long *mask, unsigned long *bits)
|
||||
{
|
||||
unsigned int i;
|
||||
int ret;
|
||||
int ret = 0;
|
||||
|
||||
lockdep_assert_held(&gc->gpiodev->srcu);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user