pinctrl: rp1: Implement RaspberryPi RP1 gpio support

The RP1 is an MFD supporting a gpio controller and /pinmux/pinctrl.
Add minimum support for the gpio only portion. The driver is in
pinctrl folder since upcoming patches will add the pinmux/pinctrl
support where the gpio part can be seen as an addition.

Signed-off-by: Andrea della Porta <andrea.porta@suse.com>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Reviewed-by: Stefan Wahren <wahrenst@gmx.net>
Link: https://lore.kernel.org/r/20250529135052.28398-5-andrea.porta@suse.com
Signed-off-by: Florian Fainelli <florian.fainelli@broadcom.com>
This commit is contained in:
Andrea della Porta
2025-06-16 11:50:34 -07:00
committed by Florian Fainelli
parent 6486341721
commit 4732f079cd
3 changed files with 802 additions and 0 deletions
+11
View File
@@ -624,6 +624,17 @@ config PINCTRL_MLXBF3
each pin. This driver can also be built as a module called
pinctrl-mlxbf3.
config PINCTRL_RP1
tristate "Pinctrl driver for RP1"
depends on MISC_RP1
default MISC_RP1
select PINMUX
select PINCONF
select GENERIC_PINCONF
help
Enable the gpio and pinctrl/mux driver for RaspberryPi RP1
multi function device.
source "drivers/pinctrl/actions/Kconfig"
source "drivers/pinctrl/aspeed/Kconfig"
source "drivers/pinctrl/bcm/Kconfig"
+1
View File
@@ -49,6 +49,7 @@ obj-$(CONFIG_PINCTRL_PIC32) += pinctrl-pic32.o
obj-$(CONFIG_PINCTRL_PISTACHIO) += pinctrl-pistachio.o
obj-$(CONFIG_PINCTRL_RK805) += pinctrl-rk805.o
obj-$(CONFIG_PINCTRL_ROCKCHIP) += pinctrl-rockchip.o
obj-$(CONFIG_PINCTRL_RP1) += pinctrl-rp1.o
obj-$(CONFIG_PINCTRL_SCMI) += pinctrl-scmi.o
obj-$(CONFIG_PINCTRL_SINGLE) += pinctrl-single.o
obj-$(CONFIG_PINCTRL_ST) += pinctrl-st.o
+790
View File
@@ -0,0 +1,790 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Driver for Raspberry Pi RP1 GPIO unit
*
* Copyright (C) 2023 Raspberry Pi Ltd.
*
* This driver is inspired by:
* pinctrl-bcm2835.c, please see original file for copyright information
*/
#include <linux/gpio/driver.h>
#include <linux/of_irq.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#define MODULE_NAME "pinctrl-rp1"
#define RP1_NUM_GPIOS 54
#define RP1_NUM_BANKS 3
#define RP1_INT_EDGE_FALLING BIT(0)
#define RP1_INT_EDGE_RISING BIT(1)
#define RP1_INT_LEVEL_LOW BIT(2)
#define RP1_INT_LEVEL_HIGH BIT(3)
#define RP1_INT_MASK GENMASK(3, 0)
#define RP1_INT_EDGE_BOTH (RP1_INT_EDGE_FALLING | \
RP1_INT_EDGE_RISING)
#define RP1_FSEL_COUNT 9
#define RP1_FSEL_ALT0 0x00
#define RP1_FSEL_GPIO 0x05
#define RP1_FSEL_NONE 0x09
#define RP1_FSEL_NONE_HW 0x1f
#define RP1_PAD_DRIVE_2MA 0x0
#define RP1_PAD_DRIVE_4MA 0x1
#define RP1_PAD_DRIVE_8MA 0x2
#define RP1_PAD_DRIVE_12MA 0x3
enum {
RP1_PUD_OFF = 0,
RP1_PUD_DOWN = 1,
RP1_PUD_UP = 2,
};
enum {
RP1_DIR_OUTPUT = 0,
RP1_DIR_INPUT = 1,
};
enum {
RP1_OUTOVER_PERI = 0,
RP1_OUTOVER_INVPERI = 1,
RP1_OUTOVER_LOW = 2,
RP1_OUTOVER_HIGH = 3,
};
enum {
RP1_OEOVER_PERI = 0,
RP1_OEOVER_INVPERI = 1,
RP1_OEOVER_DISABLE = 2,
RP1_OEOVER_ENABLE = 3,
};
enum {
RP1_INOVER_PERI = 0,
RP1_INOVER_INVPERI = 1,
RP1_INOVER_LOW = 2,
RP1_INOVER_HIGH = 3,
};
enum {
RP1_GPIO_CTRL_IRQRESET_SET = 0,
RP1_GPIO_CTRL_INT_CLR = 1,
RP1_GPIO_CTRL_INT_SET = 2,
RP1_GPIO_CTRL_OEOVER = 3,
RP1_GPIO_CTRL_FUNCSEL = 4,
RP1_GPIO_CTRL_OUTOVER = 5,
RP1_GPIO_CTRL = 6,
};
enum {
RP1_INTE_SET = 0,
RP1_INTE_CLR = 1,
};
enum {
RP1_RIO_OUT_SET = 0,
RP1_RIO_OUT_CLR = 1,
RP1_RIO_OE = 2,
RP1_RIO_OE_SET = 3,
RP1_RIO_OE_CLR = 4,
RP1_RIO_IN = 5,
};
enum {
RP1_PAD_SLEWFAST = 0,
RP1_PAD_SCHMITT = 1,
RP1_PAD_PULL = 2,
RP1_PAD_DRIVE = 3,
RP1_PAD_IN_ENABLE = 4,
RP1_PAD_OUT_DISABLE = 5,
};
static const struct reg_field rp1_gpio_fields[] = {
[RP1_GPIO_CTRL_IRQRESET_SET] = REG_FIELD(0x2004, 28, 28),
[RP1_GPIO_CTRL_INT_CLR] = REG_FIELD(0x3004, 20, 23),
[RP1_GPIO_CTRL_INT_SET] = REG_FIELD(0x2004, 20, 23),
[RP1_GPIO_CTRL_OEOVER] = REG_FIELD(0x0004, 14, 15),
[RP1_GPIO_CTRL_FUNCSEL] = REG_FIELD(0x0004, 0, 4),
[RP1_GPIO_CTRL_OUTOVER] = REG_FIELD(0x0004, 12, 13),
[RP1_GPIO_CTRL] = REG_FIELD(0x0004, 0, 31),
};
static const struct reg_field rp1_inte_fields[] = {
[RP1_INTE_SET] = REG_FIELD(0x2000, 0, 0),
[RP1_INTE_CLR] = REG_FIELD(0x3000, 0, 0),
};
static const struct reg_field rp1_rio_fields[] = {
[RP1_RIO_OUT_SET] = REG_FIELD(0x2000, 0, 0),
[RP1_RIO_OUT_CLR] = REG_FIELD(0x3000, 0, 0),
[RP1_RIO_OE] = REG_FIELD(0x0004, 0, 0),
[RP1_RIO_OE_SET] = REG_FIELD(0x2004, 0, 0),
[RP1_RIO_OE_CLR] = REG_FIELD(0x3004, 0, 0),
[RP1_RIO_IN] = REG_FIELD(0x0008, 0, 0),
};
static const struct reg_field rp1_pad_fields[] = {
[RP1_PAD_SLEWFAST] = REG_FIELD(0, 0, 0),
[RP1_PAD_SCHMITT] = REG_FIELD(0, 1, 1),
[RP1_PAD_PULL] = REG_FIELD(0, 2, 3),
[RP1_PAD_DRIVE] = REG_FIELD(0, 4, 5),
[RP1_PAD_IN_ENABLE] = REG_FIELD(0, 6, 6),
[RP1_PAD_OUT_DISABLE] = REG_FIELD(0, 7, 7),
};
struct rp1_iobank_desc {
int min_gpio;
int num_gpios;
int gpio_offset;
int inte_offset;
int ints_offset;
int rio_offset;
int pads_offset;
};
struct rp1_pin_info {
u8 num;
u8 bank;
u8 offset;
u8 fsel;
u8 irq_type;
struct regmap_field *gpio[ARRAY_SIZE(rp1_gpio_fields)];
struct regmap_field *rio[ARRAY_SIZE(rp1_rio_fields)];
struct regmap_field *inte[ARRAY_SIZE(rp1_inte_fields)];
struct regmap_field *pad[ARRAY_SIZE(rp1_pad_fields)];
};
struct rp1_pinctrl {
struct device *dev;
void __iomem *gpio_base;
void __iomem *rio_base;
void __iomem *pads_base;
int irq[RP1_NUM_BANKS];
struct rp1_pin_info pins[RP1_NUM_GPIOS];
struct pinctrl_dev *pctl_dev;
struct gpio_chip gpio_chip;
struct pinctrl_gpio_range gpio_range;
raw_spinlock_t irq_lock[RP1_NUM_BANKS];
};
static const struct rp1_iobank_desc rp1_iobanks[RP1_NUM_BANKS] = {
/* gpio inte ints rio pads */
{ 0, 28, 0x0000, 0x011c, 0x0124, 0x0000, 0x0004 },
{ 28, 6, 0x4000, 0x411c, 0x4124, 0x4000, 0x4004 },
{ 34, 20, 0x8000, 0x811c, 0x8124, 0x8000, 0x8004 },
};
static int rp1_pinconf_set(struct rp1_pin_info *pin,
unsigned int offset, unsigned long *configs,
unsigned int num_configs);
static struct rp1_pin_info *rp1_get_pin(struct gpio_chip *chip,
unsigned int offset)
{
struct rp1_pinctrl *pc = gpiochip_get_data(chip);
if (pc && offset < RP1_NUM_GPIOS)
return &pc->pins[offset];
return NULL;
}
static void rp1_input_enable(struct rp1_pin_info *pin, int value)
{
regmap_field_write(pin->pad[RP1_PAD_IN_ENABLE], !!value);
}
static void rp1_output_enable(struct rp1_pin_info *pin, int value)
{
regmap_field_write(pin->pad[RP1_PAD_OUT_DISABLE], !value);
}
static u32 rp1_get_fsel(struct rp1_pin_info *pin)
{
u32 oeover, fsel;
regmap_field_read(pin->gpio[RP1_GPIO_CTRL_OEOVER], &oeover);
regmap_field_read(pin->gpio[RP1_GPIO_CTRL_FUNCSEL], &fsel);
if (oeover != RP1_OEOVER_PERI || fsel >= RP1_FSEL_COUNT)
fsel = RP1_FSEL_NONE;
return fsel;
}
static void rp1_set_fsel(struct rp1_pin_info *pin, u32 fsel)
{
if (fsel >= RP1_FSEL_COUNT)
fsel = RP1_FSEL_NONE_HW;
rp1_input_enable(pin, 1);
rp1_output_enable(pin, 1);
if (fsel == RP1_FSEL_NONE) {
regmap_field_write(pin->gpio[RP1_GPIO_CTRL_OEOVER], RP1_OEOVER_DISABLE);
} else {
regmap_field_write(pin->gpio[RP1_GPIO_CTRL_OUTOVER], RP1_OUTOVER_PERI);
regmap_field_write(pin->gpio[RP1_GPIO_CTRL_OEOVER], RP1_OEOVER_PERI);
}
regmap_field_write(pin->gpio[RP1_GPIO_CTRL_FUNCSEL], fsel);
}
static int rp1_get_dir(struct rp1_pin_info *pin)
{
unsigned int val;
regmap_field_read(pin->rio[RP1_RIO_OE], &val);
return !val ? RP1_DIR_INPUT : RP1_DIR_OUTPUT;
}
static void rp1_set_dir(struct rp1_pin_info *pin, bool is_input)
{
int reg = is_input ? RP1_RIO_OE_CLR : RP1_RIO_OE_SET;
regmap_field_write(pin->rio[reg], 1);
}
static int rp1_get_value(struct rp1_pin_info *pin)
{
unsigned int val;
regmap_field_read(pin->rio[RP1_RIO_IN], &val);
return !!val;
}
static void rp1_set_value(struct rp1_pin_info *pin, int value)
{
/* Assume the pin is already an output */
int reg = value ? RP1_RIO_OUT_SET : RP1_RIO_OUT_CLR;
regmap_field_write(pin->rio[reg], 1);
}
static int rp1_gpio_get(struct gpio_chip *chip, unsigned int offset)
{
struct rp1_pin_info *pin = rp1_get_pin(chip, offset);
int ret;
if (!pin)
return -EINVAL;
ret = rp1_get_value(pin);
return ret;
}
static void rp1_gpio_set(struct gpio_chip *chip, unsigned int offset, int value)
{
struct rp1_pin_info *pin = rp1_get_pin(chip, offset);
if (pin)
rp1_set_value(pin, value);
}
static int rp1_gpio_get_direction(struct gpio_chip *chip, unsigned int offset)
{
struct rp1_pin_info *pin = rp1_get_pin(chip, offset);
u32 fsel;
if (!pin)
return -EINVAL;
fsel = rp1_get_fsel(pin);
if (fsel != RP1_FSEL_GPIO)
return -EINVAL;
return (rp1_get_dir(pin) == RP1_DIR_OUTPUT) ?
GPIO_LINE_DIRECTION_OUT :
GPIO_LINE_DIRECTION_IN;
}
static int rp1_gpio_direction_input(struct gpio_chip *chip, unsigned int offset)
{
struct rp1_pin_info *pin = rp1_get_pin(chip, offset);
if (!pin)
return -EINVAL;
rp1_set_dir(pin, RP1_DIR_INPUT);
rp1_set_fsel(pin, RP1_FSEL_GPIO);
return 0;
}
static int rp1_gpio_direction_output(struct gpio_chip *chip, unsigned int offset,
int value)
{
struct rp1_pin_info *pin = rp1_get_pin(chip, offset);
if (!pin)
return -EINVAL;
rp1_set_value(pin, value);
rp1_set_dir(pin, RP1_DIR_OUTPUT);
rp1_set_fsel(pin, RP1_FSEL_GPIO);
return 0;
}
static int rp1_gpio_set_config(struct gpio_chip *chip, unsigned int offset,
unsigned long config)
{
struct rp1_pin_info *pin = rp1_get_pin(chip, offset);
unsigned long configs[] = { config };
return rp1_pinconf_set(pin, offset, configs,
ARRAY_SIZE(configs));
}
static const struct gpio_chip rp1_gpio_chip = {
.label = MODULE_NAME,
.owner = THIS_MODULE,
.request = gpiochip_generic_request,
.free = gpiochip_generic_free,
.direction_input = rp1_gpio_direction_input,
.direction_output = rp1_gpio_direction_output,
.get_direction = rp1_gpio_get_direction,
.get = rp1_gpio_get,
.set = rp1_gpio_set,
.base = -1,
.set_config = rp1_gpio_set_config,
.ngpio = RP1_NUM_GPIOS,
.can_sleep = false,
};
static void rp1_gpio_irq_handler(struct irq_desc *desc)
{
struct gpio_chip *chip = irq_desc_get_handler_data(desc);
struct irq_chip *host_chip = irq_desc_get_chip(desc);
struct rp1_pinctrl *pc = gpiochip_get_data(chip);
const struct rp1_iobank_desc *bank;
int irq = irq_desc_get_irq(desc);
unsigned long ints;
int bit_pos;
if (pc->irq[0] == irq)
bank = &rp1_iobanks[0];
else if (pc->irq[1] == irq)
bank = &rp1_iobanks[1];
else
bank = &rp1_iobanks[2];
chained_irq_enter(host_chip, desc);
ints = readl(pc->gpio_base + bank->ints_offset);
for_each_set_bit(bit_pos, &ints, 32) {
struct rp1_pin_info *pin = rp1_get_pin(chip, bit_pos);
regmap_field_write(pin->gpio[RP1_GPIO_CTRL_IRQRESET_SET], 1);
generic_handle_irq(irq_find_mapping(pc->gpio_chip.irq.domain,
bank->gpio_offset + bit_pos));
}
chained_irq_exit(host_chip, desc);
}
static void rp1_gpio_irq_config(struct rp1_pin_info *pin, bool enable)
{
int reg = enable ? RP1_INTE_SET : RP1_INTE_CLR;
regmap_field_write(pin->inte[reg], 1);
if (!enable)
/* Clear any latched events */
regmap_field_write(pin->gpio[RP1_GPIO_CTRL_IRQRESET_SET], 1);
}
static void rp1_gpio_irq_enable(struct irq_data *data)
{
struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
unsigned int gpio = irqd_to_hwirq(data);
struct rp1_pin_info *pin = rp1_get_pin(chip, gpio);
rp1_gpio_irq_config(pin, true);
}
static void rp1_gpio_irq_disable(struct irq_data *data)
{
struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
unsigned int gpio = irqd_to_hwirq(data);
struct rp1_pin_info *pin = rp1_get_pin(chip, gpio);
rp1_gpio_irq_config(pin, false);
}
static int rp1_irq_set_type(struct rp1_pin_info *pin, unsigned int type)
{
u32 irq_flags;
switch (type) {
case IRQ_TYPE_NONE:
irq_flags = 0;
break;
case IRQ_TYPE_EDGE_RISING:
irq_flags = RP1_INT_EDGE_RISING;
break;
case IRQ_TYPE_EDGE_FALLING:
irq_flags = RP1_INT_EDGE_FALLING;
break;
case IRQ_TYPE_EDGE_BOTH:
irq_flags = RP1_INT_EDGE_RISING | RP1_INT_EDGE_FALLING;
break;
case IRQ_TYPE_LEVEL_HIGH:
irq_flags = RP1_INT_LEVEL_HIGH;
break;
case IRQ_TYPE_LEVEL_LOW:
irq_flags = RP1_INT_LEVEL_LOW;
break;
default:
return -EINVAL;
}
/* Clear them all */
regmap_field_write(pin->gpio[RP1_GPIO_CTRL_INT_CLR], RP1_INT_MASK);
/* Set those that are needed */
regmap_field_write(pin->gpio[RP1_GPIO_CTRL_INT_SET], irq_flags);
pin->irq_type = type;
return 0;
}
static int rp1_gpio_irq_set_type(struct irq_data *data, unsigned int type)
{
struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
unsigned int gpio = irqd_to_hwirq(data);
struct rp1_pin_info *pin = rp1_get_pin(chip, gpio);
struct rp1_pinctrl *pc = gpiochip_get_data(chip);
int bank = pin->bank;
unsigned long flags;
int ret;
raw_spin_lock_irqsave(&pc->irq_lock[bank], flags);
ret = rp1_irq_set_type(pin, type);
if (!ret) {
if (type & IRQ_TYPE_EDGE_BOTH)
irq_set_handler_locked(data, handle_edge_irq);
else
irq_set_handler_locked(data, handle_level_irq);
}
raw_spin_unlock_irqrestore(&pc->irq_lock[bank], flags);
return ret;
}
static void rp1_gpio_irq_ack(struct irq_data *data)
{
struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
unsigned int gpio = irqd_to_hwirq(data);
struct rp1_pin_info *pin = rp1_get_pin(chip, gpio);
/* Clear any latched events */
regmap_field_write(pin->gpio[RP1_GPIO_CTRL_IRQRESET_SET], 1);
}
static struct irq_chip rp1_gpio_irq_chip = {
.name = MODULE_NAME,
.irq_enable = rp1_gpio_irq_enable,
.irq_disable = rp1_gpio_irq_disable,
.irq_set_type = rp1_gpio_irq_set_type,
.irq_ack = rp1_gpio_irq_ack,
.irq_mask = rp1_gpio_irq_disable,
.irq_unmask = rp1_gpio_irq_enable,
.flags = IRQCHIP_IMMUTABLE,
GPIOCHIP_IRQ_RESOURCE_HELPERS,
};
static void rp1_pull_config_set(struct rp1_pin_info *pin, unsigned int arg)
{
regmap_field_write(pin->pad[RP1_PAD_PULL], arg & 0x3);
}
static int rp1_pinconf_set(struct rp1_pin_info *pin, unsigned int offset,
unsigned long *configs, unsigned int num_configs)
{
u32 param, arg;
int i;
if (!pin)
return -EINVAL;
for (i = 0; i < num_configs; i++) {
param = pinconf_to_config_param(configs[i]);
arg = pinconf_to_config_argument(configs[i]);
switch (param) {
case PIN_CONFIG_BIAS_DISABLE:
rp1_pull_config_set(pin, RP1_PUD_OFF);
break;
case PIN_CONFIG_BIAS_PULL_DOWN:
rp1_pull_config_set(pin, RP1_PUD_DOWN);
break;
case PIN_CONFIG_BIAS_PULL_UP:
rp1_pull_config_set(pin, RP1_PUD_UP);
break;
case PIN_CONFIG_INPUT_ENABLE:
rp1_input_enable(pin, arg);
break;
case PIN_CONFIG_OUTPUT_ENABLE:
rp1_output_enable(pin, arg);
break;
case PIN_CONFIG_OUTPUT:
rp1_set_value(pin, arg);
rp1_set_dir(pin, RP1_DIR_OUTPUT);
rp1_set_fsel(pin, RP1_FSEL_GPIO);
break;
case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
regmap_field_write(pin->pad[RP1_PAD_SCHMITT], !!arg);
break;
case PIN_CONFIG_SLEW_RATE:
regmap_field_write(pin->pad[RP1_PAD_SLEWFAST], !!arg);
break;
case PIN_CONFIG_DRIVE_STRENGTH:
switch (arg) {
case 2:
arg = RP1_PAD_DRIVE_2MA;
break;
case 4:
arg = RP1_PAD_DRIVE_4MA;
break;
case 8:
arg = RP1_PAD_DRIVE_8MA;
break;
case 12:
arg = RP1_PAD_DRIVE_12MA;
break;
default:
return -ENOTSUPP;
}
regmap_field_write(pin->pad[RP1_PAD_DRIVE], arg);
break;
default:
return -ENOTSUPP;
} /* switch param type */
} /* for each config */
return 0;
}
static const struct of_device_id rp1_pinctrl_match[] = {
{ .compatible = "raspberrypi,rp1-gpio" },
{},
};
MODULE_DEVICE_TABLE(of, rp1_pinctrl_match);
static struct rp1_pinctrl rp1_pinctrl_data = {};
static const struct regmap_config rp1_pinctrl_regmap_cfg = {
.reg_bits = 32,
.val_bits = 32,
.reg_stride = 4,
.fast_io = true,
.name = "rp1-pinctrl",
};
static int rp1_gen_regfield(struct device *dev,
const struct reg_field *array,
size_t array_size,
int reg_off,
int pin_off,
bool additive_offset,
struct regmap *regmap,
struct regmap_field *out[])
{
struct reg_field regfield;
int k;
for (k = 0; k < array_size; k++) {
regfield = array[k];
regfield.reg = (additive_offset ? regfield.reg : 0) + reg_off;
if (pin_off >= 0) {
regfield.lsb = pin_off;
regfield.msb = regfield.lsb;
}
out[k] = devm_regmap_field_alloc(dev, regmap, regfield);
if (IS_ERR(out[k]))
return PTR_ERR(out[k]);
}
return 0;
}
static int rp1_pinctrl_probe(struct platform_device *pdev)
{
struct regmap *gpio_regmap, *rio_regmap, *pads_regmap;
struct rp1_pinctrl *pc = &rp1_pinctrl_data;
struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
struct gpio_irq_chip *girq;
int err, i;
pc->dev = dev;
pc->gpio_chip = rp1_gpio_chip;
pc->gpio_chip.parent = dev;
pc->gpio_base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(pc->gpio_base))
return dev_err_probe(dev, PTR_ERR(pc->gpio_base), "could not get GPIO IO memory\n");
pc->rio_base = devm_platform_ioremap_resource(pdev, 1);
if (IS_ERR(pc->rio_base))
return dev_err_probe(dev, PTR_ERR(pc->rio_base), "could not get RIO IO memory\n");
pc->pads_base = devm_platform_ioremap_resource(pdev, 2);
if (IS_ERR(pc->pads_base))
return dev_err_probe(dev, PTR_ERR(pc->pads_base), "could not get PADS IO memory\n");
gpio_regmap = devm_regmap_init_mmio(dev, pc->gpio_base,
&rp1_pinctrl_regmap_cfg);
if (IS_ERR(gpio_regmap))
return dev_err_probe(dev, PTR_ERR(gpio_regmap), "could not init GPIO regmap\n");
rio_regmap = devm_regmap_init_mmio(dev, pc->rio_base,
&rp1_pinctrl_regmap_cfg);
if (IS_ERR(rio_regmap))
return dev_err_probe(dev, PTR_ERR(rio_regmap), "could not init RIO regmap\n");
pads_regmap = devm_regmap_init_mmio(dev, pc->pads_base,
&rp1_pinctrl_regmap_cfg);
if (IS_ERR(pads_regmap))
return dev_err_probe(dev, PTR_ERR(pads_regmap), "could not init PADS regmap\n");
for (i = 0; i < RP1_NUM_BANKS; i++) {
const struct rp1_iobank_desc *bank = &rp1_iobanks[i];
int j;
for (j = 0; j < bank->num_gpios; j++) {
struct rp1_pin_info *pin =
&pc->pins[bank->min_gpio + j];
int reg_off;
pin->num = bank->min_gpio + j;
pin->bank = i;
pin->offset = j;
reg_off = bank->gpio_offset + pin->offset *
sizeof(u32) * 2;
err = rp1_gen_regfield(dev,
rp1_gpio_fields,
ARRAY_SIZE(rp1_gpio_fields),
reg_off,
-1,
true,
gpio_regmap,
pin->gpio);
if (err)
return dev_err_probe(dev, err,
"Unable to allocate regmap for gpio\n");
reg_off = bank->inte_offset;
err = rp1_gen_regfield(dev,
rp1_inte_fields,
ARRAY_SIZE(rp1_inte_fields),
reg_off,
pin->offset,
true,
gpio_regmap,
pin->inte);
if (err)
return dev_err_probe(dev, err,
"Unable to allocate regmap for inte\n");
reg_off = bank->rio_offset;
err = rp1_gen_regfield(dev,
rp1_rio_fields,
ARRAY_SIZE(rp1_rio_fields),
reg_off,
pin->offset,
true,
rio_regmap,
pin->rio);
if (err)
return dev_err_probe(dev, err,
"Unable to allocate regmap for rio\n");
reg_off = bank->pads_offset + pin->offset * sizeof(u32);
err = rp1_gen_regfield(dev,
rp1_pad_fields,
ARRAY_SIZE(rp1_pad_fields),
reg_off,
-1,
false,
pads_regmap,
pin->pad);
if (err)
return dev_err_probe(dev, err,
"Unable to allocate regmap for pad\n");
}
raw_spin_lock_init(&pc->irq_lock[i]);
}
girq = &pc->gpio_chip.irq;
girq->chip = &rp1_gpio_irq_chip;
girq->parent_handler = rp1_gpio_irq_handler;
girq->num_parents = RP1_NUM_BANKS;
girq->parents = pc->irq;
girq->default_type = IRQ_TYPE_NONE;
girq->handler = handle_level_irq;
/*
* Use the same handler for all groups: this is necessary
* since we use one gpiochip to cover all lines - the
* irq handler then needs to figure out which group and
* bank that was firing the IRQ and look up the per-group
* and bank data.
*/
for (i = 0; i < RP1_NUM_BANKS; i++) {
pc->irq[i] = irq_of_parse_and_map(np, i);
if (!pc->irq[i]) {
girq->num_parents = i;
break;
}
}
platform_set_drvdata(pdev, pc);
err = devm_gpiochip_add_data(dev, &pc->gpio_chip, pc);
if (err)
return dev_err_probe(dev, err, "could not add GPIO chip\n");
return 0;
}
static struct platform_driver rp1_pinctrl_driver = {
.probe = rp1_pinctrl_probe,
.driver = {
.name = MODULE_NAME,
.of_match_table = rp1_pinctrl_match,
.suppress_bind_attrs = true,
},
};
module_platform_driver(rp1_pinctrl_driver);
MODULE_AUTHOR("Phil Elwell <phil@raspberrypi.com>");
MODULE_AUTHOR("Andrea della Porta <andrea.porta@suse.com>");
MODULE_DESCRIPTION("RP1 pinctrl/gpio driver");
MODULE_LICENSE("GPL");