A set of pin control fixes for the v4.0 release cycle:
- Fix up consumer return values on pin control stubs. - Four patches fixing up the interrupt handling and sleep context save in the Baytrail driver. - Make default output directions work properly in the Cherryview driver. - Fix interrupt locking in the AT91 driver. - Fix setting interrupt generating lines as input in the sunxi driver. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJVCo4HAAoJEEEQszewGV1z+HQQAMAzKL9igh3iCDR8p3tmB1sp ZBTgWl4NHT9MFeA1AmilVEn1JbmUDmDetTN7P/sVC8mxaJiheY8PrFbj4bwBsvzA JV0mlSBSj7jw8CxNM9rzSWZxRNtdpKr45siLA1SBPdni2x711SRW1H57eK73UQnQ PEVW9hWzXY4cHU6Q7dX67YDJuteQsu5A1QCy6hBYX4Kyyy5gT8RJs6lAvx2f5k8g Gsdgs60T/bTmIAiQT3FIf6VUQezW2m1PZn2fhuJeUCZWM17ej2YjVoanQUKu3Bz5 GPvV3wt2FpbKJsum5p4FJQPRD2qPsuq4jg7Msk6QOiVWHOl/QtL30AnS6N/iQ97z TlblAH3ze2t182rHeI4J8d4FIX8jRfftb9DHlgBhLZFU4k0EanMvqEWN6/8yqgmy n5nYUB88y6rI5RRLoGAStudlRIHqpz0fFvsU6IW5aZ7wpobIv+JPtMBUbfIKdQBV Xj39LDJj9W5jtI7Icl2v8q7oTknnEa7rUuH/VYbptMLkXBxndWPKG2JLFwfhQ3Py KMZvFdLP7E2uAR89KNvqQxbQQuYOK8wx5T2nFV57wVPX6VFv/G9sKUqdS5F7iraS qg8aBloBN9k79mBBWyIo/XEdluYC/zuKf2KPRvH7UhXep+e9iqCSxWyXqgbgv6F9 MtWvNLoK9kZyxymnqbmJ =qp0z -----END PGP SIGNATURE----- Merge tag 'pinctrl-v4.0-2' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl Pull pin control fixes from Linus Walleij: "Here is a slew of pin control fixes I've accumulated for the v4.0 kernel. Nothing special, just driver fixes (mainly embedded Intel it seems) and a misunderstanding regarding the stub functions was reverted: - Fix up consumer return values on pin control stubs. - Four patches fixing up the interrupt handling and sleep context save in the Baytrail driver. - Make default output directions work properly in the Cherryview driver. - Fix interrupt locking in the AT91 driver. - Fix setting interrupt generating lines as input in the sunxi driver" * tag 'pinctrl-v4.0-2' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl: pinctrl: sun4i: GPIOs configured as irq must be set to input before reading pinctrl: at91: move lock/unlock_as_irq calls into request/release pinctrl: update direction_output function of cherryview driver pinctrl: baytrail: Save pin context over system sleep pinctrl: baytrail: Rework interrupt handling pinctrl: baytrail: Clear interrupt triggering from pins that are in GPIO mode pinctrl: baytrail: Relax GPIO request rules Revert "pinctrl: consumer: use correct retval for placeholder functions"
This commit is contained in:
commit
01d62ee520
|
@ -66,6 +66,10 @@
|
|||
#define BYT_DIR_MASK (BIT(1) | BIT(2))
|
||||
#define BYT_TRIG_MASK (BIT(26) | BIT(25) | BIT(24))
|
||||
|
||||
#define BYT_CONF0_RESTORE_MASK (BYT_DIRECT_IRQ_EN | BYT_TRIG_MASK | \
|
||||
BYT_PIN_MUX)
|
||||
#define BYT_VAL_RESTORE_MASK (BYT_DIR_MASK | BYT_LEVEL)
|
||||
|
||||
#define BYT_NGPIO_SCORE 102
|
||||
#define BYT_NGPIO_NCORE 28
|
||||
#define BYT_NGPIO_SUS 44
|
||||
|
@ -134,12 +138,18 @@ static struct pinctrl_gpio_range byt_ranges[] = {
|
|||
},
|
||||
};
|
||||
|
||||
struct byt_gpio_pin_context {
|
||||
u32 conf0;
|
||||
u32 val;
|
||||
};
|
||||
|
||||
struct byt_gpio {
|
||||
struct gpio_chip chip;
|
||||
struct platform_device *pdev;
|
||||
spinlock_t lock;
|
||||
void __iomem *reg_base;
|
||||
struct pinctrl_gpio_range *range;
|
||||
struct byt_gpio_pin_context *saved_context;
|
||||
};
|
||||
|
||||
#define to_byt_gpio(c) container_of(c, struct byt_gpio, chip)
|
||||
|
@ -158,40 +168,62 @@ static void __iomem *byt_gpio_reg(struct gpio_chip *chip, unsigned offset,
|
|||
return vg->reg_base + reg_offset + reg;
|
||||
}
|
||||
|
||||
static bool is_special_pin(struct byt_gpio *vg, unsigned offset)
|
||||
static void byt_gpio_clear_triggering(struct byt_gpio *vg, unsigned offset)
|
||||
{
|
||||
void __iomem *reg = byt_gpio_reg(&vg->chip, offset, BYT_CONF0_REG);
|
||||
unsigned long flags;
|
||||
u32 value;
|
||||
|
||||
spin_lock_irqsave(&vg->lock, flags);
|
||||
value = readl(reg);
|
||||
value &= ~(BYT_TRIG_POS | BYT_TRIG_NEG | BYT_TRIG_LVL);
|
||||
writel(value, reg);
|
||||
spin_unlock_irqrestore(&vg->lock, flags);
|
||||
}
|
||||
|
||||
static u32 byt_get_gpio_mux(struct byt_gpio *vg, unsigned offset)
|
||||
{
|
||||
/* SCORE pin 92-93 */
|
||||
if (!strcmp(vg->range->name, BYT_SCORE_ACPI_UID) &&
|
||||
offset >= 92 && offset <= 93)
|
||||
return true;
|
||||
return 1;
|
||||
|
||||
/* SUS pin 11-21 */
|
||||
if (!strcmp(vg->range->name, BYT_SUS_ACPI_UID) &&
|
||||
offset >= 11 && offset <= 21)
|
||||
return true;
|
||||
return 1;
|
||||
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int byt_gpio_request(struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
struct byt_gpio *vg = to_byt_gpio(chip);
|
||||
void __iomem *reg = byt_gpio_reg(chip, offset, BYT_CONF0_REG);
|
||||
u32 value;
|
||||
bool special;
|
||||
u32 value, gpio_mux;
|
||||
|
||||
/*
|
||||
* In most cases, func pin mux 000 means GPIO function.
|
||||
* But, some pins may have func pin mux 001 represents
|
||||
* GPIO function. Only allow user to export pin with
|
||||
* func pin mux preset as GPIO function by BIOS/FW.
|
||||
* GPIO function.
|
||||
*
|
||||
* Because there are devices out there where some pins were not
|
||||
* configured correctly we allow changing the mux value from
|
||||
* request (but print out warning about that).
|
||||
*/
|
||||
value = readl(reg) & BYT_PIN_MUX;
|
||||
special = is_special_pin(vg, offset);
|
||||
if ((special && value != 1) || (!special && value)) {
|
||||
dev_err(&vg->pdev->dev,
|
||||
"pin %u cannot be used as GPIO.\n", offset);
|
||||
return -EINVAL;
|
||||
gpio_mux = byt_get_gpio_mux(vg, offset);
|
||||
if (WARN_ON(gpio_mux != value)) {
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&vg->lock, flags);
|
||||
value = readl(reg) & ~BYT_PIN_MUX;
|
||||
value |= gpio_mux;
|
||||
writel(value, reg);
|
||||
spin_unlock_irqrestore(&vg->lock, flags);
|
||||
|
||||
dev_warn(&vg->pdev->dev,
|
||||
"pin %u forcibly re-configured as GPIO\n", offset);
|
||||
}
|
||||
|
||||
pm_runtime_get(&vg->pdev->dev);
|
||||
|
@ -202,14 +234,8 @@ static int byt_gpio_request(struct gpio_chip *chip, unsigned offset)
|
|||
static void byt_gpio_free(struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
struct byt_gpio *vg = to_byt_gpio(chip);
|
||||
void __iomem *reg = byt_gpio_reg(&vg->chip, offset, BYT_CONF0_REG);
|
||||
u32 value;
|
||||
|
||||
/* clear interrupt triggering */
|
||||
value = readl(reg);
|
||||
value &= ~(BYT_TRIG_POS | BYT_TRIG_NEG | BYT_TRIG_LVL);
|
||||
writel(value, reg);
|
||||
|
||||
byt_gpio_clear_triggering(vg, offset);
|
||||
pm_runtime_put(&vg->pdev->dev);
|
||||
}
|
||||
|
||||
|
@ -236,23 +262,13 @@ static int byt_irq_type(struct irq_data *d, unsigned type)
|
|||
value &= ~(BYT_DIRECT_IRQ_EN | BYT_TRIG_POS | BYT_TRIG_NEG |
|
||||
BYT_TRIG_LVL);
|
||||
|
||||
switch (type) {
|
||||
case IRQ_TYPE_LEVEL_HIGH:
|
||||
value |= BYT_TRIG_LVL;
|
||||
case IRQ_TYPE_EDGE_RISING:
|
||||
value |= BYT_TRIG_POS;
|
||||
break;
|
||||
case IRQ_TYPE_LEVEL_LOW:
|
||||
value |= BYT_TRIG_LVL;
|
||||
case IRQ_TYPE_EDGE_FALLING:
|
||||
value |= BYT_TRIG_NEG;
|
||||
break;
|
||||
case IRQ_TYPE_EDGE_BOTH:
|
||||
value |= (BYT_TRIG_NEG | BYT_TRIG_POS);
|
||||
break;
|
||||
}
|
||||
writel(value, reg);
|
||||
|
||||
if (type & IRQ_TYPE_EDGE_BOTH)
|
||||
__irq_set_handler_locked(d->irq, handle_edge_irq);
|
||||
else if (type & IRQ_TYPE_LEVEL_MASK)
|
||||
__irq_set_handler_locked(d->irq, handle_level_irq);
|
||||
|
||||
spin_unlock_irqrestore(&vg->lock, flags);
|
||||
|
||||
return 0;
|
||||
|
@ -410,58 +426,80 @@ static void byt_gpio_irq_handler(unsigned irq, struct irq_desc *desc)
|
|||
struct irq_data *data = irq_desc_get_irq_data(desc);
|
||||
struct byt_gpio *vg = to_byt_gpio(irq_desc_get_handler_data(desc));
|
||||
struct irq_chip *chip = irq_data_get_irq_chip(data);
|
||||
u32 base, pin, mask;
|
||||
u32 base, pin;
|
||||
void __iomem *reg;
|
||||
u32 pending;
|
||||
unsigned long pending;
|
||||
unsigned virq;
|
||||
int looplimit = 0;
|
||||
|
||||
/* check from GPIO controller which pin triggered the interrupt */
|
||||
for (base = 0; base < vg->chip.ngpio; base += 32) {
|
||||
|
||||
reg = byt_gpio_reg(&vg->chip, base, BYT_INT_STAT_REG);
|
||||
|
||||
while ((pending = readl(reg))) {
|
||||
pin = __ffs(pending);
|
||||
mask = BIT(pin);
|
||||
/* Clear before handling so we can't lose an edge */
|
||||
writel(mask, reg);
|
||||
|
||||
pending = readl(reg);
|
||||
for_each_set_bit(pin, &pending, 32) {
|
||||
virq = irq_find_mapping(vg->chip.irqdomain, base + pin);
|
||||
generic_handle_irq(virq);
|
||||
|
||||
/* In case bios or user sets triggering incorretly a pin
|
||||
* might remain in "interrupt triggered" state.
|
||||
*/
|
||||
if (looplimit++ > 32) {
|
||||
dev_err(&vg->pdev->dev,
|
||||
"Gpio %d interrupt flood, disabling\n",
|
||||
base + pin);
|
||||
|
||||
reg = byt_gpio_reg(&vg->chip, base + pin,
|
||||
BYT_CONF0_REG);
|
||||
mask = readl(reg);
|
||||
mask &= ~(BYT_TRIG_NEG | BYT_TRIG_POS |
|
||||
BYT_TRIG_LVL);
|
||||
writel(mask, reg);
|
||||
mask = readl(reg); /* flush */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
chip->irq_eoi(data);
|
||||
}
|
||||
|
||||
static void byt_irq_ack(struct irq_data *d)
|
||||
{
|
||||
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
|
||||
struct byt_gpio *vg = to_byt_gpio(gc);
|
||||
unsigned offset = irqd_to_hwirq(d);
|
||||
void __iomem *reg;
|
||||
|
||||
reg = byt_gpio_reg(&vg->chip, offset, BYT_INT_STAT_REG);
|
||||
writel(BIT(offset % 32), reg);
|
||||
}
|
||||
|
||||
static void byt_irq_unmask(struct irq_data *d)
|
||||
{
|
||||
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
|
||||
struct byt_gpio *vg = to_byt_gpio(gc);
|
||||
unsigned offset = irqd_to_hwirq(d);
|
||||
unsigned long flags;
|
||||
void __iomem *reg;
|
||||
u32 value;
|
||||
|
||||
spin_lock_irqsave(&vg->lock, flags);
|
||||
|
||||
reg = byt_gpio_reg(&vg->chip, offset, BYT_CONF0_REG);
|
||||
value = readl(reg);
|
||||
|
||||
switch (irqd_get_trigger_type(d)) {
|
||||
case IRQ_TYPE_LEVEL_HIGH:
|
||||
value |= BYT_TRIG_LVL;
|
||||
case IRQ_TYPE_EDGE_RISING:
|
||||
value |= BYT_TRIG_POS;
|
||||
break;
|
||||
case IRQ_TYPE_LEVEL_LOW:
|
||||
value |= BYT_TRIG_LVL;
|
||||
case IRQ_TYPE_EDGE_FALLING:
|
||||
value |= BYT_TRIG_NEG;
|
||||
break;
|
||||
case IRQ_TYPE_EDGE_BOTH:
|
||||
value |= (BYT_TRIG_NEG | BYT_TRIG_POS);
|
||||
break;
|
||||
}
|
||||
|
||||
writel(value, reg);
|
||||
|
||||
spin_unlock_irqrestore(&vg->lock, flags);
|
||||
}
|
||||
|
||||
static void byt_irq_mask(struct irq_data *d)
|
||||
{
|
||||
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
|
||||
struct byt_gpio *vg = to_byt_gpio(gc);
|
||||
|
||||
byt_gpio_clear_triggering(vg, irqd_to_hwirq(d));
|
||||
}
|
||||
|
||||
static struct irq_chip byt_irqchip = {
|
||||
.name = "BYT-GPIO",
|
||||
.irq_ack = byt_irq_ack,
|
||||
.irq_mask = byt_irq_mask,
|
||||
.irq_unmask = byt_irq_unmask,
|
||||
.irq_set_type = byt_irq_type,
|
||||
|
@ -472,6 +510,21 @@ static void byt_gpio_irq_init_hw(struct byt_gpio *vg)
|
|||
{
|
||||
void __iomem *reg;
|
||||
u32 base, value;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Clear interrupt triggers for all pins that are GPIOs and
|
||||
* do not use direct IRQ mode. This will prevent spurious
|
||||
* interrupts from misconfigured pins.
|
||||
*/
|
||||
for (i = 0; i < vg->chip.ngpio; i++) {
|
||||
value = readl(byt_gpio_reg(&vg->chip, i, BYT_CONF0_REG));
|
||||
if ((value & BYT_PIN_MUX) == byt_get_gpio_mux(vg, i) &&
|
||||
!(value & BYT_DIRECT_IRQ_EN)) {
|
||||
byt_gpio_clear_triggering(vg, i);
|
||||
dev_dbg(&vg->pdev->dev, "disabling GPIO %d\n", i);
|
||||
}
|
||||
}
|
||||
|
||||
/* clear interrupt status trigger registers */
|
||||
for (base = 0; base < vg->chip.ngpio; base += 32) {
|
||||
|
@ -541,6 +594,11 @@ static int byt_gpio_probe(struct platform_device *pdev)
|
|||
gc->can_sleep = false;
|
||||
gc->dev = dev;
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
vg->saved_context = devm_kcalloc(&pdev->dev, gc->ngpio,
|
||||
sizeof(*vg->saved_context), GFP_KERNEL);
|
||||
#endif
|
||||
|
||||
ret = gpiochip_add(gc);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed adding byt-gpio chip\n");
|
||||
|
@ -569,6 +627,69 @@ static int byt_gpio_probe(struct platform_device *pdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int byt_gpio_suspend(struct device *dev)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct byt_gpio *vg = platform_get_drvdata(pdev);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < vg->chip.ngpio; i++) {
|
||||
void __iomem *reg;
|
||||
u32 value;
|
||||
|
||||
reg = byt_gpio_reg(&vg->chip, i, BYT_CONF0_REG);
|
||||
value = readl(reg) & BYT_CONF0_RESTORE_MASK;
|
||||
vg->saved_context[i].conf0 = value;
|
||||
|
||||
reg = byt_gpio_reg(&vg->chip, i, BYT_VAL_REG);
|
||||
value = readl(reg) & BYT_VAL_RESTORE_MASK;
|
||||
vg->saved_context[i].val = value;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int byt_gpio_resume(struct device *dev)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct byt_gpio *vg = platform_get_drvdata(pdev);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < vg->chip.ngpio; i++) {
|
||||
void __iomem *reg;
|
||||
u32 value;
|
||||
|
||||
reg = byt_gpio_reg(&vg->chip, i, BYT_CONF0_REG);
|
||||
value = readl(reg);
|
||||
if ((value & BYT_CONF0_RESTORE_MASK) !=
|
||||
vg->saved_context[i].conf0) {
|
||||
value &= ~BYT_CONF0_RESTORE_MASK;
|
||||
value |= vg->saved_context[i].conf0;
|
||||
writel(value, reg);
|
||||
dev_info(dev, "restored pin %d conf0 %#08x", i, value);
|
||||
}
|
||||
|
||||
reg = byt_gpio_reg(&vg->chip, i, BYT_VAL_REG);
|
||||
value = readl(reg);
|
||||
if ((value & BYT_VAL_RESTORE_MASK) !=
|
||||
vg->saved_context[i].val) {
|
||||
u32 v;
|
||||
|
||||
v = value & ~BYT_VAL_RESTORE_MASK;
|
||||
v |= vg->saved_context[i].val;
|
||||
if (v != value) {
|
||||
writel(v, reg);
|
||||
dev_dbg(dev, "restored pin %d val %#08x\n",
|
||||
i, v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int byt_gpio_runtime_suspend(struct device *dev)
|
||||
{
|
||||
return 0;
|
||||
|
@ -580,8 +701,9 @@ static int byt_gpio_runtime_resume(struct device *dev)
|
|||
}
|
||||
|
||||
static const struct dev_pm_ops byt_gpio_pm_ops = {
|
||||
.runtime_suspend = byt_gpio_runtime_suspend,
|
||||
.runtime_resume = byt_gpio_runtime_resume,
|
||||
SET_LATE_SYSTEM_SLEEP_PM_OPS(byt_gpio_suspend, byt_gpio_resume)
|
||||
SET_RUNTIME_PM_OPS(byt_gpio_runtime_suspend, byt_gpio_runtime_resume,
|
||||
NULL)
|
||||
};
|
||||
|
||||
static const struct acpi_device_id byt_gpio_acpi_match[] = {
|
||||
|
|
|
@ -1226,6 +1226,7 @@ static int chv_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
|
|||
static int chv_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
|
||||
int value)
|
||||
{
|
||||
chv_gpio_set(chip, offset, value);
|
||||
return pinctrl_gpio_direction_output(chip->base + offset);
|
||||
}
|
||||
|
||||
|
|
|
@ -1477,28 +1477,25 @@ static void gpio_irq_ack(struct irq_data *d)
|
|||
/* the interrupt is already cleared before by reading ISR */
|
||||
}
|
||||
|
||||
static unsigned int gpio_irq_startup(struct irq_data *d)
|
||||
static int gpio_irq_request_res(struct irq_data *d)
|
||||
{
|
||||
struct at91_gpio_chip *at91_gpio = irq_data_get_irq_chip_data(d);
|
||||
unsigned pin = d->hwirq;
|
||||
int ret;
|
||||
|
||||
ret = gpiochip_lock_as_irq(&at91_gpio->chip, pin);
|
||||
if (ret) {
|
||||
if (ret)
|
||||
dev_err(at91_gpio->chip.dev, "unable to lock pind %lu IRQ\n",
|
||||
d->hwirq);
|
||||
return ret;
|
||||
}
|
||||
gpio_irq_unmask(d);
|
||||
return 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void gpio_irq_shutdown(struct irq_data *d)
|
||||
static void gpio_irq_release_res(struct irq_data *d)
|
||||
{
|
||||
struct at91_gpio_chip *at91_gpio = irq_data_get_irq_chip_data(d);
|
||||
unsigned pin = d->hwirq;
|
||||
|
||||
gpio_irq_mask(d);
|
||||
gpiochip_unlock_as_irq(&at91_gpio->chip, pin);
|
||||
}
|
||||
|
||||
|
@ -1577,8 +1574,8 @@ void at91_pinctrl_gpio_resume(void)
|
|||
static struct irq_chip gpio_irqchip = {
|
||||
.name = "GPIO",
|
||||
.irq_ack = gpio_irq_ack,
|
||||
.irq_startup = gpio_irq_startup,
|
||||
.irq_shutdown = gpio_irq_shutdown,
|
||||
.irq_request_resources = gpio_irq_request_res,
|
||||
.irq_release_resources = gpio_irq_release_res,
|
||||
.irq_disable = gpio_irq_mask,
|
||||
.irq_mask = gpio_irq_mask,
|
||||
.irq_unmask = gpio_irq_unmask,
|
||||
|
|
|
@ -1011,6 +1011,7 @@ static const struct sunxi_pinctrl_desc sun4i_a10_pinctrl_data = {
|
|||
.pins = sun4i_a10_pins,
|
||||
.npins = ARRAY_SIZE(sun4i_a10_pins),
|
||||
.irq_banks = 1,
|
||||
.irq_read_needs_mux = true,
|
||||
};
|
||||
|
||||
static int sun4i_a10_pinctrl_probe(struct platform_device *pdev)
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include <linux/slab.h>
|
||||
|
||||
#include "../core.h"
|
||||
#include "../../gpio/gpiolib.h"
|
||||
#include "pinctrl-sunxi.h"
|
||||
|
||||
static struct irq_chip sunxi_pinctrl_edge_irq_chip;
|
||||
|
@ -464,10 +465,19 @@ static int sunxi_pinctrl_gpio_direction_input(struct gpio_chip *chip,
|
|||
static int sunxi_pinctrl_gpio_get(struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
struct sunxi_pinctrl *pctl = dev_get_drvdata(chip->dev);
|
||||
|
||||
u32 reg = sunxi_data_reg(offset);
|
||||
u8 index = sunxi_data_offset(offset);
|
||||
u32 val = (readl(pctl->membase + reg) >> index) & DATA_PINS_MASK;
|
||||
u32 set_mux = pctl->desc->irq_read_needs_mux &&
|
||||
test_bit(FLAG_USED_AS_IRQ, &chip->desc[offset].flags);
|
||||
u32 val;
|
||||
|
||||
if (set_mux)
|
||||
sunxi_pmx_set(pctl->pctl_dev, offset, SUN4I_FUNC_INPUT);
|
||||
|
||||
val = (readl(pctl->membase + reg) >> index) & DATA_PINS_MASK;
|
||||
|
||||
if (set_mux)
|
||||
sunxi_pmx_set(pctl->pctl_dev, offset, SUN4I_FUNC_IRQ);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
|
|
@ -77,6 +77,9 @@
|
|||
#define IRQ_LEVEL_LOW 0x03
|
||||
#define IRQ_EDGE_BOTH 0x04
|
||||
|
||||
#define SUN4I_FUNC_INPUT 0
|
||||
#define SUN4I_FUNC_IRQ 6
|
||||
|
||||
struct sunxi_desc_function {
|
||||
const char *name;
|
||||
u8 muxval;
|
||||
|
@ -94,6 +97,7 @@ struct sunxi_pinctrl_desc {
|
|||
int npins;
|
||||
unsigned pin_base;
|
||||
unsigned irq_banks;
|
||||
bool irq_read_needs_mux;
|
||||
};
|
||||
|
||||
struct sunxi_pinctrl_function {
|
||||
|
|
|
@ -82,7 +82,7 @@ static inline int pinctrl_gpio_direction_output(unsigned gpio)
|
|||
|
||||
static inline struct pinctrl * __must_check pinctrl_get(struct device *dev)
|
||||
{
|
||||
return ERR_PTR(-ENOSYS);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline void pinctrl_put(struct pinctrl *p)
|
||||
|
@ -93,7 +93,7 @@ static inline struct pinctrl_state * __must_check pinctrl_lookup_state(
|
|||
struct pinctrl *p,
|
||||
const char *name)
|
||||
{
|
||||
return ERR_PTR(-ENOSYS);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline int pinctrl_select_state(struct pinctrl *p,
|
||||
|
@ -104,7 +104,7 @@ static inline int pinctrl_select_state(struct pinctrl *p,
|
|||
|
||||
static inline struct pinctrl * __must_check devm_pinctrl_get(struct device *dev)
|
||||
{
|
||||
return ERR_PTR(-ENOSYS);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline void devm_pinctrl_put(struct pinctrl *p)
|
||||
|
|
Loading…
Reference in New Issue