Commit ba768535 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'pinctrl-v4.14-2' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl

Pull pin control fixes from Linus Walleij:
 "This slew of fixes for pin control was noticed and patched up early,
  so to get the annoyance out of the way for -rc1 it would make sense to
  send them already.

   - Fix a build include in the Uniphier driver to keep pace with
     ongoing refactorings.

   - Fix a slew of minor semantic and syntactic issues as well as
     stricting up Kconfig for the new Spreadtrum driver.

   - Fix the GPIO interrupt set-up on the Marvell 37xx Armada as fallout
     for dynamically allocating irq descriptors from the core. (Also
     tagged for stable.)

   - Fix AMD register suspend/resume state spool/unspooling so that
     wakeup works as it should. (Also tagged for stable.)"

* tag 'pinctrl-v4.14-2' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl:
  pinctrl/amd: save pin registers over suspend/resume
  pinctrl: armada-37xx: Fix gpio interrupt setup
  pinctrl: sprd: fix off by one bugs
  pinctrl: sprd: check for allocation failure
  pinctrl: sprd: Restrict PINCTRL_SPRD to ARCH_SPRD or COMPILE_TEST
  pinctrl: sprd: fix build errors and dependencies
  pinctrl: sprd: make three local functions static
  pinctrl: uniphier: include <linux/build_bug.h> instead of <linux/bug.h>
parents 7a95bdb0 79d2c8be
...@@ -550,9 +550,9 @@ static int armada_37xx_irq_set_wake(struct irq_data *d, unsigned int on) ...@@ -550,9 +550,9 @@ static int armada_37xx_irq_set_wake(struct irq_data *d, unsigned int on)
spin_lock_irqsave(&info->irq_lock, flags); spin_lock_irqsave(&info->irq_lock, flags);
val = readl(info->base + reg); val = readl(info->base + reg);
if (on) if (on)
val |= d->mask; val |= (BIT(d->hwirq % GPIO_PER_REG));
else else
val &= ~d->mask; val &= ~(BIT(d->hwirq % GPIO_PER_REG));
writel(val, info->base + reg); writel(val, info->base + reg);
spin_unlock_irqrestore(&info->irq_lock, flags); spin_unlock_irqrestore(&info->irq_lock, flags);
...@@ -571,10 +571,10 @@ static int armada_37xx_irq_set_type(struct irq_data *d, unsigned int type) ...@@ -571,10 +571,10 @@ static int armada_37xx_irq_set_type(struct irq_data *d, unsigned int type)
val = readl(info->base + reg); val = readl(info->base + reg);
switch (type) { switch (type) {
case IRQ_TYPE_EDGE_RISING: case IRQ_TYPE_EDGE_RISING:
val &= ~d->mask; val &= ~(BIT(d->hwirq % GPIO_PER_REG));
break; break;
case IRQ_TYPE_EDGE_FALLING: case IRQ_TYPE_EDGE_FALLING:
val |= d->mask; val |= (BIT(d->hwirq % GPIO_PER_REG));
break; break;
default: default:
spin_unlock_irqrestore(&info->irq_lock, flags); spin_unlock_irqrestore(&info->irq_lock, flags);
...@@ -624,11 +624,27 @@ static void armada_37xx_irq_handler(struct irq_desc *desc) ...@@ -624,11 +624,27 @@ static void armada_37xx_irq_handler(struct irq_desc *desc)
chained_irq_exit(chip, desc); chained_irq_exit(chip, desc);
} }
static unsigned int armada_37xx_irq_startup(struct irq_data *d)
{
struct gpio_chip *chip = irq_data_get_irq_chip_data(d);
int irq = d->hwirq - chip->irq_base;
/*
* The mask field is a "precomputed bitmask for accessing the
* chip registers" which was introduced for the generic
* irqchip framework. As we don't use this framework, we can
* reuse this field for our own usage.
*/
d->mask = BIT(irq % GPIO_PER_REG);
armada_37xx_irq_unmask(d);
return 0;
}
static int armada_37xx_irqchip_register(struct platform_device *pdev, static int armada_37xx_irqchip_register(struct platform_device *pdev,
struct armada_37xx_pinctrl *info) struct armada_37xx_pinctrl *info)
{ {
struct device_node *np = info->dev->of_node; struct device_node *np = info->dev->of_node;
int nrirqs = info->data->nr_pins;
struct gpio_chip *gc = &info->gpio_chip; struct gpio_chip *gc = &info->gpio_chip;
struct irq_chip *irqchip = &info->irq_chip; struct irq_chip *irqchip = &info->irq_chip;
struct resource res; struct resource res;
...@@ -666,8 +682,8 @@ static int armada_37xx_irqchip_register(struct platform_device *pdev, ...@@ -666,8 +682,8 @@ static int armada_37xx_irqchip_register(struct platform_device *pdev,
irqchip->irq_unmask = armada_37xx_irq_unmask; irqchip->irq_unmask = armada_37xx_irq_unmask;
irqchip->irq_set_wake = armada_37xx_irq_set_wake; irqchip->irq_set_wake = armada_37xx_irq_set_wake;
irqchip->irq_set_type = armada_37xx_irq_set_type; irqchip->irq_set_type = armada_37xx_irq_set_type;
irqchip->irq_startup = armada_37xx_irq_startup;
irqchip->name = info->data->name; irqchip->name = info->data->name;
ret = gpiochip_irqchip_add(gc, irqchip, 0, ret = gpiochip_irqchip_add(gc, irqchip, 0,
handle_edge_irq, IRQ_TYPE_NONE); handle_edge_irq, IRQ_TYPE_NONE);
if (ret) { if (ret) {
...@@ -680,19 +696,6 @@ static int armada_37xx_irqchip_register(struct platform_device *pdev, ...@@ -680,19 +696,6 @@ static int armada_37xx_irqchip_register(struct platform_device *pdev,
* controller. But we do not take advantage of this and use * controller. But we do not take advantage of this and use
* the chained irq with all of them. * the chained irq with all of them.
*/ */
for (i = 0; i < nrirqs; i++) {
struct irq_data *d = irq_get_irq_data(gc->irq_base + i);
/*
* The mask field is a "precomputed bitmask for
* accessing the chip registers" which was introduced
* for the generic irqchip framework. As we don't use
* this framework, we can reuse this field for our own
* usage.
*/
d->mask = BIT(i % GPIO_PER_REG);
}
for (i = 0; i < nr_irq_parent; i++) { for (i = 0; i < nr_irq_parent; i++) {
int irq = irq_of_parse_and_map(np, i); int irq = irq_of_parse_and_map(np, i);
......
...@@ -36,6 +36,7 @@ ...@@ -36,6 +36,7 @@
#include <linux/pinctrl/pinconf.h> #include <linux/pinctrl/pinconf.h>
#include <linux/pinctrl/pinconf-generic.h> #include <linux/pinctrl/pinconf-generic.h>
#include "core.h"
#include "pinctrl-utils.h" #include "pinctrl-utils.h"
#include "pinctrl-amd.h" #include "pinctrl-amd.h"
...@@ -725,6 +726,69 @@ static const struct pinconf_ops amd_pinconf_ops = { ...@@ -725,6 +726,69 @@ static const struct pinconf_ops amd_pinconf_ops = {
.pin_config_group_set = amd_pinconf_group_set, .pin_config_group_set = amd_pinconf_group_set,
}; };
#ifdef CONFIG_PM_SLEEP
static bool amd_gpio_should_save(struct amd_gpio *gpio_dev, unsigned int pin)
{
const struct pin_desc *pd = pin_desc_get(gpio_dev->pctrl, pin);
if (!pd)
return false;
/*
* Only restore the pin if it is actually in use by the kernel (or
* by userspace).
*/
if (pd->mux_owner || pd->gpio_owner ||
gpiochip_line_is_irq(&gpio_dev->gc, pin))
return true;
return false;
}
int amd_gpio_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct amd_gpio *gpio_dev = platform_get_drvdata(pdev);
struct pinctrl_desc *desc = gpio_dev->pctrl->desc;
int i;
for (i = 0; i < desc->npins; i++) {
int pin = desc->pins[i].number;
if (!amd_gpio_should_save(gpio_dev, pin))
continue;
gpio_dev->saved_regs[i] = readl(gpio_dev->base + pin*4);
}
return 0;
}
int amd_gpio_resume(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct amd_gpio *gpio_dev = platform_get_drvdata(pdev);
struct pinctrl_desc *desc = gpio_dev->pctrl->desc;
int i;
for (i = 0; i < desc->npins; i++) {
int pin = desc->pins[i].number;
if (!amd_gpio_should_save(gpio_dev, pin))
continue;
writel(gpio_dev->saved_regs[i], gpio_dev->base + pin*4);
}
return 0;
}
static const struct dev_pm_ops amd_gpio_pm_ops = {
SET_LATE_SYSTEM_SLEEP_PM_OPS(amd_gpio_suspend,
amd_gpio_resume)
};
#endif
static struct pinctrl_desc amd_pinctrl_desc = { static struct pinctrl_desc amd_pinctrl_desc = {
.pins = kerncz_pins, .pins = kerncz_pins,
.npins = ARRAY_SIZE(kerncz_pins), .npins = ARRAY_SIZE(kerncz_pins),
...@@ -764,6 +828,14 @@ static int amd_gpio_probe(struct platform_device *pdev) ...@@ -764,6 +828,14 @@ static int amd_gpio_probe(struct platform_device *pdev)
return irq_base; return irq_base;
} }
#ifdef CONFIG_PM_SLEEP
gpio_dev->saved_regs = devm_kcalloc(&pdev->dev, amd_pinctrl_desc.npins,
sizeof(*gpio_dev->saved_regs),
GFP_KERNEL);
if (!gpio_dev->saved_regs)
return -ENOMEM;
#endif
gpio_dev->pdev = pdev; gpio_dev->pdev = pdev;
gpio_dev->gc.direction_input = amd_gpio_direction_input; gpio_dev->gc.direction_input = amd_gpio_direction_input;
gpio_dev->gc.direction_output = amd_gpio_direction_output; gpio_dev->gc.direction_output = amd_gpio_direction_output;
...@@ -853,6 +925,9 @@ static struct platform_driver amd_gpio_driver = { ...@@ -853,6 +925,9 @@ static struct platform_driver amd_gpio_driver = {
.driver = { .driver = {
.name = "amd_gpio", .name = "amd_gpio",
.acpi_match_table = ACPI_PTR(amd_gpio_acpi_match), .acpi_match_table = ACPI_PTR(amd_gpio_acpi_match),
#ifdef CONFIG_PM_SLEEP
.pm = &amd_gpio_pm_ops,
#endif
}, },
.probe = amd_gpio_probe, .probe = amd_gpio_probe,
.remove = amd_gpio_remove, .remove = amd_gpio_remove,
......
...@@ -97,6 +97,7 @@ struct amd_gpio { ...@@ -97,6 +97,7 @@ struct amd_gpio {
unsigned int hwbank_num; unsigned int hwbank_num;
struct resource *res; struct resource *res;
struct platform_device *pdev; struct platform_device *pdev;
u32 *saved_regs;
}; };
/* KERNCZ configuration*/ /* KERNCZ configuration*/
......
...@@ -4,6 +4,8 @@ ...@@ -4,6 +4,8 @@
config PINCTRL_SPRD config PINCTRL_SPRD
bool "Spreadtrum pinctrl driver" bool "Spreadtrum pinctrl driver"
depends on OF
depends on ARCH_SPRD || COMPILE_TEST
select PINMUX select PINMUX
select PINCONF select PINCONF
select GENERIC_PINCONF select GENERIC_PINCONF
...@@ -13,5 +15,6 @@ config PINCTRL_SPRD ...@@ -13,5 +15,6 @@ config PINCTRL_SPRD
config PINCTRL_SPRD_SC9860 config PINCTRL_SPRD_SC9860
bool "Spreadtrum SC9860 pinctrl driver" bool "Spreadtrum SC9860 pinctrl driver"
depends on PINCTRL_SPRD
help help
Say Y here to enable Spreadtrum SC9860 pinctrl driver Say Y here to enable Spreadtrum SC9860 pinctrl driver
...@@ -353,13 +353,13 @@ static const struct pinctrl_ops sprd_pctrl_ops = { ...@@ -353,13 +353,13 @@ static const struct pinctrl_ops sprd_pctrl_ops = {
.dt_free_map = pinctrl_utils_free_map, .dt_free_map = pinctrl_utils_free_map,
}; };
int sprd_pmx_get_function_count(struct pinctrl_dev *pctldev) static int sprd_pmx_get_function_count(struct pinctrl_dev *pctldev)
{ {
return PIN_FUNC_MAX; return PIN_FUNC_MAX;
} }
const char *sprd_pmx_get_function_name(struct pinctrl_dev *pctldev, static const char *sprd_pmx_get_function_name(struct pinctrl_dev *pctldev,
unsigned int selector) unsigned int selector)
{ {
switch (selector) { switch (selector) {
case PIN_FUNC_1: case PIN_FUNC_1:
...@@ -375,10 +375,10 @@ const char *sprd_pmx_get_function_name(struct pinctrl_dev *pctldev, ...@@ -375,10 +375,10 @@ const char *sprd_pmx_get_function_name(struct pinctrl_dev *pctldev,
} }
} }
int sprd_pmx_get_function_groups(struct pinctrl_dev *pctldev, static int sprd_pmx_get_function_groups(struct pinctrl_dev *pctldev,
unsigned int selector, unsigned int selector,
const char * const **groups, const char * const **groups,
unsigned int * const num_groups) unsigned int * const num_groups)
{ {
struct sprd_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); struct sprd_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
struct sprd_pinctrl_soc_info *info = pctl->info; struct sprd_pinctrl_soc_info *info = pctl->info;
...@@ -400,7 +400,7 @@ static int sprd_pmx_set_mux(struct pinctrl_dev *pctldev, ...@@ -400,7 +400,7 @@ static int sprd_pmx_set_mux(struct pinctrl_dev *pctldev,
unsigned long reg; unsigned long reg;
unsigned int val = 0; unsigned int val = 0;
if (group_selector > info->ngroups) if (group_selector >= info->ngroups)
return -EINVAL; return -EINVAL;
switch (func_selector) { switch (func_selector) {
...@@ -734,7 +734,7 @@ static int sprd_pinconf_group_get(struct pinctrl_dev *pctldev, ...@@ -734,7 +734,7 @@ static int sprd_pinconf_group_get(struct pinctrl_dev *pctldev,
struct sprd_pin_group *grp; struct sprd_pin_group *grp;
unsigned int pin_id; unsigned int pin_id;
if (selector > info->ngroups) if (selector >= info->ngroups)
return -EINVAL; return -EINVAL;
grp = &info->groups[selector]; grp = &info->groups[selector];
...@@ -753,7 +753,7 @@ static int sprd_pinconf_group_set(struct pinctrl_dev *pctldev, ...@@ -753,7 +753,7 @@ static int sprd_pinconf_group_set(struct pinctrl_dev *pctldev,
struct sprd_pin_group *grp; struct sprd_pin_group *grp;
int ret, i; int ret, i;
if (selector > info->ngroups) if (selector >= info->ngroups)
return -EINVAL; return -EINVAL;
grp = &info->groups[selector]; grp = &info->groups[selector];
...@@ -813,7 +813,7 @@ static void sprd_pinconf_group_dbg_show(struct pinctrl_dev *pctldev, ...@@ -813,7 +813,7 @@ static void sprd_pinconf_group_dbg_show(struct pinctrl_dev *pctldev,
const char *name; const char *name;
int i, ret; int i, ret;
if (selector > info->ngroups) if (selector >= info->ngroups)
return; return;
grp = &info->groups[selector]; grp = &info->groups[selector];
...@@ -1100,12 +1100,16 @@ int sprd_pinctrl_remove(struct platform_device *pdev) ...@@ -1100,12 +1100,16 @@ int sprd_pinctrl_remove(struct platform_device *pdev)
void sprd_pinctrl_shutdown(struct platform_device *pdev) void sprd_pinctrl_shutdown(struct platform_device *pdev)
{ {
struct pinctrl *pinctl = devm_pinctrl_get(&pdev->dev); struct pinctrl *pinctl;
struct pinctrl_state *state; struct pinctrl_state *state;
pinctl = devm_pinctrl_get(&pdev->dev);
if (IS_ERR(pinctl))
return;
state = pinctrl_lookup_state(pinctl, "shutdown"); state = pinctrl_lookup_state(pinctl, "shutdown");
if (!IS_ERR(state)) if (IS_ERR(state))
pinctrl_select_state(pinctl, state); return;
pinctrl_select_state(pinctl, state);
} }
MODULE_DESCRIPTION("SPREADTRUM Pin Controller Driver"); MODULE_DESCRIPTION("SPREADTRUM Pin Controller Driver");
......
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
#define __PINCTRL_UNIPHIER_H__ #define __PINCTRL_UNIPHIER_H__
#include <linux/bitops.h> #include <linux/bitops.h>
#include <linux/bug.h> #include <linux/build_bug.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/types.h> #include <linux/types.h>
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment