summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/gpio/gpio-nomadik.c2
-rw-r--r--drivers/pinctrl/nomadik/pinctrl-nomadik.c54
2 files changed, 37 insertions, 19 deletions
diff --git a/drivers/gpio/gpio-nomadik.c b/drivers/gpio/gpio-nomadik.c
index fb821a9b6c5f..b7d76cc901dc 100644
--- a/drivers/gpio/gpio-nomadik.c
+++ b/drivers/gpio/gpio-nomadik.c
@@ -519,7 +519,7 @@ struct nmk_gpio_chip *nmk_gpio_populate_chip(struct device_node *np,
nmk_chip->bank = id;
chip = &nmk_chip->chip;
- chip->base = id * NMK_GPIO_PER_CHIP;
+ chip->base = -1;
chip->ngpio = NMK_GPIO_PER_CHIP;
chip->label = dev_name(gpio_dev);
chip->parent = gpio_dev;
diff --git a/drivers/pinctrl/nomadik/pinctrl-nomadik.c b/drivers/pinctrl/nomadik/pinctrl-nomadik.c
index b74378302229..5633f0ec2715 100644
--- a/drivers/pinctrl/nomadik/pinctrl-nomadik.c
+++ b/drivers/pinctrl/nomadik/pinctrl-nomadik.c
@@ -531,25 +531,33 @@ static int nmk_get_group_pins(struct pinctrl_dev *pctldev, unsigned int selector
return 0;
}
-static struct nmk_gpio_chip *find_nmk_gpio_from_pin(unsigned int pin)
+/* This makes the mapping from pin number to a GPIO chip. We also return the pin
+ * offset in the GPIO chip for convenience (and to avoid a second loop).
+ */
+static struct nmk_gpio_chip *find_nmk_gpio_from_pin(unsigned int pin,
+ unsigned int *offset)
{
- int i;
+ int i, j = 0;
struct nmk_gpio_chip *nmk_gpio;
+ /* We assume that pins are allocated in bank order. */
for (i = 0; i < NMK_MAX_BANKS; i++) {
nmk_gpio = nmk_gpio_chips[i];
if (!nmk_gpio)
continue;
- if (pin >= nmk_gpio->chip.base &&
- pin < nmk_gpio->chip.base + nmk_gpio->chip.ngpio)
+ if (pin >= j && pin < j + nmk_gpio->chip.ngpio) {
+ if (offset)
+ *offset = pin - j;
return nmk_gpio;
+ }
+ j += nmk_gpio->chip.ngpio;
}
return NULL;
}
static struct gpio_chip *find_gc_from_pin(unsigned int pin)
{
- struct nmk_gpio_chip *nmk_gpio = find_nmk_gpio_from_pin(pin);
+ struct nmk_gpio_chip *nmk_gpio = find_nmk_gpio_from_pin(pin, NULL);
if (nmk_gpio)
return &nmk_gpio->chip;
@@ -905,8 +913,18 @@ static int nmk_pmx_set(struct pinctrl_dev *pctldev, unsigned int function,
* switching to the ALT C function.
*/
for (i = 0; i < g->grp.npins; i++) {
- unsigned int bit = g->grp.pins[i] % NMK_GPIO_PER_CHIP;
- slpm[g->grp.pins[i] / NMK_GPIO_PER_CHIP] &= ~BIT(bit);
+ struct nmk_gpio_chip *nmk_chip;
+ unsigned int bit;
+
+ nmk_chip = find_nmk_gpio_from_pin(g->grp.pins[i], &bit);
+ if (!nmk_chip) {
+ dev_err(npct->dev,
+ "invalid pin offset %d in group %s at index %d\n",
+ g->grp.pins[i], g->grp.name, i);
+ goto out_pre_slpm_init;
+ }
+
+ slpm[nmk_chip->bank] &= ~BIT(bit);
}
nmk_gpio_glitch_slpm_init(slpm);
}
@@ -915,7 +933,7 @@ static int nmk_pmx_set(struct pinctrl_dev *pctldev, unsigned int function,
struct nmk_gpio_chip *nmk_chip;
unsigned int bit;
- nmk_chip = find_nmk_gpio_from_pin(g->grp.pins[i]);
+ nmk_chip = find_nmk_gpio_from_pin(g->grp.pins[i], &bit);
if (!nmk_chip) {
dev_err(npct->dev,
"invalid pin offset %d in group %s at index %d\n",
@@ -926,7 +944,6 @@ static int nmk_pmx_set(struct pinctrl_dev *pctldev, unsigned int function,
g->grp.pins[i], g->altsetting);
clk_enable(nmk_chip->clk);
- bit = g->grp.pins[i] % NMK_GPIO_PER_CHIP;
/*
* If the pin is switching to altfunc, and there was an
* interrupt installed on it which has been lazy disabled,
@@ -957,17 +974,18 @@ static int nmk_pmx_set(struct pinctrl_dev *pctldev, unsigned int function,
ret = 0;
out_glitch:
- if (glitch) {
+ if (glitch)
nmk_gpio_glitch_slpm_restore(slpm);
+out_pre_slpm_init:
+ if (glitch)
spin_unlock_irqrestore(&nmk_gpio_slpm_lock, flags);
- }
return ret;
}
static int nmk_gpio_request_enable(struct pinctrl_dev *pctldev,
struct pinctrl_gpio_range *range,
- unsigned int offset)
+ unsigned int pin)
{
struct nmk_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev);
struct nmk_gpio_chip *nmk_chip;
@@ -985,10 +1003,11 @@ static int nmk_gpio_request_enable(struct pinctrl_dev *pctldev,
chip = range->gc;
nmk_chip = gpiochip_get_data(chip);
- dev_dbg(npct->dev, "enable pin %u as GPIO\n", offset);
+ dev_dbg(npct->dev, "enable pin %u as GPIO\n", pin);
+
+ find_nmk_gpio_from_pin(pin, &bit);
clk_enable(nmk_chip->clk);
- bit = offset % NMK_GPIO_PER_CHIP;
/* There is no glitch when converting any pin to GPIO */
__nmk_gpio_set_mode(nmk_chip, bit, NMK_GPIO_ALT_GPIO);
clk_disable(nmk_chip->clk);
@@ -998,11 +1017,11 @@ static int nmk_gpio_request_enable(struct pinctrl_dev *pctldev,
static void nmk_gpio_disable_free(struct pinctrl_dev *pctldev,
struct pinctrl_gpio_range *range,
- unsigned int offset)
+ unsigned int pin)
{
struct nmk_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev);
- dev_dbg(npct->dev, "disable pin %u as GPIO\n", offset);
+ dev_dbg(npct->dev, "disable pin %u as GPIO\n", pin);
/* Set the pin to some default state, GPIO is usually default */
}
@@ -1043,7 +1062,7 @@ static int nmk_pin_config_set(struct pinctrl_dev *pctldev, unsigned int pin,
int pull, slpm, output, val, i;
bool lowemi, gpiomode, sleep;
- nmk_chip = find_nmk_gpio_from_pin(pin);
+ nmk_chip = find_nmk_gpio_from_pin(pin, &bit);
if (!nmk_chip) {
dev_err(npct->dev,
"invalid pin offset %d\n", pin);
@@ -1101,7 +1120,6 @@ static int nmk_pin_config_set(struct pinctrl_dev *pctldev, unsigned int pin,
lowemi ? "on" : "off");
clk_enable(nmk_chip->clk);
- bit = pin % NMK_GPIO_PER_CHIP;
if (gpiomode)
/* No glitch when going to GPIO mode */
__nmk_gpio_set_mode(nmk_chip, bit, NMK_GPIO_ALT_GPIO);