diff options
Diffstat (limited to 'drivers/gpio')
-rw-r--r-- | drivers/gpio/gpio-aspeed.c | 3 | ||||
-rw-r--r-- | drivers/gpio/gpio-crystalcove.c | 54 | ||||
-rw-r--r-- | drivers/gpio/gpio-mvebu.c | 9 |
3 files changed, 47 insertions, 19 deletions
diff --git a/drivers/gpio/gpio-aspeed.c b/drivers/gpio/gpio-aspeed.c index ccea609676ee..4ca436e66bdb 100644 --- a/drivers/gpio/gpio-aspeed.c +++ b/drivers/gpio/gpio-aspeed.c @@ -646,6 +646,9 @@ static int enable_debounce(struct gpio_chip *chip, unsigned int offset, int rc; int i; + if (!gpio->clk) + return -EINVAL; + rc = usecs_to_cycles(gpio, usecs, &requested_cycles); if (rc < 0) { dev_warn(chip->parent, "Failed to convert %luus to cycles at %luHz: %d\n", diff --git a/drivers/gpio/gpio-crystalcove.c b/drivers/gpio/gpio-crystalcove.c index 2197368cc899..e60156ec0c18 100644 --- a/drivers/gpio/gpio-crystalcove.c +++ b/drivers/gpio/gpio-crystalcove.c @@ -90,8 +90,18 @@ static inline int to_reg(int gpio, enum ctrl_register reg_type) { int reg; - if (gpio == 94) - return GPIOPANELCTL; + if (gpio >= CRYSTALCOVE_GPIO_NUM) { + /* + * Virtual GPIO called from ACPI, for now we only support + * the panel ctl. + */ + switch (gpio) { + case 0x5e: + return GPIOPANELCTL; + default: + return -EOPNOTSUPP; + } + } if (reg_type == CTRL_IN) { if (gpio < 8) @@ -130,36 +140,36 @@ static void crystalcove_update_irq_ctrl(struct crystalcove_gpio *cg, int gpio) static int crystalcove_gpio_dir_in(struct gpio_chip *chip, unsigned gpio) { struct crystalcove_gpio *cg = gpiochip_get_data(chip); + int reg = to_reg(gpio, CTRL_OUT); - if (gpio > CRYSTALCOVE_VGPIO_NUM) + if (reg < 0) return 0; - return regmap_write(cg->regmap, to_reg(gpio, CTRL_OUT), - CTLO_INPUT_SET); + return regmap_write(cg->regmap, reg, CTLO_INPUT_SET); } static int crystalcove_gpio_dir_out(struct gpio_chip *chip, unsigned gpio, int value) { struct crystalcove_gpio *cg = gpiochip_get_data(chip); + int reg = to_reg(gpio, CTRL_OUT); - if (gpio > CRYSTALCOVE_VGPIO_NUM) + if (reg < 0) return 0; - return regmap_write(cg->regmap, to_reg(gpio, CTRL_OUT), - CTLO_OUTPUT_SET | value); + return regmap_write(cg->regmap, reg, CTLO_OUTPUT_SET | value); } static int crystalcove_gpio_get(struct gpio_chip *chip, unsigned gpio) { struct crystalcove_gpio *cg = gpiochip_get_data(chip); - int ret; unsigned int val; + int ret, reg = to_reg(gpio, CTRL_IN); - if (gpio > CRYSTALCOVE_VGPIO_NUM) + if (reg < 0) return 0; - ret = regmap_read(cg->regmap, to_reg(gpio, CTRL_IN), &val); + ret = regmap_read(cg->regmap, reg, &val); if (ret) return ret; @@ -170,14 +180,15 @@ static void crystalcove_gpio_set(struct gpio_chip *chip, unsigned gpio, int value) { struct crystalcove_gpio *cg = gpiochip_get_data(chip); + int reg = to_reg(gpio, CTRL_OUT); - if (gpio > CRYSTALCOVE_VGPIO_NUM) + if (reg < 0) return; if (value) - regmap_update_bits(cg->regmap, to_reg(gpio, CTRL_OUT), 1, 1); + regmap_update_bits(cg->regmap, reg, 1, 1); else - regmap_update_bits(cg->regmap, to_reg(gpio, CTRL_OUT), 1, 0); + regmap_update_bits(cg->regmap, reg, 1, 0); } static int crystalcove_irq_type(struct irq_data *data, unsigned type) @@ -185,6 +196,9 @@ static int crystalcove_irq_type(struct irq_data *data, unsigned type) struct crystalcove_gpio *cg = gpiochip_get_data(irq_data_get_irq_chip_data(data)); + if (data->hwirq >= CRYSTALCOVE_GPIO_NUM) + return 0; + switch (type) { case IRQ_TYPE_NONE: cg->intcnt_value = CTLI_INTCNT_DIS; @@ -235,8 +249,10 @@ static void crystalcove_irq_unmask(struct irq_data *data) struct crystalcove_gpio *cg = gpiochip_get_data(irq_data_get_irq_chip_data(data)); - cg->set_irq_mask = false; - cg->update |= UPDATE_IRQ_MASK; + if (data->hwirq < CRYSTALCOVE_GPIO_NUM) { + cg->set_irq_mask = false; + cg->update |= UPDATE_IRQ_MASK; + } } static void crystalcove_irq_mask(struct irq_data *data) @@ -244,8 +260,10 @@ static void crystalcove_irq_mask(struct irq_data *data) struct crystalcove_gpio *cg = gpiochip_get_data(irq_data_get_irq_chip_data(data)); - cg->set_irq_mask = true; - cg->update |= UPDATE_IRQ_MASK; + if (data->hwirq < CRYSTALCOVE_GPIO_NUM) { + cg->set_irq_mask = true; + cg->update |= UPDATE_IRQ_MASK; + } } static struct irq_chip crystalcove_irqchip = { diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c index 19a92efabbef..5104b6398139 100644 --- a/drivers/gpio/gpio-mvebu.c +++ b/drivers/gpio/gpio-mvebu.c @@ -747,7 +747,7 @@ static int mvebu_pwm_probe(struct platform_device *pdev, set = U32_MAX; else return -EINVAL; - writel_relaxed(0, mvebu_gpioreg_blink_counter_select(mvchip)); + writel_relaxed(set, mvebu_gpioreg_blink_counter_select(mvchip)); mvpwm = devm_kzalloc(dev, sizeof(struct mvebu_pwm), GFP_KERNEL); if (!mvpwm) @@ -768,6 +768,13 @@ static int mvebu_pwm_probe(struct platform_device *pdev, mvpwm->chip.dev = dev; mvpwm->chip.ops = &mvebu_pwm_ops; mvpwm->chip.npwm = mvchip->chip.ngpio; + /* + * There may already be some PWM allocated, so we can't force + * mvpwm->chip.base to a fixed point like mvchip->chip.base. + * So, we let pwmchip_add() do the numbering and take the next free + * region. + */ + mvpwm->chip.base = -1; spin_lock_init(&mvpwm->lock); |