mirror of
https://github.com/tbsdtv/linux_media.git
synced 2025-07-23 12:43:29 +02:00
Merge tag 'gpio-v5.9-2' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio
Pull GPIO fixes from Linus Walleij: "Some late GPIO fixes for the v5.9 series: - Fix compiler warnings on the OMAP when PM is disabled - Clear the interrupt when setting edge sensitivity on the Spreadtrum driver. - Fix up spurious interrupts on the TC35894. - Support threaded interrupts on the Siox controller. - Fix resource leaks on the mockup driver. - Fix line event handling in syscall compatible mode for the character device. - Fix an unitialized variable in the PCA953A driver. - Fix access to all GPIO IRQs on the Aspeed AST2600. - Fix line direction on the AMD FCH driver. - Use the bitmap API instead of compiler intrinsics for bit manipulation in the PCA953x driver" * tag 'gpio-v5.9-2' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio: gpio: pca953x: Correctly initialize registers 6 and 7 for PCA957x gpio: pca953x: Use bitmap API over implicit GCC extension gpio: amd-fch: correct logic of GPIO_LINE_DIRECTION gpio: aspeed: fix ast2600 bank properties gpio/aspeed-sgpio: don't enable all interrupts by default gpio/aspeed-sgpio: enable access to all 80 input & output sgpios gpio: pca953x: Fix uninitialized pending variable gpiolib: Fix line event handling in syscall compatible mode gpio: mockup: fix resource leak in error path gpio: siox: explicitly support only threaded irqs gpio: tc35894: fix up tc35894 interrupt configuration gpio: sprd: Clear interrupt when setting the type as edge gpio: omap: Fix warnings if PM is disabled
This commit is contained in:
@@ -20,8 +20,9 @@ Required properties:
|
|||||||
- gpio-controller : Marks the device node as a GPIO controller
|
- gpio-controller : Marks the device node as a GPIO controller
|
||||||
- interrupts : Interrupt specifier, see interrupt-controller/interrupts.txt
|
- interrupts : Interrupt specifier, see interrupt-controller/interrupts.txt
|
||||||
- interrupt-controller : Mark the GPIO controller as an interrupt-controller
|
- interrupt-controller : Mark the GPIO controller as an interrupt-controller
|
||||||
- ngpios : number of GPIO lines, see gpio.txt
|
- ngpios : number of *hardware* GPIO lines, see gpio.txt. This will expose
|
||||||
(should be multiple of 8, up to 80 pins)
|
2 software GPIOs per hardware GPIO: one for hardware input, one for hardware
|
||||||
|
output. Up to 80 pins, must be a multiple of 8.
|
||||||
- clocks : A phandle to the APB clock for SGPM clock division
|
- clocks : A phandle to the APB clock for SGPM clock division
|
||||||
- bus-frequency : SGPM CLK frequency
|
- bus-frequency : SGPM CLK frequency
|
||||||
|
|
||||||
|
@@ -92,7 +92,7 @@ static int amd_fch_gpio_get_direction(struct gpio_chip *gc, unsigned int gpio)
|
|||||||
ret = (readl_relaxed(ptr) & AMD_FCH_GPIO_FLAG_DIRECTION);
|
ret = (readl_relaxed(ptr) & AMD_FCH_GPIO_FLAG_DIRECTION);
|
||||||
spin_unlock_irqrestore(&priv->lock, flags);
|
spin_unlock_irqrestore(&priv->lock, flags);
|
||||||
|
|
||||||
return ret ? GPIO_LINE_DIRECTION_IN : GPIO_LINE_DIRECTION_OUT;
|
return ret ? GPIO_LINE_DIRECTION_OUT : GPIO_LINE_DIRECTION_IN;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void amd_fch_gpio_set(struct gpio_chip *gc,
|
static void amd_fch_gpio_set(struct gpio_chip *gc,
|
||||||
|
@@ -17,7 +17,17 @@
|
|||||||
#include <linux/spinlock.h>
|
#include <linux/spinlock.h>
|
||||||
#include <linux/string.h>
|
#include <linux/string.h>
|
||||||
|
|
||||||
#define MAX_NR_SGPIO 80
|
/*
|
||||||
|
* 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
|
||||||
|
|
||||||
@@ -30,8 +40,8 @@ struct aspeed_sgpio {
|
|||||||
struct clk *pclk;
|
struct clk *pclk;
|
||||||
spinlock_t lock;
|
spinlock_t lock;
|
||||||
void __iomem *base;
|
void __iomem *base;
|
||||||
uint32_t dir_in[3];
|
|
||||||
int irq;
|
int irq;
|
||||||
|
int n_sgpio;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct aspeed_sgpio_bank {
|
struct aspeed_sgpio_bank {
|
||||||
@@ -111,31 +121,69 @@ static void __iomem *bank_reg(struct aspeed_sgpio *gpio,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#define GPIO_BANK(x) ((x) >> 5)
|
#define GPIO_BANK(x) ((x % SGPIO_OUTPUT_OFFSET) >> 5)
|
||||||
#define GPIO_OFFSET(x) ((x) & 0x1f)
|
#define GPIO_OFFSET(x) ((x % SGPIO_OUTPUT_OFFSET) & 0x1f)
|
||||||
#define GPIO_BIT(x) BIT(GPIO_OFFSET(x))
|
#define GPIO_BIT(x) BIT(GPIO_OFFSET(x))
|
||||||
|
|
||||||
static const struct aspeed_sgpio_bank *to_bank(unsigned int offset)
|
static const struct aspeed_sgpio_bank *to_bank(unsigned int offset)
|
||||||
{
|
{
|
||||||
unsigned int bank = GPIO_BANK(offset);
|
unsigned int bank;
|
||||||
|
|
||||||
|
bank = GPIO_BANK(offset);
|
||||||
|
|
||||||
WARN_ON(bank >= ARRAY_SIZE(aspeed_sgpio_banks));
|
WARN_ON(bank >= ARRAY_SIZE(aspeed_sgpio_banks));
|
||||||
return &aspeed_sgpio_banks[bank];
|
return &aspeed_sgpio_banks[bank];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int aspeed_sgpio_init_valid_mask(struct gpio_chip *gc,
|
||||||
|
unsigned long *valid_mask, unsigned int ngpios)
|
||||||
|
{
|
||||||
|
struct aspeed_sgpio *sgpio = gpiochip_get_data(gc);
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void aspeed_sgpio_irq_init_valid_mask(struct gpio_chip *gc,
|
||||||
|
unsigned long *valid_mask, unsigned int ngpios)
|
||||||
|
{
|
||||||
|
struct aspeed_sgpio *sgpio = gpiochip_get_data(gc);
|
||||||
|
int n = sgpio->n_sgpio;
|
||||||
|
|
||||||
|
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, ngpios - n);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool aspeed_sgpio_is_input(unsigned int offset)
|
||||||
|
{
|
||||||
|
return offset < SGPIO_OUTPUT_OFFSET;
|
||||||
|
}
|
||||||
|
|
||||||
static int aspeed_sgpio_get(struct gpio_chip *gc, unsigned int offset)
|
static int aspeed_sgpio_get(struct gpio_chip *gc, unsigned int offset)
|
||||||
{
|
{
|
||||||
struct aspeed_sgpio *gpio = gpiochip_get_data(gc);
|
struct aspeed_sgpio *gpio = gpiochip_get_data(gc);
|
||||||
const struct aspeed_sgpio_bank *bank = to_bank(offset);
|
const struct aspeed_sgpio_bank *bank = to_bank(offset);
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
enum aspeed_sgpio_reg reg;
|
enum aspeed_sgpio_reg reg;
|
||||||
bool is_input;
|
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
spin_lock_irqsave(&gpio->lock, flags);
|
spin_lock_irqsave(&gpio->lock, flags);
|
||||||
|
|
||||||
is_input = gpio->dir_in[GPIO_BANK(offset)] & GPIO_BIT(offset);
|
reg = aspeed_sgpio_is_input(offset) ? reg_val : reg_rdata;
|
||||||
reg = is_input ? reg_val : reg_rdata;
|
|
||||||
rc = !!(ioread32(bank_reg(gpio, bank, reg)) & GPIO_BIT(offset));
|
rc = !!(ioread32(bank_reg(gpio, bank, reg)) & GPIO_BIT(offset));
|
||||||
|
|
||||||
spin_unlock_irqrestore(&gpio->lock, flags);
|
spin_unlock_irqrestore(&gpio->lock, flags);
|
||||||
@@ -143,22 +191,31 @@ static int aspeed_sgpio_get(struct gpio_chip *gc, unsigned int offset)
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sgpio_set_value(struct gpio_chip *gc, unsigned int offset, int val)
|
static int sgpio_set_value(struct gpio_chip *gc, unsigned int offset, int val)
|
||||||
{
|
{
|
||||||
struct aspeed_sgpio *gpio = gpiochip_get_data(gc);
|
struct aspeed_sgpio *gpio = gpiochip_get_data(gc);
|
||||||
const struct aspeed_sgpio_bank *bank = to_bank(offset);
|
const struct aspeed_sgpio_bank *bank = to_bank(offset);
|
||||||
void __iomem *addr;
|
void __iomem *addr_r, *addr_w;
|
||||||
u32 reg = 0;
|
u32 reg = 0;
|
||||||
|
|
||||||
addr = bank_reg(gpio, bank, reg_val);
|
if (aspeed_sgpio_is_input(offset))
|
||||||
reg = ioread32(addr);
|
return -EINVAL;
|
||||||
|
|
||||||
|
/* Since this is an output, read the cached value from rdata, then
|
||||||
|
* update val. */
|
||||||
|
addr_r = bank_reg(gpio, bank, reg_rdata);
|
||||||
|
addr_w = bank_reg(gpio, bank, reg_val);
|
||||||
|
|
||||||
|
reg = ioread32(addr_r);
|
||||||
|
|
||||||
if (val)
|
if (val)
|
||||||
reg |= GPIO_BIT(offset);
|
reg |= GPIO_BIT(offset);
|
||||||
else
|
else
|
||||||
reg &= ~GPIO_BIT(offset);
|
reg &= ~GPIO_BIT(offset);
|
||||||
|
|
||||||
iowrite32(reg, addr);
|
iowrite32(reg, addr_w);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void aspeed_sgpio_set(struct gpio_chip *gc, unsigned int offset, int val)
|
static void aspeed_sgpio_set(struct gpio_chip *gc, unsigned int offset, int val)
|
||||||
@@ -175,43 +232,28 @@ static void aspeed_sgpio_set(struct gpio_chip *gc, unsigned int offset, int val)
|
|||||||
|
|
||||||
static int aspeed_sgpio_dir_in(struct gpio_chip *gc, unsigned int offset)
|
static int aspeed_sgpio_dir_in(struct gpio_chip *gc, unsigned int offset)
|
||||||
{
|
{
|
||||||
struct aspeed_sgpio *gpio = gpiochip_get_data(gc);
|
return aspeed_sgpio_is_input(offset) ? 0 : -EINVAL;
|
||||||
unsigned long flags;
|
|
||||||
|
|
||||||
spin_lock_irqsave(&gpio->lock, flags);
|
|
||||||
gpio->dir_in[GPIO_BANK(offset)] |= GPIO_BIT(offset);
|
|
||||||
spin_unlock_irqrestore(&gpio->lock, flags);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int aspeed_sgpio_dir_out(struct gpio_chip *gc, unsigned int offset, int val)
|
static int aspeed_sgpio_dir_out(struct gpio_chip *gc, unsigned int offset, int val)
|
||||||
{
|
{
|
||||||
struct aspeed_sgpio *gpio = gpiochip_get_data(gc);
|
struct aspeed_sgpio *gpio = gpiochip_get_data(gc);
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
/* No special action is required for setting the direction; we'll
|
||||||
|
* error-out in sgpio_set_value if this isn't an output GPIO */
|
||||||
|
|
||||||
spin_lock_irqsave(&gpio->lock, flags);
|
spin_lock_irqsave(&gpio->lock, flags);
|
||||||
|
rc = sgpio_set_value(gc, offset, val);
|
||||||
gpio->dir_in[GPIO_BANK(offset)] &= ~GPIO_BIT(offset);
|
|
||||||
sgpio_set_value(gc, offset, val);
|
|
||||||
|
|
||||||
spin_unlock_irqrestore(&gpio->lock, flags);
|
spin_unlock_irqrestore(&gpio->lock, flags);
|
||||||
|
|
||||||
return 0;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int aspeed_sgpio_get_direction(struct gpio_chip *gc, unsigned int offset)
|
static int aspeed_sgpio_get_direction(struct gpio_chip *gc, unsigned int offset)
|
||||||
{
|
{
|
||||||
int dir_status;
|
return !!aspeed_sgpio_is_input(offset);
|
||||||
struct aspeed_sgpio *gpio = gpiochip_get_data(gc);
|
|
||||||
unsigned long flags;
|
|
||||||
|
|
||||||
spin_lock_irqsave(&gpio->lock, flags);
|
|
||||||
dir_status = gpio->dir_in[GPIO_BANK(offset)] & GPIO_BIT(offset);
|
|
||||||
spin_unlock_irqrestore(&gpio->lock, flags);
|
|
||||||
|
|
||||||
return dir_status;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void irqd_to_aspeed_sgpio_data(struct irq_data *d,
|
static void irqd_to_aspeed_sgpio_data(struct irq_data *d,
|
||||||
@@ -402,6 +444,7 @@ static int aspeed_sgpio_setup_irqs(struct aspeed_sgpio *gpio,
|
|||||||
|
|
||||||
irq = &gpio->chip.irq;
|
irq = &gpio->chip.irq;
|
||||||
irq->chip = &aspeed_sgpio_irqchip;
|
irq->chip = &aspeed_sgpio_irqchip;
|
||||||
|
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;
|
||||||
irq->parent_handler = aspeed_sgpio_irq_handler;
|
irq->parent_handler = aspeed_sgpio_irq_handler;
|
||||||
@@ -409,17 +452,15 @@ static int aspeed_sgpio_setup_irqs(struct aspeed_sgpio *gpio,
|
|||||||
irq->parents = &gpio->irq;
|
irq->parents = &gpio->irq;
|
||||||
irq->num_parents = 1;
|
irq->num_parents = 1;
|
||||||
|
|
||||||
/* set IRQ settings and Enable Interrupt */
|
/* Apply default IRQ settings */
|
||||||
for (i = 0; i < ARRAY_SIZE(aspeed_sgpio_banks); i++) {
|
for (i = 0; i < ARRAY_SIZE(aspeed_sgpio_banks); i++) {
|
||||||
bank = &aspeed_sgpio_banks[i];
|
bank = &aspeed_sgpio_banks[i];
|
||||||
/* set falling or level-low irq */
|
/* set falling or level-low irq */
|
||||||
iowrite32(0x00000000, bank_reg(gpio, bank, reg_irq_type0));
|
iowrite32(0x00000000, bank_reg(gpio, bank, reg_irq_type0));
|
||||||
/* trigger type is edge */
|
/* trigger type is edge */
|
||||||
iowrite32(0x00000000, bank_reg(gpio, bank, reg_irq_type1));
|
iowrite32(0x00000000, bank_reg(gpio, bank, reg_irq_type1));
|
||||||
/* dual edge trigger mode. */
|
/* single edge trigger */
|
||||||
iowrite32(0xffffffff, bank_reg(gpio, bank, reg_irq_type2));
|
iowrite32(0x00000000, bank_reg(gpio, bank, reg_irq_type2));
|
||||||
/* enable irq */
|
|
||||||
iowrite32(0xffffffff, bank_reg(gpio, bank, reg_irq_enable));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -452,11 +493,12 @@ static int __init aspeed_sgpio_probe(struct platform_device *pdev)
|
|||||||
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_SGPIO) {
|
} else if (nr_gpios > MAX_NR_HW_SGPIO) {
|
||||||
dev_err(&pdev->dev, "Number of GPIOs exceeds the maximum of %d: %d\n",
|
dev_err(&pdev->dev, "Number of GPIOs exceeds the maximum of %d: %d\n",
|
||||||
MAX_NR_SGPIO, nr_gpios);
|
MAX_NR_HW_SGPIO, 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 = of_property_read_u32(pdev->dev.of_node, "bus-frequency", &sgpio_freq);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
@@ -497,7 +539,8 @@ static int __init aspeed_sgpio_probe(struct platform_device *pdev)
|
|||||||
spin_lock_init(&gpio->lock);
|
spin_lock_init(&gpio->lock);
|
||||||
|
|
||||||
gpio->chip.parent = &pdev->dev;
|
gpio->chip.parent = &pdev->dev;
|
||||||
gpio->chip.ngpio = nr_gpios;
|
gpio->chip.ngpio = MAX_NR_HW_SGPIO * 2;
|
||||||
|
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;
|
||||||
gpio->chip.get_direction = aspeed_sgpio_get_direction;
|
gpio->chip.get_direction = aspeed_sgpio_get_direction;
|
||||||
@@ -509,9 +552,6 @@ static int __init aspeed_sgpio_probe(struct platform_device *pdev)
|
|||||||
gpio->chip.label = dev_name(&pdev->dev);
|
gpio->chip.label = dev_name(&pdev->dev);
|
||||||
gpio->chip.base = -1;
|
gpio->chip.base = -1;
|
||||||
|
|
||||||
/* set all SGPIO pins as input (1). */
|
|
||||||
memset(gpio->dir_in, 0xff, sizeof(gpio->dir_in));
|
|
||||||
|
|
||||||
aspeed_sgpio_setup_irqs(gpio, pdev);
|
aspeed_sgpio_setup_irqs(gpio, pdev);
|
||||||
|
|
||||||
rc = devm_gpiochip_add_data(&pdev->dev, &gpio->chip, gpio);
|
rc = devm_gpiochip_add_data(&pdev->dev, &gpio->chip, gpio);
|
||||||
|
@@ -1114,8 +1114,8 @@ static const struct aspeed_gpio_config ast2500_config =
|
|||||||
|
|
||||||
static const struct aspeed_bank_props ast2600_bank_props[] = {
|
static const struct aspeed_bank_props ast2600_bank_props[] = {
|
||||||
/* input output */
|
/* input output */
|
||||||
{5, 0xffffffff, 0x0000ffff}, /* U/V/W/X */
|
{5, 0xffffffff, 0xffffff00}, /* U/V/W/X */
|
||||||
{6, 0xffff0000, 0x0fff0000}, /* Y/Z */
|
{6, 0x0000ffff, 0x0000ffff}, /* Y/Z */
|
||||||
{ },
|
{ },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -552,6 +552,7 @@ static int __init gpio_mockup_init(void)
|
|||||||
err = platform_driver_register(&gpio_mockup_driver);
|
err = platform_driver_register(&gpio_mockup_driver);
|
||||||
if (err) {
|
if (err) {
|
||||||
gpio_mockup_err("error registering platform driver\n");
|
gpio_mockup_err("error registering platform driver\n");
|
||||||
|
debugfs_remove_recursive(gpio_mockup_dbg_dir);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -582,6 +583,7 @@ static int __init gpio_mockup_init(void)
|
|||||||
gpio_mockup_err("error registering device");
|
gpio_mockup_err("error registering device");
|
||||||
platform_driver_unregister(&gpio_mockup_driver);
|
platform_driver_unregister(&gpio_mockup_driver);
|
||||||
gpio_mockup_unregister_pdevs();
|
gpio_mockup_unregister_pdevs();
|
||||||
|
debugfs_remove_recursive(gpio_mockup_dbg_dir);
|
||||||
return PTR_ERR(pdev);
|
return PTR_ERR(pdev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1516,7 +1516,7 @@ static int __maybe_unused omap_gpio_runtime_resume(struct device *dev)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int omap_gpio_suspend(struct device *dev)
|
static int __maybe_unused omap_gpio_suspend(struct device *dev)
|
||||||
{
|
{
|
||||||
struct gpio_bank *bank = dev_get_drvdata(dev);
|
struct gpio_bank *bank = dev_get_drvdata(dev);
|
||||||
|
|
||||||
@@ -1528,7 +1528,7 @@ static int omap_gpio_suspend(struct device *dev)
|
|||||||
return omap_gpio_runtime_suspend(dev);
|
return omap_gpio_runtime_suspend(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int omap_gpio_resume(struct device *dev)
|
static int __maybe_unused omap_gpio_resume(struct device *dev)
|
||||||
{
|
{
|
||||||
struct gpio_bank *bank = dev_get_drvdata(dev);
|
struct gpio_bank *bank = dev_get_drvdata(dev);
|
||||||
|
|
||||||
|
@@ -818,6 +818,8 @@ static irqreturn_t pca953x_irq_handler(int irq, void *devid)
|
|||||||
int level;
|
int level;
|
||||||
bool ret;
|
bool ret;
|
||||||
|
|
||||||
|
bitmap_zero(pending, MAX_LINE);
|
||||||
|
|
||||||
mutex_lock(&chip->i2c_lock);
|
mutex_lock(&chip->i2c_lock);
|
||||||
ret = pca953x_irq_pending(chip, pending);
|
ret = pca953x_irq_pending(chip, pending);
|
||||||
mutex_unlock(&chip->i2c_lock);
|
mutex_unlock(&chip->i2c_lock);
|
||||||
@@ -940,6 +942,7 @@ out:
|
|||||||
static int device_pca957x_init(struct pca953x_chip *chip, u32 invert)
|
static int device_pca957x_init(struct pca953x_chip *chip, u32 invert)
|
||||||
{
|
{
|
||||||
DECLARE_BITMAP(val, MAX_LINE);
|
DECLARE_BITMAP(val, MAX_LINE);
|
||||||
|
unsigned int i;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = device_pca95xx_init(chip, invert);
|
ret = device_pca95xx_init(chip, invert);
|
||||||
@@ -947,7 +950,9 @@ static int device_pca957x_init(struct pca953x_chip *chip, u32 invert)
|
|||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
/* To enable register 6, 7 to control pull up and pull down */
|
/* To enable register 6, 7 to control pull up and pull down */
|
||||||
memset(val, 0x02, NBANK(chip));
|
for (i = 0; i < NBANK(chip); i++)
|
||||||
|
bitmap_set_value8(val, 0x02, i * BANK_SZ);
|
||||||
|
|
||||||
ret = pca953x_write_regs(chip, PCA957X_BKEN, val);
|
ret = pca953x_write_regs(chip, PCA957X_BKEN, val);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out;
|
goto out;
|
||||||
|
@@ -245,6 +245,7 @@ static int gpio_siox_probe(struct siox_device *sdevice)
|
|||||||
girq->chip = &ddata->ichip;
|
girq->chip = &ddata->ichip;
|
||||||
girq->default_type = IRQ_TYPE_NONE;
|
girq->default_type = IRQ_TYPE_NONE;
|
||||||
girq->handler = handle_level_irq;
|
girq->handler = handle_level_irq;
|
||||||
|
girq->threaded = true;
|
||||||
|
|
||||||
ret = devm_gpiochip_add_data(dev, &ddata->gchip, NULL);
|
ret = devm_gpiochip_add_data(dev, &ddata->gchip, NULL);
|
||||||
if (ret)
|
if (ret)
|
||||||
|
@@ -149,17 +149,20 @@ static int sprd_gpio_irq_set_type(struct irq_data *data,
|
|||||||
sprd_gpio_update(chip, offset, SPRD_GPIO_IS, 0);
|
sprd_gpio_update(chip, offset, SPRD_GPIO_IS, 0);
|
||||||
sprd_gpio_update(chip, offset, SPRD_GPIO_IBE, 0);
|
sprd_gpio_update(chip, offset, SPRD_GPIO_IBE, 0);
|
||||||
sprd_gpio_update(chip, offset, SPRD_GPIO_IEV, 1);
|
sprd_gpio_update(chip, offset, SPRD_GPIO_IEV, 1);
|
||||||
|
sprd_gpio_update(chip, offset, SPRD_GPIO_IC, 1);
|
||||||
irq_set_handler_locked(data, handle_edge_irq);
|
irq_set_handler_locked(data, handle_edge_irq);
|
||||||
break;
|
break;
|
||||||
case IRQ_TYPE_EDGE_FALLING:
|
case IRQ_TYPE_EDGE_FALLING:
|
||||||
sprd_gpio_update(chip, offset, SPRD_GPIO_IS, 0);
|
sprd_gpio_update(chip, offset, SPRD_GPIO_IS, 0);
|
||||||
sprd_gpio_update(chip, offset, SPRD_GPIO_IBE, 0);
|
sprd_gpio_update(chip, offset, SPRD_GPIO_IBE, 0);
|
||||||
sprd_gpio_update(chip, offset, SPRD_GPIO_IEV, 0);
|
sprd_gpio_update(chip, offset, SPRD_GPIO_IEV, 0);
|
||||||
|
sprd_gpio_update(chip, offset, SPRD_GPIO_IC, 1);
|
||||||
irq_set_handler_locked(data, handle_edge_irq);
|
irq_set_handler_locked(data, handle_edge_irq);
|
||||||
break;
|
break;
|
||||||
case IRQ_TYPE_EDGE_BOTH:
|
case IRQ_TYPE_EDGE_BOTH:
|
||||||
sprd_gpio_update(chip, offset, SPRD_GPIO_IS, 0);
|
sprd_gpio_update(chip, offset, SPRD_GPIO_IS, 0);
|
||||||
sprd_gpio_update(chip, offset, SPRD_GPIO_IBE, 1);
|
sprd_gpio_update(chip, offset, SPRD_GPIO_IBE, 1);
|
||||||
|
sprd_gpio_update(chip, offset, SPRD_GPIO_IC, 1);
|
||||||
irq_set_handler_locked(data, handle_edge_irq);
|
irq_set_handler_locked(data, handle_edge_irq);
|
||||||
break;
|
break;
|
||||||
case IRQ_TYPE_LEVEL_HIGH:
|
case IRQ_TYPE_LEVEL_HIGH:
|
||||||
|
@@ -212,7 +212,7 @@ static void tc3589x_gpio_irq_sync_unlock(struct irq_data *d)
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
tc3589x_gpio->oldregs[i][j] = new;
|
tc3589x_gpio->oldregs[i][j] = new;
|
||||||
tc3589x_reg_write(tc3589x, regmap[i] + j * 8, new);
|
tc3589x_reg_write(tc3589x, regmap[i] + j, new);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -423,6 +423,21 @@ static __poll_t lineevent_poll(struct file *file,
|
|||||||
return events;
|
return events;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ssize_t lineevent_get_size(void)
|
||||||
|
{
|
||||||
|
#ifdef __x86_64__
|
||||||
|
/* i386 has no padding after 'id' */
|
||||||
|
if (in_ia32_syscall()) {
|
||||||
|
struct compat_gpioeevent_data {
|
||||||
|
compat_u64 timestamp;
|
||||||
|
u32 id;
|
||||||
|
};
|
||||||
|
|
||||||
|
return sizeof(struct compat_gpioeevent_data);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return sizeof(struct gpioevent_data);
|
||||||
|
}
|
||||||
|
|
||||||
static ssize_t lineevent_read(struct file *file,
|
static ssize_t lineevent_read(struct file *file,
|
||||||
char __user *buf,
|
char __user *buf,
|
||||||
@@ -432,9 +447,20 @@ static ssize_t lineevent_read(struct file *file,
|
|||||||
struct lineevent_state *le = file->private_data;
|
struct lineevent_state *le = file->private_data;
|
||||||
struct gpioevent_data ge;
|
struct gpioevent_data ge;
|
||||||
ssize_t bytes_read = 0;
|
ssize_t bytes_read = 0;
|
||||||
|
ssize_t ge_size;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (count < sizeof(ge))
|
/*
|
||||||
|
* When compatible system call is being used the struct gpioevent_data,
|
||||||
|
* in case of at least ia32, has different size due to the alignment
|
||||||
|
* differences. Because we have first member 64 bits followed by one of
|
||||||
|
* 32 bits there is no gap between them. The only difference is the
|
||||||
|
* padding at the end of the data structure. Hence, we calculate the
|
||||||
|
* actual sizeof() and pass this as an argument to copy_to_user() to
|
||||||
|
* drop unneeded bytes from the output.
|
||||||
|
*/
|
||||||
|
ge_size = lineevent_get_size();
|
||||||
|
if (count < ge_size)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
@@ -470,10 +496,10 @@ static ssize_t lineevent_read(struct file *file,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (copy_to_user(buf + bytes_read, &ge, sizeof(ge)))
|
if (copy_to_user(buf + bytes_read, &ge, ge_size))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
bytes_read += sizeof(ge);
|
bytes_read += ge_size;
|
||||||
} while (count >= bytes_read + sizeof(ge));
|
} while (count >= bytes_read + ge_size);
|
||||||
|
|
||||||
return bytes_read;
|
return bytes_read;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user