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)
spin_lock_irqsave(&info->irq_lock, flags);
val = readl(info->base + reg);
if (on)
val |= d->mask;
val |= (BIT(d->hwirq % GPIO_PER_REG));
else
val &= ~d->mask;
val &= ~(BIT(d->hwirq % GPIO_PER_REG));
writel(val, info->base + reg);
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)
val = readl(info->base + reg);
switch (type) {
case IRQ_TYPE_EDGE_RISING:
val &= ~d->mask;
val &= ~(BIT(d->hwirq % GPIO_PER_REG));
break;
case IRQ_TYPE_EDGE_FALLING:
val |= d->mask;
val |= (BIT(d->hwirq % GPIO_PER_REG));
break;
default:
spin_unlock_irqrestore(&info->irq_lock, flags);
......@@ -624,11 +624,27 @@ static void armada_37xx_irq_handler(struct irq_desc *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,
struct armada_37xx_pinctrl *info)
{
struct device_node *np = info->dev->of_node;
int nrirqs = info->data->nr_pins;
struct gpio_chip *gc = &info->gpio_chip;
struct irq_chip *irqchip = &info->irq_chip;
struct resource res;
......@@ -666,8 +682,8 @@ static int armada_37xx_irqchip_register(struct platform_device *pdev,
irqchip->irq_unmask = armada_37xx_irq_unmask;
irqchip->irq_set_wake = armada_37xx_irq_set_wake;
irqchip->irq_set_type = armada_37xx_irq_set_type;
irqchip->irq_startup = armada_37xx_irq_startup;
irqchip->name = info->data->name;
ret = gpiochip_irqchip_add(gc, irqchip, 0,
handle_edge_irq, IRQ_TYPE_NONE);
if (ret) {
......@@ -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
* 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++) {
int irq = irq_of_parse_and_map(np, i);
......
......@@ -36,6 +36,7 @@
#include <linux/pinctrl/pinconf.h>
#include <linux/pinctrl/pinconf-generic.h>
#include "core.h"
#include "pinctrl-utils.h"
#include "pinctrl-amd.h"
......@@ -725,6 +726,69 @@ static const struct pinconf_ops amd_pinconf_ops = {
.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 = {
.pins = kerncz_pins,
.npins = ARRAY_SIZE(kerncz_pins),
......@@ -764,6 +828,14 @@ static int amd_gpio_probe(struct platform_device *pdev)
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->gc.direction_input = amd_gpio_direction_input;
gpio_dev->gc.direction_output = amd_gpio_direction_output;
......@@ -853,6 +925,9 @@ static struct platform_driver amd_gpio_driver = {
.driver = {
.name = "amd_gpio",
.acpi_match_table = ACPI_PTR(amd_gpio_acpi_match),
#ifdef CONFIG_PM_SLEEP
.pm = &amd_gpio_pm_ops,
#endif
},
.probe = amd_gpio_probe,
.remove = amd_gpio_remove,
......
......@@ -97,6 +97,7 @@ struct amd_gpio {
unsigned int hwbank_num;
struct resource *res;
struct platform_device *pdev;
u32 *saved_regs;
};
/* KERNCZ configuration*/
......
......@@ -4,6 +4,8 @@
config PINCTRL_SPRD
bool "Spreadtrum pinctrl driver"
depends on OF
depends on ARCH_SPRD || COMPILE_TEST
select PINMUX
select PINCONF
select GENERIC_PINCONF
......@@ -13,5 +15,6 @@ config PINCTRL_SPRD
config PINCTRL_SPRD_SC9860
bool "Spreadtrum SC9860 pinctrl driver"
depends on PINCTRL_SPRD
help
Say Y here to enable Spreadtrum SC9860 pinctrl driver
......@@ -353,13 +353,13 @@ static const struct pinctrl_ops sprd_pctrl_ops = {
.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;
}
const char *sprd_pmx_get_function_name(struct pinctrl_dev *pctldev,
unsigned int selector)
static const char *sprd_pmx_get_function_name(struct pinctrl_dev *pctldev,
unsigned int selector)
{
switch (selector) {
case PIN_FUNC_1:
......@@ -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,
unsigned int selector,
const char * const **groups,
unsigned int * const num_groups)
static int sprd_pmx_get_function_groups(struct pinctrl_dev *pctldev,
unsigned int selector,
const char * const **groups,
unsigned int * const num_groups)
{
struct sprd_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
struct sprd_pinctrl_soc_info *info = pctl->info;
......@@ -400,7 +400,7 @@ static int sprd_pmx_set_mux(struct pinctrl_dev *pctldev,
unsigned long reg;
unsigned int val = 0;
if (group_selector > info->ngroups)
if (group_selector >= info->ngroups)
return -EINVAL;
switch (func_selector) {
......@@ -734,7 +734,7 @@ static int sprd_pinconf_group_get(struct pinctrl_dev *pctldev,
struct sprd_pin_group *grp;
unsigned int pin_id;
if (selector > info->ngroups)
if (selector >= info->ngroups)
return -EINVAL;
grp = &info->groups[selector];
......@@ -753,7 +753,7 @@ static int sprd_pinconf_group_set(struct pinctrl_dev *pctldev,
struct sprd_pin_group *grp;
int ret, i;
if (selector > info->ngroups)
if (selector >= info->ngroups)
return -EINVAL;
grp = &info->groups[selector];
......@@ -813,7 +813,7 @@ static void sprd_pinconf_group_dbg_show(struct pinctrl_dev *pctldev,
const char *name;
int i, ret;
if (selector > info->ngroups)
if (selector >= info->ngroups)
return;
grp = &info->groups[selector];
......@@ -1100,12 +1100,16 @@ int sprd_pinctrl_remove(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;
pinctl = devm_pinctrl_get(&pdev->dev);
if (IS_ERR(pinctl))
return;
state = pinctrl_lookup_state(pinctl, "shutdown");
if (!IS_ERR(state))
pinctrl_select_state(pinctl, state);
if (IS_ERR(state))
return;
pinctrl_select_state(pinctl, state);
}
MODULE_DESCRIPTION("SPREADTRUM Pin Controller Driver");
......
......@@ -17,7 +17,7 @@
#define __PINCTRL_UNIPHIER_H__
#include <linux/bitops.h>
#include <linux/bug.h>
#include <linux/build_bug.h>
#include <linux/kernel.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