summaryrefslogtreecommitdiff
path: root/drivers/pinctrl/nomadik/pinctrl-abx500.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pinctrl/nomadik/pinctrl-abx500.c')
-rw-r--r--drivers/pinctrl/nomadik/pinctrl-abx500.c306
1 files changed, 65 insertions, 241 deletions
diff --git a/drivers/pinctrl/nomadik/pinctrl-abx500.c b/drivers/pinctrl/nomadik/pinctrl-abx500.c
index f95001bc1d58..fc7ebeda8440 100644
--- a/drivers/pinctrl/nomadik/pinctrl-abx500.c
+++ b/drivers/pinctrl/nomadik/pinctrl-abx500.c
@@ -1,50 +1,45 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) ST-Ericsson SA 2013
*
* Author: Patrice Chotard <patrice.chotard@st.com>
- * License terms: GNU General Public License (GPL) version 2
*
* Driver allows to use AxB5xx unused pins to be used as GPIO
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
*/
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/slab.h>
-#include <linux/init.h>
+
+#include <linux/bitops.h>
+#include <linux/cleanup.h>
#include <linux/err.h>
+#include <linux/gpio/driver.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/kernel.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
-#include <linux/gpio.h>
-#include <linux/irq.h>
-#include <linux/irqdomain.h>
-#include <linux/interrupt.h>
-#include <linux/bitops.h>
+#include <linux/property.h>
+#include <linux/seq_file.h>
+#include <linux/slab.h>
+#include <linux/string_choices.h>
+#include <linux/types.h>
+
#include <linux/mfd/abx500.h>
#include <linux/mfd/abx500/ab8500.h>
-#include <linux/pinctrl/pinctrl.h>
+
#include <linux/pinctrl/consumer.h>
-#include <linux/pinctrl/pinmux.h>
-#include <linux/pinctrl/pinconf.h>
-#include <linux/pinctrl/pinconf-generic.h>
#include <linux/pinctrl/machine.h>
+#include <linux/pinctrl/pinconf-generic.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
-#include "pinctrl-abx500.h"
#include "../core.h"
#include "../pinconf.h"
#include "../pinctrl-utils.h"
-/*
- * The AB9540 and AB8540 GPIO support are extended versions
- * of the AB8500 GPIO support.
- * The AB9540 supports an additional (7th) register so that
- * more GPIO may be configured and used.
- * The AB8540 supports 4 new gpios (GPIOx_VBAT) that have
- * internal pull-up and pull-down capabilities.
- */
+#include "pinctrl-abx500.h"
/*
* GPIO registers offset
@@ -56,7 +51,6 @@
#define AB8500_GPIO_SEL4_REG 0x03
#define AB8500_GPIO_SEL5_REG 0x04
#define AB8500_GPIO_SEL6_REG 0x05
-#define AB9540_GPIO_SEL7_REG 0x06
#define AB8500_GPIO_DIR1_REG 0x10
#define AB8500_GPIO_DIR2_REG 0x11
@@ -64,7 +58,6 @@
#define AB8500_GPIO_DIR4_REG 0x13
#define AB8500_GPIO_DIR5_REG 0x14
#define AB8500_GPIO_DIR6_REG 0x15
-#define AB9540_GPIO_DIR7_REG 0x16
#define AB8500_GPIO_OUT1_REG 0x20
#define AB8500_GPIO_OUT2_REG 0x21
@@ -72,7 +65,6 @@
#define AB8500_GPIO_OUT4_REG 0x23
#define AB8500_GPIO_OUT5_REG 0x24
#define AB8500_GPIO_OUT6_REG 0x25
-#define AB9540_GPIO_OUT7_REG 0x26
#define AB8500_GPIO_PUD1_REG 0x30
#define AB8500_GPIO_PUD2_REG 0x31
@@ -80,7 +72,6 @@
#define AB8500_GPIO_PUD4_REG 0x33
#define AB8500_GPIO_PUD5_REG 0x34
#define AB8500_GPIO_PUD6_REG 0x35
-#define AB9540_GPIO_PUD7_REG 0x36
#define AB8500_GPIO_IN1_REG 0x40
#define AB8500_GPIO_IN2_REG 0x41
@@ -88,14 +79,7 @@
#define AB8500_GPIO_IN4_REG 0x43
#define AB8500_GPIO_IN5_REG 0x44
#define AB8500_GPIO_IN6_REG 0x45
-#define AB9540_GPIO_IN7_REG 0x46
-#define AB8540_GPIO_VINSEL_REG 0x47
-#define AB8540_GPIO_PULL_UPDOWN_REG 0x48
#define AB8500_GPIO_ALTFUN_REG 0x50
-#define AB8540_GPIO_PULL_UPDOWN_MASK 0x03
-#define AB8540_GPIO_VINSEL_MASK 0x03
-#define AB8540_GPIOX_VBAT_START 51
-#define AB8540_GPIOX_VBAT_END 54
#define ABX500_GPIO_INPUT 0
#define ABX500_GPIO_OUTPUT 1
@@ -121,15 +105,16 @@ static int abx500_gpio_get_bit(struct gpio_chip *chip, u8 reg,
reg += offset / 8;
ret = abx500_get_register_interruptible(pct->dev,
AB8500_MISC, reg, &val);
-
- *bit = !!(val & BIT(pos));
-
- if (ret < 0)
+ if (ret < 0) {
dev_err(pct->dev,
"%s read reg =%x, offset=%x failed (%d)\n",
__func__, reg, offset, ret);
+ return ret;
+ }
- return ret;
+ *bit = !!(val & BIT(pos));
+
+ return 0;
}
static int abx500_gpio_set_bits(struct gpio_chip *chip, u8 reg,
@@ -182,96 +167,10 @@ out:
return bit;
}
-static void abx500_gpio_set(struct gpio_chip *chip, unsigned offset, int val)
-{
- struct abx500_pinctrl *pct = gpiochip_get_data(chip);
- int ret;
-
- ret = abx500_gpio_set_bits(chip, AB8500_GPIO_OUT1_REG, offset, val);
- if (ret < 0)
- dev_err(pct->dev, "%s write failed (%d)\n", __func__, ret);
-}
-
-#ifdef CONFIG_DEBUG_FS
-static int abx500_get_pull_updown(struct abx500_pinctrl *pct, int offset,
- enum abx500_gpio_pull_updown *pull_updown)
-{
- u8 pos;
- u8 val;
- int ret;
- struct pullud *pullud;
-
- if (!pct->soc->pullud) {
- dev_err(pct->dev, "%s AB chip doesn't support pull up/down feature",
- __func__);
- ret = -EPERM;
- goto out;
- }
-
- pullud = pct->soc->pullud;
-
- if ((offset < pullud->first_pin)
- || (offset > pullud->last_pin)) {
- ret = -EINVAL;
- goto out;
- }
-
- ret = abx500_get_register_interruptible(pct->dev,
- AB8500_MISC, AB8540_GPIO_PULL_UPDOWN_REG, &val);
-
- pos = (offset - pullud->first_pin) << 1;
- *pull_updown = (val >> pos) & AB8540_GPIO_PULL_UPDOWN_MASK;
-
-out:
- if (ret < 0)
- dev_err(pct->dev, "%s failed (%d)\n", __func__, ret);
-
- return ret;
-}
-#endif
-
-static int abx500_set_pull_updown(struct abx500_pinctrl *pct,
- int offset, enum abx500_gpio_pull_updown val)
-{
- u8 pos;
- int ret;
- struct pullud *pullud;
-
- if (!pct->soc->pullud) {
- dev_err(pct->dev, "%s AB chip doesn't support pull up/down feature",
- __func__);
- ret = -EPERM;
- goto out;
- }
-
- pullud = pct->soc->pullud;
-
- if ((offset < pullud->first_pin)
- || (offset > pullud->last_pin)) {
- ret = -EINVAL;
- goto out;
- }
- pos = (offset - pullud->first_pin) << 1;
-
- ret = abx500_mask_and_set_register_interruptible(pct->dev,
- AB8500_MISC, AB8540_GPIO_PULL_UPDOWN_REG,
- AB8540_GPIO_PULL_UPDOWN_MASK << pos, val << pos);
-
-out:
- if (ret < 0)
- dev_err(pct->dev, "%s failed (%d)\n", __func__, ret);
-
- return ret;
-}
-
-static bool abx500_pullud_supported(struct gpio_chip *chip, unsigned gpio)
+static int abx500_gpio_set(struct gpio_chip *chip, unsigned int offset,
+ int val)
{
- struct abx500_pinctrl *pct = gpiochip_get_data(chip);
- struct pullud *pullud = pct->soc->pullud;
-
- return (pullud &&
- gpio >= pullud->first_pin &&
- gpio <= pullud->last_pin);
+ return abx500_gpio_set_bits(chip, AB8500_GPIO_OUT1_REG, offset, val);
}
static int abx500_gpio_direction_output(struct gpio_chip *chip,
@@ -279,7 +178,6 @@ static int abx500_gpio_direction_output(struct gpio_chip *chip,
int val)
{
struct abx500_pinctrl *pct = gpiochip_get_data(chip);
- unsigned gpio;
int ret;
/* set direction as output */
@@ -295,16 +193,7 @@ static int abx500_gpio_direction_output(struct gpio_chip *chip,
AB8500_GPIO_PUD1_REG,
offset,
ABX500_GPIO_PULL_NONE);
- if (ret < 0)
- goto out;
- /* if supported, disable both pull down and pull up */
- gpio = offset + 1;
- if (abx500_pullud_supported(chip, gpio)) {
- ret = abx500_set_pull_updown(pct,
- gpio,
- ABX500_GPIO_PULL_NONE);
- }
out:
if (ret < 0) {
dev_err(pct->dev, "%s failed (%d)\n", __func__, ret);
@@ -557,21 +446,17 @@ out:
return ret;
}
-#include <linux/seq_file.h>
-
static void abx500_gpio_dbg_show_one(struct seq_file *s,
struct pinctrl_dev *pctldev,
struct gpio_chip *chip,
unsigned offset, unsigned gpio)
{
struct abx500_pinctrl *pct = pinctrl_dev_get_drvdata(pctldev);
- const char *label = gpiochip_is_requested(chip, offset - 1);
u8 gpio_offset = offset - 1;
int mode = -1;
bool is_out;
bool pd;
- enum abx500_gpio_pull_updown pud = 0;
- int ret;
+ int ret = -ENOMEM;
const char *modes[] = {
[ABX500_DEFAULT] = "default",
@@ -587,6 +472,10 @@ static void abx500_gpio_dbg_show_one(struct seq_file *s,
[ABX500_GPIO_PULL_UP] = "pull up",
};
+ char *label __free(kfree) = gpiochip_dup_line_label(chip, offset - 1);
+ if (IS_ERR(label))
+ goto out;
+
ret = abx500_gpio_get_bit(chip, AB8500_GPIO_DIR1_REG,
gpio_offset, &is_out);
if (ret < 0)
@@ -597,22 +486,14 @@ static void abx500_gpio_dbg_show_one(struct seq_file *s,
is_out ? "out" : "in ");
if (!is_out) {
- if (abx500_pullud_supported(chip, offset)) {
- ret = abx500_get_pull_updown(pct, offset, &pud);
- if (ret < 0)
- goto out;
-
- seq_printf(s, " %-9s", pull_up_down[pud]);
- } else {
- ret = abx500_gpio_get_bit(chip, AB8500_GPIO_PUD1_REG,
- gpio_offset, &pd);
- if (ret < 0)
- goto out;
+ ret = abx500_gpio_get_bit(chip, AB8500_GPIO_PUD1_REG,
+ gpio_offset, &pd);
+ if (ret < 0)
+ goto out;
- seq_printf(s, " %-9s", pull_up_down[pd]);
- }
+ seq_printf(s, " %-9s", pull_up_down[pd]);
} else
- seq_printf(s, " %-9s", chip->get(chip, offset) ? "hi" : "lo");
+ seq_printf(s, " %-9s", str_hi_lo(chip->get(chip, offset)));
mode = abx500_get_mode(pctldev, chip, offset);
@@ -633,7 +514,7 @@ static void abx500_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
for (i = 0; i < chip->ngpio; i++, gpio++) {
/* On AB8500, there is no GPIO0, the first is the GPIO 1 */
abx500_gpio_dbg_show_one(s, pctldev, chip, i + 1, gpio);
- seq_printf(s, "\n");
+ seq_putc(s, '\n');
}
}
@@ -647,7 +528,7 @@ static inline void abx500_gpio_dbg_show_one(struct seq_file *s,
#define abx500_gpio_dbg_show NULL
#endif
-static struct gpio_chip abx500gpio_chip = {
+static const struct gpio_chip abx500gpio_chip = {
.label = "abx500-gpio",
.owner = THIS_MODULE,
.request = gpiochip_generic_request,
@@ -832,8 +713,7 @@ static int abx500_dt_add_map_configs(struct pinctrl_map **map,
if (*num_maps == *reserved_maps)
return -ENOSPC;
- dup_configs = kmemdup(configs, num_configs * sizeof(*dup_configs),
- GFP_KERNEL);
+ dup_configs = kmemdup_array(configs, num_configs, sizeof(*dup_configs), GFP_KERNEL);
if (!dup_configs)
return -ENOMEM;
@@ -927,14 +807,13 @@ static int abx500_dt_node_to_map(struct pinctrl_dev *pctldev,
struct pinctrl_map **map, unsigned *num_maps)
{
unsigned reserved_maps;
- struct device_node *np;
int ret;
reserved_maps = 0;
*map = NULL;
*num_maps = 0;
- for_each_child_of_node(np_config, np) {
+ for_each_child_of_node_scoped(np_config, np) {
ret = abx500_dt_subnode_to_map(pctldev, np, map,
&reserved_maps, num_maps);
if (ret < 0) {
@@ -981,9 +860,9 @@ static int abx500_pin_config_set(struct pinctrl_dev *pctldev,
dev_dbg(chip->parent, "pin %d [%#lx]: %s %s\n",
pin, configs[i],
- (param == PIN_CONFIG_OUTPUT) ? "output " : "input",
- (param == PIN_CONFIG_OUTPUT) ?
- (argument ? "high" : "low") :
+ (param == PIN_CONFIG_LEVEL) ? "output " : "input",
+ (param == PIN_CONFIG_LEVEL) ?
+ str_high_low(argument) :
(argument ? "pull up" : "pull down"));
/* on ABx500, there is no GPIO0, so adjust the offset */
@@ -994,23 +873,11 @@ static int abx500_pin_config_set(struct pinctrl_dev *pctldev,
ret = abx500_gpio_direction_input(chip, offset);
if (ret < 0)
goto out;
- /*
- * Some chips only support pull down, while some
- * actually support both pull up and pull down. Such
- * chips have a "pullud" range specified for the pins
- * that support both features. If the pin is not
- * within that range, we fall back to the old bit set
- * that only support pull down.
- */
- if (abx500_pullud_supported(chip, pin))
- ret = abx500_set_pull_updown(pct,
- pin,
- ABX500_GPIO_PULL_NONE);
- else
- /* Chip only supports pull down */
- ret = abx500_gpio_set_bits(chip,
- AB8500_GPIO_PUD1_REG, offset,
- ABX500_GPIO_PULL_NONE);
+
+ /* Chip only supports pull down */
+ ret = abx500_gpio_set_bits(chip,
+ AB8500_GPIO_PUD1_REG, offset,
+ ABX500_GPIO_PULL_NONE);
break;
case PIN_CONFIG_BIAS_PULL_DOWN:
@@ -1020,25 +887,13 @@ static int abx500_pin_config_set(struct pinctrl_dev *pctldev,
/*
* if argument = 1 set the pull down
* else clear the pull down
- * Some chips only support pull down, while some
- * actually support both pull up and pull down. Such
- * chips have a "pullud" range specified for the pins
- * that support both features. If the pin is not
- * within that range, we fall back to the old bit set
- * that only support pull down.
+ * Chip only supports pull down
*/
- if (abx500_pullud_supported(chip, pin))
- ret = abx500_set_pull_updown(pct,
- pin,
- argument ? ABX500_GPIO_PULL_DOWN :
- ABX500_GPIO_PULL_NONE);
- else
- /* Chip only supports pull down */
- ret = abx500_gpio_set_bits(chip,
- AB8500_GPIO_PUD1_REG,
- offset,
- argument ? ABX500_GPIO_PULL_DOWN :
- ABX500_GPIO_PULL_NONE);
+ ret = abx500_gpio_set_bits(chip,
+ AB8500_GPIO_PUD1_REG,
+ offset,
+ argument ? ABX500_GPIO_PULL_DOWN :
+ ABX500_GPIO_PULL_NONE);
break;
case PIN_CONFIG_BIAS_PULL_UP:
@@ -1050,21 +905,9 @@ static int abx500_pin_config_set(struct pinctrl_dev *pctldev,
* else clear the pull up
*/
ret = abx500_gpio_direction_input(chip, offset);
- /*
- * Some chips only support pull down, while some
- * actually support both pull up and pull down. Such
- * chips have a "pullud" range specified for the pins
- * that support both features. If the pin is not
- * within that range, do nothing
- */
- if (abx500_pullud_supported(chip, pin))
- ret = abx500_set_pull_updown(pct,
- pin,
- argument ? ABX500_GPIO_PULL_UP :
- ABX500_GPIO_PULL_NONE);
break;
- case PIN_CONFIG_OUTPUT:
+ case PIN_CONFIG_LEVEL:
ret = abx500_gpio_direction_output(chip, offset,
argument);
break;
@@ -1136,15 +979,12 @@ static int abx500_get_gpio_num(struct abx500_pinctrl_soc_data *soc)
static const struct of_device_id abx500_gpio_match[] = {
{ .compatible = "stericsson,ab8500-gpio", .data = (void *)PINCTRL_AB8500, },
{ .compatible = "stericsson,ab8505-gpio", .data = (void *)PINCTRL_AB8505, },
- { .compatible = "stericsson,ab8540-gpio", .data = (void *)PINCTRL_AB8540, },
- { .compatible = "stericsson,ab9540-gpio", .data = (void *)PINCTRL_AB9540, },
{ }
};
static int abx500_gpio_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
- const struct of_device_id *match;
struct abx500_pinctrl *pct;
unsigned int id = -1;
int ret;
@@ -1155,13 +995,9 @@ static int abx500_gpio_probe(struct platform_device *pdev)
return -ENODEV;
}
- pct = devm_kzalloc(&pdev->dev, sizeof(struct abx500_pinctrl),
- GFP_KERNEL);
- if (pct == NULL) {
- dev_err(&pdev->dev,
- "failed to allocate memory for pct\n");
+ pct = devm_kzalloc(&pdev->dev, sizeof(*pct), GFP_KERNEL);
+ if (!pct)
return -ENOMEM;
- }
pct->dev = &pdev->dev;
pct->parent = dev_get_drvdata(pdev->dev.parent);
@@ -1169,24 +1005,13 @@ static int abx500_gpio_probe(struct platform_device *pdev)
pct->chip.parent = &pdev->dev;
pct->chip.base = -1; /* Dynamic allocation */
- match = of_match_device(abx500_gpio_match, &pdev->dev);
- if (!match) {
- dev_err(&pdev->dev, "gpio dt not matching\n");
- return -ENODEV;
- }
- id = (unsigned long)match->data;
+ id = (unsigned long)device_get_match_data(&pdev->dev);
/* Poke in other ASIC variants here */
switch (id) {
case PINCTRL_AB8500:
abx500_pinctrl_ab8500_init(&pct->soc);
break;
- case PINCTRL_AB8540:
- abx500_pinctrl_ab8540_init(&pct->soc);
- break;
- case PINCTRL_AB9540:
- abx500_pinctrl_ab9540_init(&pct->soc);
- break;
case PINCTRL_AB8505:
abx500_pinctrl_ab8505_init(&pct->soc);
break;
@@ -1248,12 +1073,11 @@ out_rem_chip:
* abx500_gpio_remove() - remove Ab8500-gpio driver
* @pdev: Platform device registered
*/
-static int abx500_gpio_remove(struct platform_device *pdev)
+static void abx500_gpio_remove(struct platform_device *pdev)
{
struct abx500_pinctrl *pct = platform_get_drvdata(pdev);
gpiochip_remove(&pct->chip);
- return 0;
}
static struct platform_driver abx500_gpio_driver = {